⬅️ Back to Table of Contents
📄 no-unnecessary-qualifier.ts
📊 Analysis Summary
Metric |
Count |
🔧 Functions |
11 |
📦 Imports |
4 |
📊 Variables & Constants |
5 |
📚 Table of Contents
🛠️ File Location:
📂 packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts
📦 Imports
Name |
Source |
TSESTree |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util |
getParserServices |
../util |
Variables & Constants
Name |
Type |
Kind |
Value |
Exported |
namespacesInScope |
ts.Node[] |
const |
[] |
✗ |
currentFailedNamespaceExpression |
TSESTree.Node | null |
let/var |
null |
✗ |
esTreeNodeToTSNodeMap |
any |
const |
services.esTreeNodeToTSNodeMap |
✗ |
symbolDeclarations |
any |
const |
symbol.getDeclarations() ?? [] |
✗ |
property |
TSESTree.Identifier |
const |
node.property as TSESTree.Identifier |
✗ |
Functions
tryGetAliasedSymbol(symbol: ts.Symbol, checker: ts.TypeChecker): ts.Symbol | null
Code
function tryGetAliasedSymbol(
symbol: ts.Symbol,
checker: ts.TypeChecker,
): ts.Symbol | null {
return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias)
? checker.getAliasedSymbol(symbol)
: null;
}
- Parameters:
symbol: ts.Symbol
checker: ts.TypeChecker
- Return Type:
ts.Symbol | null
- Calls:
tsutils.isSymbolFlagSet
checker.getAliasedSymbol
symbolIsNamespaceInScope(symbol: ts.Symbol): boolean
Code
function symbolIsNamespaceInScope(symbol: ts.Symbol): boolean {
const symbolDeclarations = symbol.getDeclarations() ?? [];
if (
symbolDeclarations.some(decl =>
namespacesInScope.some(ns => ns === decl),
)
) {
return true;
}
const alias = tryGetAliasedSymbol(symbol, checker);
return alias != null && symbolIsNamespaceInScope(alias);
}
- Parameters:
symbol: ts.Symbol
- Return Type:
boolean
- Calls:
symbol.getDeclarations
symbolDeclarations.some
namespacesInScope.some
tryGetAliasedSymbol
symbolIsNamespaceInScope
getSymbolInScope(node: ts.Node, flags: ts.SymbolFlags, name: string): ts.Symbol | undefined
Code
function getSymbolInScope(
node: ts.Node,
flags: ts.SymbolFlags,
name: string,
): ts.Symbol | undefined {
const scope = checker.getSymbolsInScope(node, flags);
return scope.find(scopeSymbol => scopeSymbol.name === name);
}
- Parameters:
node: ts.Node
flags: ts.SymbolFlags
name: string
- Return Type:
ts.Symbol | undefined
- Calls:
checker.getSymbolsInScope
scope.find
symbolsAreEqual(accessed: ts.Symbol, inScope: ts.Symbol): boolean
Code
function symbolsAreEqual(accessed: ts.Symbol, inScope: ts.Symbol): boolean {
return accessed === checker.getExportSymbolOfSymbol(inScope);
}
- Parameters:
accessed: ts.Symbol
inScope: ts.Symbol
- Return Type:
boolean
- Calls:
checker.getExportSymbolOfSymbol
qualifierIsUnnecessary(qualifier: TSESTree.EntityName | TSESTree.MemberExpression, name: TSESTree.Identifier): boolean
Code
function qualifierIsUnnecessary(
qualifier: TSESTree.EntityName | TSESTree.MemberExpression,
name: TSESTree.Identifier,
): boolean {
const namespaceSymbol = services.getSymbolAtLocation(qualifier);
if (
namespaceSymbol == null ||
!symbolIsNamespaceInScope(namespaceSymbol)
) {
return false;
}
const accessedSymbol = services.getSymbolAtLocation(name);
if (accessedSymbol == null) {
return false;
}
// If the symbol in scope is different, the qualifier is necessary.
const tsQualifier = esTreeNodeToTSNodeMap.get(qualifier);
const fromScope = getSymbolInScope(
tsQualifier,
accessedSymbol.flags,
context.sourceCode.getText(name),
);
return !!fromScope && symbolsAreEqual(accessedSymbol, fromScope);
}
- Parameters:
qualifier: TSESTree.EntityName | TSESTree.MemberExpression
name: TSESTree.Identifier
- Return Type:
boolean
- Calls:
services.getSymbolAtLocation
symbolIsNamespaceInScope
esTreeNodeToTSNodeMap.get
getSymbolInScope
context.sourceCode.getText
symbolsAreEqual
- Internal Comments:
// If the symbol in scope is different, the qualifier is necessary. (x2)
visitNamespaceAccess(node: TSESTree.Node, qualifier: TSESTree.EntityName | TSESTree.MemberExpression, name: TSESTree.Identifier): void
Code
function visitNamespaceAccess(
node: TSESTree.Node,
qualifier: TSESTree.EntityName | TSESTree.MemberExpression,
name: TSESTree.Identifier,
): void {
// Only look for nested qualifier errors if we didn't already fail on the outer qualifier.
if (
!currentFailedNamespaceExpression &&
qualifierIsUnnecessary(qualifier, name)
) {
currentFailedNamespaceExpression = node;
context.report({
node: qualifier,
messageId: 'unnecessaryQualifier',
data: {
name: context.sourceCode.getText(name),
},
fix(fixer) {
return fixer.removeRange([qualifier.range[0], name.range[0]]);
},
});
}
}
- Parameters:
node: TSESTree.Node
qualifier: TSESTree.EntityName | TSESTree.MemberExpression
name: TSESTree.Identifier
- Return Type:
void
- Calls:
qualifierIsUnnecessary
context.report
context.sourceCode.getText
fixer.removeRange
- Internal Comments:
// Only look for nested qualifier errors if we didn't already fail on the outer qualifier.
`enterDeclaration(node: | TSESTree.ExportNamedDeclaration
| TSESTree.TSEnumDeclaration
| TSESTree.TSModuleDeclaration): void`
Code
function enterDeclaration(
node:
| TSESTree.ExportNamedDeclaration
| TSESTree.TSEnumDeclaration
| TSESTree.TSModuleDeclaration,
): void {
namespacesInScope.push(esTreeNodeToTSNodeMap.get(node));
}
- Parameters:
node: | TSESTree.ExportNamedDeclaration
| TSESTree.TSEnumDeclaration
| TSESTree.TSModuleDeclaration
- Return Type:
void
- Calls:
namespacesInScope.push
esTreeNodeToTSNodeMap.get
exitDeclaration(): void
Code
function exitDeclaration(): void {
namespacesInScope.pop();
}
- Return Type:
void
- Calls:
namespacesInScope.pop
resetCurrentNamespaceExpression(node: TSESTree.Node): void
Code
function resetCurrentNamespaceExpression(node: TSESTree.Node): void {
if (node === currentFailedNamespaceExpression) {
currentFailedNamespaceExpression = null;
}
}
- Parameters:
node: TSESTree.Node
- Return Type:
void
isPropertyAccessExpression(node: TSESTree.Node): node is TSESTree.MemberExpression
Code
function isPropertyAccessExpression(
node: TSESTree.Node,
): node is TSESTree.MemberExpression {
return node.type === AST_NODE_TYPES.MemberExpression && !node.computed;
}
- Parameters:
node: TSESTree.Node
- Return Type:
node is TSESTree.MemberExpression
isEntityNameExpression(node: TSESTree.Node): node is TSESTree.Identifier | TSESTree.MemberExpression
Code
function isEntityNameExpression(
node: TSESTree.Node,
): node is TSESTree.Identifier | TSESTree.MemberExpression {
return (
node.type === AST_NODE_TYPES.Identifier ||
(isPropertyAccessExpression(node) &&
isEntityNameExpression(node.object))
);
}
- Parameters:
node: TSESTree.Node
- Return Type:
node is TSESTree.Identifier | TSESTree.MemberExpression
- Calls:
isPropertyAccessExpression
isEntityNameExpression