Пример #1
1
func (this *astEquals) Check(params []interface{}, names []string) (bool, string) {
	var obtainedNodes, expectedNodes chan *NodeWithBreadcrumbs
	var obtainedNode, expectedNode *NodeWithBreadcrumbs

	obtainedNodes = make(chan *NodeWithBreadcrumbs)
	expectedNodes = make(chan *NodeWithBreadcrumbs)

	go ast.Walk(&AstChannelWalker{Out: obtainedNodes}, params[0].(ast.Node))
	go ast.Walk(&AstChannelWalker{Out: expectedNodes}, params[1].(ast.Node))

	for {
		obtainedNode = <-obtainedNodes
		expectedNode = <-expectedNodes

		if obtainedNode == nil && expectedNode == nil {
			break
		}

		if obtainedNode == nil || expectedNode == nil {
			return false, fmt.Sprintf("\n%+v\ndid not match\n%+v", obtainedNode, expectedNode)
		}

		if !this.nodeEquals(obtainedNode.Node, expectedNode.Node) {
			return false, fmt.Sprintf("\n%+v\ndid not match\n%+v", obtainedNode, expectedNode)
		}
	}

	return true, ""
}
Пример #2
0
func (v *visitor) Visit(node ast.Node) ast.Visitor {
	switch node := node.(type) {
	case *ast.Ident:
		v.use(v.pkg.Info.Uses[node])

	case *ast.ValueSpec:
		if !v.insideFunc {
			for _, ident := range node.Names {
				if !isReserved(ident.Name) {
					v.decl(v.pkg.Info.Defs[ident])
				}
			}
		}
		for _, val := range node.Values {
			ast.Walk(v, val)
		}
		return nil

	case *ast.FuncDecl:
		if node.Body != nil {
			v.insideFunc = true
			ast.Walk(v, node.Body)
			v.insideFunc = false
		}

		return nil
	}

	return v
}
Пример #3
0
func (p *Parser) Parse(fname string, isDir bool) error {
	var err error
	if p.PkgPath, err = getPkgPath(fname, isDir); err != nil {
		return err
	}

	fset := token.NewFileSet()
	if isDir {
		packages, err := parser.ParseDir(fset, fname, nil, parser.ParseComments)
		if err != nil {
			return err
		}

		for _, pckg := range packages {
			ast.Walk(&visitor{Parser: p}, pckg)
		}
	} else {
		f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
		if err != nil {
			return err
		}

		ast.Walk(&visitor{Parser: p}, f)
	}
	return nil
}
Пример #4
0
func (x *Indexer) visitSpec(kind SpotKind, spec ast.Spec) {
	switch n := spec.(type) {
	case *ast.ImportSpec:
		x.visitIdent(ImportDecl, n.Name)
		if n.Path != nil {
			if imp, err := strconv.Unquote(n.Path.Value); err == nil {
				x.importCount[x.intern(imp)]++
			}
		}

	case *ast.AliasSpec:
		x.visitIdent(kind, n.Name)
		ast.Walk(x, n.Orig)

	case *ast.ValueSpec:
		for _, n := range n.Names {
			x.visitIdent(kind, n)
		}
		ast.Walk(x, n.Type)
		for _, v := range n.Values {
			ast.Walk(x, v)
		}

	case *ast.TypeSpec:
		x.visitIdent(TypeDecl, n.Name)
		ast.Walk(x, n.Type)
	}
}
Пример #5
0
// Visits files for used nodes.
func (p *Package) Visit(node ast.Node) ast.Visitor {
	u := usedWalker(*p) // hopefully p fields are references.
	switch n := node.(type) {
	// don't walk whole file, but only:
	case *ast.ValueSpec:
		// - variable initializers
		for _, value := range n.Values {
			ast.Walk(&u, value)
		}
		// variable types.
		if n.Type != nil {
			ast.Walk(&u, n.Type)
		}
	case *ast.BlockStmt:
		// - function bodies
		for _, stmt := range n.List {
			ast.Walk(&u, stmt)
		}
	case *ast.FuncDecl:
		// - function signatures
		ast.Walk(&u, n.Type)
	case *ast.TypeSpec:
		// - type declarations
		ast.Walk(&u, n.Type)
	}
	return p
}
Пример #6
0
// rewriteOptionalMethods makes specific mutations to marshaller methods that belong to types identified
// as being "optional" (they may be nil on the wire). This allows protobuf to serialize a map or slice and
// properly discriminate between empty and nil (which is not possible in protobuf).
// TODO: move into upstream gogo-protobuf once https://github.com/gogo/protobuf/issues/181
//   has agreement
func rewriteOptionalMethods(decl ast.Decl, isOptional OptionalFunc) {
	switch t := decl.(type) {
	case *ast.FuncDecl:
		ident, ptr, ok := receiver(t)
		if !ok {
			return
		}

		// correct initialization of the form `m.Field = &OptionalType{}` to
		// `m.Field = OptionalType{}`
		if t.Name.Name == "Unmarshal" {
			ast.Walk(optionalAssignmentVisitor{fn: isOptional}, t.Body)
		}

		if !isOptional(ident.Name) {
			return
		}

		switch t.Name.Name {
		case "Unmarshal":
			ast.Walk(&optionalItemsVisitor{}, t.Body)
		case "MarshalTo", "Size", "String":
			ast.Walk(&optionalItemsVisitor{}, t.Body)
			fallthrough
		case "Marshal":
			// if the method has a pointer receiver, set it back to a normal receiver
			if ptr {
				t.Recv.List[0].Type = ident
			}
		}
	}
}
Пример #7
0
func (x *Indexer) visitSpec(spec ast.Spec, isVarDecl bool) {
	switch n := spec.(type) {
	case *ast.ImportSpec:
		x.visitComment(n.Doc)
		x.visitIdent(ImportDecl, n.Name)
		ast.Walk(x, n.Path)
		x.visitComment(n.Comment)

	case *ast.ValueSpec:
		x.visitComment(n.Doc)
		kind := ConstDecl
		if isVarDecl {
			kind = VarDecl
		}
		for _, n := range n.Names {
			x.visitIdent(kind, n)
		}
		ast.Walk(x, n.Type)
		for _, v := range n.Values {
			ast.Walk(x, v)
		}
		x.visitComment(n.Comment)

	case *ast.TypeSpec:
		x.visitComment(n.Doc)
		x.visitIdent(TypeDecl, n.Name)
		ast.Walk(x, n.Type)
		x.visitComment(n.Comment)
	}
}
Пример #8
0
// Visits files for used nodes.
func (p *Package) Visit(node ast.Node) ast.Visitor {
	u := usedWalker(*p) // hopefully p fields are references.
	switch n := node.(type) {
	// don't walk whole file, but only:
	case *ast.ValueSpec:
		// - variable initializers
		for _, value := range n.Values {
			ast.Walk(&u, value)
		}
		// variable types.
		if n.Type != nil {
			ast.Walk(&u, n.Type)
		}
	case *ast.BlockStmt:
		// - function bodies
		for _, stmt := range n.List {
			ast.Walk(&u, stmt)
		}
	case *ast.FuncDecl:
		// - function signatures
		if *includeTests {
			// Test* functions are always used
			if strings.HasPrefix(n.Name.String(), "Test") {
				u.used[n.Name.String()] = true
			}
		}
		ast.Walk(&u, n.Type)
	case *ast.TypeSpec:
		// - type declarations
		ast.Walk(&u, n.Type)
	}
	return p
}
Пример #9
0
func instrument(pkg, shortName, fullName string, fset *token.FileSet, parsedFile *ast.File, info *types.Info, out io.Writer, lits map[Literal]struct{}, blocks *[]CoverBlock, sonar *[]CoverBlock) {
	file := &File{
		fset:      fset,
		pkg:       pkg,
		shortName: shortName,
		fullName:  fullName,
		astFile:   parsedFile,
		blocks:    blocks,
		info:      info,
	}
	file.addImport("github.com/dvyukov/go-fuzz/go-fuzz-dep", fuzzdepPkg, "Main")

	if lits != nil {
		ast.Walk(&LiteralCollector{lits}, file.astFile)
	}

	ast.Walk(file, file.astFile)

	if sonar != nil {
		s := &Sonar{
			fset:      fset,
			shortName: shortName,
			fullName:  fullName,
			pkg:       pkg,
			blocks:    sonar,
			info:      info,
		}
		ast.Walk(s, file.astFile)
	}

	file.print(out)
}
Пример #10
0
func restoreIdentMapping(oldFile, newFile *ast.File, identMap st.IdentifierMap) {
	comm := make(chan *ast.Ident)
	source := &restoreIMSourceVisitor{comm}
	dest := &restoreIMDestVisitor{identMap, comm}
	go ast.Walk(source, oldFile)
	ast.Walk(dest, newFile)
}
Пример #11
0
func main() {
	goopt.Parse(func() []string { return nil })
	if len(goopt.Args) > 0 {
		x, err := parser.ParseFiles(myfiles, goopt.Args, 0)
		die(err)
		fmt.Fprintln(os.Stderr, "Parsed: ", *x["main"])
		die(typechecker.CheckPackage(myfiles, x["main"], nil))
		fmt.Fprintln(os.Stderr, "Checked: ", *x["main"])
		//for _,a := range x["main"].Files {
		//	die(printer.Fprint(os.Stdout, a))
		//}

		aaa := x86.StartData
		var bbb *Stack
		var cv = CompileVisitor{&aaa, make(map[string]string), bbb.New("global")}
		ast.Walk(StringVisitor(cv), x["main"])

		cv.Append(x86.StartText...)
		ast.Walk(&cv, x["main"])

		// Here we just add a crude debug library
		cv.Append(x86.Debugging...)
		ass := x86.Assembly(*cv.assembly)
		//fmt.Println(ass)
		die(elf.AssembleAndLink(goopt.Args[0][:len(goopt.Args[0])-3], []byte(ass)))
	}
}
Пример #12
0
func trans(pks map[string]*ast.Package) {
	ts := Trans{}
	for _, pk := range pks {
		ast.Walk(normalizer{}, pk)
		ast.Walk(ts, pk)
	}
	fmt.Println("main();")
}
Пример #13
0
// Trim trims the AST rooted at node based on the coverage profile,
// removing irrelevant and unreached parts of the program.
// If the node is an *ast.File, comments are updated as well using
// an ast.CommentMap.
func (p *Profile) Trim(node ast.Node) {
	if f, ok := node.(*ast.File); ok {
		cmap := ast.NewCommentMap(p.Fset, f, f.Comments)
		ast.Walk(&trimVisitor{p}, f)
		f.Comments = cmap.Filter(f).Comments()
	} else {
		ast.Walk(&trimVisitor{p}, node)
	}
}
Пример #14
0
func (vis *pointerCandidatesVisitor) Visit(node ast.Node) ast.Visitor {
	switch t := node.(type) {
	case *ast.AssignStmt:
		for _, expr := range t.Rhs {
			ast.Walk(vis, expr)
		}
		if t.Tok == token.DEFINE {
			return nil
		}
		for _, ee := range t.Lhs {
			depth := 1
			stop := false
			for !stop {
				fmt.Printf("%T\n", ee)
				switch e := ee.(type) {
				case *ast.Ident:
					s := vis.identMap.GetSymbol(e)
					if vis.params.Contains(s) && depth > 0 {
						if i, ok := vis.result[s]; !ok || i < depth {
							vis.result[s] = depth
						}
					}
					stop = true
				case *ast.StarExpr:
					depth--
					ee = e.X
				case *ast.UnaryExpr:
					if e.Op == token.AND {
						depth++
					}
					ee = e.X
				case *ast.ParenExpr:
					ee = e.X
				case *ast.IndexExpr:
					ast.Walk(vis, e.Index)
					stop = true
				case *ast.SelectorExpr:
					ast.Walk(vis, e.X)
					stop = true
				default:
					stop = true
				}
			}
		}
		return nil
	case *ast.UnaryExpr:
		if t.Op != token.AND {
			return vis
		}
		vis.checkAddrOperators(t)
		return nil
	case *ast.StarExpr:
		vis.checkAddrOperators(t)
		return nil
	}
	return vis
}
Пример #15
0
func compareTwoTrees(src string) {
	v1 := &channelPusher{}
	v1.fileSet = token.NewFileSet()
	v1.queue = make(chan *ast.Node)

	v2 := &channelPusher{}
	v2.fileSet = token.NewFileSet()
	v2.queue = make(chan *ast.Node)

	tree1, err := parser.ParseExpr(src)
	if err != nil {
		panic(err)
	}

	src2 := "x + 2*y"
	tree2, err := parser.ParseExpr(src2)
	if err != nil {
		panic(err)
	}
	done := make(chan struct{})
	defer close(done)

	go func() {
		ast.Walk(v1, tree1)
		close(v1.queue)
		done <- struct{}{}
	}()
	go func() {
		ast.Walk(v2, tree2)
		close(v2.queue)
		done <- struct{}{}
	}()

	var n1, n2 *ast.Node
	quit := false
	for !quit {
		select {
		case n1 = <-v1.queue:
		case n2 = <-v2.queue:
		case <-done:
			quit = true
		}
		if n1 != nil && n2 != nil {
			if !equalNodes(n1, n2) {
				println("!equalNodes")
				break
			}
			println("equalNodes")
			n1 = nil
			n2 = nil
		}
	}
}
Пример #16
0
func (v *idVisitor) Visit(n ast.Node) (w ast.Visitor) {
	switch node := n.(type) {
	case *ast.Ident, *ast.SelectorExpr:
		id, err := str(node.(ast.Expr))
		if err == nil {
			v.rIDs[id] = n
		}
	case *ast.StarExpr:
		ast.Walk(v, node.X)
		return nil
	case *ast.CallExpr:
		stmt, ok := node.Fun.(*ast.SelectorExpr)
		if ok {
			ast.Walk(v, stmt.X)
		}

		if node.Args == nil {
			return nil
		}

		for _, arg := range node.Args {
			ast.Walk(v, arg)
		}
		return nil
	case *ast.AssignStmt:
		for _, e := range node.Lhs {
			id, err := str(e)
			if err != nil {
				return
			}
			v.wIDs[id] = n
		}

		for _, e := range node.Rhs {
			ast.Walk(v, e)
		}
		return nil
	case *ast.GenDecl:
		for _, s := range node.Specs {
			val, ok := s.(*ast.ValueSpec)
			if !ok {
				continue
			}

			for _, n := range val.Names {
				id, _ := str(n)
				v.wIDs[id] = node
			}
		}
	}
	w = v
	return
}
Пример #17
0
func (x *Indexer) Visit(node ast.Node) ast.Visitor {
	switch n := node.(type) {
	case nil:
		// nothing to do

	case *ast.Ident:
		x.visitIdent(Use, n)

	case *ast.FieldList:
		x.visitFieldList(VarDecl, n)

	case *ast.InterfaceType:
		x.visitFieldList(MethodDecl, n.Methods)

	case *ast.DeclStmt:
		// local declarations should only be *ast.GenDecls;
		// ignore incorrect ASTs
		if decl, ok := n.Decl.(*ast.GenDecl); ok {
			x.decl = nil // no snippets for local declarations
			x.visitGenDecl(decl)
		}

	case *ast.GenDecl:
		x.decl = n
		x.visitGenDecl(n)

	case *ast.FuncDecl:
		kind := FuncDecl
		if n.Recv != nil {
			kind = MethodDecl
			ast.Walk(x, n.Recv)
		}
		x.decl = n
		x.visitIdent(kind, n.Name)
		ast.Walk(x, n.Type)
		if n.Body != nil {
			ast.Walk(x, n.Body)
		}

	case *ast.File:
		x.decl = nil
		x.visitIdent(PackageClause, n.Name)
		for _, d := range n.Decls {
			ast.Walk(x, d)
		}

	default:
		return x
	}

	return nil
}
func main() {
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "simple.go", nil, 0)
	if err != nil {
		// Whoops!
	}
	ast.Walk(new(FuncVisitor), file)
	printer.Fprint(os.Stdout, fset, file)
	fmt.Println("-------------------------------------")
	ast.Walk(new(ImportVisitor), file)
	printer.Fprint(os.Stdout, fset, file)

	f, _ := os.Create("/tmp/new_simple.go")
	printer.Fprint(f, fset, file)
}
Пример #19
0
func (v visitor) scanDir(dirPath string) {
	dir, err := os.Open(dirPath)
	if err != nil {
		logFatal(err)
	}
	defer dir.Close()

	names, err := dir.Readdirnames(-1)
	if err != nil {
		logFatal(err)
	}

	for _, name := range names {
		fullPath := path.Join(dirPath, name)

		fi, err := os.Stat(fullPath)
		if err != nil {
			logFatal(err)
		}

		if fi.IsDir() {
			v.scanDir(fullPath)
		} else if !fi.IsDir() && strings.HasSuffix(fullPath, ".go") {
			astFile, err := parser.ParseFile(v.fileSet, fullPath, nil, 0)
			if err != nil {
				logFatal(err)
			}

			ast.Walk(v, astFile)
		}
	}
}
Пример #20
0
// process parses and rewrites a file by generating the appropriate exported
// types for raw types.
func process(path string) error {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	// Remove code between begin/end pragma comments.
	b = regexp.MustCompile(`(?is)//raw:codegen:begin.+?//raw:codegen:end`).ReplaceAll(b, []byte{})
	b = []byte(strings.TrimRight(string(b), " \n\r"))

	// Re-parse the file without the pragmas.
	f, err := parser.ParseFile(token.NewFileSet(), path, b, 0)
	if err != nil {
		return err
	}

	// Iterate over all the nodes and add exported types where appropriate.
	var g generator
	g.w.Write(b)
	g.w.WriteString("\n\n")

	ast.Walk(&g, f)
	if g.err != nil {
		return g.err
	}

	// Rewrite original file.
	ioutil.WriteFile(path, g.w.Bytes(), 0600)

	log.Println("OK", path)

	return nil
}
Пример #21
0
func Transform(src *ast.File) *ast.File {
	// find the golex import...
	var toplevel ToplevelVisitor

	for _, spec := range src.Imports {
		ast.Print(nil, spec)
		if conv, err := strconv.Unquote(spec.Path.Value); err != nil || conv != "golex" {
			continue
		}
		if spec.Name != nil {
			toplevel.golexPackage = spec.Name.Name
		} else {
			toplevel.golexPackage = "golex"
		}
		break
	}
	if toplevel.golexPackage == "" {
		log.Print("Not a lex input")

		return src
	}

	ast.Walk(&toplevel, src)
	// Now, find switch statemnts...
	return src
}
Пример #22
0
func (c *funcContext) translateLoopingStmt(cond string, body *ast.BlockStmt, bodyPrefix, post func(), label string, flatten bool) {
	prevFlowData := c.flowDatas[""]
	data := &flowData{
		postStmt: post,
	}
	if _, ok := c.labelCases[label]; ok {
		flatten = true // always flatten if label is referenced by goto
	}
	if flatten {
		data.beginCase = c.caseCounter
		data.endCase = c.caseCounter + 1
		c.caseCounter += 2
	}
	c.flowDatas[""] = data
	c.flowDatas[label] = data

	c.printLabel(label)
	if !flatten && label != "" {
		c.Printf("%s:", label)
	}
	c.PrintCond(!flatten, fmt.Sprintf("while (%s) {", cond), fmt.Sprintf("case %d: if(!(%s)) { $s = %d; continue; }", data.beginCase, cond, data.endCase))
	c.Indent(func() {
		v := &escapeAnalysis{
			info:       c.p.info,
			candidates: make(map[types.Object]bool),
			escaping:   make(map[types.Object]bool),
		}
		ast.Walk(v, body)
		prevEV := c.p.escapingVars
		c.p.escapingVars = make(map[types.Object]bool)
		for escaping := range prevEV {
			c.p.escapingVars[escaping] = true
		}
		for escaping := range v.escaping {
			c.Printf("%s = [undefined];", c.objectName(escaping))
			c.p.escapingVars[escaping] = true
		}

		if bodyPrefix != nil {
			bodyPrefix()
		}
		c.translateStmtList(body.List)
		isTerminated := false
		if len(body.List) != 0 {
			switch body.List[len(body.List)-1].(type) {
			case *ast.ReturnStmt, *ast.BranchStmt:
				isTerminated = true
			}
		}
		if !isTerminated {
			post()
		}

		c.p.escapingVars = prevEV
	})
	c.PrintCond(!flatten, "}", fmt.Sprintf("$s = %d; continue; case %d:", data.beginCase, data.endCase))

	delete(c.flowDatas, label)
	c.flowDatas[""] = prevFlowData
}
Пример #23
0
Файл: cover.go Проект: sreis/go
func annotate(name string) {
	fset := token.NewFileSet()
	content, err := ioutil.ReadFile(name)
	if err != nil {
		log.Fatalf("cover: %s: %s", name, err)
	}
	parsedFile, err := parser.ParseFile(fset, name, content, parser.ParseComments)
	if err != nil {
		log.Fatalf("cover: %s: %s", name, err)
	}
	parsedFile.Comments = trimComments(parsedFile, fset)

	file := &File{
		fset:    fset,
		name:    name,
		astFile: parsedFile,
	}
	if *mode == "atomic" {
		file.atomicPkg = file.addImport(atomicPackagePath)
	}
	ast.Walk(file, file.astFile)
	fd := os.Stdout
	if *output != "" {
		var err error
		fd, err = os.Create(*output)
		if err != nil {
			log.Fatalf("cover: %s", err)
		}
	}
	fd.Write(initialComments(content)) // Retain '// +build' directives.
	file.print(fd)
	// After printing the source tree, add some declarations for the counters etc.
	// We could do this by adding to the tree, but it's easier just to print the text.
	file.addVariables(fd)
}
Пример #24
0
// UsesImport reports whether a given import is used.
func UsesImport(f *ast.File, path string) (used bool) {
	spec := importSpec(f, path)
	if spec == nil {
		return
	}

	name := spec.Name.String()
	switch name {
	case "<nil>":
		// If the package name is not explicitly specified,
		// make an educated guess. This is not guaranteed to be correct.
		lastSlash := strings.LastIndex(path, "/")
		if lastSlash == -1 {
			name = path
		} else {
			name = path[lastSlash+1:]
		}
	case "_", ".":
		// Not sure if this import is used - err on the side of caution.
		return true
	}

	ast.Walk(visitFn(func(n ast.Node) {
		sel, ok := n.(*ast.SelectorExpr)
		if ok && isTopName(sel.X, name) {
			used = true
		}
	}), f)

	return
}
Пример #25
0
func checkHTTPResponse(f *File, node ast.Node) {
	call := node.(*ast.CallExpr)
	if !isHTTPFuncOrMethodOnClient(f, call) {
		return // the function call is not related to this check.
	}

	finder := &blockStmtFinder{node: call}
	ast.Walk(finder, f.file)
	stmts := finder.stmts()
	if len(stmts) < 2 {
		return // the call to the http function is the last statement of the block.
	}

	asg, ok := stmts[0].(*ast.AssignStmt)
	if !ok {
		return // the first statement is not assignment.
	}
	resp := rootIdent(asg.Lhs[0])
	if resp == nil {
		return // could not find the http.Response in the assignment.
	}

	def, ok := stmts[1].(*ast.DeferStmt)
	if !ok {
		return // the following statement is not a defer.
	}
	root := rootIdent(def.Call.Fun)
	if root == nil {
		return // could not find the receiver of the defer call.
	}

	if resp.Obj == root.Obj {
		f.Badf(root.Pos(), "using %s before checking for errors", resp.Name)
	}
}
Пример #26
0
func MutateFile(src string, f, t token.Token) error {
	fset := token.NewFileSet()

	file, err := parser.ParseFile(fset, src, nil, 0)
	if err != nil {
		return fmt.Errorf("failed to parse %s: %s", src, err)
	}

	ef := ExpressionFinder{Token: f}
	ast.Walk(&ef, file)

	filename := filepath.Base(src)
	log.Printf("found %d occurrences of %s in %s", ef.Len(), f, filename)
	for index, exp := range ef.Exps {
		err := RunMutation(index, exp, f, t, src, fset, file)
		if err != nil {
			return err
		}
	}

	// Restore the original file
	err = printFile(src, fset, file)
	if err != nil {
		return err
	}
	return nil
}
Пример #27
0
func simplify(f *ast.File) {
	// remove empty declarations such as "const ()", etc
	removeEmptyDeclGroups(f)

	var s simplifier
	ast.Walk(s, f)
}
Пример #28
0
func (gas *Analyzer) process(filename string, source interface{}) error {
	mode := parser.ParseComments
	root, err := parser.ParseFile(gas.context.FileSet, filename, source, mode)
	if err == nil {
		gas.context.Comments = ast.NewCommentMap(gas.context.FileSet, root, root.Comments)
		gas.context.Root = root

		// here we get type info
		gas.context.Info = &types.Info{
			Types:      make(map[ast.Expr]types.TypeAndValue),
			Defs:       make(map[*ast.Ident]types.Object),
			Uses:       make(map[*ast.Ident]types.Object),
			Selections: make(map[*ast.SelectorExpr]*types.Selection),
			Scopes:     make(map[ast.Node]*types.Scope),
			Implicits:  make(map[ast.Node]types.Object),
		}

		conf := types.Config{Importer: importer.Default()}
		gas.context.Pkg, _ = conf.Check("pkg", gas.context.FileSet, []*ast.File{root}, gas.context.Info)
		if err != nil {
			gas.logger.Println("failed to check imports")
			return err
		}

		ast.Walk(gas, root)
		gas.Stats.NumFiles++
	}
	return err
}
Пример #29
0
func GetDeps(source string) (pkg, target string, deps, funcs, cflags, ldflags []string, err error) {
	isTest := strings.HasSuffix(source, "_test.go") && Test
	var file *ast.File
	flag := parser.ParseComments
	if !isTest {
		flag = flag | parser.ImportsOnly
	}
	file, err = parser.ParseFile(token.NewFileSet(), source, nil, flag)
	if err != nil {
		return
	}

	w := &Walker{
		Name:       "",
		Target:     "",
		pkgPos:     0,
		Deps:       []string{},
		Funcs:      []string{},
		CGoLDFlags: []string{},
		CGoCFlags:  []string{},
		ScanFuncs:  isTest,
	}

	ast.Walk(w, file)

	deps = w.Deps
	pkg = w.Name
	target = w.Target
	funcs = w.Funcs
	cflags = RemoveDups(w.CGoCFlags)
	ldflags = RemoveDups(w.CGoLDFlags)

	return
}
Пример #30
0
func (f *File) methodSet(set *types.MethodSet) {
	// Build the set of things we're looking for.
	methods := make([]method, 0, set.Len())
	docs := make([]string, set.Len())
	for i := 0; i < set.Len(); i++ {
		if ast.IsExported(set.At(i).Obj().Name()) {
			m := method{
				i,
				set.At(i),
			}
			methods = append(methods, m)
		}
	}
	if len(methods) == 0 {
		return
	}
	// Collect the docs.
	for _, file := range f.allFiles {
		visitor := &methodVisitor{
			File:    file,
			methods: methods,
			docs:    docs,
		}
		ast.Walk(visitor, file.file)
		methods = visitor.methods
	}
	// Print them in order. The incoming method set is sorted by name.
	for _, doc := range docs {
		if doc != "" {
			fmt.Print(doc)
		}
	}
}