feat: add the gosmopolitan linter (#3458)
This commit is contained in:
		
							parent
							
								
									b29a4f6dc0
								
							
						
					
					
						commit
						553d7df585
					
				@ -948,6 +948,37 @@ linters-settings:
 | 
			
		||||
      # Default: "0600"
 | 
			
		||||
      G306: "0600"
 | 
			
		||||
 | 
			
		||||
  gosmopolitan:
 | 
			
		||||
    # Allow and ignore `time.Local` usages.
 | 
			
		||||
    #
 | 
			
		||||
    # Default: false
 | 
			
		||||
    allow-time-local: true
 | 
			
		||||
    # List of fully qualified names in the `full/pkg/path.name` form, to act as "i18n escape hatches".
 | 
			
		||||
    # String literals inside call-like expressions to, or struct literals of those names,
 | 
			
		||||
    # are exempt from the writing system check.
 | 
			
		||||
    #
 | 
			
		||||
    # Default: []
 | 
			
		||||
    escape-hatches:
 | 
			
		||||
      - 'github.com/nicksnyder/go-i18n/v2/i18n.Message'
 | 
			
		||||
      - 'example.com/your/project/i18n/markers.Raw'
 | 
			
		||||
      - 'example.com/your/project/i18n/markers.OK'
 | 
			
		||||
      - 'example.com/your/project/i18n/markers.TODO'
 | 
			
		||||
      - 'command-line-arguments.Simple'
 | 
			
		||||
    # Ignore test files.
 | 
			
		||||
    #
 | 
			
		||||
    # Default: true
 | 
			
		||||
    ignore-tests: false
 | 
			
		||||
    # List of Unicode scripts to watch for any usage in string literals.
 | 
			
		||||
    # https://pkg.go.dev/unicode#pkg-variables
 | 
			
		||||
    #
 | 
			
		||||
    # Default: ["Han"]
 | 
			
		||||
    watch-for-scripts:
 | 
			
		||||
      - Devanagari
 | 
			
		||||
      - Han
 | 
			
		||||
      - Hangul
 | 
			
		||||
      - Hiragana
 | 
			
		||||
      - Katakana
 | 
			
		||||
 | 
			
		||||
  govet:
 | 
			
		||||
    # Report about shadowed variables.
 | 
			
		||||
    # Default: false
 | 
			
		||||
@ -2049,6 +2080,7 @@ linters:
 | 
			
		||||
    - goprintffuncname
 | 
			
		||||
    - gosec
 | 
			
		||||
    - gosimple
 | 
			
		||||
    - gosmopolitan
 | 
			
		||||
    - govet
 | 
			
		||||
    - grouper
 | 
			
		||||
    - ifshort
 | 
			
		||||
@ -2159,6 +2191,7 @@ linters:
 | 
			
		||||
    - goprintffuncname
 | 
			
		||||
    - gosec
 | 
			
		||||
    - gosimple
 | 
			
		||||
    - gosmopolitan
 | 
			
		||||
    - govet
 | 
			
		||||
    - grouper
 | 
			
		||||
    - ifshort
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@ -106,6 +106,7 @@ require (
 | 
			
		||||
	github.com/ultraware/whitespace v0.0.5
 | 
			
		||||
	github.com/uudashr/gocognit v1.0.6
 | 
			
		||||
	github.com/valyala/quicktemplate v1.7.0
 | 
			
		||||
	github.com/xen0n/gosmopolitan v1.2.1
 | 
			
		||||
	github.com/yagipy/maintidx v1.0.0
 | 
			
		||||
	github.com/yeya24/promlinter v0.2.0
 | 
			
		||||
	gitlab.com/bosi/decorder v0.2.3
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
										generated
									
									
									
								
							@ -548,6 +548,8 @@ github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD
 | 
			
		||||
github.com/valyala/quicktemplate v1.7.0 h1:LUPTJmlVcb46OOUY3IeD9DojFpAVbsG+5WFTcjMJzCM=
 | 
			
		||||
github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8=
 | 
			
		||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
 | 
			
		||||
github.com/xen0n/gosmopolitan v1.2.1 h1:3pttnTuFumELBRSh+KQs1zcz4fN6Zy7aB0xlnQSn1Iw=
 | 
			
		||||
github.com/xen0n/gosmopolitan v1.2.1/go.mod h1:JsHq/Brs1o050OOdmzHeOr0N7OtlnKRAGAsElF8xBQA=
 | 
			
		||||
github.com/yagipy/maintidx v1.0.0 h1:h5NvIsCz+nRDapQ0exNv4aJ0yXSI0420omVANTv3GJM=
 | 
			
		||||
github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk=
 | 
			
		||||
github.com/yeya24/promlinter v0.2.0 h1:xFKDQ82orCU5jQujdaD8stOHiv8UN68BSdn2a8u8Y3o=
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,12 @@ var defaultLintersSettings = LintersSettings{
 | 
			
		||||
	Gosec: GoSecSettings{
 | 
			
		||||
		Concurrency: runtime.NumCPU(),
 | 
			
		||||
	},
 | 
			
		||||
	Gosmopolitan: GosmopolitanSettings{
 | 
			
		||||
		AllowTimeLocal:  false,
 | 
			
		||||
		EscapeHatches:   []string{},
 | 
			
		||||
		IgnoreTests:     true,
 | 
			
		||||
		WatchForScripts: []string{"Han"},
 | 
			
		||||
	},
 | 
			
		||||
	Ifshort: IfshortSettings{
 | 
			
		||||
		MaxDeclLines: 1,
 | 
			
		||||
		MaxDeclChars: 30,
 | 
			
		||||
@ -167,6 +173,7 @@ type LintersSettings struct {
 | 
			
		||||
	Gomodguard       GoModGuardSettings
 | 
			
		||||
	Gosec            GoSecSettings
 | 
			
		||||
	Gosimple         StaticCheckSettings
 | 
			
		||||
	Gosmopolitan     GosmopolitanSettings
 | 
			
		||||
	Govet            GovetSettings
 | 
			
		||||
	Grouper          GrouperSettings
 | 
			
		||||
	Ifshort          IfshortSettings
 | 
			
		||||
@ -449,6 +456,13 @@ type GoSecSettings struct {
 | 
			
		||||
	Concurrency      int                    `mapstructure:"concurrency"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GosmopolitanSettings struct {
 | 
			
		||||
	AllowTimeLocal  bool     `mapstructure:"allow-time-local"`
 | 
			
		||||
	EscapeHatches   []string `mapstructure:"escape-hatches"`
 | 
			
		||||
	IgnoreTests     bool     `mapstructure:"ignore-tests"`
 | 
			
		||||
	WatchForScripts []string `mapstructure:"watch-for-scripts"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type GovetSettings struct {
 | 
			
		||||
	Go             string `mapstructure:"-"`
 | 
			
		||||
	CheckShadowing bool   `mapstructure:"check-shadowing"`
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								pkg/golinters/gosmopolitan.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								pkg/golinters/gosmopolitan.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
package golinters
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/xen0n/gosmopolitan"
 | 
			
		||||
	"golang.org/x/tools/go/analysis"
 | 
			
		||||
 | 
			
		||||
	"github.com/golangci/golangci-lint/pkg/config"
 | 
			
		||||
	"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func NewGosmopolitan(s *config.GosmopolitanSettings) *goanalysis.Linter {
 | 
			
		||||
	a := gosmopolitan.NewAnalyzer()
 | 
			
		||||
 | 
			
		||||
	cfgMap := map[string]map[string]interface{}{}
 | 
			
		||||
	if s != nil {
 | 
			
		||||
		cfgMap[a.Name] = map[string]interface{}{
 | 
			
		||||
			"allowtimelocal":  s.AllowTimeLocal,
 | 
			
		||||
			"escapehatches":   strings.Join(s.EscapeHatches, ","),
 | 
			
		||||
			"lookattests":     !s.IgnoreTests,
 | 
			
		||||
			"watchforscripts": strings.Join(s.WatchForScripts, ","),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return goanalysis.NewLinter(
 | 
			
		||||
		a.Name,
 | 
			
		||||
		a.Doc,
 | 
			
		||||
		[]*analysis.Analyzer{a},
 | 
			
		||||
		cfgMap,
 | 
			
		||||
	).WithLoadMode(goanalysis.LoadModeTypesInfo)
 | 
			
		||||
}
 | 
			
		||||
@ -135,6 +135,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
 | 
			
		||||
		gomodguardCfg       *config.GoModGuardSettings
 | 
			
		||||
		gosecCfg            *config.GoSecSettings
 | 
			
		||||
		gosimpleCfg         *config.StaticCheckSettings
 | 
			
		||||
		gosmopolitanCfg     *config.GosmopolitanSettings
 | 
			
		||||
		govetCfg            *config.GovetSettings
 | 
			
		||||
		grouperCfg          *config.GrouperSettings
 | 
			
		||||
		ifshortCfg          *config.IfshortSettings
 | 
			
		||||
@ -213,6 +214,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
 | 
			
		||||
		gomodguardCfg = &m.cfg.LintersSettings.Gomodguard
 | 
			
		||||
		gosecCfg = &m.cfg.LintersSettings.Gosec
 | 
			
		||||
		gosimpleCfg = &m.cfg.LintersSettings.Gosimple
 | 
			
		||||
		gosmopolitanCfg = &m.cfg.LintersSettings.Gosmopolitan
 | 
			
		||||
		govetCfg = &m.cfg.LintersSettings.Govet
 | 
			
		||||
		grouperCfg = &m.cfg.LintersSettings.Grouper
 | 
			
		||||
		ifshortCfg = &m.cfg.LintersSettings.Ifshort
 | 
			
		||||
@ -558,6 +560,12 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config {
 | 
			
		||||
			WithAlternativeNames(megacheckName).
 | 
			
		||||
			WithURL("https://github.com/dominikh/go-tools/tree/master/simple"),
 | 
			
		||||
 | 
			
		||||
		linter.NewConfig(golinters.NewGosmopolitan(gosmopolitanCfg)).
 | 
			
		||||
			WithSince("v1.53.0").
 | 
			
		||||
			WithLoadForGoAnalysis().
 | 
			
		||||
			WithPresets(linter.PresetBugs).
 | 
			
		||||
			WithURL("https://github.com/xen0n/gosmopolitan"),
 | 
			
		||||
 | 
			
		||||
		linter.NewConfig(golinters.NewGovet(govetCfg)).
 | 
			
		||||
			WithSince("v1.0.0").
 | 
			
		||||
			WithLoadForGoAnalysis().
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										3
									
								
								test/testdata/configs/gosmopolitan_allow_time_local.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/testdata/configs/gosmopolitan_allow_time_local.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
linters-settings:
 | 
			
		||||
  gosmopolitan:
 | 
			
		||||
    allow-time-local: true
 | 
			
		||||
							
								
								
									
										3
									
								
								test/testdata/configs/gosmopolitan_dont_ignore_tests.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/testdata/configs/gosmopolitan_dont_ignore_tests.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
linters-settings:
 | 
			
		||||
  gosmopolitan:
 | 
			
		||||
    ignore-tests: false
 | 
			
		||||
							
								
								
									
										8
									
								
								test/testdata/configs/gosmopolitan_escape_hatches.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								test/testdata/configs/gosmopolitan_escape_hatches.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
linters-settings:
 | 
			
		||||
  gosmopolitan:
 | 
			
		||||
    escape-hatches:
 | 
			
		||||
      - 'command-line-arguments.A'
 | 
			
		||||
      - 'command-line-arguments.B'
 | 
			
		||||
      - 'command-line-arguments.C'
 | 
			
		||||
      - 'command-line-arguments.D'
 | 
			
		||||
      - 'fmt.Println'
 | 
			
		||||
							
								
								
									
										6
									
								
								test/testdata/configs/gosmopolitan_scripts.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								test/testdata/configs/gosmopolitan_scripts.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
linters-settings:
 | 
			
		||||
  gosmopolitan:
 | 
			
		||||
    watch-for-scripts:
 | 
			
		||||
      - Hiragana
 | 
			
		||||
      - Katakana
 | 
			
		||||
      - Latin
 | 
			
		||||
							
								
								
									
										25
									
								
								test/testdata/gosmopolitan.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								test/testdata/gosmopolitan.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
			
		||||
//golangcitest:args -Egosmopolitan
 | 
			
		||||
package testdata
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type col struct {
 | 
			
		||||
	// struct tag should not get reported
 | 
			
		||||
	Foo string `gorm:"column:bar;not null;comment:'不应该报告这一行'"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	fmt.Println("hello world")
 | 
			
		||||
	fmt.Println("你好,世界") // want `string literal contains rune in Han script`
 | 
			
		||||
	fmt.Println("こんにちは、セカイ")
 | 
			
		||||
 | 
			
		||||
	_ = col{Foo: "hello"}
 | 
			
		||||
	_ = col{Foo: "你好"} // want `string literal contains rune in Han script`
 | 
			
		||||
 | 
			
		||||
	x := time.Local // want `usage of time.Local`
 | 
			
		||||
	_ = time.Now().In(x)
 | 
			
		||||
	_ = time.Date(2023, 1, 2, 3, 4, 5, 678901234, time.Local) // want `usage of time.Local`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								test/testdata/gosmopolitan_allow_time_local.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/testdata/gosmopolitan_allow_time_local.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
//golangcitest:args -Egosmopolitan
 | 
			
		||||
//golangcitest:config_path testdata/configs/gosmopolitan_allow_time_local.yml
 | 
			
		||||
//golangcitest:expected_exitcode 0
 | 
			
		||||
package testdata
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	_ = time.Local
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								test/testdata/gosmopolitan_dont_ignore_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/testdata/gosmopolitan_dont_ignore_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
//golangcitest:args -Egosmopolitan
 | 
			
		||||
//golangcitest:config_path testdata/configs/gosmopolitan_dont_ignore_tests.yml
 | 
			
		||||
package testdata
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	_ = "开启检查测试文件" // want `string literal contains rune in Han script`
 | 
			
		||||
	_ = time.Local // want `usage of time.Local`
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								test/testdata/gosmopolitan_escape_hatches.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								test/testdata/gosmopolitan_escape_hatches.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
//golangcitest:args -Egosmopolitan
 | 
			
		||||
//golangcitest:config_path testdata/configs/gosmopolitan_escape_hatches.yml
 | 
			
		||||
package testdata
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	myAlias "fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type A string
 | 
			
		||||
type B = string
 | 
			
		||||
type C struct {
 | 
			
		||||
	foo string
 | 
			
		||||
	Bar string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func D(fmt string) string {
 | 
			
		||||
	myAlias.Println(fmt, "测试")
 | 
			
		||||
	return myAlias.Sprintf("%s 测试", fmt) // want `string literal contains rune in Han script`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type X struct {
 | 
			
		||||
	baz string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	_ = A("测试")
 | 
			
		||||
	_ = string(A(string("测试")))
 | 
			
		||||
	_ = B("测试")
 | 
			
		||||
	_ = C{
 | 
			
		||||
		foo: "测试",
 | 
			
		||||
		Bar: "测试",
 | 
			
		||||
	}
 | 
			
		||||
	_ = D("测试")
 | 
			
		||||
 | 
			
		||||
	_ = &X{
 | 
			
		||||
		baz: "测试", // want `string literal contains rune in Han script`
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										12
									
								
								test/testdata/gosmopolitan_ignore_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								test/testdata/gosmopolitan_ignore_test.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
//golangcitest:args -Egosmopolitan
 | 
			
		||||
//golangcitest:expected_exitcode 0
 | 
			
		||||
package testdata
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	_ = "默认不检查测试文件"
 | 
			
		||||
	_ = time.Local
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										14
									
								
								test/testdata/gosmopolitan_scripts.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								test/testdata/gosmopolitan_scripts.go
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
//golangcitest:args -Egosmopolitan
 | 
			
		||||
//golangcitest:config_path testdata/configs/gosmopolitan_scripts.yml
 | 
			
		||||
package testdata
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
	fmt.Println("hello world")                 // want `string literal contains rune in Latin script`
 | 
			
		||||
	fmt.Println("should not report this line") //nolint:gosmopolitan
 | 
			
		||||
	fmt.Println("你好,世界")
 | 
			
		||||
	fmt.Println("こんにちは、セカイ") // want `string literal contains rune in Hiragana script`
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user