mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #450 from Microsoft/fullTypeCheckFlag
added fullTypeCheckFlag to TypeChecker
This commit is contained in:
commit
a52cdaf806
8 files changed
+237
-174
No files matched your search
+206
-153
@@ -11,7 +11,11 @@ module ts {
|
||||
var nextNodeId = 1;
|
||||
var nextMergeId = 1;
|
||||
|
||||
export function createTypeChecker(program: Program): TypeChecker {
|
||||
/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
|
||||
/// If fullTypeCheck === true - then typechecker should do every possible check to produce all errors
|
||||
/// If fullTypeCheck === false - typechecker can shortcut and skip checks that only produce errors.
|
||||
/// NOTE: checks that somehow affects decisions being made during typechecking should be executed in both cases.
|
||||
export function createTypeChecker(program: Program, fullTypeCheck: boolean): TypeChecker {
|
||||
|
||||
var Symbol = objectAllocator.getSymbolConstructor();
|
||||
var Type = objectAllocator.getTypeConstructor();
|
||||
@@ -57,7 +61,6 @@ module ts {
|
||||
var globalRegExpType: ObjectType;
|
||||
|
||||
var stringLiteralTypes: Map<StringLiteralType> = {};
|
||||
|
||||
var emitExtends = false;
|
||||
|
||||
var mergedSymbols: Symbol[] = [];
|
||||
@@ -1319,7 +1322,7 @@ module ts {
|
||||
return type;
|
||||
|
||||
function checkImplicitAny(type: Type) {
|
||||
if (!program.getCompilerOptions().noImplicitAny) {
|
||||
if (!fullTypeCheck || !program.getCompilerOptions().noImplicitAny) {
|
||||
return;
|
||||
}
|
||||
// We need to have ended up with 'any', 'any[]', 'any[][]', etc.
|
||||
@@ -4067,7 +4070,7 @@ module ts {
|
||||
var typeArgNode = typeArguments[i];
|
||||
var typeArgument = getTypeFromTypeNode(typeArgNode);
|
||||
var constraint = getConstraintOfTypeParameter(typeParameters[i]);
|
||||
if (constraint) {
|
||||
if (constraint && fullTypeCheck) {
|
||||
checkTypeAssignableTo(typeArgument, constraint, typeArgNode, Diagnostics.Type_0_does_not_satisfy_the_constraint_1_Colon, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
|
||||
}
|
||||
result.push(typeArgument);
|
||||
@@ -4283,7 +4286,7 @@ module ts {
|
||||
function checkTypeAssertion(node: TypeAssertion): Type {
|
||||
var exprType = checkExpression(node.operand);
|
||||
var targetType = getTypeFromTypeNode(node.type);
|
||||
if (targetType !== unknownType) {
|
||||
if (fullTypeCheck && targetType !== unknownType) {
|
||||
var widenedType = getWidenedType(exprType);
|
||||
if (!(isTypeAssignableTo(exprType, targetType) || isTypeAssignableTo(targetType, widenedType))) {
|
||||
checkTypeAssignableTo(targetType, widenedType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other_Colon, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other);
|
||||
@@ -4317,7 +4320,7 @@ module ts {
|
||||
var unwidenedType = checkAndMarkExpression(func.body, contextualMapper);
|
||||
var widenedType = getWidenedType(unwidenedType);
|
||||
|
||||
if (program.getCompilerOptions().noImplicitAny && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
error(func, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeToString(widenedType));
|
||||
}
|
||||
|
||||
@@ -4339,7 +4342,7 @@ module ts {
|
||||
var widenedType = getWidenedType(commonType);
|
||||
|
||||
// Check and report for noImplicitAny if the best common type implicitly gets widened to an 'any'/arrays-of-'any' type.
|
||||
if (program.getCompilerOptions().noImplicitAny && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && widenedType !== commonType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
var typeName = typeToString(widenedType);
|
||||
|
||||
if (func.name) {
|
||||
@@ -4419,6 +4422,10 @@ module ts {
|
||||
// must have at least one return statement somewhere in its body.
|
||||
// An exception to this rule is if the function implementation consists of a single 'throw' statement.
|
||||
function checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(func: FunctionDeclaration, returnType: Type): void {
|
||||
if (!fullTypeCheck) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Functions that return 'void' or 'any' don't need any return expressions.
|
||||
if (returnType === voidType || returnType === anyType) {
|
||||
return;
|
||||
@@ -4477,7 +4484,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
|
||||
if (fullTypeCheck && !(links.flags & NodeCheckFlags.TypeChecked)) {
|
||||
checkSignatureDeclaration(node);
|
||||
if (node.type) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
|
||||
@@ -4722,7 +4729,7 @@ module ts {
|
||||
}
|
||||
|
||||
function checkAssignmentOperator(valueType: Type): void {
|
||||
if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
|
||||
if (fullTypeCheck && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
|
||||
// TypeScript 1.0 spec (April 2014): 4.17
|
||||
// An assignment of the form
|
||||
// VarExpr = ValueExpr
|
||||
@@ -4836,28 +4843,32 @@ module ts {
|
||||
// DECLARATION AND STATEMENT TYPE CHECKING
|
||||
|
||||
function checkTypeParameter(node: TypeParameterDeclaration) {
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
|
||||
checkSourceElement(node.constraint);
|
||||
checkTypeParameterHasIllegalReferencesInConstraint(node);
|
||||
if (fullTypeCheck) {
|
||||
checkTypeParameterHasIllegalReferencesInConstraint(node);
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Type_parameter_name_cannot_be_0);
|
||||
}
|
||||
// TODO: Check multiple declarations are identical
|
||||
}
|
||||
|
||||
function checkParameter(parameterDeclaration: ParameterDeclaration) {
|
||||
checkVariableDeclaration(parameterDeclaration);
|
||||
|
||||
checkCollisionWithIndexVariableInGeneratedCode(parameterDeclaration, parameterDeclaration.name);
|
||||
if (fullTypeCheck) {
|
||||
checkCollisionWithIndexVariableInGeneratedCode(parameterDeclaration, parameterDeclaration.name);
|
||||
|
||||
if (parameterDeclaration.flags & (NodeFlags.Public | NodeFlags.Private) && !(parameterDeclaration.parent.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>parameterDeclaration.parent).body)) {
|
||||
error(parameterDeclaration, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
|
||||
}
|
||||
if (parameterDeclaration.flags & NodeFlags.Rest) {
|
||||
if (!isArrayType(getTypeOfSymbol(parameterDeclaration.symbol))) {
|
||||
error(parameterDeclaration, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
|
||||
if (parameterDeclaration.flags & (NodeFlags.Public | NodeFlags.Private) && !(parameterDeclaration.parent.kind === SyntaxKind.Constructor && (<ConstructorDeclaration>parameterDeclaration.parent).body)) {
|
||||
error(parameterDeclaration, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (parameterDeclaration.initializer && !(<FunctionDeclaration>parameterDeclaration.parent).body) {
|
||||
error(parameterDeclaration, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
|
||||
if (parameterDeclaration.flags & NodeFlags.Rest) {
|
||||
if (!isArrayType(getTypeOfSymbol(parameterDeclaration.symbol))) {
|
||||
error(parameterDeclaration, Diagnostics.A_rest_parameter_must_be_of_an_array_type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (parameterDeclaration.initializer && !(<FunctionDeclaration>parameterDeclaration.parent).body) {
|
||||
error(parameterDeclaration, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4901,18 +4912,19 @@ module ts {
|
||||
if (node.type) {
|
||||
checkSourceElement(node.type);
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithArgumentsInGeneratedCode(node);
|
||||
if (program.getCompilerOptions().noImplicitAny && !node.type) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ConstructSignature:
|
||||
error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
|
||||
break;
|
||||
case SyntaxKind.CallSignature:
|
||||
error(node, Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
|
||||
break;
|
||||
if (fullTypeCheck) {
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkCollisionWithArgumentsInGeneratedCode(node);
|
||||
if (program.getCompilerOptions().noImplicitAny && !node.type) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ConstructSignature:
|
||||
error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
|
||||
break;
|
||||
case SyntaxKind.CallSignature:
|
||||
error(node, Diagnostics.Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4989,6 +5001,10 @@ module ts {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fullTypeCheck) {
|
||||
return;
|
||||
}
|
||||
|
||||
function isSuperCallExpression(n: Node): boolean {
|
||||
return n.kind === SyntaxKind.CallExpression && (<CallExpression>n).func.kind === SyntaxKind.SuperKeyword;
|
||||
}
|
||||
@@ -5053,29 +5069,31 @@ module ts {
|
||||
}
|
||||
|
||||
function checkAccessorDeclaration(node: AccessorDeclaration) {
|
||||
if (node.kind === SyntaxKind.GetAccessor) {
|
||||
if (!isInAmbientContext(node) && node.body && !(bodyContainsAReturnStatement(<Block>node.body) || bodyContainsSingleThrowStatement(<Block>node.body))) {
|
||||
error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
|
||||
}
|
||||
}
|
||||
|
||||
// TypeScript 1.0 spec (April 2014): 8.4.3
|
||||
// Accessors for the same member name must specify the same accessibility.
|
||||
var otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
|
||||
var otherAccessor = <AccessorDeclaration>getDeclarationOfKind(node.symbol, otherKind);
|
||||
if (otherAccessor) {
|
||||
var visibilityFlags = NodeFlags.Private | NodeFlags.Public;
|
||||
if (((node.flags & visibilityFlags) !== (otherAccessor.flags & visibilityFlags))) {
|
||||
error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
|
||||
if (fullTypeCheck) {
|
||||
if (node.kind === SyntaxKind.GetAccessor) {
|
||||
if (!isInAmbientContext(node) && node.body && !(bodyContainsAReturnStatement(<Block>node.body) || bodyContainsSingleThrowStatement(<Block>node.body))) {
|
||||
error(node.name, Diagnostics.A_get_accessor_must_return_a_value_or_consist_of_a_single_throw_statement);
|
||||
}
|
||||
}
|
||||
|
||||
var thisType = getAnnotatedAccessorType(node);
|
||||
var otherType = getAnnotatedAccessorType(otherAccessor);
|
||||
// TypeScript 1.0 spec (April 2014): 4.5
|
||||
// If both accessors include type annotations, the specified types must be identical.
|
||||
if (thisType && otherType) {
|
||||
if (!isTypeIdenticalTo(thisType, otherType)) {
|
||||
error(node, Diagnostics.get_and_set_accessor_must_have_the_same_type);
|
||||
// TypeScript 1.0 spec (April 2014): 8.4.3
|
||||
// Accessors for the same member name must specify the same accessibility.
|
||||
var otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor;
|
||||
var otherAccessor = <AccessorDeclaration>getDeclarationOfKind(node.symbol, otherKind);
|
||||
if (otherAccessor) {
|
||||
var visibilityFlags = NodeFlags.Private | NodeFlags.Public;
|
||||
if (((node.flags & visibilityFlags) !== (otherAccessor.flags & visibilityFlags))) {
|
||||
error(node.name, Diagnostics.Getter_and_setter_accessors_do_not_agree_in_visibility);
|
||||
}
|
||||
|
||||
var thisType = getAnnotatedAccessorType(node);
|
||||
var otherType = getAnnotatedAccessorType(otherAccessor);
|
||||
// TypeScript 1.0 spec (April 2014): 4.5
|
||||
// If both accessors include type annotations, the specified types must be identical.
|
||||
if (thisType && otherType) {
|
||||
if (!isTypeIdenticalTo(thisType, otherType)) {
|
||||
error(node, Diagnostics.get_and_set_accessor_must_have_the_same_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5092,7 +5110,7 @@ module ts {
|
||||
for (var i = 0; i < len; i++) {
|
||||
checkSourceElement(node.typeArguments[i]);
|
||||
var constraint = getConstraintOfTypeParameter((<TypeReference>type).target.typeParameters[i]);
|
||||
if (constraint) {
|
||||
if (fullTypeCheck && constraint) {
|
||||
var typeArgument = (<TypeReference>type).typeArguments[i];
|
||||
checkTypeAssignableTo(typeArgument, constraint, node, Diagnostics.Type_0_does_not_satisfy_the_constraint_1_Colon, Diagnostics.Type_0_does_not_satisfy_the_constraint_1);
|
||||
}
|
||||
@@ -5106,9 +5124,11 @@ module ts {
|
||||
|
||||
function checkTypeLiteral(node: TypeLiteralNode) {
|
||||
forEach(node.members, checkSourceElement);
|
||||
var type = getTypeFromTypeLiteralNode(node);
|
||||
checkIndexConstraints(type);
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
if (fullTypeCheck) {
|
||||
var type = getTypeFromTypeLiteralNode(node);
|
||||
checkIndexConstraints(type);
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
}
|
||||
}
|
||||
|
||||
function checkArrayType(node: ArrayTypeNode) {
|
||||
@@ -5120,6 +5140,9 @@ module ts {
|
||||
}
|
||||
|
||||
function checkSpecializedSignatureDeclaration(signatureDeclarationNode: SignatureDeclaration): void {
|
||||
if (!fullTypeCheck) {
|
||||
return;
|
||||
}
|
||||
var signature = getSignatureFromDeclaration(signatureDeclarationNode);
|
||||
if (!signature.hasStringLiterals) {
|
||||
return;
|
||||
@@ -5173,7 +5196,10 @@ module ts {
|
||||
return flags & flagsToCheck;
|
||||
}
|
||||
|
||||
function checkFunctionOrConstructorSymbol(symbol: Symbol) {
|
||||
function checkFunctionOrConstructorSymbol(symbol: Symbol): void {
|
||||
if (!fullTypeCheck) {
|
||||
return;
|
||||
}
|
||||
|
||||
function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void {
|
||||
// Error if some overloads have a flag that is not shared by all overloads. To find the
|
||||
@@ -5343,7 +5369,11 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkExportsOnMergedDeclarations(node: Node) {
|
||||
function checkExportsOnMergedDeclarations(node: Node): void {
|
||||
if (!fullTypeCheck) {
|
||||
return;
|
||||
}
|
||||
|
||||
var symbol: Symbol;
|
||||
|
||||
// Exports should be checked only if enclosing module contains both exported and non exported declarations.
|
||||
@@ -5413,7 +5443,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkFunctionDeclaration(node: FunctionDeclaration) {
|
||||
function checkFunctionDeclaration(node: FunctionDeclaration): void {
|
||||
checkSignatureDeclaration(node);
|
||||
|
||||
var symbol = getSymbolOfNode(node);
|
||||
@@ -5442,7 +5472,7 @@ module ts {
|
||||
}
|
||||
|
||||
// If there is no body and no explicit return type, then report an error.
|
||||
if (program.getCompilerOptions().noImplicitAny && !node.body && !node.type) {
|
||||
if (fullTypeCheck && program.getCompilerOptions().noImplicitAny && !node.body && !node.type) {
|
||||
// Ignore privates within ambient contexts; they exist purely for documentative purposes to avoid name clashing.
|
||||
// (e.g. privates within .d.ts files do not expose type information)
|
||||
if (!isPrivateWithinAmbient(node)) {
|
||||
@@ -5629,36 +5659,38 @@ module ts {
|
||||
|
||||
function checkVariableDeclaration(node: VariableDeclaration) {
|
||||
checkSourceElement(node.type);
|
||||
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
|
||||
var symbol = getSymbolOfNode(node);
|
||||
|
||||
var typeOfValueDeclaration = getTypeOfVariableOrParameterOrProperty(symbol);
|
||||
var type: Type;
|
||||
var useTypeFromValueDeclaration = node === symbol.valueDeclaration;
|
||||
if (useTypeFromValueDeclaration) {
|
||||
type = typeOfValueDeclaration;
|
||||
}
|
||||
else {
|
||||
type = getTypeOfVariableDeclaration(node);
|
||||
}
|
||||
if (fullTypeCheck) {
|
||||
var symbol = getSymbolOfNode(node);
|
||||
|
||||
if (node.initializer) {
|
||||
if (!(getNodeLinks(node.initializer).flags & NodeCheckFlags.TypeChecked)) {
|
||||
// Use default messages
|
||||
checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
|
||||
var typeOfValueDeclaration = getTypeOfVariableOrParameterOrProperty(symbol);
|
||||
var type: Type;
|
||||
var useTypeFromValueDeclaration = node === symbol.valueDeclaration;
|
||||
if (useTypeFromValueDeclaration) {
|
||||
type = typeOfValueDeclaration;
|
||||
}
|
||||
else {
|
||||
type = getTypeOfVariableDeclaration(node);
|
||||
}
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
if (!useTypeFromValueDeclaration) {
|
||||
// TypeScript 1.0 spec (April 2014): 5.1
|
||||
// Multiple declarations for the same variable name in the same declaration space are permitted,
|
||||
// provided that each declaration associates the same type with the variable.
|
||||
if (typeOfValueDeclaration !== unknownType && type !== unknownType && !isTypeIdenticalTo(typeOfValueDeclaration, type)) {
|
||||
error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, identifierToString(node.name), typeToString(typeOfValueDeclaration), typeToString(type));
|
||||
|
||||
if (node.initializer) {
|
||||
if (!(getNodeLinks(node.initializer).flags & NodeCheckFlags.TypeChecked)) {
|
||||
// Use default messages
|
||||
checkTypeAssignableTo(checkAndMarkExpression(node.initializer), type, node, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
|
||||
checkCollisionWithCapturedSuperVariable(node, node.name);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
if (!useTypeFromValueDeclaration) {
|
||||
// TypeScript 1.0 spec (April 2014): 5.1
|
||||
// Multiple declarations for the same variable name in the same declaration space are permitted,
|
||||
// provided that each declaration associates the same type with the variable.
|
||||
if (typeOfValueDeclaration !== unknownType && type !== unknownType && !isTypeIdenticalTo(typeOfValueDeclaration, type)) {
|
||||
error(node.name, Diagnostics.Subsequent_variable_declarations_must_have_the_same_type_Variable_0_must_be_of_type_1_but_here_has_type_2, identifierToString(node.name), typeToString(typeOfValueDeclaration), typeToString(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5790,7 +5822,7 @@ module ts {
|
||||
function checkSwitchStatement(node: SwitchStatement) {
|
||||
var expressionType = checkExpression(node.expression);
|
||||
forEach(node.clauses, clause => {
|
||||
if (clause.expression) {
|
||||
if (fullTypeCheck && clause.expression) {
|
||||
// TypeScript 1.0 spec (April 2014):5.9
|
||||
// In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression.
|
||||
var caseType = checkExpression(clause.expression);
|
||||
@@ -5905,9 +5937,12 @@ module ts {
|
||||
for (var i = 0; i < typeParameterDeclarations.length; i++) {
|
||||
var node = typeParameterDeclarations[i];
|
||||
checkTypeParameter(node);
|
||||
for (var j = 0; j < i; j++) {
|
||||
if (typeParameterDeclarations[j].symbol === node.symbol) {
|
||||
error(node.name, Diagnostics.Duplicate_identifier_0, identifierToString(node.name));
|
||||
|
||||
if (fullTypeCheck) {
|
||||
for (var j = 0; j < i; j++) {
|
||||
if (typeParameterDeclarations[j].symbol === node.symbol) {
|
||||
error(node.name, Diagnostics.Duplicate_identifier_0, identifierToString(node.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5927,39 +5962,45 @@ module ts {
|
||||
checkTypeReference(node.baseType);
|
||||
}
|
||||
if (type.baseTypes.length) {
|
||||
var baseType = type.baseTypes[0];
|
||||
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1_Colon, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
var staticBaseType = getTypeOfSymbol(baseType.symbol);
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1_Colon, Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
if (baseType.symbol !== resolveEntityName(node, node.baseType.typeName, SymbolFlags.Value)) {
|
||||
error(node.baseType, Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
|
||||
if (fullTypeCheck) {
|
||||
var baseType = type.baseTypes[0];
|
||||
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Class_0_incorrectly_extends_base_class_1_Colon, Diagnostics.Class_0_incorrectly_extends_base_class_1);
|
||||
var staticBaseType = getTypeOfSymbol(baseType.symbol);
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1_Colon, Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
if (baseType.symbol !== resolveEntityName(node, node.baseType.typeName, SymbolFlags.Value)) {
|
||||
error(node.baseType, Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
|
||||
}
|
||||
|
||||
checkKindsOfPropertyMemberOverrides(type, baseType);
|
||||
}
|
||||
|
||||
// Check that base type can be evaluated as expression
|
||||
checkExpression(node.baseType.typeName);
|
||||
|
||||
checkKindsOfPropertyMemberOverrides(type, baseType);
|
||||
}
|
||||
if (node.implementedTypes) {
|
||||
forEach(node.implementedTypes, typeRefNode => {
|
||||
checkTypeReference(typeRefNode);
|
||||
var t = getTypeFromTypeReferenceNode(typeRefNode);
|
||||
if (t !== unknownType) {
|
||||
var declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
|
||||
if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
checkTypeAssignableTo(type, t, node.name, Diagnostics.Class_0_incorrectly_implements_interface_1_Colon, Diagnostics.Class_0_incorrectly_implements_interface_1);
|
||||
}
|
||||
else {
|
||||
error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
|
||||
if (fullTypeCheck) {
|
||||
var t = getTypeFromTypeReferenceNode(typeRefNode);
|
||||
if (t !== unknownType) {
|
||||
var declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
|
||||
if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
checkTypeAssignableTo(type, t, node.name, Diagnostics.Class_0_incorrectly_implements_interface_1_Colon, Diagnostics.Class_0_incorrectly_implements_interface_1);
|
||||
}
|
||||
else {
|
||||
error(typeRefNode, Diagnostics.A_class_may_only_implement_another_class_or_interface);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
checkIndexConstraints(type);
|
||||
forEach(node.members, checkSourceElement);
|
||||
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
forEach(node.members, checkSourceElement);
|
||||
if (fullTypeCheck) {
|
||||
checkIndexConstraints(type);
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
}
|
||||
}
|
||||
|
||||
function getTargetSymbol(s: Symbol) {
|
||||
@@ -6071,32 +6112,37 @@ module ts {
|
||||
}
|
||||
|
||||
function checkInterfaceDeclaration(node: InterfaceDeclaration) {
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
|
||||
checkTypeParameters(node.typeParameters);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
var symbol = getSymbolOfNode(node);
|
||||
var firstInterfaceDecl = <InterfaceDeclaration>getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration);
|
||||
if (symbol.declarations.length > 1) {
|
||||
if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
|
||||
error(node.name, Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
|
||||
}
|
||||
}
|
||||
if (fullTypeCheck) {
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0);
|
||||
|
||||
// Only check this symbol once
|
||||
if (node === firstInterfaceDecl) {
|
||||
var type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
|
||||
// run subsequent checks only if first set succeeded
|
||||
if (checkInheritedPropertiesAreIdentical(type, node.name)) {
|
||||
forEach(type.baseTypes, baseType => {
|
||||
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1_Colon, Diagnostics.Interface_0_incorrectly_extends_interface_1);
|
||||
});
|
||||
checkIndexConstraints(type);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
var symbol = getSymbolOfNode(node);
|
||||
var firstInterfaceDecl = <InterfaceDeclaration>getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration);
|
||||
if (symbol.declarations.length > 1) {
|
||||
if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) {
|
||||
error(node.name, Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters);
|
||||
}
|
||||
}
|
||||
|
||||
// Only check this symbol once
|
||||
if (node === firstInterfaceDecl) {
|
||||
var type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
|
||||
// run subsequent checks only if first set succeeded
|
||||
if (checkInheritedPropertiesAreIdentical(type, node.name)) {
|
||||
forEach(type.baseTypes, baseType => {
|
||||
checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1_Colon, Diagnostics.Interface_0_incorrectly_extends_interface_1);
|
||||
});
|
||||
checkIndexConstraints(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
forEach(node.baseTypes, checkTypeReference);
|
||||
forEach(node.members, checkSourceElement);
|
||||
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
if (fullTypeCheck) {
|
||||
checkTypeForDuplicateIndexSignatures(node);
|
||||
}
|
||||
}
|
||||
|
||||
function getConstantValue(node: Expression): number {
|
||||
@@ -6117,6 +6163,9 @@ module ts {
|
||||
}
|
||||
|
||||
function checkEnumDeclaration(node: EnumDeclaration) {
|
||||
if (!fullTypeCheck) {
|
||||
return;
|
||||
}
|
||||
checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0);
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
@@ -6190,26 +6239,28 @@ module ts {
|
||||
}
|
||||
|
||||
function checkModuleDeclaration(node: ModuleDeclaration) {
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
var symbol = getSymbolOfNode(node);
|
||||
if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) {
|
||||
var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
|
||||
if (classOrFunc) {
|
||||
if (getSourceFileOfNode(node) !== getSourceFileOfNode(classOrFunc)) {
|
||||
error(node.name, Diagnostics.A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
|
||||
}
|
||||
else if (node.pos < classOrFunc.pos) {
|
||||
error(node.name, Diagnostics.A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
|
||||
if (fullTypeCheck) {
|
||||
checkCollisionWithCapturedThisVariable(node, node.name);
|
||||
checkExportsOnMergedDeclarations(node);
|
||||
var symbol = getSymbolOfNode(node);
|
||||
if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) {
|
||||
var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol);
|
||||
if (classOrFunc) {
|
||||
if (getSourceFileOfNode(node) !== getSourceFileOfNode(classOrFunc)) {
|
||||
error(node.name, Diagnostics.A_module_declaration_cannot_be_in_a_different_file_from_a_class_or_function_with_which_it_is_merged);
|
||||
}
|
||||
else if (node.pos < classOrFunc.pos) {
|
||||
error(node.name, Diagnostics.A_module_declaration_cannot_be_located_prior_to_a_class_or_function_with_which_it_is_merged);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.name.kind === SyntaxKind.StringLiteral) {
|
||||
if (!isGlobalSourceFile(node.parent)) {
|
||||
error(node.name, Diagnostics.Ambient_external_modules_cannot_be_nested_in_other_modules);
|
||||
}
|
||||
if (isExternalModuleNameRelative(node.name.text)) {
|
||||
error(node.name, Diagnostics.Ambient_external_module_declaration_cannot_specify_relative_module_name);
|
||||
if (node.name.kind === SyntaxKind.StringLiteral) {
|
||||
if (!isGlobalSourceFile(node.parent)) {
|
||||
error(node.name, Diagnostics.Ambient_external_modules_cannot_be_nested_in_other_modules);
|
||||
}
|
||||
if (isExternalModuleNameRelative(node.name.text)) {
|
||||
error(node.name, Diagnostics.Ambient_external_module_declaration_cannot_specify_relative_module_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
checkSourceElement(node.body);
|
||||
@@ -6370,8 +6421,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Fully type check a source file and collect the relevant diagnostics. The fullTypeCheck flag is true during this
|
||||
// operation, but otherwise is false when the compiler is used by the language service.
|
||||
// Fully type check a source file and collect the relevant diagnostics.
|
||||
function checkSourceFile(node: SourceFile) {
|
||||
var links = getNodeLinks(node);
|
||||
if (!(links.flags & NodeCheckFlags.TypeChecked)) {
|
||||
@@ -6398,7 +6448,9 @@ module ts {
|
||||
forEach(program.getSourceFiles(), checkSourceFile);
|
||||
}
|
||||
|
||||
function getSortedDiagnostics(): Diagnostic[] {
|
||||
function getSortedDiagnostics(): Diagnostic[]{
|
||||
Debug.assert(fullTypeCheck, "diagnostics are available only in the full typecheck mode");
|
||||
|
||||
if (diagnosticsModified) {
|
||||
diagnostics.sort(compareDiagnostics);
|
||||
diagnostics = deduplicateSortedDiagnostics(diagnostics);
|
||||
@@ -6407,7 +6459,8 @@ module ts {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[] {
|
||||
function getDiagnostics(sourceFile?: SourceFile): Diagnostic[]{
|
||||
|
||||
if (sourceFile) {
|
||||
checkSourceFile(sourceFile);
|
||||
return filter(getSortedDiagnostics(), d => d.file === sourceFile);
|
||||
|
||||
@@ -3582,7 +3582,7 @@ module ts {
|
||||
getCompilerHost: () => host,
|
||||
getDiagnostics: getDiagnostics,
|
||||
getGlobalDiagnostics: getGlobalDiagnostics,
|
||||
getTypeChecker: () => createTypeChecker(program),
|
||||
getTypeChecker: fullTypeCheckMode => createTypeChecker(program, fullTypeCheckMode),
|
||||
getCommonSourceDirectory: () => commonSourceDirectory,
|
||||
};
|
||||
return program;
|
||||
|
||||
+1
-1
@@ -326,7 +326,7 @@ module ts {
|
||||
var reportStart = bindStart;
|
||||
}
|
||||
else {
|
||||
var checker = program.getTypeChecker();
|
||||
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
|
||||
var checkStart = new Date().getTime();
|
||||
var semanticErrors = checker.getDiagnostics();
|
||||
var emitStart = new Date().getTime();
|
||||
|
||||
@@ -537,7 +537,7 @@ module ts {
|
||||
getCompilerHost(): CompilerHost;
|
||||
getDiagnostics(sourceFile?: SourceFile): Diagnostic[];
|
||||
getGlobalDiagnostics(): Diagnostic[];
|
||||
getTypeChecker(): TypeChecker;
|
||||
getTypeChecker(fullTypeCheckMode: boolean): TypeChecker;
|
||||
getCommonSourceDirectory(): string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1904,7 +1904,7 @@ module FourSlash {
|
||||
|
||||
var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents);
|
||||
var program = ts.createProgram([fourslashFilename, fileName], { out: "fourslashTestOutput.js" }, host);
|
||||
var checker = ts.createTypeChecker(program);
|
||||
var checker = ts.createTypeChecker(program, /*fullTypeCheckMode*/ true);
|
||||
checker.checkProgram();
|
||||
|
||||
var errs = checker.getDiagnostics(files[fileName]);
|
||||
|
||||
@@ -736,7 +736,7 @@ module Harness {
|
||||
|
||||
var hadParseErrors = program.getDiagnostics().length > 0;
|
||||
|
||||
var checker = program.getTypeChecker();
|
||||
var checker = program.getTypeChecker(/*fullTypeCheckMode*/ true);
|
||||
checker.checkProgram();
|
||||
|
||||
// only emit if there weren't parse errors
|
||||
|
||||
@@ -129,7 +129,7 @@ class ProjectRunner extends RunnerBase {
|
||||
var errors = program.getDiagnostics();
|
||||
var sourceMapData: ts.SourceMapData[] = null;
|
||||
if (!errors.length) {
|
||||
var checker = program.getTypeChecker();
|
||||
var checker = program.getTypeChecker(/*fullTypeCheck*/ true);
|
||||
errors = checker.getDiagnostics();
|
||||
var emitResult = checker.emitFiles();
|
||||
errors = ts.concatenate(errors, emitResult.errors);
|
||||
|
||||
+25
-15
@@ -1256,7 +1256,11 @@ module ts {
|
||||
var formattingRulesProvider: TypeScript.Services.Formatting.RulesProvider;
|
||||
var hostCache: HostCache; // A cache of all the information about the files on the host side.
|
||||
var program: Program;
|
||||
var typeChecker: TypeChecker;
|
||||
// this checker is used to answer all LS questions except errors
|
||||
var typeInfoResolver: TypeChecker;
|
||||
// the sole purpose of this checkes is to reutrn semantic diagnostics
|
||||
// creation is deferred - use getFullTypeCheckChecker to get instance
|
||||
var fullTypeCheckChecker_doNotAccessDirectly: TypeChecker;
|
||||
var useCaseSensitivefilenames = false;
|
||||
var sourceFilesByName: Map<SourceFile> = {};
|
||||
var documentRegistry = documentRegistry;
|
||||
@@ -1272,6 +1276,10 @@ module ts {
|
||||
return lookUp(sourceFilesByName, filename);
|
||||
}
|
||||
|
||||
function getFullTypeCheckChecker() {
|
||||
return fullTypeCheckChecker_doNotAccessDirectly || (fullTypeCheckChecker_doNotAccessDirectly = program.getTypeChecker(/*fullTypeCheck*/ true));
|
||||
}
|
||||
|
||||
function createCompilerHost(): CompilerHost {
|
||||
return {
|
||||
getSourceFile: (filename, languageVersion) => {
|
||||
@@ -1403,7 +1411,8 @@ module ts {
|
||||
|
||||
// Now create a new compiler
|
||||
program = createProgram(hostfilenames, compilationSettings, createCompilerHost());
|
||||
typeChecker = program.getTypeChecker();
|
||||
typeInfoResolver = program.getTypeChecker(/*fullTypeCheckMode*/ false);
|
||||
fullTypeCheckChecker_doNotAccessDirectly = undefined;
|
||||
}
|
||||
|
||||
/// Clean up any semantic caches that are not needed.
|
||||
@@ -1411,7 +1420,8 @@ module ts {
|
||||
/// We will just dump the typeChecker and recreate a new one. this should have the effect of destroying all the semantic caches.
|
||||
function cleanupSemanticCache(): void {
|
||||
if (program) {
|
||||
typeChecker = program.getTypeChecker();
|
||||
typeInfoResolver = program.getTypeChecker(/*fullTypeCheckMode*/ false);
|
||||
fullTypeCheckChecker_doNotAccessDirectly = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1436,7 +1446,7 @@ module ts {
|
||||
|
||||
filename = TypeScript.switchToForwardSlashes(filename)
|
||||
|
||||
return typeChecker.getDiagnostics(getSourceFile(filename).getSourceFile());
|
||||
return getFullTypeCheckChecker().getDiagnostics(getSourceFile(filename));
|
||||
}
|
||||
|
||||
function getCompilerOptionsDiagnostics() {
|
||||
@@ -1678,12 +1688,12 @@ module ts {
|
||||
entries: [],
|
||||
symbols: {},
|
||||
location: mappedNode,
|
||||
typeChecker: typeChecker
|
||||
typeChecker: typeInfoResolver
|
||||
};
|
||||
|
||||
// Right of dot member completion list
|
||||
if (isRightOfDot) {
|
||||
var type: Type = typeChecker.getTypeOfExpression(mappedNode);
|
||||
var type: Type = typeInfoResolver.getTypeOfExpression(mappedNode);
|
||||
if (!type) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -1731,7 +1741,7 @@ module ts {
|
||||
isMemberCompletion = false;
|
||||
/// TODO filter meaning based on the current context
|
||||
var symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace;
|
||||
var symbols = typeChecker.getSymbolsInScope(mappedNode, symbolMeanings);
|
||||
var symbols = typeInfoResolver.getSymbolsInScope(mappedNode, symbolMeanings);
|
||||
|
||||
getCompletionEntriesFromSymbols(symbols, activeCompletionSession);
|
||||
}
|
||||
@@ -1770,7 +1780,7 @@ module ts {
|
||||
kind: completionEntry.kind,
|
||||
kindModifiers: completionEntry.kindModifiers,
|
||||
type: session.typeChecker.typeToString(type, session.location),
|
||||
fullSymbolName: typeChecker.symbolToString(symbol, session.location),
|
||||
fullSymbolName: typeInfoResolver.symbolToString(symbol, session.location),
|
||||
docComment: ""
|
||||
};
|
||||
}
|
||||
@@ -1882,13 +1892,13 @@ module ts {
|
||||
var node = getNodeAtPosition(sourceFile.getSourceFile(), position);
|
||||
if (!node) return undefined;
|
||||
|
||||
var symbol = typeChecker.getSymbolInfo(node);
|
||||
var type = symbol && typeChecker.getTypeOfSymbol(symbol);
|
||||
var symbol = typeInfoResolver.getSymbolInfo(node);
|
||||
var type = symbol && typeInfoResolver.getTypeOfSymbol(symbol);
|
||||
if (type) {
|
||||
return {
|
||||
memberName: new TypeScript.MemberNameString(typeChecker.typeToString(type)),
|
||||
memberName: new TypeScript.MemberNameString(typeInfoResolver.typeToString(type)),
|
||||
docComment: "",
|
||||
fullSymbolName: typeChecker.symbolToString(symbol, getContainerNode(node)),
|
||||
fullSymbolName: typeInfoResolver.symbolToString(symbol, getContainerNode(node)),
|
||||
kind: getSymbolKind(symbol),
|
||||
minChar: node.pos,
|
||||
limChar: node.end
|
||||
@@ -2034,7 +2044,7 @@ module ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var symbol = typeChecker.getSymbolInfo(node);
|
||||
var symbol = typeInfoResolver.getSymbolInfo(node);
|
||||
|
||||
// Could not find a symbol e.g. node is string or number keyword,
|
||||
// or the symbol was an internal symbol and does not have a declaration e.g. undefined symbol
|
||||
@@ -2045,10 +2055,10 @@ module ts {
|
||||
var result: DefinitionInfo[] = [];
|
||||
|
||||
var declarations = symbol.getDeclarations();
|
||||
var symbolName = typeChecker.symbolToString(symbol, node);
|
||||
var symbolName = typeInfoResolver.symbolToString(symbol, node);
|
||||
var symbolKind = getSymbolKind(symbol);
|
||||
var containerSymbol = symbol.parent;
|
||||
var containerName = containerSymbol ? typeChecker.symbolToString(containerSymbol, node) : "";
|
||||
var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";
|
||||
var containerKind = containerSymbol ? getSymbolKind(symbol) : "";
|
||||
|
||||
if (!tryAddConstructSignature(symbol, node, symbolKind, symbolName, containerName, result) &&
|
||||
|
||||
Reference in new issue
Block a user