Issue an error when class is used before class declaration

This commit is contained in:
Kanchalai Tanglertsampan 2017-02-24 16:46:21 -08:00
parent 65da012527
commit ed7a3d00b9
2 changed files with 25 additions and 21 deletions

View File

@ -1056,9 +1056,9 @@ namespace ts {
// block-scoped variable and namespace module. However, only when we
// try to resolve name in /*1*/ which is used in variable position,
// we want to check for block-scoped
if (meaning & SymbolFlags.BlockScopedVariable) {
if (meaning & SymbolFlags.BlockScopedVariable || (meaning & SymbolFlags.Class && (meaning & SymbolFlags.Value) === SymbolFlags.Value)) {
const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result);
if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable) {
if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable || exportOrLocalSymbol.flags & SymbolFlags.Class) {
checkResolvedBlockScopedVariable(exportOrLocalSymbol, errorLocation);
}
}
@ -1171,14 +1171,19 @@ namespace ts {
}
function checkResolvedBlockScopedVariable(result: Symbol, errorLocation: Node): void {
Debug.assert((result.flags & SymbolFlags.BlockScopedVariable) !== 0);
Debug.assert(!!(result.flags & SymbolFlags.BlockScopedVariable || result.flags & SymbolFlags.Class));
// Block-scoped variables cannot be used before their definition
const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) ? d : undefined);
const declaration = forEach(result.declarations, d => isBlockOrCatchScoped(d) || isClassLike(d) ? d : undefined);
Debug.assert(declaration !== undefined, "Block-scoped variable declaration is undefined");
if (!isInAmbientContext(declaration) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) {
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
if (result.flags & SymbolFlags.BlockScopedVariable) {
error(errorLocation, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, declarationNameToString(declaration.name));
}
else {
error(errorLocation, Diagnostics.Class_0_used_before_its_declaration, declarationNameToString(declaration.name));
}
}
}
@ -13171,10 +13176,17 @@ namespace ts {
}
return unknownType;
}
if (prop.valueDeclaration &&
isInPropertyInitializer(node) &&
!isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) {
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, right.text);
if (prop.valueDeclaration) {
if (isInPropertyInitializer(node) &&
!isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) {
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, right.text);
}
if (prop.valueDeclaration.kind === SyntaxKind.ClassDeclaration &&
node.parent && node.parent.kind !== SyntaxKind.TypeReference &&
!isInAmbientContext(prop.valueDeclaration) &&
!isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) {
error(right, Diagnostics.Class_0_used_before_its_declaration, right.text);
}
}
markPropertyAsReferenced(prop);
@ -19421,14 +19433,6 @@ namespace ts {
error(node.name || node, Diagnostics.A_mixin_class_must_have_a_constructor_with_a_single_rest_parameter_of_type_any);
}
if (baseType.symbol && baseType.symbol.valueDeclaration &&
!isInAmbientContext(baseType.symbol.valueDeclaration) &&
baseType.symbol.valueDeclaration.kind === SyntaxKind.ClassDeclaration) {
if (!isBlockScopedNameDeclaredBeforeUse(baseType.symbol.valueDeclaration, node)) {
error(baseTypeNode, Diagnostics.A_class_must_be_declared_after_its_base_class);
}
}
if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class) && !(baseConstructorType.flags & TypeFlags.TypeVariable)) {
// When the static base type is a "class-like" constructor function (but not actually a class), we verify
// that all instantiated base constructor signatures return the same type. We can simply compare the type

View File

@ -1435,6 +1435,10 @@
"category": "Error",
"code": 2448
},
"Class '{0}' used before its declaration.": {
"category": "Error",
"code": 2449
},
"Cannot redeclare block-scoped variable '{0}'.": {
"category": "Error",
"code": 2451
@ -2019,10 +2023,6 @@
"category": "Error",
"code": 2689
},
"A class must be declared after its base class.": {
"category": "Error",
"code": 2690
},
"An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.": {
"category": "Error",
"code": 2691