// 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 }
// 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 }
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) }
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 }
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 }
// 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) } }
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 }
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 }
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>", } }
// 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) }
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 }
func (l *Locator) FindIdentType(context *LocatorContext, ref *ast.Ident) (TypeDiscovery, error) { locations := context.CandidateLocations(".") return l.findTypeDeclarationInLocations(ref.String(), locations) }
func (p *printer) printIdent(n *ast.Ident) { p.print(n.String()) }
func nameFromIdent(i *ast.Ident) (name string) { if i != nil { name = i.String() } return }