Exemplo n.º 1
0
func sortImports2(fset *token.FileSet, f *ast.File) (fset2 *token.FileSet, f2 *ast.File) {
	sortImports(fset, f)
	imps := astutil.Imports(fset, f)

	var spacesBefore []string // import paths we need spaces before
	for _, impSection := range imps {
		// Within each block of contiguous imports, see if any
		// import lines are in different group numbers. If so,
		// we'll need to put a space between them so it's
		// compatible with gofmt.
		lastGroup := -1
		for _, importSpec := range impSection {
			importPath, _ := strconv.Unquote(importSpec.Path.Value)
			groupNum := importGroup(importPath)
			if groupNum != lastGroup && lastGroup != -1 {
				spacesBefore = append(spacesBefore, importPath)
			}
			lastGroup = groupNum
		}
	}

	// So gross. Print out the entire AST, add a space by modifying the bytes, and reparse the whole thing.
	// Because I don't see an API that'd let me modify (insert a newline) the FileSet directly.
	// We really need a go/ast v2, which is as friendly to parsing/printing/formatting as current, but
	// also friendly towards direct AST modification... To avoid all these horrible hacks.
	out := []byte(gist5639599.SprintAst(fset, f))
	if len(spacesBefore) > 0 {
		out = addImportSpaces(bytes.NewReader(out), spacesBefore)
	}

	fset2 = token.NewFileSet()
	var err error
	f2, err = parser.ParseFile(fset2, "", out, parser.ParseComments)
	if err != nil {
		panic(err)
	}
	return
}
Exemplo n.º 2
0
// WriteMergedPackage writes a merged package, typically coming from ast.MergePackageFiles, to w.
// It sorts and de-duplicates imports.
//
// TODO: Support comments.
func WriteMergedPackage(w io.Writer, fset *token.FileSet, merged *ast.File) {
	switch 3 {
	case 1:
		fmt.Fprintln(w, "package "+gist5639599.SprintAst(fset, merged.Name))
		fmt.Fprintln(w)
		fmt.Fprintln(w, `import (`)
		// TODO: SortImports (ala goimports).
		for _, importSpec := range merged.Imports {
			if importSpec.Name != nil && importSpec.Name.Name == "." {
				continue
			}
			fmt.Fprintln(w, "\t"+gist5639599.SprintAst(fset, importSpec))
		}
		fmt.Fprintln(w, `)`)
		fmt.Fprintln(w)

		for _, decl := range merged.Decls {
			if x, ok := decl.(*ast.GenDecl); ok && x.Tok == token.IMPORT {
				continue
			}

			fmt.Fprintln(w, gist5639599.SprintAst(fset, decl))
			fmt.Fprintln(w)
		}
	case 2:
		sortDecls(merged)

		//fmt.Fprintln(w, gist5639599.SprintAst(token.NewFileSet(), merged))

		//ast.SortImports(fset, merged)
		sortImports2(fset, merged)

		fmt.Fprintln(w, gist5639599.SprintAst(fset, merged))
	case 3:
		sortDecls(merged)

		// TODO: Clean up this mess...
		fset2, f2 := sortImports2(token.NewFileSet(), merged)

		fmt.Fprintln(w, "package "+gist5639599.SprintAst(fset, merged.Name))
		for _, decl := range f2.Decls {
			if x, ok := decl.(*ast.GenDecl); ok && x.Tok == token.IMPORT {
				fmt.Fprintln(w)
				fmt.Fprintln(w, gist5639599.SprintAst(fset2, decl))
			}
		}
		for _, decl := range merged.Decls {
			if x, ok := decl.(*ast.GenDecl); ok && (x.Tok == token.IMPORT || x.Tok == token.PACKAGE) {
				continue
			}

			fmt.Fprintln(w)
			fmt.Fprintln(w, gist5639599.SprintAst(fset, decl))
		}
	case 4:
		sortDecls(merged)

		src := []byte(gist5639599.SprintAst(fset, merged))

		out, err := imports.Process("", src, nil)
		if err != nil {
			panic(err)
		}
		os.Stdout.Write(out)
		fmt.Println()
	}
}