@sun-asterisk/sunlint 1.3.10 → 1.3.12
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 +99 -1
- package/README.md +62 -0
- package/core/cli-action-handler.js +30 -1
- package/core/cli-program.js +4 -0
- package/core/output-service.js +160 -3
- package/core/scoring-service.js +169 -0
- package/core/summary-report-service.js +319 -0
- package/core/upload-service.js +282 -0
- package/docs/API_FORMAT_GUIDE.md +370 -0
- package/docs/QUALITY_SCORING_GUIDE.md +409 -0
- package/package.json +1 -1
- package/rules/common/C023_no_duplicate_variable/symbol-based-analyzer.js +21 -22
- package/docs/AI.md +0 -163
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# Quality Scoring & Summary Report Guide
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
SunLint includes a comprehensive quality scoring system and summary report generation feature designed for CI/CD integration and management dashboards.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
### 1. Quality Scoring System
|
|
10
|
+
|
|
11
|
+
The quality score is calculated based on multiple factors:
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
Score Formula: 100 - (errorCount × 5 + warningCount × 1) × (1000 / LOC) + (rulesChecked × 0.5)
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Scoring Components:**
|
|
18
|
+
- **Base Score**: Starts at 100 (perfect quality)
|
|
19
|
+
- **Error Penalty**: -5 points per error
|
|
20
|
+
- **Warning Penalty**: -1 point per warning
|
|
21
|
+
- **LOC Normalization**: Violations are normalized per 1000 lines of code
|
|
22
|
+
- **Rule Bonus**: +0.5 points per rule checked (max 10 points)
|
|
23
|
+
- **Final Range**: 0-100
|
|
24
|
+
|
|
25
|
+
**Grade Scale:**
|
|
26
|
+
- **A+**: 95-100
|
|
27
|
+
- **A**: 90-94
|
|
28
|
+
- **B+**: 85-89
|
|
29
|
+
- **B**: 80-84
|
|
30
|
+
- **C+**: 75-79
|
|
31
|
+
- **C**: 70-74
|
|
32
|
+
- **D**: 60-69
|
|
33
|
+
- **F**: Below 60
|
|
34
|
+
|
|
35
|
+
### 2. Summary Report Format
|
|
36
|
+
|
|
37
|
+
The summary report is generated in JSON format, designed for easy integration with CI/CD pipelines and management dashboards.
|
|
38
|
+
|
|
39
|
+
**Example Output:**
|
|
40
|
+
```json
|
|
41
|
+
{
|
|
42
|
+
"metadata": {
|
|
43
|
+
"generated_at": "2025-10-07T03:48:00.636Z",
|
|
44
|
+
"tool": "SunLint",
|
|
45
|
+
"version": "1.3.9",
|
|
46
|
+
"analysis_duration_ms": 390
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"repository_url": "https://github.com/org/repo",
|
|
50
|
+
"branch": "main",
|
|
51
|
+
"commit_hash": "abc123"
|
|
52
|
+
},
|
|
53
|
+
"quality": {
|
|
54
|
+
"score": 98.9,
|
|
55
|
+
"grade": "A+",
|
|
56
|
+
"metrics": {
|
|
57
|
+
"errors": 0,
|
|
58
|
+
"warnings": 520,
|
|
59
|
+
"rulesChecked": 1,
|
|
60
|
+
"linesOfCode": 319709,
|
|
61
|
+
"violationsPerKLOC": 1.6
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"violations": {
|
|
65
|
+
"total": 520,
|
|
66
|
+
"by_severity": {
|
|
67
|
+
"errors": 0,
|
|
68
|
+
"warnings": 520
|
|
69
|
+
},
|
|
70
|
+
"by_rule": [
|
|
71
|
+
{
|
|
72
|
+
"rule_code": "C065",
|
|
73
|
+
"count": 520,
|
|
74
|
+
"severity": "warning"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
"analysis": {
|
|
79
|
+
"files_analyzed": 1000,
|
|
80
|
+
"rules_checked": 1,
|
|
81
|
+
"lines_of_code": 319709
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
### Basic Usage
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Generate summary report only
|
|
92
|
+
node cli.js --input=src --rule=C065 --output-summary=summary.json
|
|
93
|
+
|
|
94
|
+
# Generate both detailed report and summary report
|
|
95
|
+
node cli.js --input=src --rule=C065 --output=report.txt --output-summary=summary.json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### CI/CD Integration
|
|
99
|
+
|
|
100
|
+
#### GitHub Actions Example
|
|
101
|
+
|
|
102
|
+
```yaml
|
|
103
|
+
name: Code Quality Check
|
|
104
|
+
|
|
105
|
+
on:
|
|
106
|
+
pull_request:
|
|
107
|
+
branches: [ main ]
|
|
108
|
+
push:
|
|
109
|
+
branches: [ main ]
|
|
110
|
+
|
|
111
|
+
jobs:
|
|
112
|
+
quality-check:
|
|
113
|
+
runs-on: ubuntu-latest
|
|
114
|
+
|
|
115
|
+
steps:
|
|
116
|
+
- uses: actions/checkout@v3
|
|
117
|
+
|
|
118
|
+
- name: Setup Node.js
|
|
119
|
+
uses: actions/setup-node@v3
|
|
120
|
+
with:
|
|
121
|
+
node-version: '18'
|
|
122
|
+
|
|
123
|
+
- name: Install dependencies
|
|
124
|
+
run: npm install
|
|
125
|
+
|
|
126
|
+
- name: Run SunLint Analysis
|
|
127
|
+
run: |
|
|
128
|
+
node cli.js \
|
|
129
|
+
--input=src \
|
|
130
|
+
--rule=C001,C005,C015,C065 \
|
|
131
|
+
--output-summary=quality-report.json
|
|
132
|
+
env:
|
|
133
|
+
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
134
|
+
GITHUB_REF_NAME: ${{ github.ref_name }}
|
|
135
|
+
GITHUB_SHA: ${{ github.sha }}
|
|
136
|
+
|
|
137
|
+
- name: Upload Quality Report
|
|
138
|
+
uses: actions/upload-artifact@v3
|
|
139
|
+
with:
|
|
140
|
+
name: quality-report
|
|
141
|
+
path: quality-report.json
|
|
142
|
+
|
|
143
|
+
- name: Post to Dashboard
|
|
144
|
+
run: |
|
|
145
|
+
curl -X POST https://your-dashboard.com/api/quality \
|
|
146
|
+
-H "Content-Type: application/json" \
|
|
147
|
+
-H "Authorization: Bearer ${{ secrets.DASHBOARD_TOKEN }}" \
|
|
148
|
+
-d @quality-report.json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Environment Variables
|
|
152
|
+
|
|
153
|
+
The summary report automatically detects and uses Git information from environment variables (commonly available in CI/CD):
|
|
154
|
+
|
|
155
|
+
| Variable | Description | Source | Fallback |
|
|
156
|
+
|----------|-------------|--------|----------|
|
|
157
|
+
| `GITHUB_REPOSITORY` | Repository name (e.g., `owner/repo`) | GitHub Actions | Git remote URL |
|
|
158
|
+
| `GITHUB_REF_NAME` | Branch or tag name | GitHub Actions | `git rev-parse --abbrev-ref HEAD` |
|
|
159
|
+
| `GITHUB_SHA` | Commit hash | GitHub Actions | `git rev-parse HEAD` |
|
|
160
|
+
| `GITHUB_EVENT_PATH` | Path to event payload JSON | GitHub Actions | - |
|
|
161
|
+
| `GITHUB_EVENT_HEAD_COMMIT_MESSAGE` | Commit message | GitHub Actions | `git log -1 --pretty=%B` |
|
|
162
|
+
| `GITHUB_EVENT_HEAD_COMMIT_AUTHOR_EMAIL` | Author email | GitHub Actions | `git log -1 --pretty=%ae` |
|
|
163
|
+
| `GITHUB_EVENT_HEAD_COMMIT_AUTHOR_NAME` | Author name | GitHub Actions | `git log -1 --pretty=%an` |
|
|
164
|
+
|
|
165
|
+
**Additional Fields Auto-Detected:**
|
|
166
|
+
- **`repository_name`**: Extracted from repository URL
|
|
167
|
+
- **`project_path`**: Relative path from repo root (for mono-repo support)
|
|
168
|
+
- **`commit_message`**: From git log or GitHub event
|
|
169
|
+
- **`author_email`**: From git log or GitHub event
|
|
170
|
+
- **`author_name`**: From git log or GitHub event
|
|
171
|
+
- **`pr_number`**: Extracted from commit message (e.g., "#123") or branch name (e.g., "pr-123")
|
|
172
|
+
|
|
173
|
+
If environment variables are not available, the tool will automatically detect all Git information from the local repository.
|
|
174
|
+
|
|
175
|
+
## CLI Options
|
|
176
|
+
|
|
177
|
+
### `--output-summary <file>`
|
|
178
|
+
|
|
179
|
+
Generate a summary report in JSON format suitable for CI/CD and management dashboards.
|
|
180
|
+
|
|
181
|
+
**Differences from `--output`:**
|
|
182
|
+
|
|
183
|
+
| Feature | `--output` | `--output-summary` |
|
|
184
|
+
|---------|-----------|-------------------|
|
|
185
|
+
| Format | Text/JSON (ESLint-compatible) | JSON (Custom format) |
|
|
186
|
+
| Detail Level | Full violation details | Summary only |
|
|
187
|
+
| File Size | Large (includes all details) | Small (summary only) |
|
|
188
|
+
| Purpose | Detailed debugging | CI/CD integration |
|
|
189
|
+
| Includes Score | ❌ No | ✅ Yes |
|
|
190
|
+
| Includes LOC | ❌ No | ✅ Yes |
|
|
191
|
+
| Git Info | ❌ No | ✅ Yes |
|
|
192
|
+
| Violation Count by Rule | ❌ No | ✅ Yes |
|
|
193
|
+
|
|
194
|
+
**Example:**
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Detailed report: Shows every violation with line numbers and messages
|
|
198
|
+
node cli.js --input=src --rule=C065 --output=detailed-report.txt
|
|
199
|
+
|
|
200
|
+
# Summary report: Shows total count per rule, score, and metrics
|
|
201
|
+
node cli.js --input=src --rule=C065 --output-summary=summary.json
|
|
202
|
+
|
|
203
|
+
# Both: Get detailed report for debugging + summary for dashboard
|
|
204
|
+
node cli.js --input=src --rule=C065 \
|
|
205
|
+
--output=detailed-report.txt \
|
|
206
|
+
--output-summary=summary.json
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Integration Examples
|
|
210
|
+
|
|
211
|
+
### 1. Send to Management Dashboard
|
|
212
|
+
|
|
213
|
+
```javascript
|
|
214
|
+
const fs = require('fs');
|
|
215
|
+
const axios = require('axios');
|
|
216
|
+
|
|
217
|
+
const report = JSON.parse(fs.readFileSync('summary.json', 'utf8'));
|
|
218
|
+
|
|
219
|
+
await axios.post('https://dashboard.company.com/api/quality', {
|
|
220
|
+
project: 'my-project',
|
|
221
|
+
...report
|
|
222
|
+
}, {
|
|
223
|
+
headers: {
|
|
224
|
+
'Authorization': `Bearer ${process.env.DASHBOARD_TOKEN}`
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 2. Slack Notification
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
const fs = require('fs');
|
|
233
|
+
const axios = require('axios');
|
|
234
|
+
|
|
235
|
+
const report = JSON.parse(fs.readFileSync('summary.json', 'utf8'));
|
|
236
|
+
const { quality, violations, analysis } = report;
|
|
237
|
+
|
|
238
|
+
const message = {
|
|
239
|
+
text: `Code Quality Report: ${quality.grade} (${quality.score})`,
|
|
240
|
+
blocks: [
|
|
241
|
+
{
|
|
242
|
+
type: "section",
|
|
243
|
+
text: {
|
|
244
|
+
type: "mrkdwn",
|
|
245
|
+
text: `*Code Quality Analysis*\n` +
|
|
246
|
+
`Score: *${quality.score}* (${quality.grade})\n` +
|
|
247
|
+
`Violations: ${violations.total} (${violations.by_severity.errors} errors, ${violations.by_severity.warnings} warnings)\n` +
|
|
248
|
+
`Files: ${analysis.files_analyzed} | LOC: ${analysis.lines_of_code.toLocaleString()}`
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
await axios.post(process.env.SLACK_WEBHOOK_URL, message);
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 3. Quality Gate in CI/CD
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
#!/bin/bash
|
|
261
|
+
|
|
262
|
+
# Run analysis
|
|
263
|
+
node cli.js --input=src --rule=C001,C005,C015,C065 --output-summary=quality.json
|
|
264
|
+
|
|
265
|
+
# Extract score
|
|
266
|
+
SCORE=$(jq -r '.quality.score' quality.json)
|
|
267
|
+
|
|
268
|
+
# Set minimum score threshold
|
|
269
|
+
MIN_SCORE=80
|
|
270
|
+
|
|
271
|
+
# Check if score meets threshold
|
|
272
|
+
if (( $(echo "$SCORE < $MIN_SCORE" | bc -l) )); then
|
|
273
|
+
echo "❌ Quality score $SCORE is below threshold $MIN_SCORE"
|
|
274
|
+
exit 1
|
|
275
|
+
else
|
|
276
|
+
echo "✅ Quality score $SCORE meets threshold"
|
|
277
|
+
exit 0
|
|
278
|
+
fi
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Best Practices
|
|
282
|
+
|
|
283
|
+
### 1. Rule Selection
|
|
284
|
+
|
|
285
|
+
Choose rules appropriate for your quality goals:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# Security focus
|
|
289
|
+
node cli.js --input=src --rule=S001,S004,S010 --output-summary=security.json
|
|
290
|
+
|
|
291
|
+
# Code organization focus
|
|
292
|
+
node cli.js --input=src --rule=C001,C005,C006,C015 --output-summary=organization.json
|
|
293
|
+
|
|
294
|
+
# Testing focus
|
|
295
|
+
node cli.js --input=src --rule=C065,C066 --output-summary=testing.json
|
|
296
|
+
|
|
297
|
+
# Comprehensive check (slower)
|
|
298
|
+
node cli.js --input=src --rule=security,cleancode --output-summary=full.json
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 2. Performance Optimization
|
|
302
|
+
|
|
303
|
+
For large projects:
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
# Analyze only changed files (PR mode)
|
|
307
|
+
node cli.js --input=src --rule=C001,C005 --changed-files --output-summary=pr-quality.json
|
|
308
|
+
|
|
309
|
+
# Set file limits for faster analysis
|
|
310
|
+
node cli.js --input=src --rule=C001,C005 --max-files=500 --output-summary=quick-check.json
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 3. Trending Analysis
|
|
314
|
+
|
|
315
|
+
Track quality over time:
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
const fs = require('fs');
|
|
319
|
+
|
|
320
|
+
// Save with timestamp
|
|
321
|
+
const report = JSON.parse(fs.readFileSync('summary.json', 'utf8'));
|
|
322
|
+
const timestamp = new Date().toISOString();
|
|
323
|
+
|
|
324
|
+
// Store in database or time-series storage
|
|
325
|
+
await db.collection('quality_reports').insertOne({
|
|
326
|
+
...report,
|
|
327
|
+
timestamp
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Query trends
|
|
331
|
+
const last30Days = await db.collection('quality_reports')
|
|
332
|
+
.find({
|
|
333
|
+
timestamp: { $gte: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000) }
|
|
334
|
+
})
|
|
335
|
+
.sort({ timestamp: 1 })
|
|
336
|
+
.toArray();
|
|
337
|
+
|
|
338
|
+
// Calculate trend
|
|
339
|
+
const scores = last30Days.map(r => r.quality.score);
|
|
340
|
+
const trend = scores[scores.length - 1] - scores[0];
|
|
341
|
+
console.log(`Quality trend (30 days): ${trend > 0 ? '+' : ''}${trend.toFixed(1)}`);
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
## Scoring Interpretation
|
|
345
|
+
|
|
346
|
+
### Score Ranges
|
|
347
|
+
|
|
348
|
+
- **95-100 (A+)**: Excellent code quality with minimal violations
|
|
349
|
+
- **90-94 (A)**: Very good quality, minor improvements possible
|
|
350
|
+
- **85-89 (B+)**: Good quality with some areas for improvement
|
|
351
|
+
- **80-84 (B)**: Acceptable quality, several improvements recommended
|
|
352
|
+
- **75-79 (C+)**: Below average, significant improvements needed
|
|
353
|
+
- **70-74 (C)**: Poor quality, requires immediate attention
|
|
354
|
+
- **60-69 (D)**: Very poor quality, major refactoring needed
|
|
355
|
+
- **0-59 (F)**: Critical quality issues
|
|
356
|
+
|
|
357
|
+
### Metrics Understanding
|
|
358
|
+
|
|
359
|
+
**Violations per KLOC (Violations per 1000 Lines of Code)**
|
|
360
|
+
|
|
361
|
+
This metric normalizes violations by code size:
|
|
362
|
+
|
|
363
|
+
- **< 1**: Excellent
|
|
364
|
+
- **1-3**: Good
|
|
365
|
+
- **3-5**: Fair
|
|
366
|
+
- **5-10**: Poor
|
|
367
|
+
- **> 10**: Critical
|
|
368
|
+
|
|
369
|
+
## Troubleshooting
|
|
370
|
+
|
|
371
|
+
### LOC Calculation Issues
|
|
372
|
+
|
|
373
|
+
If LOC is 0 or incorrect:
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
# Ensure input path is correct
|
|
377
|
+
node cli.js --input=./src --rule=C065 --output-summary=summary.json
|
|
378
|
+
|
|
379
|
+
# For multiple paths
|
|
380
|
+
node cli.js --input=./src,./lib --rule=C065 --output-summary=summary.json
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Git Information Not Detected
|
|
384
|
+
|
|
385
|
+
In CI/CD, ensure environment variables are set:
|
|
386
|
+
|
|
387
|
+
```yaml
|
|
388
|
+
env:
|
|
389
|
+
GITHUB_REPOSITORY: ${{ github.repository }}
|
|
390
|
+
GITHUB_REF_NAME: ${{ github.ref_name }}
|
|
391
|
+
GITHUB_SHA: ${{ github.sha }}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
For local development:
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
# Check if git is available
|
|
398
|
+
git rev-parse --git-dir
|
|
399
|
+
|
|
400
|
+
# Run from repository root
|
|
401
|
+
cd /path/to/repo
|
|
402
|
+
node /path/to/sunlint/cli.js --input=src --output-summary=summary.json
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## See Also
|
|
406
|
+
|
|
407
|
+
- [Configuration Guide](CONFIGURATION.md)
|
|
408
|
+
- [CI/CD Integration Guide](CI-CD-GUIDE.md)
|
|
409
|
+
- [Command Examples](COMMAND-EXAMPLES.md)
|
package/package.json
CHANGED
|
@@ -66,8 +66,8 @@ class C023SymbolBasedAnalyzer {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
checkScope(node, violations) {
|
|
70
|
-
const seen = new Map();
|
|
69
|
+
checkScope(node, violations, parentSeen = new Map()) {
|
|
70
|
+
const seen = new Map(parentSeen);
|
|
71
71
|
|
|
72
72
|
node.forEachChild((child) => {
|
|
73
73
|
switch (child.getKind()) {
|
|
@@ -83,56 +83,55 @@ class C023SymbolBasedAnalyzer {
|
|
|
83
83
|
case SyntaxKind.ArrowFunction:
|
|
84
84
|
case SyntaxKind.MethodDeclaration:
|
|
85
85
|
case SyntaxKind.Constructor: { // ✅ also cover constructors
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
this.checkDuplicate(p, seen, violations)
|
|
86
|
+
const funcSeen = new Map();
|
|
87
|
+
child.getParameters().forEach((p) =>
|
|
88
|
+
this.checkDuplicate(p, funcSeen, violations)
|
|
90
89
|
);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (body) this.checkScope(body, violations);
|
|
90
|
+
const body = child.getBody && child.getBody();
|
|
91
|
+
if (body) this.checkScope(body, violations, funcSeen);
|
|
94
92
|
break;
|
|
95
93
|
}
|
|
96
94
|
|
|
97
95
|
case SyntaxKind.Block: {
|
|
98
|
-
this.checkScope(child, violations);
|
|
96
|
+
this.checkScope(child, violations, new Map(seen));
|
|
99
97
|
break;
|
|
100
98
|
}
|
|
101
99
|
|
|
102
100
|
case SyntaxKind.CatchClause: {
|
|
101
|
+
const catchSeen = new Map(seen);
|
|
103
102
|
const catchVar = child.getVariableDeclaration();
|
|
104
103
|
if (catchVar) {
|
|
105
|
-
|
|
106
|
-
this.checkDuplicate(catchVar, seen, violations);
|
|
104
|
+
this.checkDuplicate(catchVar, catchSeen, violations);
|
|
107
105
|
}
|
|
108
|
-
|
|
109
|
-
this.checkScope(child.getBlock(), violations);
|
|
106
|
+
this.checkScope(child.getBlock(), violations, catchSeen);
|
|
110
107
|
break;
|
|
111
108
|
}
|
|
112
109
|
|
|
113
110
|
case SyntaxKind.ForStatement:
|
|
114
111
|
case SyntaxKind.ForOfStatement:
|
|
115
112
|
case SyntaxKind.ForInStatement: {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
113
|
+
const loopSeen = new Map(seen);
|
|
114
|
+
const initializer = child.getInitializer && child.getInitializer();
|
|
115
|
+
if (initializer && initializer.getDeclarations) {
|
|
116
|
+
initializer.getDeclarations().forEach((decl) =>
|
|
117
|
+
this.checkDuplicate(decl, loopSeen, violations)
|
|
120
118
|
);
|
|
121
119
|
}
|
|
122
|
-
const statement = child.getStatement
|
|
123
|
-
if (statement) this.checkScope(statement, violations);
|
|
120
|
+
const statement = child.getStatement && child.getStatement();
|
|
121
|
+
if (statement) this.checkScope(statement, violations, loopSeen);
|
|
124
122
|
break;
|
|
125
123
|
}
|
|
126
124
|
|
|
127
125
|
default: {
|
|
128
|
-
this.checkScope(child, violations);
|
|
126
|
+
this.checkScope(child, violations, seen);
|
|
129
127
|
}
|
|
130
128
|
}
|
|
131
129
|
});
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
checkDuplicate(node, seen, violations) {
|
|
135
|
-
const
|
|
133
|
+
const nameNode = node.getNameNode();
|
|
134
|
+
const name = nameNode.getText();
|
|
136
135
|
if (!name) return;
|
|
137
136
|
const filePath = node.getSourceFile().getFilePath();
|
|
138
137
|
|
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.
|