Defer checking of class expression bodies
This commit is contained in:
parent
a264be5afa
commit
23603a39b8
4 changed files with 42 additions and 49 deletions
|
@ -409,6 +409,13 @@ namespace ts {
|
|||
}
|
||||
break loop;
|
||||
}
|
||||
if (location.kind === SyntaxKind.ClassExpression && meaning & SymbolFlags.Class) {
|
||||
let className = (<ClassExpression>location).name;
|
||||
if (className && name === className.text) {
|
||||
result = location.symbol;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// It is not legal to reference a class's own type parameters from a computed property name that
|
||||
|
@ -455,15 +462,6 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ClassExpression:
|
||||
if (meaning & SymbolFlags.Class) {
|
||||
let className = (<ClassExpression>location).name;
|
||||
if (className && name === className.text) {
|
||||
result = location.symbol;
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.Decorator:
|
||||
// Decorators are resolved at the class declaration. Resolving at the parameter
|
||||
// or member would result in looking up locals in the method.
|
||||
|
@ -1397,13 +1395,30 @@ namespace ts {
|
|||
// This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
|
||||
let _displayBuilder: SymbolDisplayBuilder;
|
||||
function getSymbolDisplayBuilder(): SymbolDisplayBuilder {
|
||||
|
||||
function getNameOfSymbol(symbol: Symbol): string {
|
||||
if (symbol.declarations && symbol.declarations.length) {
|
||||
let declaration = symbol.declarations[0];
|
||||
if (declaration.name) {
|
||||
return declarationNameToString(declaration.name);
|
||||
}
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.ClassExpression:
|
||||
return "(Anonymous class)";
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return "(Anonymous function)";
|
||||
}
|
||||
}
|
||||
return symbol.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes only the name of the symbol out to the writer. Uses the original source text
|
||||
* for the name of the symbol if it is available to match how the user inputted the name.
|
||||
*/
|
||||
function appendSymbolNameOnly(symbol: Symbol, writer: SymbolWriter): void {
|
||||
let name = symbol.declarations && symbol.declarations.length > 0 ? declarationToString(symbol.declarations[0]) : symbol.name;
|
||||
writer.writeSymbol(name, symbol);
|
||||
writer.writeSymbol(getNameOfSymbol(symbol), symbol);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7851,7 +7866,7 @@ namespace ts {
|
|||
if (node.type) {
|
||||
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
|
||||
}
|
||||
checkFunctionExpressionBodies(node.body);
|
||||
checkFunctionAndClassExpressionBodies(node.body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9567,7 +9582,7 @@ namespace ts {
|
|||
|
||||
forEach(node.statements, checkSourceElement);
|
||||
if (isFunctionBlock(node) || node.kind === SyntaxKind.ModuleBlock) {
|
||||
checkFunctionExpressionBodies(node);
|
||||
checkFunctionAndClassExpressionBodies(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10563,11 +10578,11 @@ namespace ts {
|
|||
}
|
||||
|
||||
function checkClassDeclaration(node: ClassDeclaration) {
|
||||
// Grammar checking
|
||||
if (!node.name && !(node.flags & NodeFlags.Default)) {
|
||||
grammarErrorOnFirstToken(node, Diagnostics.A_class_declaration_without_the_default_modifier_must_have_a_name);
|
||||
}
|
||||
checkClassLikeDeclaration(node);
|
||||
forEach(node.members, checkSourceElement);
|
||||
}
|
||||
|
||||
function checkClassLikeDeclaration(node: ClassLikeDeclaration) {
|
||||
|
@ -10638,7 +10653,6 @@ namespace ts {
|
|||
});
|
||||
}
|
||||
|
||||
forEach(node.members, checkSourceElement);
|
||||
if (produceDiagnostics) {
|
||||
checkIndexConstraints(type);
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
|
@ -11511,8 +11525,8 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
// Function expression bodies are checked after all statements in the enclosing body. This is to ensure
|
||||
// constructs like the following are permitted:
|
||||
// Function and class expression bodies are checked after all statements in the enclosing body. This is
|
||||
// to ensure constructs like the following are permitted:
|
||||
// let foo = function () {
|
||||
// let s = foo();
|
||||
// return "hello";
|
||||
|
@ -11520,17 +11534,20 @@ namespace ts {
|
|||
// Here, performing a full type check of the body of the function expression whilst in the process of
|
||||
// determining the type of foo would cause foo to be given type any because of the recursive reference.
|
||||
// Delaying the type check of the body ensures foo has been assigned a type.
|
||||
function checkFunctionExpressionBodies(node: Node): void {
|
||||
function checkFunctionAndClassExpressionBodies(node: Node): void {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionExpressionBodies);
|
||||
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
|
||||
checkFunctionExpressionOrObjectLiteralMethodBody(<FunctionExpression>node);
|
||||
break;
|
||||
case SyntaxKind.ClassExpression:
|
||||
forEach((<ClassExpression>node).members, checkSourceElement);
|
||||
break;
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.MethodSignature:
|
||||
forEach(node.decorators, checkFunctionExpressionBodies);
|
||||
forEach((<MethodDeclaration>node).parameters, checkFunctionExpressionBodies);
|
||||
forEach(node.decorators, checkFunctionAndClassExpressionBodies);
|
||||
forEach((<MethodDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
|
||||
if (isObjectLiteralMethod(node)) {
|
||||
checkFunctionExpressionOrObjectLiteralMethodBody(<MethodDeclaration>node);
|
||||
}
|
||||
|
@ -11539,10 +11556,10 @@ namespace ts {
|
|||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionExpressionBodies);
|
||||
forEach((<FunctionLikeDeclaration>node).parameters, checkFunctionAndClassExpressionBodies);
|
||||
break;
|
||||
case SyntaxKind.WithStatement:
|
||||
checkFunctionExpressionBodies((<WithStatement>node).expression);
|
||||
checkFunctionAndClassExpressionBodies((<WithStatement>node).expression);
|
||||
break;
|
||||
case SyntaxKind.Decorator:
|
||||
case SyntaxKind.Parameter:
|
||||
|
@ -11599,7 +11616,7 @@ namespace ts {
|
|||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.ExportAssignment:
|
||||
case SyntaxKind.SourceFile:
|
||||
forEachChild(node, checkFunctionExpressionBodies);
|
||||
forEachChild(node, checkFunctionAndClassExpressionBodies);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -11631,7 +11648,7 @@ namespace ts {
|
|||
potentialThisCollisions.length = 0;
|
||||
|
||||
forEach(node.statements, checkSourceElement);
|
||||
checkFunctionExpressionBodies(node);
|
||||
checkFunctionAndClassExpressionBodies(node);
|
||||
|
||||
if (isExternalModule(node)) {
|
||||
checkExternalModuleExports(node);
|
||||
|
|
|
@ -567,7 +567,5 @@ namespace ts {
|
|||
enum_declarations_can_only_be_used_in_a_ts_file: { code: 8015, category: DiagnosticCategory.Error, key: "'enum declarations' can only be used in a .ts file." },
|
||||
type_assertion_expressions_can_only_be_used_in_a_ts_file: { code: 8016, category: DiagnosticCategory.Error, key: "'type assertion expressions' can only be used in a .ts file." },
|
||||
decorators_can_only_be_used_in_a_ts_file: { code: 8017, category: DiagnosticCategory.Error, key: "'decorators' can only be used in a .ts file." },
|
||||
Only_identifiers_Slashqualified_names_with_optional_type_arguments_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses." },
|
||||
class_expressions_are_not_currently_supported: { code: 9003, category: DiagnosticCategory.Error, key: "'class' expressions are not currently supported." },
|
||||
};
|
||||
}
|
|
@ -2259,14 +2259,5 @@
|
|||
"'decorators' can only be used in a .ts file.": {
|
||||
"category": "Error",
|
||||
"code": 8017
|
||||
},
|
||||
|
||||
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses.": {
|
||||
"category": "Error",
|
||||
"code": 9002
|
||||
},
|
||||
"'class' expressions are not currently supported.": {
|
||||
"category": "Error",
|
||||
"code": 9003
|
||||
}
|
||||
}
|
||||
|
|
|
@ -247,19 +247,6 @@ namespace ts {
|
|||
declaration.parent.kind === SyntaxKind.CatchClause;
|
||||
}
|
||||
|
||||
export function declarationToString(declaration: Declaration) {
|
||||
if (!declaration.name) {
|
||||
switch (declaration.kind) {
|
||||
case SyntaxKind.ClassExpression:
|
||||
return "(Anonymous class)";
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
return "(Anonymous function)";
|
||||
}
|
||||
}
|
||||
return declarationNameToString(declaration.name);
|
||||
}
|
||||
|
||||
// Return display name of an identifier
|
||||
// Computed property names will just be emitted as "[<expr>]", where <expr> is the source
|
||||
// text of the expression in the computed property.
|
||||
|
|
Loading…
Reference in a new issue