mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Avoid the double-symbol trick for enums
Nameless jsdoc typedefs have their exportedness controlled by the exportedness of the location they pull their name from. Fixes #33575.
This commit is contained in:
parent
1f5caf554c
commit
620e260576
@ -541,7 +541,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function declareModuleMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags): Symbol {
|
||||
const hasExportModifier = getCombinedModifierFlags(node) & ModifierFlags.Export;
|
||||
const hasExportModifier = !!(getCombinedModifierFlags(node) & ModifierFlags.Export) || jsdocTreatAsExported(node);
|
||||
if (symbolFlags & SymbolFlags.Alias) {
|
||||
if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) {
|
||||
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes);
|
||||
@ -567,7 +567,7 @@ namespace ts {
|
||||
// and this case is specially handled. Module augmentations should only be merged with original module definition
|
||||
// and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed.
|
||||
if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file.
|
||||
if ((!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) || isJSDocTypeAlias(node)) {
|
||||
if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) {
|
||||
if (!container.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) {
|
||||
return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default!
|
||||
}
|
||||
@ -583,6 +583,21 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function jsdocTreatAsExported(node: Node) {
|
||||
if (!isJSDocTypeAlias(node)) return false;
|
||||
// jsdoc typedef handling is a bit of a doozy, but to summarize, treat the typedef as exported if:
|
||||
// 1. It has an explicit name (since by default typedefs are always directly exported, either at the top level or in a container), or
|
||||
if (!isJSDocEnumTag(node) && !!node.fullName) return true;
|
||||
// 2. The thing a nameless typedef pulls its name from is implicitly a direct export (either by assignment or actual export flag).
|
||||
const declName = getNameOfDeclaration(node);
|
||||
if (!declName) return false;
|
||||
if (isPropertyAccessEntityNameExpression(declName.parent) && isTopLevelNamespaceAssignment(declName.parent)) return true;
|
||||
if (isDeclaration(declName.parent) && getCombinedModifierFlags(declName.parent) & ModifierFlags.Export) return true;
|
||||
// This could potentially be simplified by having `delayedBindJSDocTypedefTag` pass in an override for `hasExportModifier`, since it should
|
||||
// already have calculated and branched on most of this.
|
||||
return false;
|
||||
}
|
||||
|
||||
// All container nodes are kept on a linked list in declaration order. This list is used by
|
||||
// the getLocalNameOfContainer function in the type checker to validate that the local name
|
||||
// used for a container is unique.
|
||||
|
||||
26
tests/baselines/reference/exportedEnumTypeAndValue.symbols
Normal file
26
tests/baselines/reference/exportedEnumTypeAndValue.symbols
Normal file
@ -0,0 +1,26 @@
|
||||
=== tests/cases/conformance/jsdoc/def.js ===
|
||||
/** @enum {number} */
|
||||
const MyEnum = {
|
||||
>MyEnum : Symbol(MyEnum, Decl(def.js, 1, 5), Decl(def.js, 0, 4))
|
||||
|
||||
a: 1,
|
||||
>a : Symbol(a, Decl(def.js, 1, 16))
|
||||
|
||||
b: 2
|
||||
>b : Symbol(b, Decl(def.js, 2, 7))
|
||||
|
||||
};
|
||||
export default MyEnum;
|
||||
>MyEnum : Symbol(MyEnum, Decl(def.js, 1, 5), Decl(def.js, 0, 4))
|
||||
|
||||
=== tests/cases/conformance/jsdoc/use.js ===
|
||||
import MyEnum from "./def";
|
||||
>MyEnum : Symbol(MyEnum, Decl(use.js, 0, 6))
|
||||
|
||||
/** @type {MyEnum} */
|
||||
const v = MyEnum.b;
|
||||
>v : Symbol(v, Decl(use.js, 3, 5))
|
||||
>MyEnum.b : Symbol(b, Decl(def.js, 2, 7))
|
||||
>MyEnum : Symbol(MyEnum, Decl(use.js, 0, 6))
|
||||
>b : Symbol(b, Decl(def.js, 2, 7))
|
||||
|
||||
29
tests/baselines/reference/exportedEnumTypeAndValue.types
Normal file
29
tests/baselines/reference/exportedEnumTypeAndValue.types
Normal file
@ -0,0 +1,29 @@
|
||||
=== tests/cases/conformance/jsdoc/def.js ===
|
||||
/** @enum {number} */
|
||||
const MyEnum = {
|
||||
>MyEnum : { a: number; b: number; }
|
||||
>{ a: 1, b: 2} : { a: number; b: number; }
|
||||
|
||||
a: 1,
|
||||
>a : number
|
||||
>1 : 1
|
||||
|
||||
b: 2
|
||||
>b : number
|
||||
>2 : 2
|
||||
|
||||
};
|
||||
export default MyEnum;
|
||||
>MyEnum : number
|
||||
|
||||
=== tests/cases/conformance/jsdoc/use.js ===
|
||||
import MyEnum from "./def";
|
||||
>MyEnum : { a: number; b: number; }
|
||||
|
||||
/** @type {MyEnum} */
|
||||
const v = MyEnum.b;
|
||||
>v : number
|
||||
>MyEnum.b : number
|
||||
>MyEnum : { a: number; b: number; }
|
||||
>b : number
|
||||
|
||||
@ -55,9 +55,9 @@ const Thing = Object.freeze({
|
||||
});
|
||||
|
||||
exports.Thing = Thing;
|
||||
>exports.Thing : Symbol(Thing, Decl(index.js, 4, 3), Decl(index.js, 0, 4))
|
||||
>exports : Symbol(Thing, Decl(index.js, 4, 3), Decl(index.js, 0, 4))
|
||||
>Thing : Symbol(Thing, Decl(index.js, 4, 3), Decl(index.js, 0, 4))
|
||||
>exports.Thing : Symbol(Thing, Decl(index.js, 4, 3))
|
||||
>exports : Symbol(Thing, Decl(index.js, 4, 3))
|
||||
>Thing : Symbol(Thing, Decl(index.js, 4, 3))
|
||||
>Thing : Symbol(Thing, Decl(index.js, 1, 5), Decl(index.js, 0, 4))
|
||||
|
||||
/**
|
||||
|
||||
17
tests/cases/conformance/jsdoc/exportedEnumTypeAndValue.ts
Normal file
17
tests/cases/conformance/jsdoc/exportedEnumTypeAndValue.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// @noEmit: true
|
||||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
|
||||
// @Filename: def.js
|
||||
/** @enum {number} */
|
||||
const MyEnum = {
|
||||
a: 1,
|
||||
b: 2
|
||||
};
|
||||
export default MyEnum;
|
||||
|
||||
// @Filename: use.js
|
||||
import MyEnum from "./def";
|
||||
|
||||
/** @type {MyEnum} */
|
||||
const v = MyEnum.b;
|
||||
@ -15,8 +15,7 @@
|
||||
//// export { test/**/String };
|
||||
|
||||
verify.quickInfoAt("",
|
||||
`type testString = string
|
||||
(alias) type testString = any
|
||||
`(alias) type testString = string
|
||||
(alias) const testString: {
|
||||
one: string;
|
||||
two: string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user