@@ -5860,6 +5860,32 @@ namespace ts {
5860
5860
return typeToTypeNodeHelper(type, context);
5861
5861
}
5862
5862
5863
+ function trackExistingEntityName<T extends EntityNameOrEntityNameExpression>(node: T, context: NodeBuilderContext, includePrivateSymbol?: (s: Symbol) => void) {
5864
+ let introducesError = false;
5865
+ const leftmost = getFirstIdentifier(node);
5866
+ if (isInJSFile(node) && (isExportsIdentifier(leftmost) || isModuleExportsAccessExpression(leftmost.parent) || (isQualifiedName(leftmost.parent) && isModuleIdentifier(leftmost.parent.left) && isExportsIdentifier(leftmost.parent.right)))) {
5867
+ introducesError = true;
5868
+ return { introducesError, node };
5869
+ }
5870
+ const sym = resolveEntityName(leftmost, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveALias*/ true);
5871
+ if (sym) {
5872
+ if (isSymbolAccessible(sym, context.enclosingDeclaration, SymbolFlags.All, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== SymbolAccessibility.Accessible) {
5873
+ introducesError = true;
5874
+ }
5875
+ else {
5876
+ context.tracker?.trackSymbol?.(sym, context.enclosingDeclaration, SymbolFlags.All);
5877
+ includePrivateSymbol?.(sym);
5878
+ }
5879
+ if (isIdentifier(node)) {
5880
+ const name = sym.flags & SymbolFlags.TypeParameter ? typeParameterToName(getDeclaredTypeOfSymbol(sym), context) : factory.cloneNode(node);
5881
+ name.symbol = sym; // for quickinfo, which uses identifier symbol information
5882
+ return { introducesError, node: setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping) };
5883
+ }
5884
+ }
5885
+
5886
+ return { introducesError, node };
5887
+ }
5888
+
5863
5889
function serializeExistingTypeNode(context: NodeBuilderContext, existing: TypeNode, includePrivateSymbol?: (s: Symbol) => void, bundled?: boolean) {
5864
5890
if (cancellationToken && cancellationToken.throwIfCancellationRequested) {
5865
5891
cancellationToken.throwIfCancellationRequested();
@@ -5971,25 +5997,10 @@ namespace ts {
5971
5997
}
5972
5998
5973
5999
if (isEntityName(node) || isEntityNameExpression(node)) {
5974
- const leftmost = getFirstIdentifier(node);
5975
- if (isInJSFile(node) && (isExportsIdentifier(leftmost) || isModuleExportsAccessExpression(leftmost.parent) || (isQualifiedName(leftmost.parent) && isModuleIdentifier(leftmost.parent.left) && isExportsIdentifier(leftmost.parent.right)))) {
5976
- hadError = true;
5977
- return node;
5978
- }
5979
- const sym = resolveEntityName(leftmost, SymbolFlags.All, /*ignoreErrors*/ true, /*dontResolveALias*/ true);
5980
- if (sym) {
5981
- if (isSymbolAccessible(sym, context.enclosingDeclaration, SymbolFlags.All, /*shouldComputeAliasesToMakeVisible*/ false).accessibility !== SymbolAccessibility.Accessible) {
5982
- hadError = true;
5983
- }
5984
- else {
5985
- context.tracker?.trackSymbol?.(sym, context.enclosingDeclaration, SymbolFlags.All);
5986
- includePrivateSymbol?.(sym);
5987
- }
5988
- if (isIdentifier(node)) {
5989
- const name = sym.flags & SymbolFlags.TypeParameter ? typeParameterToName(getDeclaredTypeOfSymbol(sym), context) : factory.cloneNode(node);
5990
- name.symbol = sym; // for quickinfo, which uses identifier symbol information
5991
- return setEmitFlags(setOriginalNode(name, node), EmitFlags.NoAsciiEscaping);
5992
- }
6000
+ const { introducesError, node: result } = trackExistingEntityName(node, context, includePrivateSymbol);
6001
+ hadError = hadError || introducesError;
6002
+ if (result !== node) {
6003
+ return result;
5993
6004
}
5994
6005
}
5995
6006
@@ -6716,12 +6727,44 @@ namespace ts {
6716
6727
!(p.flags & SymbolFlags.Prototype || p.escapedName === "prototype" || p.valueDeclaration && getEffectiveModifierFlags(p.valueDeclaration) & ModifierFlags.Static && isClassLike(p.valueDeclaration.parent));
6717
6728
}
6718
6729
6730
+ function sanitizeJSDocImplements(clauses: readonly ExpressionWithTypeArguments[]): ExpressionWithTypeArguments[] | undefined {
6731
+ const result = mapDefined(clauses, e => {
6732
+ const oldEnclosing = context.enclosingDeclaration;
6733
+ context.enclosingDeclaration = e;
6734
+ let expr = e.expression;
6735
+ if (isEntityNameExpression(expr)) {
6736
+ if (isIdentifier(expr) && idText(expr) === "") {
6737
+ return cleanup(/*result*/ undefined); // Empty heritage clause, should be an error, but prefer emitting no heritage clauses to reemitting the empty one
6738
+ }
6739
+ let introducesError: boolean;
6740
+ ({ introducesError, node: expr } = trackExistingEntityName(expr, context, includePrivateSymbol));
6741
+ if (introducesError) {
6742
+ return cleanup(/*result*/ undefined);
6743
+ }
6744
+ }
6745
+ return cleanup(factory.createExpressionWithTypeArguments(expr, map(e.typeArguments, a => serializeExistingTypeNode(context, a, includePrivateSymbol, bundled) || typeToTypeNodeHelper(getTypeFromTypeNode(a), context))));
6746
+
6747
+ function cleanup<T>(result: T): T {
6748
+ context.enclosingDeclaration = oldEnclosing;
6749
+ return result;
6750
+ }
6751
+ });
6752
+ if (result.length === clauses.length) {
6753
+ return result;
6754
+ }
6755
+ return undefined;
6756
+ }
6757
+
6719
6758
function serializeAsClass(symbol: Symbol, localName: string, modifierFlags: ModifierFlags) {
6759
+ const originalDecl = find(symbol.declarations, isClassLike);
6760
+ const oldEnclosing = context.enclosingDeclaration;
6761
+ context.enclosingDeclaration = originalDecl || oldEnclosing;
6720
6762
const localParams = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
6721
6763
const typeParamDecls = map(localParams, p => typeParameterToDeclaration(p, context));
6722
6764
const classType = getDeclaredTypeOfClassOrInterface(symbol);
6723
6765
const baseTypes = getBaseTypes(classType);
6724
- const implementsExpressions = mapDefined(getImplementsTypes(classType), serializeImplementedType);
6766
+ const originalImplements = originalDecl && getEffectiveImplementsTypeNodes(originalDecl);
6767
+ const implementsExpressions = originalImplements && sanitizeJSDocImplements(originalImplements) || mapDefined(getImplementsTypes(classType), serializeImplementedType);
6725
6768
const staticType = getTypeOfSymbol(symbol);
6726
6769
const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration);
6727
6770
const staticBaseType = isClass
@@ -6774,6 +6817,7 @@ namespace ts {
6774
6817
[factory.createConstructorDeclaration(/*decorators*/ undefined, factory.createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] :
6775
6818
serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
6776
6819
const indexSignatures = serializeIndexSignatures(classType, baseTypes[0]);
6820
+ context.enclosingDeclaration = oldEnclosing;
6777
6821
addResult(setTextRange(factory.createClassDeclaration(
6778
6822
/*decorators*/ undefined,
6779
6823
/*modifiers*/ undefined,
0 commit comments