@flint.fyi/ts 0.14.3 → 0.14.5

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/lib/createTypeScriptFileFromProgram.js +5 -1
  3. package/lib/index.d.ts +3 -0
  4. package/lib/index.js +3 -0
  5. package/lib/language.d.ts +1 -0
  6. package/lib/plugin.d.ts +61 -1
  7. package/lib/plugin.js +30 -0
  8. package/lib/rules/anyReturns.d.ts +6 -0
  9. package/lib/rules/anyReturns.js +187 -0
  10. package/lib/rules/anyReturns.test.d.ts +1 -0
  11. package/lib/rules/anyReturns.test.js +647 -0
  12. package/lib/rules/caseDuplicates.d.ts +6 -0
  13. package/lib/rules/caseDuplicates.js +49 -0
  14. package/lib/rules/caseDuplicates.test.d.ts +1 -0
  15. package/lib/rules/caseDuplicates.test.js +307 -0
  16. package/lib/rules/chainedAssignments.js +2 -1
  17. package/lib/rules/chainedAssignments.test.js +24 -0
  18. package/lib/rules/debuggerStatements.test.js +4 -4
  19. package/lib/rules/elseIfDuplicates.d.ts +6 -0
  20. package/lib/rules/elseIfDuplicates.js +53 -0
  21. package/lib/rules/elseIfDuplicates.test.d.ts +1 -0
  22. package/lib/rules/elseIfDuplicates.test.js +176 -0
  23. package/lib/rules/emptyBlocks.d.ts +6 -0
  24. package/lib/rules/emptyBlocks.js +66 -0
  25. package/lib/rules/emptyBlocks.test.d.ts +1 -0
  26. package/lib/rules/emptyBlocks.test.js +135 -0
  27. package/lib/rules/forDirections.d.ts +6 -0
  28. package/lib/rules/forDirections.js +124 -0
  29. package/lib/rules/forDirections.test.d.ts +1 -0
  30. package/lib/rules/forDirections.test.js +99 -0
  31. package/lib/rules/functionNewCalls.d.ts +6 -0
  32. package/lib/rules/functionNewCalls.js +60 -0
  33. package/lib/rules/functionNewCalls.test.d.ts +1 -0
  34. package/lib/rules/functionNewCalls.test.js +115 -0
  35. package/lib/rules/negativeZeroComparisons.js +4 -22
  36. package/lib/rules/nonOctalDecimalEscapes.d.ts +6 -0
  37. package/lib/rules/nonOctalDecimalEscapes.js +57 -0
  38. package/lib/rules/nonOctalDecimalEscapes.test.d.ts +1 -0
  39. package/lib/rules/nonOctalDecimalEscapes.test.js +69 -0
  40. package/lib/rules/numericLiteralParsing.d.ts +6 -0
  41. package/lib/rules/numericLiteralParsing.js +97 -0
  42. package/lib/rules/numericLiteralParsing.test.d.ts +1 -0
  43. package/lib/rules/numericLiteralParsing.test.js +99 -0
  44. package/lib/rules/octalNumbers.test.js +2 -2
  45. package/lib/rules/selfAssignments.d.ts +6 -0
  46. package/lib/rules/selfAssignments.js +44 -0
  47. package/lib/rules/selfAssignments.test.d.ts +1 -0
  48. package/lib/rules/selfAssignments.test.js +66 -0
  49. package/lib/rules/selfComparisons.d.ts +6 -0
  50. package/lib/rules/selfComparisons.js +41 -0
  51. package/lib/rules/selfComparisons.test.d.ts +1 -0
  52. package/lib/rules/selfComparisons.test.js +297 -0
  53. package/lib/rules/sequences.d.ts +6 -0
  54. package/lib/rules/sequences.js +34 -0
  55. package/lib/rules/sequences.test.d.ts +1 -0
  56. package/lib/rules/sequences.test.js +48 -0
  57. package/lib/rules/shadowedRestrictedNames.d.ts +6 -0
  58. package/lib/rules/shadowedRestrictedNames.js +95 -0
  59. package/lib/rules/shadowedRestrictedNames.test.d.ts +1 -0
  60. package/lib/rules/shadowedRestrictedNames.test.js +147 -0
  61. package/lib/rules/symbolDescriptions.test.js +4 -4
  62. package/lib/rules/typeofComparisons.d.ts +6 -0
  63. package/lib/rules/typeofComparisons.js +78 -0
  64. package/lib/rules/typeofComparisons.test.d.ts +1 -0
  65. package/lib/rules/typeofComparisons.test.js +85 -0
  66. package/lib/rules/unicodeBOMs.test.js +1 -0
  67. package/lib/rules/unnecessaryBlocks.d.ts +6 -0
  68. package/lib/rules/unnecessaryBlocks.js +75 -0
  69. package/lib/rules/unnecessaryBlocks.test.d.ts +1 -0
  70. package/lib/rules/unnecessaryBlocks.test.js +147 -0
  71. package/lib/rules/unnecessaryConcatenation.d.ts +6 -0
  72. package/lib/rules/unnecessaryConcatenation.js +38 -0
  73. package/lib/rules/unnecessaryConcatenation.test.d.ts +1 -0
  74. package/lib/rules/unnecessaryConcatenation.test.js +87 -0
  75. package/lib/rules/utils/discriminateAnyType.d.ts +12 -0
  76. package/lib/rules/utils/discriminateAnyType.js +41 -0
  77. package/lib/rules/utils/getThisExpression.d.ts +2 -0
  78. package/lib/rules/utils/getThisExpression.js +23 -0
  79. package/lib/rules/utils/isUnsafeAssignment.d.ts +13 -0
  80. package/lib/rules/utils/isUnsafeAssignment.js +76 -0
  81. package/lib/rules/utils/operators.d.ts +4 -0
  82. package/lib/rules/utils/operators.js +36 -0
  83. package/lib/rules/voidOperator.test.js +2 -2
  84. package/lib/utils/declarationIncludesGlobal.d.ts +2 -0
  85. package/lib/utils/declarationIncludesGlobal.js +5 -0
  86. package/lib/utils/declarationsIncludeGlobal.js +2 -5
  87. package/lib/utils/getDeclarationsIfGlobal.d.ts +2 -0
  88. package/lib/utils/getDeclarationsIfGlobal.js +7 -0
  89. package/lib/utils/hasSameTokens.d.ts +2 -0
  90. package/lib/utils/hasSameTokens.js +30 -0
  91. package/lib/utils/isGlobalDeclaration.js +2 -3
  92. package/lib/utils/isGlobalDeclarationOfName.d.ts +5 -0
  93. package/lib/utils/isGlobalDeclarationOfName.js +35 -0
  94. package/package.json +3 -3
  95. package/src/createTypeScriptFileFromProgram.ts +6 -1
  96. package/src/index.ts +3 -0
  97. package/src/language.ts +1 -0
  98. package/src/plugin.ts +30 -0
  99. package/src/rules/anyReturns.test.ts +649 -0
  100. package/src/rules/anyReturns.ts +263 -0
  101. package/src/rules/caseDuplicates.test.ts +308 -0
  102. package/src/rules/caseDuplicates.ts +57 -0
  103. package/src/rules/chainedAssignments.test.ts +24 -0
  104. package/src/rules/chainedAssignments.ts +4 -1
  105. package/src/rules/debuggerStatements.test.ts +4 -4
  106. package/src/rules/elseIfDuplicates.test.ts +177 -0
  107. package/src/rules/elseIfDuplicates.ts +69 -0
  108. package/src/rules/emptyBlocks.test.ts +136 -0
  109. package/src/rules/emptyBlocks.ts +73 -0
  110. package/src/rules/forDirections.test.ts +100 -0
  111. package/src/rules/forDirections.ts +163 -0
  112. package/src/rules/functionNewCalls.test.ts +116 -0
  113. package/src/rules/functionNewCalls.ts +75 -0
  114. package/src/rules/negativeZeroComparisons.ts +8 -27
  115. package/src/rules/nonOctalDecimalEscapes.test.ts +70 -0
  116. package/src/rules/nonOctalDecimalEscapes.ts +70 -0
  117. package/src/rules/numericLiteralParsing.test.ts +100 -0
  118. package/src/rules/numericLiteralParsing.ts +116 -0
  119. package/src/rules/octalNumbers.test.ts +2 -2
  120. package/src/rules/selfAssignments.test.ts +67 -0
  121. package/src/rules/selfAssignments.ts +50 -0
  122. package/src/rules/selfComparisons.test.ts +298 -0
  123. package/src/rules/selfComparisons.ts +45 -0
  124. package/src/rules/sequences.test.ts +49 -0
  125. package/src/rules/sequences.ts +37 -0
  126. package/src/rules/shadowedRestrictedNames.test.ts +148 -0
  127. package/src/rules/shadowedRestrictedNames.ts +105 -0
  128. package/src/rules/symbolDescriptions.test.ts +4 -4
  129. package/src/rules/typeofComparisons.test.ts +86 -0
  130. package/src/rules/typeofComparisons.ts +88 -0
  131. package/src/rules/unicodeBOMs.test.ts +1 -0
  132. package/src/rules/unnecessaryBlocks.test.ts +148 -0
  133. package/src/rules/unnecessaryBlocks.ts +89 -0
  134. package/src/rules/unnecessaryConcatenation.test.ts +88 -0
  135. package/src/rules/unnecessaryConcatenation.ts +44 -0
  136. package/src/rules/utils/discriminateAnyType.ts +66 -0
  137. package/src/rules/utils/getThisExpression.ts +24 -0
  138. package/src/rules/utils/isUnsafeAssignment.ts +113 -0
  139. package/src/rules/utils/operators.ts +39 -0
  140. package/src/rules/voidOperator.test.ts +2 -2
  141. package/src/utils/declarationIncludesGlobal.ts +9 -0
  142. package/src/utils/declarationsIncludeGlobal.ts +3 -7
  143. package/src/utils/getDeclarationsIfGlobal.ts +14 -0
  144. package/src/utils/hasSameTokens.ts +45 -0
  145. package/src/utils/isGlobalDeclaration.ts +3 -5
  146. package/src/utils/isGlobalDeclarationOfName.ts +56 -0
  147. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,66 @@
1
+ import * as tsutils from "ts-api-utils";
2
+ import * as ts from "typescript";
3
+
4
+ export enum AnyType {
5
+ Any,
6
+ PromiseAny,
7
+ AnyArray,
8
+ Safe,
9
+ }
10
+
11
+ /**
12
+ * @returns `AnyType.Any` if the type is `any`, `AnyType.AnyArray` if the type is `any[]` or `readonly any[]`, `AnyType.PromiseAny` if the type is `Promise<any>`,
13
+ * otherwise it returns `AnyType.Safe`.
14
+ */
15
+ export function discriminateAnyType(
16
+ type: ts.Type,
17
+ checker: ts.TypeChecker,
18
+ program: ts.Program,
19
+ tsNode: ts.Node,
20
+ ): AnyType {
21
+ return discriminateAnyTypeWorker(type, checker, program, tsNode, new Set());
22
+ }
23
+
24
+ function discriminateAnyTypeWorker(
25
+ type: ts.Type,
26
+ checker: ts.TypeChecker,
27
+ program: ts.Program,
28
+ tsNode: ts.Node,
29
+ visited: Set<ts.Type>,
30
+ ) {
31
+ if (visited.has(type)) {
32
+ return AnyType.Safe;
33
+ }
34
+ visited.add(type);
35
+ if (tsutils.isTypeFlagSet(type, ts.TypeFlags.Any)) {
36
+ return AnyType.Any;
37
+ }
38
+ if (
39
+ checker.isArrayType(type) &&
40
+ tsutils.isTypeFlagSet(
41
+ checker.getTypeArguments(type as ts.TypeReference)[0],
42
+ ts.TypeFlags.Any,
43
+ )
44
+ ) {
45
+ return AnyType.AnyArray;
46
+ }
47
+ for (const part of tsutils.typeConstituents(type)) {
48
+ if (tsutils.isThenableType(checker, tsNode, part)) {
49
+ const awaitedType = checker.getAwaitedType(part);
50
+ if (awaitedType) {
51
+ const awaitedAnyType = discriminateAnyTypeWorker(
52
+ awaitedType,
53
+ checker,
54
+ program,
55
+ tsNode,
56
+ visited,
57
+ );
58
+ if (awaitedAnyType === AnyType.Any) {
59
+ return AnyType.PromiseAny;
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ return AnyType.Safe;
66
+ }
@@ -0,0 +1,24 @@
1
+ import * as tsutils from "ts-api-utils";
2
+ import * as ts from "typescript";
3
+
4
+ export function getThisExpression(node: ts.Node): null | ts.ThisExpression {
5
+ while (true) {
6
+ node = skipParentheses(node);
7
+ if (ts.isCallExpression(node) || tsutils.isAccessExpression(node)) {
8
+ node = node.expression;
9
+ } else if (tsutils.isThisExpression(node)) {
10
+ return node;
11
+ } else {
12
+ break;
13
+ }
14
+ }
15
+
16
+ return null;
17
+ }
18
+
19
+ function skipParentheses(node: ts.Node): ts.Node {
20
+ while (ts.isParenthesizedExpression(node)) {
21
+ node = node.expression;
22
+ }
23
+ return node;
24
+ }
@@ -0,0 +1,113 @@
1
+ import * as tsutils from "ts-api-utils";
2
+ import * as ts from "typescript";
3
+
4
+ /**
5
+ * Does a simple check to see if there is an any being assigned to a non-any type.
6
+ *
7
+ * This also checks generic positions to ensure there's no unsafe sub-assignments.
8
+ * Note: in the case of generic positions, it makes the assumption that the two types are the same.
9
+ * @example See tests for examples
10
+ * @returns false if it's safe, or an object with the two types if it's unsafe
11
+ */
12
+ export function isUnsafeAssignment(
13
+ type: ts.Type,
14
+ receiver: ts.Type,
15
+ checker: ts.TypeChecker,
16
+ senderNode: null | ts.Node,
17
+ ): false | { receiver: ts.Type; sender: ts.Type } {
18
+ return isUnsafeAssignmentWorker(
19
+ type,
20
+ receiver,
21
+ checker,
22
+ senderNode,
23
+ new Map(),
24
+ );
25
+ }
26
+
27
+ function isUnsafeAssignmentWorker(
28
+ type: ts.Type,
29
+ receiver: ts.Type,
30
+ checker: ts.TypeChecker,
31
+ senderNode: null | ts.Node,
32
+ visited: Map<ts.Type, Set<ts.Type>>,
33
+ ): false | { receiver: ts.Type; sender: ts.Type } {
34
+ if (tsutils.isTypeFlagSet(type, ts.TypeFlags.Any)) {
35
+ // Allow assignment of any ==> unknown.
36
+ if (tsutils.isTypeFlagSet(receiver, ts.TypeFlags.Unknown)) {
37
+ return false;
38
+ }
39
+
40
+ if (!tsutils.isTypeFlagSet(receiver, ts.TypeFlags.Any)) {
41
+ return { receiver, sender: type };
42
+ }
43
+ }
44
+
45
+ const typeAlreadyVisited = visited.get(type);
46
+
47
+ if (typeAlreadyVisited) {
48
+ if (typeAlreadyVisited.has(receiver)) {
49
+ return false;
50
+ }
51
+ typeAlreadyVisited.add(receiver);
52
+ } else {
53
+ visited.set(type, new Set([receiver]));
54
+ }
55
+
56
+ if (tsutils.isTypeReference(type) && tsutils.isTypeReference(receiver)) {
57
+ // TODO - figure out how to handle cases like this,
58
+ // where the types are assignable, but not the same type
59
+ /*
60
+ function foo(): ReadonlySet<number> { return new Set<any>(); }
61
+
62
+ // and
63
+
64
+ type Test<T> = { prop: T }
65
+ type Test2 = { prop: string }
66
+ declare const a: Test<any>;
67
+ const b: Test2 = a;
68
+ */
69
+
70
+ if (type.target !== receiver.target) {
71
+ // if the type references are different, assume safe, as we won't know how to compare the two types
72
+ // the generic positions might not be equivalent for both types
73
+ return false;
74
+ }
75
+
76
+ if (
77
+ senderNode != null &&
78
+ ts.isNewExpression(senderNode) &&
79
+ ts.isIdentifier(senderNode.expression) &&
80
+ senderNode.expression.text === "Map" &&
81
+ (senderNode.arguments == null || senderNode.arguments.length === 0) &&
82
+ senderNode.typeArguments == null
83
+ ) {
84
+ // special case to handle `new Map()`
85
+ // unfortunately Map's default empty constructor is typed to return `Map<any, any>` :(
86
+ // https://github.com/typescript-eslint/typescript-eslint/issues/2109#issuecomment-634144396
87
+ return false;
88
+ }
89
+
90
+ const typeArguments = type.typeArguments ?? [];
91
+ const receiverTypeArguments = receiver.typeArguments ?? [];
92
+
93
+ for (let i = 0; i < typeArguments.length; i += 1) {
94
+ const arg = typeArguments[i];
95
+ const receiverArg = receiverTypeArguments[i];
96
+
97
+ const unsafe = isUnsafeAssignmentWorker(
98
+ arg,
99
+ receiverArg,
100
+ checker,
101
+ senderNode,
102
+ visited,
103
+ );
104
+ if (unsafe) {
105
+ return { receiver, sender: type };
106
+ }
107
+ }
108
+
109
+ return false;
110
+ }
111
+
112
+ return false;
113
+ }
@@ -0,0 +1,39 @@
1
+ import * as ts from "typescript";
2
+
3
+ export function isComparisonOperator(token: ts.BinaryOperatorToken) {
4
+ switch (token.kind) {
5
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
6
+ case ts.SyntaxKind.EqualsEqualsToken:
7
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
8
+ case ts.SyntaxKind.ExclamationEqualsToken:
9
+ case ts.SyntaxKind.GreaterThanEqualsToken:
10
+ case ts.SyntaxKind.GreaterThanToken:
11
+ case ts.SyntaxKind.LessThanEqualsToken:
12
+ case ts.SyntaxKind.LessThanToken:
13
+ return true;
14
+ default:
15
+ return false;
16
+ }
17
+ }
18
+
19
+ export function isEqualityOperator(token: ts.BinaryOperatorToken) {
20
+ switch (token.kind) {
21
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
22
+ case ts.SyntaxKind.EqualsEqualsToken:
23
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
24
+ case ts.SyntaxKind.ExclamationEqualsToken:
25
+ return true;
26
+ default:
27
+ return false;
28
+ }
29
+ }
30
+
31
+ export function isNegatedEqualityOperator(token: ts.BinaryOperatorToken) {
32
+ switch (token.kind) {
33
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
34
+ case ts.SyntaxKind.ExclamationEqualsToken:
35
+ return true;
36
+ default:
37
+ return false;
38
+ }
39
+ }
@@ -72,8 +72,8 @@ function process() {
72
72
  snapshot: `
73
73
  function process() {
74
74
  void doSomething();
75
- ~~~~~~~~~~~~~~~~~~
76
- Prefer an explicit value over using the void operator to produce undefined.
75
+ ~~~~~~~~~~~~~~~~~~
76
+ Prefer an explicit value over using the void operator to produce undefined.
77
77
  }
78
78
  `,
79
79
  },
@@ -0,0 +1,9 @@
1
+ import * as ts from "typescript";
2
+
3
+ export function declarationIncludesGlobal(declaration: ts.Declaration) {
4
+ const sourceFile = declaration.getSourceFile();
5
+ return (
6
+ sourceFile.hasNoDefaultLib ||
7
+ /\/lib\.[^/]*\.d\.ts$/.test(sourceFile.fileName)
8
+ );
9
+ }
@@ -1,11 +1,7 @@
1
1
  import * as ts from "typescript";
2
2
 
3
+ import { declarationIncludesGlobal } from "./declarationIncludesGlobal.js";
4
+
3
5
  export function declarationsIncludeGlobal(declarations: ts.Declaration[]) {
4
- return declarations.some((declaration) => {
5
- const sourceFile = declaration.getSourceFile();
6
- return (
7
- sourceFile.hasNoDefaultLib ||
8
- /\/lib\.[^/]*\.d\.ts$/.test(sourceFile.fileName)
9
- );
10
- });
6
+ return declarations.some(declarationIncludesGlobal);
11
7
  }
@@ -0,0 +1,14 @@
1
+ import * as ts from "typescript";
2
+
3
+ import { declarationsIncludeGlobal } from "./declarationsIncludeGlobal.js";
4
+
5
+ export function getDeclarationsIfGlobal(
6
+ node: ts.Expression,
7
+ typeChecker: ts.TypeChecker,
8
+ ) {
9
+ const declarations = typeChecker.getSymbolAtLocation(node)?.getDeclarations();
10
+
11
+ return !!declarations && declarationsIncludeGlobal(declarations)
12
+ ? declarations
13
+ : undefined;
14
+ }
@@ -0,0 +1,45 @@
1
+ import * as ts from "typescript";
2
+
3
+ export function hasSameTokens(
4
+ nodeA: ts.Node,
5
+ nodeB: ts.Node,
6
+ sourceFile: ts.SourceFile,
7
+ ): boolean {
8
+ const queueA: ts.Node[] = [nodeA];
9
+ const queueB: ts.Node[] = [nodeB];
10
+
11
+ while (true) {
12
+ const currentA = queueA.shift();
13
+ const currentB = queueB.shift();
14
+
15
+ if (!currentA || !currentB) {
16
+ break;
17
+ }
18
+
19
+ if (currentA.kind !== currentB.kind) {
20
+ return false;
21
+ }
22
+
23
+ if (
24
+ currentA.kind >= ts.SyntaxKind.FirstToken &&
25
+ currentA.kind <= ts.SyntaxKind.LastToken
26
+ ) {
27
+ if (currentA.getText(sourceFile) !== currentB.getText(sourceFile)) {
28
+ return false;
29
+ }
30
+ continue;
31
+ }
32
+
33
+ const childrenA = currentA.getChildren(sourceFile);
34
+ const childrenB = currentB.getChildren(sourceFile);
35
+
36
+ if (childrenA.length !== childrenB.length) {
37
+ return false;
38
+ }
39
+
40
+ queueA.push(...childrenA);
41
+ queueB.push(...childrenB);
42
+ }
43
+
44
+ return queueA.length === queueB.length;
45
+ }
@@ -1,12 +1,10 @@
1
1
  import * as ts from "typescript";
2
2
 
3
- import { declarationsIncludeGlobal } from "./declarationsIncludeGlobal.js";
3
+ import { getDeclarationsIfGlobal } from "./getDeclarationsIfGlobal.js";
4
4
 
5
5
  export function isGlobalDeclaration(
6
6
  node: ts.Expression,
7
7
  typeChecker: ts.TypeChecker,
8
- ): boolean {
9
- const declarations = typeChecker.getSymbolAtLocation(node)?.getDeclarations();
10
-
11
- return !!declarations && declarationsIncludeGlobal(declarations);
8
+ ) {
9
+ return !!getDeclarationsIfGlobal(node, typeChecker);
12
10
  }
@@ -0,0 +1,56 @@
1
+ import * as ts from "typescript";
2
+
3
+ import { declarationIncludesGlobal } from "./declarationIncludesGlobal.js";
4
+
5
+ /**
6
+ * TODO: Use a scope analyzer (#400).
7
+ */
8
+ export function isGlobalDeclarationOfName(
9
+ node: ts.Node,
10
+ name: string,
11
+ typeChecker: ts.TypeChecker,
12
+ ): boolean {
13
+ const declarations = typeChecker.getSymbolAtLocation(node)?.getDeclarations();
14
+ if (!declarations) {
15
+ return false;
16
+ }
17
+
18
+ return declarations.every((declaration) => {
19
+ // Special case: a variable set to a known identifier. E.g.:
20
+ // const CustomFunction = Function;
21
+ if (
22
+ ts.isVariableDeclaration(declaration) &&
23
+ declaration.initializer &&
24
+ declaration.initializer.kind === ts.SyntaxKind.Identifier
25
+ ) {
26
+ return isGlobalDeclarationOfName(
27
+ declaration.initializer,
28
+ name,
29
+ typeChecker,
30
+ );
31
+ }
32
+
33
+ // Special case: a property of an interface
34
+ if (ts.isPropertySignature(declaration)) {
35
+ return isGlobalDeclarationOfName(declaration.parent, name, typeChecker);
36
+ }
37
+
38
+ return (
39
+ isDeclarationOfName(declaration, name) &&
40
+ declarationIncludesGlobal(declaration)
41
+ );
42
+ });
43
+ }
44
+
45
+ function isDeclarationOfName(node: ts.Node, name: string) {
46
+ if (
47
+ ts.isClassDeclaration(node) ||
48
+ ts.isFunctionDeclaration(node) ||
49
+ ts.isInterfaceDeclaration(node) ||
50
+ ts.isVariableDeclaration(node)
51
+ ) {
52
+ return node.name && ts.isIdentifier(node.name) && node.name.text === name;
53
+ }
54
+
55
+ return false;
56
+ }