From dd0ed44b9aaa7dcd24bb415a5a6a241cd2d6061f Mon Sep 17 00:00:00 2001 From: David Sheldrick Date: Mon, 23 Jan 2017 17:40:20 +0100 Subject: [PATCH] Add option to output .js files while preserving jsx This commit adds the ability to preserve jsx in source code, but also to output .js files rather than .jsx files. This is useful for react-native which does not support .jsx files. --- lib/protocol.d.ts | 5 +- src/compiler/commandLineParser.ts | 3 +- src/compiler/diagnosticMessages.json | 2 +- src/compiler/types.ts | 3 +- src/harness/unittests/commandLineParsing.ts | 2 +- .../convertCompilerOptionsFromJson.ts | 2 +- src/harness/unittests/matchFiles.ts | 54 ++++++++++++++++- src/server/protocol.ts | 9 +-- tests/cases/unittests/matchFiles.ts | 58 ++++++++++++++++++- 9 files changed, 125 insertions(+), 13 deletions(-) diff --git a/lib/protocol.d.ts b/lib/protocol.d.ts index d6c0246af34..66c2ef5c8db 100644 --- a/lib/protocol.d.ts +++ b/lib/protocol.d.ts @@ -1798,9 +1798,10 @@ declare namespace ts.server.protocol { namespace JsxEmit { type None = "None"; type Preserve = "Preserve"; + type PreserveWithJsExtension = "PreserveWithJsExtension"; type React = "React"; } - type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React; + type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React | JsxEmit.PreserveWithJsExtension; namespace ModuleKind { type None = "None"; type CommonJS = "CommonJS"; @@ -1880,4 +1881,4 @@ declare namespace ts { } import protocol = ts.server.protocol; export = protocol; -export as namespace protocol; \ No newline at end of file +export as namespace protocol; diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index b222df53630..7c69676d6f0 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -67,10 +67,11 @@ namespace ts { name: "jsx", type: createMapFromTemplate({ "preserve": JsxEmit.Preserve, + "preservewithjsextension": JsxEmit.PreserveWithJsExtension, "react": JsxEmit.React }), paramType: Diagnostics.KIND, - description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react, + description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_preserveWithJsExtension_or_react, }, { name: "reactNamespace", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 43bb7415c88..6646017e73d 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2713,7 +2713,7 @@ "category": "Message", "code": 6079 }, - "Specify JSX code generation: 'preserve' or 'react'": { + "Specify JSX code generation: 'preserve', 'preserveWithJsExtension', or 'react'": { "category": "Message", "code": 6080 }, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index c16c199d3eb..9024b7c1b13 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3298,7 +3298,8 @@ export const enum JsxEmit { None = 0, Preserve = 1, - React = 2 + React = 2, + PreserveWithJsExtension = 3 } export const enum NewLineKind { diff --git a/src/harness/unittests/commandLineParsing.ts b/src/harness/unittests/commandLineParsing.ts index 8c691992043..34a096628f9 100644 --- a/src/harness/unittests/commandLineParsing.ts +++ b/src/harness/unittests/commandLineParsing.ts @@ -87,7 +87,7 @@ namespace ts { start: undefined, length: undefined, }, { - messageText: "Argument for '--jsx' option must be: 'preserve', 'react'", + messageText: "Argument for '--jsx' option must be: 'preserve', 'preservewithjsextension', 'react'", category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, diff --git a/src/harness/unittests/convertCompilerOptionsFromJson.ts b/src/harness/unittests/convertCompilerOptionsFromJson.ts index f44dc259710..cbfa47180f3 100644 --- a/src/harness/unittests/convertCompilerOptionsFromJson.ts +++ b/src/harness/unittests/convertCompilerOptionsFromJson.ts @@ -94,7 +94,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "Argument for '--jsx' option must be: 'preserve', 'react'", + messageText: "Argument for '--jsx' option must be: 'preserve', 'preservewithjsextension', 'react'", code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] diff --git a/src/harness/unittests/matchFiles.ts b/src/harness/unittests/matchFiles.ts index c562fcefe91..2b4bbfd4ee6 100644 --- a/src/harness/unittests/matchFiles.ts +++ b/src/harness/unittests/matchFiles.ts @@ -909,6 +909,31 @@ namespace ts { const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); assertParsed(actual, expected); }); + it("with jsx=preserveWithJsExtension, allowJs=false", () => { + const json = { + compilerOptions: { + jsx: "preserveWithJsExtension", + allowJs: false + } + }; + const expected: ts.ParsedCommandLine = { + options: { + jsx: ts.JsxEmit.PreserveWithJsExtension, + allowJs: false + }, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/b.tsx", + "c:/dev/c.tsx", + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + } + }; + const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); + assertParsed(actual, expected); + }); it("with jsx=none, allowJs=true", () => { const json = { compilerOptions: { @@ -961,6 +986,33 @@ namespace ts { const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); assertParsed(actual, expected); }); + it("with jsx=preserveWithJsExtension, allowJs=true", () => { + const json = { + compilerOptions: { + jsx: "preserveWithJsExtension", + allowJs: true + } + }; + const expected: ts.ParsedCommandLine = { + options: { + jsx: ts.JsxEmit.PreserveWithJsExtension, + allowJs: true + }, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/b.tsx", + "c:/dev/c.tsx", + "c:/dev/d.js", + "c:/dev/e.jsx", + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + } + }; + const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); + assertParsed(actual, expected); + }); it("exclude .min.js files using wildcards", () => { const json = { compilerOptions: { @@ -1306,4 +1358,4 @@ namespace ts { }); }); }); -} \ No newline at end of file +} diff --git a/src/server/protocol.ts b/src/server/protocol.ts index 680b81dff99..b18c887126b 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -417,7 +417,7 @@ namespace ts.server.protocol { startOffset: number; /** - * Position (can be specified instead of line/offset pair) + * Position (can be specified instead of line/offset pair) */ /* @internal */ startPosition?: number; @@ -433,7 +433,7 @@ namespace ts.server.protocol { endOffset: number; /** - * Position (can be specified instead of line/offset pair) + * Position (can be specified instead of line/offset pair) */ /* @internal */ endPosition?: number; @@ -445,7 +445,7 @@ namespace ts.server.protocol { } /** - * Response for GetCodeFixes request. + * Response for GetCodeFixes request. */ export interface GetCodeFixesResponse extends Response { body?: CodeAction[]; @@ -2272,10 +2272,11 @@ namespace ts.server.protocol { export namespace JsxEmit { export type None = "None"; export type Preserve = "Preserve"; + export type PreserveWithJsExtension = "PreserveWithJsExtension"; export type React = "React"; } - export type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React; + export type JsxEmit = JsxEmit.None | JsxEmit.Preserve | JsxEmit.React | JsxEmit.PreserveWithJsExtension; export namespace ModuleKind { export type None = "None"; diff --git a/tests/cases/unittests/matchFiles.ts b/tests/cases/unittests/matchFiles.ts index 91be2de8747..ef982f5f2bb 100644 --- a/tests/cases/unittests/matchFiles.ts +++ b/tests/cases/unittests/matchFiles.ts @@ -898,6 +898,33 @@ namespace ts { assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories); assert.deepEqual(actual.errors, expected.errors); }); + it("with jsx=preserveWithJsExtension, allowJs=false", () => { + const json = { + compilerOptions: { + jsx: "preserveWithJsExtension", + allowJs: false + } + }; + const expected: ts.ParsedCommandLine = { + options: { + jsx: ts.JsxEmit.PreserveWithJsExtension, + allowJs: false + }, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/b.tsx", + "c:/dev/c.tsx", + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + } + }; + const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); + assert.deepEqual(actual.fileNames, expected.fileNames); + assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories); + assert.deepEqual(actual.errors, expected.errors); + }); it("with jsx=none, allowJs=true", () => { const json = { compilerOptions: { @@ -954,6 +981,35 @@ namespace ts { assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories); assert.deepEqual(actual.errors, expected.errors); }); + it("with jsx=preserveWithJsExtension, allowJs=true", () => { + const json = { + compilerOptions: { + jsx: "preserveWithJsExtension", + allowJs: true + } + }; + const expected: ts.ParsedCommandLine = { + options: { + jsx: ts.JsxEmit.PreserveWithJsExtension, + allowJs: true + }, + errors: [], + fileNames: [ + "c:/dev/a.ts", + "c:/dev/b.tsx", + "c:/dev/c.tsx", + "c:/dev/d.js", + "c:/dev/e.jsx", + ], + wildcardDirectories: { + "c:/dev": ts.WatchDirectoryFlags.Recursive + } + }; + const actual = ts.parseJsonConfigFileContent(json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath); + assert.deepEqual(actual.fileNames, expected.fileNames); + assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories); + assert.deepEqual(actual.errors, expected.errors); + }); describe("with trailing recursive directory", () => { it("in includes", () => { const json = { @@ -1149,4 +1205,4 @@ namespace ts { }); }); }); -} \ No newline at end of file +}