diff --git a/go.mod b/go.mod index 61bfe0f..8416e52 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/fzipp/gocyclo v0.6.0 github.com/goccy/go-graphviz v0.2.9 github.com/stretchr/testify v1.9.0 - golang.org/x/tools v0.27.0 + golang.org/x/tools v0.28.0 ) require ( @@ -22,8 +22,8 @@ require ( go.uber.org/multierr v1.10.0 // indirect golang.org/x/image v0.21.0 // indirect golang.org/x/mod v0.22.0 // indirect - golang.org/x/sync v0.9.0 // indirect - golang.org/x/sys v0.27.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/sys v0.28.0 // indirect golang.org/x/text v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index b551511..ec82a76 100644 --- a/go.sum +++ b/go.sum @@ -44,15 +44,21 @@ golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= +golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8= +golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/engine.go b/internal/engine.go index 6338aca..7a5be67 100644 --- a/internal/engine.go +++ b/internal/engine.go @@ -49,7 +49,6 @@ var allRuleConstructors = ruleMap{ "repeated-regex-compilation": NewRepeatedRegexCompilationRule, "useless-break": NewUselessBreakRule, "defer-issues": NewDeferRule, - "gno-mod-tidy": NewMissingModPackageRule, "slice-bounds-check": NewSliceBoundCheckRule, "const-error-declaration": NewConstErrorDeclarationRule, } diff --git a/internal/lints/missing_package_mod.go b/internal/lints/missing_package_mod.go deleted file mode 100644 index 9e34bea..0000000 --- a/internal/lints/missing_package_mod.go +++ /dev/null @@ -1,108 +0,0 @@ -package lints - -import ( - "bufio" - "fmt" - "go/ast" - "go/token" - "os" - "path/filepath" - "strconv" - "strings" - - tt "github.com/gnolang/tlin/internal/types" -) - -func DetectMissingModPackage(filename string, node *ast.File, fset *token.FileSet, severity tt.Severity) ([]tt.Issue, error) { - dir := filepath.Dir(filename) - modFile := filepath.Join(dir, "gno.mod") - - requiredPackages, err := extractGnoImports(node) - if err != nil { - return nil, fmt.Errorf("failed to extract gno imports: %w", err) - } - - declaredPackages, err := extractDeclaredPackages(modFile) - if err != nil { - return nil, fmt.Errorf("failed to extract declared packages: %w", err) - } - - issues := make([]tt.Issue, 0) - - var unusedPackages []string - for pkg := range declaredPackages { - if _, ok := requiredPackages[pkg]; !ok { - unusedPackages = append(unusedPackages, pkg) - } - } - - if len(unusedPackages) > 0 { - issue := tt.Issue{ - Rule: "gno-mod-tidy", - Filename: modFile, - Start: token.Position{Filename: modFile}, - End: token.Position{Filename: modFile}, - Message: fmt.Sprintf("packages %s are declared in gno.mod file but not imported.\nrun `gno mod tidy`", strings.Join(unusedPackages, ", ")), - Severity: severity, - } - issues = append(issues, issue) - } - - for pkg := range requiredPackages { - if !declaredPackages[pkg] { - issue := tt.Issue{ - Rule: "gno-mod-tidy", - Filename: modFile, - Start: token.Position{Filename: modFile}, - End: token.Position{Filename: modFile}, - Message: fmt.Sprintf("package %s is imported but not declared in gno.mod file. please consider to remove.\nrun `gno mod tidy`", pkg), - Severity: severity, - } - issues = append(issues, issue) - } - } - - return issues, nil -} - -func extractGnoImports(node *ast.File) (map[string]bool, error) { - imports := make(map[string]bool) - for _, imp := range node.Imports { - if imp.Path != nil { - path, err := strconv.Unquote(imp.Path.Value) - if err != nil { - return nil, fmt.Errorf("failed to unquote import path: %w", err) - } - if strings.HasPrefix(path, "gno.land/p/") || strings.HasPrefix(path, "gno.land/r/") { - imports[path] = true - } - } - } - return imports, nil -} - -func extractDeclaredPackages(modFile string) (map[string]bool, error) { - file, err := os.Open(modFile) - if err != nil { - return nil, err - } - defer file.Close() - - packages := make(map[string]bool) - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, "gno.land/p/") || strings.HasPrefix(line, "gno.land/r/") { - parts := strings.Fields(line) - if len(parts) >= 2 { - packages[parts[0]] = true - } - } - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return packages, nil -} diff --git a/internal/lints/missing_package_mod_test.go b/internal/lints/missing_package_mod_test.go deleted file mode 100644 index 5a36a64..0000000 --- a/internal/lints/missing_package_mod_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package lints - -import ( - "go/parser" - "go/token" - "os" - "path/filepath" - "testing" - - "github.com/gnolang/tlin/internal/types" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestDetectMissingPackageInMod(t *testing.T) { - tests := []struct { - name string - gnoContent string - modContent string - expectedIssues int - }{ - { - name: "No missing packages", - gnoContent: ` - package foo - import ( - "gno.land/p/demo/avl" - "gno.land/r/demo/users" - ) - func SomeFunc() {} - `, - modContent: ` - module foo - require ( - gno.land/p/demo/avl v0.0.0-latest - gno.land/r/demo/users v0.0.0-latest - ) - `, - expectedIssues: 0, - }, - { - name: "One missing package", - gnoContent: ` - package foo - import ( - "gno.land/p/demo/avl" - "gno.land/r/demo/users" - ) - func Foo() {} - `, - modContent: ` - module foo - require ( - gno.land/p/demo/avl v0.0.0-latest - ) - `, - expectedIssues: 1, - }, - { - name: "Multiple missing packages", - gnoContent: ` - package bar - import ( - "gno.land/p/demo/avl" - "gno.land/r/demo/users" - "gno.land/p/demo/ufmt" - ) - func main() {} - `, - modContent: ` - module bar - require ( - gno.land/p/demo/avl v0.0.0-latest - ) - `, - expectedIssues: 2, - }, - { - name: "declared but not imported", - gnoContent: ` - package bar - - func main() {} - `, - modContent: ` - module bar - require ( - gno.land/p/demo/avl v0.0.0-latest - ) - `, - expectedIssues: 1, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tmpDir, err := os.MkdirTemp("", "test") - require.NoError(t, err) - defer os.RemoveAll(tmpDir) - - gnoFile := filepath.Join(tmpDir, "main.gno") - err = os.WriteFile(gnoFile, []byte(tt.gnoContent), 0o644) - require.NoError(t, err) - - modFile := filepath.Join(tmpDir, "gno.mod") - err = os.WriteFile(modFile, []byte(tt.modContent), 0o644) - require.NoError(t, err) - - fset := token.NewFileSet() - node, err := parser.ParseFile(fset, gnoFile, nil, parser.ParseComments) - require.NoError(t, err) - - issues, err := DetectMissingModPackage(gnoFile, node, fset, types.SeverityError) - - require.NoError(t, err) - assert.Len(t, issues, tt.expectedIssues) - - for _, issue := range issues { - assert.Equal(t, "gno-mod-tidy", issue.Rule) - assert.Equal(t, modFile, issue.Filename) - println(issue.String()) - } - }) - } -} diff --git a/internal/rule_set.go b/internal/rule_set.go index edb4650..2f3156d 100644 --- a/internal/rule_set.go +++ b/internal/rule_set.go @@ -313,32 +313,6 @@ func (r *DeferRule) SetSeverity(severity tt.Severity) { r.severity = severity } -type MissingModPackageRule struct { - severity tt.Severity -} - -func NewMissingModPackageRule() LintRule { - return &MissingModPackageRule{ - severity: tt.SeverityError, - } -} - -func (r *MissingModPackageRule) Check(filename string, node *ast.File, fset *token.FileSet) ([]tt.Issue, error) { - return lints.DetectMissingModPackage(filename, node, fset, r.severity) -} - -func (r *MissingModPackageRule) Name() string { - return "gno-mod-tidy" -} - -func (r *MissingModPackageRule) Severity() tt.Severity { - return r.severity -} - -func (r *MissingModPackageRule) SetSeverity(severity tt.Severity) { - r.severity = severity -} - type ConstErrorDeclarationRule struct { severity tt.Severity }