📄 TypeVisitor.ts
¶
📊 Analysis Summary¶
Metric | Count |
---|---|
🔧 Functions | 24 |
🧱 Classes | 1 |
📦 Imports | 8 |
📊 Variables & Constants | 6 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/scope-manager/src/referencer/TypeVisitor.ts
📦 Imports¶
Name | Source |
---|---|
TSESTree |
@typescript-eslint/types |
AST_NODE_TYPES |
@typescript-eslint/types |
Scope |
../scope |
Referencer |
./Referencer |
ParameterDefinition |
../definition |
TypeDefinition |
../definition |
ScopeType |
../scope |
Visitor |
./Visitor |
Variables & Constants¶
Name | Type | Kind | Value | Exported |
---|---|---|---|---|
typeReferencer |
TypeVisitor |
const | new TypeVisitor(referencer) |
✗ |
didVisitAnnotation |
boolean |
let/var | false |
✗ |
typeParameter |
any |
const | node.typeParameter |
✗ |
currentScope |
Scope |
let/var | scope.upper as Scope | undefined |
✗ |
entityName |
` | TSESTree.Identifier | ||
TSESTree.ThisExpression | ||||
TSESTree.TSImportType| let/var | not shown` |
✗ | |||
iter |
any |
let/var | node.exprName |
✗ |
Functions¶
TypeVisitor.visit(referencer: Referencer, node: TSESTree.Node): void
¶
Code
- Parameters:
referencer: Referencer
node: TSESTree.Node
- Return Type:
void
- Calls:
typeReferencer.visit
`TypeVisitor.visitFunctionType(node: | TSESTree.TSCallSignatureDeclaration¶
| TSESTree.TSConstructorType
| TSESTree.TSConstructSignatureDeclaration
| TSESTree.TSFunctionType
| TSESTree.TSMethodSignature): void`
Code
protected visitFunctionType(
node:
| TSESTree.TSCallSignatureDeclaration
| TSESTree.TSConstructorType
| TSESTree.TSConstructSignatureDeclaration
| TSESTree.TSFunctionType
| TSESTree.TSMethodSignature,
): void {
// arguments and type parameters can only be referenced from within the function
this.#referencer.scopeManager.nestFunctionTypeScope(node);
this.visit(node.typeParameters);
for (const param of node.params) {
let didVisitAnnotation = false;
this.visitPattern(param, (pattern, info) => {
// a parameter name creates a value type variable which can be referenced later via typeof arg
this.#referencer
.currentScope()
.defineIdentifier(
pattern,
new ParameterDefinition(pattern, node, info.rest),
);
if (pattern.typeAnnotation) {
this.visit(pattern.typeAnnotation);
didVisitAnnotation = true;
}
});
// there are a few special cases where the type annotation is owned by the parameter, not the pattern
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!didVisitAnnotation && 'typeAnnotation' in param) {
this.visit(param.typeAnnotation);
}
}
this.visit(node.returnType);
this.#referencer.close(node);
}
- Parameters:
node: | TSESTree.TSCallSignatureDeclaration | TSESTree.TSConstructorType | TSESTree.TSConstructSignatureDeclaration | TSESTree.TSFunctionType | TSESTree.TSMethodSignature
- Return Type:
void
- Calls:
this.#referencer.scopeManager.nestFunctionTypeScope
this.visit
this.visitPattern
this.#referencer .currentScope() .defineIdentifier
this.#referencer.close
- Internal Comments:
// arguments and type parameters can only be referenced from within the function (x6) // a parameter name creates a value type variable which can be referenced later via typeof arg (x7) // there are a few special cases where the type annotation is owned by the parameter, not the pattern // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
TypeVisitor.visitPropertyKey(node: TSESTree.TSMethodSignature | TSESTree.TSPropertySignature): void
¶
Code
- Parameters:
node: TSESTree.TSMethodSignature | TSESTree.TSPropertySignature
- Return Type:
void
- Calls:
this.#referencer.visit
- Internal Comments:
TypeVisitor.Identifier(node: TSESTree.Identifier): void
¶
Code
- Parameters:
node: TSESTree.Identifier
- Return Type:
void
- Calls:
this.#referencer.currentScope().referenceType
TypeVisitor.MemberExpression(node: TSESTree.MemberExpression): void
¶
Code
- Parameters:
node: TSESTree.MemberExpression
- Return Type:
void
- Calls:
this.visit
TypeVisitor.TSCallSignatureDeclaration(node: TSESTree.TSCallSignatureDeclaration): void
¶
Code
- Parameters:
node: TSESTree.TSCallSignatureDeclaration
- Return Type:
void
- Calls:
this.visitFunctionType
TypeVisitor.TSConditionalType(node: TSESTree.TSConditionalType): void
¶
Code
protected TSConditionalType(node: TSESTree.TSConditionalType): void {
// conditional types can define inferred type parameters
// which are only accessible from inside the conditional parameter
this.#referencer.scopeManager.nestConditionalTypeScope(node);
// type parameters inferred in the condition clause are not accessible within the false branch
this.visitChildren(node, ['falseType']);
this.#referencer.close(node);
this.visit(node.falseType);
}
- Parameters:
node: TSESTree.TSConditionalType
- Return Type:
void
- Calls:
this.#referencer.scopeManager.nestConditionalTypeScope
this.visitChildren
this.#referencer.close
this.visit
- Internal Comments:
TypeVisitor.TSConstructorType(node: TSESTree.TSConstructorType): void
¶
Code
- Parameters:
node: TSESTree.TSConstructorType
- Return Type:
void
- Calls:
this.visitFunctionType
TypeVisitor.TSConstructSignatureDeclaration(node: TSESTree.TSConstructSignatureDeclaration): void
¶
Code
- Parameters:
node: TSESTree.TSConstructSignatureDeclaration
- Return Type:
void
- Calls:
this.visitFunctionType
TypeVisitor.TSFunctionType(node: TSESTree.TSFunctionType): void
¶
Code
- Parameters:
node: TSESTree.TSFunctionType
- Return Type:
void
- Calls:
this.visitFunctionType
TypeVisitor.TSImportType(node: TSESTree.TSImportType): void
¶
Code
- Parameters:
node: TSESTree.TSImportType
- Return Type:
void
- Calls:
this.visit
- Internal Comments:
TypeVisitor.TSIndexSignature(node: TSESTree.TSIndexSignature): void
¶
Code
- Parameters:
node: TSESTree.TSIndexSignature
- Return Type:
void
- Calls:
this.visit
TypeVisitor.TSInferType(node: TSESTree.TSInferType): void
¶
Code
protected TSInferType(node: TSESTree.TSInferType): void {
const typeParameter = node.typeParameter;
let scope = this.#referencer.currentScope();
/*
In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the
conditional type's scope, not the child type scope.
If we define it within the child type's scope then it won't be able to be referenced outside the child type
*/
if (
scope.type === ScopeType.functionType ||
scope.type === ScopeType.mappedType
) {
// search up the scope tree to figure out if we're in a nested type scope
let currentScope = scope.upper as Scope | undefined;
while (currentScope) {
if (
currentScope.type === ScopeType.functionType ||
currentScope.type === ScopeType.mappedType
) {
// ensure valid type parents only
currentScope = currentScope.upper;
continue;
}
if (currentScope.type === ScopeType.conditionalType) {
scope = currentScope;
break;
}
break;
}
}
scope.defineIdentifier(
typeParameter.name,
new TypeDefinition(typeParameter.name, typeParameter),
);
this.visit(typeParameter.constraint);
}
- Parameters:
node: TSESTree.TSInferType
- Return Type:
void
- Calls:
this.#referencer.currentScope
scope.defineIdentifier
this.visit
- Internal Comments:
/* In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the conditional type's scope, not the child type scope. If we define it within the child type's scope then it won't be able to be referenced outside the child type */ // search up the scope tree to figure out if we're in a nested type scope (x2) // ensure valid type parents only (x3)
TypeVisitor.TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration): void
¶
Code
protected TSInterfaceDeclaration(
node: TSESTree.TSInterfaceDeclaration,
): void {
this.#referencer
.currentScope()
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
if (node.typeParameters) {
// type parameters cannot be referenced from outside their current scope
this.#referencer.scopeManager.nestTypeScope(node);
this.visit(node.typeParameters);
}
node.extends.forEach(this.visit, this);
this.visit(node.body);
if (node.typeParameters) {
this.#referencer.close(node);
}
}
- Parameters:
node: TSESTree.TSInterfaceDeclaration
- Return Type:
void
- Calls:
this.#referencer .currentScope() .defineIdentifier
this.#referencer.scopeManager.nestTypeScope
this.visit
node.extends.forEach
this.#referencer.close
- Internal Comments:
TypeVisitor.TSMappedType(node: TSESTree.TSMappedType): void
¶
Code
protected TSMappedType(node: TSESTree.TSMappedType): void {
// mapped types key can only be referenced within their return value
this.#referencer.scopeManager.nestMappedTypeScope(node);
this.#referencer
.currentScope()
.defineIdentifier(node.key, new TypeDefinition(node.key, node));
this.visit(node.constraint);
this.visit(node.nameType);
this.visit(node.typeAnnotation);
this.#referencer.close(node);
}
- Parameters:
node: TSESTree.TSMappedType
- Return Type:
void
- Calls:
this.#referencer.scopeManager.nestMappedTypeScope
this.#referencer .currentScope() .defineIdentifier
this.visit
this.#referencer.close
- Internal Comments:
TypeVisitor.TSMethodSignature(node: TSESTree.TSMethodSignature): void
¶
Code
- Parameters:
node: TSESTree.TSMethodSignature
- Return Type:
void
- Calls:
this.visitPropertyKey
this.visitFunctionType
TypeVisitor.TSNamedTupleMember(node: TSESTree.TSNamedTupleMember): void
¶
Code
- Parameters:
node: TSESTree.TSNamedTupleMember
- Return Type:
void
- Calls:
this.visit
TypeVisitor.TSPropertySignature(node: TSESTree.TSPropertySignature): void
¶
Code
- Parameters:
node: TSESTree.TSPropertySignature
- Return Type:
void
- Calls:
this.visitPropertyKey
this.visit
TypeVisitor.TSQualifiedName(node: TSESTree.TSQualifiedName): void
¶
Code
- Parameters:
node: TSESTree.TSQualifiedName
- Return Type:
void
- Calls:
this.visit
TypeVisitor.TSTypeAliasDeclaration(node: TSESTree.TSTypeAliasDeclaration): void
¶
Code
protected TSTypeAliasDeclaration(
node: TSESTree.TSTypeAliasDeclaration,
): void {
this.#referencer
.currentScope()
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
if (node.typeParameters) {
// type parameters cannot be referenced from outside their current scope
this.#referencer.scopeManager.nestTypeScope(node);
this.visit(node.typeParameters);
}
this.visit(node.typeAnnotation);
if (node.typeParameters) {
this.#referencer.close(node);
}
}
- Parameters:
node: TSESTree.TSTypeAliasDeclaration
- Return Type:
void
- Calls:
this.#referencer .currentScope() .defineIdentifier
this.#referencer.scopeManager.nestTypeScope
this.visit
this.#referencer.close
- Internal Comments:
TypeVisitor.TSTypeParameter(node: TSESTree.TSTypeParameter): void
¶
Code
- Parameters:
node: TSESTree.TSTypeParameter
- Return Type:
void
- Calls:
this.#referencer .currentScope() .defineIdentifier
this.visit
TypeVisitor.TSTypePredicate(node: TSESTree.TSTypePredicate): void
¶
Code
- Parameters:
node: TSESTree.TSTypePredicate
- Return Type:
void
- Calls:
this.#referencer.currentScope().referenceValue
this.visit
TypeVisitor.TSTypeAnnotation(node: TSESTree.TSTypeAnnotation): void
¶
Code
- Parameters:
node: TSESTree.TSTypeAnnotation
- Return Type:
void
- Calls:
this.visitChildren
- Internal Comments:
TypeVisitor.TSTypeQuery(node: TSESTree.TSTypeQuery): void
¶
Code
protected TSTypeQuery(node: TSESTree.TSTypeQuery): void {
let entityName:
| TSESTree.Identifier
| TSESTree.ThisExpression
| TSESTree.TSImportType;
if (node.exprName.type === AST_NODE_TYPES.TSQualifiedName) {
let iter = node.exprName;
while (iter.left.type === AST_NODE_TYPES.TSQualifiedName) {
iter = iter.left;
}
entityName = iter.left;
} else {
entityName = node.exprName;
if (node.exprName.type === AST_NODE_TYPES.TSImportType) {
this.visit(node.exprName);
}
}
if (entityName.type === AST_NODE_TYPES.Identifier) {
this.#referencer.currentScope().referenceValue(entityName);
}
this.visit(node.typeArguments);
}
- Parameters:
node: TSESTree.TSTypeQuery
- Return Type:
void
- Calls:
this.visit
this.#referencer.currentScope().referenceValue
Classes¶
TypeVisitor
¶
Class Code
export class TypeVisitor extends Visitor {
readonly #referencer: Referencer;
constructor(referencer: Referencer) {
super(referencer);
this.#referencer = referencer;
}
static visit(referencer: Referencer, node: TSESTree.Node): void {
const typeReferencer = new TypeVisitor(referencer);
typeReferencer.visit(node);
}
///////////////////
// Visit helpers //
///////////////////
protected visitFunctionType(
node:
| TSESTree.TSCallSignatureDeclaration
| TSESTree.TSConstructorType
| TSESTree.TSConstructSignatureDeclaration
| TSESTree.TSFunctionType
| TSESTree.TSMethodSignature,
): void {
// arguments and type parameters can only be referenced from within the function
this.#referencer.scopeManager.nestFunctionTypeScope(node);
this.visit(node.typeParameters);
for (const param of node.params) {
let didVisitAnnotation = false;
this.visitPattern(param, (pattern, info) => {
// a parameter name creates a value type variable which can be referenced later via typeof arg
this.#referencer
.currentScope()
.defineIdentifier(
pattern,
new ParameterDefinition(pattern, node, info.rest),
);
if (pattern.typeAnnotation) {
this.visit(pattern.typeAnnotation);
didVisitAnnotation = true;
}
});
// there are a few special cases where the type annotation is owned by the parameter, not the pattern
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!didVisitAnnotation && 'typeAnnotation' in param) {
this.visit(param.typeAnnotation);
}
}
this.visit(node.returnType);
this.#referencer.close(node);
}
protected visitPropertyKey(
node: TSESTree.TSMethodSignature | TSESTree.TSPropertySignature,
): void {
if (!node.computed) {
return;
}
// computed members are treated as value references, and TS expects they have a literal type
this.#referencer.visit(node.key);
}
/////////////////////
// Visit selectors //
/////////////////////
protected Identifier(node: TSESTree.Identifier): void {
this.#referencer.currentScope().referenceType(node);
}
protected MemberExpression(node: TSESTree.MemberExpression): void {
this.visit(node.object);
// don't visit the property
}
protected TSCallSignatureDeclaration(
node: TSESTree.TSCallSignatureDeclaration,
): void {
this.visitFunctionType(node);
}
protected TSConditionalType(node: TSESTree.TSConditionalType): void {
// conditional types can define inferred type parameters
// which are only accessible from inside the conditional parameter
this.#referencer.scopeManager.nestConditionalTypeScope(node);
// type parameters inferred in the condition clause are not accessible within the false branch
this.visitChildren(node, ['falseType']);
this.#referencer.close(node);
this.visit(node.falseType);
}
protected TSConstructorType(node: TSESTree.TSConstructorType): void {
this.visitFunctionType(node);
}
protected TSConstructSignatureDeclaration(
node: TSESTree.TSConstructSignatureDeclaration,
): void {
this.visitFunctionType(node);
}
protected TSFunctionType(node: TSESTree.TSFunctionType): void {
this.visitFunctionType(node);
}
protected TSImportType(node: TSESTree.TSImportType): void {
// the TS parser allows any type to be the parameter, but it's a syntax error - so we can ignore it
this.visit(node.typeArguments);
// the qualifier is just part of a standard EntityName, so it should not be visited
}
protected TSIndexSignature(node: TSESTree.TSIndexSignature): void {
for (const param of node.parameters) {
if (param.type === AST_NODE_TYPES.Identifier) {
this.visit(param.typeAnnotation);
}
}
this.visit(node.typeAnnotation);
}
protected TSInferType(node: TSESTree.TSInferType): void {
const typeParameter = node.typeParameter;
let scope = this.#referencer.currentScope();
/*
In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the
conditional type's scope, not the child type scope.
If we define it within the child type's scope then it won't be able to be referenced outside the child type
*/
if (
scope.type === ScopeType.functionType ||
scope.type === ScopeType.mappedType
) {
// search up the scope tree to figure out if we're in a nested type scope
let currentScope = scope.upper as Scope | undefined;
while (currentScope) {
if (
currentScope.type === ScopeType.functionType ||
currentScope.type === ScopeType.mappedType
) {
// ensure valid type parents only
currentScope = currentScope.upper;
continue;
}
if (currentScope.type === ScopeType.conditionalType) {
scope = currentScope;
break;
}
break;
}
}
scope.defineIdentifier(
typeParameter.name,
new TypeDefinition(typeParameter.name, typeParameter),
);
this.visit(typeParameter.constraint);
}
protected TSInterfaceDeclaration(
node: TSESTree.TSInterfaceDeclaration,
): void {
this.#referencer
.currentScope()
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
if (node.typeParameters) {
// type parameters cannot be referenced from outside their current scope
this.#referencer.scopeManager.nestTypeScope(node);
this.visit(node.typeParameters);
}
node.extends.forEach(this.visit, this);
this.visit(node.body);
if (node.typeParameters) {
this.#referencer.close(node);
}
}
protected TSMappedType(node: TSESTree.TSMappedType): void {
// mapped types key can only be referenced within their return value
this.#referencer.scopeManager.nestMappedTypeScope(node);
this.#referencer
.currentScope()
.defineIdentifier(node.key, new TypeDefinition(node.key, node));
this.visit(node.constraint);
this.visit(node.nameType);
this.visit(node.typeAnnotation);
this.#referencer.close(node);
}
protected TSMethodSignature(node: TSESTree.TSMethodSignature): void {
this.visitPropertyKey(node);
this.visitFunctionType(node);
}
protected TSNamedTupleMember(node: TSESTree.TSNamedTupleMember): void {
this.visit(node.elementType);
// we don't visit the label as the label only exists for the purposes of documentation
}
protected TSPropertySignature(node: TSESTree.TSPropertySignature): void {
this.visitPropertyKey(node);
this.visit(node.typeAnnotation);
}
protected TSQualifiedName(node: TSESTree.TSQualifiedName): void {
this.visit(node.left);
// we don't visit the right as it a name on the thing, not a name to reference
}
protected TSTypeAliasDeclaration(
node: TSESTree.TSTypeAliasDeclaration,
): void {
this.#referencer
.currentScope()
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
if (node.typeParameters) {
// type parameters cannot be referenced from outside their current scope
this.#referencer.scopeManager.nestTypeScope(node);
this.visit(node.typeParameters);
}
this.visit(node.typeAnnotation);
if (node.typeParameters) {
this.#referencer.close(node);
}
}
protected TSTypeParameter(node: TSESTree.TSTypeParameter): void {
this.#referencer
.currentScope()
.defineIdentifier(node.name, new TypeDefinition(node.name, node));
this.visit(node.constraint);
this.visit(node.default);
}
protected TSTypePredicate(node: TSESTree.TSTypePredicate): void {
if (node.parameterName.type !== AST_NODE_TYPES.TSThisType) {
this.#referencer.currentScope().referenceValue(node.parameterName);
}
this.visit(node.typeAnnotation);
}
// a type query `typeof foo` is a special case that references a _non-type_ variable,
protected TSTypeAnnotation(node: TSESTree.TSTypeAnnotation): void {
// check
this.visitChildren(node);
}
protected TSTypeQuery(node: TSESTree.TSTypeQuery): void {
let entityName:
| TSESTree.Identifier
| TSESTree.ThisExpression
| TSESTree.TSImportType;
if (node.exprName.type === AST_NODE_TYPES.TSQualifiedName) {
let iter = node.exprName;
while (iter.left.type === AST_NODE_TYPES.TSQualifiedName) {
iter = iter.left;
}
entityName = iter.left;
} else {
entityName = node.exprName;
if (node.exprName.type === AST_NODE_TYPES.TSImportType) {
this.visit(node.exprName);
}
}
if (entityName.type === AST_NODE_TYPES.Identifier) {
this.#referencer.currentScope().referenceValue(entityName);
}
this.visit(node.typeArguments);
}
}
Methods¶
visit(referencer: Referencer, node: TSESTree.Node): void
¶
Code
`visitFunctionType(node: | TSESTree.TSCallSignatureDeclaration¶
| TSESTree.TSConstructorType
| TSESTree.TSConstructSignatureDeclaration
| TSESTree.TSFunctionType
| TSESTree.TSMethodSignature): void`
Code
protected visitFunctionType(
node:
| TSESTree.TSCallSignatureDeclaration
| TSESTree.TSConstructorType
| TSESTree.TSConstructSignatureDeclaration
| TSESTree.TSFunctionType
| TSESTree.TSMethodSignature,
): void {
// arguments and type parameters can only be referenced from within the function
this.#referencer.scopeManager.nestFunctionTypeScope(node);
this.visit(node.typeParameters);
for (const param of node.params) {
let didVisitAnnotation = false;
this.visitPattern(param, (pattern, info) => {
// a parameter name creates a value type variable which can be referenced later via typeof arg
this.#referencer
.currentScope()
.defineIdentifier(
pattern,
new ParameterDefinition(pattern, node, info.rest),
);
if (pattern.typeAnnotation) {
this.visit(pattern.typeAnnotation);
didVisitAnnotation = true;
}
});
// there are a few special cases where the type annotation is owned by the parameter, not the pattern
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!didVisitAnnotation && 'typeAnnotation' in param) {
this.visit(param.typeAnnotation);
}
}
this.visit(node.returnType);
this.#referencer.close(node);
}
visitPropertyKey(node: TSESTree.TSMethodSignature | TSESTree.TSPropertySignature): void
¶
Code
Identifier(node: TSESTree.Identifier): void
¶
Code
MemberExpression(node: TSESTree.MemberExpression): void
¶
Code
TSCallSignatureDeclaration(node: TSESTree.TSCallSignatureDeclaration): void
¶
Code
TSConditionalType(node: TSESTree.TSConditionalType): void
¶
Code
protected TSConditionalType(node: TSESTree.TSConditionalType): void {
// conditional types can define inferred type parameters
// which are only accessible from inside the conditional parameter
this.#referencer.scopeManager.nestConditionalTypeScope(node);
// type parameters inferred in the condition clause are not accessible within the false branch
this.visitChildren(node, ['falseType']);
this.#referencer.close(node);
this.visit(node.falseType);
}
TSConstructorType(node: TSESTree.TSConstructorType): void
¶
Code
TSConstructSignatureDeclaration(node: TSESTree.TSConstructSignatureDeclaration): void
¶
Code
TSFunctionType(node: TSESTree.TSFunctionType): void
¶
Code
TSImportType(node: TSESTree.TSImportType): void
¶
Code
TSIndexSignature(node: TSESTree.TSIndexSignature): void
¶
Code
TSInferType(node: TSESTree.TSInferType): void
¶
Code
protected TSInferType(node: TSESTree.TSInferType): void {
const typeParameter = node.typeParameter;
let scope = this.#referencer.currentScope();
/*
In cases where there is a sub-type scope created within a conditional type, then the generic should be defined in the
conditional type's scope, not the child type scope.
If we define it within the child type's scope then it won't be able to be referenced outside the child type
*/
if (
scope.type === ScopeType.functionType ||
scope.type === ScopeType.mappedType
) {
// search up the scope tree to figure out if we're in a nested type scope
let currentScope = scope.upper as Scope | undefined;
while (currentScope) {
if (
currentScope.type === ScopeType.functionType ||
currentScope.type === ScopeType.mappedType
) {
// ensure valid type parents only
currentScope = currentScope.upper;
continue;
}
if (currentScope.type === ScopeType.conditionalType) {
scope = currentScope;
break;
}
break;
}
}
scope.defineIdentifier(
typeParameter.name,
new TypeDefinition(typeParameter.name, typeParameter),
);
this.visit(typeParameter.constraint);
}
TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration): void
¶
Code
protected TSInterfaceDeclaration(
node: TSESTree.TSInterfaceDeclaration,
): void {
this.#referencer
.currentScope()
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
if (node.typeParameters) {
// type parameters cannot be referenced from outside their current scope
this.#referencer.scopeManager.nestTypeScope(node);
this.visit(node.typeParameters);
}
node.extends.forEach(this.visit, this);
this.visit(node.body);
if (node.typeParameters) {
this.#referencer.close(node);
}
}
TSMappedType(node: TSESTree.TSMappedType): void
¶
Code
protected TSMappedType(node: TSESTree.TSMappedType): void {
// mapped types key can only be referenced within their return value
this.#referencer.scopeManager.nestMappedTypeScope(node);
this.#referencer
.currentScope()
.defineIdentifier(node.key, new TypeDefinition(node.key, node));
this.visit(node.constraint);
this.visit(node.nameType);
this.visit(node.typeAnnotation);
this.#referencer.close(node);
}
TSMethodSignature(node: TSESTree.TSMethodSignature): void
¶
Code
TSNamedTupleMember(node: TSESTree.TSNamedTupleMember): void
¶
Code
TSPropertySignature(node: TSESTree.TSPropertySignature): void
¶
Code
TSQualifiedName(node: TSESTree.TSQualifiedName): void
¶
Code
TSTypeAliasDeclaration(node: TSESTree.TSTypeAliasDeclaration): void
¶
Code
protected TSTypeAliasDeclaration(
node: TSESTree.TSTypeAliasDeclaration,
): void {
this.#referencer
.currentScope()
.defineIdentifier(node.id, new TypeDefinition(node.id, node));
if (node.typeParameters) {
// type parameters cannot be referenced from outside their current scope
this.#referencer.scopeManager.nestTypeScope(node);
this.visit(node.typeParameters);
}
this.visit(node.typeAnnotation);
if (node.typeParameters) {
this.#referencer.close(node);
}
}
TSTypeParameter(node: TSESTree.TSTypeParameter): void
¶
Code
TSTypePredicate(node: TSESTree.TSTypePredicate): void
¶
Code
TSTypeAnnotation(node: TSESTree.TSTypeAnnotation): void
¶
Code
TSTypeQuery(node: TSESTree.TSTypeQuery): void
¶
Code
protected TSTypeQuery(node: TSESTree.TSTypeQuery): void {
let entityName:
| TSESTree.Identifier
| TSESTree.ThisExpression
| TSESTree.TSImportType;
if (node.exprName.type === AST_NODE_TYPES.TSQualifiedName) {
let iter = node.exprName;
while (iter.left.type === AST_NODE_TYPES.TSQualifiedName) {
iter = iter.left;
}
entityName = iter.left;
} else {
entityName = node.exprName;
if (node.exprName.type === AST_NODE_TYPES.TSImportType) {
this.visit(node.exprName);
}
}
if (entityName.type === AST_NODE_TYPES.Identifier) {
this.#referencer.currentScope().referenceValue(entityName);
}
this.visit(node.typeArguments);
}