@sun-asterisk/sunlint 1.3.45 → 1.3.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -406,6 +406,7 @@ class CliActionHandler {
|
|
|
406
406
|
*/
|
|
407
407
|
getPresetName() {
|
|
408
408
|
if (this.options.all) return 'all preset';
|
|
409
|
+
if (this.options.specific) return 'language-specific preset';
|
|
409
410
|
if (this.options.quality) return 'quality preset';
|
|
410
411
|
if (this.options.security) return 'security preset';
|
|
411
412
|
if (this.options.category) return `${this.options.category} preset`;
|
|
@@ -525,6 +526,7 @@ class CliActionHandler {
|
|
|
525
526
|
return this.options.architecture &&
|
|
526
527
|
!this.options.impact &&
|
|
527
528
|
!this.options.all &&
|
|
529
|
+
!this.options.specific &&
|
|
528
530
|
!this.options.rule &&
|
|
529
531
|
!this.options.rules &&
|
|
530
532
|
!this.options.quality &&
|
|
@@ -540,6 +542,7 @@ class CliActionHandler {
|
|
|
540
542
|
return this.options.impact &&
|
|
541
543
|
!this.options.architecture &&
|
|
542
544
|
!this.options.all &&
|
|
545
|
+
!this.options.specific &&
|
|
543
546
|
!this.options.rule &&
|
|
544
547
|
!this.options.rules &&
|
|
545
548
|
!this.options.quality &&
|
package/core/cli-program.js
CHANGED
|
@@ -22,6 +22,7 @@ function createCliProgram() {
|
|
|
22
22
|
.option('--rules <rules>', 'Run multiple rules (comma-separated)')
|
|
23
23
|
.option('-a, --all', 'Run all available rules')
|
|
24
24
|
.option('-c, --category <category>', 'Run rules by category (quality, security, logging, naming)')
|
|
25
|
+
.option('-s, --specific', 'Run language-specific rules (requires --languages)')
|
|
25
26
|
.option('--quality', 'Run all code quality rules')
|
|
26
27
|
.option('--security', 'Run all secure coding rules');
|
|
27
28
|
|
|
@@ -108,6 +109,12 @@ Examples:
|
|
|
108
109
|
sunlint --quality --input=src # Quality rules only
|
|
109
110
|
sunlint --security --input=src # Security rules only
|
|
110
111
|
|
|
112
|
+
Language-Specific:
|
|
113
|
+
sunlint --specific --languages=dart --input=lib # Dart rules only
|
|
114
|
+
sunlint --specific --languages=kotlin --input=app/src # Kotlin rules only
|
|
115
|
+
sunlint --specific --languages=dart,kotlin --input=. # Dart + Kotlin rules
|
|
116
|
+
sunlint --all --languages=dart --input=lib # All rules + Dart rules
|
|
117
|
+
|
|
111
118
|
Git Integration:
|
|
112
119
|
sunlint --all --changed-files --input=. # Changed files only
|
|
113
120
|
sunlint --all --staged-files --input=. # Staged files only
|
|
@@ -60,6 +60,48 @@ class RuleSelectionService {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* Collect language-specific rules from ALL versions of released-rules.json
|
|
65
|
+
* Searches across all versions because the latest version may have empty categories
|
|
66
|
+
* @param {string[]} languages - Array of language names (e.g., ['dart', 'kotlin'])
|
|
67
|
+
* @returns {string[]} Array of rule IDs matching the specified languages
|
|
68
|
+
*/
|
|
69
|
+
collectLanguageSpecificRules(languages) {
|
|
70
|
+
const { getLanguageFromRuleId } = require('./constants/rules');
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
if (!fs.existsSync(this.releasedRulesPath)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const data = JSON.parse(fs.readFileSync(this.releasedRulesPath, 'utf8'));
|
|
78
|
+
const versions = data.versions || [];
|
|
79
|
+
|
|
80
|
+
if (versions.length === 0) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const targetLanguages = new Set(languages.map(l => l.toLowerCase()));
|
|
85
|
+
const matchingRuleIds = new Set();
|
|
86
|
+
|
|
87
|
+
for (const versionEntry of versions) {
|
|
88
|
+
const rulesByCategory = versionEntry.rulesByCategory || {};
|
|
89
|
+
for (const categoryRules of Object.values(rulesByCategory)) {
|
|
90
|
+
for (const ruleId of categoryRules) {
|
|
91
|
+
const ruleLanguage = getLanguageFromRuleId(ruleId);
|
|
92
|
+
if (ruleLanguage && targetLanguages.has(ruleLanguage)) {
|
|
93
|
+
matchingRuleIds.add(ruleId);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return Array.from(matchingRuleIds);
|
|
100
|
+
} catch (error) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
63
105
|
async selectRules(config, options) {
|
|
64
106
|
// Ensure adapter is initialized
|
|
65
107
|
await this.initialize();
|
|
@@ -75,6 +117,22 @@ class RuleSelectionService {
|
|
|
75
117
|
selectedRules = [options.rule];
|
|
76
118
|
} else if (options.rules) {
|
|
77
119
|
selectedRules = options.rules.split(',').map(r => r.trim());
|
|
120
|
+
} else if (options.specific) {
|
|
121
|
+
// --specific requires --languages to determine which language rules to load
|
|
122
|
+
if (!options.languages) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
chalk.red('--specific requires --languages to be specified\n') +
|
|
125
|
+
chalk.gray('Example: sunlint --specific --languages=dart --input=lib')
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
const targetLanguages = options.languages.split(',').map(l => l.trim());
|
|
129
|
+
selectedRules = this.collectLanguageSpecificRules(targetLanguages);
|
|
130
|
+
|
|
131
|
+
if (selectedRules.length === 0) {
|
|
132
|
+
console.warn(
|
|
133
|
+
chalk.yellow(`\u26A0\uFE0F No language-specific rules found for: ${targetLanguages.join(', ')}`)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
78
136
|
} else if (options.all) {
|
|
79
137
|
// Load all rules from released-rules.json
|
|
80
138
|
if (releasedRules) {
|
|
@@ -89,6 +147,20 @@ class RuleSelectionService {
|
|
|
89
147
|
// Fallback to preset file
|
|
90
148
|
selectedRules = this.loadPresetRules('all');
|
|
91
149
|
}
|
|
150
|
+
|
|
151
|
+
// Augment with language-specific rules when --languages is specified
|
|
152
|
+
// This handles the case where the latest version has empty categories
|
|
153
|
+
if (options.languages) {
|
|
154
|
+
const targetLanguages = options.languages.split(',').map(l => l.trim());
|
|
155
|
+
const languageRules = this.collectLanguageSpecificRules(targetLanguages);
|
|
156
|
+
const existingRuleSet = new Set(selectedRules);
|
|
157
|
+
|
|
158
|
+
for (const ruleId of languageRules) {
|
|
159
|
+
if (!existingRuleSet.has(ruleId)) {
|
|
160
|
+
selectedRules.push(ruleId);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
92
164
|
} else if (options.quality) {
|
|
93
165
|
// Load Common rules from released-rules.json
|
|
94
166
|
if (releasedRules && releasedRules.Common) {
|
package/package.json
CHANGED