unguard 0.10.1 → 0.10.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.
|
@@ -636,6 +636,7 @@ var preferRequiredParamWithGuard = {
|
|
|
636
636
|
};
|
|
637
637
|
|
|
638
638
|
// src/rules/cross-file/duplicate-type-declaration.ts
|
|
639
|
+
import * as ts18 from "typescript";
|
|
639
640
|
var duplicateTypeDeclaration = {
|
|
640
641
|
id: "duplicate-type-declaration",
|
|
641
642
|
severity: "warning",
|
|
@@ -645,6 +646,7 @@ var duplicateTypeDeclaration = {
|
|
|
645
646
|
for (const group of project.types.getDuplicateGroups()) {
|
|
646
647
|
const files = new Set(group.map((e) => e.file));
|
|
647
648
|
if (files.size < 2) continue;
|
|
649
|
+
if (group.every((e) => isTrivialObjectShape(e.node))) continue;
|
|
648
650
|
reportDuplicateGroup(
|
|
649
651
|
group,
|
|
650
652
|
this.id,
|
|
@@ -657,9 +659,14 @@ var duplicateTypeDeclaration = {
|
|
|
657
659
|
return diagnostics;
|
|
658
660
|
}
|
|
659
661
|
};
|
|
662
|
+
function isTrivialObjectShape(node) {
|
|
663
|
+
if (ts18.isTypeLiteralNode(node)) return node.members.length <= 1;
|
|
664
|
+
if (ts18.isInterfaceDeclaration(node)) return node.members.length <= 1;
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
660
667
|
|
|
661
668
|
// src/rules/cross-file/duplicate-function-declaration.ts
|
|
662
|
-
import * as
|
|
669
|
+
import * as ts19 from "typescript";
|
|
663
670
|
var duplicateFunctionDeclaration = {
|
|
664
671
|
id: "duplicate-function-declaration",
|
|
665
672
|
severity: "warning",
|
|
@@ -684,12 +691,13 @@ var duplicateFunctionDeclaration = {
|
|
|
684
691
|
}
|
|
685
692
|
};
|
|
686
693
|
function getBodyBlock(node) {
|
|
687
|
-
if (
|
|
688
|
-
if (
|
|
689
|
-
if (
|
|
694
|
+
if (ts19.isFunctionDeclaration(node) || ts19.isFunctionExpression(node)) return node.body;
|
|
695
|
+
if (ts19.isArrowFunction(node)) return ts19.isBlock(node.body) ? node.body : void 0;
|
|
696
|
+
if (ts19.isMethodDeclaration(node)) return node.body;
|
|
690
697
|
return void 0;
|
|
691
698
|
}
|
|
692
699
|
function isSingleStatement(node) {
|
|
700
|
+
if (ts19.isArrowFunction(node) && !ts19.isBlock(node.body)) return true;
|
|
693
701
|
const body = getBodyBlock(node);
|
|
694
702
|
return body !== void 0 && body.statements.length <= 1;
|
|
695
703
|
}
|
|
@@ -697,8 +705,8 @@ function isSetter(node) {
|
|
|
697
705
|
const body = getBodyBlock(node);
|
|
698
706
|
if (!body || body.statements.length !== 1) return false;
|
|
699
707
|
const stmt = body.statements[0];
|
|
700
|
-
if (stmt === void 0 || !
|
|
701
|
-
return
|
|
708
|
+
if (stmt === void 0 || !ts19.isExpressionStatement(stmt)) return false;
|
|
709
|
+
return ts19.isBinaryExpression(stmt.expression) && stmt.expression.operatorToken.kind === ts19.SyntaxKind.EqualsToken;
|
|
702
710
|
}
|
|
703
711
|
|
|
704
712
|
// src/rules/cross-file/optional-arg-always-used.ts
|
|
@@ -733,14 +741,14 @@ var optionalArgAlwaysUsed = {
|
|
|
733
741
|
};
|
|
734
742
|
|
|
735
743
|
// src/rules/ts/no-catch-return.ts
|
|
736
|
-
import * as
|
|
744
|
+
import * as ts20 from "typescript";
|
|
737
745
|
var noCatchReturn = {
|
|
738
746
|
kind: "ts",
|
|
739
747
|
id: "no-catch-return",
|
|
740
748
|
severity: "warning",
|
|
741
749
|
message: "Catch block silently returns a fallback value with no logging; rethrow, log the error, or let it propagate",
|
|
742
750
|
visit(node, ctx) {
|
|
743
|
-
if (!
|
|
751
|
+
if (!ts20.isCatchClause(node)) return;
|
|
744
752
|
const block = node.block;
|
|
745
753
|
if (hasReturn(block) && !hasThrow(block) && !hasLogging(block)) {
|
|
746
754
|
ctx.report(node);
|
|
@@ -750,57 +758,57 @@ var noCatchReturn = {
|
|
|
750
758
|
function walkBlock(block, predicate) {
|
|
751
759
|
function visit(node) {
|
|
752
760
|
if (predicate(node)) return true;
|
|
753
|
-
if (
|
|
754
|
-
return
|
|
761
|
+
if (ts20.isFunctionDeclaration(node) || ts20.isFunctionExpression(node) || ts20.isArrowFunction(node)) return false;
|
|
762
|
+
return ts20.forEachChild(node, visit) ?? false;
|
|
755
763
|
}
|
|
756
|
-
return
|
|
764
|
+
return ts20.forEachChild(block, visit) ?? false;
|
|
757
765
|
}
|
|
758
766
|
function hasReturn(block) {
|
|
759
|
-
return walkBlock(block, (n) =>
|
|
767
|
+
return walkBlock(block, (n) => ts20.isReturnStatement(n));
|
|
760
768
|
}
|
|
761
769
|
function hasThrow(block) {
|
|
762
|
-
return walkBlock(block, (n) =>
|
|
770
|
+
return walkBlock(block, (n) => ts20.isThrowStatement(n));
|
|
763
771
|
}
|
|
764
772
|
var LOG_OBJECTS = /* @__PURE__ */ new Set(["console", "logger", "log"]);
|
|
765
773
|
function hasLogging(block) {
|
|
766
774
|
return walkBlock(block, (n) => {
|
|
767
|
-
if (!
|
|
775
|
+
if (!ts20.isCallExpression(n)) return false;
|
|
768
776
|
const callee = n.expression;
|
|
769
|
-
if (!
|
|
770
|
-
if (!
|
|
777
|
+
if (!ts20.isPropertyAccessExpression(callee)) return false;
|
|
778
|
+
if (!ts20.isIdentifier(callee.expression)) return false;
|
|
771
779
|
return LOG_OBJECTS.has(callee.expression.text);
|
|
772
780
|
});
|
|
773
781
|
}
|
|
774
782
|
|
|
775
783
|
// src/rules/ts/no-error-rewrap.ts
|
|
776
|
-
import * as
|
|
784
|
+
import * as ts21 from "typescript";
|
|
777
785
|
var noErrorRewrap = {
|
|
778
786
|
kind: "ts",
|
|
779
787
|
id: "no-error-rewrap",
|
|
780
788
|
severity: "error",
|
|
781
789
|
message: "Re-wrapped error loses the original stack trace and type; use { cause: originalError } to preserve the error chain",
|
|
782
790
|
visit(node, ctx) {
|
|
783
|
-
if (!
|
|
791
|
+
if (!ts21.isCatchClause(node)) return;
|
|
784
792
|
if (!node.variableDeclaration) return;
|
|
785
793
|
const param = node.variableDeclaration.name;
|
|
786
|
-
if (!
|
|
794
|
+
if (!ts21.isIdentifier(param)) return;
|
|
787
795
|
const catchName = param.text;
|
|
788
796
|
findRewraps(node.block, catchName, ctx);
|
|
789
797
|
}
|
|
790
798
|
};
|
|
791
799
|
function findRewraps(block, catchName, ctx) {
|
|
792
800
|
function visit(node) {
|
|
793
|
-
if (
|
|
794
|
-
if (
|
|
801
|
+
if (ts21.isFunctionDeclaration(node) || ts21.isFunctionExpression(node) || ts21.isArrowFunction(node)) return;
|
|
802
|
+
if (ts21.isThrowStatement(node) && node.expression && ts21.isNewExpression(node.expression)) {
|
|
795
803
|
const args = node.expression.arguments;
|
|
796
804
|
if (args && args.length > 0 && referencesName(args, catchName) && !hasCauseArg(args)) {
|
|
797
805
|
ctx.report(node);
|
|
798
806
|
}
|
|
799
807
|
return;
|
|
800
808
|
}
|
|
801
|
-
|
|
809
|
+
ts21.forEachChild(node, visit);
|
|
802
810
|
}
|
|
803
|
-
|
|
811
|
+
ts21.forEachChild(block, visit);
|
|
804
812
|
}
|
|
805
813
|
function referencesName(args, name) {
|
|
806
814
|
for (const arg of args) {
|
|
@@ -809,15 +817,15 @@ function referencesName(args, name) {
|
|
|
809
817
|
return false;
|
|
810
818
|
}
|
|
811
819
|
function containsIdentifier(node, name) {
|
|
812
|
-
if (
|
|
813
|
-
return
|
|
820
|
+
if (ts21.isIdentifier(node) && node.text === name) return true;
|
|
821
|
+
return ts21.forEachChild(node, (child) => containsIdentifier(child, name) || void 0) ?? false;
|
|
814
822
|
}
|
|
815
823
|
function hasCauseArg(args) {
|
|
816
824
|
for (const arg of args) {
|
|
817
|
-
if (
|
|
825
|
+
if (ts21.isObjectLiteralExpression(arg)) {
|
|
818
826
|
for (const prop of arg.properties) {
|
|
819
|
-
if (
|
|
820
|
-
if (
|
|
827
|
+
if (ts21.isPropertyAssignment(prop) && ts21.isIdentifier(prop.name) && prop.name.text === "cause") return true;
|
|
828
|
+
if (ts21.isShorthandPropertyAssignment(prop) && prop.name.text === "cause") return true;
|
|
821
829
|
}
|
|
822
830
|
}
|
|
823
831
|
}
|
|
@@ -825,7 +833,7 @@ function hasCauseArg(args) {
|
|
|
825
833
|
}
|
|
826
834
|
|
|
827
835
|
// src/rules/cross-file/explicit-null-arg.ts
|
|
828
|
-
import * as
|
|
836
|
+
import * as ts22 from "typescript";
|
|
829
837
|
var explicitNullArg = {
|
|
830
838
|
id: "explicit-null-arg",
|
|
831
839
|
severity: "warning",
|
|
@@ -845,7 +853,7 @@ var explicitNullArg = {
|
|
|
845
853
|
const arg = site.node.arguments[i];
|
|
846
854
|
if (arg === void 0) continue;
|
|
847
855
|
if (isNullishLiteral(arg)) {
|
|
848
|
-
const val = arg.kind ===
|
|
856
|
+
const val = arg.kind === ts22.SyntaxKind.NullKeyword ? "null" : "undefined";
|
|
849
857
|
diagnostics.push({
|
|
850
858
|
ruleId: this.id,
|
|
851
859
|
severity: this.severity,
|
|
@@ -918,7 +926,7 @@ function resolveCandidates(fromFile, specifier) {
|
|
|
918
926
|
}
|
|
919
927
|
|
|
920
928
|
// src/rules/cross-file/duplicate-type-name.ts
|
|
921
|
-
import * as
|
|
929
|
+
import * as ts23 from "typescript";
|
|
922
930
|
var duplicateTypeName = {
|
|
923
931
|
id: "duplicate-type-name",
|
|
924
932
|
severity: "warning",
|
|
@@ -929,7 +937,7 @@ var duplicateTypeName = {
|
|
|
929
937
|
const hashes = new Set(group.map((e) => e.hash));
|
|
930
938
|
if (hashes.size === 1) continue;
|
|
931
939
|
const hasInferredType = group.some(
|
|
932
|
-
(e) => !
|
|
940
|
+
(e) => !ts23.isTypeLiteralNode(e.node) && !ts23.isInterfaceDeclaration(e.node)
|
|
933
941
|
);
|
|
934
942
|
if (hasInferredType) continue;
|
|
935
943
|
reportDuplicateGroup(
|
|
@@ -969,20 +977,21 @@ var duplicateConstantDeclaration = {
|
|
|
969
977
|
};
|
|
970
978
|
|
|
971
979
|
// src/rules/ts/no-dynamic-import.ts
|
|
972
|
-
import * as
|
|
980
|
+
import * as ts24 from "typescript";
|
|
973
981
|
var noDynamicImport = {
|
|
974
982
|
kind: "ts",
|
|
975
983
|
id: "no-dynamic-import",
|
|
976
984
|
severity: "error",
|
|
977
985
|
message: "Dynamic import() breaks static analysis and hides dependencies; use a static import instead",
|
|
978
986
|
visit(node, ctx) {
|
|
979
|
-
if (!
|
|
980
|
-
if (node.expression.kind !==
|
|
987
|
+
if (!ts24.isCallExpression(node)) return;
|
|
988
|
+
if (node.expression.kind !== ts24.SyntaxKind.ImportKeyword) return;
|
|
981
989
|
ctx.report(node);
|
|
982
990
|
}
|
|
983
991
|
};
|
|
984
992
|
|
|
985
993
|
// src/rules/cross-file/near-duplicate-function.ts
|
|
994
|
+
import * as ts25 from "typescript";
|
|
986
995
|
var nearDuplicateFunction = {
|
|
987
996
|
id: "near-duplicate-function",
|
|
988
997
|
severity: "warning",
|
|
@@ -992,6 +1001,7 @@ var nearDuplicateFunction = {
|
|
|
992
1001
|
for (const group of project.functions.getNearDuplicateGroups()) {
|
|
993
1002
|
const MIN_NORMALIZED_BODY = 32;
|
|
994
1003
|
if (group.every((e) => e.normalizedBodyLength < MIN_NORMALIZED_BODY)) continue;
|
|
1004
|
+
if (group.every(isSimpleStructure)) continue;
|
|
995
1005
|
reportDuplicateGroup(
|
|
996
1006
|
group,
|
|
997
1007
|
this.id,
|
|
@@ -1004,38 +1014,67 @@ var nearDuplicateFunction = {
|
|
|
1004
1014
|
return diagnostics;
|
|
1005
1015
|
}
|
|
1006
1016
|
};
|
|
1017
|
+
function getFunctionBody(node) {
|
|
1018
|
+
if (ts25.isFunctionDeclaration(node) || ts25.isFunctionExpression(node)) return node.body;
|
|
1019
|
+
if (ts25.isArrowFunction(node)) return node.body;
|
|
1020
|
+
if (ts25.isMethodDeclaration(node)) return node.body;
|
|
1021
|
+
return void 0;
|
|
1022
|
+
}
|
|
1023
|
+
function getTopLevelStatementCount(body) {
|
|
1024
|
+
if (ts25.isBlock(body)) return body.statements.length;
|
|
1025
|
+
return 1;
|
|
1026
|
+
}
|
|
1027
|
+
function hasControlFlow(node) {
|
|
1028
|
+
let found = false;
|
|
1029
|
+
function visit(current) {
|
|
1030
|
+
if (found) return;
|
|
1031
|
+
if (ts25.isIfStatement(current) || ts25.isSwitchStatement(current) || ts25.isTryStatement(current) || ts25.isForStatement(current) || ts25.isForInStatement(current) || ts25.isForOfStatement(current) || ts25.isWhileStatement(current) || ts25.isDoStatement(current)) {
|
|
1032
|
+
found = true;
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
ts25.forEachChild(current, visit);
|
|
1036
|
+
}
|
|
1037
|
+
visit(node);
|
|
1038
|
+
return found;
|
|
1039
|
+
}
|
|
1040
|
+
function isSimpleStructure(entry) {
|
|
1041
|
+
const body = getFunctionBody(entry.node);
|
|
1042
|
+
if (!body) return false;
|
|
1043
|
+
if (hasControlFlow(body)) return false;
|
|
1044
|
+
return getTopLevelStatementCount(body) <= 2;
|
|
1045
|
+
}
|
|
1007
1046
|
|
|
1008
1047
|
// src/rules/cross-file/trivial-wrapper.ts
|
|
1009
|
-
import * as
|
|
1010
|
-
function
|
|
1011
|
-
if (
|
|
1048
|
+
import * as ts26 from "typescript";
|
|
1049
|
+
function getFunctionBody2(node) {
|
|
1050
|
+
if (ts26.isFunctionDeclaration(node) || ts26.isFunctionExpression(node)) {
|
|
1012
1051
|
return node.body;
|
|
1013
1052
|
}
|
|
1014
|
-
if (
|
|
1053
|
+
if (ts26.isArrowFunction(node)) {
|
|
1015
1054
|
return node.body;
|
|
1016
1055
|
}
|
|
1017
|
-
if (
|
|
1056
|
+
if (ts26.isMethodDeclaration(node)) {
|
|
1018
1057
|
return node.body;
|
|
1019
1058
|
}
|
|
1020
1059
|
return void 0;
|
|
1021
1060
|
}
|
|
1022
1061
|
function getCalleeName(expr) {
|
|
1023
|
-
if (
|
|
1024
|
-
if (
|
|
1062
|
+
if (ts26.isIdentifier(expr)) return expr.text;
|
|
1063
|
+
if (ts26.isPropertyAccessExpression(expr)) return expr.name.text;
|
|
1025
1064
|
return void 0;
|
|
1026
1065
|
}
|
|
1027
1066
|
function getTrivialCallTarget(fn) {
|
|
1028
|
-
const body =
|
|
1067
|
+
const body = getFunctionBody2(fn.node);
|
|
1029
1068
|
if (!body) return null;
|
|
1030
1069
|
let callExpr;
|
|
1031
|
-
if (
|
|
1070
|
+
if (ts26.isBlock(body)) {
|
|
1032
1071
|
if (body.statements.length !== 1) return null;
|
|
1033
1072
|
const stmt = body.statements[0];
|
|
1034
|
-
if (!stmt || !
|
|
1035
|
-
if (!
|
|
1073
|
+
if (!stmt || !ts26.isReturnStatement(stmt) || !stmt.expression) return null;
|
|
1074
|
+
if (!ts26.isCallExpression(stmt.expression)) return null;
|
|
1036
1075
|
callExpr = stmt.expression;
|
|
1037
1076
|
} else {
|
|
1038
|
-
if (!
|
|
1077
|
+
if (!ts26.isCallExpression(body)) return null;
|
|
1039
1078
|
callExpr = body;
|
|
1040
1079
|
}
|
|
1041
1080
|
const calleeName = getCalleeName(callExpr.expression);
|
|
@@ -1043,7 +1082,7 @@ function getTrivialCallTarget(fn) {
|
|
|
1043
1082
|
const paramNames = fn.params.map((p) => p.name);
|
|
1044
1083
|
const args = callExpr.arguments;
|
|
1045
1084
|
for (const arg of args) {
|
|
1046
|
-
if (!
|
|
1085
|
+
if (!ts26.isIdentifier(arg)) return null;
|
|
1047
1086
|
if (!paramNames.includes(arg.text)) return null;
|
|
1048
1087
|
}
|
|
1049
1088
|
return { calleeName };
|
|
@@ -1340,32 +1379,32 @@ function isFailOn(value) {
|
|
|
1340
1379
|
}
|
|
1341
1380
|
|
|
1342
1381
|
// src/collect/index.ts
|
|
1343
|
-
import * as
|
|
1382
|
+
import * as ts29 from "typescript";
|
|
1344
1383
|
import { createHash as createHash2 } from "crypto";
|
|
1345
1384
|
|
|
1346
1385
|
// src/utils/hash.ts
|
|
1347
1386
|
import { createHash } from "crypto";
|
|
1348
|
-
import * as
|
|
1387
|
+
import * as ts27 from "typescript";
|
|
1349
1388
|
function hashTypeShape(node, sourceFile) {
|
|
1350
1389
|
const normalized = normalizeTypeNode(node, sourceFile);
|
|
1351
1390
|
return createHash("sha256").update(normalized).digest("hex").slice(0, 16);
|
|
1352
1391
|
}
|
|
1353
1392
|
function normalizeTypeNode(node, sourceFile) {
|
|
1354
|
-
if (
|
|
1393
|
+
if (ts27.isTypeLiteralNode(node)) {
|
|
1355
1394
|
const normalized = node.members.map((m) => normalizeTypeNode(m, sourceFile)).sort().join(";");
|
|
1356
1395
|
return `{${normalized}}`;
|
|
1357
1396
|
}
|
|
1358
|
-
if (
|
|
1397
|
+
if (ts27.isInterfaceDeclaration(node)) {
|
|
1359
1398
|
const normalized = node.members.map((m) => normalizeTypeNode(m, sourceFile)).sort().join(";");
|
|
1360
1399
|
return `{${normalized}}`;
|
|
1361
1400
|
}
|
|
1362
|
-
if (
|
|
1401
|
+
if (ts27.isPropertySignature(node)) {
|
|
1363
1402
|
const keyName = node.name.getText(sourceFile);
|
|
1364
1403
|
const optional = node.questionToken ? "?" : "";
|
|
1365
1404
|
const type = node.type ? normalizeTypeNode(node.type, sourceFile) : "any";
|
|
1366
1405
|
return `${keyName}${optional}:${type}`;
|
|
1367
1406
|
}
|
|
1368
|
-
if (
|
|
1407
|
+
if (ts27.isTypeAliasDeclaration(node)) {
|
|
1369
1408
|
return normalizeTypeNode(node.type, sourceFile);
|
|
1370
1409
|
}
|
|
1371
1410
|
return node.getText(sourceFile).replace(/\s+/g, " ").trim();
|
|
@@ -1531,7 +1570,7 @@ var InlineParamTypeRegistry = class extends BaseRegistry {
|
|
|
1531
1570
|
};
|
|
1532
1571
|
|
|
1533
1572
|
// src/typecheck/walk.ts
|
|
1534
|
-
import * as
|
|
1573
|
+
import * as ts28 from "typescript";
|
|
1535
1574
|
function buildContext(rule, sourceFile, checker, source, filename, diagnostics) {
|
|
1536
1575
|
return {
|
|
1537
1576
|
filename,
|
|
@@ -1539,7 +1578,7 @@ function buildContext(rule, sourceFile, checker, source, filename, diagnostics)
|
|
|
1539
1578
|
sourceFile,
|
|
1540
1579
|
checker,
|
|
1541
1580
|
report(node, message) {
|
|
1542
|
-
const { line, character } =
|
|
1581
|
+
const { line, character } = ts28.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile));
|
|
1543
1582
|
diagnostics.push({
|
|
1544
1583
|
ruleId: rule.id,
|
|
1545
1584
|
severity: rule.severity,
|
|
@@ -1550,7 +1589,7 @@ function buildContext(rule, sourceFile, checker, source, filename, diagnostics)
|
|
|
1550
1589
|
});
|
|
1551
1590
|
},
|
|
1552
1591
|
reportAtOffset(offset, message) {
|
|
1553
|
-
const { line, character } =
|
|
1592
|
+
const { line, character } = ts28.getLineAndCharacterOfPosition(sourceFile, offset);
|
|
1554
1593
|
diagnostics.push({
|
|
1555
1594
|
ruleId: rule.id,
|
|
1556
1595
|
severity: rule.severity,
|
|
@@ -1601,7 +1640,7 @@ function collectProject(program, tsRules, allowedFiles) {
|
|
|
1601
1640
|
rule.visit(node, ctx);
|
|
1602
1641
|
}
|
|
1603
1642
|
}
|
|
1604
|
-
|
|
1643
|
+
ts29.forEachChild(node, visit2);
|
|
1605
1644
|
};
|
|
1606
1645
|
var visit = visit2;
|
|
1607
1646
|
const file = sourceFile.fileName;
|
|
@@ -1615,7 +1654,7 @@ function collectProject(program, tsRules, allowedFiles) {
|
|
|
1615
1654
|
rule,
|
|
1616
1655
|
ctx: buildContext(rule, sourceFile, checker, source, file, diagnostics)
|
|
1617
1656
|
}));
|
|
1618
|
-
|
|
1657
|
+
ts29.forEachChild(sourceFile, visit2);
|
|
1619
1658
|
}
|
|
1620
1659
|
const fileHashes = /* @__PURE__ */ new Map();
|
|
1621
1660
|
for (const [file, { source }] of fileMap) {
|
|
@@ -1631,52 +1670,52 @@ function collectProject(program, tsRules, allowedFiles) {
|
|
|
1631
1670
|
return { index: { types, functions, constants, callSites, imports, files: fileMap, fileHashes, statementSequences, inlineParamTypes }, diagnostics };
|
|
1632
1671
|
}
|
|
1633
1672
|
function hasNonPublicModifier(node) {
|
|
1634
|
-
if (!
|
|
1635
|
-
const mods =
|
|
1673
|
+
if (!ts29.canHaveModifiers(node)) return false;
|
|
1674
|
+
const mods = ts29.getModifiers(node);
|
|
1636
1675
|
if (mods === void 0) return false;
|
|
1637
1676
|
return mods.some(
|
|
1638
|
-
(m) => m.kind ===
|
|
1677
|
+
(m) => m.kind === ts29.SyntaxKind.PrivateKeyword || m.kind === ts29.SyntaxKind.ProtectedKeyword
|
|
1639
1678
|
);
|
|
1640
1679
|
}
|
|
1641
1680
|
function isExported(node) {
|
|
1642
|
-
if (!
|
|
1643
|
-
const mods =
|
|
1681
|
+
if (!ts29.canHaveModifiers(node)) return false;
|
|
1682
|
+
const mods = ts29.getModifiers(node);
|
|
1644
1683
|
if (mods === void 0) return false;
|
|
1645
|
-
return mods.some((m) => m.kind ===
|
|
1684
|
+
return mods.some((m) => m.kind === ts29.SyntaxKind.ExportKeyword);
|
|
1646
1685
|
}
|
|
1647
1686
|
function collectTypes(node, file, sourceFile, registry) {
|
|
1648
|
-
if (
|
|
1649
|
-
const line =
|
|
1687
|
+
if (ts29.isTypeAliasDeclaration(node)) {
|
|
1688
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
|
|
1650
1689
|
registry.add(node.name.text, file, line, node.type, sourceFile, isExported(node));
|
|
1651
1690
|
}
|
|
1652
|
-
if (
|
|
1653
|
-
const line =
|
|
1691
|
+
if (ts29.isInterfaceDeclaration(node)) {
|
|
1692
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
|
|
1654
1693
|
registry.add(node.name.text, file, line, node, sourceFile, isExported(node));
|
|
1655
1694
|
}
|
|
1656
1695
|
}
|
|
1657
1696
|
function isConstantValue(node) {
|
|
1658
|
-
if (
|
|
1659
|
-
if (
|
|
1660
|
-
if (
|
|
1661
|
-
if (
|
|
1662
|
-
if (
|
|
1697
|
+
if (ts29.isStringLiteral(node)) return true;
|
|
1698
|
+
if (ts29.isNumericLiteral(node)) return true;
|
|
1699
|
+
if (ts29.isNoSubstitutionTemplateLiteral(node)) return true;
|
|
1700
|
+
if (ts29.isPrefixUnaryExpression(node)) return isConstantValue(node.operand);
|
|
1701
|
+
if (ts29.isBinaryExpression(node)) return isConstantValue(node.left) && isConstantValue(node.right);
|
|
1663
1702
|
return false;
|
|
1664
1703
|
}
|
|
1665
1704
|
function collectConstants(node, file, sourceFile, registry) {
|
|
1666
|
-
if (!
|
|
1667
|
-
if (!(node.declarationList.flags &
|
|
1705
|
+
if (!ts29.isVariableStatement(node)) return;
|
|
1706
|
+
if (!(node.declarationList.flags & ts29.NodeFlags.Const)) return;
|
|
1668
1707
|
const exported = isExported(node);
|
|
1669
1708
|
for (const decl of node.declarationList.declarations) {
|
|
1670
|
-
if (!decl.initializer || !
|
|
1709
|
+
if (!decl.initializer || !ts29.isIdentifier(decl.name)) continue;
|
|
1671
1710
|
if (!isConstantValue(decl.initializer)) continue;
|
|
1672
1711
|
const valueText = decl.initializer.getText(sourceFile).replace(/\s+/g, " ").trim();
|
|
1673
1712
|
const valueHash = createHash2("sha256").update(valueText).digest("hex").slice(0, 16);
|
|
1674
|
-
const line =
|
|
1713
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, decl.getStart(sourceFile)).line + 1;
|
|
1675
1714
|
registry.add({ name: decl.name.text, file, line, valueHash, valueText, exported });
|
|
1676
1715
|
}
|
|
1677
1716
|
}
|
|
1678
1717
|
function buildFunctionEntry(body, parameters, sourceFile, file, lineNode, name, extra) {
|
|
1679
|
-
const line =
|
|
1718
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, lineNode.getStart(sourceFile)).line + 1;
|
|
1680
1719
|
const params = extractParams(parameters, sourceFile);
|
|
1681
1720
|
const paramNames = params.map((p) => p.name);
|
|
1682
1721
|
const hash = hashFunctionBody(body, sourceFile);
|
|
@@ -1698,17 +1737,17 @@ function buildFunctionEntry(body, parameters, sourceFile, file, lineNode, name,
|
|
|
1698
1737
|
};
|
|
1699
1738
|
}
|
|
1700
1739
|
function collectFunctions(node, file, sourceFile, checker, registry) {
|
|
1701
|
-
if (
|
|
1740
|
+
if (ts29.isFunctionDeclaration(node) && node.name && node.body) {
|
|
1702
1741
|
registry.add(buildFunctionEntry(node.body, node.parameters, sourceFile, file, node, node.name.text, {
|
|
1703
1742
|
exported: isExported(node),
|
|
1704
1743
|
symbol: checker.getSymbolAtLocation(node.name),
|
|
1705
1744
|
node
|
|
1706
1745
|
}));
|
|
1707
1746
|
}
|
|
1708
|
-
if (
|
|
1747
|
+
if (ts29.isVariableStatement(node)) {
|
|
1709
1748
|
const exported = isExported(node);
|
|
1710
1749
|
for (const decl of node.declarationList.declarations) {
|
|
1711
|
-
if (decl.initializer &&
|
|
1750
|
+
if (decl.initializer && ts29.isArrowFunction(decl.initializer) && ts29.isIdentifier(decl.name)) {
|
|
1712
1751
|
const arrow = decl.initializer;
|
|
1713
1752
|
registry.add(buildFunctionEntry(arrow.body, arrow.parameters, sourceFile, file, decl, decl.name.text, {
|
|
1714
1753
|
exported,
|
|
@@ -1716,7 +1755,7 @@ function collectFunctions(node, file, sourceFile, checker, registry) {
|
|
|
1716
1755
|
node: arrow
|
|
1717
1756
|
}));
|
|
1718
1757
|
}
|
|
1719
|
-
if (decl.initializer &&
|
|
1758
|
+
if (decl.initializer && ts29.isFunctionExpression(decl.initializer) && ts29.isIdentifier(decl.name)) {
|
|
1720
1759
|
const fn = decl.initializer;
|
|
1721
1760
|
if (fn.body) {
|
|
1722
1761
|
registry.add(buildFunctionEntry(fn.body, fn.parameters, sourceFile, file, decl, decl.name.text, {
|
|
@@ -1728,22 +1767,22 @@ function collectFunctions(node, file, sourceFile, checker, registry) {
|
|
|
1728
1767
|
}
|
|
1729
1768
|
}
|
|
1730
1769
|
}
|
|
1731
|
-
if (
|
|
1770
|
+
if (ts29.isPropertyAssignment(node) && (ts29.isIdentifier(node.name) || ts29.isStringLiteral(node.name))) {
|
|
1732
1771
|
const init = node.initializer;
|
|
1733
1772
|
const propName = node.name.text;
|
|
1734
|
-
if (
|
|
1773
|
+
if (ts29.isArrowFunction(init)) {
|
|
1735
1774
|
registry.add(buildFunctionEntry(init.body, init.parameters, sourceFile, file, node, propName, { node: init }));
|
|
1736
1775
|
}
|
|
1737
|
-
if (
|
|
1776
|
+
if (ts29.isFunctionExpression(init) && init.body) {
|
|
1738
1777
|
registry.add(buildFunctionEntry(init.body, init.parameters, sourceFile, file, node, propName, { node: init }));
|
|
1739
1778
|
}
|
|
1740
1779
|
}
|
|
1741
|
-
if (
|
|
1780
|
+
if (ts29.isArrowFunction(node) || ts29.isFunctionExpression(node)) {
|
|
1742
1781
|
const parent = node.parent;
|
|
1743
|
-
if (
|
|
1744
|
-
} else if (
|
|
1782
|
+
if (ts29.isVariableDeclaration(parent) && ts29.isIdentifier(parent.name)) {
|
|
1783
|
+
} else if (ts29.isPropertyAssignment(parent)) {
|
|
1745
1784
|
} else {
|
|
1746
|
-
const body =
|
|
1785
|
+
const body = ts29.isArrowFunction(node) ? node.body : node.body;
|
|
1747
1786
|
if (body) {
|
|
1748
1787
|
const MIN_ANON_BODY = 64;
|
|
1749
1788
|
if (bodyTextLength(body, sourceFile) >= MIN_ANON_BODY) {
|
|
@@ -1753,14 +1792,14 @@ function collectFunctions(node, file, sourceFile, checker, registry) {
|
|
|
1753
1792
|
}
|
|
1754
1793
|
}
|
|
1755
1794
|
}
|
|
1756
|
-
if (
|
|
1795
|
+
if (ts29.isMethodDeclaration(node) && node.body && ts29.isIdentifier(node.name)) {
|
|
1757
1796
|
const parent = node.parent;
|
|
1758
|
-
if (
|
|
1797
|
+
if (ts29.isClassDeclaration(parent)) {
|
|
1759
1798
|
if (hasNonPublicModifier(node)) return;
|
|
1760
1799
|
const className = parent.name ? parent.name.text : "<anonymous>";
|
|
1761
1800
|
const name = `${className}.${node.name.text}`;
|
|
1762
1801
|
const implementsInterface = parent.heritageClauses?.some(
|
|
1763
|
-
(c) => c.token ===
|
|
1802
|
+
(c) => c.token === ts29.SyntaxKind.ImplementsKeyword
|
|
1764
1803
|
) ?? false;
|
|
1765
1804
|
registry.add(buildFunctionEntry(node.body, node.parameters, sourceFile, file, node, name, {
|
|
1766
1805
|
exported: isExported(parent),
|
|
@@ -1783,16 +1822,16 @@ function extractParams(parameters, sourceFile) {
|
|
|
1783
1822
|
}
|
|
1784
1823
|
function deriveAnonymousName(node, sourceFile) {
|
|
1785
1824
|
const parent = node.parent;
|
|
1786
|
-
const line =
|
|
1787
|
-
if (
|
|
1825
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
|
|
1826
|
+
if (ts29.isCallExpression(parent)) {
|
|
1788
1827
|
const grandparent = parent.parent;
|
|
1789
|
-
if (
|
|
1828
|
+
if (ts29.isPropertyAssignment(grandparent) && ts29.isIdentifier(grandparent.name)) {
|
|
1790
1829
|
return grandparent.name.text;
|
|
1791
1830
|
}
|
|
1792
1831
|
let calleeName = null;
|
|
1793
|
-
if (
|
|
1832
|
+
if (ts29.isIdentifier(parent.expression)) {
|
|
1794
1833
|
calleeName = parent.expression.text;
|
|
1795
|
-
} else if (
|
|
1834
|
+
} else if (ts29.isPropertyAccessExpression(parent.expression)) {
|
|
1796
1835
|
calleeName = parent.expression.name.text;
|
|
1797
1836
|
}
|
|
1798
1837
|
if (calleeName) {
|
|
@@ -1803,7 +1842,7 @@ function deriveAnonymousName(node, sourceFile) {
|
|
|
1803
1842
|
return `<anonymous>:${line}`;
|
|
1804
1843
|
}
|
|
1805
1844
|
function collectImports(node, file, imports) {
|
|
1806
|
-
if (
|
|
1845
|
+
if (ts29.isImportDeclaration(node) && ts29.isStringLiteral(node.moduleSpecifier)) {
|
|
1807
1846
|
const moduleSource = node.moduleSpecifier.text;
|
|
1808
1847
|
const clause = node.importClause;
|
|
1809
1848
|
if (!clause) return;
|
|
@@ -1815,7 +1854,7 @@ function collectImports(node, file, imports) {
|
|
|
1815
1854
|
source: moduleSource
|
|
1816
1855
|
});
|
|
1817
1856
|
}
|
|
1818
|
-
if (clause.namedBindings &&
|
|
1857
|
+
if (clause.namedBindings && ts29.isNamedImports(clause.namedBindings)) {
|
|
1819
1858
|
for (const el of clause.namedBindings.elements) {
|
|
1820
1859
|
imports.push({
|
|
1821
1860
|
file,
|
|
@@ -1826,9 +1865,9 @@ function collectImports(node, file, imports) {
|
|
|
1826
1865
|
}
|
|
1827
1866
|
}
|
|
1828
1867
|
}
|
|
1829
|
-
if (
|
|
1868
|
+
if (ts29.isExportDeclaration(node) && node.moduleSpecifier && ts29.isStringLiteral(node.moduleSpecifier)) {
|
|
1830
1869
|
const moduleSource = node.moduleSpecifier.text;
|
|
1831
|
-
if (node.exportClause &&
|
|
1870
|
+
if (node.exportClause && ts29.isNamedExports(node.exportClause)) {
|
|
1832
1871
|
for (const el of node.exportClause.elements) {
|
|
1833
1872
|
imports.push({
|
|
1834
1873
|
file,
|
|
@@ -1841,7 +1880,7 @@ function collectImports(node, file, imports) {
|
|
|
1841
1880
|
}
|
|
1842
1881
|
}
|
|
1843
1882
|
function collectStatementSequences(node, file, sourceFile, registry) {
|
|
1844
|
-
if (!
|
|
1883
|
+
if (!ts29.isBlock(node)) return;
|
|
1845
1884
|
const stmts = node.statements;
|
|
1846
1885
|
const n = stmts.length;
|
|
1847
1886
|
if (n < 3) return;
|
|
@@ -1858,34 +1897,34 @@ function collectStatementSequences(node, file, sourceFile, registry) {
|
|
|
1858
1897
|
const firstStmt = window[0];
|
|
1859
1898
|
const lastStmt = window[window.length - 1];
|
|
1860
1899
|
if (firstStmt === void 0 || lastStmt === void 0) continue;
|
|
1861
|
-
const line =
|
|
1862
|
-
const endLine =
|
|
1900
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, firstStmt.getStart(sourceFile)).line + 1;
|
|
1901
|
+
const endLine = ts29.getLineAndCharacterOfPosition(sourceFile, lastStmt.getEnd()).line + 1;
|
|
1863
1902
|
registry.add({ file, line, endLine, hash, normalizedHash, statementCount: size, normalizedBodyLength: normalized.length });
|
|
1864
1903
|
}
|
|
1865
1904
|
}
|
|
1866
1905
|
}
|
|
1867
1906
|
function collectInlineParamTypes(node, file, sourceFile, registry) {
|
|
1868
|
-
if (!
|
|
1907
|
+
if (!ts29.isTypeLiteralNode(node)) return;
|
|
1869
1908
|
const parent = node.parent;
|
|
1870
|
-
if (!parent || !
|
|
1909
|
+
if (!parent || !ts29.isParameter(parent)) return;
|
|
1871
1910
|
if (parent.type !== node) return;
|
|
1872
|
-
const line =
|
|
1911
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
|
|
1873
1912
|
registry.add(file, line, node, sourceFile);
|
|
1874
1913
|
}
|
|
1875
1914
|
function collectCallSites(node, file, sourceFile, checker, sites) {
|
|
1876
|
-
if (!
|
|
1915
|
+
if (!ts29.isCallExpression(node)) return;
|
|
1877
1916
|
let calleeName = null;
|
|
1878
|
-
if (
|
|
1917
|
+
if (ts29.isIdentifier(node.expression)) {
|
|
1879
1918
|
calleeName = node.expression.text;
|
|
1880
|
-
} else if (
|
|
1919
|
+
} else if (ts29.isPropertyAccessExpression(node.expression)) {
|
|
1881
1920
|
calleeName = node.expression.name.text;
|
|
1882
1921
|
}
|
|
1883
1922
|
if (calleeName) {
|
|
1884
|
-
const line =
|
|
1923
|
+
const line = ts29.getLineAndCharacterOfPosition(sourceFile, node.getStart(sourceFile)).line + 1;
|
|
1885
1924
|
let symbol;
|
|
1886
1925
|
try {
|
|
1887
1926
|
symbol = checker.getSymbolAtLocation(node.expression);
|
|
1888
|
-
if (symbol && symbol.flags &
|
|
1927
|
+
if (symbol && symbol.flags & ts29.SymbolFlags.Alias) {
|
|
1889
1928
|
symbol = checker.getAliasedSymbol(symbol);
|
|
1890
1929
|
}
|
|
1891
1930
|
} catch {
|
|
@@ -1905,12 +1944,12 @@ function collectAllComments(sourceFile) {
|
|
|
1905
1944
|
const source = sourceFile.getFullText();
|
|
1906
1945
|
const seen = /* @__PURE__ */ new Set();
|
|
1907
1946
|
function visit(node) {
|
|
1908
|
-
const leading =
|
|
1947
|
+
const leading = ts29.getLeadingCommentRanges(source, node.getFullStart());
|
|
1909
1948
|
if (leading) {
|
|
1910
1949
|
for (const r of leading) {
|
|
1911
1950
|
if (seen.has(r.pos)) continue;
|
|
1912
1951
|
seen.add(r.pos);
|
|
1913
|
-
const isLine = r.kind ===
|
|
1952
|
+
const isLine = r.kind === ts29.SyntaxKind.SingleLineCommentTrivia;
|
|
1914
1953
|
comments.push({
|
|
1915
1954
|
type: isLine ? "Line" : "Block",
|
|
1916
1955
|
value: source.slice(r.pos + 2, isLine ? r.end : r.end - 2),
|
|
@@ -1919,12 +1958,12 @@ function collectAllComments(sourceFile) {
|
|
|
1919
1958
|
});
|
|
1920
1959
|
}
|
|
1921
1960
|
}
|
|
1922
|
-
const trailing =
|
|
1961
|
+
const trailing = ts29.getTrailingCommentRanges(source, node.getEnd());
|
|
1923
1962
|
if (trailing) {
|
|
1924
1963
|
for (const r of trailing) {
|
|
1925
1964
|
if (seen.has(r.pos)) continue;
|
|
1926
1965
|
seen.add(r.pos);
|
|
1927
|
-
const isLine = r.kind ===
|
|
1966
|
+
const isLine = r.kind === ts29.SyntaxKind.SingleLineCommentTrivia;
|
|
1928
1967
|
comments.push({
|
|
1929
1968
|
type: isLine ? "Line" : "Block",
|
|
1930
1969
|
value: source.slice(r.pos + 2, isLine ? r.end : r.end - 2),
|
|
@@ -1933,34 +1972,34 @@ function collectAllComments(sourceFile) {
|
|
|
1933
1972
|
});
|
|
1934
1973
|
}
|
|
1935
1974
|
}
|
|
1936
|
-
|
|
1975
|
+
ts29.forEachChild(node, visit);
|
|
1937
1976
|
}
|
|
1938
1977
|
visit(sourceFile);
|
|
1939
1978
|
return comments;
|
|
1940
1979
|
}
|
|
1941
1980
|
|
|
1942
1981
|
// src/typecheck/program.ts
|
|
1943
|
-
import * as
|
|
1982
|
+
import * as ts30 from "typescript";
|
|
1944
1983
|
import { dirname as dirname2 } from "path";
|
|
1945
1984
|
function createProgramFromFiles(files) {
|
|
1946
1985
|
let configPath;
|
|
1947
1986
|
if (files.length > 0) {
|
|
1948
|
-
configPath =
|
|
1987
|
+
configPath = ts30.findConfigFile(dirname2(files[0]), ts30.sys.fileExists, "tsconfig.json");
|
|
1949
1988
|
}
|
|
1950
1989
|
if (configPath) {
|
|
1951
|
-
const configFile =
|
|
1952
|
-
const parsed =
|
|
1953
|
-
return
|
|
1990
|
+
const configFile = ts30.readConfigFile(configPath, ts30.sys.readFile);
|
|
1991
|
+
const parsed = ts30.parseJsonConfigFileContent(configFile.config, ts30.sys, dirname2(configPath));
|
|
1992
|
+
return ts30.createProgram({
|
|
1954
1993
|
rootNames: files,
|
|
1955
1994
|
options: { ...parsed.options, skipLibCheck: true }
|
|
1956
1995
|
});
|
|
1957
1996
|
}
|
|
1958
|
-
return
|
|
1997
|
+
return ts30.createProgram({
|
|
1959
1998
|
rootNames: files,
|
|
1960
1999
|
options: {
|
|
1961
|
-
target:
|
|
1962
|
-
module:
|
|
1963
|
-
moduleResolution:
|
|
2000
|
+
target: ts30.ScriptTarget.ESNext,
|
|
2001
|
+
module: ts30.ModuleKind.ESNext,
|
|
2002
|
+
moduleResolution: ts30.ModuleResolutionKind.Bundler,
|
|
1964
2003
|
strict: true,
|
|
1965
2004
|
skipLibCheck: true,
|
|
1966
2005
|
noEmit: true
|
|
@@ -2200,4 +2239,4 @@ export {
|
|
|
2200
2239
|
executeScan,
|
|
2201
2240
|
scan
|
|
2202
2241
|
};
|
|
2203
|
-
//# sourceMappingURL=chunk-
|
|
2242
|
+
//# sourceMappingURL=chunk-NNUATKJZ.js.map
|