@behavioral-contracts/verify-cli 1.0.0
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/LICENSE +119 -0
- package/README.md +694 -0
- package/dist/analyze-results.js +253 -0
- package/dist/analyzer.d.ts +366 -0
- package/dist/analyzer.d.ts.map +1 -0
- package/dist/analyzer.js +2592 -0
- package/dist/analyzer.js.map +1 -0
- package/dist/analyzers/async-error-analyzer.d.ts +72 -0
- package/dist/analyzers/async-error-analyzer.d.ts.map +1 -0
- package/dist/analyzers/async-error-analyzer.js +243 -0
- package/dist/analyzers/async-error-analyzer.js.map +1 -0
- package/dist/analyzers/event-listener-analyzer.d.ts +102 -0
- package/dist/analyzers/event-listener-analyzer.d.ts.map +1 -0
- package/dist/analyzers/event-listener-analyzer.js +253 -0
- package/dist/analyzers/event-listener-analyzer.js.map +1 -0
- package/dist/analyzers/react-query-analyzer.d.ts +66 -0
- package/dist/analyzers/react-query-analyzer.d.ts.map +1 -0
- package/dist/analyzers/react-query-analyzer.js +341 -0
- package/dist/analyzers/react-query-analyzer.js.map +1 -0
- package/dist/analyzers/return-value-analyzer.d.ts +61 -0
- package/dist/analyzers/return-value-analyzer.d.ts.map +1 -0
- package/dist/analyzers/return-value-analyzer.js +225 -0
- package/dist/analyzers/return-value-analyzer.js.map +1 -0
- package/dist/code-snippet.d.ts +48 -0
- package/dist/code-snippet.d.ts.map +1 -0
- package/dist/code-snippet.js +84 -0
- package/dist/code-snippet.js.map +1 -0
- package/dist/corpus-loader.d.ts +33 -0
- package/dist/corpus-loader.d.ts.map +1 -0
- package/dist/corpus-loader.js +155 -0
- package/dist/corpus-loader.js.map +1 -0
- package/dist/fixture-tester.d.ts +28 -0
- package/dist/fixture-tester.d.ts.map +1 -0
- package/dist/fixture-tester.js +176 -0
- package/dist/fixture-tester.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +375 -0
- package/dist/index.js.map +1 -0
- package/dist/package-discovery.d.ts +62 -0
- package/dist/package-discovery.d.ts.map +1 -0
- package/dist/package-discovery.js +299 -0
- package/dist/package-discovery.js.map +1 -0
- package/dist/reporter.d.ts +43 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +347 -0
- package/dist/reporter.js.map +1 -0
- package/dist/reporters/benchmarking.d.ts +70 -0
- package/dist/reporters/benchmarking.d.ts.map +1 -0
- package/dist/reporters/benchmarking.js +191 -0
- package/dist/reporters/benchmarking.js.map +1 -0
- package/dist/reporters/d3-visualizer.d.ts +40 -0
- package/dist/reporters/d3-visualizer.d.ts.map +1 -0
- package/dist/reporters/d3-visualizer.js +803 -0
- package/dist/reporters/d3-visualizer.js.map +1 -0
- package/dist/reporters/health-score.d.ts +33 -0
- package/dist/reporters/health-score.d.ts.map +1 -0
- package/dist/reporters/health-score.js +149 -0
- package/dist/reporters/health-score.js.map +1 -0
- package/dist/reporters/index.d.ts +11 -0
- package/dist/reporters/index.d.ts.map +1 -0
- package/dist/reporters/index.js +11 -0
- package/dist/reporters/index.js.map +1 -0
- package/dist/reporters/package-breakdown.d.ts +48 -0
- package/dist/reporters/package-breakdown.d.ts.map +1 -0
- package/dist/reporters/package-breakdown.js +185 -0
- package/dist/reporters/package-breakdown.js.map +1 -0
- package/dist/reporters/positive-evidence.d.ts +42 -0
- package/dist/reporters/positive-evidence.d.ts.map +1 -0
- package/dist/reporters/positive-evidence.js +436 -0
- package/dist/reporters/positive-evidence.js.map +1 -0
- package/dist/tsconfig-generator.d.ts +17 -0
- package/dist/tsconfig-generator.d.ts.map +1 -0
- package/dist/tsconfig-generator.js +107 -0
- package/dist/tsconfig-generator.js.map +1 -0
- package/dist/types.d.ts +298 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react-query-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/react-query-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return Value Analyzer
|
|
3
|
+
* Detects unprotected error checks on function return values
|
|
4
|
+
*
|
|
5
|
+
* This analyzer tracks:
|
|
6
|
+
* 1. Variable assignments from contract functions
|
|
7
|
+
* 2. Error checks on those return values (null, false, error properties)
|
|
8
|
+
* 3. Whether those checks are protected by try-catch
|
|
9
|
+
*
|
|
10
|
+
* Related: dev-notes/analyzer-enhancement/RETURN_VALUE_RESEARCH.md
|
|
11
|
+
*/
|
|
12
|
+
import * as ts from 'typescript';
|
|
13
|
+
import type { PackageContract, Postcondition } from '../types.js';
|
|
14
|
+
export interface ReturnValueCheck {
|
|
15
|
+
/** Variable name holding the return value */
|
|
16
|
+
variableName: string;
|
|
17
|
+
/** Package the function belongs to */
|
|
18
|
+
packageName: string;
|
|
19
|
+
/** Function name that returned the value */
|
|
20
|
+
functionName: string;
|
|
21
|
+
/** Postcondition that requires error handling */
|
|
22
|
+
postcondition: Postcondition;
|
|
23
|
+
/** AST node where variable was declared */
|
|
24
|
+
declarationNode: ts.Node;
|
|
25
|
+
/** AST node where error check occurs (if any) */
|
|
26
|
+
checkNode?: ts.Node;
|
|
27
|
+
/** Whether the error check is protected by try-catch */
|
|
28
|
+
isProtected: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare class ReturnValueAnalyzer {
|
|
31
|
+
private sourceFile;
|
|
32
|
+
private contracts;
|
|
33
|
+
private trackedReturnValues;
|
|
34
|
+
constructor(sourceFile: ts.SourceFile, contracts: Map<string, PackageContract>, _typeChecker: ts.TypeChecker);
|
|
35
|
+
/**
|
|
36
|
+
* Analyzes a function scope for unprotected return value checks
|
|
37
|
+
*/
|
|
38
|
+
analyze(functionNode: ts.Node): ReturnValueCheck[];
|
|
39
|
+
/**
|
|
40
|
+
* Finds variable declarations that assign return values from contract functions
|
|
41
|
+
*/
|
|
42
|
+
private findReturnValueDeclarations;
|
|
43
|
+
/**
|
|
44
|
+
* Extracts contract function information from a call expression
|
|
45
|
+
*/
|
|
46
|
+
private extractContractFunctionCall;
|
|
47
|
+
/**
|
|
48
|
+
* Finds error check on a tracked return value
|
|
49
|
+
* Looks for patterns like: if (!result), if (result.error), if (!result.success)
|
|
50
|
+
*/
|
|
51
|
+
private findErrorCheck;
|
|
52
|
+
/**
|
|
53
|
+
* Checks if a node is protected by try-catch
|
|
54
|
+
*/
|
|
55
|
+
private isNodeProtected;
|
|
56
|
+
/**
|
|
57
|
+
* Checks if child is a descendant of parent node
|
|
58
|
+
*/
|
|
59
|
+
private isDescendantOf;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=return-value-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"return-value-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/return-value-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,aAAa,EAAE,aAAa,CAAC;IAC7B,2CAA2C;IAC3C,eAAe,EAAE,EAAE,CAAC,IAAI,CAAC;IACzB,iDAAiD;IACjD,SAAS,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;IACpB,wDAAwD;IACxD,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,UAAU,CAAgB;IAClC,OAAO,CAAC,SAAS,CAA+B;IAIhD,OAAO,CAAC,mBAAmB,CAKZ;gBAGb,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,EACvC,YAAY,EAAE,EAAE,CAAC,WAAW;IAO9B;;OAEG;IACH,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,IAAI,GAAG,gBAAgB,EAAE;IA6ClD;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAwBnC;;OAEG;IACH,OAAO,CAAC,2BAA2B;IAuDnC;;;OAGG;IACH,OAAO,CAAC,cAAc;IA6DtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAyBvB;;OAEG;IACH,OAAO,CAAC,cAAc;CAYvB"}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Return Value Analyzer
|
|
3
|
+
* Detects unprotected error checks on function return values
|
|
4
|
+
*
|
|
5
|
+
* This analyzer tracks:
|
|
6
|
+
* 1. Variable assignments from contract functions
|
|
7
|
+
* 2. Error checks on those return values (null, false, error properties)
|
|
8
|
+
* 3. Whether those checks are protected by try-catch
|
|
9
|
+
*
|
|
10
|
+
* Related: dev-notes/analyzer-enhancement/RETURN_VALUE_RESEARCH.md
|
|
11
|
+
*/
|
|
12
|
+
import * as ts from 'typescript';
|
|
13
|
+
export class ReturnValueAnalyzer {
|
|
14
|
+
sourceFile;
|
|
15
|
+
contracts;
|
|
16
|
+
// private typeChecker: ts.TypeChecker; // Reserved for future type-aware detection
|
|
17
|
+
// Track return values that need error checking
|
|
18
|
+
trackedReturnValues = new Map();
|
|
19
|
+
constructor(sourceFile, contracts, _typeChecker // Reserved for future type-aware detection
|
|
20
|
+
) {
|
|
21
|
+
this.sourceFile = sourceFile;
|
|
22
|
+
this.contracts = contracts;
|
|
23
|
+
// this.typeChecker = typeChecker; // Reserved for future type-aware detection
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Analyzes a function scope for unprotected return value checks
|
|
27
|
+
*/
|
|
28
|
+
analyze(functionNode) {
|
|
29
|
+
const violations = [];
|
|
30
|
+
// Step 1: Find all variable declarations from contract functions
|
|
31
|
+
this.findReturnValueDeclarations(functionNode);
|
|
32
|
+
// Step 2: For each tracked return value, find error checks
|
|
33
|
+
for (const [varName, info] of this.trackedReturnValues.entries()) {
|
|
34
|
+
const errorCheck = this.findErrorCheck(varName, functionNode);
|
|
35
|
+
if (!errorCheck) {
|
|
36
|
+
// No error check found - violation
|
|
37
|
+
violations.push({
|
|
38
|
+
variableName: varName,
|
|
39
|
+
packageName: info.packageName,
|
|
40
|
+
functionName: info.functionName,
|
|
41
|
+
postcondition: info.postcondition,
|
|
42
|
+
declarationNode: info.declarationNode,
|
|
43
|
+
isProtected: false,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
// Error check found - verify it's in try-catch
|
|
48
|
+
const isProtected = this.isNodeProtected(errorCheck, functionNode);
|
|
49
|
+
if (!isProtected) {
|
|
50
|
+
// Error check exists but not in try-catch - violation
|
|
51
|
+
violations.push({
|
|
52
|
+
variableName: varName,
|
|
53
|
+
packageName: info.packageName,
|
|
54
|
+
functionName: info.functionName,
|
|
55
|
+
postcondition: info.postcondition,
|
|
56
|
+
declarationNode: info.declarationNode,
|
|
57
|
+
checkNode: errorCheck,
|
|
58
|
+
isProtected: false,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Clear for next function
|
|
64
|
+
this.trackedReturnValues.clear();
|
|
65
|
+
return violations;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Finds variable declarations that assign return values from contract functions
|
|
69
|
+
*/
|
|
70
|
+
findReturnValueDeclarations(scope) {
|
|
71
|
+
const visit = (node) => {
|
|
72
|
+
// Pattern: const result = validator.normalizeEmail(email)
|
|
73
|
+
if (ts.isVariableDeclaration(node) && node.initializer) {
|
|
74
|
+
const callInfo = this.extractContractFunctionCall(node.initializer);
|
|
75
|
+
if (callInfo) {
|
|
76
|
+
const varName = node.name.getText(this.sourceFile);
|
|
77
|
+
this.trackedReturnValues.set(varName, {
|
|
78
|
+
packageName: callInfo.packageName,
|
|
79
|
+
functionName: callInfo.functionName,
|
|
80
|
+
postcondition: callInfo.postcondition,
|
|
81
|
+
declarationNode: node,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Continue visiting children
|
|
86
|
+
ts.forEachChild(node, visit);
|
|
87
|
+
};
|
|
88
|
+
visit(scope);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Extracts contract function information from a call expression
|
|
92
|
+
*/
|
|
93
|
+
extractContractFunctionCall(node) {
|
|
94
|
+
if (!ts.isCallExpression(node)) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
let functionName = null;
|
|
98
|
+
let objectName = null;
|
|
99
|
+
// Pattern: validator.normalizeEmail(...)
|
|
100
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
101
|
+
functionName = node.expression.name.text;
|
|
102
|
+
if (ts.isIdentifier(node.expression.expression)) {
|
|
103
|
+
objectName = node.expression.expression.text;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Pattern: normalizeEmail(...) - direct call
|
|
107
|
+
if (ts.isIdentifier(node.expression)) {
|
|
108
|
+
functionName = node.expression.text;
|
|
109
|
+
}
|
|
110
|
+
if (!functionName) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
// Check if this function belongs to any contract
|
|
114
|
+
for (const [packageName, contract] of this.contracts.entries()) {
|
|
115
|
+
// Simple heuristic: if objectName matches package name or is similar
|
|
116
|
+
const packageMatches = objectName === packageName ||
|
|
117
|
+
objectName === packageName.split('/').pop() ||
|
|
118
|
+
objectName === packageName.replace(/@/g, '').replace(/\//g, '-');
|
|
119
|
+
if (packageMatches || !objectName) {
|
|
120
|
+
// Check if function exists in contract
|
|
121
|
+
const func = contract.functions?.find(f => f.name === functionName);
|
|
122
|
+
if (func && func.postconditions && func.postconditions.length > 0) {
|
|
123
|
+
return {
|
|
124
|
+
packageName,
|
|
125
|
+
functionName,
|
|
126
|
+
postcondition: func.postconditions[0], // Use first postcondition
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Finds error check on a tracked return value
|
|
135
|
+
* Looks for patterns like: if (!result), if (result.error), if (!result.success)
|
|
136
|
+
*/
|
|
137
|
+
findErrorCheck(varName, scope) {
|
|
138
|
+
let checkNode = null;
|
|
139
|
+
const visit = (node) => {
|
|
140
|
+
// Pattern: if (!result) { ... }
|
|
141
|
+
if (ts.isIfStatement(node)) {
|
|
142
|
+
const condition = node.expression;
|
|
143
|
+
// Check for: !variable
|
|
144
|
+
if (ts.isPrefixUnaryExpression(condition) &&
|
|
145
|
+
condition.operator === ts.SyntaxKind.ExclamationToken &&
|
|
146
|
+
ts.isIdentifier(condition.operand) &&
|
|
147
|
+
condition.operand.text === varName) {
|
|
148
|
+
checkNode = node;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Check for: variable (boolean check)
|
|
152
|
+
if (ts.isIdentifier(condition) && condition.text === varName) {
|
|
153
|
+
checkNode = node;
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
// Check for: !variable.property
|
|
157
|
+
if (ts.isPrefixUnaryExpression(condition) &&
|
|
158
|
+
condition.operator === ts.SyntaxKind.ExclamationToken &&
|
|
159
|
+
ts.isPropertyAccessExpression(condition.operand) &&
|
|
160
|
+
ts.isIdentifier(condition.operand.expression) &&
|
|
161
|
+
condition.operand.expression.text === varName) {
|
|
162
|
+
checkNode = node;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
// Check for: variable.error or variable.success
|
|
166
|
+
if (ts.isPropertyAccessExpression(condition) &&
|
|
167
|
+
ts.isIdentifier(condition.expression) &&
|
|
168
|
+
condition.expression.text === varName) {
|
|
169
|
+
checkNode = node;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Pattern: result || defaultValue
|
|
174
|
+
if (ts.isBinaryExpression(node) &&
|
|
175
|
+
node.operatorToken.kind === ts.SyntaxKind.BarBarToken &&
|
|
176
|
+
ts.isIdentifier(node.left) &&
|
|
177
|
+
node.left.text === varName) {
|
|
178
|
+
checkNode = node;
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
// Continue searching if not found
|
|
182
|
+
if (!checkNode) {
|
|
183
|
+
ts.forEachChild(node, visit);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
visit(scope);
|
|
187
|
+
return checkNode;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Checks if a node is protected by try-catch
|
|
191
|
+
*/
|
|
192
|
+
isNodeProtected(node, functionScope) {
|
|
193
|
+
let current = node;
|
|
194
|
+
// Walk up the AST until we find a try block or reach function boundary
|
|
195
|
+
while (current && current !== functionScope) {
|
|
196
|
+
const parent = current.parent;
|
|
197
|
+
if (!parent) {
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
// Check if we're inside a try block
|
|
201
|
+
if (ts.isTryStatement(parent)) {
|
|
202
|
+
// Check if current node is within the try block (not catch or finally)
|
|
203
|
+
if (parent.tryBlock === current || this.isDescendantOf(node, parent.tryBlock)) {
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
current = parent;
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Checks if child is a descendant of parent node
|
|
213
|
+
*/
|
|
214
|
+
isDescendantOf(child, parent) {
|
|
215
|
+
let current = child;
|
|
216
|
+
while (current) {
|
|
217
|
+
if (current === parent) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
current = current.parent;
|
|
221
|
+
}
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
//# sourceMappingURL=return-value-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"return-value-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/return-value-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Snippet Extraction Module
|
|
3
|
+
*
|
|
4
|
+
* Extracts code snippets around violation locations with context lines.
|
|
5
|
+
*/
|
|
6
|
+
export interface CodeSnippet {
|
|
7
|
+
lines: CodeLine[];
|
|
8
|
+
startLine: number;
|
|
9
|
+
endLine: number;
|
|
10
|
+
}
|
|
11
|
+
export interface CodeLine {
|
|
12
|
+
lineNumber: number;
|
|
13
|
+
content: string;
|
|
14
|
+
isViolation: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Extracts a code snippet from a file around a specific line
|
|
18
|
+
*
|
|
19
|
+
* @param filePath - Path to the source file
|
|
20
|
+
* @param violationLine - Line number where the violation occurred
|
|
21
|
+
* @param contextLines - Number of lines to show before and after (default: 4)
|
|
22
|
+
* @returns Code snippet with context
|
|
23
|
+
*/
|
|
24
|
+
export declare function extractCodeSnippet(filePath: string, violationLine: number, contextLines?: number): Promise<CodeSnippet | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Formats a code snippet for terminal display
|
|
27
|
+
*
|
|
28
|
+
* @param snippet - Code snippet to format
|
|
29
|
+
* @param maxLineLength - Maximum length of a line (truncate longer lines)
|
|
30
|
+
* @returns Formatted string array
|
|
31
|
+
*/
|
|
32
|
+
export declare function formatSnippetForTerminal(snippet: CodeSnippet, maxLineLength?: number): string[];
|
|
33
|
+
/**
|
|
34
|
+
* Formats a code snippet for JSON export
|
|
35
|
+
*
|
|
36
|
+
* @param snippet - Code snippet to format
|
|
37
|
+
* @returns Object suitable for JSON serialization
|
|
38
|
+
*/
|
|
39
|
+
export declare function formatSnippetForJSON(snippet: CodeSnippet): {
|
|
40
|
+
startLine: number;
|
|
41
|
+
endLine: number;
|
|
42
|
+
lines: Array<{
|
|
43
|
+
line: number;
|
|
44
|
+
content: string;
|
|
45
|
+
highlighted: boolean;
|
|
46
|
+
}>;
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=code-snippet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-snippet.d.ts","sourceRoot":"","sources":["../src/code-snippet.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,YAAY,GAAE,MAAU,GACvB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CA8B7B;AAED;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,WAAW,EACpB,aAAa,GAAE,MAAY,GAC1B,MAAM,EAAE,CAmBV;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,WAAW,GAAG;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;CACvE,CAUA"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Snippet Extraction Module
|
|
3
|
+
*
|
|
4
|
+
* Extracts code snippets around violation locations with context lines.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
/**
|
|
8
|
+
* Extracts a code snippet from a file around a specific line
|
|
9
|
+
*
|
|
10
|
+
* @param filePath - Path to the source file
|
|
11
|
+
* @param violationLine - Line number where the violation occurred
|
|
12
|
+
* @param contextLines - Number of lines to show before and after (default: 4)
|
|
13
|
+
* @returns Code snippet with context
|
|
14
|
+
*/
|
|
15
|
+
export async function extractCodeSnippet(filePath, violationLine, contextLines = 4) {
|
|
16
|
+
try {
|
|
17
|
+
// Read the entire file
|
|
18
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
19
|
+
const lines = content.split('\n');
|
|
20
|
+
// Calculate range (1-indexed line numbers)
|
|
21
|
+
const startLine = Math.max(1, violationLine - contextLines);
|
|
22
|
+
const endLine = Math.min(lines.length, violationLine + contextLines);
|
|
23
|
+
// Extract lines (convert to 0-indexed for array access)
|
|
24
|
+
const snippetLines = [];
|
|
25
|
+
for (let i = startLine; i <= endLine; i++) {
|
|
26
|
+
const lineContent = lines[i - 1]; // Convert to 0-indexed
|
|
27
|
+
snippetLines.push({
|
|
28
|
+
lineNumber: i,
|
|
29
|
+
content: lineContent,
|
|
30
|
+
isViolation: i === violationLine,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
lines: snippetLines,
|
|
35
|
+
startLine,
|
|
36
|
+
endLine,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
// File might not be accessible, return null
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Formats a code snippet for terminal display
|
|
46
|
+
*
|
|
47
|
+
* @param snippet - Code snippet to format
|
|
48
|
+
* @param maxLineLength - Maximum length of a line (truncate longer lines)
|
|
49
|
+
* @returns Formatted string array
|
|
50
|
+
*/
|
|
51
|
+
export function formatSnippetForTerminal(snippet, maxLineLength = 120) {
|
|
52
|
+
const output = [];
|
|
53
|
+
const maxLineNumWidth = String(snippet.endLine).length;
|
|
54
|
+
for (const line of snippet.lines) {
|
|
55
|
+
const lineNum = String(line.lineNumber).padStart(maxLineNumWidth, ' ');
|
|
56
|
+
let content = line.content;
|
|
57
|
+
// Truncate long lines
|
|
58
|
+
if (content.length > maxLineLength) {
|
|
59
|
+
content = content.substring(0, maxLineLength - 3) + '...';
|
|
60
|
+
}
|
|
61
|
+
// Add line prefix
|
|
62
|
+
const prefix = line.isViolation ? '>' : ' ';
|
|
63
|
+
output.push(`${prefix} ${lineNum} | ${content}`);
|
|
64
|
+
}
|
|
65
|
+
return output;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Formats a code snippet for JSON export
|
|
69
|
+
*
|
|
70
|
+
* @param snippet - Code snippet to format
|
|
71
|
+
* @returns Object suitable for JSON serialization
|
|
72
|
+
*/
|
|
73
|
+
export function formatSnippetForJSON(snippet) {
|
|
74
|
+
return {
|
|
75
|
+
startLine: snippet.startLine,
|
|
76
|
+
endLine: snippet.endLine,
|
|
77
|
+
lines: snippet.lines.map(line => ({
|
|
78
|
+
line: line.lineNumber,
|
|
79
|
+
content: line.content,
|
|
80
|
+
highlighted: line.isViolation,
|
|
81
|
+
})),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=code-snippet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-snippet.js","sourceRoot":"","sources":["../src/code-snippet.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAclC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,aAAqB,EACrB,eAAuB,CAAC;IAExB,IAAI,CAAC;QACH,uBAAuB;QACvB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACrD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,2CAA2C;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,GAAG,YAAY,CAAC,CAAC;QAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,aAAa,GAAG,YAAY,CAAC,CAAC;QAErE,wDAAwD;QACxD,MAAM,YAAY,GAAe,EAAE,CAAC;QACpC,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB;YACzD,YAAY,CAAC,IAAI,CAAC;gBAChB,UAAU,EAAE,CAAC;gBACb,OAAO,EAAE,WAAW;gBACpB,WAAW,EAAE,CAAC,KAAK,aAAa;aACjC,CAAC,CAAC;QACL,CAAC;QAED,OAAO;YACL,KAAK,EAAE,YAAY;YACnB,SAAS;YACT,OAAO;SACR,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,4CAA4C;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAoB,EACpB,gBAAwB,GAAG;IAE3B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;IAEvD,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;QACvE,IAAI,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QAE3B,sBAAsB;QACtB,IAAI,OAAO,CAAC,MAAM,GAAG,aAAa,EAAE,CAAC;YACnC,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,aAAa,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;QAC5D,CAAC;QAED,kBAAkB;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5C,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,OAAO,MAAM,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoB;IAKvD,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,IAAI,CAAC,UAAU;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus Loader - loads and validates behavioral contract files
|
|
3
|
+
*/
|
|
4
|
+
import type { PackageContract, CorpusLoadResult } from './types.js';
|
|
5
|
+
export interface LoadCorpusOptions {
|
|
6
|
+
includeDrafts?: boolean;
|
|
7
|
+
includeDeprecated?: boolean;
|
|
8
|
+
includeInDevelopment?: boolean;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Loads all behavioral contracts from the corpus directory
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadCorpus(corpusPath: string, options?: LoadCorpusOptions): Promise<CorpusLoadResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Loads a single contract file (for testing)
|
|
16
|
+
*/
|
|
17
|
+
export declare function loadContractFile(filePath: string): PackageContract;
|
|
18
|
+
/**
|
|
19
|
+
* Validates a contract object against the schema
|
|
20
|
+
*/
|
|
21
|
+
export declare function validateContract(contract: PackageContract, schemaPath: string): {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
errors: string[];
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Gets the list of packages that have contracts in the corpus
|
|
27
|
+
*/
|
|
28
|
+
export declare function getAvailablePackages(corpusPath: string): string[];
|
|
29
|
+
/**
|
|
30
|
+
* Finds which packages from the corpus are actually used in a TypeScript project
|
|
31
|
+
*/
|
|
32
|
+
export declare function findUsedPackages(projectPackageJson: string, availableContracts: Map<string, PackageContract>): string[];
|
|
33
|
+
//# sourceMappingURL=corpus-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"corpus-loader.d.ts","sourceRoot":"","sources":["../src/corpus-loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAKpE,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAyG3B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAGlE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,MAAM,GACjB;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAatC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAWjE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,kBAAkB,EAAE,MAAM,EAC1B,kBAAkB,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,GAC/C,MAAM,EAAE,CAeV"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Corpus Loader - loads and validates behavioral contract files
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'fs';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { glob } from 'glob';
|
|
7
|
+
import * as YAML from 'yaml';
|
|
8
|
+
import AjvModule from 'ajv';
|
|
9
|
+
// Handle ESM/CJS interop for Ajv
|
|
10
|
+
const Ajv = AjvModule.default || AjvModule;
|
|
11
|
+
/**
|
|
12
|
+
* Loads all behavioral contracts from the corpus directory
|
|
13
|
+
*/
|
|
14
|
+
export async function loadCorpus(corpusPath, options = {}) {
|
|
15
|
+
const contracts = new Map();
|
|
16
|
+
const errors = [];
|
|
17
|
+
const skipped = [];
|
|
18
|
+
// Find all contract.yaml files
|
|
19
|
+
const contractFiles = await glob('**/contract.yaml', {
|
|
20
|
+
cwd: path.join(corpusPath, 'packages'),
|
|
21
|
+
absolute: true,
|
|
22
|
+
});
|
|
23
|
+
if (contractFiles.length === 0) {
|
|
24
|
+
errors.push(`No contract files found in ${corpusPath}/packages`);
|
|
25
|
+
return { contracts, errors };
|
|
26
|
+
}
|
|
27
|
+
// Load JSON Schema for validation
|
|
28
|
+
const schemaPath = path.join(corpusPath, 'schema', 'contract.schema.json');
|
|
29
|
+
let schema;
|
|
30
|
+
try {
|
|
31
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
|
|
32
|
+
schema = JSON.parse(schemaContent);
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
errors.push(`Failed to load schema from ${schemaPath}: ${err}`);
|
|
36
|
+
return { contracts, errors };
|
|
37
|
+
}
|
|
38
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
39
|
+
const validate = ajv.compile(schema);
|
|
40
|
+
// Load and validate each contract
|
|
41
|
+
for (const filePath of contractFiles) {
|
|
42
|
+
try {
|
|
43
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
44
|
+
const contract = YAML.parse(content);
|
|
45
|
+
// Get contract status (default to 'production' if not specified)
|
|
46
|
+
const status = contract.status || 'production';
|
|
47
|
+
// Skip in-development contracts silently (to avoid errors during development)
|
|
48
|
+
if (status === 'in-development' && !options.includeInDevelopment) {
|
|
49
|
+
skipped.push({
|
|
50
|
+
package: contract.package || path.basename(path.dirname(filePath)),
|
|
51
|
+
status: 'in-development',
|
|
52
|
+
reason: 'Contract is in development (use --include-drafts to include)'
|
|
53
|
+
});
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
// Validate against JSON Schema
|
|
57
|
+
const valid = validate(contract);
|
|
58
|
+
if (!valid) {
|
|
59
|
+
// If it's in-development and validation fails, skip silently
|
|
60
|
+
if (status === 'in-development') {
|
|
61
|
+
skipped.push({
|
|
62
|
+
package: contract.package || path.basename(path.dirname(filePath)),
|
|
63
|
+
status: 'in-development',
|
|
64
|
+
reason: 'Contract validation failed (in-development)'
|
|
65
|
+
});
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const validationErrors = validate.errors
|
|
69
|
+
?.map((err) => ` ${err.instancePath} ${err.message}`)
|
|
70
|
+
.join('\n');
|
|
71
|
+
errors.push(`Invalid contract ${filePath}:\n${validationErrors}`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
// Filter by status
|
|
75
|
+
if (status === 'draft' && !options.includeDrafts) {
|
|
76
|
+
skipped.push({
|
|
77
|
+
package: contract.package,
|
|
78
|
+
status: 'draft',
|
|
79
|
+
reason: 'Draft contract excluded (use --include-drafts to include)'
|
|
80
|
+
});
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (status === 'deprecated' && !options.includeDeprecated) {
|
|
84
|
+
skipped.push({
|
|
85
|
+
package: contract.package,
|
|
86
|
+
status: 'deprecated',
|
|
87
|
+
reason: 'Deprecated contract excluded (use --include-deprecated to include)'
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// Check for duplicate package names
|
|
92
|
+
if (contracts.has(contract.package)) {
|
|
93
|
+
errors.push(`Duplicate contract for package "${contract.package}" found at ${filePath}`);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
contracts.set(contract.package, contract);
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
errors.push(`Failed to load contract ${filePath}: ${err}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { contracts, errors, skipped };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Loads a single contract file (for testing)
|
|
106
|
+
*/
|
|
107
|
+
export function loadContractFile(filePath) {
|
|
108
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
109
|
+
return YAML.parse(content);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Validates a contract object against the schema
|
|
113
|
+
*/
|
|
114
|
+
export function validateContract(contract, schemaPath) {
|
|
115
|
+
const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
|
|
116
|
+
const schema = JSON.parse(schemaContent);
|
|
117
|
+
const ajv = new Ajv({ allErrors: true, strict: false });
|
|
118
|
+
const validate = ajv.compile(schema);
|
|
119
|
+
const valid = validate(contract);
|
|
120
|
+
const errors = valid
|
|
121
|
+
? []
|
|
122
|
+
: (validate.errors?.map((err) => `${err.instancePath} ${err.message}`) || []);
|
|
123
|
+
return { valid, errors };
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Gets the list of packages that have contracts in the corpus
|
|
127
|
+
*/
|
|
128
|
+
export function getAvailablePackages(corpusPath) {
|
|
129
|
+
const packagesDir = path.join(corpusPath, 'packages');
|
|
130
|
+
if (!fs.existsSync(packagesDir)) {
|
|
131
|
+
return [];
|
|
132
|
+
}
|
|
133
|
+
return fs
|
|
134
|
+
.readdirSync(packagesDir, { withFileTypes: true })
|
|
135
|
+
.filter(dirent => dirent.isDirectory())
|
|
136
|
+
.map(dirent => dirent.name);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Finds which packages from the corpus are actually used in a TypeScript project
|
|
140
|
+
*/
|
|
141
|
+
export function findUsedPackages(projectPackageJson, availableContracts) {
|
|
142
|
+
try {
|
|
143
|
+
const packageJson = JSON.parse(fs.readFileSync(projectPackageJson, 'utf-8'));
|
|
144
|
+
const dependencies = {
|
|
145
|
+
...packageJson.dependencies,
|
|
146
|
+
...packageJson.devDependencies,
|
|
147
|
+
};
|
|
148
|
+
return Array.from(availableContracts.keys()).filter(packageName => packageName in dependencies);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
console.warn(`Could not read ${projectPackageJson}: ${err}`);
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=corpus-loader.js.map
|