Skip to content

Commit 4554796

Browse files
Merge pull request #127 from bloomberg/isolated-declarations-visibility-refactor
Deduplicated code for symbol visibility checks.
2 parents 62318bf + 69d991a commit 4554796

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,
@@ -1472,6 +1470,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
14721470
var freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral;
14731471
var exactOptionalPropertyTypes = compilerOptions.exactOptionalPropertyTypes;
14741472

1473+
var { hasVisibleDeclarations, isEntityNameVisible } = createEntityVisibilityChecker({
1474+
defaultSymbolAccessibility: SymbolAccessibility.NotAccessible,
1475+
isThisAccessible,
1476+
isDeclarationVisible,
1477+
markDeclarationAsVisible(declaration) {
1478+
getNodeLinks(declaration).isVisible = true;
1479+
},
1480+
resolveName,
1481+
});
14751482
var checkBinaryExpression = createCheckBinaryExpression();
14761483
var emitResolver = createResolver();
14771484
var nodeBuilder = createNodeBuilder();
@@ -6174,121 +6181,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61746181
return isModuleWithStringLiteralName(declaration) || (declaration.kind === SyntaxKind.SourceFile && isExternalOrCommonJsModule(declaration as SourceFile));
61756182
}
61766183

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

62946188
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)