func (v *visitor) Visit(node ast.Node) ast.Visitor { switch node := node.(type) { case *ast.FuncDecl: v.funcName = node.Name.Name v.m = make(map[*ast.Object][]string) case *ast.DeferStmt: if sel, ok := node.Call.Fun.(*ast.SelectorExpr); ok { if ident, ok := sel.X.(*ast.Ident); ok { if selectors, ok := v.m[ident.Obj]; !ok { v.m[ident.Obj] = []string{sel.Sel.Name} } else { found := false for _, selname := range selectors { if selname == sel.Sel.Name { pos := v.fset.Position(node.Pos()) fmt.Printf("%s: %s:%d:%d: Repeating defer %s.%s() inside function %s\n", v.pkgPath, pos.Filename, pos.Line, pos.Column, ident.Name, selname, v.funcName) found = true exitStatus = 1 break } } if !found { v.m[ident.Obj] = append(selectors, sel.Sel.Name) } } } } } return v }
// The variadic arguments may start with link and category types, // and must end with a format string and any arguments. func (f *file) errorf(n ast.Node, confidence float64, args ...interface{}) { if confidence < f.config.MinConfidence { return } p := f.fset.Position(n.Pos()) problem := Problem{ File: f.filename, Position: p, Confidence: confidence, LineText: srcLine(f.src, p), } argLoop: for len(args) > 1 { // always leave at least the format string in args switch v := args[0].(type) { case link: problem.Link = string(v) case category: problem.Category = string(v) default: break argLoop } args = args[1:] } problem.Text = fmt.Sprintf(args[0].(string), args[1:]...) f.problems = append(f.problems, problem) }
func (f *File) printNode(node, ident ast.Node, url string) { if !f.doPrint { f.found = true return } fmt.Printf("%s%s%s", url, f.sourcePos(f.fset.Position(ident.Pos())), f.docs(node)) }
func (lp *linePrinter) trim(n ast.Node) bool { stmt, ok := n.(ast.Stmt) if !ok { return true } line := lp.fset.Position(n.Pos()).Line if line != lp.line { return false } switch stmt := stmt.(type) { case *ast.IfStmt: stmt.Body = lp.trimBlock(stmt.Body) case *ast.SwitchStmt: stmt.Body = lp.trimBlock(stmt.Body) case *ast.TypeSwitchStmt: stmt.Body = lp.trimBlock(stmt.Body) case *ast.CaseClause: stmt.Body = lp.trimList(stmt.Body) case *ast.CommClause: stmt.Body = lp.trimList(stmt.Body) case *ast.BlockStmt: stmt.List = lp.trimList(stmt.List) } return true }
func (v *funcVisitor) Visit(n ast.Node) ast.Visitor { switch n := n.(type) { case *ast.FuncDecl: // Function name is prepended with "T." if there is a receiver, where // T is the type of the receiver, dereferenced if it is a pointer. name := n.Name.Name if n.Recv != nil { field := n.Recv.List[0] switch recv := field.Type.(type) { case *ast.StarExpr: name = recv.X.(*ast.Ident).Name + "." + name case *ast.Ident: name = recv.Name + "." + name } } start, end := v.fset.Position(n.Pos()), v.fset.Position(n.End()) f := v.pkg.RegisterFunction(name, start.Filename, start.Offset, end.Offset) v.state.functions = append(v.state.functions, f) sv := &stmtVisitor{v.state} if n.Body != nil { sv.VisitStmt(n.Body) } // TODO function coverage (insert "function.Enter", "function.Leave"). // TODO come up with naming scheme for function literals. // case *ast.FuncLit: } return v }
func getSourceString(node ast.Node, fset *token.FileSet) string { p1 := fset.Position(node.Pos()) p2 := fset.Position(node.End()) b := getFileBytes(p1.Filename) return string(b[p1.Offset:p2.Offset]) }
// normalizeNodePos resets all position information of node and its descendants. func normalizeNodePos(node ast.Node) { ast.Inspect(node, func(node ast.Node) bool { if node == nil { return true } if node.Pos() == token.NoPos && node.End() == token.NoPos { return true } pv := reflect.ValueOf(node) if pv.Kind() != reflect.Ptr { return true } v := pv.Elem() if v.Kind() != reflect.Struct { return true } for i := 0; i < v.NumField(); i++ { f := v.Field(i) ft := f.Type() if f.CanSet() && ft.PkgPath() == "go/token" && ft.Name() == "Pos" && f.Int() != 0 { f.SetInt(1) } } return true }) }
func posLink_urlFunc(node ast.Node, fset *token.FileSet) string { var relpath string var line int var low, high int // selection if p := node.Pos(); p.IsValid() { pos := fset.Position(p) relpath = pos.Filename line = pos.Line low = pos.Offset } if p := node.End(); p.IsValid() { high = fset.Position(p).Offset } var buf bytes.Buffer template.HTMLEscape(&buf, []byte(relpath)) // selection ranges are of form "s=low:high" if low < high { fmt.Fprintf(&buf, "?s=%d:%d", low, high) // no need for URL escaping // if we have a selection, position the page // such that the selection is a bit below the top line -= 10 if line < 1 { line = 1 } } // line id's in html-printed source are of the // form "L%d" where %d stands for the line number if line > 0 { fmt.Fprintf(&buf, "#L%d", line) // no need for URL escaping } return buf.String() }
// The variadic arguments may start with link and category types, // and must end with a format string and any arguments. // It returns the new Problem. func (f *file) errorf(n ast.Node, confidence float64, args ...interface{}) *Problem { pos := f.fset.Position(n.Pos()) if pos.Filename == "" { pos.Filename = f.filename } return f.pkg.errorfAt(pos, confidence, args...) }
/* * findCalls() parses the node passed in and, if it's a * SelectorExpr (which any call to a function/method will be) * populates the map passed in as the second argument. * This is the function used for finder.find(). * * Functions will have the package as the X node, * whereas methods will have the object identifier as the * X. We do not differentiate in this function (there * really isn't a good way without access to the list of * imports and identifiers, so that has to be done higher up * the stack). */ func findCalls(n ast.Node, f *finder) bool { switch x := n.(type) { case *ast.File: locfields := strings.Split(fset.Position(n.Pos()).String(), ":") f.currentFile = locfields[0] case *ast.SelectorExpr: switch y := x.X.(type) { case *ast.Ident: locfields := strings.Split(fset.Position(y.NamePos).String(), ":") ln, err := strconv.Atoi(locfields[1]) if err != nil { ln = -1 } f.dset.AddPackageCall(Call{ Qual: y.Name, Sel: x.Sel.Name, // Location: y.NamePos, Line: ln, }, f.currentFile, true) default: return true } // END switch y := default: return true } // END switch x := return true }
// Used for implicit objects created by some ImportSpecs and CaseClauses. func (r *resolver) defineImplicit(b *Block, n ast.Node, name string) { obj := r.info.Implicits[n] if obj == nil { logf("%s: internal error: not an implicit definition: %T\n", r.fset.Position(n.Pos()), n) } r.defineObject(b, name, obj) }
func (f *gofile) newIssueRangeFromNode(n ast.Node) *issueRange { s := f.Fset().Position(n.Pos()) e := f.Fset().Position(n.End()) return &issueRange{ s, e, } }
func (a *stmtCompiler) definePkg(ident ast.Node, id, path string) *PkgIdent { v, prev := a.block.DefinePackage(id, path, ident.Pos()) if prev != nil { a.diagAt(ident.Pos(), "%s redeclared as imported package name\n\tprevious declaration at %s", id, a.fset.Position(prev.Pos())) return nil } return v }
func (f *file) errorf(n ast.Node, confidence float64, format string, a ...interface{}) { p := f.fset.Position(n.Pos()) f.problems = append(f.problems, Problem{ Position: p, Text: fmt.Sprintf(format, a...), Confidence: confidence, LineText: srcLine(f.src, p), }) }
// Visit implements ast.Visistor's Visit method func (t *prohibitVisitor) Visit(node ast.Node) ast.Visitor { if node == nil { return t } if filterChanStmtOrExpr(node) != nil { t.AddError(node.Pos(), fmt.Sprintf("Channel operation in non top-level block: %v", node)) } return t }
func (v *annotationVisitor) addAnnoation(n ast.Node, packageName string, name string) { pos := v.fset.Position(n.Pos()) end := v.fset.Position(n.End()) v.annotations = append(v.annotations, TypeAnnotation{ pos.Offset - len(packageWrapper), end.Offset - len(packageWrapper), packageName, name}) }
// compiles expression or statement func (w *World) compile(n ast.Node) Expr { switch n := n.(type) { case ast.Stmt: return w.compileStmt(n) case ast.Expr: return w.compileExpr(n) default: panic(err(n.Pos(), "not allowed")) } }
func (vis *findNodeVisitor) Visit(node ast.Node) (w ast.Visitor) { if node == nil || vis.result != nil { return nil } if utils.ComparePosWithinFile(vis.stPos, vis.fset.Position(node.Pos())) == 0 && utils.ComparePosWithinFile(vis.endPos, vis.fset.Position(node.End())) == 0 { vis.result = node return nil } return vis }
func nodeLabel(fset *token.FileSet, x ast.Node) string { pos := fset.Position(x.Pos()) label := fmt.Sprintf("%T %s:%d", x, pos.Filename, pos.Line) switch x := x.(type) { case *ast.Ident: label = x.Name + " " + label case *ast.SelectorExpr: label = "." + x.Sel.Name + " " + label } return label }
func (f *file) indentOf(node ast.Node) string { line := srcLine(f.src, f.fset.Position(node.Pos())) for i, r := range line { switch r { case ' ', '\t': default: return line[:i] } } return line // unusual or empty line }
func (es *extractStrings) processBasicLit(basicLit *ast.BasicLit, n ast.Node, fset *token.FileSet) { s, _ := strconv.Unquote(basicLit.Value) if len(s) > 0 && basicLit.Kind == token.STRING && s != "\t" && s != "\n" && s != " " && !es.filter(s) { //TODO: fix to remove these: s != "\\t" && s != "\\n" && s != " " position := fset.Position(n.Pos()) stringInfo := common.StringInfo{Value: s, Filename: position.Filename, Offset: position.Offset, Line: position.Line, Column: position.Column} es.ExtractedStrings[s] = stringInfo } }
func (v *Visitor) Visit(node ast.Node) (w ast.Visitor) { if node != nil { fmt.Println(fset.Position(node.Pos())) fmt.Println(fset.Position(node.End())) fmt.Println(reflect.TypeOf(node)) if f := m[reflect.TypeOf(node)]; f != nil { f(node) } } return v }
func (v *calltipVisitor) Visit(node ast.Node) (w ast.Visitor) { if node != nil { if x, ok := node.(*ast.CallExpr); ok { a := v.fset.Position(node.Pos()) b := v.fset.Position(node.End()) if (a.IsValid() && v.offset >= a.Offset) && (!b.IsValid() || v.offset <= b.Offset) { v.x = x } } } return v }
func (file *WasmGoSourceFile) ErrorNode(node ast.Node, format string, a ...interface{}) error { pos := node.Pos() position := file.fset.File(pos).PositionFor(pos, false) s := fmt.Sprintf(format, a...) src := file.getSingleLineGoSource(node) if src != "" { s = fmt.Sprintf("%s (src: %s)", s, src) } e := &GoWasmError{ msg: fmt.Sprintf("%s @ %v", s, position), } return e }
func (g *Grapher) NewRef(node ast.Node, obj types.Object) (*Ref, error) { key, err := g.defKey(obj) if err != nil { return nil, err } pos := g.program.Fset.Position(node.Pos()) return &Ref{ File: pos.Filename, Span: makeSpan(g.program.Fset, node), Def: key, }, nil }
func (this DepthWalker) Visit(node ast.Node) ast.Visitor { if node == nil { return this + 1 } buffer := "" for i := 0; i < int(this); i++ { buffer += " " } fmt.Printf("%sPos: %d %s\n", buffer, node.Pos(), AllSources.Position(node.Pos())) fmt.Printf("%sEnd: %d %s\n", buffer, node.End(), AllSources.Position(node.End())) fmt.Printf("%s%T\n", buffer, node) fmt.Printf("%s%v\n", buffer, node) if e, ok := node.(ast.Expr); ok { obj, typ := types.ExprType(e, LocalImporter) fmt.Printf("%s%v\n", buffer, obj) fmt.Printf("%s%v\n", buffer, typ) } fmt.Println() switch n := node.(type) { } return this + 1 }
func NewIssue(ctx *Context, node ast.Node, desc string, severity Score, confidence Score) *Issue { var code string fobj := ctx.FileSet.File(node.Pos()) name := fobj.Name() line := fobj.Line(node.Pos()) if file, err := os.Open(fobj.Name()); err == nil { defer file.Close() s := (int64)(fobj.Position(node.Pos()).Offset) // Go bug, should be int64 e := (int64)(fobj.Position(node.End()).Offset) // Go bug, should be int64 code, err = codeSnippet(file, s, e, node) if err != nil { code = err.Error() } } return &Issue{ File: name, Line: line, What: desc, Confidence: confidence, Severity: severity, Code: code, } }
func (visitor *astNodeVisitorForMultipleStatements) Visit(node ast.Node) (w ast.Visitor) { if node != nil { if visitor.context.fset.Position(node.Pos()).Line == visitor.context.selection.Begin.Line && visitor.context.fset.Position(node.Pos()).Column == visitor.context.selection.Begin.Column && !visitor.context.shouldRecord { // fmt.Println("Starting with node at pos", visitor.context.fset.Position(node.Pos()), "and end", visitor.context.fset.Position(node.End())) // ast.Print(visitor.context.fset, node) // fmt.Println(node.Pos(), node) // fmt.Println("Parent") // ast.Print(visitor.context.fset, visitor.parentNode) visitor.context.posParent = visitor.parentNode visitor.context.shouldRecord = true } if visitor.context.shouldRecord && visitor.context.posParent == visitor.parentNode { visitor.context.nodesToExtract = append(visitor.context.nodesToExtract, node) } if visitor.context.fset.Position(node.End()).Line == visitor.context.selection.End.Line && visitor.context.fset.Position(node.End()).Column == visitor.context.selection.End.Column { // fmt.Println("Ending with node at pos", visitor.context.fset.Position(node.Pos()), "and end", visitor.context.fset.Position(node.End())) // ast.Print(visitor.context.fset, node) // fmt.Println("Parent") // ast.Print(visitor.context.fset, visitor.parentNode) visitor.context.endParent = visitor.parentNode visitor.context.shouldRecord = false return nil } } return &astNodeVisitorForMultipleStatements{ parentNode: node, context: visitor.context, } }
// Span returns the 0-based offset range of the given AST node. // The range is half-open, including the start position but excluding the end. // If node == nil or lacks a valid start position, Span returns -1, -1. // If the end position of node is invalid, start == end. func (pi *PackageInfo) Span(node ast.Node) (start, end int) { if node == nil { return -1, -1 } else if pos := node.Pos(); pos == token.NoPos { return -1, -1 } else { start = pi.FileSet.Position(pos).Offset end = start } if pos := node.End(); pos != token.NoPos { end = pi.FileSet.Position(pos).Offset } return }
func (v *annotationVisitor) addAnnotation(n ast.Node, packageName string, name string) { pos := v.fset.Position(n.Pos()) end := v.fset.Position(n.End()) importPath := "" if packageName != "" { importPath = v.importPaths[packageName] if importPath == "" { return } } v.annotations = append(v.annotations, TypeAnnotation{ pos.Offset - len(packageWrapper), end.Offset - len(packageWrapper), importPath, name}) }