func ExecuteAsCommand(o *common.Opt) (err error) { term = os.Getenv("TERM") _, err = Execute(o) if err != nil { if !o.Quiet { fmt.Println(err) } return } if !o.Quiet { for i := range violations { if !violations[i].Fixed { printViolation(violations[i]) } } } vcnt := 0 for i := range violations { if !violations[i].Fixed { vcnt++ } } if 0 < vcnt { if !o.Quiet { fmt.Printf("\n%d %s generated.\n", vcnt, pluralize(vcnt, "warning", "warnings")) } err = common.NewError("error while executing lint") } return }
func Execute(o *common.Opt) (v []common.Violation, err error) { // Clear global vars violations = []common.Violation{} common.BufSize = 0 if o.SrcRoot == "" { err = common.NewError("source directory is required.") return } if o.Id == "" { err = common.NewError("ID of the rule set is required.") return } opt = o err = MkReportDir(false) if err != nil { return } if opt.ConfigPath == "" { err = common.NewError("config directory is required.") return } err = LoadConfig() if err != nil { return } printReportHeader() err = Lint(opt.SrcRoot) finishReportFiles() return violations, err }
func MkReportDir(whenNotExist bool) (err error) { if opt.Html == "" { return } if !whenNotExist { if opt.Force { os.RemoveAll(opt.Html) } else { err = common.NewError("report directory already exists. use `-f` option to force reporting.") return } } err = os.MkdirAll(opt.Html, 0777) return }
func LoadConfig() (err error) { // Get config directory(.fint) pathConfig := opt.ConfigPath if err = dirExists(pathConfig); err != nil { return } // Get target ID directory pathTarget := filepath.Join(pathConfig, common.DirBuiltin, common.DirTargets, opt.Id) if err = dirExists(pathTarget); err != nil { return common.NewError("no matching target to [" + opt.Id + "]") } // Get modules directory pathModules := filepath.Join(pathConfig, common.DirBuiltin, common.DirModules) if err = dirExists(pathModules); err != nil { return common.NewError("modules directory not found in [" + pathModules + "]") } // Load .fint/builtin/modules/*/config.json config = new(common.Config) filesModules, _ := ioutil.ReadDir(pathModules) for i := range filesModules { entry := filesModules[i] if entry.IsDir() { // entry name is the name of module entryPath := filepath.Join(pathModules, entry.Name()) var configBytes []byte configBytes, err = ioutil.ReadFile(filepath.Join(entryPath, common.FileConfig)) if err != nil { return } var c common.ModuleConfig json.Unmarshal(configBytes, &c) // Set name as Id to be searchable c.Id = entry.Name() config.ModuleConfigs = append(config.ModuleConfigs, c) } } // Load target ruleset var configBytes []byte configBytes, err = ioutil.ReadFile(filepath.Join(pathTarget, common.FileRuleSet)) if err != nil { return common.NewError("no matching target to [" + opt.Id + "]") } var target common.Target json.Unmarshal(configBytes, &target) config.Targets = append(config.Targets, target) // Load target locales filesTargetLocales, _ := ioutil.ReadDir(filepath.Join(pathTarget, common.DirLocales)) for i := range filesTargetLocales { entry := filesTargetLocales[i] locale := strings.TrimSuffix(entry.Name(), filepath.Ext(entry.Name())) // Get contents of en.json, ja.json, ... var configBytes []byte configBytes, _ = ioutil.ReadFile(filepath.Join(pathTarget, common.DirLocales, entry.Name())) var lt common.LocalizedTarget json.Unmarshal(configBytes, <) for i := range target.RuleSets { for j := range target.RuleSets[i].Modules { for k := range target.RuleSets[i].Modules[j].Rules { // Pass all localized messages for each rules if target.RuleSets[i].Modules[j].Rules[k].Message == nil { target.RuleSets[i].Modules[j].Rules[k].Message = make(map[string]string) } target.RuleSets[i].Modules[j].Rules[k].Message[locale] = lt.RuleSets[i].Modules[j].Rules[k].Message } } } } return }
func LintFile(srcRoot string, m common.Module, locale string, fix bool, lintWalkFunc LintWalkFunc) (fmap map[string]map[int][]common.Violation, err error) { filename := srcRoot if matched, _ := regexp.MatchString(m.Pattern, filename); !matched { return } if fmap == nil { fmap = make(map[string]map[int][]common.Violation) } var f *os.File f, err = os.Open(filename) if err != nil { err = common.NewError("cannot open " + filename) return } defer f.Close() var ftmp *os.File if fix { // Prepare fixed file ftmp, _ = os.OpenFile(filename+".tmp", os.O_RDWR|os.O_CREATE, 0666) defer ftmp.Close() } if common.BufSize == 0 { common.BufSize = common.DefaultBufSize } r := bufio.NewReaderSize(f, common.BufSize) vmap := make(map[int][]common.Violation) for n := 1; true; n++ { var line string line, err = r.ReadString(common.LinefeedRune) if err != io.EOF && err != nil { return } var lvs []common.Violation vsr, fixedAny, fixedLine := lintWalkFunc(m, n, filename, strings.TrimSuffix(line, common.Linefeed), locale, fix) tmpLine := line if vsr != nil { lvs = append(lvs, vsr...) if fixedAny { if strings.HasSuffix(line, common.Linefeed) { tmpLine = fixedLine + common.Linefeed } else { tmpLine = fixedLine } } } if fix { ftmp.WriteString(tmpLine) } vmap[n] = lvs if err == io.EOF { err = nil break } } if fix { ftmp.Close() os.Remove(filename) CopyFile(filename+".tmp", filename) os.Remove(filename + ".tmp") } if fmap[filename] == nil { fmap[filename] = make(map[int][]common.Violation) } fmap[filename] = vmap return }