mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 22:32:33 -05:00
Bind a jsdoc enum as SymbolFlags.TypeAlias and not SymbolFlags.Enum (#32520)
* Bind a jsdoc enum as SymbolFlags.TypeAlias and not SymbolFlags.Enum * Actually include an @enum tag as a declaration * Add enum tag refs into a couple more syntax kind lists * accept symbol baseline update
This commit is contained in:
@@ -120,7 +120,7 @@ namespace ts {
|
||||
let thisParentContainer: Node; // Container one level up
|
||||
let blockScopeContainer: Node;
|
||||
let lastContainer: Node;
|
||||
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag)[];
|
||||
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[];
|
||||
let seenThisKeyword: boolean;
|
||||
|
||||
// state used by control flow analysis
|
||||
@@ -732,7 +732,8 @@ namespace ts {
|
||||
break;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag);
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
|
||||
break;
|
||||
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
|
||||
case SyntaxKind.SourceFile: {
|
||||
@@ -1436,9 +1437,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag) {
|
||||
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) {
|
||||
node.tagName.parent = node;
|
||||
if (node.fullName) {
|
||||
if (node.kind !== SyntaxKind.JSDocEnumTag && node.fullName) {
|
||||
setParentPointers(node, node.fullName);
|
||||
}
|
||||
}
|
||||
@@ -1805,7 +1806,7 @@ namespace ts {
|
||||
currentFlow = { flags: FlowFlags.Start };
|
||||
parent = typeAlias;
|
||||
bind(typeAlias.typeExpression);
|
||||
if (!typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
|
||||
if (isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
|
||||
parent = typeAlias.parent;
|
||||
bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
|
||||
}
|
||||
@@ -2319,7 +2320,8 @@ namespace ts {
|
||||
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag);
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2766,11 +2768,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (!isBindingPattern(node.name)) {
|
||||
const isEnum = isInJSFile(node) && !!getJSDocEnumTag(node);
|
||||
const enumFlags = (isEnum ? SymbolFlags.RegularEnum : SymbolFlags.None);
|
||||
const enumExcludes = (isEnum ? SymbolFlags.RegularEnumExcludes : SymbolFlags.None);
|
||||
if (isBlockOrCatchScoped(node)) {
|
||||
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable | enumFlags, SymbolFlags.BlockScopedVariableExcludes | enumExcludes);
|
||||
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
|
||||
}
|
||||
else if (isParameterDeclaration(node)) {
|
||||
// It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration
|
||||
@@ -2785,7 +2784,7 @@ namespace ts {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
|
||||
}
|
||||
else {
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable | enumFlags, SymbolFlags.FunctionScopedVariableExcludes | enumExcludes);
|
||||
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1680,6 +1680,7 @@ namespace ts {
|
||||
break;
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
// js type aliases do not resolve names from their host, so skip past it
|
||||
location = getJSDocHost(location);
|
||||
break;
|
||||
@@ -2025,7 +2026,7 @@ namespace ts {
|
||||
// Block-scoped variables cannot be used before their definition
|
||||
const declaration = find(
|
||||
result.declarations,
|
||||
d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration) || isInJSFile(d) && !!getJSDocEnumTag(d));
|
||||
d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration));
|
||||
|
||||
if (declaration === undefined) return Debug.fail("Declaration to checkResolvedBlockScopedVariable is undefined");
|
||||
|
||||
@@ -4851,6 +4852,7 @@ namespace ts {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
// Top-level jsdoc type aliases are considered exported
|
||||
// First parent is comment node, second is hosting declaration or token; we only care about those tokens or declarations whose parent is a source file
|
||||
return !!(node.parent && node.parent.parent && node.parent.parent.parent && isSourceFile(node.parent.parent.parent));
|
||||
@@ -6156,6 +6158,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.MappedType:
|
||||
case SyntaxKind.ConditionalType:
|
||||
@@ -6489,8 +6492,10 @@ namespace ts {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
const declaration = <JSDocTypedefTag | JSDocCallbackTag | TypeAliasDeclaration>find(symbol.declarations, d =>
|
||||
isJSDocTypeAlias(d) || d.kind === SyntaxKind.TypeAliasDeclaration);
|
||||
const declaration = find(symbol.declarations, isTypeAlias);
|
||||
if (!declaration) {
|
||||
return Debug.fail("Type alias symbol with no valid declaration found");
|
||||
}
|
||||
const typeNode = isJSDocTypeAlias(declaration) ? declaration.typeExpression : declaration.type;
|
||||
// If typeNode is missing, we will error in checkJSDocTypedefTag.
|
||||
let type = typeNode ? getTypeFromTypeNode(typeNode) : errorType;
|
||||
@@ -6507,7 +6512,7 @@ namespace ts {
|
||||
}
|
||||
else {
|
||||
type = errorType;
|
||||
error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
|
||||
error(isJSDocEnumTag(declaration) ? declaration : declaration.name || declaration, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
|
||||
}
|
||||
links.declaredType = type;
|
||||
}
|
||||
@@ -9159,21 +9164,6 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
// JS enums are 'string' or 'number', not an enum type.
|
||||
const enumTag = isInJSFile(node) && symbol.valueDeclaration && getJSDocEnumTag(symbol.valueDeclaration);
|
||||
if (enumTag) {
|
||||
const links = getNodeLinks(enumTag);
|
||||
if (!pushTypeResolution(enumTag, TypeSystemPropertyName.EnumTagType)) {
|
||||
return errorType;
|
||||
}
|
||||
let type = enumTag.typeExpression ? getTypeFromTypeNode(enumTag.typeExpression) : errorType;
|
||||
if (!popTypeResolution()) {
|
||||
type = errorType;
|
||||
error(node, Diagnostics.Enum_type_0_circularly_references_itself, symbolToString(symbol));
|
||||
}
|
||||
return (links.resolvedEnumType = type);
|
||||
}
|
||||
|
||||
// Get type from reference to named type that cannot be generic (enum or type parameter)
|
||||
const res = tryGetDeclaredTypeOfSymbol(symbol);
|
||||
if (res) {
|
||||
@@ -26409,6 +26399,7 @@ namespace ts {
|
||||
// A jsdoc typedef and callback are, by definition, type aliases
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
return DeclarationSpaces.ExportType;
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
return isAmbientModule(d as ModuleDeclaration) || getModuleInstanceState(d as ModuleDeclaration) !== ModuleInstanceState.NonInstantiated
|
||||
@@ -30325,6 +30316,7 @@ namespace ts {
|
||||
return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
case SyntaxKind.JSDocCallbackTag:
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
return checkJSDocTypeAliasTag(node as JSDocTypedefTag);
|
||||
case SyntaxKind.JSDocTemplateTag:
|
||||
return checkJSDocTemplateTag(node as JSDocTemplateTag);
|
||||
|
||||
@@ -2466,7 +2466,8 @@ namespace ts {
|
||||
kind: SyntaxKind.JSDocClassTag;
|
||||
}
|
||||
|
||||
export interface JSDocEnumTag extends JSDocTag {
|
||||
export interface JSDocEnumTag extends JSDocTag, Declaration {
|
||||
parent: JSDoc;
|
||||
kind: SyntaxKind.JSDocEnumTag;
|
||||
typeExpression?: JSDocTypeExpression;
|
||||
}
|
||||
|
||||
@@ -2147,11 +2147,11 @@ namespace ts {
|
||||
return !!name && name.escapedText === "new";
|
||||
}
|
||||
|
||||
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag {
|
||||
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag;
|
||||
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag {
|
||||
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocEnumTag;
|
||||
}
|
||||
|
||||
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | TypeAliasDeclaration {
|
||||
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | TypeAliasDeclaration {
|
||||
return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node);
|
||||
}
|
||||
|
||||
@@ -5091,7 +5091,7 @@ namespace ts {
|
||||
* attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol
|
||||
* will be merged with)
|
||||
*/
|
||||
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
|
||||
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag | JSDocEnumTag): Identifier | undefined {
|
||||
const hostNode = declaration.parent.parent;
|
||||
if (!hostNode) {
|
||||
return undefined;
|
||||
@@ -5177,6 +5177,8 @@ namespace ts {
|
||||
}
|
||||
case SyntaxKind.JSDocTypedefTag:
|
||||
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag);
|
||||
case SyntaxKind.JSDocEnumTag:
|
||||
return nameForNamelessJSDocTypedef(declaration as JSDocEnumTag);
|
||||
case SyntaxKind.ExportAssignment: {
|
||||
const { expression } = declaration as ExportAssignment;
|
||||
return isIdentifier(expression) ? expression : undefined;
|
||||
|
||||
@@ -97,7 +97,7 @@ class TypeWriterWalker {
|
||||
if (!isSymbolWalk) {
|
||||
// Don't try to get the type of something that's already a type.
|
||||
// Exception for `T` in `type T = something` because that may evaluate to some interesting type.
|
||||
if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAlias(node.parent) && node.parent.name === node)) {
|
||||
if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user