Merge pull request #665 from Microsoft/circularTypeInferenceErrors
Report circular type inference errors with -noImplicitAny
This commit is contained in:
commit
b9ebb367c0
|
@ -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);
|
||||
|
|
|
@ -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." },
|
||||
};
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -1973,7 +1973,7 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
function emitNode(node: Node) {
|
||||
function emitNode(node: Node): void {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3533,7 +3533,7 @@ module ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function isDeclaration() {
|
||||
function isDeclaration(): boolean {
|
||||
switch (token) {
|
||||
case SyntaxKind.VarKeyword:
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
103
tests/baselines/reference/implicitAnyFromCircularInference.js
Normal file
103
tests/baselines/reference/implicitAnyFromCircularInference.js
Normal 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;
|
||||
})();
|
51
tests/cases/compiler/implicitAnyFromCircularInference.ts
Normal file
51
tests/cases/compiler/implicitAnyFromCircularInference.ts
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue