diff --git a/internal/config/config.go b/internal/config/config.go index c43fab908..4319c1630 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -65,6 +65,7 @@ import ( "github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/only_throw_error" "github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/prefer_as_const" "github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/prefer_promise_reject_errors" + // "github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/prefer_readonly_parameter_types" // Temporarily disabled - incomplete implementation "github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/prefer_reduce_type_parameter" "github.com/web-infra-dev/rslint/internal/plugins/typescript/rules/prefer_return_this_type" @@ -306,47 +307,46 @@ func (config RslintConfig) GetRulesForFile(filePath string) map[string]*RuleConf for _, entry := range config { // First check if the file should be ignored - if isFileIgnored(filePath, entry.Ignores) { + if isFileMatched(filePath, entry.Ignores) { continue // Skip this config entry for ignored files } - // Check if the file matches the files pattern - matches := true - - if matches { + // Skip this config entry if the file doesn't match the files pattern + if len(entry.Files) > 0 && !isFileMatched(filePath, entry.Files) { + continue + } - /// Merge rules from plugin - for _, plugin := range entry.Plugins { + /// Merge rules from plugin + for _, plugin := range entry.Plugins { - for _, rule := range GetAllRulesForPlugin(plugin) { - enabledRules[rule.Name] = &RuleConfig{Level: "error"} // Default level for plugin rules - } + for _, rule := range GetAllRulesForPlugin(plugin) { + enabledRules[rule.Name] = &RuleConfig{Level: "error"} // Default level for plugin rules } - // Merge rules from this entry - for ruleName, ruleValue := range entry.Rules { - - switch v := ruleValue.(type) { - case string: - // Handle simple string values like "error", "warn", "off" - enabledRules[ruleName] = &RuleConfig{Level: v} - case map[string]interface{}: - // Handle object configuration - ruleConfig := &RuleConfig{} - if level, ok := v["level"].(string); ok { - ruleConfig.Level = level - } - if options, ok := v["options"].(map[string]interface{}); ok { - ruleConfig.Options = options - } - if ruleConfig.IsEnabled() { - enabledRules[ruleName] = ruleConfig - } - case []interface{}: - // Handle array format like ["error", {...options}] or ["warn"] or ["off"] - ruleConfig := parseArrayRuleConfig(v) - if ruleConfig != nil && ruleConfig.IsEnabled() { - enabledRules[ruleName] = ruleConfig - } + } + // Merge rules from this entry + for ruleName, ruleValue := range entry.Rules { + + switch v := ruleValue.(type) { + case string: + // Handle simple string values like "error", "warn", "off" + enabledRules[ruleName] = &RuleConfig{Level: v} + case map[string]interface{}: + // Handle object configuration + ruleConfig := &RuleConfig{} + if level, ok := v["level"].(string); ok { + ruleConfig.Level = level + } + if options, ok := v["options"].(map[string]interface{}); ok { + ruleConfig.Options = options + } + if ruleConfig.IsEnabled() { + enabledRules[ruleName] = ruleConfig + } + case []interface{}: + // Handle array format like ["error", {...options}] or ["warn"] or ["off"] + ruleConfig := parseArrayRuleConfig(v) + if ruleConfig != nil && ruleConfig.IsEnabled() { + enabledRules[ruleName] = ruleConfig } } } @@ -471,13 +471,13 @@ func getAllTypeScriptEslintPluginRules() []rule.Rule { return rules } -// isFileIgnored checks if a file should be ignored based on ignore patterns -func isFileIgnored(filePath string, ignorePatterns []string) bool { +// isFileMatched checks if a file should be matched based on glob patterns +func isFileMatched(filePath string, ignorePatterns []string) bool { // Get current working directory for relative path resolution cwd, err := os.Getwd() if err != nil { // If we can't get cwd, fall back to simple matching - return isFileIgnoredSimple(filePath, ignorePatterns) + return isFileMatchedSimple(filePath, ignorePatterns) } // Normalize the file path relative to cwd @@ -515,8 +515,8 @@ func normalizePath(filePath, cwd string) string { })) } -// isFileIgnoredSimple provides fallback matching when cwd is unavailable -func isFileIgnoredSimple(filePath string, ignorePatterns []string) bool { +// isFileMatchedSimple provides fallback matching when cwd is unavailable +func isFileMatchedSimple(filePath string, ignorePatterns []string) bool { for _, pattern := range ignorePatterns { if matched, err := doublestar.Match(pattern, filePath); err == nil && matched { return true diff --git a/internal/config/cwd_test.go b/internal/config/cwd_test.go index f6f9c3d41..54b319a4c 100644 --- a/internal/config/cwd_test.go +++ b/internal/config/cwd_test.go @@ -17,62 +17,62 @@ func TestCwdHandling(t *testing.T) { defer t.Chdir(originalCwd) // Restore after test completes tests := []struct { - name string - filePath string - patterns []string - shouldIgnore bool - description string + name string + filePath string + patterns []string + shouldMatch bool + description string }{ { - name: "Relative path matching", - filePath: "src/component.ts", - patterns: []string{"src/**"}, - shouldIgnore: true, - description: "Relative paths should match relative patterns", + name: "Relative path matching", + filePath: "src/component.ts", + patterns: []string{"src/**"}, + shouldMatch: true, + description: "Relative paths should match relative patterns", }, { - name: "Absolute path to relative path matching", - filePath: filepath.Join(originalCwd, "src/component.ts"), - patterns: []string{"src/**"}, - shouldIgnore: true, - description: "Absolute paths should be converted to relative paths before matching", + name: "Absolute path to relative path matching", + filePath: filepath.Join(originalCwd, "src/component.ts"), + patterns: []string{"src/**"}, + shouldMatch: true, + description: "Absolute paths should be converted to relative paths before matching", }, { - name: "node_modules recursive matching", - filePath: "node_modules/package/deep/file.js", - patterns: []string{"node_modules/**"}, - shouldIgnore: true, - description: "Recursive patterns should match deeply nested files", + name: "node_modules recursive matching", + filePath: "node_modules/package/deep/file.js", + patterns: []string{"node_modules/**"}, + shouldMatch: true, + description: "Recursive patterns should match deeply nested files", }, { - name: "Test file pattern matching", - filePath: "src/utils/helper.test.ts", - patterns: []string{"**/*.test.ts"}, - shouldIgnore: true, - description: "Global recursive patterns should match test files in any location", + name: "Test file pattern matching", + filePath: "src/utils/helper.test.ts", + patterns: []string{"**/*.test.ts"}, + shouldMatch: true, + description: "Global recursive patterns should match test files in any location", }, { - name: "Non-matching file", - filePath: "src/component.ts", - patterns: []string{"dist/**", "*.log"}, - shouldIgnore: false, - description: "Files not matching any pattern should not be ignored", + name: "Non-matching file", + filePath: "src/component.ts", + patterns: []string{"dist/**", "*.log"}, + shouldMatch: false, + description: "Files not matching any pattern should not be ignored", }, { - name: "Cross-platform path handling", - filePath: "src\\windows\\style\\path.ts", - patterns: []string{"src/**"}, - shouldIgnore: true, - description: "Windows style paths should be handled correctly", + name: "Cross-platform path handling", + filePath: "src\\windows\\style\\path.ts", + patterns: []string{"src/**"}, + shouldMatch: true, + description: "Windows style paths should be handled correctly", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := isFileIgnored(tt.filePath, tt.patterns) - if result != tt.shouldIgnore { - t.Errorf("%s: isFileIgnored(%q, %v) = %v, expected %v", - tt.description, tt.filePath, tt.patterns, result, tt.shouldIgnore) + result := isFileMatched(tt.filePath, tt.patterns) + if result != tt.shouldMatch { + t.Errorf("%s: isFileMatched(%q, %v) = %v, expected %v", + tt.description, tt.filePath, tt.patterns, result, tt.shouldMatch) } }) } diff --git a/website/docs/en/config/index.md b/website/docs/en/config/index.md index d6704c493..d972116d4 100644 --- a/website/docs/en/config/index.md +++ b/website/docs/en/config/index.md @@ -49,6 +49,25 @@ The configuration file contains an array of configuration entries. Each entry de ## Configuration Options +### files + +- **Type:** `string[]` +- **Default:** `[]` + +An array of glob patterns for files and directories to include during linting. If omitted, all files are included. + +```jsonc +{ + "files": ["./src/**", "./tests/**"], +} +``` + +Patterns support: + +- **Glob patterns**: `*.js`, `**/*.ts` +- **Directory patterns**: `src/**`, `tests/**` +- **Negation**: `!important.ts` (when used with other patterns) + ### ignores - **Type:** `string[]`