github.com/daixiang0/gci@v0.13.0/pkg/analyzer/analyzer.go (about) 1 package analyzer 2 3 import ( 4 "fmt" 5 "go/token" 6 "strings" 7 8 "golang.org/x/tools/go/analysis" 9 10 "github.com/daixiang0/gci/pkg/config" 11 "github.com/daixiang0/gci/pkg/gci" 12 "github.com/daixiang0/gci/pkg/io" 13 "github.com/daixiang0/gci/pkg/log" 14 ) 15 16 const ( 17 NoInlineCommentsFlag = "noInlineComments" 18 NoPrefixCommentsFlag = "noPrefixComments" 19 SkipGeneratedFlag = "skipGenerated" 20 SectionsFlag = "Sections" 21 SectionSeparatorsFlag = "SectionSeparators" 22 SectionDelimiter = "," 23 ) 24 25 var ( 26 noInlineComments bool 27 noPrefixComments bool 28 skipGenerated bool 29 sectionsStr string 30 sectionSeparatorsStr string 31 ) 32 33 func init() { 34 Analyzer.Flags.BoolVar(&noInlineComments, NoInlineCommentsFlag, false, "If comments in the same line as the input should be present") 35 Analyzer.Flags.BoolVar(&noPrefixComments, NoPrefixCommentsFlag, false, "If comments above an input should be present") 36 Analyzer.Flags.BoolVar(&skipGenerated, SkipGeneratedFlag, false, "Skip generated files") 37 Analyzer.Flags.StringVar(§ionsStr, SectionsFlag, "", "Specify the Sections format that should be used to check the file formatting") 38 Analyzer.Flags.StringVar(§ionSeparatorsStr, SectionSeparatorsFlag, "", "Specify the Sections that are inserted as Separators between Sections") 39 40 log.InitLogger() 41 defer log.L().Sync() 42 } 43 44 var Analyzer = &analysis.Analyzer{ 45 Name: "gci", 46 Doc: "A tool that control Go package import order and make it always deterministic.", 47 Run: runAnalysis, 48 } 49 50 func runAnalysis(pass *analysis.Pass) (interface{}, error) { 51 var fileReferences []*token.File 52 // extract file references for all files in the analyzer pass 53 for _, pkgFile := range pass.Files { 54 fileForPos := pass.Fset.File(pkgFile.Package) 55 if fileForPos != nil { 56 fileReferences = append(fileReferences, fileForPos) 57 } 58 } 59 expectedNumFiles := len(pass.Files) 60 foundNumFiles := len(fileReferences) 61 if expectedNumFiles != foundNumFiles { 62 return nil, InvalidNumberOfFilesInAnalysis{expectedNumFiles, foundNumFiles} 63 } 64 65 // read configuration options 66 gciCfg, err := parseGciConfiguration() 67 if err != nil { 68 return nil, err 69 } 70 71 for _, file := range fileReferences { 72 filePath := file.Name() 73 unmodifiedFile, formattedFile, err := gci.LoadFormatGoFile(io.File{FilePath: filePath}, *gciCfg) 74 if err != nil { 75 return nil, err 76 } 77 fix, err := GetSuggestedFix(file, unmodifiedFile, formattedFile) 78 if err != nil { 79 return nil, err 80 } 81 if fix == nil { 82 // no difference 83 continue 84 } 85 pass.Report(analysis.Diagnostic{ 86 Pos: fix.TextEdits[0].Pos, 87 Message: fmt.Sprintf("fix by `%s %s`", generateCmdLine(*gciCfg), filePath), 88 SuggestedFixes: []analysis.SuggestedFix{*fix}, 89 }) 90 } 91 return nil, nil 92 } 93 94 func parseGciConfiguration() (*config.Config, error) { 95 fmtCfg := config.BoolConfig{ 96 NoInlineComments: noInlineComments, 97 NoPrefixComments: noPrefixComments, 98 Debug: false, 99 SkipGenerated: skipGenerated, 100 } 101 102 var sectionStrings []string 103 if sectionsStr != "" { 104 sectionStrings = strings.Split(sectionsStr, SectionDelimiter) 105 } 106 107 var sectionSeparatorStrings []string 108 if sectionSeparatorsStr != "" { 109 sectionSeparatorStrings = strings.Split(sectionSeparatorsStr, SectionDelimiter) 110 fmt.Println(sectionSeparatorsStr) 111 } 112 return config.YamlConfig{Cfg: fmtCfg, SectionStrings: sectionStrings, SectionSeparatorStrings: sectionSeparatorStrings}.Parse() 113 } 114 115 func generateCmdLine(cfg config.Config) string { 116 result := "gci write" 117 118 if cfg.BoolConfig.NoInlineComments { 119 result += " --NoInlineComments " 120 } 121 122 if cfg.BoolConfig.NoPrefixComments { 123 result += " --NoPrefixComments " 124 } 125 126 if cfg.BoolConfig.SkipGenerated { 127 result += " --skip-generated " 128 } 129 130 if cfg.BoolConfig.CustomOrder { 131 result += " --custom-order " 132 } 133 134 for _, s := range cfg.Sections.String() { 135 result += fmt.Sprintf(" --Section \"%s\" ", s) 136 } 137 for _, s := range cfg.SectionSeparators.String() { 138 result += fmt.Sprintf(" --SectionSeparator %s ", s) 139 } 140 return result 141 }