func fixImportCheck(body []byte, importPath string) ([]byte, error) { fset := token.NewFileSet() // todo: see if we can restrict the mode some more f, err := parser.ParseFile(fset, "", body, parser.ParseComments) if err != nil { log.Fatal(err) } var after *ast.CommentGroup var pos token.Pos = token.Pos(len(body)) for _, v := range f.Comments { text := strings.TrimSpace(v.Text()) if v.Pos() > f.Package && v.Pos() < pos && strings.HasPrefix(text, "import") { pos = v.Pos() after = v } } if after != nil && bytes.IndexByte(body[f.Package:pos], '\n') == -1 { comment := fmt.Sprintf(`// import "%s"`, importPath) buf := new(bytes.Buffer) buf.Write(body[:after.Pos()-1]) buf.WriteString(comment) buf.Write(body[after.End()-1:]) body = buf.Bytes() } return body, nil }
// lintPackageComment checks package comments. It complains if // there is no package comment, or if it is not of the right form. // This has a notable false positive in that a package comment // could rightfully appear in a different file of the same package, // but that's not easy to fix since this linter is file-oriented. func (f *file) lintPackageComment() { if f.isTest() { return } const ref = styleGuideBase + "#package-comments" prefix := "Package " + f.f.Name.Name + " " // Look for a detached package comment. // First, scan for the last comment that occurs before the "package" keyword. var lastCG *ast.CommentGroup for _, cg := range f.f.Comments { if cg.Pos() > f.f.Package { // Gone past "package" keyword. break } lastCG = cg } if lastCG != nil && strings.HasPrefix(lastCG.Text(), prefix) { endPos := f.fset.Position(lastCG.End()) pkgPos := f.fset.Position(f.f.Package) if endPos.Line+1 < pkgPos.Line { // There isn't a great place to anchor this error; // the start of the blank lines between the doc and the package statement // is at least pointing at the location of the problem. pos := token.Position{ Filename: endPos.Filename, // Offset not set; it is non-trivial, and doesn't appear to be needed. Line: endPos.Line + 1, Column: 1, } f.pkg.errorfAt(pos, 0.9, link(ref), category("comments"), "package comment is detached; there should be no blank lines between it and the package statement") return } } if f.f.Doc == nil { f.errorf(f.f, 0.2, link(ref), category("comments"), "should have a package comment, unless it's in another file for this package") return } s := f.f.Doc.Text() if ts := strings.TrimLeft(s, " \t"); ts != s { f.errorf(f.f.Doc, 1, link(ref), category("comments"), "package comment should not have leading space") s = ts } // Only non-main packages need to keep to this form. if f.f.Name.Name != "main" && !strings.HasPrefix(s, prefix) { f.errorf(f.f.Doc, 1, link(ref), category("comments"), `package comment should be of the form "%s..."`, prefix) } }