oxlint-harness 1.0.9 → 1.0.11

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/command.js CHANGED
@@ -56,7 +56,7 @@ The suppression file format uses counts per rule per file:
56
56
  tighten: Flags.boolean({
57
57
  char: "t",
58
58
  description: "Tighten suppressions by reducing counts when violations are fixed",
59
- default: true,
59
+ default: false,
60
60
  allowNo: true,
61
61
  }),
62
62
  };
@@ -89,7 +89,7 @@ The suppression file format uses counts per rule per file:
89
89
  this.log(" --show-code <number> Show code snippets for files with N or fewer errors (default: 3, 0 to disable)");
90
90
  this.log(" --results-path <path> Path to save oxlint JSON results (default: artifacts/oxlint-results.json)");
91
91
  this.log(" --no-save-results Don't save oxlint JSON results to file");
92
- this.log(" -t, --tighten Tighten suppressions when violations are fixed (default: true)");
92
+ this.log(" -t, --tighten Tighten suppressions when violations are fixed");
93
93
  this.log(" --no-tighten Don't tighten suppressions");
94
94
  this.log(" --no-type-aware Don't pass --type-aware to oxlint (default: passes it)");
95
95
  this.log(" --no-type-check Don't pass --type-check to oxlint (default: passes it)");
@@ -187,7 +187,7 @@ The suppression file format uses counts per rule per file:
187
187
  "results-path": process.env.OXLINT_HARNESS_RESULTS_PATH ||
188
188
  "artifacts/oxlint-results.json",
189
189
  "save-results": true,
190
- tighten: true,
190
+ tighten: false,
191
191
  };
192
192
  // Manually parse known flags and collect unknown ones
193
193
  for (let i = 0; i < rawArgs.length; i++) {
@@ -270,10 +270,11 @@ The suppression file format uses counts per rule per file:
270
270
  }
271
271
  // Handle suppression logic
272
272
  const suppressionManager = new SuppressionManager(flags.suppressions);
273
+ const targetedPaths = oxlintArgs.filter(arg => !arg.startsWith('-'));
273
274
  if (flags.update) {
274
275
  // Update mode: generate/update suppression file
275
276
  const currentSuppressions = suppressionManager.loadSuppressions();
276
- const updatedSuppressions = suppressionManager.updateSuppressions(currentSuppressions, diagnostics);
277
+ const updatedSuppressions = suppressionManager.updateSuppressions(currentSuppressions, diagnostics, targetedPaths.length > 0 ? targetedPaths : undefined);
277
278
  suppressionManager.saveSuppressions(updatedSuppressions);
278
279
  this.log(`${colors.success("Updated suppression file:")} ${colors.filename(flags.suppressions)}`);
279
280
  this.log(`${colors.info("Total diagnostics:")} ${colors.emphasis(diagnostics.length.toString())}`);
@@ -282,15 +283,13 @@ The suppression file format uses counts per rule per file:
282
283
  // Normal mode: check suppressions
283
284
  const suppressions = suppressionManager.loadSuppressions();
284
285
  const excessErrors = suppressionManager.findExcessErrors(diagnostics, suppressions);
285
- // Tighten is on by default; env var can override the flag
286
- let shouldTighten = flags.tighten;
287
- if (process.env.OXLINT_HARNESS_TIGHTEN_BULK_SUPPRESSION?.toLowerCase() ===
288
- "true") {
289
- shouldTighten = true;
290
- }
286
+ // Tighten is opt-in via --tighten flag or env var
287
+ const shouldTighten = flags.tighten ||
288
+ process.env.OXLINT_HARNESS_TIGHTEN_BULK_SUPPRESSION?.toLowerCase() ===
289
+ "true";
291
290
  if (shouldTighten) {
292
291
  // Tighten suppressions by removing/reducing cleaned-up violations
293
- const tightenedSuppressions = suppressionManager.tightenSuppressions(suppressions, diagnostics);
292
+ const tightenedSuppressions = suppressionManager.tightenSuppressions(suppressions, diagnostics, targetedPaths.length > 0 ? targetedPaths : undefined);
294
293
  suppressionManager.saveSuppressions(tightenedSuppressions);
295
294
  this.log(`${colors.success("Tightened suppression file:")} ${colors.filename(flags.suppressions)}`);
296
295
  }
@@ -7,6 +7,7 @@ export declare class SuppressionManager {
7
7
  saveSuppressions(suppressions: SuppressionFile): void;
8
8
  generateSuppressions(diagnostics: ProcessedDiagnostic[]): SuppressionFile;
9
9
  findExcessErrors(diagnostics: ProcessedDiagnostic[], suppressions: SuppressionFile): ExcessError[];
10
- updateSuppressions(currentSuppressions: SuppressionFile, diagnostics: ProcessedDiagnostic[]): SuppressionFile;
11
- tightenSuppressions(currentSuppressions: SuppressionFile, diagnostics: ProcessedDiagnostic[]): SuppressionFile;
10
+ private isFileCoveredByPaths;
11
+ updateSuppressions(currentSuppressions: SuppressionFile, diagnostics: ProcessedDiagnostic[], targetedPaths?: string[]): SuppressionFile;
12
+ tightenSuppressions(currentSuppressions: SuppressionFile, diagnostics: ProcessedDiagnostic[], targetedPaths?: string[]): SuppressionFile;
12
13
  }
@@ -31,6 +31,9 @@ export class SuppressionManager {
31
31
  }
32
32
  }
33
33
  saveSuppressions(suppressions) {
34
+ if (Object.keys(suppressions).length === 0) {
35
+ return;
36
+ }
34
37
  try {
35
38
  const sorted = this.sortSuppressions(suppressions);
36
39
  const content = JSON.stringify(sorted, null, 2);
@@ -93,10 +96,24 @@ export class SuppressionManager {
93
96
  }
94
97
  return excessErrors;
95
98
  }
96
- updateSuppressions(currentSuppressions, diagnostics) {
99
+ isFileCoveredByPaths(filename, paths) {
100
+ return paths.some(path => {
101
+ const normalizedPath = path.replace(/\/+$/, '');
102
+ return filename === normalizedPath || filename.startsWith(normalizedPath + '/');
103
+ });
104
+ }
105
+ updateSuppressions(currentSuppressions, diagnostics, targetedPaths) {
97
106
  const newSuppressions = this.generateSuppressions(diagnostics);
98
107
  // Merge with existing suppressions, using new counts
99
108
  const updated = { ...currentSuppressions };
109
+ // Remove entries for targeted files that have no new diagnostics
110
+ if (targetedPaths && targetedPaths.length > 0) {
111
+ for (const filename of Object.keys(updated)) {
112
+ if (this.isFileCoveredByPaths(filename, targetedPaths) && !newSuppressions[filename]) {
113
+ delete updated[filename];
114
+ }
115
+ }
116
+ }
100
117
  for (const [filename, rules] of Object.entries(newSuppressions)) {
101
118
  updated[filename] = { ...updated[filename], ...rules };
102
119
  }
@@ -108,7 +125,7 @@ export class SuppressionManager {
108
125
  }
109
126
  return this.sortSuppressions(updated);
110
127
  }
111
- tightenSuppressions(currentSuppressions, diagnostics) {
128
+ tightenSuppressions(currentSuppressions, diagnostics, targetedPaths) {
112
129
  // Group diagnostics by file and rule to get actual counts
113
130
  const actualCounts = new Map();
114
131
  for (const diagnostic of diagnostics) {
@@ -123,6 +140,10 @@ export class SuppressionManager {
123
140
  const tightened = { ...currentSuppressions };
124
141
  // Process each file in current suppressions
125
142
  for (const [filename, rules] of Object.entries(tightened)) {
143
+ // Skip files not covered by targeted paths
144
+ if (targetedPaths && targetedPaths.length > 0 && !this.isFileCoveredByPaths(filename, targetedPaths)) {
145
+ continue;
146
+ }
126
147
  const fileRules = { ...rules };
127
148
  // Process each rule in the file
128
149
  for (const [rule, suppression] of Object.entries(fileRules)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-harness",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "description": "A harness for oxlint with bulk suppressions support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -51,5 +51,5 @@
51
51
  "engines": {
52
52
  "node": ">=22"
53
53
  },
54
- "packageManager": "pnpm@9.15.9"
54
+ "packageManager": "pnpm@10.28.0+sha512.05df71d1421f21399e053fde567cea34d446fa02c76571441bfc1c7956e98e363088982d940465fd34480d4d90a0668bc12362f8aa88000a64e83d0b0e47be48"
55
55
  }