From 7ed933f5c41a73adc77f8bcdd6421d81bca4d5db Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 10 Dec 2014 10:16:51 -0800 Subject: [PATCH 1/7] Type guards do no affect values of type any --- src/compiler/checker.ts | 8 ++++---- src/compiler/types.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6d913f7360c..76e0d342a62 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6422,11 +6422,11 @@ module ts { // and the right operand to be of type Any or a subtype of the 'Function' interface type. // The result is always of the Boolean primitive type. // NOTE: do not raise error if leftType is unknown as related error was already reported - if (leftType !== unknownType && !isStructuredType(leftType)) { + if (!(leftType.flags & TypeFlags.Any || isStructuredType(leftType))) { error(node.left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } // NOTE: do not raise error if right is unknown as related error was already reported - if (rightType !== unknownType && rightType !== anyType && !isTypeSubtypeOf(rightType, globalFunctionType)) { + if (!(rightType.flags & TypeFlags.Any || isTypeSubtypeOf(rightType, globalFunctionType))) { error(node.right, Diagnostics.The_right_hand_side_of_an_instanceof_expression_must_be_of_type_any_or_of_a_type_assignable_to_the_Function_interface_type); } return booleanType; @@ -6440,7 +6440,7 @@ module ts { if (leftType !== anyType && leftType !== stringType && leftType !== numberType) { error(node.left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number); } - if (!isStructuredType(rightType)) { + if (!(rightType.flags & TypeFlags.Any || isStructuredType(rightType))) { error(node.right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter); } return booleanType; @@ -7796,7 +7796,7 @@ module ts { var exprType = checkExpression(node.expression); // unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved // in this case error about missing name is already reported - do not report extra one - if (!isStructuredType(exprType) && exprType !== unknownType) { + if (!(exprType.flags & TypeFlags.Any || isStructuredType(exprType))) { error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c2d57876e6a..75b5cc644c6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1201,7 +1201,7 @@ module ts { StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, - Structured = Any | ObjectType | Union | TypeParameter + Structured = ObjectType | Union | TypeParameter } // Properties common to all types From 98c9f75e2165f5a187cbceda38972bd37423c6f2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 10 Dec 2014 10:17:48 -0800 Subject: [PATCH 2/7] Adding test case --- tests/baselines/reference/typeGuardsWithAny.js | 12 ++++++++++++ .../baselines/reference/typeGuardsWithAny.types | 17 +++++++++++++++++ .../expressions/typeGuards/typeGuardsWithAny.ts | 4 ++++ 3 files changed, 33 insertions(+) create mode 100644 tests/baselines/reference/typeGuardsWithAny.js create mode 100644 tests/baselines/reference/typeGuardsWithAny.types create mode 100644 tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts diff --git a/tests/baselines/reference/typeGuardsWithAny.js b/tests/baselines/reference/typeGuardsWithAny.js new file mode 100644 index 00000000000..628ea425185 --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.js @@ -0,0 +1,12 @@ +//// [typeGuardsWithAny.ts] +var x: any = { p: 0 }; +if (x instanceof Object) { + x.p; // No error, type any is not narrowed +} + + +//// [typeGuardsWithAny.js] +var x = { p: 0 }; +if (x instanceof Object) { + x.p; // No error, type any is not narrowed +} diff --git a/tests/baselines/reference/typeGuardsWithAny.types b/tests/baselines/reference/typeGuardsWithAny.types new file mode 100644 index 00000000000..d79f813715b --- /dev/null +++ b/tests/baselines/reference/typeGuardsWithAny.types @@ -0,0 +1,17 @@ +=== tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts === +var x: any = { p: 0 }; +>x : any +>{ p: 0 } : { p: number; } +>p : number + +if (x instanceof Object) { +>x instanceof Object : boolean +>x : any +>Object : ObjectConstructor + + x.p; // No error, type any is not narrowed +>x.p : any +>x : any +>p : any +} + diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts new file mode 100644 index 00000000000..4e58d1a4acc --- /dev/null +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts @@ -0,0 +1,4 @@ +var x: any = { p: 0 }; +if (x instanceof Object) { + x.p; // No error, type any is not narrowed +} From 35adeb8363d38a9c0b562e6c3ade5eea119df70c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 10 Dec 2014 14:25:02 -0800 Subject: [PATCH 3/7] Addressing CR feedback --- src/compiler/checker.ts | 8 ++++---- src/compiler/types.ts | 1 - tests/baselines/reference/typeGuardsWithAny.js | 10 ++++++++-- tests/baselines/reference/typeGuardsWithAny.types | 8 +++++++- .../expressions/typeGuards/typeGuardsWithAny.ts | 5 ++++- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 76e0d342a62..c3bea06c41f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4445,8 +4445,8 @@ module ts { // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { var type = getTypeOfSymbol(symbol); - // Only narrow when symbol is variable of a structured type - if (node && (symbol.flags & SymbolFlags.Variable && type.flags & TypeFlags.Structured)) { + // Only narrow when symbol is variable of an object, union, or type parameter type + if (node && symbol.flags & SymbolFlags.Variable && type.flags & (TypeFlags.ObjectType | TypeFlags.Union | TypeFlags.TypeParameter)) { loop: while (node.parent) { var child = node; node = node.parent; @@ -6400,12 +6400,12 @@ module ts { return numberType; } - // Return true if type is any, an object type, a type parameter, or a union type composed of only those kinds of types + // Return true if type an object type, a type parameter, or a union type composed of only those kinds of types function isStructuredType(type: Type): boolean { if (type.flags & TypeFlags.Union) { return !forEach((type).types, t => !isStructuredType(t)); } - return (type.flags & TypeFlags.Structured) !== 0; + return (type.flags & (TypeFlags.ObjectType | TypeFlags.TypeParameter)) !== 0; } function isConstEnumObjectType(type: Type) : boolean { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 75b5cc644c6..83a5d4a4e82 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1201,7 +1201,6 @@ module ts { StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, - Structured = ObjectType | Union | TypeParameter } // Properties common to all types diff --git a/tests/baselines/reference/typeGuardsWithAny.js b/tests/baselines/reference/typeGuardsWithAny.js index 628ea425185..56676fb6d68 100644 --- a/tests/baselines/reference/typeGuardsWithAny.js +++ b/tests/baselines/reference/typeGuardsWithAny.js @@ -1,12 +1,18 @@ //// [typeGuardsWithAny.ts] var x: any = { p: 0 }; if (x instanceof Object) { - x.p; // No error, type any is not narrowed + x.p; // No error, type any unaffected by type guard +} +else { + x.p; // No error, type any unaffected by type guard } //// [typeGuardsWithAny.js] var x = { p: 0 }; if (x instanceof Object) { - x.p; // No error, type any is not narrowed + x.p; // No error, type any unaffected by type guard +} +else { + x.p; // No error, type any unaffected by type guard } diff --git a/tests/baselines/reference/typeGuardsWithAny.types b/tests/baselines/reference/typeGuardsWithAny.types index d79f813715b..ee628c9c249 100644 --- a/tests/baselines/reference/typeGuardsWithAny.types +++ b/tests/baselines/reference/typeGuardsWithAny.types @@ -9,7 +9,13 @@ if (x instanceof Object) { >x : any >Object : ObjectConstructor - x.p; // No error, type any is not narrowed + x.p; // No error, type any unaffected by type guard +>x.p : any +>x : any +>p : any +} +else { + x.p; // No error, type any unaffected by type guard >x.p : any >x : any >p : any diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts index 4e58d1a4acc..e7e756ea8e0 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardsWithAny.ts @@ -1,4 +1,7 @@ var x: any = { p: 0 }; if (x instanceof Object) { - x.p; // No error, type any is not narrowed + x.p; // No error, type any unaffected by type guard +} +else { + x.p; // No error, type any unaffected by type guard } From c0779106793cd8783ee61158225e19b0461a6e0b Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 6 Dec 2014 23:04:17 -0800 Subject: [PATCH 4/7] added getApiVersion method to TypeScriptServicesFactory --- src/services/services.ts | 3 +++ src/services/shims.ts | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/services/services.ts b/src/services/services.ts index 980b7ecda3d..ea0639f2eff 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -14,6 +14,9 @@ /// module ts { + + export var ScriptAPIVersion = "1.4" + export interface Node { getSourceFile(): SourceFile; getChildCount(sourceFile?: SourceFile): number; diff --git a/src/services/shims.ts b/src/services/shims.ts index 5556743830f..095371f3845 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -859,6 +859,13 @@ module ts { private _shims: Shim[] = []; private documentRegistry: DocumentRegistry = createDocumentRegistry(); + /* + * Returns script API version. + */ + public getApiVersion(dummy: any): string { + return ScriptAPIVersion; + } + public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim { try { var hostAdapter = new LanguageServiceShimHostAdapter(host); From fbec3fe3c4732504cfca9a71eba479f909ea0e25 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sun, 7 Dec 2014 15:17:20 -0800 Subject: [PATCH 5/7] removed dummy parameter from getApiVersion method --- src/services/shims.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/shims.ts b/src/services/shims.ts index 095371f3845..dbbb9068429 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -862,7 +862,7 @@ module ts { /* * Returns script API version. */ - public getApiVersion(dummy: any): string { + public getApiVersion(): string { return ScriptAPIVersion; } From 0a17fc687d07591522e6fcd9a08db05cdc76a9f6 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sun, 7 Dec 2014 21:41:15 -0800 Subject: [PATCH 6/7] addressed CR feedback: rename getApiVersion to getServicesVersion --- src/services/services.ts | 2 +- src/services/shims.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index ea0639f2eff..af460ff42cf 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -15,7 +15,7 @@ module ts { - export var ScriptAPIVersion = "1.4" + export var servicesVersion = "0.4" export interface Node { getSourceFile(): SourceFile; diff --git a/src/services/shims.ts b/src/services/shims.ts index dbbb9068429..379c56796d8 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -862,8 +862,8 @@ module ts { /* * Returns script API version. */ - public getApiVersion(): string { - return ScriptAPIVersion; + public getServicesVersion(): string { + return servicesVersion; } public createLanguageServiceShim(host: LanguageServiceShimHost): LanguageServiceShim { From c3bc360c533cd3f9e3ada6ddb7493c2497ac18bb Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 10 Dec 2014 14:52:42 -0800 Subject: [PATCH 7/7] add missing property to harnessLS --- src/harness/harnessLanguageService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index d3082a17ba2..0b908d87d86 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -139,6 +139,9 @@ module Harness.LanguageService { constructor(private cancellationToken: ts.CancellationToken = CancellationToken.None) { } + public trace(s: string) { + } + public addDefaultLibrary() { this.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text); }