@behavioral-contracts/verify-cli 1.0.0 → 1.2.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/dist/ai-prompt-generator.d.ts +16 -0
- package/dist/ai-prompt-generator.d.ts.map +1 -0
- package/dist/ai-prompt-generator.js +481 -0
- package/dist/ai-prompt-generator.js.map +1 -0
- package/dist/analyzer.d.ts +41 -0
- package/dist/analyzer.d.ts.map +1 -1
- package/dist/analyzer.js +93 -1
- package/dist/analyzer.js.map +1 -1
- package/dist/analyzers/event-listener-analyzer.d.ts +39 -4
- package/dist/analyzers/event-listener-analyzer.d.ts.map +1 -1
- package/dist/analyzers/event-listener-analyzer.js +123 -10
- package/dist/analyzers/event-listener-analyzer.js.map +1 -1
- package/dist/cli/suppressions.d.ts +9 -0
- package/dist/cli/suppressions.d.ts.map +1 -0
- package/dist/cli/suppressions.js +242 -0
- package/dist/cli/suppressions.js.map +1 -0
- package/dist/index.js +93 -38
- package/dist/index.js.map +1 -1
- package/dist/suppressions/config-loader.d.ts +47 -0
- package/dist/suppressions/config-loader.d.ts.map +1 -0
- package/dist/suppressions/config-loader.js +214 -0
- package/dist/suppressions/config-loader.js.map +1 -0
- package/dist/suppressions/dead-suppression-detector.d.ts +45 -0
- package/dist/suppressions/dead-suppression-detector.d.ts.map +1 -0
- package/dist/suppressions/dead-suppression-detector.js +101 -0
- package/dist/suppressions/dead-suppression-detector.js.map +1 -0
- package/dist/suppressions/index.d.ts +12 -0
- package/dist/suppressions/index.d.ts.map +1 -0
- package/dist/suppressions/index.js +18 -0
- package/dist/suppressions/index.js.map +1 -0
- package/dist/suppressions/manifest.d.ts +114 -0
- package/dist/suppressions/manifest.d.ts.map +1 -0
- package/dist/suppressions/manifest.js +281 -0
- package/dist/suppressions/manifest.js.map +1 -0
- package/dist/suppressions/matcher.d.ts +73 -0
- package/dist/suppressions/matcher.d.ts.map +1 -0
- package/dist/suppressions/matcher.js +163 -0
- package/dist/suppressions/matcher.js.map +1 -0
- package/dist/suppressions/parser.d.ts +59 -0
- package/dist/suppressions/parser.d.ts.map +1 -0
- package/dist/suppressions/parser.js +156 -0
- package/dist/suppressions/parser.js.map +1 -0
- package/dist/suppressions/types.d.ts +121 -0
- package/dist/suppressions/types.d.ts.map +1 -0
- package/dist/suppressions/types.js +8 -0
- package/dist/suppressions/types.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dead Suppression Detector
|
|
3
|
+
*
|
|
4
|
+
* Detects suppressions that are no longer needed because the analyzer has improved.
|
|
5
|
+
*/
|
|
6
|
+
import { loadManifestSync, saveManifestSync } from './manifest.js';
|
|
7
|
+
/**
|
|
8
|
+
* Detect dead suppressions in the manifest
|
|
9
|
+
*
|
|
10
|
+
* A dead suppression is one where stillViolates is false,
|
|
11
|
+
* meaning the analyzer no longer flags this location.
|
|
12
|
+
*
|
|
13
|
+
* @param projectRoot - Project root directory
|
|
14
|
+
* @param currentVersion - Current analyzer version
|
|
15
|
+
* @returns Array of dead suppressions
|
|
16
|
+
*/
|
|
17
|
+
export function detectDeadSuppressions(projectRoot, currentVersion) {
|
|
18
|
+
const manifest = loadManifestSync(projectRoot);
|
|
19
|
+
const deadSuppressions = [];
|
|
20
|
+
for (const suppression of manifest.suppressions) {
|
|
21
|
+
if (!suppression.stillViolates) {
|
|
22
|
+
deadSuppressions.push({
|
|
23
|
+
suppression,
|
|
24
|
+
improvedInVersion: currentVersion,
|
|
25
|
+
originalVersion: suppression.analyzerVersion,
|
|
26
|
+
improvementReason: `Analyzer ${currentVersion} no longer flags this pattern`
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return deadSuppressions;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Remove dead suppressions from manifest
|
|
34
|
+
*
|
|
35
|
+
* @param projectRoot - Project root directory
|
|
36
|
+
* @returns Number of dead suppressions removed
|
|
37
|
+
*/
|
|
38
|
+
export function removeDeadSuppressionsFromManifest(projectRoot) {
|
|
39
|
+
const manifest = loadManifestSync(projectRoot);
|
|
40
|
+
const beforeCount = manifest.suppressions.length;
|
|
41
|
+
manifest.suppressions = manifest.suppressions.filter(s => s.stillViolates);
|
|
42
|
+
saveManifestSync(manifest);
|
|
43
|
+
return beforeCount - manifest.suppressions.length;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get dead suppression summary
|
|
47
|
+
*
|
|
48
|
+
* @param deadSuppressions - Array of dead suppressions
|
|
49
|
+
* @returns Summary object
|
|
50
|
+
*/
|
|
51
|
+
export function getDeadSuppressionSummary(deadSuppressions) {
|
|
52
|
+
const byPackage = new Map();
|
|
53
|
+
const byFile = new Map();
|
|
54
|
+
let oldestDate = null;
|
|
55
|
+
let newestDate = null;
|
|
56
|
+
for (const dead of deadSuppressions) {
|
|
57
|
+
// Count by package
|
|
58
|
+
const packageCount = byPackage.get(dead.suppression.package) || 0;
|
|
59
|
+
byPackage.set(dead.suppression.package, packageCount + 1);
|
|
60
|
+
// Count by file
|
|
61
|
+
const fileCount = byFile.get(dead.suppression.file) || 0;
|
|
62
|
+
byFile.set(dead.suppression.file, fileCount + 1);
|
|
63
|
+
// Track dates
|
|
64
|
+
const suppressedAt = new Date(dead.suppression.suppressedAt);
|
|
65
|
+
if (!oldestDate || suppressedAt < oldestDate) {
|
|
66
|
+
oldestDate = suppressedAt;
|
|
67
|
+
}
|
|
68
|
+
if (!newestDate || suppressedAt > newestDate) {
|
|
69
|
+
newestDate = suppressedAt;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
totalDead: deadSuppressions.length,
|
|
74
|
+
byPackage,
|
|
75
|
+
byFile,
|
|
76
|
+
oldestSuppression: oldestDate,
|
|
77
|
+
newestSuppression: newestDate
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Format dead suppression for display
|
|
82
|
+
*
|
|
83
|
+
* @param dead - Dead suppression
|
|
84
|
+
* @returns Formatted string
|
|
85
|
+
*/
|
|
86
|
+
export function formatDeadSuppression(dead) {
|
|
87
|
+
const s = dead.suppression;
|
|
88
|
+
const daysAgo = Math.floor((Date.now() - new Date(s.suppressedAt).getTime()) / (1000 * 60 * 60 * 24));
|
|
89
|
+
return [
|
|
90
|
+
`├─ ${s.file}:${s.line}`,
|
|
91
|
+
`│ Package: ${s.package}`,
|
|
92
|
+
`│ Postcondition: ${s.postconditionId}`,
|
|
93
|
+
`│ Suppressed: ${new Date(s.suppressedAt).toISOString().split('T')[0]} (${daysAgo} days ago)`,
|
|
94
|
+
`│ Analyzer: ${dead.originalVersion} → ${dead.improvedInVersion}`,
|
|
95
|
+
`│`,
|
|
96
|
+
`│ Why improved: ${dead.improvementReason || 'Analyzer no longer flags this pattern'}`,
|
|
97
|
+
`│ Action: Remove @behavioral-contract-ignore comment at line ${s.line}`,
|
|
98
|
+
`│`
|
|
99
|
+
].join('\n');
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=dead-suppression-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dead-suppression-detector.js","sourceRoot":"","sources":["../../src/suppressions/dead-suppression-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suppression System
|
|
3
|
+
*
|
|
4
|
+
* Public API for suppressing false positive violations and detecting dead suppressions.
|
|
5
|
+
*/
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
export { parseInlineSuppressions, getSuppressionForLine, suppressionMatches, validateSuppressionComment, generateSuppressionComment, getNodeComments } from './parser.js';
|
|
8
|
+
export { loadConfig, loadConfigSync, ruleMatches, findMatchingRules, createDefaultConfig } from './config-loader.js';
|
|
9
|
+
export { loadManifest, loadManifestSync, saveManifest, saveManifestSync, createManifest, upsertSuppression, removeSuppression, findSuppression, generateSuppressionId, createSuppression, getDeadSuppressions, getActiveSuppressions, removeDeadSuppressions } from './manifest.js';
|
|
10
|
+
export { checkSuppression, batchCheckSuppressions, getSuppressionStats } from './matcher.js';
|
|
11
|
+
export { detectDeadSuppressions, removeDeadSuppressionsFromManifest, getDeadSuppressionSummary, formatDeadSuppression } from './dead-suppression-detector.js';
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/suppressions/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,YAAY,CAAC;AAG3B,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,EAC1B,0BAA0B,EAC1B,eAAe,EAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,UAAU,EACV,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,sBAAsB,EACtB,kCAAkC,EAClC,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suppression System
|
|
3
|
+
*
|
|
4
|
+
* Public API for suppressing false positive violations and detecting dead suppressions.
|
|
5
|
+
*/
|
|
6
|
+
// Types
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
// Inline comment parsing
|
|
9
|
+
export { parseInlineSuppressions, getSuppressionForLine, suppressionMatches, validateSuppressionComment, generateSuppressionComment, getNodeComments } from './parser.js';
|
|
10
|
+
// Config file loading
|
|
11
|
+
export { loadConfig, loadConfigSync, ruleMatches, findMatchingRules, createDefaultConfig } from './config-loader.js';
|
|
12
|
+
// Manifest management
|
|
13
|
+
export { loadManifest, loadManifestSync, saveManifest, saveManifestSync, createManifest, upsertSuppression, removeSuppression, findSuppression, generateSuppressionId, createSuppression, getDeadSuppressions, getActiveSuppressions, removeDeadSuppressions } from './manifest.js';
|
|
14
|
+
// Suppression checking
|
|
15
|
+
export { checkSuppression, batchCheckSuppressions, getSuppressionStats } from './matcher.js';
|
|
16
|
+
// Dead suppression detection
|
|
17
|
+
export { detectDeadSuppressions, removeDeadSuppressionsFromManifest, getDeadSuppressionSummary, formatDeadSuppression } from './dead-suppression-detector.js';
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/suppressions/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,yBAAyB;AACzB,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,0BAA0B,EAC1B,0BAA0B,EAC1B,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB,sBAAsB;AACtB,OAAO,EACL,UAAU,EACV,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,oBAAoB,CAAC;AAE5B,sBAAsB;AACtB,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,eAAe,CAAC;AAEvB,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAEtB,6BAA6B;AAC7B,OAAO,EACL,sBAAsB,EACtB,kCAAkC,EAClC,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suppression Manifest Management
|
|
3
|
+
*
|
|
4
|
+
* Handles loading, saving, and updating .verify-cli/suppressions.json
|
|
5
|
+
*/
|
|
6
|
+
import { Suppression, SuppressionManifest } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Load suppression manifest from project root
|
|
9
|
+
*
|
|
10
|
+
* @param projectRoot - Absolute path to project root
|
|
11
|
+
* @returns Manifest object (creates new if doesn't exist)
|
|
12
|
+
*/
|
|
13
|
+
export declare function loadManifest(projectRoot: string): Promise<SuppressionManifest>;
|
|
14
|
+
/**
|
|
15
|
+
* Load manifest synchronously
|
|
16
|
+
*
|
|
17
|
+
* @param projectRoot - Absolute path to project root
|
|
18
|
+
* @returns Manifest object
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadManifestSync(projectRoot: string): SuppressionManifest;
|
|
21
|
+
/**
|
|
22
|
+
* Save suppression manifest to disk
|
|
23
|
+
*
|
|
24
|
+
* @param manifest - Manifest to save
|
|
25
|
+
*/
|
|
26
|
+
export declare function saveManifest(manifest: SuppressionManifest): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Save manifest synchronously
|
|
29
|
+
*
|
|
30
|
+
* @param manifest - Manifest to save
|
|
31
|
+
*/
|
|
32
|
+
export declare function saveManifestSync(manifest: SuppressionManifest): void;
|
|
33
|
+
/**
|
|
34
|
+
* Create a new empty manifest
|
|
35
|
+
*
|
|
36
|
+
* @param projectRoot - Absolute path to project root
|
|
37
|
+
* @returns New manifest
|
|
38
|
+
*/
|
|
39
|
+
export declare function createManifest(projectRoot: string): SuppressionManifest;
|
|
40
|
+
/**
|
|
41
|
+
* Add or update a suppression in the manifest
|
|
42
|
+
*
|
|
43
|
+
* @param manifest - Manifest to update
|
|
44
|
+
* @param suppression - Suppression to add or update
|
|
45
|
+
* @returns Updated manifest
|
|
46
|
+
*/
|
|
47
|
+
export declare function upsertSuppression(manifest: SuppressionManifest, suppression: Suppression): SuppressionManifest;
|
|
48
|
+
/**
|
|
49
|
+
* Remove a suppression from the manifest
|
|
50
|
+
*
|
|
51
|
+
* @param manifest - Manifest to update
|
|
52
|
+
* @param suppressionId - ID of suppression to remove
|
|
53
|
+
* @returns Updated manifest
|
|
54
|
+
*/
|
|
55
|
+
export declare function removeSuppression(manifest: SuppressionManifest, suppressionId: string): SuppressionManifest;
|
|
56
|
+
/**
|
|
57
|
+
* Find a suppression by location
|
|
58
|
+
*
|
|
59
|
+
* @param manifest - Manifest to search
|
|
60
|
+
* @param file - File path (relative to project root)
|
|
61
|
+
* @param line - Line number
|
|
62
|
+
* @param packageName - Package name
|
|
63
|
+
* @param postconditionId - Postcondition ID
|
|
64
|
+
* @returns Suppression if found, undefined otherwise
|
|
65
|
+
*/
|
|
66
|
+
export declare function findSuppression(manifest: SuppressionManifest, file: string, line: number, packageName: string, postconditionId: string): Suppression | undefined;
|
|
67
|
+
/**
|
|
68
|
+
* Generate a unique suppression ID
|
|
69
|
+
*
|
|
70
|
+
* @param file - File path
|
|
71
|
+
* @param line - Line number
|
|
72
|
+
* @param packageName - Package name
|
|
73
|
+
* @param postconditionId - Postcondition ID
|
|
74
|
+
* @returns Unique ID string
|
|
75
|
+
*/
|
|
76
|
+
export declare function generateSuppressionId(file: string, line: number, packageName: string, postconditionId: string): string;
|
|
77
|
+
/**
|
|
78
|
+
* Create a suppression object
|
|
79
|
+
*
|
|
80
|
+
* @param options - Suppression options
|
|
81
|
+
* @returns Suppression object
|
|
82
|
+
*/
|
|
83
|
+
export declare function createSuppression(options: {
|
|
84
|
+
file: string;
|
|
85
|
+
line: number;
|
|
86
|
+
column?: number;
|
|
87
|
+
packageName: string;
|
|
88
|
+
postconditionId: string;
|
|
89
|
+
reason: string;
|
|
90
|
+
suppressedBy: Suppression['suppressedBy'];
|
|
91
|
+
analyzerVersion: string;
|
|
92
|
+
}): Suppression;
|
|
93
|
+
/**
|
|
94
|
+
* Get all dead suppressions (stillViolates: false)
|
|
95
|
+
*
|
|
96
|
+
* @param manifest - Manifest to search
|
|
97
|
+
* @returns Array of dead suppressions
|
|
98
|
+
*/
|
|
99
|
+
export declare function getDeadSuppressions(manifest: SuppressionManifest): Suppression[];
|
|
100
|
+
/**
|
|
101
|
+
* Get all active suppressions (stillViolates: true)
|
|
102
|
+
*
|
|
103
|
+
* @param manifest - Manifest to search
|
|
104
|
+
* @returns Array of active suppressions
|
|
105
|
+
*/
|
|
106
|
+
export declare function getActiveSuppressions(manifest: SuppressionManifest): Suppression[];
|
|
107
|
+
/**
|
|
108
|
+
* Remove all dead suppressions from manifest
|
|
109
|
+
*
|
|
110
|
+
* @param manifest - Manifest to clean
|
|
111
|
+
* @returns Updated manifest
|
|
112
|
+
*/
|
|
113
|
+
export declare function removeDeadSuppressions(manifest: SuppressionManifest): SuppressionManifest;
|
|
114
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/suppressions/manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAM9D;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAyB9B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,CAyBzE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAa/E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAapE;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,CAOvE;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,WAAW,GACvB,mBAAmB,CAYrB;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,mBAAmB,EAC7B,aAAa,EAAE,MAAM,GACpB,mBAAmB,CAGrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,mBAAmB,EAC7B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,WAAW,GAAG,SAAS,CAQzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,MAAM,CASR;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC1C,eAAe,EAAE,MAAM,CAAC;CACzB,GAAG,WAAW,CAwBd;AAwED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,WAAW,EAAE,CAEhF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,WAAW,EAAE,CAElF;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,mBAAmB,GAAG,mBAAmB,CAGzF"}
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suppression Manifest Management
|
|
3
|
+
*
|
|
4
|
+
* Handles loading, saving, and updating .verify-cli/suppressions.json
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'fs';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import * as crypto from 'crypto';
|
|
9
|
+
const MANIFEST_DIR = '.verify-cli';
|
|
10
|
+
const MANIFEST_FILENAME = 'suppressions.json';
|
|
11
|
+
const MANIFEST_VERSION = '1.0.0';
|
|
12
|
+
/**
|
|
13
|
+
* Load suppression manifest from project root
|
|
14
|
+
*
|
|
15
|
+
* @param projectRoot - Absolute path to project root
|
|
16
|
+
* @returns Manifest object (creates new if doesn't exist)
|
|
17
|
+
*/
|
|
18
|
+
export async function loadManifest(projectRoot) {
|
|
19
|
+
const manifestPath = getManifestPath(projectRoot);
|
|
20
|
+
if (!fs.existsSync(manifestPath)) {
|
|
21
|
+
return createManifest(projectRoot);
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
const content = await fs.promises.readFile(manifestPath, 'utf-8');
|
|
25
|
+
const manifest = JSON.parse(content);
|
|
26
|
+
// Validate manifest structure
|
|
27
|
+
validateManifest(manifest);
|
|
28
|
+
// Migrate if needed
|
|
29
|
+
if (manifest.version !== MANIFEST_VERSION) {
|
|
30
|
+
return migrateManifest(manifest, projectRoot);
|
|
31
|
+
}
|
|
32
|
+
return manifest;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
throw new Error(`Failed to load suppression manifest: ${error instanceof Error ? error.message : String(error)}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Load manifest synchronously
|
|
40
|
+
*
|
|
41
|
+
* @param projectRoot - Absolute path to project root
|
|
42
|
+
* @returns Manifest object
|
|
43
|
+
*/
|
|
44
|
+
export function loadManifestSync(projectRoot) {
|
|
45
|
+
const manifestPath = getManifestPath(projectRoot);
|
|
46
|
+
if (!fs.existsSync(manifestPath)) {
|
|
47
|
+
return createManifest(projectRoot);
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
51
|
+
const manifest = JSON.parse(content);
|
|
52
|
+
// Validate manifest structure
|
|
53
|
+
validateManifest(manifest);
|
|
54
|
+
// Migrate if needed
|
|
55
|
+
if (manifest.version !== MANIFEST_VERSION) {
|
|
56
|
+
return migrateManifest(manifest, projectRoot);
|
|
57
|
+
}
|
|
58
|
+
return manifest;
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
throw new Error(`Failed to load suppression manifest: ${error instanceof Error ? error.message : String(error)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Save suppression manifest to disk
|
|
66
|
+
*
|
|
67
|
+
* @param manifest - Manifest to save
|
|
68
|
+
*/
|
|
69
|
+
export async function saveManifest(manifest) {
|
|
70
|
+
const manifestPath = getManifestPath(manifest.projectRoot);
|
|
71
|
+
// Ensure directory exists
|
|
72
|
+
await fs.promises.mkdir(path.dirname(manifestPath), { recursive: true });
|
|
73
|
+
// Update timestamp
|
|
74
|
+
manifest.lastUpdated = new Date().toISOString();
|
|
75
|
+
// Pretty print JSON
|
|
76
|
+
const content = JSON.stringify(manifest, null, 2);
|
|
77
|
+
await fs.promises.writeFile(manifestPath, content, 'utf-8');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Save manifest synchronously
|
|
81
|
+
*
|
|
82
|
+
* @param manifest - Manifest to save
|
|
83
|
+
*/
|
|
84
|
+
export function saveManifestSync(manifest) {
|
|
85
|
+
const manifestPath = getManifestPath(manifest.projectRoot);
|
|
86
|
+
// Ensure directory exists
|
|
87
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
88
|
+
// Update timestamp
|
|
89
|
+
manifest.lastUpdated = new Date().toISOString();
|
|
90
|
+
// Pretty print JSON
|
|
91
|
+
const content = JSON.stringify(manifest, null, 2);
|
|
92
|
+
fs.writeFileSync(manifestPath, content, 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Create a new empty manifest
|
|
96
|
+
*
|
|
97
|
+
* @param projectRoot - Absolute path to project root
|
|
98
|
+
* @returns New manifest
|
|
99
|
+
*/
|
|
100
|
+
export function createManifest(projectRoot) {
|
|
101
|
+
return {
|
|
102
|
+
version: MANIFEST_VERSION,
|
|
103
|
+
projectRoot: path.resolve(projectRoot),
|
|
104
|
+
lastUpdated: new Date().toISOString(),
|
|
105
|
+
suppressions: []
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Add or update a suppression in the manifest
|
|
110
|
+
*
|
|
111
|
+
* @param manifest - Manifest to update
|
|
112
|
+
* @param suppression - Suppression to add or update
|
|
113
|
+
* @returns Updated manifest
|
|
114
|
+
*/
|
|
115
|
+
export function upsertSuppression(manifest, suppression) {
|
|
116
|
+
const existingIndex = manifest.suppressions.findIndex(s => s.id === suppression.id);
|
|
117
|
+
if (existingIndex >= 0) {
|
|
118
|
+
// Update existing suppression
|
|
119
|
+
manifest.suppressions[existingIndex] = suppression;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// Add new suppression
|
|
123
|
+
manifest.suppressions.push(suppression);
|
|
124
|
+
}
|
|
125
|
+
return manifest;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Remove a suppression from the manifest
|
|
129
|
+
*
|
|
130
|
+
* @param manifest - Manifest to update
|
|
131
|
+
* @param suppressionId - ID of suppression to remove
|
|
132
|
+
* @returns Updated manifest
|
|
133
|
+
*/
|
|
134
|
+
export function removeSuppression(manifest, suppressionId) {
|
|
135
|
+
manifest.suppressions = manifest.suppressions.filter(s => s.id !== suppressionId);
|
|
136
|
+
return manifest;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Find a suppression by location
|
|
140
|
+
*
|
|
141
|
+
* @param manifest - Manifest to search
|
|
142
|
+
* @param file - File path (relative to project root)
|
|
143
|
+
* @param line - Line number
|
|
144
|
+
* @param packageName - Package name
|
|
145
|
+
* @param postconditionId - Postcondition ID
|
|
146
|
+
* @returns Suppression if found, undefined otherwise
|
|
147
|
+
*/
|
|
148
|
+
export function findSuppression(manifest, file, line, packageName, postconditionId) {
|
|
149
|
+
return manifest.suppressions.find(s => s.file === file &&
|
|
150
|
+
s.line === line &&
|
|
151
|
+
s.package === packageName &&
|
|
152
|
+
s.postconditionId === postconditionId);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Generate a unique suppression ID
|
|
156
|
+
*
|
|
157
|
+
* @param file - File path
|
|
158
|
+
* @param line - Line number
|
|
159
|
+
* @param packageName - Package name
|
|
160
|
+
* @param postconditionId - Postcondition ID
|
|
161
|
+
* @returns Unique ID string
|
|
162
|
+
*/
|
|
163
|
+
export function generateSuppressionId(file, line, packageName, postconditionId) {
|
|
164
|
+
const data = `${file}:${line}:${packageName}:${postconditionId}`;
|
|
165
|
+
const hash = crypto
|
|
166
|
+
.createHash('sha256')
|
|
167
|
+
.update(data)
|
|
168
|
+
.digest('hex')
|
|
169
|
+
.substring(0, 8);
|
|
170
|
+
return `suppress-${file.replace(/[^a-z0-9]/gi, '-')}-${line}-${hash}`;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Create a suppression object
|
|
174
|
+
*
|
|
175
|
+
* @param options - Suppression options
|
|
176
|
+
* @returns Suppression object
|
|
177
|
+
*/
|
|
178
|
+
export function createSuppression(options) {
|
|
179
|
+
const id = generateSuppressionId(options.file, options.line, options.packageName, options.postconditionId);
|
|
180
|
+
const now = new Date().toISOString();
|
|
181
|
+
return {
|
|
182
|
+
id,
|
|
183
|
+
file: options.file,
|
|
184
|
+
line: options.line,
|
|
185
|
+
column: options.column,
|
|
186
|
+
package: options.packageName,
|
|
187
|
+
postconditionId: options.postconditionId,
|
|
188
|
+
reason: options.reason,
|
|
189
|
+
suppressedAt: now,
|
|
190
|
+
suppressedBy: options.suppressedBy,
|
|
191
|
+
lastChecked: now,
|
|
192
|
+
stillViolates: true,
|
|
193
|
+
analyzerVersion: options.analyzerVersion
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Get path to manifest file
|
|
198
|
+
*
|
|
199
|
+
* @param projectRoot - Project root directory
|
|
200
|
+
* @returns Absolute path to manifest file
|
|
201
|
+
*/
|
|
202
|
+
function getManifestPath(projectRoot) {
|
|
203
|
+
return path.join(projectRoot, MANIFEST_DIR, MANIFEST_FILENAME);
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Validate manifest structure
|
|
207
|
+
*
|
|
208
|
+
* @param manifest - Manifest to validate
|
|
209
|
+
* @throws Error if manifest is invalid
|
|
210
|
+
*/
|
|
211
|
+
function validateManifest(manifest) {
|
|
212
|
+
if (typeof manifest !== 'object' || manifest === null) {
|
|
213
|
+
throw new Error('Manifest must be an object');
|
|
214
|
+
}
|
|
215
|
+
if (!manifest.version || typeof manifest.version !== 'string') {
|
|
216
|
+
throw new Error('Manifest must have a version');
|
|
217
|
+
}
|
|
218
|
+
if (!manifest.projectRoot || typeof manifest.projectRoot !== 'string') {
|
|
219
|
+
throw new Error('Manifest must have a projectRoot');
|
|
220
|
+
}
|
|
221
|
+
if (!manifest.lastUpdated || typeof manifest.lastUpdated !== 'string') {
|
|
222
|
+
throw new Error('Manifest must have a lastUpdated timestamp');
|
|
223
|
+
}
|
|
224
|
+
if (!Array.isArray(manifest.suppressions)) {
|
|
225
|
+
throw new Error('Manifest suppressions must be an array');
|
|
226
|
+
}
|
|
227
|
+
manifest.suppressions.forEach((s, index) => {
|
|
228
|
+
if (!s.id || typeof s.id !== 'string') {
|
|
229
|
+
throw new Error(`Suppression ${index}: Missing or invalid id`);
|
|
230
|
+
}
|
|
231
|
+
if (!s.file || typeof s.file !== 'string') {
|
|
232
|
+
throw new Error(`Suppression ${index}: Missing or invalid file`);
|
|
233
|
+
}
|
|
234
|
+
if (typeof s.line !== 'number') {
|
|
235
|
+
throw new Error(`Suppression ${index}: Missing or invalid line`);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Migrate manifest to current version
|
|
241
|
+
*
|
|
242
|
+
* @param oldManifest - Old manifest
|
|
243
|
+
* @param projectRoot - Project root
|
|
244
|
+
* @returns Migrated manifest
|
|
245
|
+
*/
|
|
246
|
+
function migrateManifest(oldManifest, projectRoot) {
|
|
247
|
+
// Currently only one version, but prepare for future migrations
|
|
248
|
+
const newManifest = createManifest(projectRoot);
|
|
249
|
+
// Copy suppressions
|
|
250
|
+
newManifest.suppressions = oldManifest.suppressions || [];
|
|
251
|
+
return newManifest;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Get all dead suppressions (stillViolates: false)
|
|
255
|
+
*
|
|
256
|
+
* @param manifest - Manifest to search
|
|
257
|
+
* @returns Array of dead suppressions
|
|
258
|
+
*/
|
|
259
|
+
export function getDeadSuppressions(manifest) {
|
|
260
|
+
return manifest.suppressions.filter(s => !s.stillViolates);
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Get all active suppressions (stillViolates: true)
|
|
264
|
+
*
|
|
265
|
+
* @param manifest - Manifest to search
|
|
266
|
+
* @returns Array of active suppressions
|
|
267
|
+
*/
|
|
268
|
+
export function getActiveSuppressions(manifest) {
|
|
269
|
+
return manifest.suppressions.filter(s => s.stillViolates);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Remove all dead suppressions from manifest
|
|
273
|
+
*
|
|
274
|
+
* @param manifest - Manifest to clean
|
|
275
|
+
* @returns Updated manifest
|
|
276
|
+
*/
|
|
277
|
+
export function removeDeadSuppressions(manifest) {
|
|
278
|
+
manifest.suppressions = manifest.suppressions.filter(s => s.stillViolates);
|
|
279
|
+
return manifest;
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/suppressions/manifest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AAGjC,MAAM,YAAY,GAAG,aAAa,CAAC;AACnC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAC9C,MAAM,gBAAgB,GAAG,OAAO,CAAC;AAEjC;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,WAAmB;IAEnB,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAwB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE1D,8BAA8B;QAC9B,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE3B,oBAAoB;QACpB,IAAI,QAAQ,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;YAC1C,OAAO,eAAe,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,wCAAwC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACjG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB;IAClD,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,cAAc,CAAC,WAAW,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAwB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE1D,8BAA8B;QAC9B,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE3B,oBAAoB;QACpB,IAAI,QAAQ,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;YAC1C,OAAO,eAAe,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,wCAAwC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACjG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAA6B;IAC9D,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE3D,0BAA0B;IAC1B,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzE,mBAAmB;IACnB,QAAQ,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEhD,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAElD,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAA6B;IAC5D,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE3D,0BAA0B;IAC1B,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,mBAAmB;IACnB,QAAQ,CAAC,WAAW,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAEhD,oBAAoB;IACpB,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAElD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB;IAChD,OAAO;QACL,OAAO,EAAE,gBAAgB;QACzB,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;QACtC,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACrC,YAAY,EAAE,EAAE;KACjB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA6B,EAC7B,WAAwB;IAExB,MAAM,aAAa,GAAG,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,EAAE,CAAC,CAAC;IAEpF,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QACvB,8BAA8B;QAC9B,QAAQ,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,WAAW,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,sBAAsB;QACtB,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAA6B,EAC7B,aAAqB;IAErB,QAAQ,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,aAAa,CAAC,CAAC;IAClF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAC7B,QAA6B,EAC7B,IAAY,EACZ,IAAY,EACZ,WAAmB,EACnB,eAAuB;IAEvB,OAAO,QAAQ,CAAC,YAAY,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,IAAI,KAAK,IAAI;QACf,CAAC,CAAC,IAAI,KAAK,IAAI;QACf,CAAC,CAAC,OAAO,KAAK,WAAW;QACzB,CAAC,CAAC,eAAe,KAAK,eAAe,CACxC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAY,EACZ,IAAY,EACZ,WAAmB,EACnB,eAAuB;IAEvB,MAAM,IAAI,GAAG,GAAG,IAAI,IAAI,IAAI,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;IACjE,MAAM,IAAI,GAAG,MAAM;SAChB,UAAU,CAAC,QAAQ,CAAC;SACpB,MAAM,CAAC,IAAI,CAAC;SACZ,MAAM,CAAC,KAAK,CAAC;SACb,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAEnB,OAAO,YAAY,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;AACxE,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OASjC;IACC,MAAM,EAAE,GAAG,qBAAqB,CAC9B,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,IAAI,EACZ,OAAO,CAAC,WAAW,EACnB,OAAO,CAAC,eAAe,CACxB,CAAC;IAEF,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAErC,OAAO;QACL,EAAE;QACF,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO,CAAC,WAAW;QAC5B,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,YAAY,EAAE,GAAG;QACjB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,WAAW,EAAE,GAAG;QAChB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,OAAO,CAAC,eAAe;KACzC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,WAAmB;IAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,EAAE,iBAAiB,CAAC,CAAC;AACjE,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,QAA6B;IACrD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,OAAO,IAAI,OAAO,QAAQ,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,OAAO,QAAQ,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,WAAW,IAAI,OAAO,QAAQ,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE;QACzC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,yBAAyB,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,2BAA2B,CAAC,CAAC;QACnE,CAAC;QACD,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,2BAA2B,CAAC,CAAC;QACnE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,eAAe,CACtB,WAAgC,EAChC,WAAmB;IAEnB,gEAAgE;IAChE,MAAM,WAAW,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;IAEhD,oBAAoB;IACpB,WAAW,CAAC,YAAY,GAAG,WAAW,CAAC,YAAY,IAAI,EAAE,CAAC;IAE1D,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAA6B;IAC/D,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAA6B;IACjE,OAAO,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAA6B;IAClE,QAAQ,CAAC,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;IAC3E,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suppression Matcher
|
|
3
|
+
*
|
|
4
|
+
* Combines inline comments and config rules to check if violations are suppressed
|
|
5
|
+
*/
|
|
6
|
+
import * as ts from 'typescript';
|
|
7
|
+
import { SuppressionCheckResult } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for checking suppressions
|
|
10
|
+
*/
|
|
11
|
+
export interface CheckSuppressionOptions {
|
|
12
|
+
/** Project root directory */
|
|
13
|
+
projectRoot: string;
|
|
14
|
+
/** TypeScript source file */
|
|
15
|
+
sourceFile: ts.SourceFile;
|
|
16
|
+
/** Line number of violation (1-indexed) */
|
|
17
|
+
line: number;
|
|
18
|
+
/** Column number of violation (1-indexed) */
|
|
19
|
+
column?: number;
|
|
20
|
+
/** Package name */
|
|
21
|
+
packageName: string;
|
|
22
|
+
/** Postcondition ID */
|
|
23
|
+
postconditionId: string;
|
|
24
|
+
/** Current analyzer version */
|
|
25
|
+
analyzerVersion: string;
|
|
26
|
+
/** Update manifest with suppression metadata */
|
|
27
|
+
updateManifest?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if a violation is suppressed
|
|
31
|
+
*
|
|
32
|
+
* Checks both inline comments and config file rules.
|
|
33
|
+
* Optionally updates manifest with metadata.
|
|
34
|
+
*
|
|
35
|
+
* @param options - Check options
|
|
36
|
+
* @returns Suppression check result
|
|
37
|
+
*/
|
|
38
|
+
export declare function checkSuppression(options: CheckSuppressionOptions): SuppressionCheckResult;
|
|
39
|
+
/**
|
|
40
|
+
* Batch check suppressions for multiple violations
|
|
41
|
+
*
|
|
42
|
+
* @param violations - Array of violations to check
|
|
43
|
+
* @param projectRoot - Project root directory
|
|
44
|
+
* @param analyzerVersion - Current analyzer version
|
|
45
|
+
* @returns Map of violation ID to suppression result
|
|
46
|
+
*/
|
|
47
|
+
export declare function batchCheckSuppressions(violations: Array<{
|
|
48
|
+
id: string;
|
|
49
|
+
sourceFile: ts.SourceFile;
|
|
50
|
+
line: number;
|
|
51
|
+
column?: number;
|
|
52
|
+
packageName: string;
|
|
53
|
+
postconditionId: string;
|
|
54
|
+
}>, projectRoot: string, analyzerVersion: string): Map<string, SuppressionCheckResult>;
|
|
55
|
+
/**
|
|
56
|
+
* Get suppression statistics
|
|
57
|
+
*
|
|
58
|
+
* @param projectRoot - Project root directory
|
|
59
|
+
* @returns Statistics object
|
|
60
|
+
*/
|
|
61
|
+
export declare function getSuppressionStats(projectRoot: string): {
|
|
62
|
+
totalSuppressions: number;
|
|
63
|
+
activeSuppressions: number;
|
|
64
|
+
deadSuppressions: number;
|
|
65
|
+
bySource: {
|
|
66
|
+
inlineComment: number;
|
|
67
|
+
configFile: number;
|
|
68
|
+
aiAgent: number;
|
|
69
|
+
cli: number;
|
|
70
|
+
};
|
|
71
|
+
byPackage: Map<string, number>;
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=matcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../../src/suppressions/matcher.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAQjC,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IAEpB,6BAA6B;IAC7B,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IAE1B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IAEb,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,uBAAuB;IACvB,eAAe,EAAE,MAAM,CAAC;IAExB,+BAA+B;IAC/B,eAAe,EAAE,MAAM,CAAC;IAExB,gDAAgD;IAChD,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CAiFzF;AAgDD;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,KAAK,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC,EACF,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,MAAM,GACtB,GAAG,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAmBrC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG;IACxD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE;QACR,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;IACF,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CA0BA"}
|