From f7647db7f7d0b9b48fefbc5cd56b9246289b680b Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Tue, 4 Oct 2016 06:30:05 -0700 Subject: [PATCH 01/24] Fix tests changed by #11309 --- .../reference/variableDeclarationInStrictMode1.errors.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/variableDeclarationInStrictMode1.errors.txt b/tests/baselines/reference/variableDeclarationInStrictMode1.errors.txt index 9dd9a8d41a1bf..46782aaa1d69d 100644 --- a/tests/baselines/reference/variableDeclarationInStrictMode1.errors.txt +++ b/tests/baselines/reference/variableDeclarationInStrictMode1.errors.txt @@ -1,4 +1,4 @@ -lib.d.ts(28,18): error TS2300: Duplicate identifier 'eval'. +lib.d.ts(32,18): error TS2300: Duplicate identifier 'eval'. tests/cases/compiler/variableDeclarationInStrictMode1.ts(2,5): error TS1100: Invalid use of 'eval' in strict mode. tests/cases/compiler/variableDeclarationInStrictMode1.ts(2,5): error TS2300: Duplicate identifier 'eval'. From a70624d4159e9de3f2c497d2f7ec52082fee7bf6 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Oct 2016 12:08:58 -0700 Subject: [PATCH 02/24] Add test when require is just a function in external module --- ...quireAsFunctionInExternalModule.errors.txt | 20 ++++++++++ .../requireAsFunctionInExternalModule.js | 37 +++++++++++++++++++ .../requireAsFunctionInExternalModule.ts | 16 ++++++++ 3 files changed, 73 insertions(+) create mode 100644 tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt create mode 100644 tests/baselines/reference/requireAsFunctionInExternalModule.js create mode 100644 tests/cases/compiler/requireAsFunctionInExternalModule.ts diff --git a/tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt b/tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt new file mode 100644 index 0000000000000..58e3b145f3552 --- /dev/null +++ b/tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/m2.ts(1,10): error TS2305: Module '"tests/cases/compiler/m"' has no exported member 'hello'. + + +==== tests/cases/compiler/c.js (0 errors) ==== + export default function require(a) { } + export function has(a) { return true } + +==== tests/cases/compiler/m.js (0 errors) ==== + import require, { has } from "./c" + export function hello() { } + if (has('ember-debug')) { + require('ember-debug'); + } + +==== tests/cases/compiler/m2.ts (1 errors) ==== + import { hello } from "./m"; + ~~~~~ +!!! error TS2305: Module '"tests/cases/compiler/m"' has no exported member 'hello'. + hello(); + \ No newline at end of file diff --git a/tests/baselines/reference/requireAsFunctionInExternalModule.js b/tests/baselines/reference/requireAsFunctionInExternalModule.js new file mode 100644 index 0000000000000..a8b14db31388b --- /dev/null +++ b/tests/baselines/reference/requireAsFunctionInExternalModule.js @@ -0,0 +1,37 @@ +//// [tests/cases/compiler/requireAsFunctionInExternalModule.ts] //// + +//// [c.js] +export default function require(a) { } +export function has(a) { return true } + +//// [m.js] +import require, { has } from "./c" +export function hello() { } +if (has('ember-debug')) { + require('ember-debug'); +} + +//// [m2.ts] +import { hello } from "./m"; +hello(); + + +//// [c.js] +"use strict"; +function require(a) { } +exports.__esModule = true; +exports["default"] = require; +function has(a) { return true; } +exports.has = has; +//// [m.js] +"use strict"; +var c_1 = require("./c"); +function hello() { } +exports.hello = hello; +if (c_1.has('ember-debug')) { + c_1["default"]('ember-debug'); +} +//// [m2.js] +"use strict"; +var m_1 = require("./m"); +m_1.hello(); diff --git a/tests/cases/compiler/requireAsFunctionInExternalModule.ts b/tests/cases/compiler/requireAsFunctionInExternalModule.ts new file mode 100644 index 0000000000000..1715090c329ee --- /dev/null +++ b/tests/cases/compiler/requireAsFunctionInExternalModule.ts @@ -0,0 +1,16 @@ +// @allowjs: true +// @outDir: dist +// @Filename: c.js +export default function require(a) { } +export function has(a) { return true } + +// @Filename: m.js +import require, { has } from "./c" +export function hello() { } +if (has('ember-debug')) { + require('ember-debug'); +} + +// @Filename: m2.ts +import { hello } from "./m"; +hello(); From a830c844b7846f56a785d0ed8a2e75d4bec7a14f Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 4 Oct 2016 12:25:07 -0700 Subject: [PATCH 03/24] Bind the source file as external module only if not already done Return type of require call is from external module resolution only if it doesnt resolve to local module Fixes #10931 --- src/compiler/binder.ts | 4 +- src/compiler/checker.ts | 5 ++- ...quireAsFunctionInExternalModule.errors.txt | 20 ---------- .../requireAsFunctionInExternalModule.symbols | 31 ++++++++++++++++ .../requireAsFunctionInExternalModule.types | 37 +++++++++++++++++++ 5 files changed, 75 insertions(+), 22 deletions(-) delete mode 100644 tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt create mode 100644 tests/baselines/reference/requireAsFunctionInExternalModule.symbols create mode 100644 tests/baselines/reference/requireAsFunctionInExternalModule.types diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 2fe7d30ab56af..c8785819b9e97 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2000,7 +2000,9 @@ namespace ts { function setCommonJsModuleIndicator(node: Node) { if (!file.commonJsModuleIndicator) { file.commonJsModuleIndicator = node; - bindSourceFileAsExternalModule(); + if (!file.externalModuleIndicator) { + bindSourceFileAsExternalModule(); + } } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 422f2a70dccde..1354002a29e3b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12535,7 +12535,10 @@ namespace ts { } // In JavaScript files, calls to any identifier 'require' are treated as external module imports - if (isInJavaScriptFile(node) && isRequireCall(node, /*checkArgumentIsStringLiteral*/true)) { + if (isInJavaScriptFile(node) && + isRequireCall(node, /*checkArgumentIsStringLiteral*/true) && + // Make sure require is not a local function + !resolveName(node.expression, (node.expression).text, SymbolFlags.Value | SymbolFlags.ExportValue, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) { return resolveExternalModuleTypeByLiteral(node.arguments[0]); } diff --git a/tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt b/tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt deleted file mode 100644 index 58e3b145f3552..0000000000000 --- a/tests/baselines/reference/requireAsFunctionInExternalModule.errors.txt +++ /dev/null @@ -1,20 +0,0 @@ -tests/cases/compiler/m2.ts(1,10): error TS2305: Module '"tests/cases/compiler/m"' has no exported member 'hello'. - - -==== tests/cases/compiler/c.js (0 errors) ==== - export default function require(a) { } - export function has(a) { return true } - -==== tests/cases/compiler/m.js (0 errors) ==== - import require, { has } from "./c" - export function hello() { } - if (has('ember-debug')) { - require('ember-debug'); - } - -==== tests/cases/compiler/m2.ts (1 errors) ==== - import { hello } from "./m"; - ~~~~~ -!!! error TS2305: Module '"tests/cases/compiler/m"' has no exported member 'hello'. - hello(); - \ No newline at end of file diff --git a/tests/baselines/reference/requireAsFunctionInExternalModule.symbols b/tests/baselines/reference/requireAsFunctionInExternalModule.symbols new file mode 100644 index 0000000000000..2f44d6b661184 --- /dev/null +++ b/tests/baselines/reference/requireAsFunctionInExternalModule.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/c.js === +export default function require(a) { } +>require : Symbol(require, Decl(c.js, 0, 0)) +>a : Symbol(a, Decl(c.js, 0, 32)) + +export function has(a) { return true } +>has : Symbol(has, Decl(c.js, 0, 38)) +>a : Symbol(a, Decl(c.js, 1, 20)) + +=== tests/cases/compiler/m.js === +import require, { has } from "./c" +>require : Symbol(require, Decl(m.js, 0, 6)) +>has : Symbol(has, Decl(m.js, 0, 17)) + +export function hello() { } +>hello : Symbol(hello, Decl(m.js, 0, 34)) + +if (has('ember-debug')) { +>has : Symbol(has, Decl(m.js, 0, 17)) + + require('ember-debug'); +>require : Symbol(require, Decl(m.js, 0, 6)) +} + +=== tests/cases/compiler/m2.ts === +import { hello } from "./m"; +>hello : Symbol(hello, Decl(m2.ts, 0, 8)) + +hello(); +>hello : Symbol(hello, Decl(m2.ts, 0, 8)) + diff --git a/tests/baselines/reference/requireAsFunctionInExternalModule.types b/tests/baselines/reference/requireAsFunctionInExternalModule.types new file mode 100644 index 0000000000000..2ce5f3aed3860 --- /dev/null +++ b/tests/baselines/reference/requireAsFunctionInExternalModule.types @@ -0,0 +1,37 @@ +=== tests/cases/compiler/c.js === +export default function require(a) { } +>require : (a: any) => void +>a : any + +export function has(a) { return true } +>has : (a: any) => boolean +>a : any +>true : true + +=== tests/cases/compiler/m.js === +import require, { has } from "./c" +>require : (a: any) => void +>has : (a: any) => boolean + +export function hello() { } +>hello : () => void + +if (has('ember-debug')) { +>has('ember-debug') : boolean +>has : (a: any) => boolean +>'ember-debug' : "ember-debug" + + require('ember-debug'); +>require('ember-debug') : void +>require : (a: any) => void +>'ember-debug' : "ember-debug" +} + +=== tests/cases/compiler/m2.ts === +import { hello } from "./m"; +>hello : () => void + +hello(); +>hello() : void +>hello : () => void + From c4300e017f8b2f05e591af8f6c65c43dffa96403 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 13 Oct 2016 17:53:44 -0700 Subject: [PATCH 04/24] Adds ES5 to ES3 transformer for reserved words --- Jakefile.js | 18 ++- src/compiler/transformer.ts | 5 + src/compiler/transformers/es5.ts | 83 ++++++++++ src/compiler/transformers/module/module.ts | 53 ++----- src/compiler/transformers/module/system.ts | 8 +- src/compiler/tsconfig.json | 1 + src/harness/tsconfig.json | 1 + src/services/tsconfig.json | 1 + .../allowSyntheticDefaultImports10.js | 4 +- .../baselines/reference/bluebirdStaticThis.js | 6 +- .../reference/classMethodWithKeywordName1.js | 2 +- ...constructorWithIncompleteTypeAnnotation.js | 10 +- .../baselines/reference/convertKeywordsYes.js | 144 +++++++++--------- .../destructuringParameterDeclaration6.js | 8 +- tests/baselines/reference/es6ClassTest5.js | 2 +- .../reference/fatarrowfunctionsErrors.js | 2 +- tests/baselines/reference/keywordField.js | 6 +- .../reference/keywordInJsxIdentifier.js | 4 +- .../reference/nestedClassDeclaration.js | 2 +- ...bjectBindingPatternKeywordIdentifiers01.js | 2 +- ...bjectBindingPatternKeywordIdentifiers02.js | 2 +- ...bjectBindingPatternKeywordIdentifiers03.js | 2 +- ...bjectBindingPatternKeywordIdentifiers04.js | 2 +- ...ndPropertiesErrorFromNotUsingIdentifier.js | 12 +- ...ctTypesIdentityWithConstructSignatures2.js | 2 +- ...ConstructSignaturesDifferingParamCounts.js | 2 +- ...nstructSignaturesDifferingByConstraints.js | 2 +- ...structSignaturesDifferingByConstraints2.js | 2 +- ...structSignaturesDifferingByConstraints3.js | 2 +- ...onstructSignaturesDifferingByReturnType.js | 2 +- ...nstructSignaturesDifferingByReturnType2.js | 2 +- ...tSignaturesDifferingTypeParameterCounts.js | 2 +- ...ctSignaturesDifferingTypeParameterNames.js | 2 +- ...enericConstructSignaturesOptionalParams.js | 2 +- ...nericConstructSignaturesOptionalParams2.js | 2 +- ...nericConstructSignaturesOptionalParams3.js | 2 +- .../parserErrorRecovery_ObjectLiteral2.js | 2 +- .../parserErrorRecovery_ObjectLiteral3.js | 2 +- .../parserErrorRecovery_ObjectLiteral4.js | 2 +- .../parserErrorRecovery_ObjectLiteral5.js | 2 +- .../parserExportAsFunctionIdentifier.js | 2 +- .../parserKeywordsAsIdentifierName1.js | 6 +- .../parserShorthandPropertyAssignment2.js | 2 +- .../reference/parserSuperExpression3.js | 2 +- .../prototypeOnConstructorFunctions.js | 2 +- tests/baselines/reference/reservedWords.js | 18 +-- tests/baselines/reference/reservedWords2.js | 4 +- tests/baselines/reference/super1.js | 2 +- .../reference/tsxReactEmitNesting.js | 24 +-- .../reference/typeQueryWithReservedWords.js | 4 +- 50 files changed, 270 insertions(+), 208 deletions(-) create mode 100644 src/compiler/transformers/es5.ts diff --git a/Jakefile.js b/Jakefile.js index 64a8553ef39dc..ff6a9f1bd1aab 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -70,13 +70,14 @@ var compilerSources = [ "visitor.ts", "transformers/destructuring.ts", "transformers/ts.ts", - "transformers/module/es6.ts", - "transformers/module/system.ts", - "transformers/module/module.ts", "transformers/jsx.ts", "transformers/es7.ts", - "transformers/generators.ts", "transformers/es6.ts", + "transformers/es5.ts", + "transformers/generators.ts", + "transformers/module/es6.ts", + "transformers/module/system.ts", + "transformers/module/module.ts", "transformer.ts", "sourcemap.ts", "comments.ts", @@ -104,13 +105,14 @@ var servicesSources = [ "visitor.ts", "transformers/destructuring.ts", "transformers/ts.ts", - "transformers/module/es6.ts", - "transformers/module/system.ts", - "transformers/module/module.ts", "transformers/jsx.ts", "transformers/es7.ts", - "transformers/generators.ts", "transformers/es6.ts", + "transformers/es5.ts", + "transformers/generators.ts", + "transformers/module/es6.ts", + "transformers/module/system.ts", + "transformers/module/module.ts", "transformer.ts", "sourcemap.ts", "comments.ts", diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 92407af2bb9fe..1d2df002865b7 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -3,6 +3,7 @@ /// /// /// +/// /// /// /// @@ -122,6 +123,10 @@ namespace ts { transformers.push(transformGenerators); } + if (languageVersion < ScriptTarget.ES5) { + transformers.push(transformES5); + } + return transformers; } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts new file mode 100644 index 0000000000000..9e5a72c2bad6f --- /dev/null +++ b/src/compiler/transformers/es5.ts @@ -0,0 +1,83 @@ +/// +/// + +/*@internal*/ +namespace ts { + /** + * Transforms ES5 syntax into ES3 syntax. + * + * @param context Context and state information for the transformation. + */ + export function transformES5(context: TransformationContext) { + const previousOnSubstituteNode = context.onSubstituteNode; + context.onSubstituteNode = onSubstituteNode; + context.enableSubstitution(SyntaxKind.PropertyAccessExpression); + context.enableSubstitution(SyntaxKind.PropertyAssignment); + return transformSourceFile; + + /** + * Transforms an ES5 source file to ES3. + * + * @param node A SourceFile + */ + function transformSourceFile(node: SourceFile) { + return node; + } + + /** + * Hooks node substitutions. + * + * @param emitContext The context for the emitter. + * @param node The node to substitute. + */ + function onSubstituteNode(emitContext: EmitContext, node: Node) { + node = previousOnSubstituteNode(emitContext, node); + if (isPropertyAccessExpression(node)) { + return substitutePropertyAccessExpression(node); + } + else if (isPropertyAssignment(node)) { + return substitutePropertyAssignment(node); + } + return node; + } + + /** + * Substitutes a PropertyAccessExpression whose name is a reserved word. + * + * @param node A PropertyAccessExpression + */ + function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression { + const literalName = trySubstituteReservedName(node.name); + if (literalName) { + return createElementAccess(node.expression, literalName, /*location*/ node); + } + return node; + } + + /** + * Substitutes a PropertyAssignment whose name is a reserved word. + * + * @param node A PropertyAssignment + */ + function substitutePropertyAssignment(node: PropertyAssignment): PropertyAssignment { + const literalName = isIdentifier(node.name) && trySubstituteReservedName(node.name); + if (literalName) { + return updatePropertyAssignment(node, literalName, node.initializer); + } + return node; + } + + /** + * If an identifier name is a reserved word, returns a string literal for the name. + * + * @param name An Identifier + */ + function trySubstituteReservedName(name: Identifier) { + const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(name.text) : undefined); + if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { + return createLiteral(name, /*location*/ name); + } + return undefined; + } + } +} \ No newline at end of file diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 94852616037a3..edbc0f43a68a7 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -955,39 +955,19 @@ namespace ts { const declaration = resolver.getReferencedImportDeclaration(node); if (declaration) { if (isImportClause(declaration)) { - if (languageVersion >= ScriptTarget.ES5) { - return createPropertyAccess( - getGeneratedNameForNode(declaration.parent), - createIdentifier("default"), - /*location*/ node - ); - } - else { - // TODO: ES3 transform to handle x.default -> x["default"] - return createElementAccess( - getGeneratedNameForNode(declaration.parent), - createLiteral("default"), - /*location*/ node - ); - } + return createPropertyAccess( + getGeneratedNameForNode(declaration.parent), + createIdentifier("default"), + /*location*/ node + ); } else if (isImportSpecifier(declaration)) { const name = declaration.propertyName || declaration.name; - if (name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion <= ScriptTarget.ES3) { - // TODO: ES3 transform to handle x.default -> x["default"] - return createElementAccess( - getGeneratedNameForNode(declaration.parent.parent.parent), - createLiteral(name.text), - /*location*/ node - ); - } - else { - return createPropertyAccess( - getGeneratedNameForNode(declaration.parent.parent.parent), - getSynthesizedClone(name), - /*location*/ node - ); - } + return createPropertyAccess( + getGeneratedNameForNode(declaration.parent.parent.parent), + getSynthesizedClone(name), + /*location*/ node + ); } } } @@ -1024,15 +1004,10 @@ namespace ts { function createExportAssignment(name: Identifier, value: Expression) { return createAssignment( - name.originalKeywordKind === SyntaxKind.DefaultKeyword && languageVersion === ScriptTarget.ES3 - ? createElementAccess( - createIdentifier("exports"), - createLiteral(name.text) - ) - : createPropertyAccess( - createIdentifier("exports"), - getSynthesizedClone(name) - ), + createPropertyAccess( + createIdentifier("exports"), + getSynthesizedClone(name) + ), value ); } diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 0bb188eb39069..349d035f45980 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -19,7 +19,6 @@ namespace ts { const compilerOptions = context.getCompilerOptions(); const resolver = context.getEmitResolver(); const host = context.getEmitHost(); - const languageVersion = getEmitScriptTarget(compilerOptions); const previousOnSubstituteNode = context.onSubstituteNode; const previousOnEmitNode = context.onEmitNode; context.onSubstituteNode = onSubstituteNode; @@ -1312,12 +1311,7 @@ namespace ts { return undefined; } - if (name.originalKeywordKind && languageVersion === ScriptTarget.ES3) { - return createElementAccess(importAlias, createLiteral(name.text)); - } - else { - return createPropertyAccess(importAlias, getSynthesizedClone(name)); - } + return createPropertyAccess(importAlias, getSynthesizedClone(name)); } function collectDependencyGroups(externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]) { diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index f128c994af12b..894ad9683f7ed 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -26,6 +26,7 @@ "transformers/jsx.ts", "transformers/es7.ts", "transformers/es6.ts", + "transformers/es5.ts", "transformers/generators.ts", "transformers/destructuring.ts", "transformers/module/module.ts", diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index f9d302ace81ed..ffd3f30e29364 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -28,6 +28,7 @@ "../compiler/transformers/jsx.ts", "../compiler/transformers/es7.ts", "../compiler/transformers/es6.ts", + "../compiler/transformers/es5.ts", "../compiler/transformers/generators.ts", "../compiler/transformers/destructuring.ts", "../compiler/transformers/module/module.ts", diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 58312c6f38ff3..cfad296aba27b 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -27,6 +27,7 @@ "../compiler/transformers/jsx.ts", "../compiler/transformers/es7.ts", "../compiler/transformers/es6.ts", + "../compiler/transformers/es5.ts", "../compiler/transformers/generators.ts", "../compiler/transformers/destructuring.ts", "../compiler/transformers/module/module.ts", diff --git a/tests/baselines/reference/allowSyntheticDefaultImports10.js b/tests/baselines/reference/allowSyntheticDefaultImports10.js index 746997c4c8941..396cd75b57461 100644 --- a/tests/baselines/reference/allowSyntheticDefaultImports10.js +++ b/tests/baselines/reference/allowSyntheticDefaultImports10.js @@ -13,5 +13,5 @@ Foo.default.default.foo(); //// [a.js] "use strict"; var Foo = require("./b"); -Foo.default.bar(); -Foo.default.default.foo(); +Foo["default"].bar(); +Foo["default"]["default"].foo(); diff --git a/tests/baselines/reference/bluebirdStaticThis.js b/tests/baselines/reference/bluebirdStaticThis.js index 301f32319a7b4..606f778323fdb 100644 --- a/tests/baselines/reference/bluebirdStaticThis.js +++ b/tests/baselines/reference/bluebirdStaticThis.js @@ -146,12 +146,12 @@ var x; var arr; var foo; var fooProm; -fooProm = Promise.try(Promise, function () { +fooProm = Promise["try"](Promise, function () { return foo; }); -fooProm = Promise.try(Promise, function () { +fooProm = Promise["try"](Promise, function () { return foo; }, arr); -fooProm = Promise.try(Promise, function () { +fooProm = Promise["try"](Promise, function () { return foo; }, arr, x); diff --git a/tests/baselines/reference/classMethodWithKeywordName1.js b/tests/baselines/reference/classMethodWithKeywordName1.js index 6e1faee005cc0..a7cb994bfb397 100644 --- a/tests/baselines/reference/classMethodWithKeywordName1.js +++ b/tests/baselines/reference/classMethodWithKeywordName1.js @@ -7,6 +7,6 @@ class C { var C = (function () { function C() { } - C.try = function () { }; + C["try"] = function () { }; return C; }()); diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js index 2e3190c15c825..1ee309b0eb424 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.js @@ -292,7 +292,7 @@ var TypeScriptAllInOne; (function (TypeScriptAllInOne) { var Program = (function () { function Program() { - this.case = bfs.STATEMENTS(4); + this["case"] = bfs.STATEMENTS(4); } Program.Main = function () { var args = []; @@ -305,13 +305,13 @@ var TypeScriptAllInOne; retValue = bfs.VARIABLES(); if (retValue != 0) ^= { - return: 1 + "return": 1 }; } finally { } }; - Program.prototype.if = function (retValue) { + Program.prototype["if"] = function (retValue) { if (retValue === void 0) { retValue = != 0; } return 1; ^ @@ -327,7 +327,7 @@ var TypeScriptAllInOne; return 1; } }; - Program.prototype.catch = function (e) { + Program.prototype["catch"] = function (e) { console.log(e); }; return Program; @@ -364,7 +364,7 @@ var BasicFeatures = (function () { ; var quoted = '"', quoted2 = "'"; var reg = /\w*/; - var objLit = { "var": number = 42, equals: function (x) { return x["var"] === 42; }, instanceof: function () { return 'objLit{42}'; } }; + var objLit = { "var": number = 42, equals: function (x) { return x["var"] === 42; }, "instanceof": function () { return 'objLit{42}'; } }; var weekday = Weekdays.Monday; var con = char + f + hexchar + float.toString() + float2.toString() + reg.toString() + objLit + weekday; // diff --git a/tests/baselines/reference/convertKeywordsYes.js b/tests/baselines/reference/convertKeywordsYes.js index ba3c661d1d031..b7bd60e4a9535 100644 --- a/tests/baselines/reference/convertKeywordsYes.js +++ b/tests/baselines/reference/convertKeywordsYes.js @@ -344,43 +344,43 @@ var bigObject = { string: 0, get: 0, yield: 0, - break: 0, - case: 0, - catch: 0, - class: 0, - continue: 0, - const: 0, - debugger: 0, + "break": 0, + "case": 0, + "catch": 0, + "class": 0, + "continue": 0, + "const": 0, + "debugger": 0, declare: 0, - default: 0, - delete: 0, - do: 0, - else: 0, - enum: 0, - export: 0, - extends: 0, - false: 0, - finally: 0, - for: 0, - function: 0, - if: 0, - import: 0, - in: 0, - instanceof: 0, - new: 0, - null: 0, - return: 0, - super: 0, - switch: 0, - this: 0, - throw: 0, - true: 0, - try: 0, - typeof: 0, - var: 0, - void: 0, - while: 0, - with: 0 + "default": 0, + "delete": 0, + "do": 0, + "else": 0, + "enum": 0, + "export": 0, + "extends": 0, + "false": 0, + "finally": 0, + "for": 0, + "function": 0, + "if": 0, + "import": 0, + "in": 0, + "instanceof": 0, + "new": 0, + "null": 0, + "return": 0, + "super": 0, + "switch": 0, + "this": 0, + "throw": 0, + "true": 0, + "try": 0, + "typeof": 0, + "var": 0, + "void": 0, + "while": 0, + "with": 0 }; var bigClass = (function () { function bigClass() { @@ -401,43 +401,43 @@ var bigClass = (function () { this.string = 0; this.get = 0; this.yield = 0; - this.break = 0; - this.case = 0; - this.catch = 0; - this.class = 0; - this.continue = 0; - this.const = 0; - this.debugger = 0; + this["break"] = 0; + this["case"] = 0; + this["catch"] = 0; + this["class"] = 0; + this["continue"] = 0; + this["const"] = 0; + this["debugger"] = 0; this.declare = 0; - this.default = 0; - this.delete = 0; - this.do = 0; - this.else = 0; - this.enum = 0; - this.export = 0; - this.extends = 0; - this.false = 0; - this.finally = 0; - this.for = 0; - this.function = 0; - this.if = 0; - this.import = 0; - this.in = 0; - this.instanceof = 0; - this.new = 0; - this.null = 0; - this.return = 0; - this.super = 0; - this.switch = 0; - this.this = 0; - this.throw = 0; - this.true = 0; - this.try = 0; - this.typeof = 0; - this.var = 0; - this.void = 0; - this.while = 0; - this.with = 0; + this["default"] = 0; + this["delete"] = 0; + this["do"] = 0; + this["else"] = 0; + this["enum"] = 0; + this["export"] = 0; + this["extends"] = 0; + this["false"] = 0; + this["finally"] = 0; + this["for"] = 0; + this["function"] = 0; + this["if"] = 0; + this["import"] = 0; + this["in"] = 0; + this["instanceof"] = 0; + this["new"] = 0; + this["null"] = 0; + this["return"] = 0; + this["super"] = 0; + this["switch"] = 0; + this["this"] = 0; + this["throw"] = 0; + this["true"] = 0; + this["try"] = 0; + this["typeof"] = 0; + this["var"] = 0; + this["void"] = 0; + this["while"] = 0; + this["with"] = 0; } return bigClass; }()); diff --git a/tests/baselines/reference/destructuringParameterDeclaration6.js b/tests/baselines/reference/destructuringParameterDeclaration6.js index ad86b2983b3c3..03307415b6514 100644 --- a/tests/baselines/reference/destructuringParameterDeclaration6.js +++ b/tests/baselines/reference/destructuringParameterDeclaration6.js @@ -27,7 +27,7 @@ b2({ while: 1 }); "use strict"; // Error function a(_a) { - var = _a.while; + var = _a["while"]; } function a1(_a) { var public = _a.public; @@ -56,13 +56,13 @@ function a7() { a[_i - 0] = arguments[_i]; } } -a({ while: 1 }); +a({ "while": 1 }); // No Error function b1(_a) { var x = _a.public; } function b2(_a) { - var y = _a.while; + var y = _a["while"]; } b1({ public: 1 }); -b2({ while: 1 }); +b2({ "while": 1 }); diff --git a/tests/baselines/reference/es6ClassTest5.js b/tests/baselines/reference/es6ClassTest5.js index b909fac58b50f..7d4238fda65b1 100644 --- a/tests/baselines/reference/es6ClassTest5.js +++ b/tests/baselines/reference/es6ClassTest5.js @@ -23,7 +23,7 @@ var C1T5 = (function () { }()); var bigClass = (function () { function bigClass() { - this.break = 1; + this["break"] = 1; } return bigClass; }()); diff --git a/tests/baselines/reference/fatarrowfunctionsErrors.js b/tests/baselines/reference/fatarrowfunctionsErrors.js index 2ac20f1966ade..ced4660d8d10b 100644 --- a/tests/baselines/reference/fatarrowfunctionsErrors.js +++ b/tests/baselines/reference/fatarrowfunctionsErrors.js @@ -20,7 +20,7 @@ foo(function () { } return 0; }); -foo((1), { return: 0 }); +foo((1), { "return": 0 }); foo(function (x) { return x; }); foo(function (x) { if (x === void 0) { x = 0; } diff --git a/tests/baselines/reference/keywordField.js b/tests/baselines/reference/keywordField.js index 581d5afa14a38..a146cffade84f 100644 --- a/tests/baselines/reference/keywordField.js +++ b/tests/baselines/reference/keywordField.js @@ -12,7 +12,7 @@ var q = a["if"]; //// [keywordField.js] var obj = {}; -obj.if = 1; -var a = { if: "test" }; -var n = a.if; +obj["if"] = 1; +var a = { "if": "test" }; +var n = a["if"]; var q = a["if"]; diff --git a/tests/baselines/reference/keywordInJsxIdentifier.js b/tests/baselines/reference/keywordInJsxIdentifier.js index 6009e1980e639..d9c3b51e9a30b 100644 --- a/tests/baselines/reference/keywordInJsxIdentifier.js +++ b/tests/baselines/reference/keywordInJsxIdentifier.js @@ -9,6 +9,6 @@ declare var React: any; //// [keywordInJsxIdentifier.js] React.createElement("foo", { "class-id": true }); -React.createElement("foo", { class: true }); +React.createElement("foo", { "class": true }); React.createElement("foo", { "class-id": "1" }); -React.createElement("foo", { class: "1" }); +React.createElement("foo", { "class": "1" }); diff --git a/tests/baselines/reference/nestedClassDeclaration.js b/tests/baselines/reference/nestedClassDeclaration.js index 04e2f6348efb6..cc300ec75a31c 100644 --- a/tests/baselines/reference/nestedClassDeclaration.js +++ b/tests/baselines/reference/nestedClassDeclaration.js @@ -38,5 +38,5 @@ function foo() { }()); } var x = { - class: C4 + "class": C4 }, _a = void 0; diff --git a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers01.js b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers01.js index cd339bb590716..a905e53f22122 100644 --- a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers01.js +++ b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers01.js @@ -3,4 +3,4 @@ var { while } = { while: 1 } //// [objectBindingPatternKeywordIdentifiers01.js] -var = { while: 1 }.while; +var = { "while": 1 }["while"]; diff --git a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers02.js b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers02.js index 0286a78ba8227..5bc6e1f996367 100644 --- a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers02.js +++ b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers02.js @@ -3,4 +3,4 @@ var { while: while } = { while: 1 } //// [objectBindingPatternKeywordIdentifiers02.js] -var _a = { while: 1 }, = _a.while, = _a.while; +var _a = { "while": 1 }, = _a["while"], = _a["while"]; diff --git a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers03.js b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers03.js index 4bbb1afb4cb5b..3d8643d63ce28 100644 --- a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers03.js +++ b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers03.js @@ -3,4 +3,4 @@ var { "while" } = { while: 1 } //// [objectBindingPatternKeywordIdentifiers03.js] -var = { while: 1 }["while"]; +var = { "while": 1 }["while"]; diff --git a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers04.js b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers04.js index 4e53b13c0a6ba..de7608a77d22d 100644 --- a/tests/baselines/reference/objectBindingPatternKeywordIdentifiers04.js +++ b/tests/baselines/reference/objectBindingPatternKeywordIdentifiers04.js @@ -3,4 +3,4 @@ var { "while": while } = { while: 1 } //// [objectBindingPatternKeywordIdentifiers04.js] -var _a = { while: 1 }, = _a["while"], = _a.while; +var _a = { "while": 1 }, = _a["while"], = _a["while"]; diff --git a/tests/baselines/reference/objectLiteralShorthandPropertiesErrorFromNotUsingIdentifier.js b/tests/baselines/reference/objectLiteralShorthandPropertiesErrorFromNotUsingIdentifier.js index b72f0351b9c82..7b9c9f5d32850 100644 --- a/tests/baselines/reference/objectLiteralShorthandPropertiesErrorFromNotUsingIdentifier.js +++ b/tests/baselines/reference/objectLiteralShorthandPropertiesErrorFromNotUsingIdentifier.js @@ -27,15 +27,15 @@ var y = { 42: , get e() { }, set f() { }, - this: , - super: , - var: , - class: , - typeof: + "this": , + "super": , + "var": , + "class": , + "typeof": }; var x = { a: .b, a: ["ss"], a: [1] }; -var v = { class: }; // error +var v = { "class": }; // error diff --git a/tests/baselines/reference/objectTypesIdentityWithConstructSignatures2.js b/tests/baselines/reference/objectTypesIdentityWithConstructSignatures2.js index 315e079d429bf..0a422dbda6f0f 100644 --- a/tests/baselines/reference/objectTypesIdentityWithConstructSignatures2.js +++ b/tests/baselines/reference/objectTypesIdentityWithConstructSignatures2.js @@ -91,7 +91,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return ''; } }; // not a construct signature, function called new +var b = { "new": function (x) { return ''; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithConstructSignaturesDifferingParamCounts.js b/tests/baselines/reference/objectTypesIdentityWithConstructSignaturesDifferingParamCounts.js index a61bedfd52f23..5fa148b541d45 100644 --- a/tests/baselines/reference/objectTypesIdentityWithConstructSignaturesDifferingParamCounts.js +++ b/tests/baselines/reference/objectTypesIdentityWithConstructSignaturesDifferingParamCounts.js @@ -91,7 +91,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return ''; } }; // not a construct signature, function called new +var b = { "new": function (x) { return ''; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints.js index c15c53b9bf80d..6a66e8bbda3b9 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints.js @@ -92,7 +92,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return ''; } }; // not a construct signature, function called new +var b = { "new": function (x) { return ''; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints2.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints2.js index f8aff596dc9c5..e19837a9f7f2c 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints2.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints2.js @@ -109,7 +109,7 @@ var D = (function () { return D; }()); var a; -var b = { new: function (x, y) { return ''; } }; // not a construct signature, function called new +var b = { "new": function (x, y) { return ''; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints3.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints3.js index 141aa86823b27..735c5bdc2d69c 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints3.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByConstraints3.js @@ -128,7 +128,7 @@ var D = (function () { return D; }()); var a; -var b = { new: function (x, y) { return ''; } }; // not a construct signature, function called new +var b = { "new": function (x, y) { return ''; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType.js index b651d368f334b..6eab84a49ddb4 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType.js @@ -99,7 +99,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return null; } }; // not a construct signature, function called new +var b = { "new": function (x) { return null; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType2.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType2.js index ff7095c4ea1a1..d927a8e082a22 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType2.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingByReturnType2.js @@ -95,7 +95,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return null; } }; // not a construct signature, function called new +var b = { "new": function (x) { return null; } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterCounts.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterCounts.js index 314eb700c4b19..512bebb3b0e8d 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterCounts.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterCounts.js @@ -87,7 +87,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return x; } }; +var b = { "new": function (x) { return x; } }; function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterNames.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterNames.js index 182cf8263b779..80cfcd23ec9c3 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterNames.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesDifferingTypeParameterNames.js @@ -87,7 +87,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x) { return new C(x); } }; +var b = { "new": function (x) { return new C(x); } }; function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams.js index 5c5dd26c33171..87cb0b33531e5 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams.js @@ -91,7 +91,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x, y) { return new C(x, y); } }; // not a construct signature, function called new +var b = { "new": function (x, y) { return new C(x, y); } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams2.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams2.js index 14b2ec3c0ca0a..6b0e91f817ff9 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams2.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams2.js @@ -91,7 +91,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x, y) { return new C(x, y); } }; // not a construct signature, function called new +var b = { "new": function (x, y) { return new C(x, y); } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams3.js b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams3.js index ffc238cacae09..55f2a0217e934 100644 --- a/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams3.js +++ b/tests/baselines/reference/objectTypesIdentityWithGenericConstructSignaturesOptionalParams3.js @@ -91,7 +91,7 @@ var C = (function () { return C; }()); var a; -var b = { new: function (x, y) { return new C(x, y); } }; // not a construct signature, function called new +var b = { "new": function (x, y) { return new C(x, y); } }; // not a construct signature, function called new function foo1b(x) { } function foo1c(x) { } function foo2(x) { } diff --git a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral2.js b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral2.js index 6a703759fff75..c206a30237a5e 100644 --- a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral2.js +++ b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral2.js @@ -4,4 +4,4 @@ return; //// [parserErrorRecovery_ObjectLiteral2.js] var v = { a: , - return: }; + "return": }; diff --git a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral3.js b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral3.js index eecf45fea4fa0..6cee2b4272519 100644 --- a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral3.js +++ b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral3.js @@ -4,4 +4,4 @@ return; //// [parserErrorRecovery_ObjectLiteral3.js] var v = { a: , - return: }; + "return": }; diff --git a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral4.js b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral4.js index 87a1a31437ef7..23d17c8047b5c 100644 --- a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral4.js +++ b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral4.js @@ -4,4 +4,4 @@ return; //// [parserErrorRecovery_ObjectLiteral4.js] var v = { a: 1, - return: }; + "return": }; diff --git a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral5.js b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral5.js index 97e618946a0e2..7b83132bf0fb4 100644 --- a/tests/baselines/reference/parserErrorRecovery_ObjectLiteral5.js +++ b/tests/baselines/reference/parserErrorRecovery_ObjectLiteral5.js @@ -4,4 +4,4 @@ return; //// [parserErrorRecovery_ObjectLiteral5.js] var v = { a: 1, - return: }; + "return": }; diff --git a/tests/baselines/reference/parserExportAsFunctionIdentifier.js b/tests/baselines/reference/parserExportAsFunctionIdentifier.js index 7ed76bb87d945..62429c76855c7 100644 --- a/tests/baselines/reference/parserExportAsFunctionIdentifier.js +++ b/tests/baselines/reference/parserExportAsFunctionIdentifier.js @@ -9,4 +9,4 @@ var x = f.export(); //// [parserExportAsFunctionIdentifier.js] var f; -var x = f.export(); +var x = f["export"](); diff --git a/tests/baselines/reference/parserKeywordsAsIdentifierName1.js b/tests/baselines/reference/parserKeywordsAsIdentifierName1.js index c0c8c8443647f..a717abcc08ba0 100644 --- a/tests/baselines/reference/parserKeywordsAsIdentifierName1.js +++ b/tests/baselines/reference/parserKeywordsAsIdentifierName1.js @@ -8,7 +8,7 @@ var big = { //// [parserKeywordsAsIdentifierName1.js] var big = { - break: 0, - super: 0, - const: 0 + "break": 0, + "super": 0, + "const": 0 }; diff --git a/tests/baselines/reference/parserShorthandPropertyAssignment2.js b/tests/baselines/reference/parserShorthandPropertyAssignment2.js index 0de0fa3829fc6..95d2f32ffad0e 100644 --- a/tests/baselines/reference/parserShorthandPropertyAssignment2.js +++ b/tests/baselines/reference/parserShorthandPropertyAssignment2.js @@ -2,4 +2,4 @@ var v = { class }; //// [parserShorthandPropertyAssignment2.js] -var v = { class: }; +var v = { "class": }; diff --git a/tests/baselines/reference/parserSuperExpression3.js b/tests/baselines/reference/parserSuperExpression3.js index f311efcd0f6a8..064353669c80c 100644 --- a/tests/baselines/reference/parserSuperExpression3.js +++ b/tests/baselines/reference/parserSuperExpression3.js @@ -10,7 +10,7 @@ var C = (function () { function C() { } C.prototype.M = function () { - this.super(0); + this["super"](0); }; return C; }()); diff --git a/tests/baselines/reference/prototypeOnConstructorFunctions.js b/tests/baselines/reference/prototypeOnConstructorFunctions.js index d2e5ddde9251f..de1fec1f7e8ac 100644 --- a/tests/baselines/reference/prototypeOnConstructorFunctions.js +++ b/tests/baselines/reference/prototypeOnConstructorFunctions.js @@ -12,4 +12,4 @@ i.const.prototype.prop = "yo"; //// [prototypeOnConstructorFunctions.js] var i; -i.const.prototype.prop = "yo"; +i["const"].prototype.prop = "yo"; diff --git a/tests/baselines/reference/reservedWords.js b/tests/baselines/reference/reservedWords.js index 12fbcae0c651e..3424c05418175 100644 --- a/tests/baselines/reference/reservedWords.js +++ b/tests/baselines/reference/reservedWords.js @@ -19,16 +19,16 @@ var obj2 = { //// [reservedWords.js] var obj = { - if: 0, - debugger: 2, - break: 3, - function: 4 + "if": 0, + "debugger": 2, + "break": 3, + "function": 4 }; //This compiles. var obj2 = { - if: 0, - while: 1, - debugger: 2, - break: 3, - function: 4 + "if": 0, + "while": 1, + "debugger": 2, + "break": 3, + "function": 4 }; diff --git a/tests/baselines/reference/reservedWords2.js b/tests/baselines/reference/reservedWords2.js index a79a0564c788d..d9c8105c35f5b 100644 --- a/tests/baselines/reference/reservedWords2.js +++ b/tests/baselines/reference/reservedWords2.js @@ -27,8 +27,8 @@ function () { } throw function () { }; module; void {}; -var _a = { while: 1, return: 2 }, = _a.while, = _a.return; -var _b = { this: 1, switch: { continue: 2 } }, = _b.this, = _b.switch.continue; +var _a = { "while": 1, "return": 2 }, = _a["while"], = _a["return"]; +var _b = { "this": 1, "switch": { "continue": 2 } }, = _b["this"], = _b["switch"]["continue"]; var _c = void 0; debugger; if () diff --git a/tests/baselines/reference/super1.js b/tests/baselines/reference/super1.js index 9f1289dce554c..0094f696fafb5 100644 --- a/tests/baselines/reference/super1.js +++ b/tests/baselines/reference/super1.js @@ -97,7 +97,7 @@ var SubSub1 = (function (_super) { return _super.apply(this, arguments) || this; } SubSub1.prototype.bar = function () { - return _super.prototype.super.foo; + return _super.prototype["super"].foo; }; return SubSub1; }(Sub1)); diff --git a/tests/baselines/reference/tsxReactEmitNesting.js b/tests/baselines/reference/tsxReactEmitNesting.js index 29e948f687b32..eaee315c340cb 100644 --- a/tests/baselines/reference/tsxReactEmitNesting.js +++ b/tests/baselines/reference/tsxReactEmitNesting.js @@ -38,21 +38,21 @@ let render = (ctrl, model) => //// [file.js] // A simple render function with nesting and control statements var render = function (ctrl, model) { - return vdom.createElement("section", { class: "todoapp" }, - vdom.createElement("header", { class: "header" }, + return vdom.createElement("section", { "class": "todoapp" }, + vdom.createElement("header", { "class": "header" }, vdom.createElement("h1", null, "todos "), - vdom.createElement("input", { class: "new-todo", autofocus: true, autocomplete: "off", placeholder: "What needs to be done?", value: model.newTodo, onKeyup: ctrl.addTodo.bind(ctrl, model) })), - vdom.createElement("section", { class: "main", style: { display: (model.todos && model.todos.length) ? "block" : "none" } }, - vdom.createElement("input", { class: "toggle-all", type: "checkbox", onChange: ctrl.toggleAll.bind(ctrl) }), - vdom.createElement("ul", { class: "todo-list" }, model.filteredTodos.map(function (todo) { - return vdom.createElement("li", { class: { todo: true, completed: todo.completed, editing: todo == model.editedTodo } }, - vdom.createElement("div", { class: "view" }, + vdom.createElement("input", { "class": "new-todo", autofocus: true, autocomplete: "off", placeholder: "What needs to be done?", value: model.newTodo, onKeyup: ctrl.addTodo.bind(ctrl, model) })), + vdom.createElement("section", { "class": "main", style: { display: (model.todos && model.todos.length) ? "block" : "none" } }, + vdom.createElement("input", { "class": "toggle-all", type: "checkbox", onChange: ctrl.toggleAll.bind(ctrl) }), + vdom.createElement("ul", { "class": "todo-list" }, model.filteredTodos.map(function (todo) { + return vdom.createElement("li", { "class": { todo: true, completed: todo.completed, editing: todo == model.editedTodo } }, + vdom.createElement("div", { "class": "view" }, (!todo.editable) ? - vdom.createElement("input", { class: "toggle", type: "checkbox" }) + vdom.createElement("input", { "class": "toggle", type: "checkbox" }) : null, vdom.createElement("label", { onDoubleClick: function () { ctrl.editTodo(todo); } }, todo.title), - vdom.createElement("button", { class: "destroy", onClick: ctrl.removeTodo.bind(ctrl, todo) }), - vdom.createElement("div", { class: "iconBorder" }, - vdom.createElement("div", { class: "icon" })))); + vdom.createElement("button", { "class": "destroy", onClick: ctrl.removeTodo.bind(ctrl, todo) }), + vdom.createElement("div", { "class": "iconBorder" }, + vdom.createElement("div", { "class": "icon" })))); })))); }; diff --git a/tests/baselines/reference/typeQueryWithReservedWords.js b/tests/baselines/reference/typeQueryWithReservedWords.js index 7561eeddb7528..09c3b642a36d0 100644 --- a/tests/baselines/reference/typeQueryWithReservedWords.js +++ b/tests/baselines/reference/typeQueryWithReservedWords.js @@ -21,9 +21,9 @@ var Controller = (function () { } Controller.prototype.create = function () { }; - Controller.prototype.delete = function () { + Controller.prototype["delete"] = function () { }; - Controller.prototype.var = function () { + Controller.prototype["var"] = function () { }; return Controller; }()); From 4304eab6549720cdca02376d841446372126c038 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 14 Oct 2016 11:12:47 -0700 Subject: [PATCH 05/24] JSX Text belongs with its other token friends --- src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 638504e613f11..138e6097292dd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -45,6 +45,7 @@ namespace ts { // Literals NumericLiteral, StringLiteral, + JsxText, RegularExpressionLiteral, NoSubstitutionTemplateLiteral, // Pseudo-literals @@ -302,7 +303,6 @@ namespace ts { JsxElement, JsxSelfClosingElement, JsxOpeningElement, - JsxText, JsxClosingElement, JsxAttribute, JsxSpreadAttribute, From eb4bb4a9e0f7b1e63ac8957239b7d15cfdfd9b6e Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 14 Oct 2016 12:08:41 -0700 Subject: [PATCH 06/24] Fix-ups around formatting and assertions --- src/services/formatting/formatting.ts | 5 +++-- src/services/formatting/formattingScanner.ts | 4 ++-- src/services/formatting/rulesMap.ts | 2 +- src/services/utilities.ts | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/services/formatting/formatting.ts b/src/services/formatting/formatting.ts index 16108450d2ccd..2b7d0f8d68c13 100644 --- a/src/services/formatting/formatting.ts +++ b/src/services/formatting/formatting.ts @@ -624,10 +624,11 @@ namespace ts.formatting { return inheritedIndentation; } - if (isToken(child)) { + // JSX text shouldn't affect indenting + if (isToken(child) && child.kind !== SyntaxKind.JsxText) { // if child node is a token, it does not impact indentation, proceed it using parent indentation scope rules const tokenInfo = formattingScanner.readTokenInfo(child); - Debug.assert(tokenInfo.token.end === child.end); + Debug.assert(tokenInfo.token.end === child.end, "Token end is child end"); consumeTokenAndAdvanceScanner(tokenInfo, node, parentDynamicIndentation, child); return inheritedIndentation; } diff --git a/src/services/formatting/formattingScanner.ts b/src/services/formatting/formattingScanner.ts index 7822e4a72fcaa..2020352f86b9e 100644 --- a/src/services/formatting/formattingScanner.ts +++ b/src/services/formatting/formattingScanner.ts @@ -31,7 +31,7 @@ namespace ts.formatting { } export function getFormattingScanner(sourceFile: SourceFile, startPos: number, endPos: number): FormattingScanner { - Debug.assert(scanner === undefined); + Debug.assert(scanner === undefined, "Scanner should be undefined"); scanner = sourceFile.languageVariant === LanguageVariant.JSX ? jsxScanner : standardScanner; scanner.setText(sourceFile.text); @@ -62,7 +62,7 @@ namespace ts.formatting { }; function advance(): void { - Debug.assert(scanner !== undefined); + Debug.assert(scanner !== undefined, "Scanner should be present"); lastTokenInfo = undefined; const isStarted = scanner.getStartPos() !== startPos; diff --git a/src/services/formatting/rulesMap.ts b/src/services/formatting/rulesMap.ts index 65c30908863c0..cd6f2e539d6c5 100644 --- a/src/services/formatting/rulesMap.ts +++ b/src/services/formatting/rulesMap.ts @@ -35,8 +35,8 @@ namespace ts.formatting { } private GetRuleBucketIndex(row: number, column: number): number { + Debug.assert(row <= SyntaxKind.LastKeyword && column <= SyntaxKind.LastKeyword, "Must compute formatting context from tokens"); const rulesBucketIndex = (row * this.mapRowLength) + column; - // Debug.Assert(rulesBucketIndex < this.map.Length, "Trying to access an index outside the array."); return rulesBucketIndex; } diff --git a/src/services/utilities.ts b/src/services/utilities.ts index b58c4188e0d0d..936abfbb2ed4a 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -750,7 +750,7 @@ namespace ts { return find(startNode || sourceFile); function findRightmostToken(n: Node): Node { - if (isToken(n) || n.kind === SyntaxKind.JsxText) { + if (isToken(n)) { return n; } @@ -761,7 +761,7 @@ namespace ts { } function find(n: Node): Node { - if (isToken(n) || n.kind === SyntaxKind.JsxText) { + if (isToken(n)) { return n; } From 8094b2c5def5ed39e5a9ddc18bfd09bab731aa11 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 16 Oct 2016 17:28:45 -0700 Subject: [PATCH 07/24] Improve contextual typing of partially annotated signatures --- src/compiler/checker.ts | 66 +++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 22ab44ee0898d..b3b6557c98bf3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3144,8 +3144,7 @@ namespace ts { // Use contextual parameter type if one is available let type: Type; if (declaration.symbol.name === "this") { - const thisParameter = getContextualThisParameter(func); - type = thisParameter ? getTypeOfSymbol(thisParameter) : undefined; + type = getContextualThisParameterType(func); } else { type = getContextuallyTypedParameterType(declaration); @@ -4789,9 +4788,6 @@ namespace ts { if (isJSConstructSignature) { minArgumentCount--; } - if (!thisParameter && isObjectLiteralMethod(declaration)) { - thisParameter = getContextualThisParameter(declaration); - } const classType = declaration.kind === SyntaxKind.Constructor ? getDeclaredTypeOfClassOrInterface(getMergedSymbol((declaration.parent).symbol)) @@ -6101,9 +6097,24 @@ namespace ts { } function isContextSensitiveFunctionLikeDeclaration(node: FunctionLikeDeclaration) { - const areAllParametersUntyped = !forEach(node.parameters, p => p.type); - const isNullaryArrow = node.kind === SyntaxKind.ArrowFunction && !node.parameters.length; - return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow; + // Functions with type parameters are not context sensitive. + if (node.typeParameters) { + return false; + } + // Functions with any parameters that lack type annotations are context sensitive. + if (forEach(node.parameters, p => !p.type)) { + return true; + } + // For arrow functions we now know we're not context sensitive. + if (node.kind === SyntaxKind.ArrowFunction) { + return false; + } + // If the first parameter is not an explicit 'this' parameter, then the function has + // an implicit 'this' parameter which is subject to contextual typing. Otherwise we + // know that all parameters (including 'this') have type annotations and nothing is + // subject to contextual typing. + const parameter = firstOrUndefined(node.parameters); + return !(parameter && parameter.name.kind === SyntaxKind.Identifier && (parameter.name).text === "this"); } function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { @@ -9629,7 +9640,7 @@ namespace ts { } } - const thisType = getThisTypeOfDeclaration(container); + let thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType(container); if (thisType) { return thisType; } @@ -9869,14 +9880,16 @@ namespace ts { } } - function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol { + function getContextualThisParameterType(func: FunctionLikeDeclaration): Type { if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) { const contextualSignature = getContextualSignature(func); if (contextualSignature) { - return contextualSignature.thisParameter; + const thisParameter = contextualSignature.thisParameter; + if (thisParameter) { + return getTypeOfSymbol(thisParameter); + } } } - return undefined; } @@ -12840,21 +12853,36 @@ namespace ts { function assignContextualParameterTypes(signature: Signature, context: Signature, mapper: TypeMapper) { const len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0); + if (isInferentialContext(mapper)) { + for (let i = 0; i < len; i++) { + const declaration = signature.parameters[i].valueDeclaration; + if (declaration.type) { + inferTypes(mapper.context, getTypeFromTypeNode(declaration.type), getTypeAtPosition(context, i)); + } + } + } if (context.thisParameter) { - if (!signature.thisParameter) { - signature.thisParameter = createTransientSymbol(context.thisParameter, undefined); + const parameter = signature.thisParameter; + if (!parameter || parameter.valueDeclaration && !(parameter.valueDeclaration).type) { + if (!parameter) { + signature.thisParameter = createTransientSymbol(context.thisParameter, undefined); + } + assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper); } - assignTypeToParameterAndFixTypeParameters(signature.thisParameter, getTypeOfSymbol(context.thisParameter), mapper); } for (let i = 0; i < len; i++) { const parameter = signature.parameters[i]; - const contextualParameterType = getTypeAtPosition(context, i); - assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper); + if (!(parameter.valueDeclaration).type) { + const contextualParameterType = getTypeAtPosition(context, i); + assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper); + } } if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) { const parameter = lastOrUndefined(signature.parameters); - const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters)); - assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper); + if (!(parameter.valueDeclaration).type) { + const contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters)); + assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper); + } } } From 808db07ce44d46574e88d15ba706bb79bdd160f3 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 16 Oct 2016 17:31:57 -0700 Subject: [PATCH 08/24] Accept new baselines --- tests/baselines/reference/thisTypeInFunctions.types | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index 44bf23ad509af..a2aaba4cdd736 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -453,7 +453,7 @@ let anyToSpecified: (this: { y: number }, x: number) => number = function(x: num >this : { y: number; } >y : number >x : number ->function(x: number): number { return x + 12; } : (x: number) => number +>function(x: number): number { return x + 12; } : (this: { y: number; }, x: number) => number >x : number >x + 12 : number >x : number From 6425f0ccfdbec7f7f189589cd8f49a829ef785a8 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 16 Oct 2016 17:37:37 -0700 Subject: [PATCH 09/24] Fix lint error --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b3b6557c98bf3..db95eb9bc17bd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9640,7 +9640,7 @@ namespace ts { } } - let thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType(container); + const thisType = getThisTypeOfDeclaration(container) || getContextualThisParameterType(container); if (thisType) { return thisType; } From ebba1c3d1a3c7d0a52a0531c2ec5edb9b2f94597 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sun, 16 Oct 2016 20:57:51 -0700 Subject: [PATCH 10/24] fix flow in finally blocks --- src/compiler/binder.ts | 36 ++++++++++++++----- tests/baselines/reference/flowInFinally1.js | 33 +++++++++++++++++ .../reference/flowInFinally1.symbols | 29 +++++++++++++++ .../baselines/reference/flowInFinally1.types | 34 ++++++++++++++++++ tests/cases/compiler/flowInFinally1.ts | 16 +++++++++ 5 files changed, 140 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/flowInFinally1.js create mode 100644 tests/baselines/reference/flowInFinally1.symbols create mode 100644 tests/baselines/reference/flowInFinally1.types create mode 100644 tests/cases/compiler/flowInFinally1.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4711d54e0b267..31732bc833f7b 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -984,24 +984,44 @@ namespace ts { } function bindTryStatement(node: TryStatement): void { - const postFinallyLabel = createBranchLabel(); + const preFinallyLabel = createBranchLabel(); const preTryFlow = currentFlow; // TODO: Every statement in try block is potentially an exit point! bind(node.tryBlock); - addAntecedent(postFinallyLabel, currentFlow); + addAntecedent(preFinallyLabel, currentFlow); + + const flowAfterTry = currentFlow; + let flowAfterCatch = unreachableFlow; + if (node.catchClause) { currentFlow = preTryFlow; bind(node.catchClause); - addAntecedent(postFinallyLabel, currentFlow); + addAntecedent(preFinallyLabel, currentFlow); + + flowAfterCatch = currentFlow; } if (node.finallyBlock) { - currentFlow = preTryFlow; + // in finally flow is combined from pre-try/flow from try/flow from catch + // pre-flow is necessary to make sure that finally is reachable even if finaly flows in both try and finally blocks are unreachable + addAntecedent(preFinallyLabel, preTryFlow); + currentFlow = finishFlowLabel(preFinallyLabel); bind(node.finallyBlock); + // if flow after finally is unreachable - keep it + // otherwise check if flows after try and after catch are unreachable + // if yes - convert current flow to unreachable + // i.e. + // try { return "1" } finally { console.log(1); } + // console.log(2); // this line should be unreachable even if flow falls out of finally block + if (!(currentFlow.flags & FlowFlags.Unreachable)) { + if ((flowAfterTry.flags & FlowFlags.Unreachable) && (flowAfterCatch.flags & FlowFlags.Unreachable)) { + currentFlow = flowAfterTry == reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow + ? reportedUnreachableFlow + : unreachableFlow; + } + } } - // if try statement has finally block and flow after finally block is unreachable - keep it - // otherwise use whatever flow was accumulated at postFinallyLabel - if (!node.finallyBlock || !(currentFlow.flags & FlowFlags.Unreachable)) { - currentFlow = finishFlowLabel(postFinallyLabel); + else { + currentFlow = finishFlowLabel(preFinallyLabel); } } diff --git a/tests/baselines/reference/flowInFinally1.js b/tests/baselines/reference/flowInFinally1.js new file mode 100644 index 0000000000000..b6bf494e83232 --- /dev/null +++ b/tests/baselines/reference/flowInFinally1.js @@ -0,0 +1,33 @@ +//// [flowInFinally1.ts] + +class A { + constructor() { } + method() { } +} + +let a: A | null = null; + +try { + a = new A(); +} finally { + if (a) { + a.method(); + } +} + +//// [flowInFinally1.js] +var A = (function () { + function A() { + } + A.prototype.method = function () { }; + return A; +}()); +var a = null; +try { + a = new A(); +} +finally { + if (a) { + a.method(); + } +} diff --git a/tests/baselines/reference/flowInFinally1.symbols b/tests/baselines/reference/flowInFinally1.symbols new file mode 100644 index 0000000000000..2ecedaee0257c --- /dev/null +++ b/tests/baselines/reference/flowInFinally1.symbols @@ -0,0 +1,29 @@ +=== tests/cases/compiler/flowInFinally1.ts === + +class A { +>A : Symbol(A, Decl(flowInFinally1.ts, 0, 0)) + + constructor() { } + method() { } +>method : Symbol(A.method, Decl(flowInFinally1.ts, 2, 19)) +} + +let a: A | null = null; +>a : Symbol(a, Decl(flowInFinally1.ts, 6, 3)) +>A : Symbol(A, Decl(flowInFinally1.ts, 0, 0)) + +try { + a = new A(); +>a : Symbol(a, Decl(flowInFinally1.ts, 6, 3)) +>A : Symbol(A, Decl(flowInFinally1.ts, 0, 0)) + +} finally { + if (a) { +>a : Symbol(a, Decl(flowInFinally1.ts, 6, 3)) + + a.method(); +>a.method : Symbol(A.method, Decl(flowInFinally1.ts, 2, 19)) +>a : Symbol(a, Decl(flowInFinally1.ts, 6, 3)) +>method : Symbol(A.method, Decl(flowInFinally1.ts, 2, 19)) + } +} diff --git a/tests/baselines/reference/flowInFinally1.types b/tests/baselines/reference/flowInFinally1.types new file mode 100644 index 0000000000000..c9cbab6dbd161 --- /dev/null +++ b/tests/baselines/reference/flowInFinally1.types @@ -0,0 +1,34 @@ +=== tests/cases/compiler/flowInFinally1.ts === + +class A { +>A : A + + constructor() { } + method() { } +>method : () => void +} + +let a: A | null = null; +>a : A | null +>A : A +>null : null +>null : null + +try { + a = new A(); +>a = new A() : A +>a : A | null +>new A() : A +>A : typeof A + +} finally { + if (a) { +>a : A | null + + a.method(); +>a.method() : void +>a.method : () => void +>a : A +>method : () => void + } +} diff --git a/tests/cases/compiler/flowInFinally1.ts b/tests/cases/compiler/flowInFinally1.ts new file mode 100644 index 0000000000000..4ab2977e7dfc0 --- /dev/null +++ b/tests/cases/compiler/flowInFinally1.ts @@ -0,0 +1,16 @@ +// @strictNullChecks: true + +class A { + constructor() { } + method() { } +} + +let a: A | null = null; + +try { + a = new A(); +} finally { + if (a) { + a.method(); + } +} \ No newline at end of file From 8a2d16134d0001d5c0ce8f1b1df451f4a93af982 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 17 Oct 2016 06:09:19 -0700 Subject: [PATCH 11/24] Remove unnecessary assert --- src/server/scriptInfo.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 68dd59d2d3266..2792b3e47a963 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -84,11 +84,7 @@ namespace ts.server { } getDefaultProject() { - if (this.containingProjects.length === 0) { - return Errors.ThrowNoProject(); - } - Debug.assert(this.containingProjects.length !== 0); - return this.containingProjects[0]; + return this.containingProjects.length === 0 ? Errors.ThrowNoProject() : this.containingProjects[0]; } setFormatOptions(formatSettings: FormatCodeSettings): void { From df58df17f66f13d66d304bb4076849e07c4645f7 Mon Sep 17 00:00:00 2001 From: Herrington Darkholme Date: Mon, 17 Oct 2016 09:04:16 -0700 Subject: [PATCH 12/24] Add partially annotated function tests --- ...AnnotatedFunctionInferenceError.errors.txt | 27 ++++ ...artiallyAnnotatedFunctionInferenceError.js | 39 +++++ ...tatedFunctionInferenceWithTypeParameter.js | 85 +++++++++++ ...FunctionInferenceWithTypeParameter.symbols | 114 +++++++++++++++ ...edFunctionInferenceWithTypeParameter.types | 136 ++++++++++++++++++ ...llyAnnotatedFunctionWitoutTypeParameter.js | 12 ++ ...notatedFunctionWitoutTypeParameter.symbols | 19 +++ ...AnnotatedFunctionWitoutTypeParameter.types | 23 +++ ...artiallyAnnotatedFunctionInferenceError.ts | 14 ++ ...tatedFunctionInferenceWithTypeParameter.ts | 33 +++++ ...llyAnnotatedFunctionWitoutTypeParameter.ts | 7 + 11 files changed, 509 insertions(+) create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.errors.txt create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.js create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.js create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.symbols create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.types create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.js create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.symbols create mode 100644 tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.types create mode 100644 tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts create mode 100644 tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceWithTypeParameter.ts create mode 100644 tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitoutTypeParameter.ts diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.errors.txt b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.errors.txt new file mode 100644 index 0000000000000..a9fc9b68cf899 --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.errors.txt @@ -0,0 +1,27 @@ +tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts(12,11): error TS2345: Argument of type '(t1: D, t2: D, t3: any) => void' is not assignable to parameter of type '(t: D, t1: D) => void'. +tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts(13,11): error TS2345: Argument of type '(t1: D, t2: D, t3: any) => void' is not assignable to parameter of type '(t: D, t1: D) => void'. +tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts(14,11): error TS2345: Argument of type '(t1: C, t2: C, t3: D) => void' is not assignable to parameter of type '(t: C, t1: C) => void'. + + +==== tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts (3 errors) ==== + class C { + test: string + } + + class D extends C { + test2: string + } + + declare function testError(a: (t: T, t1: T) => void): T + + // more args + testError((t1: D, t2, t3) => {}) + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(t1: D, t2: D, t3: any) => void' is not assignable to parameter of type '(t: D, t1: D) => void'. + testError((t1, t2: D, t3) => {}) + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(t1: D, t2: D, t3: any) => void' is not assignable to parameter of type '(t: D, t1: D) => void'. + testError((t1, t2, t3: D) => {}) + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '(t1: C, t2: C, t3: D) => void' is not assignable to parameter of type '(t: C, t1: C) => void'. + \ No newline at end of file diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.js b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.js new file mode 100644 index 0000000000000..9702595fffbed --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceError.js @@ -0,0 +1,39 @@ +//// [partiallyAnnotatedFunctionInferenceError.ts] +class C { + test: string +} + +class D extends C { + test2: string +} + +declare function testError(a: (t: T, t1: T) => void): T + +// more args +testError((t1: D, t2, t3) => {}) +testError((t1, t2: D, t3) => {}) +testError((t1, t2, t3: D) => {}) + + +//// [partiallyAnnotatedFunctionInferenceError.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var C = (function () { + function C() { + } + return C; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + return _super.apply(this, arguments) || this; + } + return D; +}(C)); +// more args +testError(function (t1, t2, t3) { }); +testError(function (t1, t2, t3) { }); +testError(function (t1, t2, t3) { }); diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.js b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.js new file mode 100644 index 0000000000000..d485fb11d7fb4 --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.js @@ -0,0 +1,85 @@ +//// [partiallyAnnotatedFunctionInferenceWithTypeParameter.ts] +class C { + test: string +} + +class D extends C { + test2: string +} + +declare function test(a: (t: T, t1: T) => void): T + +declare function testRest(a: (t: T, t1: T, ...ts: T[]) => void): T + + +// exactly +test((t1: D, t2) => { t2.test2 }) +test((t1, t2: D) => { t2.test2 }) + +// zero arg +test(() => {}) + +// fewer args +test((t1: D) => {}) + +// rest arg +test((...ts: D[]) => {}) + +// source function has rest arg +testRest((t1: D) => {}) +testRest((t1, t2, t3) => {}) +testRest((t1: D, t2, t3) => {}) +testRest((t1, t2: D, t3) => {}) +testRest((t2: D, ...t3) => {}) +testRest((t2, ...t3: D[]) => {}) + + +//// [partiallyAnnotatedFunctionInferenceWithTypeParameter.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var C = (function () { + function C() { + } + return C; +}()); +var D = (function (_super) { + __extends(D, _super); + function D() { + return _super.apply(this, arguments) || this; + } + return D; +}(C)); +// exactly +test(function (t1, t2) { t2.test2; }); +test(function (t1, t2) { t2.test2; }); +// zero arg +test(function () { }); +// fewer args +test(function (t1) { }); +// rest arg +test(function () { + var ts = []; + for (var _i = 0; _i < arguments.length; _i++) { + ts[_i - 0] = arguments[_i]; + } +}); +// source function has rest arg +testRest(function (t1) { }); +testRest(function (t1, t2, t3) { }); +testRest(function (t1, t2, t3) { }); +testRest(function (t1, t2, t3) { }); +testRest(function (t2) { + var t3 = []; + for (var _i = 1; _i < arguments.length; _i++) { + t3[_i - 1] = arguments[_i]; + } +}); +testRest(function (t2) { + var t3 = []; + for (var _i = 1; _i < arguments.length; _i++) { + t3[_i - 1] = arguments[_i]; + } +}); diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.symbols b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.symbols new file mode 100644 index 0000000000000..b3c66f8f8cd0e --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.symbols @@ -0,0 +1,114 @@ +=== tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceWithTypeParameter.ts === +class C { +>C : Symbol(C, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 0, 0)) + + test: string +>test : Symbol(C.test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 0, 9)) +} + +class D extends C { +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) +>C : Symbol(C, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 0, 0)) + + test2: string +>test2 : Symbol(D.test2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 4, 19)) +} + +declare function test(a: (t: T, t1: T) => void): T +>test : Symbol(test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 6, 1)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 22)) +>C : Symbol(C, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 0, 0)) +>a : Symbol(a, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 35)) +>t : Symbol(t, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 39)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 22)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 44)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 22)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 22)) + +declare function testRest(a: (t: T, t1: T, ...ts: T[]) => void): T +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 26)) +>C : Symbol(C, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 0, 0)) +>a : Symbol(a, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 39)) +>t : Symbol(t, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 43)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 26)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 48)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 26)) +>ts : Symbol(ts, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 55)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 26)) +>T : Symbol(T, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 10, 26)) + + +// exactly +test((t1: D, t2) => { t2.test2 }) +>test : Symbol(test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 6, 1)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 14, 6)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 14, 12)) +>t2.test2 : Symbol(D.test2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 4, 19)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 14, 12)) +>test2 : Symbol(D.test2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 4, 19)) + +test((t1, t2: D) => { t2.test2 }) +>test : Symbol(test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 6, 1)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 15, 6)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 15, 9)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) +>t2.test2 : Symbol(D.test2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 4, 19)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 15, 9)) +>test2 : Symbol(D.test2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 4, 19)) + +// zero arg +test(() => {}) +>test : Symbol(test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 6, 1)) + +// fewer args +test((t1: D) => {}) +>test : Symbol(test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 6, 1)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 21, 6)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) + +// rest arg +test((...ts: D[]) => {}) +>test : Symbol(test, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 6, 1)) +>ts : Symbol(ts, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 24, 6)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) + +// source function has rest arg +testRest((t1: D) => {}) +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 27, 10)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) + +testRest((t1, t2, t3) => {}) +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 28, 10)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 28, 13)) +>t3 : Symbol(t3, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 28, 17)) + +testRest((t1: D, t2, t3) => {}) +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 29, 10)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 29, 16)) +>t3 : Symbol(t3, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 29, 20)) + +testRest((t1, t2: D, t3) => {}) +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>t1 : Symbol(t1, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 30, 10)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 30, 13)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) +>t3 : Symbol(t3, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 30, 20)) + +testRest((t2: D, ...t3) => {}) +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 31, 10)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) +>t3 : Symbol(t3, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 31, 16)) + +testRest((t2, ...t3: D[]) => {}) +>testRest : Symbol(testRest, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 8, 63)) +>t2 : Symbol(t2, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 32, 10)) +>t3 : Symbol(t3, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 32, 13)) +>D : Symbol(D, Decl(partiallyAnnotatedFunctionInferenceWithTypeParameter.ts, 2, 1)) + diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.types b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.types new file mode 100644 index 0000000000000..c2113ae4d75d9 --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionInferenceWithTypeParameter.types @@ -0,0 +1,136 @@ +=== tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceWithTypeParameter.ts === +class C { +>C : C + + test: string +>test : string +} + +class D extends C { +>D : D +>C : C + + test2: string +>test2 : string +} + +declare function test(a: (t: T, t1: T) => void): T +>test : (a: (t: T, t1: T) => void) => T +>T : T +>C : C +>a : (t: T, t1: T) => void +>t : T +>T : T +>t1 : T +>T : T +>T : T + +declare function testRest(a: (t: T, t1: T, ...ts: T[]) => void): T +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>T : T +>C : C +>a : (t: T, t1: T, ...ts: T[]) => void +>t : T +>T : T +>t1 : T +>T : T +>ts : T[] +>T : T +>T : T + + +// exactly +test((t1: D, t2) => { t2.test2 }) +>test((t1: D, t2) => { t2.test2 }) : D +>test : (a: (t: T, t1: T) => void) => T +>(t1: D, t2) => { t2.test2 } : (t1: D, t2: D) => void +>t1 : D +>D : D +>t2 : D +>t2.test2 : string +>t2 : D +>test2 : string + +test((t1, t2: D) => { t2.test2 }) +>test((t1, t2: D) => { t2.test2 }) : D +>test : (a: (t: T, t1: T) => void) => T +>(t1, t2: D) => { t2.test2 } : (t1: D, t2: D) => void +>t1 : D +>t2 : D +>D : D +>t2.test2 : string +>t2 : D +>test2 : string + +// zero arg +test(() => {}) +>test(() => {}) : C +>test : (a: (t: T, t1: T) => void) => T +>() => {} : () => void + +// fewer args +test((t1: D) => {}) +>test((t1: D) => {}) : D +>test : (a: (t: T, t1: T) => void) => T +>(t1: D) => {} : (t1: D) => void +>t1 : D +>D : D + +// rest arg +test((...ts: D[]) => {}) +>test((...ts: D[]) => {}) : D +>test : (a: (t: T, t1: T) => void) => T +>(...ts: D[]) => {} : (...ts: D[]) => void +>ts : D[] +>D : D + +// source function has rest arg +testRest((t1: D) => {}) +>testRest((t1: D) => {}) : D +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>(t1: D) => {} : (t1: D) => void +>t1 : D +>D : D + +testRest((t1, t2, t3) => {}) +>testRest((t1, t2, t3) => {}) : C +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>(t1, t2, t3) => {} : (t1: C, t2: C, t3: C) => void +>t1 : C +>t2 : C +>t3 : C + +testRest((t1: D, t2, t3) => {}) +>testRest((t1: D, t2, t3) => {}) : D +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>(t1: D, t2, t3) => {} : (t1: D, t2: D, t3: D) => void +>t1 : D +>D : D +>t2 : D +>t3 : D + +testRest((t1, t2: D, t3) => {}) +>testRest((t1, t2: D, t3) => {}) : D +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>(t1, t2: D, t3) => {} : (t1: D, t2: D, t3: D) => void +>t1 : D +>t2 : D +>D : D +>t3 : D + +testRest((t2: D, ...t3) => {}) +>testRest((t2: D, ...t3) => {}) : any +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>(t2: D, ...t3) => {} : (t2: D, ...t3: any[]) => void +>t2 : D +>D : D +>t3 : any[] + +testRest((t2, ...t3: D[]) => {}) +>testRest((t2, ...t3: D[]) => {}) : C +>testRest : (a: (t: T, t1: T, ...ts: T[]) => void) => T +>(t2, ...t3: D[]) => {} : (t2: C, ...t3: D[]) => void +>t2 : C +>t3 : D[] +>D : D + diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.js b/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.js new file mode 100644 index 0000000000000..8b81ff506fe14 --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.js @@ -0,0 +1,12 @@ +//// [partiallyAnnotatedFunctionWitoutTypeParameter.ts] + +// simple case +declare function simple(f: (a: number, b: number) => void): {} + +simple((a: number, b) => {}) +simple((a, b: number) => {}) + + +//// [partiallyAnnotatedFunctionWitoutTypeParameter.js] +simple(function (a, b) { }); +simple(function (a, b) { }); diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.symbols b/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.symbols new file mode 100644 index 0000000000000..a7ed6b67d8317 --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.symbols @@ -0,0 +1,19 @@ +=== tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitoutTypeParameter.ts === + +// simple case +declare function simple(f: (a: number, b: number) => void): {} +>simple : Symbol(simple, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 0, 0)) +>f : Symbol(f, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 2, 24)) +>a : Symbol(a, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 2, 28)) +>b : Symbol(b, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 2, 38)) + +simple((a: number, b) => {}) +>simple : Symbol(simple, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 0, 0)) +>a : Symbol(a, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 4, 8)) +>b : Symbol(b, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 4, 18)) + +simple((a, b: number) => {}) +>simple : Symbol(simple, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 0, 0)) +>a : Symbol(a, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 5, 8)) +>b : Symbol(b, Decl(partiallyAnnotatedFunctionWitoutTypeParameter.ts, 5, 10)) + diff --git a/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.types b/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.types new file mode 100644 index 0000000000000..f07cd5a8928b8 --- /dev/null +++ b/tests/baselines/reference/partiallyAnnotatedFunctionWitoutTypeParameter.types @@ -0,0 +1,23 @@ +=== tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitoutTypeParameter.ts === + +// simple case +declare function simple(f: (a: number, b: number) => void): {} +>simple : (f: (a: number, b: number) => void) => {} +>f : (a: number, b: number) => void +>a : number +>b : number + +simple((a: number, b) => {}) +>simple((a: number, b) => {}) : {} +>simple : (f: (a: number, b: number) => void) => {} +>(a: number, b) => {} : (a: number, b: number) => void +>a : number +>b : number + +simple((a, b: number) => {}) +>simple((a, b: number) => {}) : {} +>simple : (f: (a: number, b: number) => void) => {} +>(a, b: number) => {} : (a: number, b: number) => void +>a : number +>b : number + diff --git a/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts b/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts new file mode 100644 index 0000000000000..867b6526c1277 --- /dev/null +++ b/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceError.ts @@ -0,0 +1,14 @@ +class C { + test: string +} + +class D extends C { + test2: string +} + +declare function testError(a: (t: T, t1: T) => void): T + +// more args +testError((t1: D, t2, t3) => {}) +testError((t1, t2: D, t3) => {}) +testError((t1, t2, t3: D) => {}) diff --git a/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceWithTypeParameter.ts b/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceWithTypeParameter.ts new file mode 100644 index 0000000000000..530d506f64cf2 --- /dev/null +++ b/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionInferenceWithTypeParameter.ts @@ -0,0 +1,33 @@ +class C { + test: string +} + +class D extends C { + test2: string +} + +declare function test(a: (t: T, t1: T) => void): T + +declare function testRest(a: (t: T, t1: T, ...ts: T[]) => void): T + + +// exactly +test((t1: D, t2) => { t2.test2 }) +test((t1, t2: D) => { t2.test2 }) + +// zero arg +test(() => {}) + +// fewer args +test((t1: D) => {}) + +// rest arg +test((...ts: D[]) => {}) + +// source function has rest arg +testRest((t1: D) => {}) +testRest((t1, t2, t3) => {}) +testRest((t1: D, t2, t3) => {}) +testRest((t1, t2: D, t3) => {}) +testRest((t2: D, ...t3) => {}) +testRest((t2, ...t3: D[]) => {}) diff --git a/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitoutTypeParameter.ts b/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitoutTypeParameter.ts new file mode 100644 index 0000000000000..994df11e247f7 --- /dev/null +++ b/tests/cases/conformance/types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitoutTypeParameter.ts @@ -0,0 +1,7 @@ +// @noImplicitAny: true + +// simple case +declare function simple(f: (a: number, b: number) => void): {} + +simple((a: number, b) => {}) +simple((a, b: number) => {}) From 8aa56c1ccedb4070a8d6d8f3f703cd80b9841317 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 17 Oct 2016 09:12:15 -0700 Subject: [PATCH 13/24] Add fourslash test for contextually-typed `this` Regression test for #10972 --- tests/cases/fourslash/memberListOnContextualThis.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tests/cases/fourslash/memberListOnContextualThis.ts diff --git a/tests/cases/fourslash/memberListOnContextualThis.ts b/tests/cases/fourslash/memberListOnContextualThis.ts new file mode 100644 index 0000000000000..7eeb67dc62046 --- /dev/null +++ b/tests/cases/fourslash/memberListOnContextualThis.ts @@ -0,0 +1,12 @@ +/// +////interface A { +//// a: string; +////} +////declare function ctx(callback: (this: A) => string): string; +////ctx(function () { return th/*1*/is./*2*/a }); + +goTo.marker('1'); +verify.quickInfoIs("this: A"); +goTo.marker('2'); +verify.memberListContains('a', '(property) A.a: string'); + From 6a59948ea125bc8c7d0205ef732f451a706bf68b Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 17 Oct 2016 09:46:26 -0700 Subject: [PATCH 14/24] Add lib-concatting newlines to jakefile as well --- Jakefile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/Jakefile.js b/Jakefile.js index 64a8553ef39dc..18cafccd4e423 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -355,6 +355,7 @@ function concatenateFiles(destinationFile, sourceFiles) { if (!fs.existsSync(sourceFiles[i])) { fail(sourceFiles[i] + " does not exist!"); } + fs.appendFileSync(temp, "\n\n"); fs.appendFileSync(temp, fs.readFileSync(sourceFiles[i])); } // Move the file to the final destination From 4c5a72831466c2738c81dfe3fa5634c11ae093a0 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 17 Oct 2016 10:15:13 -0700 Subject: [PATCH 15/24] Don't use ternary operator --- src/server/scriptInfo.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 2792b3e47a963..78127925958ec 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -84,7 +84,10 @@ namespace ts.server { } getDefaultProject() { - return this.containingProjects.length === 0 ? Errors.ThrowNoProject() : this.containingProjects[0]; + if (this.containingProjects.length === 0) { + return Errors.ThrowNoProject(); + } + return this.containingProjects[0]; } setFormatOptions(formatSettings: FormatCodeSettings): void { From b71e8a21679d5c0b5020802b8851d109ec0d1a32 Mon Sep 17 00:00:00 2001 From: Jason Ramsay Date: Mon, 17 Oct 2016 13:11:13 -0700 Subject: [PATCH 16/24] Add isSemantic check to getDiagnosticsWorker --- src/server/session.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/session.ts b/src/server/session.ts index 3df6a1acb5126..40110d94d53f5 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -389,9 +389,9 @@ namespace ts.server { }); } - private getDiagnosticsWorker(args: protocol.FileRequestArgs, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) { + private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) { const { project, file } = this.getFileAndProject(args); - if (shouldSkipSematicCheck(project)) { + if (isSemantic && shouldSkipSematicCheck(project)) { return []; } const scriptInfo = project.getScriptInfoForNormalizedPath(file); @@ -492,11 +492,11 @@ namespace ts.server { } private getSyntacticDiagnosticsSync(args: protocol.SyntacticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] { - return this.getDiagnosticsWorker(args, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition); + return this.getDiagnosticsWorker(args, /*isSemantic*/ false, (project, file) => project.getLanguageService().getSyntacticDiagnostics(file), args.includeLinePosition); } private getSemanticDiagnosticsSync(args: protocol.SemanticDiagnosticsSyncRequestArgs): protocol.Diagnostic[] | protocol.DiagnosticWithLinePosition[] { - return this.getDiagnosticsWorker(args, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition); + return this.getDiagnosticsWorker(args, /*isSemantic*/ true, (project, file) => project.getLanguageService().getSemanticDiagnostics(file), args.includeLinePosition); } private getDocumentHighlights(args: protocol.DocumentHighlightsRequestArgs, simplifiedResult: boolean): protocol.DocumentHighlightsItem[] | DocumentHighlights[] { From 45253f85cf69f17daf401cc2b02cd8cb1c788b83 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 17 Oct 2016 14:00:49 -0700 Subject: [PATCH 17/24] Remove baseline-accept warning from CONTRIBUTING It's not longer true. You can baseline-accept after running just a few tests. --- CONTRIBUTING.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1c24202297998..6dbb7e514a0da 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -183,5 +183,3 @@ jake baseline-accept ``` to establish the new baselines as the desired behavior. This will change the files in `tests\baselines\reference`, which should be included as part of your commit. It's important to carefully validate changes in the baselines. - -**Note** that `baseline-accept` should only be run after a full test run! Accepting baselines after running a subset of tests will delete baseline files for the tests that didn't run. From 09b9ea5507b8b70d5a7c9e325e2d7126b17404d9 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 17 Oct 2016 14:29:24 -0700 Subject: [PATCH 18/24] address PR feedback --- src/compiler/binder.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 31732bc833f7b..086ec9dd927a8 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1002,7 +1002,7 @@ namespace ts { } if (node.finallyBlock) { // in finally flow is combined from pre-try/flow from try/flow from catch - // pre-flow is necessary to make sure that finally is reachable even if finaly flows in both try and finally blocks are unreachable + // pre-flow is necessary to make sure that finally is reachable even if finally flows in both try and finally blocks are unreachable addAntecedent(preFinallyLabel, preTryFlow); currentFlow = finishFlowLabel(preFinallyLabel); bind(node.finallyBlock); @@ -1014,7 +1014,7 @@ namespace ts { // console.log(2); // this line should be unreachable even if flow falls out of finally block if (!(currentFlow.flags & FlowFlags.Unreachable)) { if ((flowAfterTry.flags & FlowFlags.Unreachable) && (flowAfterCatch.flags & FlowFlags.Unreachable)) { - currentFlow = flowAfterTry == reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow + currentFlow = flowAfterTry === reportedUnreachableFlow || flowAfterCatch === reportedUnreachableFlow ? reportedUnreachableFlow : unreachableFlow; } From af52b6314c553195474ba11d38b4b952ef2f15fa Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 17 Oct 2016 15:34:03 -0700 Subject: [PATCH 19/24] Address CR feedback --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index db95eb9bc17bd..41fc483f4ee80 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6114,7 +6114,7 @@ namespace ts { // know that all parameters (including 'this') have type annotations and nothing is // subject to contextual typing. const parameter = firstOrUndefined(node.parameters); - return !(parameter && parameter.name.kind === SyntaxKind.Identifier && (parameter.name).text === "this"); + return !(parameter && parameterIsThisKeyword(parameter)); } function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | ArrowFunction | MethodDeclaration { From 05ebd1d5fb464405a7b7112b969d740fb3879b71 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 17 Oct 2016 15:46:05 -0700 Subject: [PATCH 20/24] Merge pull request #11651 from Microsoft/vladima/literals-in-protocol switch enums in protocol to unions of literal types --- scripts/buildProtocol.ts | 69 +++++++++---- src/harness/unittests/session.ts | 69 ++++++++++--- src/server/editorServices.ts | 85 ++++++++++++++-- src/server/protocol.ts | 163 +++++++++++++++++++++++++++++-- src/server/session.ts | 28 ++---- 5 files changed, 346 insertions(+), 68 deletions(-) diff --git a/scripts/buildProtocol.ts b/scripts/buildProtocol.ts index 55ad086815c68..66f29f577d933 100644 --- a/scripts/buildProtocol.ts +++ b/scripts/buildProtocol.ts @@ -10,6 +10,8 @@ function endsWith(s: string, suffix: string) { class DeclarationsWalker { private visitedTypes: ts.Type[] = []; private text = ""; + private removedTypes: ts.Type[] = []; + private constructor(private typeChecker: ts.TypeChecker, private protocolFile: ts.SourceFile) { } @@ -17,9 +19,18 @@ class DeclarationsWalker { let text = "declare namespace ts.server.protocol {\n"; var walker = new DeclarationsWalker(typeChecker, protocolFile); walker.visitTypeNodes(protocolFile); - return walker.text + text = walker.text ? `declare namespace ts.server.protocol {\n${walker.text}}` : ""; + if (walker.removedTypes) { + text += "\ndeclare namespace ts {\n"; + text += " // these types are empty stubs for types from services and should not be used directly\n" + for (const type of walker.removedTypes) { + text += ` export type ${type.symbol.name} = never;\n`; + } + text += "}" + } + return text; } private processType(type: ts.Type): void { @@ -41,19 +52,18 @@ class DeclarationsWalker { if (sourceFile === this.protocolFile || path.basename(sourceFile.fileName) === "lib.d.ts") { return; } - // splice declaration in final d.ts file - let text = decl.getFullText(); - if (decl.kind === ts.SyntaxKind.EnumDeclaration && !(decl.flags & ts.NodeFlags.Const)) { - // patch enum declaration to make them constan - const declStart = decl.getStart() - decl.getFullStart(); - const prefix = text.substring(0, declStart); - const suffix = text.substring(declStart + "enum".length, decl.getEnd() - decl.getFullStart()); - text = prefix + "const enum" + suffix; + if (decl.kind === ts.SyntaxKind.EnumDeclaration) { + this.removedTypes.push(type); + return; } - this.text += `${text}\n`; + else { + // splice declaration in final d.ts file + let text = decl.getFullText(); + this.text += `${text}\n`; + // recursively pull all dependencies into result dts file - // recursively pull all dependencies into result dts file - this.visitTypeNodes(decl); + this.visitTypeNodes(decl); + } } } } @@ -69,15 +79,37 @@ class DeclarationsWalker { case ts.SyntaxKind.Parameter: case ts.SyntaxKind.IndexSignature: if (((node.parent).type) === node) { - const type = this.typeChecker.getTypeAtLocation(node); - if (type && !(type.flags & ts.TypeFlags.TypeParameter)) { - this.processType(type); - } + this.processTypeOfNode(node); } break; + case ts.SyntaxKind.InterfaceDeclaration: + const heritageClauses = (node.parent).heritageClauses; + if (heritageClauses) { + if (heritageClauses[0].token !== ts.SyntaxKind.ExtendsKeyword) { + throw new Error(`Unexpected kind of heritage clause: ${ts.SyntaxKind[heritageClauses[0].kind]}`); + } + for (const type of heritageClauses[0].types) { + this.processTypeOfNode(type); + } + } + break; } } ts.forEachChild(node, n => this.visitTypeNodes(n)); + } + + private processTypeOfNode(node: ts.Node): void { + if (node.kind === ts.SyntaxKind.UnionType) { + for (const t of (node).types) { + this.processTypeOfNode(t); + } + } + else { + const type = this.typeChecker.getTypeAtLocation(node); + if (type && !(type.flags & (ts.TypeFlags.TypeParameter))) { + this.processType(type); + } + } } } @@ -128,9 +160,12 @@ function generateProtocolFile(protocolTs: string, typeScriptServicesDts: string) if (extraDeclarations) { protocolDts += extraDeclarations; } + protocolDts += "\nimport protocol = ts.server.protocol;"; + protocolDts += "\nexport = protocol;"; + protocolDts += "\nexport as namespace protocol;"; // do sanity check and try to compile generated text as standalone program const sanityCheckProgram = getProgramWithProtocolText(protocolDts, /*includeTypeScriptServices*/ false); - const diagnostics = [...program.getSyntacticDiagnostics(), ...program.getSemanticDiagnostics(), ...program.getGlobalDiagnostics()]; + const diagnostics = [...sanityCheckProgram.getSyntacticDiagnostics(), ...sanityCheckProgram.getSemanticDiagnostics(), ...sanityCheckProgram.getGlobalDiagnostics()]; if (diagnostics.length) { const flattenedDiagnostics = diagnostics.map(d => ts.flattenDiagnosticMessageText(d.messageText, "\n")).join("\n"); throw new Error(`Unexpected errors during sanity check: ${flattenedDiagnostics}`); diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index badbbaf526b7a..9099f0a4285d1 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -39,12 +39,18 @@ namespace ts.server { getLogFileName: (): string => undefined }; + class TestSession extends Session { + getProjectService() { + return this.projectService; + } + } + describe("the Session class", () => { - let session: Session; + let session: TestSession; let lastSent: protocol.Message; beforeEach(() => { - session = new Session(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true); + session = new TestSession(mockHost, nullCancellationToken, /*useOneInferredProject*/ false, /*typingsInstaller*/ undefined, Utils.byteLength, process.hrtime, mockLogger, /*canUseEvents*/ true); session.send = (msg: protocol.Message) => { lastSent = msg; }; @@ -55,7 +61,7 @@ namespace ts.server { const req: protocol.FileRequest = { command: CommandNames.Open, seq: 0, - type: "command", + type: "request", arguments: { file: undefined } @@ -67,7 +73,7 @@ namespace ts.server { const req: protocol.Request = { command: "foobar", seq: 0, - type: "command" + type: "request" }; session.executeCommand(req); @@ -85,7 +91,7 @@ namespace ts.server { const req: protocol.ConfigureRequest = { command: CommandNames.Configure, seq: 0, - type: "command", + type: "request", arguments: { hostInfo: "unit test", formatOptions: { @@ -106,6 +112,47 @@ namespace ts.server { body: undefined }); }); + it ("should handle literal types in request", () => { + const configureRequest: protocol.ConfigureRequest = { + command: CommandNames.Configure, + seq: 0, + type: "request", + arguments: { + formatOptions: { + indentStyle: "Block" + } + } + }; + + session.onMessage(JSON.stringify(configureRequest)); + + assert.equal(session.getProjectService().getFormatCodeOptions().indentStyle, IndentStyle.Block); + + const setOptionsRequest: protocol.SetCompilerOptionsForInferredProjectsRequest = { + command: CommandNames.CompilerOptionsForInferredProjects, + seq: 1, + type: "request", + arguments: { + options: { + module: "System", + target: "ES5", + jsx: "React", + newLine: "Lf", + moduleResolution: "Node" + } + } + }; + session.onMessage(JSON.stringify(setOptionsRequest)); + assert.deepEqual( + session.getProjectService().getCompilerOptionsForInferredProjects(), + { + module: ModuleKind.System, + target: ScriptTarget.ES5, + jsx: JsxEmit.React, + newLine: NewLineKind.LineFeed, + moduleResolution: ModuleResolutionKind.NodeJs + }); + }); }); describe("onMessage", () => { @@ -118,7 +165,7 @@ namespace ts.server { const req: protocol.Request = { command: name, seq: i, - type: "command" + type: "request" }; i++; session.onMessage(JSON.stringify(req)); @@ -151,7 +198,7 @@ namespace ts.server { const req: protocol.ConfigureRequest = { command: CommandNames.Configure, seq: 0, - type: "command", + type: "request", arguments: { hostInfo: "unit test", formatOptions: { @@ -175,7 +222,7 @@ namespace ts.server { describe("send", () => { it("is an overrideable handle which sends protocol messages over the wire", () => { - const msg = { seq: 0, type: "none" }; + const msg: server.protocol.Request = { seq: 0, type: "request", command: "" }; const strmsg = JSON.stringify(msg); const len = 1 + Utils.byteLength(strmsg, "utf8"); const resultMsg = `Content-Length: ${len}\r\n\r\n${strmsg}\n`; @@ -203,7 +250,7 @@ namespace ts.server { expect(session.executeCommand({ command, seq: 0, - type: "command" + type: "request" })).to.deep.equal(result); }); it("throws when a duplicate handler is passed", () => { @@ -304,7 +351,7 @@ namespace ts.server { expect(session.executeCommand({ seq: 0, - type: "command", + type: "request", command: session.customHandler })).to.deep.equal({ response: undefined, @@ -405,7 +452,7 @@ namespace ts.server { this.seq++; this.server.enqueue({ seq: this.seq, - type: "command", + type: "request", command, arguments: args }); diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 54b257242fdeb..6556aa0146046 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -17,6 +17,68 @@ namespace ts.server { (event: ProjectServiceEvent): void; } + function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: CommandLineOption[]): Map> { + const map: Map> = createMap>(); + for (const option of commandLineOptions) { + if (typeof option.type === "object") { + const optionMap = >option.type; + // verify that map contains only numbers + for (const id in optionMap) { + Debug.assert(typeof optionMap[id] === "number"); + } + map[option.name] = optionMap; + } + } + return map; + } + + const compilerOptionConverters = prepareConvertersForEnumLikeCompilerOptions(optionDeclarations); + const indentStyle = createMap({ + "none": IndentStyle.None, + "block": IndentStyle.Block, + "smart": IndentStyle.Smart + }); + + export function convertFormatOptions(protocolOptions: protocol.FormatCodeSettings): FormatCodeSettings { + if (typeof protocolOptions.indentStyle === "string") { + protocolOptions.indentStyle = indentStyle[protocolOptions.indentStyle.toLowerCase()]; + Debug.assert(protocolOptions.indentStyle !== undefined); + } + return protocolOptions; + } + + export function convertCompilerOptions(protocolOptions: protocol.ExternalProjectCompilerOptions): CompilerOptions & protocol.CompileOnSaveMixin { + for (const id in compilerOptionConverters) { + const propertyValue = protocolOptions[id]; + if (typeof propertyValue === "string") { + const mappedValues = compilerOptionConverters[id]; + protocolOptions[id] = mappedValues[propertyValue.toLowerCase()]; + } + } + return protocolOptions; + } + + export function tryConvertScriptKindName(scriptKindName: protocol.ScriptKindName | ScriptKind): ScriptKind { + return typeof scriptKindName === "string" + ? convertScriptKindName(scriptKindName) + : scriptKindName; + } + + export function convertScriptKindName(scriptKindName: protocol.ScriptKindName) { + switch (scriptKindName) { + case "JS": + return ScriptKind.JS; + case "JSX": + return ScriptKind.JSX; + case "TS": + return ScriptKind.TS; + case "TSX": + return ScriptKind.TSX; + default: + return ScriptKind.Unknown; + } + } + /** * This helper function processes a list of projects and return the concatenated, sortd and deduplicated output of processing each project. */ @@ -63,7 +125,7 @@ namespace ts.server { const externalFilePropertyReader: FilePropertyReader = { getFileName: x => x.fileName, - getScriptKind: x => x.scriptKind, + getScriptKind: x => tryConvertScriptKindName(x.scriptKind), hasMixedContent: x => x.hasMixedContent }; @@ -214,6 +276,10 @@ namespace ts.server { this.ensureInferredProjectsUpToDate(); } + getCompilerOptionsForInferredProjects() { + return this.compilerOptionsForInferredProjects; + } + updateTypingsForProject(response: SetTypings | InvalidateCachedTypings): void { const project = this.findProject(response.projectName); if (!project) { @@ -231,10 +297,10 @@ namespace ts.server { } setCompilerOptionsForInferredProjects(projectCompilerOptions: protocol.ExternalProjectCompilerOptions): void { - this.compilerOptionsForInferredProjects = projectCompilerOptions; + this.compilerOptionsForInferredProjects = convertCompilerOptions(projectCompilerOptions); this.compileOnSaveForInferredProjects = projectCompilerOptions.compileOnSave; for (const proj of this.inferredProjects) { - proj.setCompilerOptions(projectCompilerOptions); + proj.setCompilerOptions(this.compilerOptionsForInferredProjects); proj.compileOnSaveEnabled = projectCompilerOptions.compileOnSave; } this.updateProjectGraphs(this.inferredProjects); @@ -744,12 +810,13 @@ namespace ts.server { } private createAndAddExternalProject(projectFileName: string, files: protocol.ExternalFile[], options: protocol.ExternalProjectCompilerOptions, typingOptions: TypingOptions) { + const compilerOptions = convertCompilerOptions(options); const project = new ExternalProject( projectFileName, this, this.documentRegistry, - options, - /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(options, files, externalFilePropertyReader), + compilerOptions, + /*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, files, externalFilePropertyReader), options.compileOnSave === undefined ? true : options.compileOnSave); this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typingOptions, /*configFileErrors*/ undefined); @@ -1018,7 +1085,7 @@ namespace ts.server { if (args.file) { const info = this.getScriptInfoForNormalizedPath(toNormalizedPath(args.file)); if (info) { - info.setFormatOptions(args.formatOptions); + info.setFormatOptions(convertFormatOptions(args.formatOptions)); this.logger.info(`Host configuration update for file ${args.file}`); } } @@ -1028,7 +1095,7 @@ namespace ts.server { this.logger.info(`Host information ${args.hostInfo}`); } if (args.formatOptions) { - mergeMaps(this.hostConfiguration.formatCodeOptions, args.formatOptions); + mergeMaps(this.hostConfiguration.formatCodeOptions, convertFormatOptions(args.formatOptions)); this.logger.info("Format host information updated"); } } @@ -1142,7 +1209,7 @@ namespace ts.server { const scriptInfo = this.getScriptInfo(file.fileName); Debug.assert(!scriptInfo || !scriptInfo.isOpen); const normalizedPath = scriptInfo ? scriptInfo.fileName : toNormalizedPath(file.fileName); - this.openClientFileWithNormalizedPath(normalizedPath, file.content, file.scriptKind, file.hasMixedContent); + this.openClientFileWithNormalizedPath(normalizedPath, file.content, tryConvertScriptKindName(file.scriptKind), file.hasMixedContent); } } @@ -1235,7 +1302,7 @@ namespace ts.server { if (externalProject) { if (!tsConfigFiles) { // external project already exists and not config files were added - update the project and return; - this.updateNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, proj.options, proj.typingOptions, proj.options.compileOnSave, /*configFileErrors*/ undefined); + this.updateNonInferredProject(externalProject, proj.rootFiles, externalFilePropertyReader, convertCompilerOptions(proj.options), proj.typingOptions, proj.options.compileOnSave, /*configFileErrors*/ undefined); return; } // some config files were added to external project (that previously were not there) diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 80623f05aec3a..7da95e49575f5 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -109,7 +109,7 @@ namespace ts.server.protocol { /** * One of "request", "response", or "event" */ - type: string; + type: "request" | "response" | "event"; } /** @@ -833,7 +833,7 @@ namespace ts.server.protocol { /** * Script kind of the file */ - scriptKind?: ScriptKind; + scriptKind?: ScriptKindName | ts.ScriptKind; /** * Whether file has mixed content (i.e. .cshtml file that combines html markup with C#/JavaScript) */ @@ -866,20 +866,23 @@ namespace ts.server.protocol { typingOptions?: TypingOptions; } - /** - * For external projects, some of the project settings are sent together with - * compiler settings. - */ - export interface ExternalProjectCompilerOptions extends CompilerOptions { + export interface CompileOnSaveMixin { /** * If compile on save is enabled for the project */ compileOnSave?: boolean; } + /** + * For external projects, some of the project settings are sent together with + * compiler settings. + */ + export type ExternalProjectCompilerOptions = CompilerOptions & CompileOnSaveMixin; + /** * Contains information about current project version */ + /* @internal */ export interface ProjectVersionInfo { /** * Project name @@ -896,7 +899,7 @@ namespace ts.server.protocol { /** * Current set of compiler options for project */ - options: CompilerOptions; + options: ts.CompilerOptions; } /** @@ -920,6 +923,7 @@ namespace ts.server.protocol { * if changes is set - then this is the set of changes that should be applied to existing project * otherwise - assume that nothing is changed */ + /* @internal */ export interface ProjectFiles { /** * Information abount project verison @@ -938,6 +942,7 @@ namespace ts.server.protocol { /** * Combines project information with project level errors. */ + /* @internal */ export interface ProjectFilesWithDiagnostics extends ProjectFiles { /** * List of errors in project @@ -1012,9 +1017,11 @@ namespace ts.server.protocol { * Used to specify the script kind of the file explicitly. It could be one of the following: * "TS", "JS", "TSX", "JSX" */ - scriptKindName?: "TS" | "JS" | "TSX" | "JSX"; + scriptKindName?: ScriptKindName; } + export type ScriptKindName = "TS" | "JS" | "TSX" | "JSX"; + /** * Open request; value of command field is "open". Notify the * server that the client has file open. The server will not @@ -1109,6 +1116,7 @@ namespace ts.server.protocol { /** * Arguments to SynchronizeProjectListRequest */ + /* @internal */ export interface SynchronizeProjectListRequestArgs { /** * List of last known projects @@ -2056,4 +2064,141 @@ namespace ts.server.protocol { export interface NavTreeResponse extends Response { body?: NavigationTree; } + + export namespace IndentStyle { + export type None = "None"; + export type Block = "Block"; + export type Smart = "Smart"; + } + + export type IndentStyle = IndentStyle.None | IndentStyle.Block | IndentStyle.Smart; + + export interface EditorSettings { + baseIndentSize?: number; + indentSize?: number; + tabSize?: number; + newLineCharacter?: string; + convertTabsToSpaces?: boolean; + indentStyle?: IndentStyle | ts.IndentStyle; + } + + export interface FormatCodeSettings extends EditorSettings { + insertSpaceAfterCommaDelimiter?: boolean; + insertSpaceAfterSemicolonInForStatements?: boolean; + insertSpaceBeforeAndAfterBinaryOperators?: boolean; + insertSpaceAfterKeywordsInControlFlowStatements?: boolean; + insertSpaceAfterFunctionKeywordForAnonymousFunctions?: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis?: boolean; + insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets?: boolean; + insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces?: boolean; + insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces?: boolean; + placeOpenBraceOnNewLineForFunctions?: boolean; + placeOpenBraceOnNewLineForControlBlocks?: boolean; + } + + export interface CompilerOptions { + allowJs?: boolean; + allowSyntheticDefaultImports?: boolean; + allowUnreachableCode?: boolean; + allowUnusedLabels?: boolean; + baseUrl?: string; + charset?: string; + declaration?: boolean; + declarationDir?: string; + disableSizeLimit?: boolean; + emitBOM?: boolean; + emitDecoratorMetadata?: boolean; + experimentalDecorators?: boolean; + forceConsistentCasingInFileNames?: boolean; + inlineSourceMap?: boolean; + inlineSources?: boolean; + isolatedModules?: boolean; + jsx?: JsxEmit | ts.JsxEmit; + lib?: string[]; + locale?: string; + mapRoot?: string; + maxNodeModuleJsDepth?: number; + module?: ModuleKind | ts.ModuleKind; + moduleResolution?: ModuleResolutionKind | ts.ModuleResolutionKind; + newLine?: NewLineKind | ts.NewLineKind; + noEmit?: boolean; + noEmitHelpers?: boolean; + noEmitOnError?: boolean; + noErrorTruncation?: boolean; + noFallthroughCasesInSwitch?: boolean; + noImplicitAny?: boolean; + noImplicitReturns?: boolean; + noImplicitThis?: boolean; + noUnusedLocals?: boolean; + noUnusedParameters?: boolean; + noImplicitUseStrict?: boolean; + noLib?: boolean; + noResolve?: boolean; + out?: string; + outDir?: string; + outFile?: string; + paths?: MapLike; + preserveConstEnums?: boolean; + project?: string; + reactNamespace?: string; + removeComments?: boolean; + rootDir?: string; + rootDirs?: string[]; + skipLibCheck?: boolean; + skipDefaultLibCheck?: boolean; + sourceMap?: boolean; + sourceRoot?: string; + strictNullChecks?: boolean; + suppressExcessPropertyErrors?: boolean; + suppressImplicitAnyIndexErrors?: boolean; + target?: ScriptTarget | ts.ScriptTarget; + traceResolution?: boolean; + types?: string[]; + /** Paths used to used to compute primary types search locations */ + typeRoots?: string[]; + [option: string]: CompilerOptionsValue | undefined; + } + + export namespace JsxEmit { + export type None = "None"; + export type Preserve = "Preserve"; + export type React = "React"; + } + + export type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React; + + export namespace ModuleKind { + export type None = "None"; + export type CommonJS = "CommonJS"; + export type AMD = "AMD"; + export type UMD = "UMD"; + export type System = "System"; + export type ES6 = "ES6"; + export type ES2015 = "ES2015"; + } + + export type ModuleKind = ModuleKind.None | ModuleKind.CommonJS | ModuleKind.AMD | ModuleKind.UMD | ModuleKind.System | ModuleKind.ES6 | ModuleKind.ES2015; + + export namespace ModuleResolutionKind { + export type Classic = "Classic"; + export type Node = "Node"; + } + + export type ModuleResolutionKind = ModuleResolutionKind.Classic | ModuleResolutionKind.Node; + + export namespace NewLineKind { + export type Crlf = "Crlf"; + export type Lf = "Lf"; + } + + export type NewLineKind = NewLineKind.Crlf | NewLineKind.Lf; + + export namespace ScriptTarget { + export type ES3 = "ES3"; + export type ES5 = "ES5"; + export type ES6 = "ES6"; + export type ES2015 = "ES2015"; + } + + export type ScriptTarget = ScriptTarget.ES3 | ScriptTarget.ES5 | ScriptTarget.ES6 | ScriptTarget.ES2015; } diff --git a/src/server/session.ts b/src/server/session.ts index 3df6a1acb5126..bf179c907732f 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -807,7 +807,7 @@ namespace ts.server { private getIndentation(args: protocol.IndentationRequestArgs) { const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args); const position = this.getPosition(args, project.getScriptInfoForNormalizedPath(file)); - const options = args.options || this.projectService.getFormatCodeOptions(file); + const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file); const indentation = project.getLanguageService(/*ensureSynchronized*/ false).getIndentationAtPosition(file, position, options); return { position, indentation }; } @@ -874,19 +874,19 @@ namespace ts.server { private getFormattingEditsForRangeFull(args: protocol.FormatRequestArgs) { const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args); - const options = args.options || this.projectService.getFormatCodeOptions(file); + const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file); return project.getLanguageService(/*ensureSynchronized*/ false).getFormattingEditsForRange(file, args.position, args.endPosition, options); } private getFormattingEditsForDocumentFull(args: protocol.FormatRequestArgs) { const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args); - const options = args.options || this.projectService.getFormatCodeOptions(file); + const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file); return project.getLanguageService(/*ensureSynchronized*/ false).getFormattingEditsForDocument(file, options); } private getFormattingEditsAfterKeystrokeFull(args: protocol.FormatOnKeyRequestArgs) { const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args); - const options = args.options || this.projectService.getFormatCodeOptions(file); + const options = args.options ? convertFormatOptions(args.options) : this.projectService.getFormatCodeOptions(file); return project.getLanguageService(/*ensureSynchronized*/ false).getFormattingEditsAfterKeystroke(file, args.position, args.key, options); } @@ -1426,24 +1426,8 @@ namespace ts.server { [CommandNames.RenameInfoFull]: (request: protocol.FileLocationRequest) => { return this.requiredResponse(this.getRenameInfo(request.arguments)); }, - [CommandNames.Open]: (request: protocol.Request) => { - const openArgs = request.arguments; - let scriptKind: ScriptKind; - switch (openArgs.scriptKindName) { - case "TS": - scriptKind = ScriptKind.TS; - break; - case "JS": - scriptKind = ScriptKind.JS; - break; - case "TSX": - scriptKind = ScriptKind.TSX; - break; - case "JSX": - scriptKind = ScriptKind.JSX; - break; - } - this.openClientFile(toNormalizedPath(openArgs.file), openArgs.fileContent, scriptKind); + [CommandNames.Open]: (request: protocol.OpenRequest) => { + this.openClientFile(toNormalizedPath(request.arguments.file), request.arguments.fileContent, convertScriptKindName(request.arguments.scriptKindName)); return this.notRequired(); }, [CommandNames.Quickinfo]: (request: protocol.QuickInfoRequest) => { From 722e72339209470858dde59a08e31d8a9a598ab8 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 17 Oct 2016 15:47:33 -0700 Subject: [PATCH 21/24] Include the correct file by default (#11685) --- src/compiler/utilities.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7d4a144407462..952a32052508e 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4172,7 +4172,7 @@ namespace ts { case ScriptTarget.ES2016: return "lib.es2016.d.ts"; case ScriptTarget.ES2015: - return "lib.es2015.d.ts"; + return "lib.es6.d.ts"; default: return "lib.d.ts"; From 28899f386011353aeee3ccb17accab03a927f444 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 17 Oct 2016 16:08:00 -0700 Subject: [PATCH 22/24] Update the resolveName symbol flags for 'require' resolution --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1354002a29e3b..7ac93d2e3186a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12538,7 +12538,7 @@ namespace ts { if (isInJavaScriptFile(node) && isRequireCall(node, /*checkArgumentIsStringLiteral*/true) && // Make sure require is not a local function - !resolveName(node.expression, (node.expression).text, SymbolFlags.Value | SymbolFlags.ExportValue, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) { + !resolveName(node.expression, (node.expression).text, SymbolFlags.Value, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)) { return resolveExternalModuleTypeByLiteral(node.arguments[0]); } From deb344907733d37822bb8e2f56b16f55d64c7c6c Mon Sep 17 00:00:00 2001 From: Jason Ramsay Date: Mon, 17 Oct 2016 14:50:03 -0700 Subject: [PATCH 23/24] Add getSyntacticDiagnostics unit test --- src/server/client.ts | 28 +++++++++++-------- .../getJavaScriptSyntacticDiagnostics01.ts | 23 +++++++++++++++ 2 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 tests/cases/fourslash/server/getJavaScriptSyntacticDiagnostics01.ts diff --git a/src/server/client.ts b/src/server/client.ts index b0bc2c5dac052..6d8ef419a7aae 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -424,33 +424,39 @@ namespace ts.server { } getSyntacticDiagnostics(fileName: string): Diagnostic[] { - const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file: fileName }; + const args: protocol.SyntacticDiagnosticsSyncRequestArgs = { file: fileName, includeLinePosition: true }; const request = this.processRequest(CommandNames.SyntacticDiagnosticsSync, args); const response = this.processResponse(request); - return (response.body).map(entry => this.convertDiagnostic(entry, fileName)); + return (response.body).map(entry => this.convertDiagnostic(entry, fileName)); } getSemanticDiagnostics(fileName: string): Diagnostic[] { - const args: protocol.SemanticDiagnosticsSyncRequestArgs = { file: fileName }; + const args: protocol.SemanticDiagnosticsSyncRequestArgs = { file: fileName, includeLinePosition: true }; const request = this.processRequest(CommandNames.SemanticDiagnosticsSync, args); const response = this.processResponse(request); - return (response.body).map(entry => this.convertDiagnostic(entry, fileName)); + return (response.body).map(entry => this.convertDiagnostic(entry, fileName)); } - convertDiagnostic(entry: protocol.Diagnostic, fileName: string): Diagnostic { - const start = this.lineOffsetToPosition(fileName, entry.start); - const end = this.lineOffsetToPosition(fileName, entry.end); + convertDiagnostic(entry: protocol.DiagnosticWithLinePosition, fileName: string): Diagnostic { + let category: DiagnosticCategory; + for (const id in DiagnosticCategory) { + if (typeof id === "string" && entry.category === id.toLowerCase()) { + category = (DiagnosticCategory)[id]; + } + } + + Debug.assert(category !== undefined, "convertDiagnostic: category should not be undefined"); return { file: undefined, - start: start, - length: end - start, - messageText: entry.text, - category: undefined, + start: entry.start, + length: entry.length, + messageText: entry.message, + category: category, code: entry.code }; } diff --git a/tests/cases/fourslash/server/getJavaScriptSyntacticDiagnostics01.ts b/tests/cases/fourslash/server/getJavaScriptSyntacticDiagnostics01.ts new file mode 100644 index 0000000000000..0aa88ebd90c90 --- /dev/null +++ b/tests/cases/fourslash/server/getJavaScriptSyntacticDiagnostics01.ts @@ -0,0 +1,23 @@ +/// + +// @allowJs: true +// @Filename: a.js +//// var ===; + +verify.getSyntacticDiagnostics(`[ + { + "message": "Variable declaration expected.", + "start": 4, + "length": 3, + "category": "error", + "code": 1134 + }, + { + "message": "Expression expected.", + "start": 7, + "length": 1, + "category": "error", + "code": 1109 + } +]`); +verify.getSemanticDiagnostics(`[]`); \ No newline at end of file From 121f51e5523a6bcc6ac6d3790f4cd7fee68ac2ab Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 17 Oct 2016 23:15:22 -0700 Subject: [PATCH 24/24] Merge pull request #11694 from Microsoft/vladima/reload-tmp allow reload from temp files --- .../unittests/tsserverProjectSystem.ts | 62 ++++++++++++++++++- src/server/project.ts | 4 +- src/server/scriptInfo.ts | 4 +- src/server/session.ts | 3 +- 4 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 9d086e4549e23..c3962c7749419 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -170,11 +170,18 @@ namespace ts.projectSystem { return host; } + class TestSession extends server.Session { + getProjectService() { + return this.projectService; + } + }; + export function createSession(host: server.ServerHost, typingsInstaller?: server.ITypingsInstaller, projectServiceEventHandler?: server.ProjectServiceEventHandler) { if (typingsInstaller === undefined) { typingsInstaller = new TestTypingsInstaller("/a/data/", /*throttleLimit*/5, host); } - return new server.Session(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ projectServiceEventHandler !== undefined, projectServiceEventHandler); + + return new TestSession(host, nullCancellationToken, /*useSingleInferredProject*/ false, typingsInstaller, Utils.byteLength, process.hrtime, nullLogger, /*canUseEvents*/ projectServiceEventHandler !== undefined, projectServiceEventHandler); } export interface CreateProjectServiceParameters { @@ -515,11 +522,13 @@ namespace ts.projectSystem { this.reloadFS(filesOrFolders); } + write(s: string) { + } + readonly readFile = (s: string) => (this.fs.get(this.toPath(s))).content; readonly resolvePath = (s: string) => s; readonly getExecutingFilePath = () => this.executingFilePath; readonly getCurrentDirectory = () => this.currentDirectory; - readonly write = (s: string) => notImplemented(); readonly exit = () => notImplemented(); readonly getEnvironmentVariable = (v: string) => notImplemented(); } @@ -2420,4 +2429,53 @@ namespace ts.projectSystem { assert.isTrue(inferredProject.containsFile(file1.path)); }); }); + + describe("reload", () => { + it("should work with temp file", () => { + const f1 = { + path: "/a/b/app.ts", + content: "let x = 1" + }; + const tmp = { + path: "/a/b/app.tmp", + content: "const y = 42" + }; + const host = createServerHost([f1, tmp]); + const session = createSession(host); + + // send open request + session.executeCommand({ + type: "request", + command: "open", + seq: 1, + arguments: { file: f1.path } + }); + + // reload from tmp file + session.executeCommand({ + type: "request", + command: "reload", + seq: 2, + arguments: { file: f1.path, tmpfile: tmp.path } + }); + + // verify content + const projectServiice = session.getProjectService(); + const snap1 = projectServiice.getScriptInfo(f1.path).snap(); + assert.equal(snap1.getText(0, snap1.getLength()), tmp.content, "content should be equal to the content of temp file"); + + // reload from original file file + session.executeCommand({ + type: "request", + command: "reload", + seq: 2, + arguments: { file: f1.path } + }); + + // verify content + const snap2 = projectServiice.getScriptInfo(f1.path).snap(); + assert.equal(snap2.getText(0, snap2.getLength()), f1.content, "content should be equal to the content of original file"); + + }); + }); } \ No newline at end of file diff --git a/src/server/project.ts b/src/server/project.ts index a355d75f94236..dd8902e83d1e3 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -437,11 +437,11 @@ namespace ts.server { } } - reloadScript(filename: NormalizedPath): boolean { + reloadScript(filename: NormalizedPath, tempFileName?: NormalizedPath): boolean { const script = this.projectService.getScriptInfoForNormalizedPath(filename); if (script) { Debug.assert(script.isAttached(this)); - script.reloadFromFile(); + script.reloadFromFile(tempFileName); return true; } return false; diff --git a/src/server/scriptInfo.ts b/src/server/scriptInfo.ts index 78127925958ec..84649863a7b3a 100644 --- a/src/server/scriptInfo.ts +++ b/src/server/scriptInfo.ts @@ -125,12 +125,12 @@ namespace ts.server { this.host.writeFile(fileName, snap.getText(0, snap.getLength())); } - reloadFromFile() { + reloadFromFile(tempFileName?: NormalizedPath) { if (this.hasMixedContent) { this.reload(""); } else { - this.svc.reloadFromFile(this.fileName); + this.svc.reloadFromFile(tempFileName || this.fileName); this.markContainingProjectsAsDirty(); } } diff --git a/src/server/session.ts b/src/server/session.ts index f029dc4a5d0f0..3bf4acd248622 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1076,11 +1076,12 @@ namespace ts.server { private reload(args: protocol.ReloadRequestArgs, reqSeq: number) { const file = toNormalizedPath(args.file); + const tempFileName = args.tmpfile && toNormalizedPath(args.tmpfile); const project = this.projectService.getDefaultProjectForFile(file, /*refreshInferredProjects*/ true); if (project) { this.changeSeq++; // make sure no changes happen before this one is finished - if (project.reloadScript(file)) { + if (project.reloadScript(file, tempFileName)) { this.output(undefined, CommandNames.Reload, reqSeq); } }