Пример #1
0
func (m Mocks) Output(pkg, dir string, chanSize int, dest io.Writer) error {
	if _, err := dest.Write([]byte(commentHeader)); err != nil {
		return err
	}

	fset := token.NewFileSet()

	f := &ast.File{
		Name:  &ast.Ident{Name: pkg},
		Decls: m.decls(chanSize),
	}

	var b bytes.Buffer
	format.Node(&b, fset, f)

	// TODO: Determine why adding imports without creating a new ast file
	// will only allow one import to be printed to the file.
	fset = token.NewFileSet()
	file, err := parser.ParseFile(fset, pkg, &b, 0)
	if err != nil {
		return err
	}

	file, fset, err = addImports(file, fset, dir)
	if err != nil {
		return err
	}

	return format.Node(dest, fset, file)
}
Пример #2
0
func (b *builder) merge() ([]byte, error) {
	var buf bytes.Buffer
	if err := b.tpl.Execute(&buf, b); err != nil {
		return nil, err
	}

	f, err := parser.ParseFile(b.fset, "", &buf, 0)
	if err != nil {
		return nil, err
	}
	// b.imports(f)
	b.deleteImports(f)
	b.files["main.go"] = f

	pkg, _ := ast.NewPackage(b.fset, b.files, nil, nil)
	pkg.Name = "main"

	ret, err := ast.MergePackageFiles(pkg, 0), nil
	if err != nil {
		return nil, err
	}

	// @TODO: we reread the file, probably something goes wrong with position
	buf.Reset()
	if err = format.Node(&buf, b.fset, ret); err != nil {
		return nil, err
	}

	ret, err = parser.ParseFile(b.fset, "", buf.Bytes(), 0)
	if err != nil {
		return nil, err
	}

	for _, spec := range b.imports {
		var name string
		if spec.Name != nil {
			name = spec.Name.Name
		}
		ipath, _ := strconv.Unquote(spec.Path.Value)
		addImport(b.fset, ret, name, ipath)
	}

	buf.Reset()
	if err := format.Node(&buf, b.fset, ret); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}
Пример #3
0
func CodeBytes(fset *token.FileSet, node interface{}) ([]byte, error) {
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, node); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #4
0
/*
 * Given a file path, rewrites any tests in the Ginkgo format.
 * First, we parse the AST, and update the imports declaration.
 * Then, we walk the first child elements in the file, returning tests to rewrite.
 * A top level init func is declared, with a single Describe func inside.
 * Then the test functions to rewrite are inserted as It statements inside the Describe.
 * Finally we walk the rest of the file, replacing other usages of *testing.T
 * Once that is complete, we write the AST back out again to its file.
 */
func rewriteTestsInFile(pathToFile string) {
	fileSet := token.NewFileSet()
	rootNode, err := parser.ParseFile(fileSet, pathToFile, nil, 0)
	if err != nil {
		panic(fmt.Sprintf("Error parsing test file '%s':\n%s\n", pathToFile, err.Error()))
	}

	addGinkgoImports(rootNode)
	removeTestingImport(rootNode)

	topLevelInitFunc := createInitBlock()
	describeBlock := createDescribeBlock()
	topLevelInitFunc.Body.List = append(topLevelInitFunc.Body.List, describeBlock)

	for _, testFunc := range findTestFuncs(rootNode) {
		rewriteTestFuncAsItStatement(testFunc, rootNode, describeBlock)
	}

	rootNode.Decls = append(rootNode.Decls, topLevelInitFunc)
	rewriteOtherFuncsToUseGinkgoT(rootNode.Decls)
	walkNodesInRootNodeReplacingTestingT(rootNode)

	var buffer bytes.Buffer
	if err = format.Node(&buffer, fileSet, rootNode); err != nil {
		panic(fmt.Sprintf("Error formatting ast node after rewriting tests.\n%s\n", err.Error()))
	}

	fileInfo, err := os.Stat(pathToFile)
	if err != nil {
		panic(fmt.Sprintf("Error stat'ing file: %s\n", pathToFile))
	}

	ioutil.WriteFile(pathToFile, buffer.Bytes(), fileInfo.Mode())
	return
}
Пример #5
0
func (m Mocks) Output(pkg string, chanSize int, dest io.Writer) error {
	f := &ast.File{
		Name:  &ast.Ident{Name: pkg},
		Decls: m.decls(chanSize),
	}
	return format.Node(dest, token.NewFileSet(), f)
}
Пример #6
0
func TestExamples(t *testing.T) {
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "test.go", strings.NewReader(exampleTestFile), parser.ParseComments)
	if err != nil {
		t.Fatal(err)
	}
	for i, e := range doc.Examples(file) {
		c := exampleTestCases[i]
		if e.Name != c.Name {
			t.Errorf("got Name == %q, want %q", e.Name, c.Name)
		}
		if w := c.Play; w != "" {
			var g string // hah
			if e.Play == nil {
				g = "<nil>"
			} else {
				var buf bytes.Buffer
				if err := format.Node(&buf, fset, e.Play); err != nil {
					t.Fatal(err)
				}
				g = buf.String()
			}
			if g != w {
				t.Errorf("%s: got Play == %q, want %q", c.Name, g, w)
			}
		}
		if g, w := e.Output, c.Output; g != w {
			t.Errorf("%s: got Output == %q, want %q", c.Name, g, w)
		}
	}
}
Пример #7
0
// Gen generates Go code for a set of table mappings.
func (c *Code) Gen(mapper *Map, pkg string, out io.Writer) {
	data := struct {
		Package   string
		Imports   []importSpec
		TableMaps []tableMapTmpl
	}{
		Package: pkg,
		Imports: mapper.Imports(),
	}

	for i, tableMap := range *mapper {
		log.Printf("%d: generating map %s -> %s", i, tableMap.Table, tableMap.Struct)
		data.TableMaps = append(data.TableMaps, c.genMapper(tableMap))
	}

	if err := c.tmpl.Execute(c.buf, data); err != nil {
		// TODO(paulsmith): return error
		log.Fatal(err)
	}

	// gofmt
	fset := token.NewFileSet()
	ast, err := parser.ParseFile(fset, "", c.buf.Bytes(), parser.ParseComments)
	if err != nil {
		// TODO(paulsmith): return error
		log.Fatal(err)
	}
	err = format.Node(out, fset, ast)
	if err != nil {
		// TODO(paulsmith): return error
		log.Fatal(err)
	}
}
Пример #8
0
func gofmt(n interface{}) string {
	gofmtBuf.Reset()
	if err := format.Node(&gofmtBuf, fset, n); err != nil {
		return "<" + err.Error() + ">"
	}
	return gofmtBuf.String()
}
Пример #9
0
// FormatCode runs "goimports -w" on the source file.
func (f *SourceFile) FormatCode() error {
	// Parse file into AST
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, f.Abs(), nil, parser.ParseComments)
	if err != nil {
		content, _ := ioutil.ReadFile(f.Abs())
		var buf bytes.Buffer
		scanner.PrintError(&buf, err)
		return fmt.Errorf("%s\n========\nContent:\n%s", buf.String(), content)
	}
	// Clean unused imports
	imports := astutil.Imports(fset, file)
	for _, group := range imports {
		for _, imp := range group {
			path := strings.Trim(imp.Path.Value, `"`)
			if !astutil.UsesImport(file, path) {
				if imp.Name != nil {
					astutil.DeleteNamedImport(fset, file, imp.Name.Name, path)
				} else {
					astutil.DeleteImport(fset, file, path)
				}
			}
		}
	}
	ast.SortImports(fset, file)
	// Open file to be written
	w, err := os.OpenFile(f.Abs(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
	if err != nil {
		return err
	}
	defer w.Close()
	// Write formatted code without unused imports
	return format.Node(w, fset, file)
}
Пример #10
0
// nodeString returns a string representation of n.
func nodeString(n ast.Node) string {
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, n); err != nil {
		log.Fatal(err) // should always succeed
	}
	return buf.String()
}
Пример #11
0
func TranspileFile(goFilename, phpFilename, phpStr string, gosrc io.Writer) error {
	parser := parser.NewParser()
	file, err := parser.Parse(phpFilename, phpStr)
	if err != nil {
		return fmt.Errorf("found errors while parsing %s: %s", phpFilename, err)
	}

	tg := Togo{currentScope: parser.FileSet.Scope}

	nodes := []goast.Node{}
	for _, node := range tg.beginScope(tg.currentScope) {
		nodes = append(nodes, node)
	}
	for _, phpNode := range file.Nodes {
		nodes = append(nodes, tg.ToGoStmt(phpNode.(phpast.Statement)))
	}

	buf := &bytes.Buffer{}

	if err = format.Node(buf, token.NewFileSet(), File(phpFilename[:len(phpFilename)-4], nodes...)); err != nil {
		return fmt.Errorf("error while formatting %s: %s", phpFilename, err)
	}

	imported, err := imports.Process(goFilename, buf.Bytes(), &imports.Options{AllErrors: true, Comments: true, TabIndent: true, TabWidth: 8})
	if err != nil {
		return fmt.Errorf("error while getting imports for %s: %s", phpFilename, err)
	}

	_, err = gosrc.Write(imported)
	return err
}
Пример #12
0
func print(t *testing.T, name string, f *ast.File) string {
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		t.Fatalf("%s gofmt: %v", name, err)
	}
	return string(buf.Bytes())
}
Пример #13
0
// FormatCode runs "goimports -w" on the source file.
func (f *SourceFile) FormatCode() error {
	if NoFormat {
		return nil
	}
	// Parse file into AST
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, f.Abs(), nil, parser.ParseComments)
	if err != nil {
		return err
	}
	// Clean unused imports
	imports := astutil.Imports(fset, file)
	for _, group := range imports {
		for _, imp := range group {
			path := strings.Trim(imp.Path.Value, `"`)
			if !astutil.UsesImport(file, path) {
				astutil.DeleteImport(fset, file, path)
			}
		}
	}
	ast.SortImports(fset, file)
	// Open file to be written
	w, err := os.OpenFile(f.Abs(), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
	if err != nil {
		return err
	}
	defer w.Close()
	// Write formatted code without unused imports
	return format.Node(w, fset, file)
}
Пример #14
0
// Rewrite modifies the AST to rewrite import statements and package import comments.
// src should be compatible with go/parser/#ParseFile:
// (The type of the argument for the src parameter must be string, []byte, or io.Reader.)
//
// return of nil, nil (no result, no error) means no changes are needed
func Rewrite(fname string, src interface{}, prefix string, remove bool) (buf *bytes.Buffer, err error) {
	// Create the AST by parsing src.
	fset := token.NewFileSet() // positions are relative to fset
	f, err := parser.ParseFile(fset, fname, src, parser.ParseComments)
	if err != nil {
		log.Printf("Error parsing file %s, source: [%s], error: %s", fname, src, err)
		return nil, err
	}
	// normalize the prefix ending with a trailing slash
	if prefix[len(prefix)-1] != '/' {
		prefix += "/"
	}

	changed, err := RewriteImports(f, prefix, remove)
	if err != nil {
		log.Printf("Error rewriting imports in the AST: file %s - %s", fname, err)
		return nil, err
	}
	changed2, err := RewriteImportComments(f, fset, prefix, remove)
	if err != nil {
		log.Printf("Error rewriting import comments in the AST: file %s - %s", fname, err)
		return nil, err
	}
	if !changed && !changed2 {
		return nil, nil
	}
	buf = &bytes.Buffer{}
	err = format.Node(buf, fset, f)
	return buf, err
}
Пример #15
0
func (p *Presentation) example_htmlFunc(info *PageInfo, funcName string) string {
	var buf bytes.Buffer
	for _, eg := range info.Examples {
		name := stripExampleSuffix(eg.Name)

		if name != funcName {
			continue
		}

		// print code
		cnode := &printer.CommentedNode{Node: eg.Code, Comments: eg.Comments}
		code := p.node_htmlFunc(info, cnode, true)
		out := eg.Output
		wholeFile := true

		// Additional formatting if this is a function body.
		if n := len(code); n >= 2 && code[0] == '{' && code[n-1] == '}' {
			wholeFile = false
			// remove surrounding braces
			code = code[1 : n-1]
			// unindent
			code = strings.Replace(code, "\n    ", "\n", -1)
			// remove output comment
			if loc := exampleOutputRx.FindStringIndex(code); loc != nil {
				code = strings.TrimSpace(code[:loc[0]])
			}
		}

		// Write out the playground code in standard Go style
		// (use tabs, no comment highlight, etc).
		play := ""
		if eg.Play != nil && p.ShowPlayground {
			var buf bytes.Buffer
			if err := format.Node(&buf, info.FSet, eg.Play); err != nil {
				log.Print(err)
			} else {
				play = buf.String()
			}
		}

		// Drop output, as the output comment will appear in the code.
		if wholeFile && play == "" {
			out = ""
		}

		if p.ExampleHTML == nil {
			out = ""
			return ""
		}

		err := p.ExampleHTML.Execute(&buf, struct {
			Name, Doc, Code, Play, Output string
			Share                         bool
		}{eg.Name, eg.Doc, code, play, out, info.Share})
		if err != nil {
			log.Print(err)
		}
	}
	return buf.String()
}
Пример #16
0
func TestFilterDuplicates(t *testing.T) {
	// parse input
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "", input, 0)
	if err != nil {
		t.Fatal(err)
	}

	// create package
	files := map[string]*ast.File{"": file}
	pkg, err := ast.NewPackage(fset, files, nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	// filter
	merged := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates)

	// pretty-print
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, merged); err != nil {
		t.Fatal(err)
	}
	output := buf.String()

	if output != golden {
		t.Errorf("incorrect output:\n%s", output)
	}
}
Пример #17
0
// Parse the arguments string Template(A, B, C)
func parseTemplateAndArgs(s string) (name string, args []string) {
	expr, err := parser.ParseExpr(s)
	if err != nil {
		fatalf("Failed to parse %q: %v", s, err)
	}
	debugf("expr = %#v\n", expr)
	callExpr, ok := expr.(*ast.CallExpr)
	if !ok {
		fatalf("Failed to parse %q: expecting Identifier(...)", s)
	}
	debugf("fun = %#v", callExpr.Fun)
	fn, ok := callExpr.Fun.(*ast.Ident)
	if !ok {
		fatalf("Failed to parse %q: expecting Identifier(...)", s)
	}
	name = fn.Name
	for i, arg := range callExpr.Args {
		var buf bytes.Buffer
		debugf("arg[%d] = %#v", i, arg)
		format.Node(&buf, token.NewFileSet(), arg)
		s := buf.String()
		debugf("parsed = %q", s)
		args = append(args, s)
	}
	return
}
Пример #18
0
func gofmtFile(f *ast.File) ([]byte, error) {
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #19
0
func rewriteFile(fset *token.FileSet, f *ast.File, filename string) error {
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		return fmt.Errorf("failed to pretty-print syntax tree: %v", err)
	}
	return ioutil.WriteFile(filename, buf.Bytes(), 0644)
}
Пример #20
0
func annotate(file string) {
	fset = token.NewFileSet()
	f, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}

	for _, imp := range f.Imports {
		if imp.Name != nil && imp.Name.Name == importName {
			log.Printf(`"%s" already imported. skipping %s`, importName, file)
			return
		}
		if imp.Path.Value == importPath {
			log.Printf(`"%s", already imported. skipping %s`, importPath, file)
			return
		}
	}

	edits := editList{packageName: f.Name.Name}

	// insert our import directly after the package line
	edits.Add(int(f.Name.End()), []byte(importStmt))

	ast.Inspect(f, edits.inspect)

	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		log.Fatal("format.Node", err)
	}

	data := buf.Bytes()

	var pos int
	var out []byte
	for _, e := range edits.edits {
		out = append(out, data[pos:e.pos]...)
		out = append(out, []byte(e.val)...)
		pos = e.pos
	}
	out = append(out, data[pos:]...)

	// it's easier to append the setup code at the end
	out = append(out, []byte(setup)...)

	src, err := format.Source(out)
	if err != nil {
		log.Fatal("format.Source ", err)
	}

	if !writeFiles {
		fmt.Println(string(src))
		return
	}

	err = ioutil.WriteFile(file, src, 0)
	if err != nil {
		log.Fatal(err)
	}
}
Пример #21
0
// gofmt takes the given, valid, Go AST and returns a
// canonically-formatted go program in a byte-array, or an error.
func gofmt(f *ast.File) ([]byte, error) {
	fset := token.NewFileSet()
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		return nil, err
	}
	return buf.Bytes(), nil
}
Пример #22
0
func CreateSourceCode(astFile *ast.File) ([]byte, error) {
	sourceCode := &bytes.Buffer{}
	err := format.Node(sourceCode, token.NewFileSet(), astFile)
	if err != nil {
		return nil, err
	}
	return sourceCode.Bytes(), nil
}
Пример #23
0
// rewrite reads, modifies, and writes filename, replacing all imports
// of packages P in noncanonical by noncanonical[P].
// It records in used which noncanonical packages were imported.
// used[P]=="" indicates that P was imported but its canonical path is unknown.
func rewriteFile(filename string, noncanonical map[string]*build.Package, used map[string]bool) error {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
	if err != nil {
		return err
	}
	var changed bool
	for _, imp := range f.Imports {
		impPath, err := strconv.Unquote(imp.Path.Value)
		if err != nil {
			log.Printf("%s: bad import spec %q: %v",
				fset.Position(imp.Pos()), imp.Path.Value, err)
			continue
		}
		p, ok := noncanonical[impPath]
		if !ok {
			continue // import path is canonical
		}

		used[impPath] = true

		if p == nil {
			// The canonical path is unknown.
			// Show the offending import.
			// TODO(adonovan): should we show the actual source text?
			fmt.Fprintf(stderr, "\t%s:%d: import %q\n",
				shortPath(filename),
				fset.Position(imp.Pos()).Line, impPath)
			continue
		}

		changed = true

		imp.Path.Value = strconv.Quote(p.ImportComment)

		// Add a renaming import if necessary.
		//
		// This is a guess at best.  We can't see whether a 'go
		// get' of the canonical import path would have the same
		// name or not.  Assume it's the last segment.
		//
		// TODO(adonovan): should we make an HTTP request?
		newBase := path.Base(p.ImportComment)
		if imp.Name == nil && newBase != p.Name {
			imp.Name = &ast.Ident{Name: p.Name}
		}
	}

	if changed && !*dryrun {
		var buf bytes.Buffer
		if err := format.Node(&buf, fset, f); err != nil {
			return fmt.Errorf("%s: couldn't format file: %v", filename, err)
		}
		return writeFile(filename, buf.Bytes(), 0644)
	}

	return nil
}
Пример #24
0
// This example illustrates how to remove a variable declaration
// in a Go program while maintaining correct comment association
// using an ast.CommentMap.
func ExampleCommentMap() {
	// src is the input for which we create the AST that we
	// are going to manipulate.
	src := `
// This is the package comment.
package main

// This comment is associated with the hello constant.
const hello = "Hello, World!" // line comment 1

// This comment is associated with the foo variable.
var foo = hello // line comment 2 

// This comment is associated with the main function.
func main() {
	fmt.Println(hello) // line comment 3
}
`

	// Create the AST by parsing src.
	fset := token.NewFileSet() // positions are relative to fset
	f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments)
	if err != nil {
		panic(err)
	}

	// Create an ast.CommentMap from the ast.File's comments.
	// This helps keeping the association between comments
	// and AST nodes.
	cmap := ast.NewCommentMap(fset, f, f.Comments)

	// Remove the first variable declaration from the list of declarations.
	f.Decls = removeFirstVarDecl(f.Decls)

	// Use the comment map to filter comments that don't belong anymore
	// (the comments associated with the variable declaration), and create
	// the new comments list.
	f.Comments = cmap.Filter(f).Comments()

	// Print the modified AST.
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, f); err != nil {
		panic(err)
	}
	fmt.Printf("%s", buf.Bytes())

	// output:
	// // This is the package comment.
	// package main
	//
	// // This comment is associated with the hello constant.
	// const hello = "Hello, World!" // line comment 1
	//
	// // This comment is associated with the main function.
	// func main() {
	// 	fmt.Println(hello) // line comment 3
	// }
}
Пример #25
0
// Format source from reader to writer
func Format(fname string, r io.Reader, w io.Writer) error {
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, fname, r, parser.ParseComments)
	if err != nil {
		return err
	}

	return format.Node(w, fset, f)
}
Пример #26
0
func (b *BlockStmt) Format() string {
	var buf bytes.Buffer
	fset := token.NewFileSet()
	for i := range b.Children {
		format.Node(&buf, fset, b.Node[i])
		fmt.Fprintln(&buf)
	}
	return buf.String()
}
Пример #27
0
func (gen CodeGenerator) GenerateFake() (string, error) {
	buf := new(bytes.Buffer)
	err := format.Node(buf, token.NewFileSet(), gen.sourceFile())
	if err != nil {
		return "", err
	}

	code, err := imports.Process("", buf.Bytes(), nil)
	return commentLine() + prettifyCode(string(code)), err
}
Пример #28
0
func Format(n ast.Node) string {
	var buf bytes.Buffer
	fset := token.NewFileSet()
	format.Node(&buf, fset, n)
	str := buf.String()
	if strings.HasSuffix(str, "\n") {
		str = str[:len(str)-1]
	}
	return str
}
Пример #29
0
Файл: main.go Проект: w1ng/tools
func main() {
	if len(os.Args) <= 1 {
		return
	}
	resp, err := http.Get(raw)
	if err != nil {
		log.Fatal(err)
	}
	// parser
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, "", resp.Body, 0)
	if err != nil {
		log.Fatal(err)
	}

	// remove Init()
LOOP:
	for k := range f.Decls {
		switch f.Decls[k].(type) {
		case *ast.FuncDecl:
			decl := f.Decls[k].(*ast.FuncDecl)
			if decl.Name.Name == "Init" {
				f.Decls = append(f.Decls[:k], f.Decls[k+1:]...)
				break LOOP
			}
		}
	}

	// create file
	out, err := os.Create("services.go")
	if err != nil {
		log.Fatal(err)
	}

	// rewrite
	format.Node(out, fset, f)

	//add stub
	funcMap := template.FuncMap{
		"Name": func(s string) string {
			a := []rune(s)
			a[0] = unicode.ToUpper(a[0])
			return string(a)
		},
	}
	tmpl, err := template.New("proto.tmpl").Funcs(funcMap).Parse(t)
	if err != nil {
		log.Fatal(err)
	}
	err = tmpl.Execute(out, os.Args[1:])
	if err != nil {
		log.Fatal(err)
	}
}
Пример #30
0
func source(expect func(interface{}) *expect.Expect, pkg string, decls []ast.Decl, scope *ast.Scope) string {
	buf := bytes.Buffer{}
	f := &ast.File{
		Name:  &ast.Ident{Name: pkg},
		Decls: decls,
		Scope: scope,
	}
	err := format.Node(&buf, token.NewFileSet(), f)
	expect(err).To.Be.Nil()
	return buf.String()
}