Skip to content

Commit 69d991a

Browse files
Deduplicated code for symbol visibility checks.
Signed-off-by: Titian Cernicova-Dragomir <[email protected]>
1 parent af1e6fa commit 69d991a

File tree

4 files changed

+167
-266
lines changed

4 files changed

+167
-266
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ import {
108108
createDiagnosticForNodeFromMessageChain,
109109
createDiagnosticMessageChainFromDiagnostic,
110110
createEmptyExports,
111+
createEntityVisibilityChecker,
111112
createEvaluator,
112113
createFileDiagnostic,
113114
createGetCanonicalFileName,
@@ -623,7 +624,6 @@ import {
623624
isJsxSpreadAttribute,
624625
isJSXTagName,
625626
isKnownSymbol,
626-
isLateVisibilityPaintedStatement,
627627
isLeftHandSideExpression,
628628
isLineBreak,
629629
isLiteralComputedPropertyDeclarationName,
@@ -821,7 +821,6 @@ import {
821821
LateBoundBinaryExpressionDeclaration,
822822
LateBoundDeclaration,
823823
LateBoundName,
824-
LateVisibilityPaintedStatement,
825824
length,
826825
LiteralExpression,
827826
LiteralType,
@@ -997,7 +996,6 @@ import {
997996
symbolName,
998997
SymbolTable,
999998
SymbolTracker,
1000-
SymbolVisibilityResult,
1001999
SyntaxKind,
10021000
SyntheticDefaultModuleType,
10031001
SyntheticExpression,
@@ -1466,6 +1464,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
14661464
var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral;
14671465
var exactOptionalPropertyTypes = compilerOptions.exactOptionalPropertyTypes;
14681466

1467+
var { hasVisibleDeclarations, isEntityNameVisible } = createEntityVisibilityChecker({
1468+
defaultSymbolAccessibility: SymbolAccessibility.NotAccessible,
1469+
isThisAccessible,
1470+
isDeclarationVisible,
1471+
markDeclarationAsVisible(declaration) {
1472+
getNodeLinks(declaration).isVisible = true;
1473+
},
1474+
resolveName,
1475+
});
14691476
var checkBinaryExpression = createCheckBinaryExpression();
14701477
var emitResolver = createResolver();
14711478
var nodeBuilder = createNodeBuilder();
@@ -6162,121 +6169,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61626169
return isModuleWithStringLiteralName(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile));
61636170
}
61646171

6165-
function hasVisibleDeclarations(symbol: Symbol, shouldComputeAliasToMakeVisible: boolean): SymbolVisibilityResult | undefined {
6166-
let aliasesToMakeVisible: LateVisibilityPaintedStatement[] | undefined;
6167-
if (!every(filter(symbol.declarations, d => d.kind !== SyntaxKind.Identifier), getIsDeclarationVisible)) {
6168-
return undefined;
6169-
}
6170-
return { accessibility: SymbolAccessibility.Accessible, aliasesToMakeVisible };
6171-
6172-
function getIsDeclarationVisible(declaration: Declaration) {
6173-
if (!isDeclarationVisible(declaration)) {
6174-
// Mark the unexported alias as visible if its parent is visible
6175-
// because these kind of aliases can be used to name types in declaration file
6176-
6177-
const anyImportSyntax = getAnyImportSyntax(declaration);
6178-
if (
6179-
anyImportSyntax &&
6180-
!hasSyntacticModifier(anyImportSyntax, ModifierFlags.Export) && // import clause without export
6181-
isDeclarationVisible(anyImportSyntax.parent)
6182-
) {
6183-
return addVisibleAlias(declaration, anyImportSyntax);
6184-
}
6185-
else if (
6186-
isVariableDeclaration(declaration) && isVariableStatement(declaration.parent.parent) &&
6187-
!hasSyntacticModifier(declaration.parent.parent, ModifierFlags.Export) && // unexported variable statement
6188-
isDeclarationVisible(declaration.parent.parent.parent)
6189-
) {
6190-
return addVisibleAlias(declaration, declaration.parent.parent);
6191-
}
6192-
else if (
6193-
isLateVisibilityPaintedStatement(declaration) // unexported top-level statement
6194-
&& !hasSyntacticModifier(declaration, ModifierFlags.Export)
6195-
&& isDeclarationVisible(declaration.parent)
6196-
) {
6197-
return addVisibleAlias(declaration, declaration);
6198-
}
6199-
else if (isBindingElement(declaration)) {
6200-
if (
6201-
symbol.flags & SymbolFlags.Alias && isInJSFile(declaration) && declaration.parent?.parent // exported import-like top-level JS require statement
6202-
&& isVariableDeclaration(declaration.parent.parent)
6203-
&& declaration.parent.parent.parent?.parent && isVariableStatement(declaration.parent.parent.parent.parent)
6204-
&& !hasSyntacticModifier(declaration.parent.parent.parent.parent, ModifierFlags.Export)
6205-
&& declaration.parent.parent.parent.parent.parent // check if the thing containing the variable statement is visible (ie, the file)
6206-
&& isDeclarationVisible(declaration.parent.parent.parent.parent.parent)
6207-
) {
6208-
return addVisibleAlias(declaration, declaration.parent.parent.parent.parent);
6209-
}
6210-
else if (symbol.flags & SymbolFlags.BlockScopedVariable) {
6211-
const variableStatement = findAncestor(declaration, isVariableStatement)!;
6212-
if (hasSyntacticModifier(variableStatement, ModifierFlags.Export)) {
6213-
return true;
6214-
}
6215-
if (!isDeclarationVisible(variableStatement.parent)) {
6216-
return false;
6217-
}
6218-
return addVisibleAlias(declaration, variableStatement);
6219-
}
6220-
}
6221-
6222-
// Declaration is not visible
6223-
return false;
6224-
}
6225-
6226-
return true;
6227-
}
6228-
6229-
function addVisibleAlias(declaration: Declaration, aliasingStatement: LateVisibilityPaintedStatement) {
6230-
// In function "buildTypeDisplay" where we decide whether to write type-alias or serialize types,
6231-
// we want to just check if type- alias is accessible or not but we don't care about emitting those alias at that time
6232-
// since we will do the emitting later in trackSymbol.
6233-
if (shouldComputeAliasToMakeVisible) {
6234-
getNodeLinks(declaration).isVisible = true;
6235-
aliasesToMakeVisible = appendIfUnique(aliasesToMakeVisible, aliasingStatement);
6236-
}
6237-
return true;
6238-
}
6239-
}
6240-
6241-
function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult {
6242-
// get symbol of the first identifier of the entityName
6243-
let meaning: SymbolFlags;
6244-
if (
6245-
entityName.parent.kind === SyntaxKind.TypeQuery ||
6246-
entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) ||
6247-
entityName.parent.kind === SyntaxKind.ComputedPropertyName
6248-
) {
6249-
// Typeof value
6250-
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
6251-
}
6252-
else if (
6253-
entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression ||
6254-
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration
6255-
) {
6256-
// Left identifier from type reference or TypeAlias
6257-
// Entity name of the import declaration
6258-
meaning = SymbolFlags.Namespace;
6259-
}
6260-
else {
6261-
// Type Reference or TypeAlias entity = Identifier
6262-
meaning = SymbolFlags.Type;
6263-
}
6264-
6265-
const firstIdentifier = getFirstIdentifier(entityName);
6266-
const symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false);
6267-
if (symbol && symbol.flags & SymbolFlags.TypeParameter && meaning & SymbolFlags.Type) {
6268-
return { accessibility: SymbolAccessibility.Accessible };
6269-
}
6270-
if (!symbol && isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfDeclaration(getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)), firstIdentifier, meaning, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
6271-
return { accessibility: SymbolAccessibility.Accessible };
6272-
}
6273-
6274-
// Verify if the symbol is accessible
6275-
return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || {
6276-
accessibility: SymbolAccessibility.NotAccessible,
6277-
errorSymbolName: getTextOfNode(firstIdentifier),
6278-
errorNode: firstIdentifier,
6279-
};
6172+
function isThisAccessible(thisIdentifier: Identifier, meaning: SymbolFlags) {
6173+
return isSymbolAccessible(getSymbolOfDeclaration(getThisContainer(thisIdentifier, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)), thisIdentifier, meaning, /*shouldComputeAliasesToMakeVisible*/ false);
62806174
}
62816175

62826176
function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags: SymbolFormatFlags = SymbolFormatFlags.AllowAnyNodeKind, writer?: EmitTextWriter): string {

src/compiler/transformers/declarations/emitBinder.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ export interface EmitDeclarationSymbol {
106106
declarations: Declaration[];
107107
signatureDeclarations?: Node[];
108108
flags: SymbolFlags;
109-
isVisible?: boolean;
110109
members?: EmitDeclarationSymbolTable;
111110
exports?: EmitDeclarationSymbolTable;
112111
}
@@ -582,7 +581,6 @@ export function bindSourceFileForDeclarationEmit(file: SourceFile) {
582581
postBindingAction.push(() => {
583582
const resolvedSymbol = resolveName(node.expression, name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias);
584583
if (resolvedSymbol) {
585-
resolvedSymbol.isVisible = true;
586584
resolvedSymbol.declarations.forEach(d => getNodeLinks(d).isVisible = true);
587585
}
588586
});
@@ -607,7 +605,6 @@ export function bindSourceFileForDeclarationEmit(file: SourceFile) {
607605
postBindingAction.push(() => {
608606
const resolvedSymbol = resolveName(e, (e.propertyName ?? e.name).escapedText, ~0);
609607
if (resolvedSymbol) {
610-
resolvedSymbol.isVisible = true;
611608
resolvedSymbol.declarations.forEach(d => getNodeLinks(d).isVisible = true);
612609
}
613610
});

0 commit comments

Comments
 (0)