@aiready/consistency 0.6.8 ā 0.6.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/.turbo/turbo-build.log +9 -9
- package/.turbo/turbo-test.log +276 -46
- package/LANGUAGE-SUPPORT-FIX.md +154 -0
- package/README.md +17 -0
- package/dist/chunk-7PHHJOGC.mjs +1374 -0
- package/dist/cli.js +22 -16
- package/dist/cli.mjs +19 -15
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -2
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
- package/src/__tests__/language-filter.test.ts +52 -0
- package/src/analyzer.ts +2 -0
- package/src/analyzers/naming-ast.ts +7 -1
- package/src/cli.ts +20 -16
- package/src/utils/ast-parser.ts +3 -2
package/dist/cli.js
CHANGED
|
@@ -49,7 +49,6 @@ function parseFile(filePath, content) {
|
|
|
49
49
|
filePath: isTypeScript ? filePath : void 0
|
|
50
50
|
});
|
|
51
51
|
} catch (error) {
|
|
52
|
-
console.warn(`Failed to parse ${filePath}:`, error instanceof Error ? error.message : error);
|
|
53
52
|
return null;
|
|
54
53
|
}
|
|
55
54
|
}
|
|
@@ -864,7 +863,10 @@ async function loadNamingConfig(files) {
|
|
|
864
863
|
async function analyzeNamingAST(files) {
|
|
865
864
|
const issues = [];
|
|
866
865
|
const { allAbbreviations, allShortWords, disabledChecks } = await loadNamingConfig(files);
|
|
867
|
-
|
|
866
|
+
const supportedFiles = files.filter(
|
|
867
|
+
(file) => /\.(js|jsx|ts|tsx)$/i.test(file)
|
|
868
|
+
);
|
|
869
|
+
for (const file of supportedFiles) {
|
|
868
870
|
try {
|
|
869
871
|
const ast = parseFile(file);
|
|
870
872
|
if (!ast) continue;
|
|
@@ -1387,7 +1389,11 @@ var import_fs2 = require("fs");
|
|
|
1387
1389
|
var import_path2 = require("path");
|
|
1388
1390
|
var import_core4 = require("@aiready/core");
|
|
1389
1391
|
var program = new import_commander.Command();
|
|
1390
|
-
program.name("aiready-consistency").description("Detect consistency
|
|
1392
|
+
program.name("aiready-consistency").description("Detect consistency patterns in naming, code structure, and architecture").version("0.1.0").addHelpText("after", `
|
|
1393
|
+
LANGUAGE SUPPORT:
|
|
1394
|
+
Supported: TypeScript (.ts, .tsx), JavaScript (.js, .jsx)
|
|
1395
|
+
Note: Python, Java, and other language files will be safely ignored
|
|
1396
|
+
|
|
1391
1397
|
CONFIGURATION:
|
|
1392
1398
|
Supports config files: aiready.json, aiready.config.json, .aiready.json, .aireadyrc.json
|
|
1393
1399
|
CLI options override config file settings
|
|
@@ -1400,7 +1406,7 @@ ANALYSIS CATEGORIES:
|
|
|
1400
1406
|
EXAMPLES:
|
|
1401
1407
|
aiready-consistency . # Full analysis
|
|
1402
1408
|
aiready-consistency . --no-naming # Skip naming checks
|
|
1403
|
-
aiready-consistency . --min-severity major # Only show major+
|
|
1409
|
+
aiready-consistency . --min-severity major # Only show major+ patterns
|
|
1404
1410
|
aiready-consistency . --output json > report.json # JSON export
|
|
1405
1411
|
`).argument("<directory>", "Directory to analyze").option("--naming", "Check naming conventions and quality (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code pattern consistency (default: true)").option("--no-patterns", "Skip pattern analysis").option("--architecture", "Check architectural consistency (not yet implemented)").option("--min-severity <level>", "Minimum severity: info|minor|major|critical. Default: info").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console|json|markdown", "console").option("--output-file <path>", "Output file path (for json/markdown)").action(async (directory, options) => {
|
|
1406
1412
|
console.log(import_chalk.default.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
@@ -1461,14 +1467,14 @@ function displayConsoleReport(report, elapsedTime) {
|
|
|
1461
1467
|
const { summary, results, recommendations } = report;
|
|
1462
1468
|
console.log(import_chalk.default.bold("\n\u{1F4CA} Summary\n"));
|
|
1463
1469
|
console.log(`Files Analyzed: ${import_chalk.default.cyan(summary.filesAnalyzed)}`);
|
|
1464
|
-
console.log(`Total
|
|
1470
|
+
console.log(`Total Patterns Found: ${import_chalk.default.yellow(summary.totalIssues)}`);
|
|
1465
1471
|
console.log(` Naming: ${import_chalk.default.yellow(summary.namingIssues)}`);
|
|
1466
|
-
console.log(` Patterns: ${import_chalk.default.yellow(summary.patternIssues)}`);
|
|
1472
|
+
console.log(` Code Patterns: ${import_chalk.default.yellow(summary.patternIssues)}`);
|
|
1467
1473
|
console.log(` Architecture: ${import_chalk.default.yellow(summary.architectureIssues)}`);
|
|
1468
1474
|
console.log(`Analysis Time: ${import_chalk.default.gray(elapsedTime + "s")}
|
|
1469
1475
|
`);
|
|
1470
1476
|
if (summary.totalIssues === 0) {
|
|
1471
|
-
console.log(import_chalk.default.green("\u2728 No consistency
|
|
1477
|
+
console.log(import_chalk.default.green("\u2728 No consistency patterns found! Your codebase is AI-friendly.\n"));
|
|
1472
1478
|
return;
|
|
1473
1479
|
}
|
|
1474
1480
|
const namingResults = results.filter(
|
|
@@ -1478,11 +1484,11 @@ function displayConsoleReport(report, elapsedTime) {
|
|
|
1478
1484
|
(r) => r.issues.some((i) => i.category === "patterns")
|
|
1479
1485
|
);
|
|
1480
1486
|
if (namingResults.length > 0) {
|
|
1481
|
-
console.log(import_chalk.default.bold("\u{1F3F7}\uFE0F Naming
|
|
1487
|
+
console.log(import_chalk.default.bold("\u{1F3F7}\uFE0F Naming Patterns\n"));
|
|
1482
1488
|
displayCategoryIssues(namingResults, 5);
|
|
1483
1489
|
}
|
|
1484
1490
|
if (patternResults.length > 0) {
|
|
1485
|
-
console.log(import_chalk.default.bold("\n\u{1F504}
|
|
1491
|
+
console.log(import_chalk.default.bold("\n\u{1F504} Code Patterns\n"));
|
|
1486
1492
|
displayCategoryIssues(patternResults, 5);
|
|
1487
1493
|
}
|
|
1488
1494
|
console.log(import_chalk.default.bold("\n\u{1F4A1} Recommendations\n"));
|
|
@@ -1513,7 +1519,7 @@ function displayCategoryIssues(results, maxToShow) {
|
|
|
1513
1519
|
}
|
|
1514
1520
|
const remaining = results.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
1515
1521
|
if (remaining > 0) {
|
|
1516
|
-
console.log(import_chalk.default.dim(` ... and ${remaining} more
|
|
1522
|
+
console.log(import_chalk.default.dim(` ... and ${remaining} more patterns
|
|
1517
1523
|
`));
|
|
1518
1524
|
}
|
|
1519
1525
|
}
|
|
@@ -1532,28 +1538,28 @@ function generateMarkdownReport(report, elapsedTime) {
|
|
|
1532
1538
|
`;
|
|
1533
1539
|
markdown += `- **Files Analyzed:** ${summary.filesAnalyzed}
|
|
1534
1540
|
`;
|
|
1535
|
-
markdown += `- **Total
|
|
1541
|
+
markdown += `- **Total Patterns Found:** ${summary.totalIssues}
|
|
1536
1542
|
`;
|
|
1537
1543
|
markdown += ` - Naming: ${summary.namingIssues}
|
|
1538
1544
|
`;
|
|
1539
|
-
markdown += ` - Patterns: ${summary.patternIssues}
|
|
1545
|
+
markdown += ` - Code Patterns: ${summary.patternIssues}
|
|
1540
1546
|
`;
|
|
1541
1547
|
markdown += ` - Architecture: ${summary.architectureIssues}
|
|
1542
1548
|
|
|
1543
1549
|
`;
|
|
1544
1550
|
if (summary.totalIssues === 0) {
|
|
1545
|
-
markdown += `\u2728 No consistency
|
|
1551
|
+
markdown += `\u2728 No consistency patterns found! Your codebase is AI-friendly.
|
|
1546
1552
|
`;
|
|
1547
1553
|
return markdown;
|
|
1548
1554
|
}
|
|
1549
|
-
markdown += `##
|
|
1555
|
+
markdown += `## Patterns by Category
|
|
1550
1556
|
|
|
1551
1557
|
`;
|
|
1552
1558
|
const namingResults = results.filter(
|
|
1553
1559
|
(r) => r.issues.some((i) => i.category === "naming")
|
|
1554
1560
|
);
|
|
1555
1561
|
if (namingResults.length > 0) {
|
|
1556
|
-
markdown += `### \u{1F3F7}\uFE0F Naming
|
|
1562
|
+
markdown += `### \u{1F3F7}\uFE0F Naming Patterns
|
|
1557
1563
|
|
|
1558
1564
|
`;
|
|
1559
1565
|
for (const result of namingResults) {
|
|
@@ -1576,7 +1582,7 @@ function generateMarkdownReport(report, elapsedTime) {
|
|
|
1576
1582
|
(r) => r.issues.some((i) => i.category === "patterns")
|
|
1577
1583
|
);
|
|
1578
1584
|
if (patternResults.length > 0) {
|
|
1579
|
-
markdown += `### \u{1F504}
|
|
1585
|
+
markdown += `### \u{1F504} Code Patterns
|
|
1580
1586
|
|
|
1581
1587
|
`;
|
|
1582
1588
|
for (const result of patternResults) {
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
analyzeConsistency
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-7PHHJOGC.mjs";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -10,7 +10,11 @@ import { writeFileSync, mkdirSync, existsSync } from "fs";
|
|
|
10
10
|
import { dirname } from "path";
|
|
11
11
|
import { loadConfig, mergeConfigWithDefaults, resolveOutputPath } from "@aiready/core";
|
|
12
12
|
var program = new Command();
|
|
13
|
-
program.name("aiready-consistency").description("Detect consistency
|
|
13
|
+
program.name("aiready-consistency").description("Detect consistency patterns in naming, code structure, and architecture").version("0.1.0").addHelpText("after", `
|
|
14
|
+
LANGUAGE SUPPORT:
|
|
15
|
+
Supported: TypeScript (.ts, .tsx), JavaScript (.js, .jsx)
|
|
16
|
+
Note: Python, Java, and other language files will be safely ignored
|
|
17
|
+
|
|
14
18
|
CONFIGURATION:
|
|
15
19
|
Supports config files: aiready.json, aiready.config.json, .aiready.json, .aireadyrc.json
|
|
16
20
|
CLI options override config file settings
|
|
@@ -23,7 +27,7 @@ ANALYSIS CATEGORIES:
|
|
|
23
27
|
EXAMPLES:
|
|
24
28
|
aiready-consistency . # Full analysis
|
|
25
29
|
aiready-consistency . --no-naming # Skip naming checks
|
|
26
|
-
aiready-consistency . --min-severity major # Only show major+
|
|
30
|
+
aiready-consistency . --min-severity major # Only show major+ patterns
|
|
27
31
|
aiready-consistency . --output json > report.json # JSON export
|
|
28
32
|
`).argument("<directory>", "Directory to analyze").option("--naming", "Check naming conventions and quality (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code pattern consistency (default: true)").option("--no-patterns", "Skip pattern analysis").option("--architecture", "Check architectural consistency (not yet implemented)").option("--min-severity <level>", "Minimum severity: info|minor|major|critical. Default: info").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console|json|markdown", "console").option("--output-file <path>", "Output file path (for json/markdown)").action(async (directory, options) => {
|
|
29
33
|
console.log(chalk.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
@@ -84,14 +88,14 @@ function displayConsoleReport(report, elapsedTime) {
|
|
|
84
88
|
const { summary, results, recommendations } = report;
|
|
85
89
|
console.log(chalk.bold("\n\u{1F4CA} Summary\n"));
|
|
86
90
|
console.log(`Files Analyzed: ${chalk.cyan(summary.filesAnalyzed)}`);
|
|
87
|
-
console.log(`Total
|
|
91
|
+
console.log(`Total Patterns Found: ${chalk.yellow(summary.totalIssues)}`);
|
|
88
92
|
console.log(` Naming: ${chalk.yellow(summary.namingIssues)}`);
|
|
89
|
-
console.log(` Patterns: ${chalk.yellow(summary.patternIssues)}`);
|
|
93
|
+
console.log(` Code Patterns: ${chalk.yellow(summary.patternIssues)}`);
|
|
90
94
|
console.log(` Architecture: ${chalk.yellow(summary.architectureIssues)}`);
|
|
91
95
|
console.log(`Analysis Time: ${chalk.gray(elapsedTime + "s")}
|
|
92
96
|
`);
|
|
93
97
|
if (summary.totalIssues === 0) {
|
|
94
|
-
console.log(chalk.green("\u2728 No consistency
|
|
98
|
+
console.log(chalk.green("\u2728 No consistency patterns found! Your codebase is AI-friendly.\n"));
|
|
95
99
|
return;
|
|
96
100
|
}
|
|
97
101
|
const namingResults = results.filter(
|
|
@@ -101,11 +105,11 @@ function displayConsoleReport(report, elapsedTime) {
|
|
|
101
105
|
(r) => r.issues.some((i) => i.category === "patterns")
|
|
102
106
|
);
|
|
103
107
|
if (namingResults.length > 0) {
|
|
104
|
-
console.log(chalk.bold("\u{1F3F7}\uFE0F Naming
|
|
108
|
+
console.log(chalk.bold("\u{1F3F7}\uFE0F Naming Patterns\n"));
|
|
105
109
|
displayCategoryIssues(namingResults, 5);
|
|
106
110
|
}
|
|
107
111
|
if (patternResults.length > 0) {
|
|
108
|
-
console.log(chalk.bold("\n\u{1F504}
|
|
112
|
+
console.log(chalk.bold("\n\u{1F504} Code Patterns\n"));
|
|
109
113
|
displayCategoryIssues(patternResults, 5);
|
|
110
114
|
}
|
|
111
115
|
console.log(chalk.bold("\n\u{1F4A1} Recommendations\n"));
|
|
@@ -136,7 +140,7 @@ function displayCategoryIssues(results, maxToShow) {
|
|
|
136
140
|
}
|
|
137
141
|
const remaining = results.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
138
142
|
if (remaining > 0) {
|
|
139
|
-
console.log(chalk.dim(` ... and ${remaining} more
|
|
143
|
+
console.log(chalk.dim(` ... and ${remaining} more patterns
|
|
140
144
|
`));
|
|
141
145
|
}
|
|
142
146
|
}
|
|
@@ -155,28 +159,28 @@ function generateMarkdownReport(report, elapsedTime) {
|
|
|
155
159
|
`;
|
|
156
160
|
markdown += `- **Files Analyzed:** ${summary.filesAnalyzed}
|
|
157
161
|
`;
|
|
158
|
-
markdown += `- **Total
|
|
162
|
+
markdown += `- **Total Patterns Found:** ${summary.totalIssues}
|
|
159
163
|
`;
|
|
160
164
|
markdown += ` - Naming: ${summary.namingIssues}
|
|
161
165
|
`;
|
|
162
|
-
markdown += ` - Patterns: ${summary.patternIssues}
|
|
166
|
+
markdown += ` - Code Patterns: ${summary.patternIssues}
|
|
163
167
|
`;
|
|
164
168
|
markdown += ` - Architecture: ${summary.architectureIssues}
|
|
165
169
|
|
|
166
170
|
`;
|
|
167
171
|
if (summary.totalIssues === 0) {
|
|
168
|
-
markdown += `\u2728 No consistency
|
|
172
|
+
markdown += `\u2728 No consistency patterns found! Your codebase is AI-friendly.
|
|
169
173
|
`;
|
|
170
174
|
return markdown;
|
|
171
175
|
}
|
|
172
|
-
markdown += `##
|
|
176
|
+
markdown += `## Patterns by Category
|
|
173
177
|
|
|
174
178
|
`;
|
|
175
179
|
const namingResults = results.filter(
|
|
176
180
|
(r) => r.issues.some((i) => i.category === "naming")
|
|
177
181
|
);
|
|
178
182
|
if (namingResults.length > 0) {
|
|
179
|
-
markdown += `### \u{1F3F7}\uFE0F Naming
|
|
183
|
+
markdown += `### \u{1F3F7}\uFE0F Naming Patterns
|
|
180
184
|
|
|
181
185
|
`;
|
|
182
186
|
for (const result of namingResults) {
|
|
@@ -199,7 +203,7 @@ function generateMarkdownReport(report, elapsedTime) {
|
|
|
199
203
|
(r) => r.issues.some((i) => i.category === "patterns")
|
|
200
204
|
);
|
|
201
205
|
if (patternResults.length > 0) {
|
|
202
|
-
markdown += `### \u{1F504}
|
|
206
|
+
markdown += `### \u{1F504} Code Patterns
|
|
203
207
|
|
|
204
208
|
`;
|
|
205
209
|
for (const result of patternResults) {
|
package/dist/index.d.mts
CHANGED
|
@@ -54,11 +54,14 @@ interface ConsistencyReport {
|
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Main consistency analyzer that orchestrates all analysis types
|
|
57
|
+
* Note: Currently only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
58
|
+
* Python and other language files will be ignored during naming analysis.
|
|
57
59
|
*/
|
|
58
60
|
declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
63
|
* AST-based naming analyzer
|
|
64
|
+
* Only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
62
65
|
*/
|
|
63
66
|
declare function analyzeNamingAST(files: string[]): Promise<NamingIssue[]>;
|
|
64
67
|
|
package/dist/index.d.ts
CHANGED
|
@@ -54,11 +54,14 @@ interface ConsistencyReport {
|
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* Main consistency analyzer that orchestrates all analysis types
|
|
57
|
+
* Note: Currently only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
58
|
+
* Python and other language files will be ignored during naming analysis.
|
|
57
59
|
*/
|
|
58
60
|
declare function analyzeConsistency(options: ConsistencyOptions): Promise<ConsistencyReport>;
|
|
59
61
|
|
|
60
62
|
/**
|
|
61
63
|
* AST-based naming analyzer
|
|
64
|
+
* Only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
62
65
|
*/
|
|
63
66
|
declare function analyzeNamingAST(files: string[]): Promise<NamingIssue[]>;
|
|
64
67
|
|
package/dist/index.js
CHANGED
|
@@ -51,7 +51,6 @@ function parseFile(filePath, content) {
|
|
|
51
51
|
filePath: isTypeScript ? filePath : void 0
|
|
52
52
|
});
|
|
53
53
|
} catch (error) {
|
|
54
|
-
console.warn(`Failed to parse ${filePath}:`, error instanceof Error ? error.message : error);
|
|
55
54
|
return null;
|
|
56
55
|
}
|
|
57
56
|
}
|
|
@@ -877,7 +876,10 @@ async function loadNamingConfig(files) {
|
|
|
877
876
|
async function analyzeNamingAST(files) {
|
|
878
877
|
const issues = [];
|
|
879
878
|
const { allAbbreviations, allShortWords, disabledChecks } = await loadNamingConfig(files);
|
|
880
|
-
|
|
879
|
+
const supportedFiles = files.filter(
|
|
880
|
+
(file) => /\.(js|jsx|ts|tsx)$/i.test(file)
|
|
881
|
+
);
|
|
882
|
+
for (const file of supportedFiles) {
|
|
881
883
|
try {
|
|
882
884
|
const ast = parseFile(file);
|
|
883
885
|
if (!ast) continue;
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/consistency",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.12",
|
|
4
4
|
"description": "Detects consistency issues in naming, patterns, and architecture that confuse AI models",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@typescript-eslint/typescript-estree": "^8.53.0",
|
|
44
44
|
"chalk": "^5.3.0",
|
|
45
45
|
"commander": "^12.1.0",
|
|
46
|
-
"@aiready/core": "0.7.
|
|
46
|
+
"@aiready/core": "0.7.9"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^22.10.5",
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
import { analyzeNamingAST } from '../analyzers/naming-ast';
|
|
3
|
+
|
|
4
|
+
describe('Language File Filtering', () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
// Suppress console warnings during tests
|
|
7
|
+
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should only process JS/TS files', async () => {
|
|
11
|
+
const mixedFiles = [
|
|
12
|
+
'/path/to/file.ts',
|
|
13
|
+
'/path/to/file.tsx',
|
|
14
|
+
'/path/to/file.js',
|
|
15
|
+
'/path/to/file.jsx',
|
|
16
|
+
'/path/to/file.py', // Should be filtered out
|
|
17
|
+
'/path/to/file.java', // Should be filtered out
|
|
18
|
+
'/path/to/file.rb', // Should be filtered out
|
|
19
|
+
'/path/to/file.go', // Should be filtered out
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
// This test verifies that the function doesn't crash on non-JS/TS files
|
|
23
|
+
// In reality, it will try to read these files if they exist, but parseFile will return null
|
|
24
|
+
// and they'll be skipped. The filtering happens before parseFile is called.
|
|
25
|
+
await expect(analyzeNamingAST(mixedFiles)).resolves.not.toThrow();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should filter out Python files before parsing', async () => {
|
|
29
|
+
const files = [
|
|
30
|
+
'/path/to/script.py',
|
|
31
|
+
'/path/to/another.py',
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
// Should not attempt to parse Python files
|
|
35
|
+
const result = await analyzeNamingAST(files);
|
|
36
|
+
expect(result).toEqual([]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should accept all JS/TS file extensions', async () => {
|
|
40
|
+
const jstsFiles = [
|
|
41
|
+
'test.js',
|
|
42
|
+
'test.jsx',
|
|
43
|
+
'test.ts',
|
|
44
|
+
'test.tsx',
|
|
45
|
+
'TEST.JS', // Test case-insensitive
|
|
46
|
+
'TEST.TS',
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
// These should all pass the filter (though they won't parse if they don't exist)
|
|
50
|
+
await expect(analyzeNamingAST(jstsFiles)).resolves.not.toThrow();
|
|
51
|
+
});
|
|
52
|
+
});
|
package/src/analyzer.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { analyzePatterns } from './analyzers/patterns';
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Main consistency analyzer that orchestrates all analysis types
|
|
9
|
+
* Note: Currently only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
10
|
+
* Python and other language files will be ignored during naming analysis.
|
|
9
11
|
*/
|
|
10
12
|
export async function analyzeConsistency(
|
|
11
13
|
options: ConsistencyOptions
|
|
@@ -20,6 +20,7 @@ import { loadNamingConfig } from '../utils/config-loader';
|
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* AST-based naming analyzer
|
|
23
|
+
* Only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
23
24
|
*/
|
|
24
25
|
export async function analyzeNamingAST(files: string[]): Promise<NamingIssue[]> {
|
|
25
26
|
const issues: NamingIssue[] = [];
|
|
@@ -27,7 +28,12 @@ export async function analyzeNamingAST(files: string[]): Promise<NamingIssue[]>
|
|
|
27
28
|
// Load and merge configuration
|
|
28
29
|
const { allAbbreviations, allShortWords, disabledChecks } = await loadNamingConfig(files);
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
// Filter to only JS/TS files that the TypeScript parser can handle
|
|
32
|
+
const supportedFiles = files.filter(file =>
|
|
33
|
+
/\.(js|jsx|ts|tsx)$/i.test(file)
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
for (const file of supportedFiles) {
|
|
31
37
|
try {
|
|
32
38
|
const ast = parseFile(file);
|
|
33
39
|
if (!ast) continue; // Skip files that fail to parse
|
package/src/cli.ts
CHANGED
|
@@ -12,9 +12,13 @@ const program = new Command();
|
|
|
12
12
|
|
|
13
13
|
program
|
|
14
14
|
.name('aiready-consistency')
|
|
15
|
-
.description('Detect consistency
|
|
15
|
+
.description('Detect consistency patterns in naming, code structure, and architecture')
|
|
16
16
|
.version('0.1.0')
|
|
17
17
|
.addHelpText('after', `
|
|
18
|
+
LANGUAGE SUPPORT:
|
|
19
|
+
Supported: TypeScript (.ts, .tsx), JavaScript (.js, .jsx)
|
|
20
|
+
Note: Python, Java, and other language files will be safely ignored
|
|
21
|
+
|
|
18
22
|
CONFIGURATION:
|
|
19
23
|
Supports config files: aiready.json, aiready.config.json, .aiready.json, .aireadyrc.json
|
|
20
24
|
CLI options override config file settings
|
|
@@ -27,7 +31,7 @@ ANALYSIS CATEGORIES:
|
|
|
27
31
|
EXAMPLES:
|
|
28
32
|
aiready-consistency . # Full analysis
|
|
29
33
|
aiready-consistency . --no-naming # Skip naming checks
|
|
30
|
-
aiready-consistency . --min-severity major # Only show major+
|
|
34
|
+
aiready-consistency . --min-severity major # Only show major+ patterns
|
|
31
35
|
aiready-consistency . --output json > report.json # JSON export
|
|
32
36
|
`)
|
|
33
37
|
.argument('<directory>', 'Directory to analyze')
|
|
@@ -121,14 +125,14 @@ function displayConsoleReport(report: any, elapsedTime: string): void {
|
|
|
121
125
|
|
|
122
126
|
console.log(chalk.bold('\nš Summary\n'));
|
|
123
127
|
console.log(`Files Analyzed: ${chalk.cyan(summary.filesAnalyzed)}`);
|
|
124
|
-
console.log(`Total
|
|
128
|
+
console.log(`Total Patterns Found: ${chalk.yellow(summary.totalIssues)}`);
|
|
125
129
|
console.log(` Naming: ${chalk.yellow(summary.namingIssues)}`);
|
|
126
|
-
console.log(` Patterns: ${chalk.yellow(summary.patternIssues)}`);
|
|
130
|
+
console.log(` Code Patterns: ${chalk.yellow(summary.patternIssues)}`);
|
|
127
131
|
console.log(` Architecture: ${chalk.yellow(summary.architectureIssues)}`);
|
|
128
132
|
console.log(`Analysis Time: ${chalk.gray(elapsedTime + 's')}\n`);
|
|
129
133
|
|
|
130
134
|
if (summary.totalIssues === 0) {
|
|
131
|
-
console.log(chalk.green('⨠No consistency
|
|
135
|
+
console.log(chalk.green('⨠No consistency patterns found! Your codebase is AI-friendly.\n'));
|
|
132
136
|
return;
|
|
133
137
|
}
|
|
134
138
|
|
|
@@ -141,12 +145,12 @@ function displayConsoleReport(report: any, elapsedTime: string): void {
|
|
|
141
145
|
);
|
|
142
146
|
|
|
143
147
|
if (namingResults.length > 0) {
|
|
144
|
-
console.log(chalk.bold('š·ļø Naming
|
|
148
|
+
console.log(chalk.bold('š·ļø Naming Patterns\n'));
|
|
145
149
|
displayCategoryIssues(namingResults, 5);
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
if (patternResults.length > 0) {
|
|
149
|
-
console.log(chalk.bold('\nš
|
|
153
|
+
console.log(chalk.bold('\nš Code Patterns\n'));
|
|
150
154
|
displayCategoryIssues(patternResults, 5);
|
|
151
155
|
}
|
|
152
156
|
|
|
@@ -191,7 +195,7 @@ function displayCategoryIssues(results: any[], maxToShow: number): void {
|
|
|
191
195
|
|
|
192
196
|
const remaining = results.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
193
197
|
if (remaining > 0) {
|
|
194
|
-
console.log(chalk.dim(` ... and ${remaining} more
|
|
198
|
+
console.log(chalk.dim(` ... and ${remaining} more patterns\n`));
|
|
195
199
|
}
|
|
196
200
|
}
|
|
197
201
|
|
|
@@ -204,24 +208,24 @@ function generateMarkdownReport(report: any, elapsedTime: string): string {
|
|
|
204
208
|
|
|
205
209
|
markdown += `## Summary\n\n`;
|
|
206
210
|
markdown += `- **Files Analyzed:** ${summary.filesAnalyzed}\n`;
|
|
207
|
-
markdown += `- **Total
|
|
211
|
+
markdown += `- **Total Patterns Found:** ${summary.totalIssues}\n`;
|
|
208
212
|
markdown += ` - Naming: ${summary.namingIssues}\n`;
|
|
209
|
-
markdown += ` - Patterns: ${summary.patternIssues}\n`;
|
|
213
|
+
markdown += ` - Code Patterns: ${summary.patternIssues}\n`;
|
|
210
214
|
markdown += ` - Architecture: ${summary.architectureIssues}\n\n`;
|
|
211
215
|
|
|
212
216
|
if (summary.totalIssues === 0) {
|
|
213
|
-
markdown += `⨠No consistency
|
|
217
|
+
markdown += `⨠No consistency patterns found! Your codebase is AI-friendly.\n`;
|
|
214
218
|
return markdown;
|
|
215
219
|
}
|
|
216
220
|
|
|
217
|
-
markdown += `##
|
|
221
|
+
markdown += `## Patterns by Category\n\n`;
|
|
218
222
|
|
|
219
|
-
// Naming
|
|
223
|
+
// Naming patterns
|
|
220
224
|
const namingResults = results.filter((r: any) =>
|
|
221
225
|
r.issues.some((i: any) => i.category === 'naming')
|
|
222
226
|
);
|
|
223
227
|
if (namingResults.length > 0) {
|
|
224
|
-
markdown += `### š·ļø Naming
|
|
228
|
+
markdown += `### š·ļø Naming Patterns\n\n`;
|
|
225
229
|
for (const result of namingResults) {
|
|
226
230
|
for (const issue of result.issues) {
|
|
227
231
|
if (issue.category !== 'naming') continue;
|
|
@@ -235,12 +239,12 @@ function generateMarkdownReport(report: any, elapsedTime: string): string {
|
|
|
235
239
|
markdown += `\n`;
|
|
236
240
|
}
|
|
237
241
|
|
|
238
|
-
//
|
|
242
|
+
// Code patterns
|
|
239
243
|
const patternResults = results.filter((r: any) =>
|
|
240
244
|
r.issues.some((i: any) => i.category === 'patterns')
|
|
241
245
|
);
|
|
242
246
|
if (patternResults.length > 0) {
|
|
243
|
-
markdown += `### š
|
|
247
|
+
markdown += `### š Code Patterns\n\n`;
|
|
244
248
|
for (const result of patternResults) {
|
|
245
249
|
for (const issue of result.issues) {
|
|
246
250
|
if (issue.category !== 'patterns') continue;
|
package/src/utils/ast-parser.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { readFileSync } from 'fs';
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Parse a file into an AST
|
|
6
|
+
* Only supports TypeScript/JavaScript files (.ts, .tsx, .js, .jsx)
|
|
6
7
|
*/
|
|
7
8
|
export function parseFile(filePath: string, content?: string): TSESTree.Program | null {
|
|
8
9
|
try {
|
|
@@ -22,8 +23,8 @@ export function parseFile(filePath: string, content?: string): TSESTree.Program
|
|
|
22
23
|
filePath: isTypeScript ? filePath : undefined,
|
|
23
24
|
});
|
|
24
25
|
} catch (error) {
|
|
25
|
-
//
|
|
26
|
-
|
|
26
|
+
// Silently skip files that fail to parse (likely non-JS/TS or syntax errors)
|
|
27
|
+
// Non-JS/TS files should be filtered before reaching this point
|
|
27
28
|
return null;
|
|
28
29
|
}
|
|
29
30
|
}
|