Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e3f118f

Browse files
committed
test: reference tests
1 parent 2495ce9 commit e3f118f

File tree

7 files changed

+155
-15
lines changed

7 files changed

+155
-15
lines changed

packages/experimental-utils/src/ts-estree.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ export {
1010
TSESTree,
1111
} from '@typescript-eslint/typescript-estree/dist/ts-estree';
1212
export { simpleTraverse } from '@typescript-eslint/typescript-estree/dist/simple-traverse';
13+
export { visitorKeys } from '@typescript-eslint/typescript-estree/dist/visitor-keys';
1314
export { ParserServices } from '@typescript-eslint/typescript-estree/dist/parser-options';

packages/scope-manager/src/analyze.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils';
1+
import {
2+
TSESLint,
3+
TSESTree,
4+
visitorKeys,
5+
} from '@typescript-eslint/experimental-utils';
26
import { Referencer, ReferencerOptions } from './referencer';
37
import { ScopeManager } from './ScopeManager';
48

@@ -41,7 +45,7 @@ const DEFAULT_OPTIONS: Options = {
4145
impliedStrict: false,
4246
sourceType: 'script',
4347
ecmaVersion: 2018,
44-
childVisitorKeys: null,
48+
childVisitorKeys: visitorKeys,
4549
fallback: 'iteration',
4650
};
4751

packages/scope-manager/tests/serializers/Reference.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Reference } from '../../src/referencer/Reference';
44
const serializer = createSerializer(Reference, [
55
'identifier',
66
'init',
7+
'isTypeReference',
78
'resolved',
89
'writeExpr',
910
]);
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils';
2+
import { getSpecificNode, parseAndAnalyze } from '../util';
3+
4+
describe('referencing a type - positive', () => {
5+
it('records a reference when a type is referenced from a type', () => {
6+
const { ast, scopeManager } = parseAndAnalyze(`
7+
type TypeDecl = string;
8+
type OtherType = TypeDecl;
9+
`);
10+
const node = getSpecificNode(
11+
ast,
12+
AST_NODE_TYPES.TSTypeAliasDeclaration,
13+
n => (n.id.name === 'TypeDecl' ? n : null),
14+
);
15+
const variable = scopeManager.getDeclaredVariables(node)[0];
16+
17+
// there should be one reference from the declaration itself
18+
expect(variable.references).toHaveLength(2);
19+
expect(variable.references[0].identifier.parent).toBe(node);
20+
21+
// and one reference from the usage
22+
const otherTypeDecl = getSpecificNode(
23+
ast,
24+
AST_NODE_TYPES.TSTypeAliasDeclaration,
25+
n => (n.id.name === 'OtherType' ? n : null),
26+
);
27+
expect(variable.references[1].identifier.parent?.parent).toBe(
28+
otherTypeDecl,
29+
);
30+
});
31+
32+
it('records a reference when a dual value-type is referenced from a type', () => {
33+
const { ast, scopeManager } = parseAndAnalyze(`
34+
class Class {}
35+
type Type = Class;
36+
`);
37+
const node = getSpecificNode(ast, AST_NODE_TYPES.ClassDeclaration);
38+
const variable = scopeManager.getDeclaredVariables(node)[0];
39+
40+
// there should be one reference from the type declaration
41+
expect(variable.references).toHaveLength(1);
42+
const otherTypeDecl = getSpecificNode(
43+
ast,
44+
AST_NODE_TYPES.TSTypeAliasDeclaration,
45+
);
46+
expect(variable.references[0].identifier.parent?.parent).toBe(
47+
otherTypeDecl,
48+
);
49+
});
50+
51+
it('records a reference when a generic type parameter is referenced from its type', () => {
52+
const { ast, scopeManager } = parseAndAnalyze(`
53+
type TypeDecl<TypeParam> = TypeParam;
54+
`);
55+
const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeParameter);
56+
const variable = scopeManager.getDeclaredVariables(node)[0];
57+
58+
// there should be one reference from the declaration itself
59+
expect(variable.references).toHaveLength(2);
60+
expect(variable.references[0].identifier.parent).toBe(node);
61+
62+
// and one reference from the usage
63+
const usage = getSpecificNode(ast, AST_NODE_TYPES.TSTypeReference);
64+
expect(variable.references[1].identifier.parent).toBe(usage);
65+
});
66+
});
67+
68+
describe('referencing a type - negative', () => {
69+
it('does not record a reference when a value is referenced from a type', () => {
70+
const { ast, scopeManager } = parseAndAnalyze(`
71+
const value = 1;
72+
type Type = value;
73+
`);
74+
const node = getSpecificNode(ast, AST_NODE_TYPES.VariableDeclarator);
75+
const variable = scopeManager.getDeclaredVariables(node)[0];
76+
77+
// there should be one reference from the declaration itself
78+
expect(variable.references).toHaveLength(1);
79+
expect(variable.references[0].identifier.parent).toBe(node);
80+
});
81+
82+
it('does not record a reference when a type is referenced from a value', () => {
83+
const { ast, scopeManager } = parseAndAnalyze(`
84+
type Type = value;
85+
const value = 1;
86+
`);
87+
const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeAliasDeclaration);
88+
const variable = scopeManager.getDeclaredVariables(node)[0];
89+
90+
// there should be one reference from the declaration itself
91+
expect(variable.references).toHaveLength(1);
92+
expect(variable.references[0].identifier.parent).toBe(node);
93+
});
94+
95+
it.todo(
96+
'does not record a reference when a type is referenced from outside its declaring type',
97+
// () => {
98+
// const { ast, scopeManager } = parseAndAnalyze(`
99+
// type TypeDecl<TypeParam> = T;
100+
// type Other = TypeParam;
101+
// `);
102+
// const node = getSpecificNode(ast, AST_NODE_TYPES.TSTypeParameter);
103+
// const variable = scopeManager.getDeclaredVariables(node)[0];
104+
105+
// // there should be one reference from the declaration itself
106+
// expect(variable.references).toHaveLength(1);
107+
// expect(variable.references[0].identifier.parent).toBe(node);
108+
// },
109+
);
110+
});

packages/scope-manager/tests/types/variable-definition.test.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ describe('variable definition', () => {
2626
references: Array [
2727
Reference$1 {
2828
identifier: Identifier<"TypeDecl">,
29+
isTypeReference: true,
2930
resolved: Variable$1,
3031
},
3132
],
@@ -68,8 +69,9 @@ describe('variable definition', () => {
6869
],
6970
name: "InterfaceDecl",
7071
references: Array [
71-
Reference$2 {
72+
Reference$1 {
7273
identifier: Identifier<"InterfaceDecl">,
74+
isTypeReference: true,
7375
resolved: Variable$1,
7476
},
7577
],
@@ -101,6 +103,7 @@ describe('variable definition', () => {
101103
references: Array [
102104
Reference$2 {
103105
identifier: Identifier<"TypeParam">,
106+
isTypeReference: true,
104107
resolved: Variable$2,
105108
},
106109
],
@@ -120,9 +123,9 @@ describe('variable definition', () => {
120123
);
121124
expect(scopeManager.getDeclaredVariables(node)).toMatchInlineSnapshot(`
122125
Array [
123-
Variable$2 {
126+
Variable$3 {
124127
defs: Array [
125-
TypeDefinition$2 {
128+
TypeDefinition$3 {
126129
name: Identifier<"Inferred">,
127130
node: TSTypeParameter$1 {
128131
name: Identifier<"Inferred">,
@@ -134,13 +137,15 @@ describe('variable definition', () => {
134137
],
135138
name: "Inferred",
136139
references: Array [
137-
Reference$4 {
140+
Reference$5 {
138141
identifier: Identifier<"Inferred">,
139-
resolved: Variable$2,
142+
isTypeReference: true,
143+
resolved: Variable$3,
140144
},
141-
Reference$5 {
145+
Reference$6 {
142146
identifier: Identifier<"Inferred">,
143-
resolved: Variable$2,
147+
isTypeReference: true,
148+
resolved: Variable$3,
144149
},
145150
],
146151
},

packages/scope-manager/tests/util/getSpecificNode.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,20 @@ function getSpecificNode<
2828
cb?: (node: TNode) => TReturnType | null | undefined,
2929
): TReturnType {
3030
let node: TReturnType | null | undefined = null;
31-
simpleTraverse(ast, {
32-
[selector](n: TNode) {
33-
node = cb ? cb(n) : ((n as never) as TReturnType);
31+
simpleTraverse(
32+
ast,
33+
{
34+
[selector](n: TNode) {
35+
const res = cb ? cb(n) : ((n as never) as TReturnType);
36+
if (res) {
37+
// the callback shouldn't match multiple nodes or else tests may behave weirdly
38+
expect(node).toBeFalsy();
39+
node = res;
40+
}
41+
},
3442
},
35-
});
43+
true,
44+
);
3645

3746
expect(node).not.toBeFalsy();
3847
return node!;

packages/typescript-estree/src/simple-traverse.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,22 @@ type SimpleTraverseOptions =
2828
class SimpleTraverser {
2929
private readonly allVisitorKeys = visitorKeys;
3030
private readonly selectors: SimpleTraverseOptions;
31+
private readonly setParentPointers: boolean;
3132

32-
constructor(selectors: SimpleTraverseOptions) {
33+
constructor(selectors: SimpleTraverseOptions, setParentPointers = false) {
3334
this.selectors = selectors;
35+
this.setParentPointers = setParentPointers;
3436
}
3537

3638
traverse(node: unknown, parent: TSESTree.Node | undefined): void {
3739
if (!isValidNode(node)) {
3840
return;
3941
}
4042

43+
if (this.setParentPointers) {
44+
node.parent = parent;
45+
}
46+
4147
if ('enter' in this.selectors) {
4248
this.selectors.enter(node, parent);
4349
} else if (node.type in this.selectors) {
@@ -66,6 +72,10 @@ class SimpleTraverser {
6672
export function simpleTraverse(
6773
startingNode: TSESTree.Node,
6874
options: SimpleTraverseOptions,
75+
setParentPointers = false,
6976
): void {
70-
new SimpleTraverser(options).traverse(startingNode, undefined);
77+
new SimpleTraverser(options, setParentPointers).traverse(
78+
startingNode,
79+
undefined,
80+
);
7181
}

0 commit comments

Comments
 (0)