unguard 0.13.0 → 0.13.2
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.
|
@@ -632,6 +632,7 @@ var optionalArgAlwaysUsed = {
|
|
|
632
632
|
|
|
633
633
|
// src/rules/cross-file/repeated-literal-property.ts
|
|
634
634
|
import * as ts8 from "typescript";
|
|
635
|
+
var MODULE_SCOPE = -1;
|
|
635
636
|
var repeatedLiteralProperty = {
|
|
636
637
|
id: "repeated-literal-property",
|
|
637
638
|
severity: "warning",
|
|
@@ -651,7 +652,8 @@ var repeatedLiteralProperty = {
|
|
|
651
652
|
valueMap.set(result.literalText, list);
|
|
652
653
|
}
|
|
653
654
|
const line = ts8.getLineAndCharacterOfPosition(sourceFile, prop.getStart(sourceFile)).line + 1;
|
|
654
|
-
|
|
655
|
+
const scopeId = findEnclosingFunctionStart(prop, sourceFile);
|
|
656
|
+
list.push({ line, isAsConst: result.isAsConst, scopeId });
|
|
655
657
|
}
|
|
656
658
|
}
|
|
657
659
|
ts8.forEachChild(node, visit2);
|
|
@@ -661,31 +663,40 @@ var repeatedLiteralProperty = {
|
|
|
661
663
|
ts8.forEachChild(sourceFile, visit2);
|
|
662
664
|
for (const [value, occurrences] of valueMap) {
|
|
663
665
|
const hasAsConst = occurrences.some((o) => o.isAsConst);
|
|
666
|
+
const uniqueScopes = new Set(occurrences.map((o) => o.scopeId));
|
|
664
667
|
const threshold = hasAsConst ? 3 : 5;
|
|
665
|
-
if (
|
|
668
|
+
if (uniqueScopes.size < threshold) continue;
|
|
666
669
|
const sorted = [...occurrences].sort((a, b) => a.line - b.line);
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}
|
|
670
|
+
const first = sorted[0];
|
|
671
|
+
if (first === void 0) continue;
|
|
672
|
+
const otherLines = sorted.slice(1).map((o) => o.line).join(", ");
|
|
673
|
+
diagnostics.push({
|
|
674
|
+
ruleId: this.id,
|
|
675
|
+
severity: this.severity,
|
|
676
|
+
message: `${JSON.stringify(value)}${hasAsConst ? " as const" : ""} repeated across ${uniqueScopes.size} scopes as property value (also at lines ${otherLines})`,
|
|
677
|
+
file,
|
|
678
|
+
line: first.line,
|
|
679
|
+
column: 1
|
|
680
|
+
});
|
|
678
681
|
}
|
|
679
682
|
}
|
|
680
683
|
return diagnostics;
|
|
681
684
|
}
|
|
682
685
|
};
|
|
686
|
+
function findEnclosingFunctionStart(node, sourceFile) {
|
|
687
|
+
let current = node.parent;
|
|
688
|
+
while (current) {
|
|
689
|
+
if (ts8.isFunctionDeclaration(current) || ts8.isFunctionExpression(current) || ts8.isArrowFunction(current) || ts8.isMethodDeclaration(current)) {
|
|
690
|
+
return current.getStart(sourceFile);
|
|
691
|
+
}
|
|
692
|
+
current = current.parent;
|
|
693
|
+
}
|
|
694
|
+
return MODULE_SCOPE;
|
|
695
|
+
}
|
|
683
696
|
function extractLiteral(node, sourceFile) {
|
|
684
|
-
if (ts8.isStringLiteral(node) || ts8.
|
|
697
|
+
if (ts8.isStringLiteral(node) || ts8.isNoSubstitutionTemplateLiteral(node)) {
|
|
685
698
|
return { literalText: node.text, isAsConst: false };
|
|
686
699
|
}
|
|
687
|
-
if (node.kind === ts8.SyntaxKind.TrueKeyword) return { literalText: "true", isAsConst: false };
|
|
688
|
-
if (node.kind === ts8.SyntaxKind.FalseKeyword) return { literalText: "false", isAsConst: false };
|
|
689
700
|
if (ts8.isAsExpression(node) && node.type.getText(sourceFile).trim() === "const") {
|
|
690
701
|
const inner = extractLiteral(node.expression, sourceFile);
|
|
691
702
|
if (inner.literalText !== null) {
|
|
@@ -763,17 +774,17 @@ var repeatedReturnShape = {
|
|
|
763
774
|
const unique = [...byFunction.values()];
|
|
764
775
|
if (unique.length < THRESHOLD) continue;
|
|
765
776
|
const sorted = unique.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line);
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
}
|
|
777
|
+
const first = sorted[0];
|
|
778
|
+
if (first === void 0) continue;
|
|
779
|
+
const others = sorted.slice(1).map((e) => `${e.functionName} (${e.file}:${e.line})`).join(", ");
|
|
780
|
+
diagnostics.push({
|
|
781
|
+
ruleId: this.id,
|
|
782
|
+
severity: this.severity,
|
|
783
|
+
message: `${unique.length} functions return shape {${first.props.join(", ")}}; consider a shared return type (${others})`,
|
|
784
|
+
file: first.file,
|
|
785
|
+
line: first.line,
|
|
786
|
+
column: 1
|
|
787
|
+
});
|
|
777
788
|
}
|
|
778
789
|
return diagnostics;
|
|
779
790
|
}
|
|
@@ -817,7 +828,7 @@ function collectReturnShapes(funcNode, file, funcLine, functionName, sourceFile,
|
|
|
817
828
|
}
|
|
818
829
|
function addShape(objLiteral, file, funcLine, functionName, sourceFile, shapeMap) {
|
|
819
830
|
const props = extractPropertyNames(objLiteral);
|
|
820
|
-
if (props === null || props.length
|
|
831
|
+
if (props === null || props.length < 2) return;
|
|
821
832
|
const { sorted, list } = getShapeGroup(shapeMap, props);
|
|
822
833
|
list.push({ file, line: funcLine, functionName, props: sorted });
|
|
823
834
|
}
|
|
@@ -2918,4 +2929,4 @@ export {
|
|
|
2918
2929
|
executeScan,
|
|
2919
2930
|
scan
|
|
2920
2931
|
};
|
|
2921
|
-
//# sourceMappingURL=chunk-
|
|
2932
|
+
//# sourceMappingURL=chunk-2QER6GG7.js.map
|