@sun-asterisk/sunlint 1.0.6 → 1.0.7
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.
- package/CHANGELOG.md +108 -169
- package/README.md +7 -1
- package/config/presets/beginner.json +1 -1
- package/config/presets/ci.json +3 -2
- package/config/presets/recommended.json +1 -1
- package/config/presets/strict.json +3 -2
- package/config/rules-registry.json +60 -0
- package/config/sunlint-schema.json +0 -7
- package/config/typescript/eslint.config.js +4 -0
- package/core/config-manager.js +9 -8
- package/core/config-merger.js +12 -0
- package/core/file-targeting-service.js +1 -6
- package/core/rule-mapping-service.js +8 -0
- package/package.json +2 -5
- package/cli-legacy.js +0 -355
- package/docs/AI.md +0 -163
- package/docs/ARCHITECTURE.md +0 -78
- package/docs/CI-CD-GUIDE.md +0 -315
- package/docs/COMMAND-EXAMPLES.md +0 -256
- package/docs/DEBUG.md +0 -86
- package/docs/DISTRIBUTION.md +0 -153
- package/docs/ENHANCED_FILE_TARGETING.md +0 -0
- package/docs/ESLINT-INTEGRATION-STRATEGY.md +0 -392
- package/docs/ESLINT_INTEGRATION.md +0 -238
- package/docs/FILE_TARGETING_COMPARISON.md +0 -0
- package/docs/FOLDER_STRUCTURE.md +0 -59
- package/docs/HEURISTIC_VS_AI.md +0 -113
- package/docs/README.md +0 -32
- package/docs/RELEASE_GUIDE.md +0 -230
- package/docs/RULE-RESPONSIBILITY-MATRIX.md +0 -204
- package/eslint-integration/.eslintrc.js +0 -98
- package/eslint-integration/cli.js +0 -35
- package/eslint-integration/eslint-plugin-custom/c002-no-duplicate-code.js +0 -204
- package/eslint-integration/eslint-plugin-custom/c003-no-vague-abbreviations.js +0 -246
- package/eslint-integration/eslint-plugin-custom/c006-function-name-verb-noun.js +0 -207
- package/eslint-integration/eslint-plugin-custom/c010-limit-block-nesting.js +0 -90
- package/eslint-integration/eslint-plugin-custom/c013-no-dead-code.js +0 -43
- package/eslint-integration/eslint-plugin-custom/c014-abstract-dependency-preferred.js +0 -38
- package/eslint-integration/eslint-plugin-custom/c017-limit-constructor-logic.js +0 -39
- package/eslint-integration/eslint-plugin-custom/c018-no-generic-throw.js +0 -335
- package/eslint-integration/eslint-plugin-custom/c023-no-duplicate-variable-name-in-scope.js +0 -142
- package/eslint-integration/eslint-plugin-custom/c027-limit-function-nesting.js +0 -50
- package/eslint-integration/eslint-plugin-custom/c029-catch-block-logging.js +0 -80
- package/eslint-integration/eslint-plugin-custom/c030-use-custom-error-classes.js +0 -294
- package/eslint-integration/eslint-plugin-custom/c034-no-implicit-return.js +0 -34
- package/eslint-integration/eslint-plugin-custom/c035-no-empty-catch.js +0 -32
- package/eslint-integration/eslint-plugin-custom/c041-no-config-inline.js +0 -64
- package/eslint-integration/eslint-plugin-custom/c042-boolean-name-prefix.js +0 -406
- package/eslint-integration/eslint-plugin-custom/c043-no-console-or-print.js +0 -300
- package/eslint-integration/eslint-plugin-custom/c047-no-duplicate-retry-logic.js +0 -239
- package/eslint-integration/eslint-plugin-custom/c048-no-var-declaration.js +0 -31
- package/eslint-integration/eslint-plugin-custom/index.js +0 -155
- package/eslint-integration/eslint-plugin-custom/package.json +0 -13
- package/eslint-integration/eslint-plugin-custom/package.json.bak +0 -9
- package/eslint-integration/eslint-plugin-custom/s003-no-unvalidated-redirect.js +0 -86
- package/eslint-integration/eslint-plugin-custom/s005-no-origin-auth.js +0 -95
- package/eslint-integration/eslint-plugin-custom/s006-activation-recovery-secret-not-plaintext.js +0 -69
- package/eslint-integration/eslint-plugin-custom/s008-crypto-agility.js +0 -62
- package/eslint-integration/eslint-plugin-custom/s009-no-insecure-crypto.js +0 -103
- package/eslint-integration/eslint-plugin-custom/s010-no-insecure-random-in-sensitive-context.js +0 -123
- package/eslint-integration/eslint-plugin-custom/s011-no-insecure-uuid.js +0 -66
- package/eslint-integration/eslint-plugin-custom/s012-hardcode-secret.js +0 -71
- package/eslint-integration/eslint-plugin-custom/s014-insecure-tls-version.js +0 -50
- package/eslint-integration/eslint-plugin-custom/s015-insecure-tls-certificate.js +0 -43
- package/eslint-integration/eslint-plugin-custom/s016-sensitive-query-parameter.js +0 -59
- package/eslint-integration/eslint-plugin-custom/s017-no-sql-injection.js +0 -193
- package/eslint-integration/eslint-plugin-custom/s018-positive-input-validation.js +0 -56
- package/eslint-integration/eslint-plugin-custom/s019-no-raw-user-input-in-email.js +0 -113
- package/eslint-integration/eslint-plugin-custom/s020-no-eval-dynamic-execution.js +0 -89
- package/eslint-integration/eslint-plugin-custom/s022-output-encoding.js +0 -78
- package/eslint-integration/eslint-plugin-custom/s023-no-json-injection.js +0 -300
- package/eslint-integration/eslint-plugin-custom/s025-server-side-input-validation.js +0 -217
- package/eslint-integration/eslint-plugin-custom/s026-json-schema-validation.js +0 -68
- package/eslint-integration/eslint-plugin-custom/s027-no-hardcoded-secrets.js +0 -80
- package/eslint-integration/eslint-plugin-custom/s029-require-csrf-protection.js +0 -79
- package/eslint-integration/eslint-plugin-custom/s030-no-directory-browsing.js +0 -78
- package/eslint-integration/eslint-plugin-custom/s033-require-samesite-cookie.js +0 -80
- package/eslint-integration/eslint-plugin-custom/s034-require-host-cookie-prefix.js +0 -77
- package/eslint-integration/eslint-plugin-custom/s035-cookie-specific-path.js +0 -74
- package/eslint-integration/eslint-plugin-custom/s036-no-unsafe-file-include.js +0 -68
- package/eslint-integration/eslint-plugin-custom/s037-require-anti-cache-headers.js +0 -70
- package/eslint-integration/eslint-plugin-custom/s038-no-version-disclosure.js +0 -74
- package/eslint-integration/eslint-plugin-custom/s039-no-session-token-in-url.js +0 -63
- package/eslint-integration/eslint-plugin-custom/s041-require-session-invalidate-on-logout.js +0 -211
- package/eslint-integration/eslint-plugin-custom/s042-require-periodic-reauthentication.js +0 -294
- package/eslint-integration/eslint-plugin-custom/s043-terminate-sessions-on-password-change.js +0 -254
- package/eslint-integration/eslint-plugin-custom/s044-require-full-session-for-sensitive-operations.js +0 -292
- package/eslint-integration/eslint-plugin-custom/s045-anti-automation-controls.js +0 -46
- package/eslint-integration/eslint-plugin-custom/s046-secure-notification-on-auth-change.js +0 -44
- package/eslint-integration/eslint-plugin-custom/s047-secure-random-passwords.js +0 -108
- package/eslint-integration/eslint-plugin-custom/s048-password-credential-recovery.js +0 -54
- package/eslint-integration/eslint-plugin-custom/s050-session-token-weak-hash.js +0 -94
- package/eslint-integration/eslint-plugin-custom/s052-secure-random-authentication-code.js +0 -66
- package/eslint-integration/eslint-plugin-custom/s054-verification-default-account.js +0 -109
- package/eslint-integration/eslint-plugin-custom/s055-verification-rest-check-the-incoming-content-type.js +0 -143
- package/eslint-integration/eslint-plugin-custom/s057-utc-logging.js +0 -54
- package/eslint-integration/eslint-plugin-custom/s058-no-ssrf.js +0 -73
- package/eslint-integration/eslint-plugin-custom/t002-interface-prefix-i.js +0 -42
- package/eslint-integration/eslint-plugin-custom/t003-ts-ignore-reason.js +0 -48
- package/eslint-integration/eslint-plugin-custom/t004-interface-public-only.js +0 -160
- package/eslint-integration/eslint-plugin-custom/t007-no-fn-in-constructor.js +0 -52
- package/eslint-integration/eslint-plugin-custom/t011-no-real-time-dependency.js +0 -175
- package/eslint-integration/eslint-plugin-custom/t019-no-empty-type.js +0 -95
- package/eslint-integration/eslint-plugin-custom/t025-no-nested-union-tuple.js +0 -48
- package/eslint-integration/eslint-plugin-custom/t026-limit-nested-generics.js +0 -377
- package/eslint-integration/eslint.config.js +0 -125
- package/eslint-integration/eslint.config.simple.js +0 -24
- package/eslint-integration/package.json +0 -23
- package/eslint-integration/sample.ts +0 -53
- package/eslint-integration/test-s003.js +0 -5
- package/eslint-integration/tsconfig.json +0 -27
- package/examples/.github/workflows/code-quality.yml +0 -111
- package/examples/README.md +0 -69
- package/examples/basic-typescript-demo/.eslintrc.json +0 -18
- package/examples/basic-typescript-demo/.next/cache/eslint/.cache_1othrmo +0 -1
- package/examples/basic-typescript-demo/.sunlint.json +0 -29
- package/examples/basic-typescript-demo/eslint.config.mjs +0 -37
- package/examples/basic-typescript-demo/next-env.d.ts +0 -5
- package/examples/basic-typescript-demo/next.config.mjs +0 -4
- package/examples/basic-typescript-demo/package-lock.json +0 -5656
- package/examples/basic-typescript-demo/package.json +0 -34
- package/examples/basic-typescript-demo/src/app/layout.tsx +0 -18
- package/examples/basic-typescript-demo/src/app/page.tsx +0 -48
- package/examples/basic-typescript-demo/src/config.ts +0 -14
- package/examples/basic-typescript-demo/src/good-practices.ts +0 -58
- package/examples/basic-typescript-demo/src/types.generated.ts +0 -13
- package/examples/basic-typescript-demo/src/user.test.ts +0 -19
- package/examples/basic-typescript-demo/src/violations.ts +0 -61
- package/examples/basic-typescript-demo/test-config-priority.sh +0 -0
- package/examples/basic-typescript-demo/test-file-targeting.sh +0 -0
- package/examples/basic-typescript-demo/tsconfig.json +0 -27
- package/examples/enhanced-config.json +0 -0
- package/examples/eslint-integration-demo/.eslintrc.js +0 -38
- package/examples/eslint-integration-demo/.sunlint.json +0 -42
- package/examples/eslint-integration-demo/next-env.d.ts +0 -5
- package/examples/eslint-integration-demo/next.config.js +0 -8
- package/examples/eslint-integration-demo/package-lock.json +0 -5740
- package/examples/eslint-integration-demo/package.json +0 -37
- package/examples/eslint-integration-demo/src/api.test.ts +0 -20
- package/examples/eslint-integration-demo/src/conflict-test.tsx +0 -44
- package/examples/eslint-integration-demo/src/naming-conflicts.ts +0 -50
- package/examples/eslint-integration-demo/test-file-targeting.sh +0 -0
- package/examples/eslint-integration-demo/tsconfig.json +0 -26
- package/examples/file-targeting-demo/global.d.ts +0 -11
- package/examples/file-targeting-demo/jest.config.js +0 -8
- package/examples/file-targeting-demo/sample.ts +0 -53
- package/examples/file-targeting-demo/src/server.js +0 -11
- package/examples/file-targeting-demo/src/server.test.js +0 -11
- package/examples/file-targeting-demo/src/types.d.ts +0 -4
- package/examples/file-targeting-demo/src/types.generated.ts +0 -10
- package/examples/file-targeting-demo/user-service.test.ts +0 -15
- package/examples/file-targeting-demo/user-service.ts +0 -13
- package/examples/file-targeting-demo/utils.js +0 -15
- package/examples/multi-language-project/.eslintrc.json +0 -38
- package/examples/multi-language-project/package.json +0 -37
- package/examples/multi-language-project/src/sample.ts +0 -39
- package/examples/rule-test-fixtures/README.md +0 -67
- package/examples/rule-test-fixtures/rules/C006_function_naming/clean/typescript-clean.ts +0 -64
- package/examples/rule-test-fixtures/rules/C006_function_naming/violations/dart-violations.dart +0 -56
- package/examples/rule-test-fixtures/rules/C006_function_naming/violations/typescript-violations.ts +0 -47
- package/examples/rule-test-fixtures/rules/C019_log_level_usage/clean/typescript-clean.ts +0 -93
- package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/dart-violations.dart +0 -75
- package/examples/rule-test-fixtures/rules/C019_log_level_usage/violations/typescript-violations.ts +0 -84
- package/examples/rule-test-fixtures/rules/C029_catch_block_logging/clean/typescript-clean.ts +0 -0
- package/examples/rule-test-fixtures/rules/C029_catch_block_logging/violations/typescript-violations.ts +0 -37
package/cli-legacy.js
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* LEGACY CLI - DO NOT USE
|
|
5
|
-
* This is the old monolithic CLI implementation kept for reference only.
|
|
6
|
-
* Use cli.js instead - it has the new modular architecture with ESLint integration.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { Command } = require('commander');
|
|
10
|
-
const chalk = require('chalk');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const fs = require('fs');
|
|
13
|
-
const MultiRuleRunner = require('./core/multi-rule-runner');
|
|
14
|
-
const ConfigManager = require('./core/config-manager');
|
|
15
|
-
const ReportGenerator = require('./core/report-generator');
|
|
16
|
-
const { version } = require('./package.json');
|
|
17
|
-
|
|
18
|
-
const program = new Command();
|
|
19
|
-
|
|
20
|
-
program
|
|
21
|
-
.name('sunlint')
|
|
22
|
-
.description('☀️ Sun Lint - Coding Standards Checker | Multi-rule Quality & Security Analysis')
|
|
23
|
-
.version(version);
|
|
24
|
-
|
|
25
|
-
// Rule selection
|
|
26
|
-
program
|
|
27
|
-
.option('-r, --rule <rule>', 'Run single rule (e.g., C019)')
|
|
28
|
-
.option('-R, --rules <rules>', 'Run multiple rules (e.g., C019,C006,C021)')
|
|
29
|
-
.option('-a, --all', 'Run all available rules')
|
|
30
|
-
.option('-c, --category <category>', 'Run rules by category (quality,security,logging,naming)')
|
|
31
|
-
.option('--quality', 'Run all code quality rules')
|
|
32
|
-
.option('--security', 'Run all secure coding rules')
|
|
33
|
-
.option('--preset <preset>', 'Use predefined rule preset (recommended,strict,beginner)')
|
|
34
|
-
|
|
35
|
-
// Input/Output
|
|
36
|
-
.option('-i, --input <path>', 'Input file or directory to analyze', 'src')
|
|
37
|
-
.option('-f, --format <format>', 'Output format (eslint,json,summary,table)', 'eslint')
|
|
38
|
-
.option('-o, --output <file>', 'Output file path')
|
|
39
|
-
.option('--config <file>', 'Configuration file path', '.sunlint.json')
|
|
40
|
-
|
|
41
|
-
// CI/CD and Git integration
|
|
42
|
-
.option('--changed-files', 'Only analyze files changed in current branch (git diff)')
|
|
43
|
-
.option('--staged-files', 'Only analyze staged files (git diff --cached)')
|
|
44
|
-
.option('--diff-base <ref>', 'Compare against specific git reference (e.g., origin/main)')
|
|
45
|
-
.option('--since <commit>', 'Only analyze files changed since specific commit')
|
|
46
|
-
.option('--pr-mode', 'Enable PR mode (changed files + baseline comparison)')
|
|
47
|
-
.option('--baseline <file>', 'Load baseline results to compare against')
|
|
48
|
-
.option('--save-baseline <file>', 'Save current results as baseline')
|
|
49
|
-
.option('--fail-on-new-violations', 'Exit with error only on new violations (not existing)')
|
|
50
|
-
|
|
51
|
-
// Rule control
|
|
52
|
-
.option('--exclude-rules <rules>', 'Exclude specific rules (e.g., C019,C006)')
|
|
53
|
-
.option('--include-rules <rules>', 'Include only specific rules (e.g., C019,C006)')
|
|
54
|
-
.option('--disable-rule <rule>', 'Disable specific rule')
|
|
55
|
-
.option('--enable-rule <rule>', 'Enable specific rule')
|
|
56
|
-
.option('--severity <level>', 'Minimum severity level (error,warning,info)', 'info')
|
|
57
|
-
.option('--languages <langs>', 'Target languages (typescript,dart,kotlin)')
|
|
58
|
-
|
|
59
|
-
// Advanced options
|
|
60
|
-
.option('--ai', 'Enable AI-powered analysis')
|
|
61
|
-
.option('--no-ai', 'Force disable AI analysis (use heuristic only)')
|
|
62
|
-
.option('--no-cache', 'Disable result caching')
|
|
63
|
-
.option('--max-concurrent <n>', 'Maximum concurrent rule execution', '5')
|
|
64
|
-
.option('--timeout <ms>', 'Timeout for rule execution (ms)', '30000')
|
|
65
|
-
.option('--fix', 'Auto-fix issues when possible')
|
|
66
|
-
.option('--dry-run', 'Show what would be analyzed without running')
|
|
67
|
-
.option('--verbose', 'Enable verbose logging')
|
|
68
|
-
.option('--quiet', 'Suppress non-error output')
|
|
69
|
-
.option('--debug', 'Enable debug mode');
|
|
70
|
-
|
|
71
|
-
program.action(async (options) => {
|
|
72
|
-
try {
|
|
73
|
-
// Sun Lint banner
|
|
74
|
-
console.log(chalk.yellow.bold('☀️ Sun Lint - Coding Standards Checker'));
|
|
75
|
-
console.log(chalk.gray(`Version: ${version} | Sun* Engineering`));
|
|
76
|
-
|
|
77
|
-
if (options.debug) {
|
|
78
|
-
console.log(chalk.yellow('Debug mode enabled'));
|
|
79
|
-
console.log('Options:', options);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Handle quality/security shortcuts
|
|
83
|
-
if (options.quality) {
|
|
84
|
-
options.category = 'quality';
|
|
85
|
-
}
|
|
86
|
-
if (options.security) {
|
|
87
|
-
options.category = 'security';
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Load configuration
|
|
91
|
-
const configManager = new ConfigManager();
|
|
92
|
-
const config = await configManager.loadConfig(options.config, options);
|
|
93
|
-
|
|
94
|
-
if (options.verbose) {
|
|
95
|
-
console.log(chalk.gray('Configuration loaded:'), config);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Validate input
|
|
99
|
-
if (!fs.existsSync(options.input)) {
|
|
100
|
-
console.error(chalk.red(`❌ Input path not found: ${options.input}`));
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Show dry run info
|
|
105
|
-
if (options.dryRun) {
|
|
106
|
-
console.log(chalk.yellow('🔍 Dry run mode - Analysis preview:'));
|
|
107
|
-
await showDryRunPreview(config, options);
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// Initialize multi-rule runner
|
|
112
|
-
const runner = new MultiRuleRunner(config, options);
|
|
113
|
-
|
|
114
|
-
// Get rules to run
|
|
115
|
-
const rulesToRun = await getRulesToRun(config, options);
|
|
116
|
-
|
|
117
|
-
if (rulesToRun.length === 0) {
|
|
118
|
-
console.log(chalk.yellow('⚠️ No rules to run'));
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (!options.quiet) {
|
|
123
|
-
const rulesByCategory = categorizeRules(rulesToRun);
|
|
124
|
-
console.log(chalk.green(`🚀 Running ${rulesToRun.length} rules on: ${options.input}`));
|
|
125
|
-
|
|
126
|
-
if (rulesByCategory.quality.length > 0) {
|
|
127
|
-
console.log(chalk.blue(` 📋 Quality rules: ${rulesByCategory.quality.map(r => r.id).join(', ')}`));
|
|
128
|
-
}
|
|
129
|
-
if (rulesByCategory.security.length > 0) {
|
|
130
|
-
console.log(chalk.red(` 🔒 Security rules: ${rulesByCategory.security.map(r => r.id).join(', ')}`));
|
|
131
|
-
}
|
|
132
|
-
if (rulesByCategory.other.length > 0) {
|
|
133
|
-
console.log(chalk.gray(` ⚙️ Other rules: ${rulesByCategory.other.map(r => r.id).join(', ')}`));
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Run analysis
|
|
138
|
-
const startTime = Date.now();
|
|
139
|
-
const results = await runner.runRules(rulesToRun, options.input, options);
|
|
140
|
-
const duration = Date.now() - startTime;
|
|
141
|
-
|
|
142
|
-
// Generate report
|
|
143
|
-
const reportGenerator = new ReportGenerator(config, options);
|
|
144
|
-
const report = await reportGenerator.generateReport(results, {
|
|
145
|
-
duration,
|
|
146
|
-
rulesRun: rulesToRun.length,
|
|
147
|
-
filesAnalyzed: results.filesAnalyzed || 0
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// Output results
|
|
151
|
-
await outputResults(report, options);
|
|
152
|
-
|
|
153
|
-
// Exit with appropriate code
|
|
154
|
-
const allResults = results.results || [];
|
|
155
|
-
const hasErrors = allResults.some(r =>
|
|
156
|
-
r.violations && r.violations.some(v => v.severity === 'error')
|
|
157
|
-
);
|
|
158
|
-
process.exit(hasErrors ? 1 : 0);
|
|
159
|
-
|
|
160
|
-
} catch (error) {
|
|
161
|
-
console.error(chalk.red('❌ Sun Lint Error:'), error.message);
|
|
162
|
-
if (options.debug) {
|
|
163
|
-
console.error(error.stack);
|
|
164
|
-
}
|
|
165
|
-
process.exit(1);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
async function getRulesToRun(config, options) {
|
|
170
|
-
const allRules = config.rules || {};
|
|
171
|
-
const rulesRegistry = require('./config/rules-registry.json');
|
|
172
|
-
|
|
173
|
-
let selectedRules = [];
|
|
174
|
-
|
|
175
|
-
if (options.rule) {
|
|
176
|
-
// Single rule
|
|
177
|
-
selectedRules = [options.rule];
|
|
178
|
-
} else if (options.rules) {
|
|
179
|
-
// Multiple rules
|
|
180
|
-
selectedRules = options.rules.split(',').map(r => r.trim());
|
|
181
|
-
} else if (options.all) {
|
|
182
|
-
// All rules
|
|
183
|
-
selectedRules = Object.keys(rulesRegistry.rules);
|
|
184
|
-
} else if (options.category) {
|
|
185
|
-
// Rules by category
|
|
186
|
-
const category = rulesRegistry.categories[options.category];
|
|
187
|
-
if (category && category.rules) {
|
|
188
|
-
selectedRules = category.rules;
|
|
189
|
-
}
|
|
190
|
-
} else if (options.preset) {
|
|
191
|
-
// Load preset using ConfigManager
|
|
192
|
-
try {
|
|
193
|
-
const ConfigManager = require('./core/config-manager');
|
|
194
|
-
const configManager = new ConfigManager();
|
|
195
|
-
|
|
196
|
-
const presetName = options.preset.startsWith('@sun/sunlint/')
|
|
197
|
-
? options.preset
|
|
198
|
-
: `@sun/sunlint/${options.preset}`;
|
|
199
|
-
const presetConfig = await configManager.loadPreset(presetName);
|
|
200
|
-
if (presetConfig && presetConfig.rules) {
|
|
201
|
-
selectedRules = Object.keys(presetConfig.rules).filter(ruleId =>
|
|
202
|
-
presetConfig.rules[ruleId] !== 'off' && presetConfig.rules[ruleId] !== false
|
|
203
|
-
);
|
|
204
|
-
console.log(chalk.blue(`🎯 Using preset: ${presetName}`));
|
|
205
|
-
}
|
|
206
|
-
} catch (error) {
|
|
207
|
-
console.error(chalk.red(`❌ Failed to load preset '${options.preset}':`), error.message);
|
|
208
|
-
process.exit(1);
|
|
209
|
-
}
|
|
210
|
-
} else {
|
|
211
|
-
// Default: use config rules
|
|
212
|
-
selectedRules = Object.keys(allRules).filter(ruleId =>
|
|
213
|
-
allRules[ruleId] !== 'off' && allRules[ruleId] !== false
|
|
214
|
-
);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// Filter out excluded rules
|
|
218
|
-
if (options.excludeRules) {
|
|
219
|
-
const excludedRules = options.excludeRules.split(',').map(r => r.trim());
|
|
220
|
-
selectedRules = selectedRules.filter(rule => !excludedRules.includes(rule));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Filter by severity
|
|
224
|
-
if (options.severity) {
|
|
225
|
-
const minSeverity = options.severity;
|
|
226
|
-
const severityLevels = { info: 0, warning: 1, error: 2 };
|
|
227
|
-
const minLevel = severityLevels[minSeverity] || 0;
|
|
228
|
-
|
|
229
|
-
selectedRules = selectedRules.filter(ruleId => {
|
|
230
|
-
const rule = rulesRegistry.rules[ruleId];
|
|
231
|
-
if (!rule) return false;
|
|
232
|
-
const ruleLevel = severityLevels[rule.severity] || 0;
|
|
233
|
-
return ruleLevel >= minLevel;
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Filter by languages
|
|
238
|
-
if (options.languages) {
|
|
239
|
-
const targetLanguages = options.languages.split(',').map(l => l.trim());
|
|
240
|
-
selectedRules = selectedRules.filter(ruleId => {
|
|
241
|
-
const rule = rulesRegistry.rules[ruleId];
|
|
242
|
-
if (!rule) return false;
|
|
243
|
-
return rule.languages.some(lang => targetLanguages.includes(lang));
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// Convert to rule objects
|
|
248
|
-
return selectedRules.map(ruleId => ({
|
|
249
|
-
id: ruleId,
|
|
250
|
-
...rulesRegistry.rules[ruleId]
|
|
251
|
-
})).filter(rule => rule.name); // Filter out invalid rules
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
function categorizeRules(rules) {
|
|
255
|
-
const categories = {
|
|
256
|
-
quality: [],
|
|
257
|
-
security: [],
|
|
258
|
-
other: []
|
|
259
|
-
};
|
|
260
|
-
|
|
261
|
-
rules.forEach(rule => {
|
|
262
|
-
if (rule.category === 'security' || rule.id.startsWith('S')) {
|
|
263
|
-
categories.security.push(rule);
|
|
264
|
-
} else if (['logging', 'naming', 'validation', 'design'].includes(rule.category)) {
|
|
265
|
-
categories.quality.push(rule);
|
|
266
|
-
} else {
|
|
267
|
-
categories.other.push(rule);
|
|
268
|
-
}
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
return categories;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
async function showDryRunPreview(config, options) {
|
|
275
|
-
const rulesToRun = await getRulesToRun(config, options);
|
|
276
|
-
const rulesByCategory = categorizeRules(rulesToRun);
|
|
277
|
-
|
|
278
|
-
console.log(chalk.blue('📋 Sun Lint Analysis Preview:'));
|
|
279
|
-
console.log(chalk.gray(`Input: ${options.input}`));
|
|
280
|
-
console.log(chalk.gray(`Format: ${options.format}`));
|
|
281
|
-
console.log(chalk.gray(`Rules to run: ${rulesToRun.length}`));
|
|
282
|
-
|
|
283
|
-
if (rulesByCategory.quality.length > 0) {
|
|
284
|
-
console.log(chalk.blue('📋 Quality Rules:'));
|
|
285
|
-
rulesByCategory.quality.forEach(rule => {
|
|
286
|
-
console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (rulesByCategory.security.length > 0) {
|
|
291
|
-
console.log(chalk.red('🔒 Security Rules:'));
|
|
292
|
-
rulesByCategory.security.forEach(rule => {
|
|
293
|
-
console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (rulesByCategory.other.length > 0) {
|
|
298
|
-
console.log(chalk.white('⚙️ Other Rules:'));
|
|
299
|
-
rulesByCategory.other.forEach(rule => {
|
|
300
|
-
console.log(` ${chalk.cyan(rule.id)}: ${rule.name} (${rule.severity})`);
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
async function outputResults(report, options) {
|
|
306
|
-
// Console output
|
|
307
|
-
if (!options.quiet) {
|
|
308
|
-
console.log(report.formatted);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
// File output
|
|
312
|
-
if (options.output) {
|
|
313
|
-
fs.writeFileSync(options.output, JSON.stringify(report.raw, null, 2));
|
|
314
|
-
console.log(chalk.green(`📄 Report saved to: ${options.output}`));
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Summary
|
|
318
|
-
if (report.summary && !options.quiet) {
|
|
319
|
-
console.log(chalk.blue('\n📊 Sun Lint Summary:'));
|
|
320
|
-
console.log(report.summary);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Error handling
|
|
325
|
-
process.on('unhandledRejection', (reason, promise) => {
|
|
326
|
-
console.error(chalk.red('Sun Lint - Unhandled Rejection:'), promise, chalk.red('reason:'), reason);
|
|
327
|
-
process.exit(1);
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
process.on('uncaughtException', (error) => {
|
|
331
|
-
console.error(chalk.red('Sun Lint - Uncaught Exception:'), error);
|
|
332
|
-
process.exit(1);
|
|
333
|
-
});
|
|
334
|
-
|
|
335
|
-
// Help examples
|
|
336
|
-
program.addHelpText('after', `
|
|
337
|
-
Examples:
|
|
338
|
-
$ sunlint --rule=C019 --input=src
|
|
339
|
-
$ sunlint --rules=C019,C006 --input=src --format=json
|
|
340
|
-
$ sunlint --all --input=src --format=summary
|
|
341
|
-
$ sunlint --quality --input=src
|
|
342
|
-
$ sunlint --security --input=src
|
|
343
|
-
$ sunlint --category=logging --input=src
|
|
344
|
-
$ sunlint --preset=recommended --input=src
|
|
345
|
-
$ sunlint --config=.sunlint.json --input=src
|
|
346
|
-
$ sunlint --rule=C019 --input=src --output=report.json
|
|
347
|
-
$ sunlint --all --input=src --exclude-rules=C006,C031
|
|
348
|
-
$ sunlint --rule=C019 --input=src --ai
|
|
349
|
-
$ sunlint --rule=C019 --input=src --no-ai
|
|
350
|
-
$ sunlint --all --input=src --severity=error --ai
|
|
351
|
-
|
|
352
|
-
Sun* Engineering - Coding Standards Made Simple ☀️
|
|
353
|
-
`);
|
|
354
|
-
|
|
355
|
-
program.parse();
|
package/docs/AI.md
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
# 🤖 AI-Powered Analysis
|
|
2
|
-
|
|
3
|
-
Sunlint supports AI-powered code analysis alongside traditional pattern-based analysis for more intelligent and context-aware rule checking.
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
- **🎯 Smart Analysis**: Uses AI to understand code context and intent
|
|
8
|
-
- **🔄 Fallback Strategy**: Automatically falls back to pattern analysis if AI fails
|
|
9
|
-
- **⚡ Performance**: AI analysis runs per-file with caching support
|
|
10
|
-
- **🔧 Configurable**: Multiple AI providers and models supported
|
|
11
|
-
|
|
12
|
-
## Configuration
|
|
13
|
-
|
|
14
|
-
### In `.sunlint.json`:
|
|
15
|
-
|
|
16
|
-
```json
|
|
17
|
-
{
|
|
18
|
-
"ai": {
|
|
19
|
-
"enabled": true,
|
|
20
|
-
"provider": "openai",
|
|
21
|
-
"model": "gpt-4o-mini",
|
|
22
|
-
"apiKey": "${OPENAI_API_KEY}",
|
|
23
|
-
"fallbackToPattern": true
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Environment Variables:
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
export OPENAI_API_KEY="your-openai-api-key"
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
## Supported Providers
|
|
35
|
-
|
|
36
|
-
### OpenAI
|
|
37
|
-
- **Models**: `gpt-4`, `gpt-4o-mini`, `gpt-3.5-turbo`
|
|
38
|
-
- **API Key**: Required via `OPENAI_API_KEY` environment variable
|
|
39
|
-
- **Cost**: Pay-per-use based on OpenAI pricing
|
|
40
|
-
|
|
41
|
-
### GitHub Copilot (Planned)
|
|
42
|
-
- **Integration**: VS Code extension integration
|
|
43
|
-
- **Models**: GitHub Copilot models
|
|
44
|
-
- **Authentication**: VS Code Copilot session
|
|
45
|
-
|
|
46
|
-
## AI-Enhanced Rules
|
|
47
|
-
|
|
48
|
-
### C019 - Log Level Usage
|
|
49
|
-
✅ **AI-Enabled**: Understands code context to determine appropriate log levels
|
|
50
|
-
|
|
51
|
-
**AI Analysis Features:**
|
|
52
|
-
- **Context Understanding**: Analyzes surrounding code to determine error criticality
|
|
53
|
-
- **Intent Recognition**: Understands whether errors are expected or exceptional
|
|
54
|
-
- **Semantic Analysis**: Goes beyond pattern matching to understand meaning
|
|
55
|
-
|
|
56
|
-
**Example:**
|
|
57
|
-
```typescript
|
|
58
|
-
// AI understands this is a validation error, suggests warn level
|
|
59
|
-
if (!user.email) {
|
|
60
|
-
console.error('Missing email'); // AI: Should use console.warn()
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// AI understands this is a critical system error, keeps error level
|
|
64
|
-
try {
|
|
65
|
-
await database.connect();
|
|
66
|
-
} catch (error) {
|
|
67
|
-
console.error('Database connection failed:', error); // AI: Appropriate error level
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Usage
|
|
72
|
-
|
|
73
|
-
### CLI Commands
|
|
74
|
-
|
|
75
|
-
**Enable AI for specific rule:**
|
|
76
|
-
```bash
|
|
77
|
-
sunlint --rule=C019 --input=src --ai
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
**Enable AI for all rules:**
|
|
81
|
-
```bash
|
|
82
|
-
sunlint --quality --input=src --ai
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
**Debug AI analysis:**
|
|
86
|
-
```bash
|
|
87
|
-
sunlint --rule=C019 --input=src --ai --verbose
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### VS Code Integration
|
|
91
|
-
|
|
92
|
-
1. **Debug Configuration**: Use "Debug Sunlint - AI Analysis"
|
|
93
|
-
2. **Task**: Run "Sunlint: AI Analysis Test"
|
|
94
|
-
3. **Set API Key**: Configure `OPENAI_API_KEY` in environment
|
|
95
|
-
|
|
96
|
-
## Output Differences
|
|
97
|
-
|
|
98
|
-
### Pattern Analysis Output:
|
|
99
|
-
```
|
|
100
|
-
WARNING: Error log level used for non-critical issue - should use warn/info level
|
|
101
|
-
at src/user.ts:15:5 (C019)
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### AI Analysis Output:
|
|
105
|
-
```
|
|
106
|
-
WARNING: Email validation error should use console.warn() - this is user input validation, not a system error
|
|
107
|
-
at src/user.ts:15:5 (C019)
|
|
108
|
-
Suggestion: Change to console.warn('User email validation failed:', email)
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Performance Considerations
|
|
112
|
-
|
|
113
|
-
- **Caching**: AI responses are cached per file content hash
|
|
114
|
-
- **Concurrency**: AI calls are made concurrently with rate limiting
|
|
115
|
-
- **Timeout**: 30-second timeout per AI request
|
|
116
|
-
- **Cost**: Monitor API usage in OpenAI dashboard
|
|
117
|
-
|
|
118
|
-
## Troubleshooting
|
|
119
|
-
|
|
120
|
-
### Common Issues
|
|
121
|
-
|
|
122
|
-
**API Key Not Found:**
|
|
123
|
-
```bash
|
|
124
|
-
⚠️ AI API key not found, falling back to pattern analysis
|
|
125
|
-
```
|
|
126
|
-
Solution: Set `OPENAI_API_KEY` environment variable
|
|
127
|
-
|
|
128
|
-
**API Rate Limit:**
|
|
129
|
-
```bash
|
|
130
|
-
AI Analysis failed: OpenAI API error: 429 Too Many Requests
|
|
131
|
-
```
|
|
132
|
-
Solution: Reduce `maxConcurrentRules` in config or wait
|
|
133
|
-
|
|
134
|
-
**Network Issues:**
|
|
135
|
-
```bash
|
|
136
|
-
AI Analysis failed: OpenAI API error: Network timeout
|
|
137
|
-
```
|
|
138
|
-
Solution: Check internet connection, increase `timeoutMs`
|
|
139
|
-
|
|
140
|
-
### Debug AI Issues
|
|
141
|
-
|
|
142
|
-
1. **Enable verbose mode**: `--verbose`
|
|
143
|
-
2. **Check API key**: `echo $OPENAI_API_KEY`
|
|
144
|
-
3. **Test connection**: Use debug configuration
|
|
145
|
-
4. **Check API quota**: Visit OpenAI dashboard
|
|
146
|
-
|
|
147
|
-
## Future Enhancements
|
|
148
|
-
|
|
149
|
-
- **🔄 GitHub Copilot Integration**: Direct integration with VS Code Copilot
|
|
150
|
-
- **📊 Custom Models**: Support for fine-tuned models
|
|
151
|
-
- **🎯 Rule-Specific Prompts**: Specialized prompts per rule type
|
|
152
|
-
- **💾 Smart Caching**: Semantic caching across similar code patterns
|
|
153
|
-
- **📈 Analytics**: AI vs Pattern analysis effectiveness metrics
|
|
154
|
-
|
|
155
|
-
## Cost Estimation
|
|
156
|
-
|
|
157
|
-
**OpenAI API Costs** (approximate):
|
|
158
|
-
- **gpt-4o-mini**: ~$0.001 per 1K tokens
|
|
159
|
-
- **gpt-4**: ~$0.03 per 1K tokens
|
|
160
|
-
- **Average file**: ~500 tokens
|
|
161
|
-
- **1000 files with gpt-4o-mini**: ~$0.50
|
|
162
|
-
|
|
163
|
-
**Recommendation**: Start with `gpt-4o-mini` for cost-effectiveness.
|
package/docs/ARCHITECTURE.md
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# SunLint Modular Architecture
|
|
2
|
-
|
|
3
|
-
## Phase 1: TypeScript Focus với Kiến trúc Modular
|
|
4
|
-
|
|
5
|
-
### Cấu trúc mới:
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
cli.js # CLI entry point (simplified)
|
|
9
|
-
core/
|
|
10
|
-
├── cli-program.js # CLI options definition (Rule C005)
|
|
11
|
-
├── cli-action-handler.js # Main execution flow (Rule C005)
|
|
12
|
-
├── rule-selection-service.js # Rule selection logic (Rule C005)
|
|
13
|
-
├── analysis-orchestrator.js # Analysis coordination (Rule C005)
|
|
14
|
-
├── output-service.js # Output formatting (Rule C005)
|
|
15
|
-
├── eslint-engine-service.js # ESLint integration (future)
|
|
16
|
-
└── sunlint-engine-service.js # Native SunLint engine
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### Nguyên tắc thiết kế:
|
|
20
|
-
|
|
21
|
-
1. **Rule C005**: Mỗi class/file chỉ làm một việc
|
|
22
|
-
2. **Rule C014**: Dependency injection thay vì new trực tiếp
|
|
23
|
-
3. **Rule C012**: Tách rõ Command và Query
|
|
24
|
-
4. **Modular**: Dễ mở rộng cho Phase 2
|
|
25
|
-
|
|
26
|
-
### Luồng hoạt động:
|
|
27
|
-
|
|
28
|
-
1. `cli.js` → `CliActionHandler`
|
|
29
|
-
2. `CliActionHandler` → Load config, validate input
|
|
30
|
-
3. `RuleSelectionService` → Select rules based on options
|
|
31
|
-
4. `AnalysisOrchestrator` → Run analysis (SunLint or ESLint)
|
|
32
|
-
5. `OutputService` → Format and display results
|
|
33
|
-
|
|
34
|
-
### Các tính năng hiện tại:
|
|
35
|
-
|
|
36
|
-
- ✅ Modular CLI với dependency injection
|
|
37
|
-
- ✅ Rule selection (single, multiple, all, category)
|
|
38
|
-
- ✅ Dry run mode
|
|
39
|
-
- ✅ TypeScript-specific options (chuẩn bị cho Phase 1)
|
|
40
|
-
- ✅ Graceful fallback khi không tìm thấy dependencies
|
|
41
|
-
- ✅ Clean error handling và logging
|
|
42
|
-
|
|
43
|
-
### Phase 1 roadmap:
|
|
44
|
-
|
|
45
|
-
1. **✅ Done**: Modular CLI architecture
|
|
46
|
-
2. **✅ Done**: ESLint integration cho TypeScript
|
|
47
|
-
3. **Next**: TypeScript custom rules thông qua ESLint
|
|
48
|
-
4. **✅ Done**: Hybrid engine (ESLint + SunLint)
|
|
49
|
-
|
|
50
|
-
### Phase 2 roadmap:
|
|
51
|
-
|
|
52
|
-
1. Native SunLint engine cho tất cả ngôn ngữ
|
|
53
|
-
2. Mở rộng Dart, Kotlin rules
|
|
54
|
-
3. AI-powered analysis
|
|
55
|
-
4. VS Code extension integration
|
|
56
|
-
|
|
57
|
-
### Usage Examples:
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
# Basic usage
|
|
61
|
-
sunlint --rule=C006 --input=src
|
|
62
|
-
|
|
63
|
-
# Category-based
|
|
64
|
-
sunlint --quality --input=src
|
|
65
|
-
|
|
66
|
-
# TypeScript-specific (Phase 1)
|
|
67
|
-
sunlint --typescript --input=src
|
|
68
|
-
sunlint --typescript-engine=eslint --input=src
|
|
69
|
-
|
|
70
|
-
# Dry run
|
|
71
|
-
sunlint --dry-run --all --input=src
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Dependencies:
|
|
75
|
-
|
|
76
|
-
- Minimal core dependencies
|
|
77
|
-
- ESLint integration sẽ được thêm trong Phase 1
|
|
78
|
-
- Graceful fallback khi dependencies không có sẵn
|