Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 40 additions & 40 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
}
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
78 changes: 39 additions & 39 deletions internal/config/cwd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
})
}
Expand Down
19 changes: 19 additions & 0 deletions website/docs/en/config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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[]`
Expand Down
Loading