diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1a8c2a09f04..416d3296151 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1910,13 +1910,13 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.resolvedExports) { const earlySymbols = symbol.flags & SymbolFlags.Module ? getExportsOfModuleWorker(symbol) : symbol.exports; - const lateSymbols = getLateBoundExportsOfSymbol(symbol); // In the event we recursively resolve the members of the symbol, we // should only see the early-bound members of the symbol here. links.resolvedExports = earlySymbols || emptySymbols; // fill in any as-yet-unresolved late-bound members. + const lateSymbols = createSymbolTable(); for (const decl of symbol.declarations) { const members = getMembersOfDeclaration(decl); if (members) { @@ -5561,26 +5561,6 @@ namespace ts { } } - /** - * Gets the symbol table used to store members added during late-binding. - * This table is filled in as the late-bound names for dynamic members are resolved. - */ - function getLateBoundMembersOfSymbol(symbol: Symbol): SymbolTable { - Debug.assert(!!(symbol.flags & SymbolFlags.LateBindableContainer), "Expected a container that supports late-binding."); - const links = getSymbolLinks(symbol); - return links.lateMembers || (links.lateMembers = createSymbolTable()); - } - - /** - * Gets the symbol table used to store exports added during late-binding. - * This table is filled in as the late-bound names for dynamic members are resolved. - */ - function getLateBoundExportsOfSymbol(symbol: Symbol): SymbolTable { - Debug.assert(!!(symbol.flags & SymbolFlags.Class), "Expected a container that supports late-binding of exports."); - const links = getSymbolLinks(symbol); - return links.lateExports || (links.lateExports = createSymbolTable()); - } - /** * Adds a declaration to a late-bound dynamic member. This performs the same function for * late-bound members that `addDeclarationToSymbol` in binder.ts performs for early-bound @@ -5675,13 +5655,9 @@ namespace ts { * For a description of late-binding, see `lateBindMember`. */ function getMembersOfSymbol(symbol: Symbol) { - if (symbol.flags & SymbolFlags.LateBindableContainer) { + if (symbol.flags & SymbolFlags.LateBindingContainer) { const links = getSymbolLinks(symbol); if (!links.resolvedMembers) { - // Get (or create) the SymbolTable from the parent used to store late- - // bound symbols. We get a shared table so that we can correctly merge - // late-bound symbols across accessor pairs. - const lateMembers = getLateBoundMembersOfSymbol(symbol); const earlyMembers = symbol.members; // In the event we recursively resolve the members of the symbol, we @@ -5690,6 +5666,7 @@ namespace ts { links.resolvedMembers = earlyMembers || emptySymbols; // fill in any as-yet-unresolved late-bound members. + const lateMembers = createSymbolTable(); for (const decl of symbol.declarations) { const members = getMembersOfDeclaration(decl); if (members) { @@ -5718,7 +5695,7 @@ namespace ts { const links = getSymbolLinks(symbol); if (!links.lateSymbol) { const parent = symbol.parent; - if (symbolHasLateBindableName(symbol) && parent && parent.flags & SymbolFlags.LateBindableContainer) { + if (symbolHasLateBindableName(symbol) && parent && parent.flags & SymbolFlags.LateBindingContainer) { // force late binding of members/exports. This will set the late-bound symbol if (some(symbol.declarations, hasStaticModifier)) { getExportsOfSymbol(parent); @@ -7979,7 +7956,9 @@ namespace ts { links.resolvedType = getIndexType(getTypeFromTypeNode(node.type)); break; case SyntaxKind.UniqueKeyword: - links.resolvedType = getUniqueType(node); + links.resolvedType = node.type.kind === SyntaxKind.SymbolKeyword + ? getUniqueESSymbolTypeForNode(walkUpParenthesizedTypes(node.parent)) + : unknownType break; } } @@ -8353,13 +8332,6 @@ namespace ts { return links.resolvedType; } - function nodeCanHaveUniqueESSymbolType(node: Node) { - return isVariableDeclaration(node) ? isConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) : - isPropertyDeclaration(node) ? hasReadonlyModifier(node) && hasStaticModifier(node) : - isPropertySignature(node) ? hasReadonlyModifier(node) : - false; - } - function createUniqueESSymbolType(symbol: Symbol) { const type = createType(TypeFlags.UniqueESSymbol); type.symbol = symbol; @@ -8367,21 +8339,16 @@ namespace ts { } function getUniqueESSymbolTypeForNode(node: Node) { - const parent = walkUpParentheses(node); - if (nodeCanHaveUniqueESSymbolType(parent)) { - const symbol = getSymbolOfNode(parent); + if (isVariableDeclaration(node) ? isConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) : + isPropertyDeclaration(node) ? hasReadonlyModifier(node) && hasStaticModifier(node) : + isPropertySignature(node) && hasReadonlyModifier(node)) { + const symbol = getSymbolOfNode(node); const links = getSymbolLinks(symbol); return links.type || (links.type = createUniqueESSymbolType(symbol)); } return esSymbolType; } - function getUniqueType(node: UniqueTypeOperatorNode) { - return node.type.kind === SyntaxKind.SymbolKeyword - ? getUniqueESSymbolTypeForNode(node.parent) - : unknownType; - } - function getTypeFromJSDocVariadicType(node: JSDocVariadicType): Type { const links = getNodeLinks(node); if (!links.resolvedType) { @@ -17271,7 +17238,7 @@ namespace ts { // Treat any call to the global 'Symbol' function that is part of a const variable or readonly property // as a fresh unique symbol literal type. if (returnType.flags & TypeFlags.ESSymbolLike && isSymbolOrSymbolForCall(node)) { - return getUniqueESSymbolTypeForNode(node.parent); + return getUniqueESSymbolTypeForNode(walkUpParenthesizedExpressions(node.parent)); } return returnType; } diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 2efea500a9b..a671d107d0b 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -460,6 +460,19 @@ namespace ts { return emitTypePredicate(type); } + function writeEntityName(entityName: EntityName | Expression) { + if (entityName.kind === SyntaxKind.Identifier) { + writeTextOfNode(currentText, entityName); + } + else { + const left = entityName.kind === SyntaxKind.QualifiedName ? (entityName).left : (entityName).expression; + const right = entityName.kind === SyntaxKind.QualifiedName ? (entityName).right : (entityName).name; + writeEntityName(left); + write("."); + writeTextOfNode(currentText, right); + } + } + function emitEntityName(entityName: EntityNameOrEntityNameExpression) { const visibilityResult = resolver.isEntityNameVisible(entityName, // Aliases can be written asynchronously so use correct enclosing declaration @@ -579,19 +592,6 @@ namespace ts { } } - function writeEntityName(entityName: EntityName | Expression) { - if (entityName.kind === SyntaxKind.Identifier) { - writeTextOfNode(currentText, entityName); - } - else { - const left = entityName.kind === SyntaxKind.QualifiedName ? (entityName).left : (entityName).expression; - const right = entityName.kind === SyntaxKind.QualifiedName ? (entityName).right : (entityName).name; - writeEntityName(left); - write("."); - writeTextOfNode(currentText, right); - } - } - function emitSourceFile(node: SourceFile) { currentText = node.text; currentLineMap = getLineStarts(node); @@ -1246,7 +1246,7 @@ namespace ts { emitBindingPattern(node.name); } else { - writeNameOfDeclaration(node, getVariableDeclarationTypeOrNameVisibilityError); + writeNameOfDeclaration(node, getVariableDeclarationTypeVisibilityError); // If optional property emit ? but in the case of parameterProperty declaration with "?" indicating optional parameter for the constructor // we don't want to emit property declaration with "?" @@ -1262,12 +1262,12 @@ namespace ts { resolver.writeLiteralConstValue(node, writer); } else if (!hasModifier(node, ModifierFlags.Private)) { - writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeOrNameVisibilityError); + writeTypeOfDeclaration(node, node.type, getVariableDeclarationTypeVisibilityError); } } } - function getVariableDeclarationTypeOrNameVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { + function getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult: SymbolAccessibilityResult) { if (node.kind === SyntaxKind.VariableDeclaration) { return symbolAccessibilityResult.errorModuleName ? symbolAccessibilityResult.accessibility === SymbolAccessibility.CannotBeNamed ? @@ -1303,8 +1303,8 @@ namespace ts { } } - function getVariableDeclarationTypeOrNameVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { - const diagnosticMessage = getVariableDeclarationTypeOrNameVisibilityDiagnosticMessage(symbolAccessibilityResult); + function getVariableDeclarationTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { + const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: node, @@ -1329,7 +1329,7 @@ namespace ts { function emitBindingElement(bindingElement: BindingElement) { function getBindingElementTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic { - const diagnosticMessage = getVariableDeclarationTypeOrNameVisibilityDiagnosticMessage(symbolAccessibilityResult); + const diagnosticMessage = getVariableDeclarationTypeVisibilityDiagnosticMessage(symbolAccessibilityResult); return diagnosticMessage !== undefined ? { diagnosticMessage, errorNode: bindingElement, diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index c79ff4c4287..7dd75bce717 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2638,12 +2638,12 @@ namespace ts { case SyntaxKind.AnyKeyword: case SyntaxKind.StringKeyword: case SyntaxKind.NumberKeyword: + case SyntaxKind.SymbolKeyword: case SyntaxKind.BooleanKeyword: case SyntaxKind.UndefinedKeyword: case SyntaxKind.NeverKeyword: case SyntaxKind.ObjectKeyword: - case SyntaxKind.SymbolKeyword: - // If these are followed by a dot, then parse these out as a dotted type reference instead. + // If these are followed by a dot, then parse these out as a dotted type reference instead. return tryParse(parseKeywordAndNoDot) || parseTypeReference(); case SyntaxKind.AsteriskToken: return parseJSDocAllType(); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f4cc88e9a31..a311e8c4eb2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2784,7 +2784,6 @@ namespace ts { // State InObjectTypeLiteral = 1 << 20, InTypeAlias = 1 << 23, // Writing type in type alias declaration - IsDeclarationOfUniqueESSymbolType = 1 << 24, } /* @internal */ @@ -3057,7 +3056,7 @@ namespace ts { Classifiable = Class | Enum | TypeAlias | Interface | TypeParameter | Module, /* @internal */ - LateBindableContainer = Class | Interface | TypeLiteral | ObjectLiteral, + LateBindingContainer = Class | Interface | TypeLiteral | ObjectLiteral, } export interface Symbol { @@ -3099,13 +3098,11 @@ namespace ts { resolvedMembers?: SymbolTable; // Combined early- and late-bound members of a symbol exportsChecked?: boolean; // True if exports of external module have been checked typeParametersChecked?: boolean; // True if type parameters of merged class and interface declarations have been checked. - isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration + isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration bindingElement?: BindingElement; // Binding element associated with property symbol exportsSomeValue?: boolean; // True if module exports some value (not just types) enumKind?: EnumKind; // Enum declaration classification lateSymbol?: Symbol; // Late-bound symbol for a computed property - lateMembers?: SymbolTable; // Late-bound members resolved during check - lateExports?: SymbolTable; // Late-bound exports resolved during check } /* @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index b2ece2421ab..9d22d45f980 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1715,19 +1715,19 @@ namespace ts { return getAssignmentTargetKind(node) !== AssignmentKind.None; } - export function walkUpParentheses(node: Node) { - while (node && (node.kind === SyntaxKind.ParenthesizedType || - node.kind === SyntaxKind.ParenthesizedExpression)) { + function walkUp(node: Node, kind: SyntaxKind) { + while (node && node.kind === kind) { node = node.parent; } return node; } + export function walkUpParenthesizedTypes(node: Node) { + return walkUp(node, SyntaxKind.ParenthesizedType); + } + export function walkUpParenthesizedExpressions(node: Node) { - while (node && node.kind === SyntaxKind.ParenthesizedExpression) { - node = node.parent; - } - return node; + return walkUp(node, SyntaxKind.ParenthesizedExpression); } // a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped @@ -1736,9 +1736,6 @@ namespace ts { return false; } node = walkUpParenthesizedExpressions(node.parent); - while (node && node.kind === SyntaxKind.ParenthesizedExpression) { - node = node.parent; - } return node && node.kind === SyntaxKind.DeleteExpression; } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 0b92c4c00a2..6d5ec9fbf00 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -1781,7 +1781,6 @@ declare namespace ts { IgnoreErrors = 60416, InObjectTypeLiteral = 1048576, InTypeAlias = 8388608, - IsDeclarationOfUniqueESSymbolType = 16777216, } interface SymbolDisplayBuilder { buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0c5d2b56fc0..95fbed8c9c9 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -1781,7 +1781,6 @@ declare namespace ts { IgnoreErrors = 60416, InObjectTypeLiteral = 1048576, InTypeAlias = 8388608, - IsDeclarationOfUniqueESSymbolType = 16777216, } interface SymbolDisplayBuilder { buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;