Merge pull request #665 from Microsoft/circularTypeInferenceErrors

Report circular type inference errors with -noImplicitAny
This commit is contained in:
Anders Hejlsberg 2014-09-12 13:15:17 -07:00
commit b9ebb367c0
8 changed files with 272 additions and 6 deletions

View file

@ -413,7 +413,7 @@ module ts {
}
}
function getFullyQualifiedName(symbol: Symbol) {
function getFullyQualifiedName(symbol: Symbol): string {
return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
}
@ -1420,6 +1420,12 @@ module ts {
}
else if (links.type === resolvingType) {
links.type = anyType;
if (compilerOptions.noImplicitAny) {
var diagnostic = (<VariableDeclaration>symbol.valueDeclaration).type ?
Diagnostics._0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation :
Diagnostics._0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer;
error(symbol.valueDeclaration, diagnostic, symbolToString(symbol));
}
}
return links.type;
}
@ -1475,7 +1481,7 @@ module ts {
// Otherwise, fall back to 'any'.
else {
if (compilerOptions.noImplicitAny) {
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbol.name);
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
}
type = anyType;
@ -1489,6 +1495,10 @@ module ts {
}
else if (links.type === resolvingType) {
links.type = anyType;
if (compilerOptions.noImplicitAny) {
var getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
}
}
}
@ -1552,7 +1562,7 @@ module ts {
function hasBaseType(type: InterfaceType, checkBase: InterfaceType) {
return check(type);
function check(type: InterfaceType) {
function check(type: InterfaceType): boolean {
var target = <InterfaceType>getTargetType(type);
return target === checkBase || forEach(target.baseTypes, check);
}
@ -2036,6 +2046,15 @@ module ts {
}
else if (signature.resolvedReturnType === resolvingType) {
signature.resolvedReturnType = anyType;
if (compilerOptions.noImplicitAny) {
var declaration = <Declaration>signature.declaration;
if (declaration.name) {
error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, identifierToString(declaration.name));
}
else {
error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions);
}
}
}
return signature.resolvedReturnType;
}
@ -6587,7 +6606,7 @@ module ts {
// Language service support
function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
function findChildAtPosition(parent: Node) {
function findChildAtPosition(parent: Node): Node {
var child = forEachChild(parent, node => {
if (position >= node.pos && position <= node.end && position >= getTokenPosOfNode(node)) {
return findChildAtPosition(node);

View file

@ -390,6 +390,10 @@ module ts {
Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
_0_implicitly_has_type_any_because_it_is_referenced_directly_or_indirectly_in_its_own_type_annotation: { code: 7021, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation." },
_0_implicitly_has_type_any_because_it_is_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer: { code: 7022, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer." },
_0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7023, category: DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
Function_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions: { code: 7024, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions." },
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
};
}

View file

@ -1557,6 +1557,22 @@
"category": "Error",
"code": 7020
},
"'{0}' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.": {
"category": "Error",
"code": 7021
},
"'{0}' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer.": {
"category": "Error",
"code": 7022
},
"'{0}' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.": {
"category": "Error",
"code": 7023
},
"Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.": {
"category": "Error",
"code": 7024
},
"You cannot rename this element.": {
"category": "Error",
"code": 8000

View file

@ -1973,7 +1973,7 @@ module ts {
}
}
function emitNode(node: Node) {
function emitNode(node: Node): void {
if (!node) {
return;
}

View file

@ -3533,7 +3533,7 @@ module ts {
return finishNode(node);
}
function isDeclaration() {
function isDeclaration(): boolean {
switch (token) {
case SyntaxKind.VarKeyword:
case SyntaxKind.FunctionKeyword:

View file

@ -0,0 +1,73 @@
==== tests/cases/compiler/implicitAnyFromCircularInference.ts (9 errors) ====
// Error expected
var a: typeof a;
~
!!! 'a' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.
// Error expected on b or c
var b: typeof c;
var c: typeof b;
~
!!! 'c' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.
// Error expected
var d: Array<typeof d>;
~
!!! 'd' implicitly has type 'any' because it is referenced directly or indirectly in its own type annotation.
function f() { return f; }
// Error expected
function g() { return g(); }
~
!!! 'g' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
// Error expected
var f1 = function () {
~~~~~~~~~~~~~
return f1();
~~~~~~~~~~~~~~~~
};
~
!!! Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
// Error expected
var f2 = () => f2();
~~~~~~~~~~
!!! Function implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
// Error expected
function h() {
~
!!! 'h' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
return foo();
function foo() {
return h() || "hello";
}
}
interface A {
s: string;
}
function foo(x: A): string { return "abc"; }
class C {
// Error expected
s = foo(this);
~~~~~~~~~~~~~~
!!! 's' implicitly has type 'any' because it is does not have a type annotation and is referenced directly or indirectly in its own initializer.
}
class D {
// Error expected
get x() {
~~~~~~~~~
return this.x;
~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
!!! 'x' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
}

View file

@ -0,0 +1,103 @@
//// [implicitAnyFromCircularInference.ts]
// Error expected
var a: typeof a;
// Error expected on b or c
var b: typeof c;
var c: typeof b;
// Error expected
var d: Array<typeof d>;
function f() { return f; }
// Error expected
function g() { return g(); }
// Error expected
var f1 = function () {
return f1();
};
// Error expected
var f2 = () => f2();
// Error expected
function h() {
return foo();
function foo() {
return h() || "hello";
}
}
interface A {
s: string;
}
function foo(x: A): string { return "abc"; }
class C {
// Error expected
s = foo(this);
}
class D {
// Error expected
get x() {
return this.x;
}
}
//// [implicitAnyFromCircularInference.js]
// Error expected
var a;
// Error expected on b or c
var b;
var c;
// Error expected
var d;
function f() {
return f;
}
// Error expected
function g() {
return g();
}
// Error expected
var f1 = function () {
return f1();
};
// Error expected
var f2 = function () { return f2(); };
// Error expected
function h() {
return foo();
function foo() {
return h() || "hello";
}
}
function foo(x) {
return "abc";
}
var C = (function () {
function C() {
// Error expected
this.s = foo(this);
}
return C;
})();
var D = (function () {
function D() {
}
Object.defineProperty(D.prototype, "x", {
// Error expected
get: function () {
return this.x;
},
enumerable: true,
configurable: true
});
return D;
})();

View file

@ -0,0 +1,51 @@
// @noimplicitany: true
// @target: es5
// Error expected
var a: typeof a;
// Error expected on b or c
var b: typeof c;
var c: typeof b;
// Error expected
var d: Array<typeof d>;
function f() { return f; }
// Error expected
function g() { return g(); }
// Error expected
var f1 = function () {
return f1();
};
// Error expected
var f2 = () => f2();
// Error expected
function h() {
return foo();
function foo() {
return h() || "hello";
}
}
interface A {
s: string;
}
function foo(x: A): string { return "abc"; }
class C {
// Error expected
s = foo(this);
}
class D {
// Error expected
get x() {
return this.x;
}
}