Error on emit declaration of extends class w/o symbol
Error when emitting an extends clause for a type that has no symbol. This error only occurs on exported classes. This prevents the emitter from producing types that extend from intersections, which are not parseable right now.
This commit is contained in:
parent
58b8a54e5f
commit
cd272e8244
|
@ -20844,6 +20844,9 @@ namespace ts {
|
|||
const classType = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(node));
|
||||
resolveBaseTypesOfClass(classType);
|
||||
const baseType = classType.resolvedBaseTypes.length ? classType.resolvedBaseTypes[0] : unknownType;
|
||||
if (!baseType.symbol) {
|
||||
writer.reportIllegalExtends();
|
||||
}
|
||||
getSymbolDisplayBuilder().buildTypeDisplay(baseType, writer, enclosingDeclaration, flags);
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ namespace ts {
|
|||
const writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
|
||||
writer.trackSymbol = trackSymbol;
|
||||
writer.reportInaccessibleThisError = reportInaccessibleThisError;
|
||||
writer.reportIllegalExtends = reportIllegalExtends;
|
||||
writer.writeKeyword = writer.write;
|
||||
writer.writeOperator = writer.write;
|
||||
writer.writePunctuation = writer.write;
|
||||
|
@ -313,6 +314,14 @@ namespace ts {
|
|||
recordTypeReferenceDirectivesIfNecessary(resolver.getTypeReferenceDirectivesForSymbol(symbol, meaning));
|
||||
}
|
||||
|
||||
function reportIllegalExtends() {
|
||||
if (errorNameNode) {
|
||||
reportedDeclarationError = true;
|
||||
emitterDiagnostics.add(createDiagnosticForNode(errorNameNode, Diagnostics.Extends_clause_of_exported_class_0_refers_to_a_type_with_no_declaration,
|
||||
declarationNameToString(errorNameNode)));
|
||||
}
|
||||
}
|
||||
|
||||
function reportInaccessibleThisError() {
|
||||
if (errorNameNode) {
|
||||
reportedDeclarationError = true;
|
||||
|
@ -1071,7 +1080,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function emitHeritageClause(typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
function emitHeritageClause(className: Identifier, typeReferences: ExpressionWithTypeArguments[], isImplementsList: boolean) {
|
||||
if (typeReferences) {
|
||||
write(isImplementsList ? " implements " : " extends ");
|
||||
emitCommaList(typeReferences, emitTypeOfTypeReference);
|
||||
|
@ -1086,7 +1095,9 @@ namespace ts {
|
|||
}
|
||||
else {
|
||||
writer.getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError;
|
||||
errorNameNode = className;
|
||||
resolver.writeBaseConstructorTypeOfClass(<ClassLikeDeclaration>enclosingDeclaration, enclosingDeclaration, TypeFormatFlags.UseTypeOfFunction | TypeFormatFlags.UseTypeAliasValue, writer);
|
||||
errorNameNode = undefined;
|
||||
}
|
||||
|
||||
function getHeritageClauseVisibilityError(): SymbolAccessibilityDiagnostic {
|
||||
|
@ -1136,9 +1147,10 @@ namespace ts {
|
|||
emitTypeParameters(node.typeParameters);
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(node);
|
||||
if (baseTypeNode) {
|
||||
emitHeritageClause([baseTypeNode], /*isImplementsList*/ false);
|
||||
node.name
|
||||
emitHeritageClause(node.name, [baseTypeNode], /*isImplementsList*/ false);
|
||||
}
|
||||
emitHeritageClause(getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
|
||||
emitHeritageClause(node.name, getClassImplementsHeritageClauseElements(node), /*isImplementsList*/ true);
|
||||
write(" {");
|
||||
writeLine();
|
||||
increaseIndent();
|
||||
|
@ -1160,7 +1172,7 @@ namespace ts {
|
|||
emitTypeParameters(node.typeParameters);
|
||||
const interfaceExtendsTypes = filter(getInterfaceBaseTypeNodes(node), base => isEntityNameExpression(base.expression));
|
||||
if (interfaceExtendsTypes && interfaceExtendsTypes.length) {
|
||||
emitHeritageClause(interfaceExtendsTypes, /*isImplementsList*/ false);
|
||||
emitHeritageClause(node.name, interfaceExtendsTypes, /*isImplementsList*/ false);
|
||||
}
|
||||
write(" {");
|
||||
writeLine();
|
||||
|
|
|
@ -2352,6 +2352,10 @@
|
|||
"category": "Error",
|
||||
"code": 4092
|
||||
},
|
||||
"Extends clause of exported class '{0}' refers to a type with no declaration.": {
|
||||
"category": "Error",
|
||||
"code": 4093
|
||||
},
|
||||
|
||||
"The current host does not support the '{0}' option.": {
|
||||
"category": "Error",
|
||||
|
|
|
@ -2459,6 +2459,7 @@
|
|||
// with import statements it previously saw (but chose not to emit).
|
||||
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
|
||||
reportInaccessibleThisError(): void;
|
||||
reportIllegalExtends(): void;
|
||||
}
|
||||
|
||||
export const enum TypeFormatFlags {
|
||||
|
|
|
@ -53,7 +53,8 @@ namespace ts {
|
|||
decreaseIndent: noop,
|
||||
clear: () => str = "",
|
||||
trackSymbol: noop,
|
||||
reportInaccessibleThisError: noop
|
||||
reportInaccessibleThisError: noop,
|
||||
reportIllegalExtends: noop
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1166,7 +1166,8 @@ namespace ts {
|
|||
decreaseIndent: () => { indent--; },
|
||||
clear: resetWriter,
|
||||
trackSymbol: noop,
|
||||
reportInaccessibleThisError: noop
|
||||
reportInaccessibleThisError: noop,
|
||||
reportIllegalExtends: noop
|
||||
};
|
||||
|
||||
function writeIndent() {
|
||||
|
@ -1386,4 +1387,4 @@ namespace ts {
|
|||
// First token is the open curly, this is where we want to put the 'super' call.
|
||||
return constructor.body.getFirstToken(sourceFile).getEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue