Exemple #1
0
// SameIdent returns true if a and b are the same.
func SameIdent(a, b *ast.Ident) bool {
	// TODO(waigani) Don't rely on name, it could change and still be the same
	// ident.
	if a.String() != b.String() {
		return false
	}

	// TODO(waigani) this happens if ident decl is outside of current
	// file. We need to use the FileSet to find it.
	if a.Obj == nil && b.Obj == nil {
		return true
	}

	pa, err := DeclPos(a)
	if err != nil {
		// TODO(waigani) log error
		return false
	}

	pb, err := DeclPos(b)
	if err != nil {
		// TODO(waigani) log error
		return false
	}

	if pa != pb {
		return false
	}

	return true
}
Exemple #2
0
// DeclLhsPos returns the  position of the ident's variable on the left hand
// side of the assignment operator with which it was declared.
func DeclLhsPos(ident *ast.Ident) (int, error) {
	var identPos int
	switch n := ident.Obj.Decl.(type) {
	case *ast.AssignStmt:

		// find position of ident on lhs of assignment
		for i, exp := range n.Lhs {
			if a, ok := exp.(*ast.Ident); ok && SameIdent(a, ident) {
				identPos = i
				break
			}
		}
	case *ast.ValueSpec:

		// find position of ident on lhs of assignment
		for i, name := range n.Names {
			if name.String() == ident.String() {
				identPos = i
				break
			}
		}

	default:
		return 0, errors.New("could not get lhs position of ident: unknown decl type")
	}
	return identPos, nil

}
Exemple #3
0
func (c *compiler) makeFunc(ident *ast.Ident, ftyp *types.Signature) *LLVMValue {
	fname := ident.String()
	if ftyp.Recv() == nil && fname == "init" {
		// Make "init" functions anonymous.
		fname = ""
	} else {
		var pkgname string
		if recv := ftyp.Recv(); recv != nil {
			var recvname string
			switch recvtyp := recv.Type().(type) {
			case *types.Pointer:
				if named, ok := recvtyp.Elem().(*types.Named); ok {
					obj := named.Obj()
					recvname = "*" + obj.Name()
					pkgname = obj.Pkg().Path()
				}
			case *types.Named:
				named := recvtyp
				obj := named.Obj()
				recvname = obj.Name()
				pkgname = obj.Pkg().Path()
			}

			if recvname != "" {
				fname = fmt.Sprintf("%s.%s", recvname, fname)
			} else {
				// If the receiver is an unnamed struct, we're
				// synthesising a method for an unnamed struct
				// type. There's no meaningful name to give the
				// function, so leave it up to LLVM.
				fname = ""
			}
		} else {
			obj := c.typeinfo.Objects[ident]
			pkgname = obj.Pkg().Path()
		}
		if fname != "" {
			fname = pkgname + "." + fname
		}
	}

	// gcimporter may produce multiple AST objects for the same function.
	llvmftyp := c.types.ToLLVM(ftyp)
	var fn llvm.Value
	if fname != "" {
		fn = c.module.Module.NamedFunction(fname)
	}
	if fn.IsNil() {
		llvmfptrtyp := llvmftyp.StructElementTypes()[0].ElementType()
		fn = llvm.AddFunction(c.module.Module, fname, llvmfptrtyp)
	}
	fn = llvm.ConstInsertValue(llvm.ConstNull(llvmftyp), fn, []uint32{0})
	return c.NewValue(fn, ftyp)
}
Exemple #4
0
func findImportedTypes(name *ast.Ident, withImports []*ast.ImportSpec, dir GoDir) []*ast.TypeSpec {
	importName := name.String()
	for _, imp := range withImports {
		path := strings.Trim(imp.Path.Value, `"`)
		if pkg, err := dir.Import(path, importName); err == nil {
			typs, _ := loadPkgTypeSpecs(pkg, dir)
			addSelector(typs, importName)
			return typs
		}
	}
	return nil
}
Exemple #5
0
func handleUnresolved(unresolved *ast.Ident) gxui.CodeSyntaxLayers {
	layers := make(gxui.CodeSyntaxLayers, 0, 1)
	switch unresolved.String() {
	case "append", "cap", "close", "complex", "copy",
		"delete", "imag", "len", "make", "new", "panic",
		"print", "println", "real", "recover":

		layers = append(layers, nodeLayer(unresolved, builtinColor))
	case "nil":
		layers = append(layers, nodeLayer(unresolved, nilColor))
	}
	return layers
}
Exemple #6
0
// Writes a TAGS line to a buffer buffer
func (t *buffer) tagLine(leaf *ast.Ident, pkgname, rcvname string) {
	P := t.fset.Position(leaf.NamePos)
	n, l := leaf.String(), P.Line
	s, o := t.lineANDpos(P.Line, n)
	beforedot := pkgname
	if rcvname != "" {
		beforedot = rcvname
	}
	if rcvname != "" && *fullTag {
		fmt.Fprintf(t, "%s\177%s.%s.%s\001%d,%d\n", s, pkgname, rcvname, n, l, o)
	} else {
		fmt.Fprintf(t, "%s\177%s.%s\001%d,%d\n", s, beforedot, n, l, o)
	}
}
Exemple #7
0
func (r *Resolver) resolveIdent(context *resolution.LocatorContext, ident *ast.Ident) (ast.Expr, error) {
	if r.isBuiltIn(ident.String()) {
		return ident, nil
	}
	discovery, err := r.locator.FindIdentType(context, ident)
	if err != nil {
		return nil, err
	}
	al := r.model.AddImport("", discovery.Location)
	return &ast.SelectorExpr{
		X:   ast.NewIdent(al),
		Sel: ast.NewIdent(ident.String()),
	}, nil
}
Exemple #8
0
func findImportedTypes(name *ast.Ident, withImports []*ast.ImportSpec, dir GoDir) ([]*ast.TypeSpec, map[*ast.InterfaceType][]Dependency) {
	importName := name.String()
	for _, imp := range withImports {
		path := strings.Trim(imp.Path.Value, `"`)
		name, pkg, err := dir.Import(path, "")
		if err != nil {
			log.Printf("Error loading import: %s", err)
			continue
		}
		if imp.Name != nil {
			name = imp.Name.String()
		}
		if name != importName {
			continue
		}
		typs, deps, _ := loadPkgTypeSpecs(pkg, dir)
		addSelector(typs, importName)
		return typs, deps
	}
	return nil, nil
}
Exemple #9
0
func (self *HTMLStyler) Ident(id *ast.Ident) ([]byte, printer.HTMLTag) {
	classes := "go-local"
	if id.IsExported() {
		classes = "go-exported"
	}

	switch id.String() {
	case "bool", "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "float32", "float64", "byte", "uint", "int", "float", "uintptr", "string":
		classes += " go-prim-ident"
	default:
		if tok, ok := self.prev.(token.Token); ok && tok.String() == "func" || tok.String() == ")" {
			classes += " go-func-ident"
		}
	}

	self.prev = id

	return []byte(id.String()), printer.HTMLTag{
		Start: "<span class=\"go-ident " + classes + "\">",
		End:   "</span>",
	}
}
Exemple #10
0
// IdentDeclExpr returns the expression that the identifier was declared with.
func IdentDeclExpr(ident *ast.Ident) (ast.Expr, error) {

	if ident.Obj == nil {
		return nil, errors.Errorf("ident object is nil for ident %q", ident.Name)
	}

	switch n := ident.Obj.Decl.(type) {
	case *ast.AssignStmt:

		// find position of ident on lhs of assignment
		var identPos int
		for i, exp := range n.Lhs {
			if a, ok := exp.(*ast.Ident); ok && SameIdent(a, ident) {
				identPos = i
				break
			}
		}

		return n.Rhs[identPos], nil
	case *ast.ValueSpec:

		// find position of ident on lhs of assignment
		var identPos int
		for i, name := range n.Names {
			if name.String() == ident.String() {
				identPos = i
			}
		}

		if n.Values != nil {
			// get the rhs counterpart
			return n.Values[identPos], nil
		}

	}

	return nil, errors.Errorf("no expr found for %T", ident.Name)
}
Exemple #11
0
func aeFn(f *ast.File) bool {
	// During the walk, we track the last thing seen that looks like
	// an appengine.Context, and reset it once the walk leaves a func.
	var lastContext *ast.Ident

	fixed := false

	// Update imports.
	for _, imp := range f.Imports {
		pth, _ := strconv.Unquote(imp.Path.Value)
		if pth == "appengine" || strings.HasPrefix(pth, "appengine/") {
			imp.Path.Value = strconv.Quote(mapPackage(pth))
			fixed = true
		}
	}

	// Update any API changes.
	walk(f, func(n interface{}) {
		if as, ok := n.(*ast.AssignStmt); ok {
			if len(as.Lhs) == 1 && len(as.Rhs) == 1 {
				// If this node is an assignment from an appengine.NewContext invocation,
				// remember the identifier on the LHS.
				if isCall(as.Rhs[0], "appengine", "NewContext") {
					if ident, ok := as.Lhs[0].(*ast.Ident); ok {
						lastContext = ast.NewIdent(ident.Name)
						return
					}
				}
				// x (=|:=) appengine.Timeout(y, z)
				//   should become
				// x, _ (=|:=) context.WithTimeout(y, z)
				if isCall(as.Rhs[0], "appengine", "Timeout") {
					addImport(f, ctxPackage)
					as.Lhs = append(as.Lhs, ast.NewIdent("_"))
					// isCall already did the type checking.
					sel := as.Rhs[0].(*ast.CallExpr).Fun.(*ast.SelectorExpr)
					sel.X = ast.NewIdent("context")
					sel.Sel = ast.NewIdent("WithTimeout")
					fixed = true
					return
				}
			}
			return
		}

		// If this node is a FuncDecl, we've finished the function, so reset lastContext.
		if _, ok := n.(*ast.FuncDecl); ok {
			lastContext = nil
			return
		}

		if call, ok := n.(*ast.CallExpr); ok {
			if isPkgDot(call.Fun, "appengine", "Datacenter") && len(call.Args) == 0 {
				insertContext(f, call, lastContext)
				fixed = true
				return
			}

			sel, ok := call.Fun.(*ast.SelectorExpr)
			if !ok {
				return
			}
			// refersTo(sel.X, lastContext) doesn't work.
			if lastContext != nil && isName(sel.X, lastContext.String()) && logMethod[sel.Sel.Name] {
				// c.Errorf(...)
				//   should become
				// log.Errorf(c, ...)
				addImport(f, mapPackage("appengine/log"))
				sel.X = &ast.Ident{ // ast.NewIdent doesn't preserve the position.
					NamePos: sel.X.Pos(),
					Name:    "log",
				}
				insertContext(f, call, lastContext)
				fixed = true
				return
			}
		}
	})
	return fixed
}
Exemple #12
0
func (l *Locator) FindIdentType(context *LocatorContext, ref *ast.Ident) (TypeDiscovery, error) {
	locations := context.CandidateLocations(".")
	return l.findTypeDeclarationInLocations(ref.String(), locations)
}
Exemple #13
0
func (p *printer) printIdent(n *ast.Ident) {
	p.print(n.String())
}
Exemple #14
0
func nameFromIdent(i *ast.Ident) (name string) {
	if i != nil {
		name = i.String()
	}
	return
}