From 1a9af12d6d2ebc34d06a533e7c1035243b4d0c1a Mon Sep 17 00:00:00 2001 From: Denis Isaev Date: Thu, 28 Jun 2018 22:39:23 +0300 Subject: [PATCH] Fix #96: support lll --- .golangci.example.yml | 3 + README.md | 6 ++ pkg/commands/executor.go | 2 +- pkg/commands/run.go | 41 +++++++---- pkg/config/config.go | 31 ++++++-- pkg/golinters/errcheck.go | 3 +- pkg/golinters/gofmt.go | 3 +- pkg/golinters/govet.go | 3 +- pkg/golinters/lll.go | 72 +++++++++++++++++++ pkg/lint/lintersdb/lintersdb.go | 13 +++- pkg/lint/load.go | 12 +++- pkg/lint/runner.go | 8 ++- pkg/printers/text.go | 22 +++--- .../processors/autogenerated_exclude.go | 6 +- .../processors/autogenerated_exclude_test.go | 3 +- test/testdata/lll.go | 6 ++ third_party/lll/LICENSE | 19 +++++ 17 files changed, 207 insertions(+), 46 deletions(-) create mode 100644 pkg/golinters/lll.go create mode 100644 test/testdata/lll.go create mode 100644 third_party/lll/LICENSE diff --git a/.golangci.example.yml b/.golangci.example.yml index 64b121d8..8020fab4 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -104,6 +104,9 @@ linters-settings: # Default is to use a neutral variety of English. # Setting locale to US will correct the British spelling of 'colour' to 'color'. locale: US + lll: + # max line length, lines longer will be reported. Default is 120. '\t' is counted as 1 character. + line-length: 120 linters: enable: diff --git a/README.md b/README.md index d90a4d1b..4eff6742 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ maligned: Tool to detect Go structs that would take less memory if their fields megacheck: 3 sub-linters in one: unused, gosimple and staticcheck [fast: false] depguard: Go linter that checks if package imports are in a list of acceptable packages [fast: false] misspell: Finds commonly misspelled English words in comments [fast: true] +lll: Reports long lines [fast: true] ``` Pass `-E/--enable` to enable linter and `-D/--disable` to disable: @@ -220,6 +221,7 @@ golangci-lint linters - [megacheck](https://github.com/dominikh/go-tools/tree/master/cmd/megacheck) - 3 sub-linters in one: unused, gosimple and staticcheck - [depguard](https://github.com/OpenPeeDeeP/depguard) - Go linter that checks if package imports are in a list of acceptable packages - [misspell](https://github.com/client9/misspell) - Finds commonly misspelled English words in comments +- [lll](https://github.com/walle/lll) - Reports long lines # Configuration The config file has lower priority than command-line options. If the same bool/string/int option is provided on the command-line @@ -422,6 +424,9 @@ linters-settings: # Default is to use a neutral variety of English. # Setting locale to US will correct the British spelling of 'colour' to 'color'. locale: US + lll: + # max line length, lines longer will be reported. Default is 120. '\t' is counted as 1 character. + line-length: 120 linters: enable: @@ -601,6 +606,7 @@ Thanks to developers and authors of used linters: - [alecthomas](https://github.com/alecthomas) - [OpenPeeDeeP](https://github.com/OpenPeeDeeP) - [client9](https://github.com/client9) +- [walle](https://github.com/walle) # Future Plans 1. Upstream all changes of forked linters. diff --git a/pkg/commands/executor.go b/pkg/commands/executor.go index eb274341..a424336d 100644 --- a/pkg/commands/executor.go +++ b/pkg/commands/executor.go @@ -23,7 +23,7 @@ type Executor struct { func NewExecutor(version, commit, date string) *Executor { e := &Executor{ - cfg: &config.Config{}, + cfg: config.NewDefault(), version: version, commit: commit, date: date, diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 8fc665e5..073e75a6 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -32,7 +32,8 @@ func getDefaultExcludeHelp() string { return strings.Join(parts, "\n") } -const welcomeMessage = "Run this tool in cloud on every github pull request in https://golangci.com for free (public repos)" +const welcomeMessage = "Run this tool in cloud on every github pull " + + "request in https://golangci.com for free (public repos)" func wh(text string) string { return color.GreenString(text) @@ -62,7 +63,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) { fs.StringSliceVar(&rc.BuildTags, "build-tags", nil, wh("Build tags")) fs.DurationVar(&rc.Deadline, "deadline", time.Minute, wh("Deadline for total work")) fs.BoolVar(&rc.AnalyzeTests, "tests", true, wh("Analyze tests (*_test.go)")) - fs.BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, wh("Print avg and max memory usage of golangci-lint and total time")) + fs.BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, + wh("Print avg and max memory usage of golangci-lint and total time")) fs.StringVarP(&rc.Config, "config", "c", "", wh("Read config from file path `PATH`")) fs.BoolVar(&rc.NoConfig, "no-config", false, wh("Don't read config")) fs.StringSliceVar(&rc.SkipDirs, "skip-dirs", nil, wh("Regexps of directories to skip")) @@ -75,16 +77,20 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) { // but when number of linters started to grow it became ovious that // we can't fill 90% of flags by linters settings: common flags became hard to find. // New linters settings should be done only through config file. - fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results") + fs.BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", + false, "Errcheck: check for ignored type assertion results") hideFlag("errcheck.check-type-assertions") - fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()") + fs.BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, + "Errcheck: check for errors assigned to blank identifier: _ = errFunc()") hideFlag("errcheck.check-blank") - fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, "Govet: check for shadowed variables") + fs.BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, + "Govet: check for shadowed variables") hideFlag("govet.check-shadowing") - fs.Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it") + fs.Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, + "Golint: minimum confidence of a problem to print it") hideFlag("golint.min-confidence") fs.BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code") @@ -94,7 +100,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) { 30, "Minimal complexity of function to report it") hideFlag("gocyclo.min-complexity") - fs.BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, "Maligned: print suggested more optimal struct fields ordering") + fs.BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, + "Maligned: print suggested more optimal struct fields ordering") hideFlag("maligned.suggest-new") fs.IntVar(&lsc.Dupl.Threshold, "dupl.threshold", @@ -124,7 +131,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) { fs.BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters")) fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters")) fs.StringSliceVarP(&lc.Presets, "presets", "p", nil, - wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|")))) + wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see "+ + "them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|")))) fs.BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set")) // Issues config @@ -132,13 +140,20 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config) { fs.StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", nil, wh("Exclude issue by regexp")) fs.BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultExcludeHelp()) - fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, wh("Maximum issues count per one linter. Set to 0 to disable")) - fs.IntVar(&ic.MaxSameIssues, "max-same-issues", 3, wh("Maximum count of issues with the same text. Set to 0 to disable")) + fs.IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, + wh("Maximum issues count per one linter. Set to 0 to disable")) + fs.IntVar(&ic.MaxSameIssues, "max-same-issues", 3, + wh("Maximum count of issues with the same text. Set to 0 to disable")) fs.BoolVarP(&ic.Diff, "new", "n", false, - wh("Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code")) - fs.StringVar(&ic.DiffFromRevision, "new-from-rev", "", wh("Show only new issues created after git revision `REV`")) - fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", wh("Show only new issues created in git patch with file path `PATH`")) + wh("Show only new issues: if there are unstaged changes or untracked files, only those changes "+ + "are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration "+ + "of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at "+ + "the moment of integration: much better don't allow issues in new code")) + fs.StringVar(&ic.DiffFromRevision, "new-from-rev", "", + wh("Show only new issues created after git revision `REV`")) + fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", + wh("Show only new issues created in git patch with file path `PATH`")) } diff --git a/pkg/config/config.go b/pkg/config/config.go index e62e97de..fbf86a8f 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -30,14 +30,16 @@ type ExcludePattern struct { var DefaultExcludePatterns = []ExcludePattern{ { - Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked", - Linter: "errcheck", - Why: "Almost all programs ignore errors on these functions and in most cases it's ok", + Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close" + + "|.*Flush|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked", + Linter: "errcheck", + Why: "Almost all programs ignore errors on these functions and in most cases it's ok", }, { - Pattern: "(comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)", - Linter: "golint", - Why: "Annoying issue about not having a comment. The rare codebase has such comments", + Pattern: "(comment on exported (method|function|type|const)|" + + "should have( a package)? comment|comment should be of the form)", + Linter: "golint", + Why: "Annoying issue about not having a comment. The rare codebase has such comments", }, { Pattern: "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this", @@ -156,6 +158,17 @@ type LintersSettings struct { Misspell struct { Locale string } + Lll LllSettings +} + +type LllSettings struct { + LineLength int `mapstructure:"line-length"` +} + +var defaultLintersSettings = LintersSettings{ + Lll: LllSettings{ + LineLength: 120, + }, } type Linters struct { @@ -196,3 +209,9 @@ type Config struct { //nolint:maligned InternalTest bool // Option is used only for testing golangci-lint code, don't use it } + +func NewDefault() *Config { + return &Config{ + LintersSettings: defaultLintersSettings, + } +} diff --git a/pkg/golinters/errcheck.go b/pkg/golinters/errcheck.go index 5c5bd00e..5e8cde4c 100644 --- a/pkg/golinters/errcheck.go +++ b/pkg/golinters/errcheck.go @@ -16,7 +16,8 @@ func (Errcheck) Name() string { } func (Errcheck) Desc() string { - return "Errcheck is a program for checking for unchecked errors in go programs. These unchecked errors can be critical bugs in some cases" + return "Errcheck is a program for checking for unchecked errors " + + "in go programs. These unchecked errors can be critical bugs in some cases" } func (e Errcheck) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) { diff --git a/pkg/golinters/gofmt.go b/pkg/golinters/gofmt.go index 7051e5f6..58d954bb 100644 --- a/pkg/golinters/gofmt.go +++ b/pkg/golinters/gofmt.go @@ -31,7 +31,8 @@ func (g Gofmt) Desc() string { return "Goimports does everything that gofmt does. Additionally it checks unused imports" } - return "Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification" + return "Gofmt checks whether code was gofmt-ed. By default " + + "this tool runs with -s option to check for code simplification" } func getFirstDeletedAndAddedLineNumberInHunk(h *diff.Hunk) (int, int, error) { diff --git a/pkg/golinters/govet.go b/pkg/golinters/govet.go index a200b1ba..b6ccc031 100644 --- a/pkg/golinters/govet.go +++ b/pkg/golinters/govet.go @@ -25,7 +25,8 @@ func (Govet) Name() string { } func (Govet) Desc() string { - return "Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string" + return "Vet examines Go source code and reports suspicious constructs, " + + "such as Printf calls whose arguments do not align with the format string" } func (g Govet) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) { diff --git a/pkg/golinters/lll.go b/pkg/golinters/lll.go new file mode 100644 index 00000000..c417438c --- /dev/null +++ b/pkg/golinters/lll.go @@ -0,0 +1,72 @@ +package golinters + +import ( + "bufio" + "context" + "fmt" + "go/token" + "os" + "strings" + "unicode/utf8" + + "github.com/golangci/golangci-lint/pkg/lint/linter" + "github.com/golangci/golangci-lint/pkg/result" +) + +type Lll struct{} + +func (Lll) Name() string { + return "lll" +} + +func (Lll) Desc() string { + return "Reports long lines" +} + +func (lint Lll) getIssuesForFile(filename string, maxLineLen int) ([]result.Issue, error) { + var res []result.Issue + + f, err := os.Open(filename) + if err != nil { + return nil, fmt.Errorf("can't open file %s: %s", filename, err) + } + + lineNumber := 1 + scanner := bufio.NewScanner(f) + for scanner.Scan() { + line := scanner.Text() + line = strings.Replace(line, "\t", " ", -1) + lineLen := utf8.RuneCountInString(line) + if lineLen > maxLineLen { + res = append(res, result.Issue{ + Pos: token.Position{ + Filename: filename, + Line: lineNumber, + Column: 1, + }, + Text: fmt.Sprintf("line is %d characters", lineLen), + FromLinter: lint.Name(), + }) + } + lineNumber++ + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("can't scan file %s: %s", filename, err) + } + + return res, nil +} + +func (lint Lll) Run(ctx context.Context, lintCtx *linter.Context) ([]result.Issue, error) { + var res []result.Issue + for _, f := range lintCtx.PkgProgram.Files(lintCtx.Cfg.Run.AnalyzeTests) { + issues, err := lint.getIssuesForFile(f, lintCtx.Settings().Lll.LineLength) + if err != nil { + return nil, err + } + res = append(res, issues...) + } + + return res, nil +} diff --git a/pkg/lint/lintersdb/lintersdb.go b/pkg/lint/lintersdb/lintersdb.go index 00eb8d5d..edee0ddd 100644 --- a/pkg/lint/lintersdb/lintersdb.go +++ b/pkg/lint/lintersdb/lintersdb.go @@ -14,7 +14,8 @@ import ( ) func AllPresets() []string { - return []string{linter.PresetBugs, linter.PresetUnused, linter.PresetFormatting, linter.PresetStyle, linter.PresetComplexity, linter.PresetPerformance} + return []string{linter.PresetBugs, linter.PresetUnused, linter.PresetFormatting, + linter.PresetStyle, linter.PresetComplexity, linter.PresetPerformance} } func allPresetsSet() map[string]bool { @@ -166,6 +167,10 @@ func GetAllSupportedLinterConfigs() []linter.Config { WithPresets(linter.PresetStyle). WithSpeed(7). WithURL("https://github.com/client9/misspell"), + linter.NewConfig(golinters.Lll{}). + WithPresets(linter.PresetStyle). + WithSpeed(10). + WithURL("https://github.com/walle/lll"), } if os.Getenv("GOLANGCI_COM_RUN") == "1" { @@ -175,6 +180,7 @@ func GetAllSupportedLinterConfigs() []linter.Config { golinters.Maligned{}.Name(): true, // rarely usable golinters.TypeCheck{}.Name(): true, // annoying because of different building envs golinters.Misspell{}.Name(): true, // unsure about false-positives number + golinters.Lll{}.Name(): true, // annoying } return enableLinterConfigs(lcs, func(lc *linter.Config) bool { return !disabled[lc.Linter.Name()] @@ -314,7 +320,10 @@ func GetAllLinterConfigsForPreset(p string) []linter.Config { return ret } -func getEnabledLintersSet(lcfg *config.Linters, enabledByDefaultLinters []linter.Config) map[string]*linter.Config { // nolint:gocyclo +// nolint:gocyclo +func getEnabledLintersSet(lcfg *config.Linters, + enabledByDefaultLinters []linter.Config) map[string]*linter.Config { + resultLintersSet := map[string]*linter.Config{} switch { case len(lcfg.Presets) != 0: diff --git a/pkg/lint/load.go b/pkg/lint/load.go index bc899ea7..3133d95a 100644 --- a/pkg/lint/load.go +++ b/pkg/lint/load.go @@ -109,7 +109,9 @@ func isLocalProjectAnalysis(args []string) bool { return true } -func getTypeCheckFuncBodies(cfg *config.Run, linters []linter.Config, pkgProg *packages.Program, log logutils.Log) func(string) bool { +func getTypeCheckFuncBodies(cfg *config.Run, linters []linter.Config, + pkgProg *packages.Program, log logutils.Log) func(string) bool { + if !isLocalProjectAnalysis(cfg.Args) { loadDebugf("analysis in nonlocal, don't optimize loading by not typechecking func bodies") return nil @@ -155,7 +157,9 @@ func getTypeCheckFuncBodies(cfg *config.Run, linters []linter.Config, pkgProg *p } } -func loadWholeAppIfNeeded(ctx context.Context, linters []linter.Config, cfg *config.Config, pkgProg *packages.Program, log logutils.Log) (*loader.Program, *loader.Config, error) { +func loadWholeAppIfNeeded(ctx context.Context, linters []linter.Config, cfg *config.Config, + pkgProg *packages.Program, log logutils.Log) (*loader.Program, *loader.Config, error) { + if !isFullImportNeeded(linters, cfg) { return nil, nil, nil } @@ -255,7 +259,9 @@ func separateNotCompilingPackages(lintCtx *linter.Context) { } //nolint:gocyclo -func LoadContext(ctx context.Context, linters []linter.Config, cfg *config.Config, log logutils.Log) (*linter.Context, error) { +func LoadContext(ctx context.Context, linters []linter.Config, cfg *config.Config, + log logutils.Log) (*linter.Context, error) { + // Set GOROOT to have working cross-compilation: cross-compiled binaries // have invalid GOROOT. XXX: can't use runtime.GOROOT(). goroot, err := goutils.DiscoverGoRoot() diff --git a/pkg/lint/runner.go b/pkg/lint/runner.go index 457fa23e..6ccb70d8 100644 --- a/pkg/lint/runner.go +++ b/pkg/lint/runner.go @@ -66,7 +66,9 @@ type lintRes struct { issues []result.Issue } -func (r Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, lc linter.Config) (ret []result.Issue, err error) { +func (r Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, + lc linter.Config) (ret []result.Issue, err error) { + defer func() { if panicData := recover(); panicData != nil { err = fmt.Errorf("panic occurred: %s", panicData) @@ -88,7 +90,9 @@ func (r Runner) runLinterSafe(ctx context.Context, lintCtx *linter.Context, lc l return issues, nil } -func (r Runner) runWorker(ctx context.Context, lintCtx *linter.Context, tasksCh <-chan linter.Config, lintResultsCh chan<- lintRes, name string) { +func (r Runner) runWorker(ctx context.Context, lintCtx *linter.Context, + tasksCh <-chan linter.Config, lintResultsCh chan<- lintRes, name string) { + sw := timeutils.NewStopwatch(name, r.Log) defer sw.Print() diff --git a/pkg/printers/text.go b/pkg/printers/text.go index 4aea67c0..c2d7e205 100644 --- a/pkg/printers/text.go +++ b/pkg/printers/text.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "io/ioutil" - "strings" "time" "github.com/fatih/color" @@ -140,18 +139,15 @@ func (p Text) printUnderLinePointer(i *result.Issue, line string) { return } - var j int - for ; j < len(line) && line[j] == '\t'; j++ { - } - tabsCount := j - spacesCount := i.Pos.Column - 1 - tabsCount - prefix := "" - if tabsCount != 0 { - prefix += strings.Repeat("\t", tabsCount) - } - if spacesCount != 0 { - prefix += strings.Repeat(" ", spacesCount) + col0 := i.Pos.Column - 1 + prefixRunes := make([]rune, 0, len(line)) + for j := 0; j < len(line) && j < col0; j++ { + if line[j] == '\t' { + prefixRunes = append(prefixRunes, '\t') + } else { + prefixRunes = append(prefixRunes, ' ') + } } - fmt.Fprintf(logutils.StdOut, "%s%s\n", prefix, p.SprintfColored(color.FgYellow, "^")) + fmt.Fprintf(logutils.StdOut, "%s%s\n", string(prefixRunes), p.SprintfColored(color.FgYellow, "^")) } diff --git a/pkg/result/processors/autogenerated_exclude.go b/pkg/result/processors/autogenerated_exclude.go index 3a12b589..6fbbc102 100644 --- a/pkg/result/processors/autogenerated_exclude.go +++ b/pkg/result/processors/autogenerated_exclude.go @@ -103,10 +103,12 @@ func getDoc(f *ast.File, fset *token.FileSet, filePath string) string { var importPos token.Pos if len(f.Imports) != 0 { importPos = f.Imports[0].Pos() - autogenDebugf("file %q: search comments until first import pos %d (%s)", filePath, importPos, fset.Position(importPos)) + autogenDebugf("file %q: search comments until first import pos %d (%s)", + filePath, importPos, fset.Position(importPos)) } else { importPos = f.End() - autogenDebugf("file %q: search comments until EOF pos %d (%s)", filePath, importPos, fset.Position(importPos)) + autogenDebugf("file %q: search comments until EOF pos %d (%s)", + filePath, importPos, fset.Position(importPos)) } var neededComments []string diff --git a/pkg/result/processors/autogenerated_exclude_test.go b/pkg/result/processors/autogenerated_exclude_test.go index e0ca2364..53a25dd6 100644 --- a/pkg/result/processors/autogenerated_exclude_test.go +++ b/pkg/result/processors/autogenerated_exclude_test.go @@ -39,7 +39,8 @@ func TestIsAutogeneratedDetection(t *testing.T) { // DO NOT EDIT ** This file was generated with the bake tool ** DO NOT EDIT // // Generated by running -// maketables --tables=all --data=http://www.unicode.org/Public/8.0.0/ucd/UnicodeData.txt --casefolding=http://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt +// maketables --tables=all --data=http://www.unicode.org/Public/8.0.0/ucd/UnicodeData.txt +// --casefolding=http://www.unicode.org/Public/8.0.0/ucd/CaseFolding.txt // DO NOT EDIT /* diff --git a/test/testdata/lll.go b/test/testdata/lll.go new file mode 100644 index 00000000..63f27ada --- /dev/null +++ b/test/testdata/lll.go @@ -0,0 +1,6 @@ +// args: -Elll +package testdata + +func Lll() { + // In my experience, long lines are the lines with comments, not the code. So this is a long comment // ERROR "line is 135 characters" +} diff --git a/third_party/lll/LICENSE b/third_party/lll/LICENSE new file mode 100644 index 00000000..7f9e1b07 --- /dev/null +++ b/third_party/lll/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016 Fredrik Wallgren + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file