func fprint(w io.Writer, a interface{}) error { switch x := a.(type) { case *ast.FieldList: // printer.Fprint does not support this type. Hack around it. return fprintFieldList(w, x) case ast.Node, []ast.Decl, []ast.Stmt: return printer.Fprint(w, token.NewFileSet(), x) case []ast.Expr: i := 0 for ; i < len(x)-1; i++ { if err := printer.Fprint(w, token.NewFileSet(), x[i]); err != nil { return err } if _, err := w.Write([]byte(", ")); err != nil { return err } } if len(x) != 0 { return printer.Fprint(w, token.NewFileSet(), x[i]) } return nil case string: _, err := io.WriteString(w, x) return err default: panic(fmt.Sprintf("unsupported value: %v", x)) } }
func printIncReturns(fset *token.FileSet, v map[*ast.ReturnStmt]*ast.FuncType) { for ret, ftyp := range v { fmt.Print("FUNC TYPE: ") printer.Fprint(os.Stdout, fset, ftyp) fmt.Print(" RETURN: ") printer.Fprint(os.Stdout, fset, ret) fmt.Println() } }
// Do creates a concrete ast from the generic one and writes it to the given io.Writer func (g *Generify) Do(packageName string, w io.Writer) error { var decls []ast.Decl g.genTypes, decls = findGenerics(g.file) if len(g.genTypes) == 0 { return fmt.Errorf("no generic types found") } if len(g.genTypes) != len(g.concreteTypes.Instance[0]) { return fmt.Errorf("there are %d generic types but %d concrete types", len(g.genTypes), len(g.concreteTypes.Instance[0])) } removeCommentsFrom(decls) decls = splitDeclsToUngroupedDecls(decls) g.genericDecls = g.inspectAllDeclsForDependencies(decls) g.checkMethodDependencies() g.renameStructsAndVars() g.renameFunctions() file := ast.File{Name: g.file.Name, Decls: g.staticDecls(), Scope: g.file.Scope, Imports: g.file.Imports} if packageName != "" { file.Name.Name = packageName } fset := token.NewFileSet() err := printer.Fprint(w, fset, &file) if err != nil { return err } w.Write(newline) for _, types := range g.concreteTypes.Instance { // rename all identifiers for _, ra := range g.renameActions { ra.rename(types) } // write the renamed ast for _, decl := range g.genericDecls { if len(decl.usedTypes) > 0 && !decl.isAllreadyWritten(types) { err := printer.Fprint(w, fset, decl.decl) if err != nil { return err } w.Write(newline) } } } return nil }
func (v *visitor) rangestr(rs *ast.RangeStmt) string { v.buffer.Reset() v.buffer.WriteString("for ") printer.Fprint(&v.buffer, v.fset, rs.Key) if rs.Value != nil { v.buffer.WriteString(", ") printer.Fprint(&v.buffer, v.fset, rs.Value) } v.buffer.WriteString(" := range ") printer.Fprint(&v.buffer, v.fset, rs.X) return v.buffer.String() }
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) }
func (f *file) render(x interface{}) string { var buf bytes.Buffer if err := printer.Fprint(&buf, f.fset, x); err != nil { panic(err) } return buf.String() }
// Process takes a Go source file and bumps version declaration according to conf. // Returns the modified code and a map from identifiers to updated versions and an error, if any. func (conf Config) Process(filename string, src interface{}) ([]byte, map[string]string, error) { fset := token.NewFileSet() file, err := parser.ParseFile(fset, filename, src, parser.ParseComments) if err != nil { return nil, nil, err } versions, err := conf.ProcessNode(fset, file) if err != nil { return nil, nil, err } var buf bytes.Buffer err = printer.Fprint(&buf, fset, file) if err != nil { return nil, nil, err } out := buf.Bytes() out, err = format.Source(out) if err != nil { return nil, nil, err } return out, versions, nil }
func render(fset *token.FileSet, x interface{}) string { var buf bytes.Buffer if err := printer.Fprint(&buf, fset, x); err != nil { panic(err) } return buf.String() }
func astString(x ast.Expr) string { var buf bytes.Buffer if err := printer.Fprint(&buf, fset, x); err != nil { panic(err) } return buf.String() }
func main() { if filename == "" || line == -1 || column == -1 || newName == "" { fmt.Printf("%v %v %v \n", filename, line, column) fmt.Printf("Usage: goref -f <filename> -l <line number> -c <column number> -n <new symbol name>\n") return } newPack, count := RenameIdent(".", filename, line, column, newName) if newPack != nil { fmt.Printf("res : %v\n", count) for fname, f := range newPack.Files { if nf, err := os.OpenFile("refgo_out_"+fname, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666); err != nil { fmt.Printf("file %v already exists,cannot finish output\n", "refgo_out_"+fname) return } else { printer.Fprint(nf, f) nf.Close() } } } else { fmt.Printf("error : %v\n", count) } }
func (r *InterfaceGen) formatType(fileset *token.FileSet, field *ast.Field) *Type { var typeBuf bytes.Buffer _ = printer.Fprint(&typeBuf, fileset, field.Type) if len(field.Names) == 0 { fatalNode(fileset, field, "RPC interface parameters and results must all be named") } for _, typeName := range types(field.Type) { parts := strings.SplitN(typeName, ".", 2) if len(parts) > 1 { for _, imp := range r.CheckImports { importPath := imp.Path.Value[1 : len(imp.Path.Value)-1] if imp.Name != nil && imp.Name.String() == parts[0] { r.Imports[fmt.Sprintf("%s %s", imp.Name, importPath)] = true } else if filepath.Base(importPath) == parts[0] { r.Imports[importPath] = true } } } } t := &Type{Type: typeBuf.String()} for _, n := range field.Names { lowerName := n.Name name := strings.ToUpper(lowerName[0:1]) + lowerName[1:] t.Names = append(t.Names, name) t.LowerNames = append(t.LowerNames, lowerName) } return t }
func extractFunc(funcName string, inputPath string) ([]string, string, error) { fset := token.NewFileSet() fp, err := parser.ParseFile(fset, inputPath, nil, 0) if err != nil { return nil, "", err } imports := make([]string, 0) for _, imp := range fp.Imports { imports = append(imports, imp.Path.Value) } var buf bytes.Buffer for _, decl := range fp.Decls { f, ok := decl.(*ast.FuncDecl) if !ok { continue } if f.Name.Name != funcName { continue } f.Name.Name = "ffjson_" + f.Name.Name printer.Fprint(&buf, fset, f) break } return imports, string(buf.Bytes()), nil }
func (w *Walker) walkFile(name string, file *ast.File) { // Not entering a scope here; file boundaries aren't interesting. for _, di := range file.Decls { switch d := di.(type) { case *ast.GenDecl: switch d.Tok { case token.IMPORT: continue case token.CONST: for _, sp := range d.Specs { w.walkConst(sp.(*ast.ValueSpec)) } case token.TYPE: for _, sp := range d.Specs { w.walkTypeSpec(sp.(*ast.TypeSpec)) } case token.VAR: for _, sp := range d.Specs { w.walkVar(sp.(*ast.ValueSpec)) } default: log.Fatalf("unknown token type %d in GenDecl", d.Tok) } case *ast.FuncDecl: // Ignore. Handled in subsequent pass, by go/doc. default: log.Printf("unhandled %T, %#v\n", di, di) printer.Fprint(os.Stderr, w.fset, di) os.Stderr.Write([]byte("\n")) } } }
func main() { if len(os.Args) > 1 { args(os.Args[1]) return } r := bufio.NewReader(os.Stdin) for { fmt.Print(">> ") line, _, _ := r.ReadLine() p := parser.ParseFromString("<REPL>", string(line)+"\n") fmt.Println(p) // a := generator.GenerateAST(p) a := generator.EvalExprs(p) fset := token.NewFileSet() ast.Print(fset, a) var buf bytes.Buffer printer.Fprint(&buf, fset, a) fmt.Printf("%s\n", buf.String()) } }
func args(filename string) { b, err := ioutil.ReadFile(filename) if err != nil { panic(err) } p := parser.ParseFromString(filename, string(b)+"\n") a := generator.GenerateAST(p) fset := token.NewFileSet() defaultImports := []string{"github.com/gsp-lang/stdlib/prelude", "github.com/gsp-lang/gsp/core"} for _, defaultImport := range defaultImports { split := strings.Split(defaultImport, "/") pkgName := split[len(split)-1] if !(a.Name.Name == "prelude" && pkgName == "prelude") { astutil.AddImport(fset, a, defaultImport) } } if a.Name.Name != "prelude" { a.Decls = append(a.Decls, &ast.GenDecl{ Tok: token.VAR, Specs: []ast.Spec{&ast.ValueSpec{ Names: []*ast.Ident{&ast.Ident{Name: "_"}}, Values: []ast.Expr{&ast.Ident{Name: "prelude.Len"}}, }}, }) } var buf bytes.Buffer printer.Fprint(&buf, fset, a) fmt.Printf("%s\n", buf.String()) }
func ExampleFprint() { // Parse source file and extract the AST without comments for // this function, with position information referring to the // file set fset. funcAST, fset := parseFunc("example_test.go", "ExampleFprint") // Print the function body into buffer buf. // The file set is provided to the printer so that it knows // about the original source formatting and can add additional // line breaks where they were present in the source. var buf bytes.Buffer printer.Fprint(&buf, fset, funcAST.Body) // Remove braces {} enclosing the function body, unindent, // and trim leading and trailing white space. s := buf.String() s = s[1 : len(s)-1] s = strings.TrimSpace(strings.Replace(s, "\n\t", "\n", -1)) // Print the cleaned-up body text to stdout. fmt.Println(s) // output: // funcAST, fset := parseFunc("example_test.go", "ExampleFprint") // // var buf bytes.Buffer // printer.Fprint(&buf, fset, funcAST.Body) // // s := buf.String() // s = s[1 : len(s)-1] // s = strings.TrimSpace(strings.Replace(s, "\n\t", "\n", -1)) // // fmt.Println(s) }
func TestGenerateTestCase(t *testing.T) { fset := token.NewFileSet() srcFile := "/home/joar/go/src/github.com/joarleth/slask/slask.go" file, err := parser.ParseFile(fset, srcFile, nil, parser.ParseComments) if err != nil { t.Error(err) } mutationIDs := []uint{3, 7} for _, d := range file.Decls { if fd, ok := d.(*ast.FuncDecl); ok { if fd.Name.Name == "Join" { f, fset := GenerateTestCase(fd, mutationIDs, "slask") var buf bytes.Buffer printer.Fprint(&buf, fset, f) s := buf.String() fmt.Printf(s) break } } } }
// Render renders an ast node func (scope *Scope) Render(x ast.Node) string { var buf bytes.Buffer if err := printer.Fprint(&buf, scope.fset, x); err != nil { panic(err) } return buf.String() }
func getSource(t *testing.T, n ast.Node) string { fset := token.NewFileSet() var buf bytes.Buffer err := printer.Fprint(&buf, fset, n) assert.NoError(t, err) return buf.String() }
// Process formats and adjusts returns for the provided file in a // package in pkgDir. If pkgDir is empty, the file is treated as a // standalone fragment (opt.Fragment should be true). If opt is nil // the defaults are used. func Process(pkgDir, filename string, src []byte, opt *Options) ([]byte, error) { if opt == nil { opt = &Options{} } fileSet := token.NewFileSet() file, adjust, typeInfo, err := parseAndCheck(fileSet, pkgDir, filename, src, opt) if err != nil { return nil, err } if err := fixReturns(fileSet, file, typeInfo); err != nil { return nil, err } var buf bytes.Buffer err = printer.Fprint(&buf, fileSet, file) if err != nil { return nil, err } out := buf.Bytes() if adjust != nil { out = adjust(src, out) } out, err = format.Source(out) if err != nil { return nil, err } return out, nil }
func main() { // src is the input for which we want to print the AST. src := ` package main func hello(a, b Any, rest ...Any) Any { return a } func main() { f := 10 f.(func(int)Any) } ` // Create the AST by parsing src. fset := token.NewFileSet() // positions are relative to fset f, err := parser.ParseFile(fset, "", src, 0) if err != nil { panic(err) } // (f.Decls[0].(*ast.GenDecl)).Specs[0].Name.Obj = nil // ((f.Decls[0].(*ast.GenDecl)).Specs[0].(*ast.TypeSpec).Name.Obj) = nil // f.Imports = nil ast.Print(fset, f) // Print the AST. var buf bytes.Buffer printer.Fprint(&buf, fset, f) fmt.Println(buf.String()) }
func main() { fileSet := token.NewFileSet() astFile, err := parser.ParseFile(fileSet, "minimal.go", nil, parser.ParseComments) if err != nil { panic(err) } ast.Print(fileSet, astFile) return astFile.Decls = append(astFile.Decls[:0], append([]ast.Decl{&ast.FuncDecl{ Name: ast.NewIdent("MyNewFunc"), Type: &ast.FuncType{ Func: 15, Params: &ast.FieldList{ Opening: 29, Closing: 30, }, }, }}, astFile.Decls[0:]...)...) offset := astFile.Decls[0].End() - astFile.Decls[0].Pos() intoffset := int(offset) fmt.Println("offset", offset) astFile.Comments[0].List[0].Slash += offset // astFile.Comments[0].List[0].Slash = 18 astFile.Decls[1].(*ast.GenDecl).TokPos += offset astFile.Decls[1].(*ast.GenDecl).Lparen += offset astFile.Decls[1].(*ast.GenDecl).Rparen += offset fileSetFile := fileSet.File(1) newFileSet := token.NewFileSet() newFileSetFile := newFileSet.AddFile("whatever", 1, fileSetFile.Size()+int(offset)) newFileSetFile.SetLines([]int{ 0, 13, 14, 15, 15 + intoffset, 20 + intoffset, 21 + intoffset, 32 + intoffset, 33 + intoffset, }) // hardcoded for now fmt.Println("astFile:") spew.Dump(astFile) fmt.Println() fmt.Println() fmt.Println("fileSet:") spew.Dump(fileSet) buf := new(bytes.Buffer) err = printer.Fprint(buf, newFileSet, astFile) if err != nil { panic(err) } fmt.Println(buf) }
func registerPlugins(src string, plugins features.Plugins) error { fset := token.NewFileSet() file := filepath.Join(src, importFile) f, err := parser.ParseFile(fset, file, nil, 0) if err != nil { return err } for _, m := range plugins.Packages() { astutil.AddNamedImport(fset, f, "_", m) } var buf bytes.Buffer err = printer.Fprint(&buf, fset, f) if err != nil { return err } // Save generated code file err = ioutil.WriteFile(file, buf.Bytes(), os.FileMode(0660)) if err != nil { return err } // run `go generate` for all plugins return goGenerate(plugins) }
func (w AgentWriter) fieldList(fields *ast.FieldList) string { var out bytes.Buffer for i, param := range fields.List { if i != 0 { fmt.Fprint(&out, ", ") } for j, pname := range param.Names { if j != 0 { fmt.Fprint(&out, ", ") } fmt.Fprint(&out, pname) } if len(param.Names) == 0 { // Give the arg an arbitrary name, since anonymous structs can't // otherwise have multiple fields of the same type. fmt.Fprintf(&out, "val%d", i+1) } fmt.Fprint(&out, " ") printer.Fprint(&out, w.fset, param.Type) } return out.String() }
func processFile(file string) error { fset := token.NewFileSet() f, err := parser.ParseFile(fset, file, nil, parser.ParseComments) if err != nil { return fmt.Errorf("%s: %v", file, err) } var changed bool for _, d := range f.Decls { d, ok := d.(*ast.GenDecl) if !ok || d.Tok != token.IMPORT { // Not an import declaration, so we're done. // Imports are always first. break } for _, s := range d.Specs { s, ok := s.(*ast.ImportSpec) if !ok || s.Path.Kind != token.STRING { continue } old := s.Path.Value s.Path.Value = rewrite(s.Path.Value) if s.Path.Value != old { changed = true } } } if !changed { return nil } var buf bytes.Buffer if err := printer.Fprint(&buf, fset, f); err != nil { return err } return ioutil.WriteFile(file, buf.Bytes(), 0) }
// WriteToDir writes pkg to the directory at dir as Go source files. // // If necessary, populates the package tree with go/ast's data structures // as an intermediate step. // // The package will not be typechecked. func WriteToDir(pkg *Package, dir string) error { err := os.Mkdir(dir, 0755) if err != nil && !os.IsExist(err) { return err } fset := &token.FileSet{} if pkg.ast == nil { populateASTWithTokenSet(pkg, fset) } for _, f := range pkg.Files() { fp, err := os.Create(filepath.Join(dir, f.Name())) if err != nil { return err } err = printer.Fprint(fp, fset, f.AST()) fp.Close() if err != nil { return err } } return nil }
// ConvertBreakpoint converts from a proc.Breakpoint to // an api.Breakpoint. func ConvertBreakpoint(bp *proc.Breakpoint) *Breakpoint { b := &Breakpoint{ Name: bp.Name, ID: bp.ID, FunctionName: bp.FunctionName, File: bp.File, Line: bp.Line, Addr: bp.Addr, Tracepoint: bp.Tracepoint, Stacktrace: bp.Stacktrace, Goroutine: bp.Goroutine, Variables: bp.Variables, LoadArgs: LoadConfigFromProc(bp.LoadArgs), LoadLocals: LoadConfigFromProc(bp.LoadLocals), TotalHitCount: bp.TotalHitCount, } b.HitCount = map[string]uint64{} for idx := range bp.HitCount { b.HitCount[strconv.Itoa(idx)] = bp.HitCount[idx] } var buf bytes.Buffer printer.Fprint(&buf, token.NewFileSet(), bp.Cond) b.Cond = buf.String() return b }
func astStr(o interface{}, fset *token.FileSet) string { defer func() { recover() }() var w bytes.Buffer w.WriteByte('\n') printer.Fprint(&w, fset, o) return w.String() }
// writeOutput creates stubs for a specific source file to be compiled by 6g // (The comments here say 6g and 6c but the code applies to the 8 and 5 tools too.) func (p *Package) writeOutput(f *File, srcfile string) { base := srcfile if strings.HasSuffix(base, ".go") { base = base[0 : len(base)-3] } base = strings.Map(slashToUnderscore, base) fgo1 := creat("_obj/" + base + ".cgo1.go") fgcc := creat("_obj/" + base + ".cgo2.c") p.GoFiles = append(p.GoFiles, base+".cgo1.go") p.GccFiles = append(p.GccFiles, base+".cgo2.c") // Write Go output: Go input with rewrites of C.xxx to _C_xxx. fmt.Fprintf(fgo1, "// Created by cgo - DO NOT EDIT\n\n") fmt.Fprintf(fgo1, "//line %s:1\n", srcfile) printer.Fprint(fgo1, fset, f.AST) // While we process the vars and funcs, also write 6c and gcc output. // Gcc output starts with the preamble. fmt.Fprintf(fgcc, "%s\n", f.Preamble) fmt.Fprintf(fgcc, "%s\n", gccProlog) for _, n := range f.Name { if n.FuncType != nil { p.writeOutputFunc(fgcc, n) } } fgo1.Close() fgcc.Close() }
func walkFile(path string) error { b, err := ioutil.ReadFile(path) if err != nil { return kerr.Wrap("FGAHVRNUPV", err) } fset := token.NewFileSet() file, err := parser.ParseFile(fset, path, nil, parser.ParseComments) if err != nil { return kerr.Wrap("ALRIEYJBJE", err) } // visitor implements ast.Visitor v := &visitor{b, false} ast.Walk(v, file) // if we made a replacement, re-write the modified file if v.Found { fmt.Println(path) f, err := os.Create(path) if err != nil { return kerr.Wrap("QFPDQRTIRS", err) } defer f.Close() if err := printer.Fprint(f, fset, file); err != nil { return kerr.Wrap("VEPVDWFWEF", err) } } return nil }