@utoo/lint 0.4.10 → 0.4.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/index.cjs +81 -23
- package/index.js +81 -23
- package/package.json +6 -6
- package/schema.json +5 -0
package/index.cjs
CHANGED
|
@@ -1313,6 +1313,9 @@ function appendPluginRuleDiagnostics(report, options, { perFileConfig = true } =
|
|
|
1313
1313
|
let appended = false;
|
|
1314
1314
|
|
|
1315
1315
|
for (const filePath of filePaths) {
|
|
1316
|
+
if ((report.diagnostics ?? []).some((diagnostic) => diagnostic.filePath === filePath && diagnostic.ruleId === "parse" && diagnostic.severity === "error")) {
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1316
1319
|
const matchPath = singleMatchPath ?? filePath;
|
|
1317
1320
|
const ruleMap = jsPluginRuleMapForFile(options, matchPath, perFileConfig);
|
|
1318
1321
|
if (ruleMap.size === 0) {
|
|
@@ -1500,6 +1503,10 @@ function nativeConfigGlobals(config) {
|
|
|
1500
1503
|
return Object.keys(globals).length > 0 ? globals : undefined;
|
|
1501
1504
|
}
|
|
1502
1505
|
|
|
1506
|
+
function nativeConfigSourceType(config) {
|
|
1507
|
+
return config?.languageOptions?.sourceType ?? config?.parserOptions?.sourceType;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1503
1510
|
function isGlobalsObject(value) {
|
|
1504
1511
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
1505
1512
|
}
|
|
@@ -1508,7 +1515,7 @@ function configCanUseNativeRulesFastPath(config) {
|
|
|
1508
1515
|
const entries = Array.isArray(config) ? config : [config];
|
|
1509
1516
|
let hasEnabledRule = false;
|
|
1510
1517
|
for (const entry of entries) {
|
|
1511
|
-
if (!entry || typeof entry !== "object" || Object.keys(entry.settings ?? {}).length > 0 || nativeConfigGlobals(entry)) {
|
|
1518
|
+
if (!entry || typeof entry !== "object" || Object.keys(entry.settings ?? {}).length > 0 || nativeConfigGlobals(entry) || nativeConfigSourceType(entry) !== undefined) {
|
|
1512
1519
|
return false;
|
|
1513
1520
|
}
|
|
1514
1521
|
for (const ruleConfig of Object.values(entry.rules ?? {})) {
|
|
@@ -1537,8 +1544,12 @@ function nativeSerializableConfig(config) {
|
|
|
1537
1544
|
.map((key) => [key, config[key]])
|
|
1538
1545
|
);
|
|
1539
1546
|
const globals = nativeConfigGlobals(config);
|
|
1540
|
-
|
|
1541
|
-
|
|
1547
|
+
const sourceType = nativeConfigSourceType(config);
|
|
1548
|
+
if (globals || sourceType !== undefined) {
|
|
1549
|
+
serialized.languageOptions = {
|
|
1550
|
+
...(globals ? { globals } : {}),
|
|
1551
|
+
...(sourceType === undefined ? {} : { sourceType })
|
|
1552
|
+
};
|
|
1542
1553
|
}
|
|
1543
1554
|
return serialized;
|
|
1544
1555
|
}
|
|
@@ -1620,15 +1631,16 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
1620
1631
|
let rules = calculated.rules;
|
|
1621
1632
|
const settings = calculated.settings;
|
|
1622
1633
|
const globals = configured ? nativeConfigGlobals(calculated) : undefined;
|
|
1634
|
+
const sourceType = configured ? nativeConfigSourceType(calculated) : undefined;
|
|
1623
1635
|
if (configured && options.rules) {
|
|
1624
1636
|
rules = selectedRulesWithConfigOptions(rules, options.rules);
|
|
1625
1637
|
}
|
|
1626
1638
|
if (configured) {
|
|
1627
1639
|
rules = withoutJsPluginRules(rules, jsPluginRuleIdsForOptions(options, matchPath));
|
|
1628
1640
|
}
|
|
1629
|
-
const signature = configured ? stableConfigSignature({ rules, settings, globals }) : "<native-defaults>";
|
|
1641
|
+
const signature = configured ? stableConfigSignature({ rules, settings, globals, sourceType }) : "<native-defaults>";
|
|
1630
1642
|
if (!groups.has(signature)) {
|
|
1631
|
-
groups.set(signature, { paths: [], rules, settings, globals, configured });
|
|
1643
|
+
groups.set(signature, { paths: [], rules, settings, globals, sourceType, configured });
|
|
1632
1644
|
}
|
|
1633
1645
|
groups.get(signature).paths.push(filePath);
|
|
1634
1646
|
}
|
|
@@ -1651,7 +1663,7 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
1651
1663
|
};
|
|
1652
1664
|
}
|
|
1653
1665
|
|
|
1654
|
-
const selectedRules = severityOnlyNativeRuleNames(group.rules, group.settings, group.globals);
|
|
1666
|
+
const selectedRules = severityOnlyNativeRuleNames(group.rules, group.settings, group.globals, group.sourceType);
|
|
1655
1667
|
if (selectedRules) {
|
|
1656
1668
|
return {
|
|
1657
1669
|
paths: group.paths,
|
|
@@ -1677,7 +1689,10 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
1677
1689
|
overrideConfig: {
|
|
1678
1690
|
rules: allDisabledNativeRules(group.rules),
|
|
1679
1691
|
...(group.settings ? { settings: group.settings } : {}),
|
|
1680
|
-
...(group.globals
|
|
1692
|
+
...((group.globals || group.sourceType !== undefined) ? { languageOptions: {
|
|
1693
|
+
...(group.globals ? { globals: group.globals } : {}),
|
|
1694
|
+
...(group.sourceType === undefined ? {} : { sourceType: group.sourceType })
|
|
1695
|
+
} } : {})
|
|
1681
1696
|
},
|
|
1682
1697
|
forceMaterializedConfig: true
|
|
1683
1698
|
}
|
|
@@ -1685,8 +1700,8 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
1685
1700
|
});
|
|
1686
1701
|
}
|
|
1687
1702
|
|
|
1688
|
-
function severityOnlyNativeRuleNames(rules, settings, globals) {
|
|
1689
|
-
if (globals || Object.keys(settings ?? {}).length > 0) {
|
|
1703
|
+
function severityOnlyNativeRuleNames(rules, settings, globals, sourceType) {
|
|
1704
|
+
if (globals || sourceType !== undefined || Object.keys(settings ?? {}).length > 0) {
|
|
1690
1705
|
return undefined;
|
|
1691
1706
|
}
|
|
1692
1707
|
|
|
@@ -1774,7 +1789,7 @@ function lintText(code, options = {}) {
|
|
|
1774
1789
|
|
|
1775
1790
|
const tmp = mkdtempSync(join(tmpdir(), "utoo-lint-"));
|
|
1776
1791
|
const requestedPath = textFilePathForOptions(options, "text.js");
|
|
1777
|
-
const extension = extname(requestedPath) || ".js";
|
|
1792
|
+
const extension = requestedPath.match(/\.d\.(?:ts|mts|cts)$/)?.[0] ?? (extname(requestedPath) || ".js");
|
|
1778
1793
|
const tempFile = join(tmp, `input${extension}`);
|
|
1779
1794
|
const discoveredConfig =
|
|
1780
1795
|
!options.noConfig && !options.config && !options.overrideConfig
|
|
@@ -2350,7 +2365,11 @@ function withTemporaryConfig(options, callback) {
|
|
|
2350
2365
|
{}
|
|
2351
2366
|
);
|
|
2352
2367
|
const hasGlobals = Object.keys(globals).length > 0;
|
|
2353
|
-
|
|
2368
|
+
const sourceType = configs.reduce(
|
|
2369
|
+
(current, config) => nativeConfigSourceType(configDataFromConfig(config, options.filePath ?? options.filename, options.cwd)) ?? current,
|
|
2370
|
+
undefined
|
|
2371
|
+
);
|
|
2372
|
+
if (Object.keys(rules).length === 0 && !hasSettings && !hasGlobals && sourceType === undefined) {
|
|
2354
2373
|
if (shouldMaterializeFileConfig) {
|
|
2355
2374
|
return callback({
|
|
2356
2375
|
...options,
|
|
@@ -2362,7 +2381,7 @@ function withTemporaryConfig(options, callback) {
|
|
|
2362
2381
|
}
|
|
2363
2382
|
const enabledRules = enabledRuleNamesFromConfigs(...configs).filter((rule) => !jsPluginRuleIds.has(rule));
|
|
2364
2383
|
const hasExplicitOffRules = Object.values(rules).some((value) => ruleConfigSeverity(value) === 0);
|
|
2365
|
-
if (!shouldMaterializeFileConfig && !hasSettings && !hasGlobals && !hasRuleOptions(rules) && !hasExplicitOffRules && !options.forceMaterializedConfig) {
|
|
2384
|
+
if (!shouldMaterializeFileConfig && !hasSettings && !hasGlobals && sourceType === undefined && !hasRuleOptions(rules) && !hasExplicitOffRules && !options.forceMaterializedConfig) {
|
|
2366
2385
|
return callback({
|
|
2367
2386
|
...options,
|
|
2368
2387
|
config: shouldMaterializeFileConfig ? undefined : options.config,
|
|
@@ -2377,7 +2396,10 @@ function withTemporaryConfig(options, callback) {
|
|
|
2377
2396
|
writeFileSync(configPath, JSON.stringify({
|
|
2378
2397
|
rules: nativeRules(rules),
|
|
2379
2398
|
...(hasSettings ? { settings } : {}),
|
|
2380
|
-
...(hasGlobals
|
|
2399
|
+
...((hasGlobals || sourceType !== undefined) ? { languageOptions: {
|
|
2400
|
+
...(hasGlobals ? { globals } : {}),
|
|
2401
|
+
...(sourceType === undefined ? {} : { sourceType })
|
|
2402
|
+
} } : {})
|
|
2381
2403
|
}));
|
|
2382
2404
|
return callback({
|
|
2383
2405
|
...options,
|
|
@@ -2496,11 +2518,6 @@ class Linter {
|
|
|
2496
2518
|
const customRuleMap = customRuleMapForConfig(config, this.rules, normalizedFilePath, verifyOptions.cwd);
|
|
2497
2519
|
const customRuleFilterMap = customRuleMapForConfig(config, this.rules);
|
|
2498
2520
|
const customRules = customRuleEntriesForConfig(config, customRuleMap, normalizedFilePath, verifyOptions.cwd);
|
|
2499
|
-
const sourceCode = createLinterSourceCode(
|
|
2500
|
-
code,
|
|
2501
|
-
parserForConfig(config, this.parsers, normalizedFilePath, verifyOptions.cwd),
|
|
2502
|
-
{ ...parserOptionsForConfig(config, normalizedFilePath, verifyOptions.cwd), requireParser: customRules.length > 0 }
|
|
2503
|
-
);
|
|
2504
2521
|
const nativeConfig = configWithoutCustomRules(config, customRuleFilterMap);
|
|
2505
2522
|
const lintOptions = {
|
|
2506
2523
|
cwd: verifyOptions.cwd,
|
|
@@ -2512,6 +2529,22 @@ class Linter {
|
|
|
2512
2529
|
};
|
|
2513
2530
|
const report = lintText(code, lintOptions);
|
|
2514
2531
|
const ruleSeverities = ruleSeverityMapForOptions(lintOptions, normalizedFilePath);
|
|
2532
|
+
const nativeMessages = (report.diagnostics ?? [])
|
|
2533
|
+
.filter((diagnostic) => !isRuleDefinitionError(diagnostic) || !customRuleMap.has(diagnostic.ruleId))
|
|
2534
|
+
.map((diagnostic) => diagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
2535
|
+
if (nativeMessages.some((message) => message.fatal)) {
|
|
2536
|
+
this.sourceCode = null;
|
|
2537
|
+
this.suppressedMessages = (report.suppressedDiagnostics ?? [])
|
|
2538
|
+
.map((diagnostic) => suppressedDiagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
2539
|
+
this.times = { passes: [] };
|
|
2540
|
+
this.fixPassCount = 0;
|
|
2541
|
+
return sortLintMessages(nativeMessages);
|
|
2542
|
+
}
|
|
2543
|
+
const sourceCode = createLinterSourceCode(
|
|
2544
|
+
code,
|
|
2545
|
+
parserForConfig(config, this.parsers, normalizedFilePath, verifyOptions.cwd),
|
|
2546
|
+
{ ...parserOptionsForConfig(config, normalizedFilePath, verifyOptions.cwd), requireParser: customRules.length > 0 }
|
|
2547
|
+
);
|
|
2515
2548
|
this.sourceCode = sourceCode;
|
|
2516
2549
|
const customRuleMessages = runCustomLinterRules(customRules, sourceCode, {
|
|
2517
2550
|
cwd: verifyOptions.cwd,
|
|
@@ -2519,7 +2552,7 @@ class Linter {
|
|
|
2519
2552
|
config: calculatedConfig({ cwd: verifyOptions.cwd, noConfig: true, overrideConfig: config }, normalizedFilePath)
|
|
2520
2553
|
});
|
|
2521
2554
|
const nativeRuleFilter = applyDisableDirectives(
|
|
2522
|
-
|
|
2555
|
+
nativeMessages,
|
|
2523
2556
|
sourceCode
|
|
2524
2557
|
);
|
|
2525
2558
|
const customRuleFilter = applyDisableDirectives(customRuleMessages, sourceCode);
|
|
@@ -2901,6 +2934,9 @@ function appendCustomLintTextMessages(results, code, filePath, config, rules, op
|
|
|
2901
2934
|
return results;
|
|
2902
2935
|
}
|
|
2903
2936
|
let result = results.find((item) => item.filePath === filePath);
|
|
2937
|
+
if (result?.fatalErrorCount > 0) {
|
|
2938
|
+
return results;
|
|
2939
|
+
}
|
|
2904
2940
|
const effectiveCode = typeof result?.output === "string" ? result.output : code;
|
|
2905
2941
|
const sourceCode = createLinterSourceCode(effectiveCode, null, { ...parserOptionsForConfig(config, filePath, options.cwd), requireParser: true });
|
|
2906
2942
|
const messages = runCustomLinterRules(customRules, sourceCode, {
|
|
@@ -2987,6 +3023,9 @@ function relintAfterCustomFixes(result, code, filePath, customRules, config, rul
|
|
|
2987
3023
|
|
|
2988
3024
|
function appendCustomLintFileMessages(results, config, options) {
|
|
2989
3025
|
for (const result of results) {
|
|
3026
|
+
if (result.fatalErrorCount > 0) {
|
|
3027
|
+
continue;
|
|
3028
|
+
}
|
|
2990
3029
|
const filePath = result.filePath;
|
|
2991
3030
|
const rules = customRuleMapForConfig(config, new Map(), filePath, options.cwd);
|
|
2992
3031
|
const customRules = customRuleEntriesForConfig(config, rules, filePath, options.cwd);
|
|
@@ -3106,7 +3145,7 @@ function applyDisableDirectives(messages, sourceCode) {
|
|
|
3106
3145
|
const kept = [];
|
|
3107
3146
|
const suppressed = [];
|
|
3108
3147
|
for (const message of messages) {
|
|
3109
|
-
if (!message.ruleId || message.ruleId === "parse" || message.ruleId === "io") {
|
|
3148
|
+
if (!message.ruleId || message.ruleId === "parse" || message.ruleId === "io" || isRuleDefinitionError(message)) {
|
|
3110
3149
|
kept.push(message);
|
|
3111
3150
|
continue;
|
|
3112
3151
|
}
|
|
@@ -4520,7 +4559,7 @@ function reportToESLintResults(report, textOptions = {}) {
|
|
|
4520
4559
|
byFile.set(filePath, emptyESLintResult(filePath, textOptions.source));
|
|
4521
4560
|
}
|
|
4522
4561
|
const ruleSeverities = textOptions.ruleSeverityForFile?.(filePath) ?? textOptions.ruleSeverities;
|
|
4523
|
-
if (diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4562
|
+
if (!isRuleDefinitionError(diagnostic) && diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4524
4563
|
continue;
|
|
4525
4564
|
}
|
|
4526
4565
|
byFile.get(filePath).messages.push(diagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
@@ -4532,7 +4571,7 @@ function reportToESLintResults(report, textOptions = {}) {
|
|
|
4532
4571
|
byFile.set(filePath, emptyESLintResult(filePath, textOptions.source));
|
|
4533
4572
|
}
|
|
4534
4573
|
const ruleSeverities = textOptions.ruleSeverityForFile?.(filePath) ?? textOptions.ruleSeverities;
|
|
4535
|
-
if (diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4574
|
+
if (!isRuleDefinitionError(diagnostic) && diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4536
4575
|
continue;
|
|
4537
4576
|
}
|
|
4538
4577
|
byFile.get(filePath).suppressedMessages.push(suppressedDiagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
@@ -4588,8 +4627,19 @@ function applyCompatibilityDisableDirectives(result, textOptions) {
|
|
|
4588
4627
|
result.suppressedMessages.push(...filtered.suppressedMessages);
|
|
4589
4628
|
}
|
|
4590
4629
|
|
|
4630
|
+
function isRuleDefinitionError(diagnostic) {
|
|
4631
|
+
return typeof diagnostic?.ruleId === "string"
|
|
4632
|
+
&& diagnostic.message === `Definition for rule '${diagnostic.ruleId}' was not found.`;
|
|
4633
|
+
}
|
|
4634
|
+
|
|
4591
4635
|
function normalizeReportDiagnostics(diagnostics, options = {}) {
|
|
4592
4636
|
return (diagnostics ?? []).flatMap((diagnostic) => {
|
|
4637
|
+
if (isRuleDefinitionError(diagnostic)) {
|
|
4638
|
+
// Native cannot see JS plugin definitions. A mounted rule is known even
|
|
4639
|
+
// when it is disabled or emits no messages for this file.
|
|
4640
|
+
const filePath = options.pluginTextFilePath ?? diagnostic.filePath;
|
|
4641
|
+
return jsPluginRuleMapForFile(options, filePath).has(diagnostic.ruleId) ? [] : [diagnostic];
|
|
4642
|
+
}
|
|
4593
4643
|
if (!diagnostic?.ruleId) {
|
|
4594
4644
|
return [diagnostic];
|
|
4595
4645
|
}
|
|
@@ -5311,12 +5361,18 @@ function emptyESLintResult(filePath, source) {
|
|
|
5311
5361
|
function diagnosticToESLintMessage(diagnostic, ruleSeverities) {
|
|
5312
5362
|
const message = {
|
|
5313
5363
|
ruleId: diagnostic.ruleId,
|
|
5314
|
-
severity:
|
|
5364
|
+
severity: isRuleDefinitionError(diagnostic)
|
|
5365
|
+
? 2
|
|
5366
|
+
: ruleSeverities?.get(diagnostic.ruleId) ?? (diagnostic.severity === "error" ? 2 : 1),
|
|
5315
5367
|
message: diagnostic.message,
|
|
5316
5368
|
line: diagnostic.line,
|
|
5317
5369
|
column: diagnostic.column,
|
|
5318
5370
|
nodeType: null
|
|
5319
5371
|
};
|
|
5372
|
+
if (diagnostic.ruleId === "parse" && diagnostic.severity === "error") {
|
|
5373
|
+
message.fatal = true;
|
|
5374
|
+
message.severity = 2;
|
|
5375
|
+
}
|
|
5320
5376
|
if (typeof diagnostic.endLine === "number") {
|
|
5321
5377
|
message.endLine = diagnostic.endLine;
|
|
5322
5378
|
}
|
|
@@ -5367,11 +5423,13 @@ function suppressedDiagnosticToESLintMessage(diagnostic, ruleSeverities) {
|
|
|
5367
5423
|
}
|
|
5368
5424
|
|
|
5369
5425
|
function finalizeESLintResult(result) {
|
|
5426
|
+
result.fatalErrorCount = 0;
|
|
5370
5427
|
result.errorCount = 0;
|
|
5371
5428
|
result.warningCount = 0;
|
|
5372
5429
|
result.fixableErrorCount = 0;
|
|
5373
5430
|
result.fixableWarningCount = 0;
|
|
5374
5431
|
for (const message of result.messages) {
|
|
5432
|
+
if (message.fatal) result.fatalErrorCount += 1;
|
|
5375
5433
|
if (message.severity === 2) {
|
|
5376
5434
|
result.errorCount += 1;
|
|
5377
5435
|
if (ruleFixItems(message.fix).length > 0) {
|
package/index.js
CHANGED
|
@@ -675,11 +675,6 @@ export class Linter {
|
|
|
675
675
|
const customRuleMap = customRuleMapForConfig(config, this.rules, normalizedFilePath, verifyOptions.cwd);
|
|
676
676
|
const customRuleFilterMap = customRuleMapForConfig(config, this.rules);
|
|
677
677
|
const customRules = customRuleEntriesForConfig(config, customRuleMap, normalizedFilePath, verifyOptions.cwd);
|
|
678
|
-
const sourceCode = createLinterSourceCode(
|
|
679
|
-
code,
|
|
680
|
-
parserForConfig(config, this.parsers, normalizedFilePath, verifyOptions.cwd),
|
|
681
|
-
{ ...parserOptionsForConfig(config, normalizedFilePath, verifyOptions.cwd), requireParser: customRules.length > 0 }
|
|
682
|
-
);
|
|
683
678
|
const nativeConfig = configWithoutCustomRules(config, customRuleFilterMap);
|
|
684
679
|
const lintOptions = {
|
|
685
680
|
cwd: verifyOptions.cwd,
|
|
@@ -691,6 +686,22 @@ export class Linter {
|
|
|
691
686
|
};
|
|
692
687
|
const report = lintText(code, lintOptions);
|
|
693
688
|
const ruleSeverities = ruleSeverityMapForOptions(lintOptions, normalizedFilePath);
|
|
689
|
+
const nativeMessages = (report.diagnostics ?? [])
|
|
690
|
+
.filter((diagnostic) => !isRuleDefinitionError(diagnostic) || !customRuleMap.has(diagnostic.ruleId))
|
|
691
|
+
.map((diagnostic) => diagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
692
|
+
if (nativeMessages.some((message) => message.fatal)) {
|
|
693
|
+
this.sourceCode = null;
|
|
694
|
+
this.suppressedMessages = (report.suppressedDiagnostics ?? [])
|
|
695
|
+
.map((diagnostic) => suppressedDiagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
696
|
+
this.times = { passes: [] };
|
|
697
|
+
this.fixPassCount = 0;
|
|
698
|
+
return sortLintMessages(nativeMessages);
|
|
699
|
+
}
|
|
700
|
+
const sourceCode = createLinterSourceCode(
|
|
701
|
+
code,
|
|
702
|
+
parserForConfig(config, this.parsers, normalizedFilePath, verifyOptions.cwd),
|
|
703
|
+
{ ...parserOptionsForConfig(config, normalizedFilePath, verifyOptions.cwd), requireParser: customRules.length > 0 }
|
|
704
|
+
);
|
|
694
705
|
this.sourceCode = sourceCode;
|
|
695
706
|
const customRuleMessages = runCustomLinterRules(customRules, sourceCode, {
|
|
696
707
|
cwd: verifyOptions.cwd,
|
|
@@ -698,7 +709,7 @@ export class Linter {
|
|
|
698
709
|
config: calculatedConfig({ cwd: verifyOptions.cwd, noConfig: true, overrideConfig: config }, normalizedFilePath)
|
|
699
710
|
});
|
|
700
711
|
const nativeRuleFilter = applyDisableDirectives(
|
|
701
|
-
|
|
712
|
+
nativeMessages,
|
|
702
713
|
sourceCode
|
|
703
714
|
);
|
|
704
715
|
const customRuleFilter = applyDisableDirectives(customRuleMessages, sourceCode);
|
|
@@ -1080,6 +1091,9 @@ function appendCustomLintTextMessages(results, code, filePath, config, rules, op
|
|
|
1080
1091
|
return results;
|
|
1081
1092
|
}
|
|
1082
1093
|
let result = results.find((item) => item.filePath === filePath);
|
|
1094
|
+
if (result?.fatalErrorCount > 0) {
|
|
1095
|
+
return results;
|
|
1096
|
+
}
|
|
1083
1097
|
const effectiveCode = typeof result?.output === "string" ? result.output : code;
|
|
1084
1098
|
const sourceCode = createLinterSourceCode(effectiveCode, null, { ...parserOptionsForConfig(config, filePath, options.cwd), requireParser: true });
|
|
1085
1099
|
const messages = runCustomLinterRules(customRules, sourceCode, {
|
|
@@ -1166,6 +1180,9 @@ function relintAfterCustomFixes(result, code, filePath, customRules, config, rul
|
|
|
1166
1180
|
|
|
1167
1181
|
function appendCustomLintFileMessages(results, config, options) {
|
|
1168
1182
|
for (const result of results) {
|
|
1183
|
+
if (result.fatalErrorCount > 0) {
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1169
1186
|
const filePath = result.filePath;
|
|
1170
1187
|
const rules = customRuleMapForConfig(config, new Map(), filePath, options.cwd);
|
|
1171
1188
|
const customRules = customRuleEntriesForConfig(config, rules, filePath, options.cwd);
|
|
@@ -1285,7 +1302,7 @@ function applyDisableDirectives(messages, sourceCode) {
|
|
|
1285
1302
|
const kept = [];
|
|
1286
1303
|
const suppressed = [];
|
|
1287
1304
|
for (const message of messages) {
|
|
1288
|
-
if (!message.ruleId || message.ruleId === "parse" || message.ruleId === "io") {
|
|
1305
|
+
if (!message.ruleId || message.ruleId === "parse" || message.ruleId === "io" || isRuleDefinitionError(message)) {
|
|
1289
1306
|
kept.push(message);
|
|
1290
1307
|
continue;
|
|
1291
1308
|
}
|
|
@@ -3349,6 +3366,9 @@ function appendPluginRuleDiagnostics(report, options, { perFileConfig = true } =
|
|
|
3349
3366
|
let appended = false;
|
|
3350
3367
|
|
|
3351
3368
|
for (const filePath of filePaths) {
|
|
3369
|
+
if ((report.diagnostics ?? []).some((diagnostic) => diagnostic.filePath === filePath && diagnostic.ruleId === "parse" && diagnostic.severity === "error")) {
|
|
3370
|
+
continue;
|
|
3371
|
+
}
|
|
3352
3372
|
const matchPath = singleMatchPath ?? filePath;
|
|
3353
3373
|
const ruleMap = jsPluginRuleMapForFile(options, matchPath, perFileConfig);
|
|
3354
3374
|
if (ruleMap.size === 0) {
|
|
@@ -3536,6 +3556,10 @@ function nativeConfigGlobals(config) {
|
|
|
3536
3556
|
return Object.keys(globals).length > 0 ? globals : undefined;
|
|
3537
3557
|
}
|
|
3538
3558
|
|
|
3559
|
+
function nativeConfigSourceType(config) {
|
|
3560
|
+
return config?.languageOptions?.sourceType ?? config?.parserOptions?.sourceType;
|
|
3561
|
+
}
|
|
3562
|
+
|
|
3539
3563
|
function isGlobalsObject(value) {
|
|
3540
3564
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3541
3565
|
}
|
|
@@ -3544,7 +3568,7 @@ function configCanUseNativeRulesFastPath(config) {
|
|
|
3544
3568
|
const entries = Array.isArray(config) ? config : [config];
|
|
3545
3569
|
let hasEnabledRule = false;
|
|
3546
3570
|
for (const entry of entries) {
|
|
3547
|
-
if (!entry || typeof entry !== "object" || Object.keys(entry.settings ?? {}).length > 0 || nativeConfigGlobals(entry)) {
|
|
3571
|
+
if (!entry || typeof entry !== "object" || Object.keys(entry.settings ?? {}).length > 0 || nativeConfigGlobals(entry) || nativeConfigSourceType(entry) !== undefined) {
|
|
3548
3572
|
return false;
|
|
3549
3573
|
}
|
|
3550
3574
|
for (const ruleConfig of Object.values(entry.rules ?? {})) {
|
|
@@ -3573,8 +3597,12 @@ function nativeSerializableConfig(config) {
|
|
|
3573
3597
|
.map((key) => [key, config[key]])
|
|
3574
3598
|
);
|
|
3575
3599
|
const globals = nativeConfigGlobals(config);
|
|
3576
|
-
|
|
3577
|
-
|
|
3600
|
+
const sourceType = nativeConfigSourceType(config);
|
|
3601
|
+
if (globals || sourceType !== undefined) {
|
|
3602
|
+
serialized.languageOptions = {
|
|
3603
|
+
...(globals ? { globals } : {}),
|
|
3604
|
+
...(sourceType === undefined ? {} : { sourceType })
|
|
3605
|
+
};
|
|
3578
3606
|
}
|
|
3579
3607
|
return serialized;
|
|
3580
3608
|
}
|
|
@@ -3656,15 +3684,16 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
3656
3684
|
let rules = calculated.rules;
|
|
3657
3685
|
const settings = calculated.settings;
|
|
3658
3686
|
const globals = configured ? nativeConfigGlobals(calculated) : undefined;
|
|
3687
|
+
const sourceType = configured ? nativeConfigSourceType(calculated) : undefined;
|
|
3659
3688
|
if (configured && options.rules) {
|
|
3660
3689
|
rules = selectedRulesWithConfigOptions(rules, options.rules);
|
|
3661
3690
|
}
|
|
3662
3691
|
if (configured) {
|
|
3663
3692
|
rules = withoutJsPluginRules(rules, jsPluginRuleIdsForOptions(options, matchPath));
|
|
3664
3693
|
}
|
|
3665
|
-
const signature = configured ? stableConfigSignature({ rules, settings, globals }) : "<native-defaults>";
|
|
3694
|
+
const signature = configured ? stableConfigSignature({ rules, settings, globals, sourceType }) : "<native-defaults>";
|
|
3666
3695
|
if (!groups.has(signature)) {
|
|
3667
|
-
groups.set(signature, { paths: [], rules, settings, globals, configured });
|
|
3696
|
+
groups.set(signature, { paths: [], rules, settings, globals, sourceType, configured });
|
|
3668
3697
|
}
|
|
3669
3698
|
groups.get(signature).paths.push(filePath);
|
|
3670
3699
|
}
|
|
@@ -3687,7 +3716,7 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
3687
3716
|
};
|
|
3688
3717
|
}
|
|
3689
3718
|
|
|
3690
|
-
const selectedRules = severityOnlyNativeRuleNames(group.rules, group.settings, group.globals);
|
|
3719
|
+
const selectedRules = severityOnlyNativeRuleNames(group.rules, group.settings, group.globals, group.sourceType);
|
|
3691
3720
|
if (selectedRules) {
|
|
3692
3721
|
return {
|
|
3693
3722
|
paths: group.paths,
|
|
@@ -3713,7 +3742,10 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
3713
3742
|
overrideConfig: {
|
|
3714
3743
|
rules: allDisabledNativeRules(group.rules),
|
|
3715
3744
|
...(group.settings ? { settings: group.settings } : {}),
|
|
3716
|
-
...(group.globals
|
|
3745
|
+
...((group.globals || group.sourceType !== undefined) ? { languageOptions: {
|
|
3746
|
+
...(group.globals ? { globals: group.globals } : {}),
|
|
3747
|
+
...(group.sourceType === undefined ? {} : { sourceType: group.sourceType })
|
|
3748
|
+
} } : {})
|
|
3717
3749
|
},
|
|
3718
3750
|
forceMaterializedConfig: true
|
|
3719
3751
|
}
|
|
@@ -3721,8 +3753,8 @@ function nativeConfigRunsForFiles(paths, options) {
|
|
|
3721
3753
|
});
|
|
3722
3754
|
}
|
|
3723
3755
|
|
|
3724
|
-
function severityOnlyNativeRuleNames(rules, settings, globals) {
|
|
3725
|
-
if (globals || Object.keys(settings ?? {}).length > 0) {
|
|
3756
|
+
function severityOnlyNativeRuleNames(rules, settings, globals, sourceType) {
|
|
3757
|
+
if (globals || sourceType !== undefined || Object.keys(settings ?? {}).length > 0) {
|
|
3726
3758
|
return undefined;
|
|
3727
3759
|
}
|
|
3728
3760
|
|
|
@@ -3810,7 +3842,7 @@ export function lintText(code, options = {}) {
|
|
|
3810
3842
|
|
|
3811
3843
|
const tmp = mkdtempSync(join(tmpdir(), "utoo-lint-"));
|
|
3812
3844
|
const requestedPath = textFilePathForOptions(options, "text.js");
|
|
3813
|
-
const extension = extname(requestedPath) || ".js";
|
|
3845
|
+
const extension = requestedPath.match(/\.d\.(?:ts|mts|cts)$/)?.[0] ?? (extname(requestedPath) || ".js");
|
|
3814
3846
|
const tempFile = join(tmp, `input${extension}`);
|
|
3815
3847
|
const discoveredConfig =
|
|
3816
3848
|
!options.noConfig && !options.config && !options.overrideConfig
|
|
@@ -4386,7 +4418,11 @@ function withTemporaryConfig(options, callback) {
|
|
|
4386
4418
|
{}
|
|
4387
4419
|
);
|
|
4388
4420
|
const hasGlobals = Object.keys(globals).length > 0;
|
|
4389
|
-
|
|
4421
|
+
const sourceType = configs.reduce(
|
|
4422
|
+
(current, config) => nativeConfigSourceType(configDataFromConfig(config, options.filePath ?? options.filename, options.cwd)) ?? current,
|
|
4423
|
+
undefined
|
|
4424
|
+
);
|
|
4425
|
+
if (Object.keys(rules).length === 0 && !hasSettings && !hasGlobals && sourceType === undefined) {
|
|
4390
4426
|
if (shouldMaterializeFileConfig) {
|
|
4391
4427
|
return callback({
|
|
4392
4428
|
...options,
|
|
@@ -4398,7 +4434,7 @@ function withTemporaryConfig(options, callback) {
|
|
|
4398
4434
|
}
|
|
4399
4435
|
const enabledRules = enabledRuleNamesFromConfigs(...configs).filter((rule) => !jsPluginRuleIds.has(rule));
|
|
4400
4436
|
const hasExplicitOffRules = Object.values(rules).some((value) => ruleConfigSeverity(value) === 0);
|
|
4401
|
-
if (!shouldMaterializeFileConfig && !hasSettings && !hasGlobals && !hasRuleOptions(rules) && !hasExplicitOffRules && !options.forceMaterializedConfig) {
|
|
4437
|
+
if (!shouldMaterializeFileConfig && !hasSettings && !hasGlobals && sourceType === undefined && !hasRuleOptions(rules) && !hasExplicitOffRules && !options.forceMaterializedConfig) {
|
|
4402
4438
|
return callback({
|
|
4403
4439
|
...options,
|
|
4404
4440
|
config: shouldMaterializeFileConfig ? undefined : options.config,
|
|
@@ -4413,7 +4449,10 @@ function withTemporaryConfig(options, callback) {
|
|
|
4413
4449
|
writeFileSync(configPath, JSON.stringify({
|
|
4414
4450
|
rules: nativeRules(rules),
|
|
4415
4451
|
...(hasSettings ? { settings } : {}),
|
|
4416
|
-
...(hasGlobals
|
|
4452
|
+
...((hasGlobals || sourceType !== undefined) ? { languageOptions: {
|
|
4453
|
+
...(hasGlobals ? { globals } : {}),
|
|
4454
|
+
...(sourceType === undefined ? {} : { sourceType })
|
|
4455
|
+
} } : {})
|
|
4417
4456
|
}));
|
|
4418
4457
|
return callback({
|
|
4419
4458
|
...options,
|
|
@@ -4523,7 +4562,7 @@ function reportToESLintResults(report, textOptions = {}) {
|
|
|
4523
4562
|
byFile.set(filePath, emptyESLintResult(filePath, textOptions.source));
|
|
4524
4563
|
}
|
|
4525
4564
|
const ruleSeverities = textOptions.ruleSeverityForFile?.(filePath) ?? textOptions.ruleSeverities;
|
|
4526
|
-
if (diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4565
|
+
if (!isRuleDefinitionError(diagnostic) && diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4527
4566
|
continue;
|
|
4528
4567
|
}
|
|
4529
4568
|
byFile.get(filePath).messages.push(diagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
@@ -4535,7 +4574,7 @@ function reportToESLintResults(report, textOptions = {}) {
|
|
|
4535
4574
|
byFile.set(filePath, emptyESLintResult(filePath, textOptions.source));
|
|
4536
4575
|
}
|
|
4537
4576
|
const ruleSeverities = textOptions.ruleSeverityForFile?.(filePath) ?? textOptions.ruleSeverities;
|
|
4538
|
-
if (diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4577
|
+
if (!isRuleDefinitionError(diagnostic) && diagnostic.ruleId && ruleSeverities?.get(diagnostic.ruleId) === 0) {
|
|
4539
4578
|
continue;
|
|
4540
4579
|
}
|
|
4541
4580
|
byFile.get(filePath).suppressedMessages.push(suppressedDiagnosticToESLintMessage(diagnostic, ruleSeverities));
|
|
@@ -4591,8 +4630,19 @@ function applyCompatibilityDisableDirectives(result, textOptions) {
|
|
|
4591
4630
|
result.suppressedMessages.push(...filtered.suppressedMessages);
|
|
4592
4631
|
}
|
|
4593
4632
|
|
|
4633
|
+
function isRuleDefinitionError(diagnostic) {
|
|
4634
|
+
return typeof diagnostic?.ruleId === "string"
|
|
4635
|
+
&& diagnostic.message === `Definition for rule '${diagnostic.ruleId}' was not found.`;
|
|
4636
|
+
}
|
|
4637
|
+
|
|
4594
4638
|
function normalizeReportDiagnostics(diagnostics, options = {}) {
|
|
4595
4639
|
return (diagnostics ?? []).flatMap((diagnostic) => {
|
|
4640
|
+
if (isRuleDefinitionError(diagnostic)) {
|
|
4641
|
+
// Native cannot see JS plugin definitions. A mounted rule is known even
|
|
4642
|
+
// when it is disabled or emits no messages for this file.
|
|
4643
|
+
const filePath = options.pluginTextFilePath ?? diagnostic.filePath;
|
|
4644
|
+
return jsPluginRuleMapForFile(options, filePath).has(diagnostic.ruleId) ? [] : [diagnostic];
|
|
4645
|
+
}
|
|
4596
4646
|
if (!diagnostic?.ruleId) {
|
|
4597
4647
|
return [diagnostic];
|
|
4598
4648
|
}
|
|
@@ -5314,12 +5364,18 @@ function emptyESLintResult(filePath, source) {
|
|
|
5314
5364
|
function diagnosticToESLintMessage(diagnostic, ruleSeverities) {
|
|
5315
5365
|
const message = {
|
|
5316
5366
|
ruleId: diagnostic.ruleId,
|
|
5317
|
-
severity:
|
|
5367
|
+
severity: isRuleDefinitionError(diagnostic)
|
|
5368
|
+
? 2
|
|
5369
|
+
: ruleSeverities?.get(diagnostic.ruleId) ?? (diagnostic.severity === "error" ? 2 : 1),
|
|
5318
5370
|
message: diagnostic.message,
|
|
5319
5371
|
line: diagnostic.line,
|
|
5320
5372
|
column: diagnostic.column,
|
|
5321
5373
|
nodeType: null
|
|
5322
5374
|
};
|
|
5375
|
+
if (diagnostic.ruleId === "parse" && diagnostic.severity === "error") {
|
|
5376
|
+
message.fatal = true;
|
|
5377
|
+
message.severity = 2;
|
|
5378
|
+
}
|
|
5323
5379
|
if (typeof diagnostic.endLine === "number") {
|
|
5324
5380
|
message.endLine = diagnostic.endLine;
|
|
5325
5381
|
}
|
|
@@ -5370,11 +5426,13 @@ function suppressedDiagnosticToESLintMessage(diagnostic, ruleSeverities) {
|
|
|
5370
5426
|
}
|
|
5371
5427
|
|
|
5372
5428
|
function finalizeESLintResult(result) {
|
|
5429
|
+
result.fatalErrorCount = 0;
|
|
5373
5430
|
result.errorCount = 0;
|
|
5374
5431
|
result.warningCount = 0;
|
|
5375
5432
|
result.fixableErrorCount = 0;
|
|
5376
5433
|
result.fixableWarningCount = 0;
|
|
5377
5434
|
for (const message of result.messages) {
|
|
5435
|
+
if (message.fatal) result.fatalErrorCount += 1;
|
|
5378
5436
|
if (message.severity === 2) {
|
|
5379
5437
|
result.errorCount += 1;
|
|
5380
5438
|
if (ruleFixItems(message.fix).length > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@utoo/lint",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.12",
|
|
4
4
|
"description": "High-performance JavaScript and TypeScript linter powered by Yuku",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -74,11 +74,11 @@
|
|
|
74
74
|
"use-at-your-own-risk.js"
|
|
75
75
|
],
|
|
76
76
|
"optionalDependencies": {
|
|
77
|
-
"@utoo/lint-darwin-arm64": "0.4.
|
|
78
|
-
"@utoo/lint-darwin-x64": "0.4.
|
|
79
|
-
"@utoo/lint-linux-arm64": "0.4.
|
|
80
|
-
"@utoo/lint-linux-x64": "0.4.
|
|
81
|
-
"@utoo/lint-win32-x64": "0.4.
|
|
77
|
+
"@utoo/lint-darwin-arm64": "0.4.12",
|
|
78
|
+
"@utoo/lint-darwin-x64": "0.4.12",
|
|
79
|
+
"@utoo/lint-linux-arm64": "0.4.12",
|
|
80
|
+
"@utoo/lint-linux-x64": "0.4.12",
|
|
81
|
+
"@utoo/lint-win32-x64": "0.4.12"
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
84
|
"@eslint/eslintrc": "2.1.4",
|
package/schema.json
CHANGED
|
@@ -86,6 +86,11 @@
|
|
|
86
86
|
"type": "object",
|
|
87
87
|
"additionalProperties": true,
|
|
88
88
|
"properties": {
|
|
89
|
+
"sourceType": {
|
|
90
|
+
"description": "Parse as a module (always strict), script, or CommonJS. Defaults to the source file extension.",
|
|
91
|
+
"type": "string",
|
|
92
|
+
"enum": ["module", "script", "commonjs"]
|
|
93
|
+
},
|
|
89
94
|
"globals": {
|
|
90
95
|
"description": "Globals declared for matching files, using ESLint flat config values. \"readonly\" accepts reads, \"writable\" also accepts writes, and \"off\" removes a built-in global.",
|
|
91
96
|
"type": "object",
|