From 4e2febf1bbd3d8aaaf2261cf52fcd2f4770fde9c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 17 Apr 2024 15:21:19 -0700 Subject: [PATCH 1/6] Add transpileDeclaration API entrypoint --- src/services/transpile.ts | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 084413a701b2f..4dc4391d919ac 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -51,14 +51,37 @@ const optionsRedundantWithVerbatimModuleSyntax = new Set([ /* * This function will compile source text from 'input' argument using specified compiler options. - * If not options are provided - it will use a set of default compiler options. + * If no options are provided - it will use a set of default compiler options. * Extra compiler options that will unconditionally be used by this function are: * - isolatedModules = true * - allowNonTsExtensions = true * - noLib = true * - noResolve = true + * - declaration = false */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { + return transpileWorker(input, transpileOptions, /*declarations*/ false); +} + +/* + * This function will create a declaration file from 'input' argument using specified compiler options. + * If no options are provided - it will use a set of default compiler options. + * Extra compiler options that will unconditionally be used by this function are: + * - isolatedModules = true + * - allowNonTsExtensions = true + * - noLib = true + * - noResolve = true + * - declaration = true + * - emitDeclarationOnly = true + * - declarationDir = undefined + * Note that this declaration file may differ from one produced by a full program typecheck, + * in that only types in the single input file are available to be used in the generated declarations. + */ +export function transpileDeclaration(input: string, transpileOptions: TranspileOptions): TranspileOutput { + return transpileWorker(input, transpileOptions, /*declarations*/ true); +} + +function transpileWorker(input: string, transpileOptions: TranspileOptions, declaration?: boolean): TranspileOutput { const diagnostics: Diagnostic[] = []; const options: CompilerOptions = transpileOptions.compilerOptions ? fixupCompilerOptions(transpileOptions.compilerOptions, diagnostics) : {}; @@ -86,6 +109,15 @@ export function transpileModule(input: string, transpileOptions: TranspileOption // Filename can be non-ts file. options.allowNonTsExtensions = true; + if (declaration) { + options.declaration = true; + options.declarationDir = undefined; + options.emitDeclarationOnly = true; + } + else { + options.declaration = false; + } + const newLine = getNewLineCharacter(options); // Create a compilerHost object to allow the compiler to read and write files const compilerHost: CompilerHost = { From 425ffd05be82cede70600ba080556c71b3d82012 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 19 Apr 2024 11:18:07 -0700 Subject: [PATCH 2/6] Small changes, API baseline update --- src/services/transpile.ts | 4 +--- tests/baselines/reference/api/typescript.d.ts | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 4dc4391d919ac..a3cbadfcc4616 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -73,7 +73,6 @@ export function transpileModule(input: string, transpileOptions: TranspileOption * - noResolve = true * - declaration = true * - emitDeclarationOnly = true - * - declarationDir = undefined * Note that this declaration file may differ from one produced by a full program typecheck, * in that only types in the single input file are available to be used in the generated declarations. */ @@ -111,7 +110,6 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl if (declaration) { options.declaration = true; - options.declarationDir = undefined; options.emitDeclarationOnly = true; } else { @@ -174,7 +172,7 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } // Emit - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ undefined, transpileOptions.transformers); + program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ declaration, transpileOptions.transformers); if (outputText === undefined) return Debug.fail("Output generation failed"); diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index ad1b05ed05eb7..7fa959ec00be4 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -11195,6 +11195,7 @@ declare namespace ts { }; function preProcessFile(sourceText: string, readImportFiles?: boolean, detectJavaScriptImports?: boolean): PreProcessedFileInfo; function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput; + function transpileDeclaration(input: string, transpileOptions: TranspileOptions): TranspileOutput; function transpile(input: string, compilerOptions?: CompilerOptions, fileName?: string, diagnostics?: Diagnostic[], moduleName?: string): string; interface TranspileOptions { compilerOptions?: CompilerOptions; From 26cae5bb45a6c757d3d7cc17bebff088686fc03e Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 19 Apr 2024 15:19:43 -0700 Subject: [PATCH 3/6] New transpile runner for harness, transpile tests and a bugfix --- src/compiler/emitter.ts | 2 +- src/harness/harnessIO.ts | 1 + src/harness/runnerbase.ts | 2 +- src/services/transpile.ts | 37 ++++- src/testRunner/_namespaces/Harness.ts | 1 + src/testRunner/runner.ts | 9 ++ src/testRunner/transpileRunner.ts | 132 +++++++++++++++++ .../transpile/declarationBasicSyntax.d.ts | 90 ++++++++++++ .../transpile/declarationBasicSyntax.js | 138 ++++++++++++++++++ .../declarationCrossFileInferences.d.ts | 22 +++ .../declarationCrossFileInferences.js | 37 +++++ .../transpile/declarationLinkedAliases.d.ts | 8 + .../transpile/declarationLinkedAliases.js | 11 ++ .../declarationSingleFileHasErrors.d.ts | 4 + .../declarationSingleFileHasErrors.js | 7 + ...eclarationSingleFileHasErrorsReported.d.ts | 14 ++ .../declarationSingleFileHasErrorsReported.js | 17 +++ .../transpile/declarationsSimple.d.ts | 23 +++ .../reference/transpile/declarationsSimple.js | 24 +++ .../cases/transpile/declarationBasicSyntax.ts | 45 ++++++ .../declarationCrossFileInferences.ts | 13 ++ .../transpile/declarationLinkedAliases.ts | 4 + .../declarationSingleFileHasErrors.ts | 2 + .../declarationSingleFileHasErrorsReported.ts | 3 + tests/cases/transpile/declarationsSimple.ts | 14 ++ 25 files changed, 654 insertions(+), 6 deletions(-) create mode 100644 src/testRunner/transpileRunner.ts create mode 100644 tests/baselines/reference/transpile/declarationBasicSyntax.d.ts create mode 100644 tests/baselines/reference/transpile/declarationBasicSyntax.js create mode 100644 tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts create mode 100644 tests/baselines/reference/transpile/declarationCrossFileInferences.js create mode 100644 tests/baselines/reference/transpile/declarationLinkedAliases.d.ts create mode 100644 tests/baselines/reference/transpile/declarationLinkedAliases.js create mode 100644 tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts create mode 100644 tests/baselines/reference/transpile/declarationSingleFileHasErrors.js create mode 100644 tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts create mode 100644 tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.js create mode 100644 tests/baselines/reference/transpile/declarationsSimple.d.ts create mode 100644 tests/baselines/reference/transpile/declarationsSimple.js create mode 100644 tests/cases/transpile/declarationBasicSyntax.ts create mode 100644 tests/cases/transpile/declarationCrossFileInferences.ts create mode 100644 tests/cases/transpile/declarationLinkedAliases.ts create mode 100644 tests/cases/transpile/declarationSingleFileHasErrors.ts create mode 100644 tests/cases/transpile/declarationSingleFileHasErrorsReported.ts create mode 100644 tests/cases/transpile/declarationsSimple.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6699fe5ad3cfc..c7275a4c624ed 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -533,7 +533,7 @@ function getSourceMapFilePath(jsFilePath: string, options: CompilerOptions) { } /** @internal */ -export function getOutputExtension(fileName: string, options: CompilerOptions): Extension { +export function getOutputExtension(fileName: string, options: Pick): Extension { return fileExtensionIs(fileName, Extension.Json) ? Extension.Json : options.jsx === JsxEmit.Preserve && fileExtensionIsOneOf(fileName, [Extension.Jsx, Extension.Tsx]) ? Extension.Jsx : fileExtensionIsOneOf(fileName, [Extension.Mts, Extension.Mjs]) ? Extension.Mjs : diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 0603409e77f52..916ec60b8478a 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -303,6 +303,7 @@ export namespace Compiler { { name: "noTypesAndSymbols", type: "boolean", defaultValueDescription: false }, // Emitted js baseline will print full paths for every output file { name: "fullEmitPaths", type: "boolean", defaultValueDescription: false }, + { name: "reportDiagnostics", type: "boolean", defaultValueDescription: false }, // used to enable error collection in `transpile` baselines ]; let optionsIndex: Map; diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index fbe8f32b299f7..cc341aa499e89 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -4,7 +4,7 @@ import { } from "./_namespaces/Harness"; import * as ts from "./_namespaces/ts"; -export type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project"; +export type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "transpile"; export type CompilerTestKind = "conformance" | "compiler"; export type FourslashTestKind = "fourslash" | "fourslash-server"; diff --git a/src/services/transpile.ts b/src/services/transpile.ts index a3cbadfcc4616..b5793fa6e8e21 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -25,6 +25,7 @@ import { normalizePath, optionDeclarations, parseCustomTypeOption, + ScriptTarget, toPath, transpileOptionValueCompilerOptions, } from "./_namespaces/ts"; @@ -80,6 +81,33 @@ export function transpileDeclaration(input: string, transpileOptions: TranspileO return transpileWorker(input, transpileOptions, /*declarations*/ true); } +// Declaration emit works without a `lib`, but some local inferences you'd expect to work won't without +// at least a minimal `lib` available, since the checker will `any` their types without these defined. +// Late bound symbol names, in particular, are impossible to define without `Symbol` at least partially defined. +// TODO: This should *probably* just load the full, real `lib` for the `target`. +const barebonesLibContent = `/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number {} +interface Object {} +interface RegExp {} +interface String {} +interface Array { length: number; [n: number]: T; } +interface SymbolConstructor { + (desc?: string | number): symbol; + for(name: string): symbol; + readonly toStringTag: symbol; +} +declare var Symbol: SymbolConstructor; +interface Symbol { + readonly [Symbol.toStringTag]: string; +}`; +const barebonesLibName = "lib.d.ts"; +const barebonesLibSourceFile = createSourceFile(barebonesLibName, barebonesLibContent, {languageVersion: ScriptTarget.Latest}); + function transpileWorker(input: string, transpileOptions: TranspileOptions, declaration?: boolean): TranspileOutput { const diagnostics: Diagnostic[] = []; @@ -119,7 +147,7 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl const newLine = getNewLineCharacter(options); // Create a compilerHost object to allow the compiler to read and write files const compilerHost: CompilerHost = { - getSourceFile: fileName => fileName === normalizePath(inputFileName) ? sourceFile : undefined, + getSourceFile: fileName => fileName === normalizePath(inputFileName) ? sourceFile : fileName === normalizePath(barebonesLibName) ? barebonesLibSourceFile : undefined, writeFile: (name, text) => { if (fileExtensionIs(name, ".map")) { Debug.assertEqual(sourceMapText, undefined, "Unexpected multiple source map outputs, file:", name); @@ -130,12 +158,12 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl outputText = text; } }, - getDefaultLibFileName: () => "lib.d.ts", + getDefaultLibFileName: () => barebonesLibName, useCaseSensitiveFileNames: () => false, getCanonicalFileName: fileName => fileName, getCurrentDirectory: () => "", getNewLine: () => newLine, - fileExists: (fileName): boolean => fileName === inputFileName, + fileExists: (fileName): boolean => fileName === inputFileName || (!!declaration && fileName === barebonesLibName), readFile: () => "", directoryExists: () => true, getDirectories: () => [], @@ -165,7 +193,8 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl let outputText: string | undefined; let sourceMapText: string | undefined; - const program = createProgram([inputFileName], options, compilerHost); + const inputs = declaration ? [inputFileName, barebonesLibName] : [inputFileName]; + const program = createProgram(inputs, options, compilerHost); if (transpileOptions.reportDiagnostics) { addRange(/*to*/ diagnostics, /*from*/ program.getSyntacticDiagnostics(sourceFile)); diff --git a/src/testRunner/_namespaces/Harness.ts b/src/testRunner/_namespaces/Harness.ts index e9b235a19d652..7577c667a8050 100644 --- a/src/testRunner/_namespaces/Harness.ts +++ b/src/testRunner/_namespaces/Harness.ts @@ -7,6 +7,7 @@ export { Parallel }; export * from "../fourslashRunner"; export * from "../compilerRunner"; +export * from "../transpileRunner"; export * from "../runner"; // If running as emitted CJS, don't start executing the tests here; instead start in runner.ts. diff --git a/src/testRunner/runner.ts b/src/testRunner/runner.ts index ecf720996e43e..e5ac52c131025 100644 --- a/src/testRunner/runner.ts +++ b/src/testRunner/runner.ts @@ -11,6 +11,7 @@ import { setShardId, setShards, TestRunnerKind, + TranspileRunner, } from "./_namespaces/Harness"; import * as project from "./_namespaces/project"; import * as ts from "./_namespaces/ts"; @@ -66,6 +67,8 @@ export function createRunner(kind: TestRunnerKind): RunnerBase { return new FourSlashRunner(FourSlash.FourSlashTestType.Server); case "project": return new project.ProjectRunner(); + case "transpile": + return new TranspileRunner(); } return ts.Debug.fail(`Unknown runner kind ${kind}`); } @@ -190,6 +193,9 @@ function handleTestConfig() { case "fourslash-generated": runners.push(new GeneratedFourslashRunner(FourSlash.FourSlashTestType.Native)); break; + case "transpile": + runners.push(new TranspileRunner()); + break; } } } @@ -206,6 +212,9 @@ function handleTestConfig() { runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Native)); runners.push(new FourSlashRunner(FourSlash.FourSlashTestType.Server)); // runners.push(new GeneratedFourslashRunner()); + + // transpile + runners.push(new TranspileRunner()); } if (runUnitTests === undefined) { runUnitTests = runners.length !== 1; // Don't run unit tests when running only one runner if unit tests were not explicitly asked for diff --git a/src/testRunner/transpileRunner.ts b/src/testRunner/transpileRunner.ts new file mode 100644 index 0000000000000..d58969effd68f --- /dev/null +++ b/src/testRunner/transpileRunner.ts @@ -0,0 +1,132 @@ +import { + Baseline, + Compiler, + getFileBasedTestConfigurations, + IO, + RunnerBase, + TestCaseParser, + TestRunnerKind, +} from "./_namespaces/Harness"; +import * as vpath from "./_namespaces/vpath"; +import * as ts from "./_namespaces/ts"; + +export class TranspileRunner extends RunnerBase { + protected basePath: string = "tests/cases/transpile"; + protected testSuiteName: TestRunnerKind = "transpile"; + + constructor() { + super(); + } + + public enumerateTestFiles() { + // see also: `enumerateTestFiles` in tests/webTestServer.ts + return this.enumerateFiles(this.basePath, /\.[cm]?[tj]sx?/i, { recursive: true }); + } + + public kind() { + return this.testSuiteName; + } + + public initializeTests() { + if (this.tests.length === 0) { + this.tests = IO.enumerateTestFiles(this); + } + + describe(this.testSuiteName + " tests", () => { + this.tests.forEach(file => { + file = vpath.normalizeSeparators(file); + describe(file, () => { + const tests = TranspileTestCase.getConfigurations(file); + for (const test of tests) { + test.run(); + } + }); + }); + }); + } +} + +enum TranspileKind { + Module, + Declaration, +} + +class TranspileTestCase { + static varyBy = []; + + static getConfigurations(file: string): TranspileTestCase[] { + const ext = vpath.extname(file); + const baseName = vpath.basename(file); + const justName = baseName.slice(0, baseName.length - ext.length); + const content = IO.readFile(file)!; + const settings = TestCaseParser.extractCompilerSettings(content); + const settingConfigurations = getFileBasedTestConfigurations(settings, TranspileTestCase.varyBy); + return settingConfigurations?.map(c => { + const desc = Object.entries(c).map(([key, value]) => `${key}=${value}`).join(","); + return new TranspileTestCase(`${justName}(${desc})`, ext, content, {...settings, ...c}); + }) || [new TranspileTestCase(justName, ext, content, settings)]; + } + + private jsOutName; + private dtsOutName; + private units; + constructor( + private justName: string, + private ext: string, + private content: string, + private settings: TestCaseParser.CompilerSettings, + ) { + this.jsOutName = justName + this.getJsOutputExtension(`${justName}${ext}`); + this.dtsOutName = justName + ts.getDeclarationEmitExtensionForPath(`${justName}${ext}`); + this.units = TestCaseParser.makeUnitsFromTest(content, `${justName}${ext}`, settings); + } + + getJsOutputExtension(name: string) { + return ts.getOutputExtension(name, { jsx: this.settings.jsx === "preserve" ? ts.JsxEmit.Preserve : undefined }); + } + + runKind(kind: TranspileKind) { + it(`transpile test ${this.justName} has expected ${kind === TranspileKind.Module ? "js" : "declaration"} output`, () => { + let baselineText = ""; + + // include inputs in output so how the test is parsed and broken down is more obvious + this.units.testUnitData.forEach(unit => { + baselineText += `//// [${unit.name}] ////\r\n`; + baselineText += unit.content; + if (!unit.content.endsWith("\n")) { + baselineText += "\r\n" + } + }); + + this.units.testUnitData.forEach(unit => { + const opts: ts.CompilerOptions = {}; + Compiler.setCompilerOptionsFromHarnessSetting(this.settings, opts); + const result = (kind === TranspileKind.Module ? ts.transpileModule : ts.transpileDeclaration)(unit.content, { compilerOptions: opts, fileName: unit.name, reportDiagnostics: this.settings.reportDiagnostics === "true" }); + + baselineText += `//// [${ts.changeExtension(unit.name, kind === TranspileKind.Module ? this.getJsOutputExtension(unit.name) : ts.getDeclarationEmitExtensionForPath(unit.name) )}] ////\r\n`; + baselineText += result.outputText; + if (!result.outputText.endsWith("\n")) { + baselineText += "\r\n" + } + if (result.diagnostics && result.diagnostics.length) { + baselineText += "\r\n\r\n//// [Diagnostics reported]\r\n"; + baselineText += Compiler.getErrorBaseline([{ content: unit.content, unitName: unit.name }], result.diagnostics, !!opts.pretty); + if (!baselineText.endsWith("\n")) { + baselineText += "\r\n" + } + } + }); + + Baseline.runBaseline(`transpile/${kind === TranspileKind.Module ? this.jsOutName : this.dtsOutName}`, baselineText); + }); + } + + run() { + if (!this.settings.emitDeclarationOnly) { + this.runKind(TranspileKind.Module); + } + if (this.settings.declaration) { + this.runKind(TranspileKind.Declaration); + } + } +} diff --git a/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts b/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts new file mode 100644 index 0000000000000..74ff8b4e2adf5 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts @@ -0,0 +1,90 @@ +//// [variables.ts] //// +export const a = 1; +export let b = 2; +export var c = 3; +using d = undefined; +export { d }; +await using e = undefined; +export { e }; +//// [interface.ts] //// +export interface Foo { + a: string; + readonly b: string; + c?: string; +} +//// [class.ts] //// +const i = Symbol(); +export class Bar { + a: string; + b?: string; + declare c: string; + #d: string; + public e: string; + protected f: string; + private g: string; + ["h"]: string; + [i]: string; +} + +export abstract class Baz { + abstract a: string; + abstract method(): void; +} +//// [namespace.ts] //// +export namespace ns { + namespace internal { + export class Foo {} + } + export namespace nested { + export import inner = internal; + } +} +//// [alias.ts] //// +export type A = { x: T }; +//// [variables.d.ts] //// +export declare const a = 1; +export declare let b: number; +export declare var c: number; +declare const d: any; +export { d }; +declare const e: any; +export { e }; +//// [interface.d.ts] //// +export interface Foo { + a: string; + readonly b: string; + c?: string; +} +//// [class.d.ts] //// +declare const i: unique symbol; +export declare class Bar { + #private; + a: string; + b?: string; + c: string; + e: string; + protected f: string; + private g; + ["h"]: string; + [i]: string; +} +export declare abstract class Baz { + abstract a: string; + abstract method(): void; +} +export {}; +//// [namespace.d.ts] //// +export declare namespace ns { + namespace internal { + class Foo { + } + } + export namespace nested { + export import inner = internal; + } + export {}; +} +//// [alias.d.ts] //// +export type A = { + x: T; +}; diff --git a/tests/baselines/reference/transpile/declarationBasicSyntax.js b/tests/baselines/reference/transpile/declarationBasicSyntax.js new file mode 100644 index 0000000000000..bc376250a19b0 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationBasicSyntax.js @@ -0,0 +1,138 @@ +//// [variables.ts] //// +export const a = 1; +export let b = 2; +export var c = 3; +using d = undefined; +export { d }; +await using e = undefined; +export { e }; +//// [interface.ts] //// +export interface Foo { + a: string; + readonly b: string; + c?: string; +} +//// [class.ts] //// +const i = Symbol(); +export class Bar { + a: string; + b?: string; + declare c: string; + #d: string; + public e: string; + protected f: string; + private g: string; + ["h"]: string; + [i]: string; +} + +export abstract class Baz { + abstract a: string; + abstract method(): void; +} +//// [namespace.ts] //// +export namespace ns { + namespace internal { + export class Foo {} + } + export namespace nested { + export import inner = internal; + } +} +//// [alias.ts] //// +export type A = { x: T }; +//// [variables.js] //// +var __addDisposableResource = (this && this.__addDisposableResource) || function (env, value, async) { + if (value !== null && value !== void 0) { + if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); + var dispose; + if (async) { + if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); + dispose = value[Symbol.asyncDispose]; + } + if (dispose === void 0) { + if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); + dispose = value[Symbol.dispose]; + } + if (typeof dispose !== "function") throw new TypeError("Object not disposable."); + env.stack.push({ value: value, dispose: dispose, async: async }); + } + else if (async) { + env.stack.push({ async: true }); + } + return value; +}; +var __disposeResources = (this && this.__disposeResources) || (function (SuppressedError) { + return function (env) { + function fail(e) { + env.error = env.hasError ? new SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; + env.hasError = true; + } + function next() { + while (env.stack.length) { + var rec = env.stack.pop(); + try { + var result = rec.dispose && rec.dispose.call(rec.value); + if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); + } + catch (e) { + fail(e); + } + } + if (env.hasError) throw env.error; + } + return next(); + }; +})(typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { + var e = new Error(message); + return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; +}); +export const a = 1; +export let b = 2; +export var c = 3; +export { d }; +export { e }; +var d, e; +const env_1 = { stack: [], error: void 0, hasError: false }; +try { + d = __addDisposableResource(env_1, undefined, false); + e = __addDisposableResource(env_1, undefined, true); +} +catch (e_1) { + env_1.error = e_1; + env_1.hasError = true; +} +finally { + const result_1 = __disposeResources(env_1); + if (result_1) + await result_1; +} +//// [interface.js] //// +export {}; +//// [class.js] //// +var _Bar_d; +const i = Symbol(); +export class Bar { + constructor() { + _Bar_d.set(this, void 0); + } +} +_Bar_d = new WeakMap(); +export class Baz { +} +//// [namespace.js] //// +export var ns; +(function (ns) { + let internal; + (function (internal) { + class Foo { + } + internal.Foo = Foo; + })(internal || (internal = {})); + let nested; + (function (nested) { + nested.inner = internal; + })(nested = ns.nested || (ns.nested = {})); +})(ns || (ns = {})); +//// [alias.js] //// +export {}; diff --git a/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts b/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts new file mode 100644 index 0000000000000..11bf4c1415dec --- /dev/null +++ b/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts @@ -0,0 +1,22 @@ +//// [defines.ts] //// +export class A { + field = { x: 1 } +} +//// [consumes.ts] //// +import {A} from "./defines.js"; +export function create() { + return new A(); +} +//// [exposes.ts] //// +import {create} from "./consumes.js"; +export const value = create(); +//// [defines.d.ts] //// +export declare class A { + field: { + x: number; + }; +} +//// [consumes.d.ts] //// +export declare function create(): any; +//// [exposes.d.ts] //// +export declare const value: any; diff --git a/tests/baselines/reference/transpile/declarationCrossFileInferences.js b/tests/baselines/reference/transpile/declarationCrossFileInferences.js new file mode 100644 index 0000000000000..c63babe311fd3 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationCrossFileInferences.js @@ -0,0 +1,37 @@ +//// [defines.ts] //// +export class A { + field = { x: 1 } +} +//// [consumes.ts] //// +import {A} from "./defines.js"; +export function create() { + return new A(); +} +//// [exposes.ts] //// +import {create} from "./consumes.js"; +export const value = create(); +//// [defines.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.A = void 0; +var A = /** @class */ (function () { + function A() { + this.field = { x: 1 }; + } + return A; +}()); +exports.A = A; +//// [consumes.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.create = create; +var defines_js_1 = require("./defines.js"); +function create() { + return new defines_js_1.A(); +} +//// [exposes.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.value = void 0; +var consumes_js_1 = require("./consumes.js"); +exports.value = (0, consumes_js_1.create)(); diff --git a/tests/baselines/reference/transpile/declarationLinkedAliases.d.ts b/tests/baselines/reference/transpile/declarationLinkedAliases.d.ts new file mode 100644 index 0000000000000..f32860fc576f6 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationLinkedAliases.d.ts @@ -0,0 +1,8 @@ +//// [declarationLinkedAliases.ts] //// +import { A } from "mod"; +import B = A.C; +export { B }; +//// [declarationLinkedAliases.d.ts] //// +import { A } from "mod"; +import B = A.C; +export { B }; diff --git a/tests/baselines/reference/transpile/declarationLinkedAliases.js b/tests/baselines/reference/transpile/declarationLinkedAliases.js new file mode 100644 index 0000000000000..550d48a3d5cb4 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationLinkedAliases.js @@ -0,0 +1,11 @@ +//// [declarationLinkedAliases.ts] //// +import { A } from "mod"; +import B = A.C; +export { B }; +//// [declarationLinkedAliases.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.B = void 0; +var mod_1 = require("mod"); +var B = mod_1.A.C; +exports.B = B; diff --git a/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts b/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts new file mode 100644 index 0000000000000..0383a7f32d20a --- /dev/null +++ b/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts @@ -0,0 +1,4 @@ +//// [declarationSingleFileHasErrors.ts] //// +export const a number = "missing colon"; +//// [declarationSingleFileHasErrors.d.ts] //// +export declare const a: any, number = "missing colon"; diff --git a/tests/baselines/reference/transpile/declarationSingleFileHasErrors.js b/tests/baselines/reference/transpile/declarationSingleFileHasErrors.js new file mode 100644 index 0000000000000..3168dbe6f4c1f --- /dev/null +++ b/tests/baselines/reference/transpile/declarationSingleFileHasErrors.js @@ -0,0 +1,7 @@ +//// [declarationSingleFileHasErrors.ts] //// +export const a number = "missing colon"; +//// [declarationSingleFileHasErrors.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.number = exports.a = void 0; +exports.number = "missing colon"; diff --git a/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts b/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts new file mode 100644 index 0000000000000..4848aba78729d --- /dev/null +++ b/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts @@ -0,0 +1,14 @@ +//// [declarationSingleFileHasErrorsReported.ts] //// +export const a string = "missing colon"; +//// [declarationSingleFileHasErrorsReported.d.ts] //// +export declare const a: any, string = "missing colon"; + + +//// [Diagnostics reported] +declarationSingleFileHasErrorsReported.ts(1,16): error TS1005: ',' expected. + + +==== declarationSingleFileHasErrorsReported.ts (1 errors) ==== + export const a string = "missing colon"; + ~~~~~~ +!!! error TS1005: ',' expected. diff --git a/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.js b/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.js new file mode 100644 index 0000000000000..1e1cddc825811 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.js @@ -0,0 +1,17 @@ +//// [declarationSingleFileHasErrorsReported.ts] //// +export const a string = "missing colon"; +//// [declarationSingleFileHasErrorsReported.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.string = exports.a = void 0; +exports.string = "missing colon"; + + +//// [Diagnostics reported] +declarationSingleFileHasErrorsReported.ts(1,16): error TS1005: ',' expected. + + +==== declarationSingleFileHasErrorsReported.ts (1 errors) ==== + export const a string = "missing colon"; + ~~~~~~ +!!! error TS1005: ',' expected. diff --git a/tests/baselines/reference/transpile/declarationsSimple.d.ts b/tests/baselines/reference/transpile/declarationsSimple.d.ts new file mode 100644 index 0000000000000..3d9a2d9977903 --- /dev/null +++ b/tests/baselines/reference/transpile/declarationsSimple.d.ts @@ -0,0 +1,23 @@ +//// [declarationsSimple.ts] //// +export const c: number = 1; + +export interface A { + x: number; +} + +let expr: { x: number; }; + +expr = { + x: 12, +} + +export default expr; +//// [declarationsSimple.d.ts] //// +export declare const c: number; +export interface A { + x: number; +} +declare let expr: { + x: number; +}; +export default expr; diff --git a/tests/baselines/reference/transpile/declarationsSimple.js b/tests/baselines/reference/transpile/declarationsSimple.js new file mode 100644 index 0000000000000..24a5d7bf7314b --- /dev/null +++ b/tests/baselines/reference/transpile/declarationsSimple.js @@ -0,0 +1,24 @@ +//// [declarationsSimple.ts] //// +export const c: number = 1; + +export interface A { + x: number; +} + +let expr: { x: number; }; + +expr = { + x: 12, +} + +export default expr; +//// [declarationsSimple.js] //// +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.c = void 0; +exports.c = 1; +var expr; +expr = { + x: 12, +}; +exports.default = expr; diff --git a/tests/cases/transpile/declarationBasicSyntax.ts b/tests/cases/transpile/declarationBasicSyntax.ts new file mode 100644 index 0000000000000..606808e509b47 --- /dev/null +++ b/tests/cases/transpile/declarationBasicSyntax.ts @@ -0,0 +1,45 @@ +// @declaration: true +// @target: es6 +// @filename: variables.ts +export const a = 1; +export let b = 2; +export var c = 3; +using d = undefined; +export { d }; +await using e = undefined; +export { e }; +// @filename: interface.ts +export interface Foo { + a: string; + readonly b: string; + c?: string; +} +// @filename: class.ts +const i = Symbol(); +export class Bar { + a: string; + b?: string; + declare c: string; + #d: string; + public e: string; + protected f: string; + private g: string; + ["h"]: string; + [i]: string; +} + +export abstract class Baz { + abstract a: string; + abstract method(): void; +} +// @filename: namespace.ts +export namespace ns { + namespace internal { + export class Foo {} + } + export namespace nested { + export import inner = internal; + } +} +// @filename: alias.ts +export type A = { x: T }; \ No newline at end of file diff --git a/tests/cases/transpile/declarationCrossFileInferences.ts b/tests/cases/transpile/declarationCrossFileInferences.ts new file mode 100644 index 0000000000000..dc42c9d9e132c --- /dev/null +++ b/tests/cases/transpile/declarationCrossFileInferences.ts @@ -0,0 +1,13 @@ +// @declaration: true +// @filename: defines.ts +export class A { + field = { x: 1 } +} +// @filename: consumes.ts +import {A} from "./defines.js"; +export function create() { + return new A(); +} +// @filename: exposes.ts +import {create} from "./consumes.js"; +export const value = create(); \ No newline at end of file diff --git a/tests/cases/transpile/declarationLinkedAliases.ts b/tests/cases/transpile/declarationLinkedAliases.ts new file mode 100644 index 0000000000000..054e3049ac43b --- /dev/null +++ b/tests/cases/transpile/declarationLinkedAliases.ts @@ -0,0 +1,4 @@ +// @declaration: true +import { A } from "mod"; +import B = A.C; +export { B }; \ No newline at end of file diff --git a/tests/cases/transpile/declarationSingleFileHasErrors.ts b/tests/cases/transpile/declarationSingleFileHasErrors.ts new file mode 100644 index 0000000000000..b1c857dd6d74f --- /dev/null +++ b/tests/cases/transpile/declarationSingleFileHasErrors.ts @@ -0,0 +1,2 @@ +// @declaration: true +export const a number = "missing colon"; \ No newline at end of file diff --git a/tests/cases/transpile/declarationSingleFileHasErrorsReported.ts b/tests/cases/transpile/declarationSingleFileHasErrorsReported.ts new file mode 100644 index 0000000000000..b1dd4f8b21e2d --- /dev/null +++ b/tests/cases/transpile/declarationSingleFileHasErrorsReported.ts @@ -0,0 +1,3 @@ +// @declaration: true +// @reportDiagnostics: true +export const a string = "missing colon"; \ No newline at end of file diff --git a/tests/cases/transpile/declarationsSimple.ts b/tests/cases/transpile/declarationsSimple.ts new file mode 100644 index 0000000000000..3ff1d529165f2 --- /dev/null +++ b/tests/cases/transpile/declarationsSimple.ts @@ -0,0 +1,14 @@ +// @declaration: true +export const c: number = 1; + +export interface A { + x: number; +} + +let expr: { x: number; }; + +expr = { + x: 12, +} + +export default expr; \ No newline at end of file From 18c6810aa62c5ed2105998e31d29559c11ac4c1b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 19 Apr 2024 16:05:24 -0700 Subject: [PATCH 4/6] Enable isolatedDeclarations, actually collect emit errors --- src/services/transpile.ts | 13 ++++++--- src/testRunner/transpileRunner.ts | 16 +++++------ .../transpile/declarationBasicSyntax.d.ts | 27 +++++++++++++++++++ .../declarationCrossFileInferences.d.ts | 26 ++++++++++++++++++ .../declarationSingleFileHasErrors.d.ts | 11 ++++++++ ...eclarationSingleFileHasErrorsReported.d.ts | 6 ++++- 6 files changed, 86 insertions(+), 13 deletions(-) diff --git a/src/services/transpile.ts b/src/services/transpile.ts index b5793fa6e8e21..59f68124fde39 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -61,13 +61,14 @@ const optionsRedundantWithVerbatimModuleSyntax = new Set([ * - declaration = false */ export function transpileModule(input: string, transpileOptions: TranspileOptions): TranspileOutput { - return transpileWorker(input, transpileOptions, /*declarations*/ false); + return transpileWorker(input, transpileOptions, /*declaration*/ false); } /* * This function will create a declaration file from 'input' argument using specified compiler options. * If no options are provided - it will use a set of default compiler options. * Extra compiler options that will unconditionally be used by this function are: + * - isolatedDeclarations = true * - isolatedModules = true * - allowNonTsExtensions = true * - noLib = true @@ -78,7 +79,7 @@ export function transpileModule(input: string, transpileOptions: TranspileOption * in that only types in the single input file are available to be used in the generated declarations. */ export function transpileDeclaration(input: string, transpileOptions: TranspileOptions): TranspileOutput { - return transpileWorker(input, transpileOptions, /*declarations*/ true); + return transpileWorker(input, transpileOptions, /*declaration*/ true); } // Declaration emit works without a `lib`, but some local inferences you'd expect to work won't without @@ -106,7 +107,7 @@ interface Symbol { readonly [Symbol.toStringTag]: string; }`; const barebonesLibName = "lib.d.ts"; -const barebonesLibSourceFile = createSourceFile(barebonesLibName, barebonesLibContent, {languageVersion: ScriptTarget.Latest}); +const barebonesLibSourceFile = createSourceFile(barebonesLibName, barebonesLibContent, { languageVersion: ScriptTarget.Latest }); function transpileWorker(input: string, transpileOptions: TranspileOptions, declaration?: boolean): TranspileOutput { const diagnostics: Diagnostic[] = []; @@ -139,6 +140,7 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl if (declaration) { options.declaration = true; options.emitDeclarationOnly = true; + options.isolatedDeclarations = true; } else { options.declaration = false; @@ -201,7 +203,10 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl addRange(/*to*/ diagnostics, /*from*/ program.getOptionsDiagnostics()); } // Emit - program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ declaration, transpileOptions.transformers); + const result = program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ declaration, transpileOptions.transformers, /*forceDtsEmit*/ declaration); + + // TODO: Should this require `reportDiagnostics`? + addRange(/*to*/ diagnostics, /*from*/ result.diagnostics); if (outputText === undefined) return Debug.fail("Output generation failed"); diff --git a/src/testRunner/transpileRunner.ts b/src/testRunner/transpileRunner.ts index d58969effd68f..1f4213a06dc1f 100644 --- a/src/testRunner/transpileRunner.ts +++ b/src/testRunner/transpileRunner.ts @@ -7,11 +7,11 @@ import { TestCaseParser, TestRunnerKind, } from "./_namespaces/Harness"; -import * as vpath from "./_namespaces/vpath"; import * as ts from "./_namespaces/ts"; +import * as vpath from "./_namespaces/vpath"; export class TranspileRunner extends RunnerBase { - protected basePath: string = "tests/cases/transpile"; + protected basePath = "tests/cases/transpile"; protected testSuiteName: TestRunnerKind = "transpile"; constructor() { @@ -63,7 +63,7 @@ class TranspileTestCase { const settingConfigurations = getFileBasedTestConfigurations(settings, TranspileTestCase.varyBy); return settingConfigurations?.map(c => { const desc = Object.entries(c).map(([key, value]) => `${key}=${value}`).join(","); - return new TranspileTestCase(`${justName}(${desc})`, ext, content, {...settings, ...c}); + return new TranspileTestCase(`${justName}(${desc})`, ext, content, { ...settings, ...c }); }) || [new TranspileTestCase(justName, ext, content, settings)]; } @@ -94,7 +94,7 @@ class TranspileTestCase { baselineText += `//// [${unit.name}] ////\r\n`; baselineText += unit.content; if (!unit.content.endsWith("\n")) { - baselineText += "\r\n" + baselineText += "\r\n"; } }); @@ -102,17 +102,17 @@ class TranspileTestCase { const opts: ts.CompilerOptions = {}; Compiler.setCompilerOptionsFromHarnessSetting(this.settings, opts); const result = (kind === TranspileKind.Module ? ts.transpileModule : ts.transpileDeclaration)(unit.content, { compilerOptions: opts, fileName: unit.name, reportDiagnostics: this.settings.reportDiagnostics === "true" }); - - baselineText += `//// [${ts.changeExtension(unit.name, kind === TranspileKind.Module ? this.getJsOutputExtension(unit.name) : ts.getDeclarationEmitExtensionForPath(unit.name) )}] ////\r\n`; + + baselineText += `//// [${ts.changeExtension(unit.name, kind === TranspileKind.Module ? this.getJsOutputExtension(unit.name) : ts.getDeclarationEmitExtensionForPath(unit.name))}] ////\r\n`; baselineText += result.outputText; if (!result.outputText.endsWith("\n")) { - baselineText += "\r\n" + baselineText += "\r\n"; } if (result.diagnostics && result.diagnostics.length) { baselineText += "\r\n\r\n//// [Diagnostics reported]\r\n"; baselineText += Compiler.getErrorBaseline([{ content: unit.content, unitName: unit.name }], result.diagnostics, !!opts.pretty); if (!baselineText.endsWith("\n")) { - baselineText += "\r\n" + baselineText += "\r\n"; } } }); diff --git a/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts b/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts index 74ff8b4e2adf5..43e328bf1152c 100644 --- a/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts +++ b/tests/baselines/reference/transpile/declarationBasicSyntax.d.ts @@ -73,6 +73,33 @@ export declare abstract class Baz { abstract method(): void; } export {}; + + +//// [Diagnostics reported] +class.ts(1,7): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. + + +==== class.ts (1 errors) ==== + const i = Symbol(); + ~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 class.ts:1:7: Add a type annotation to the variable i. + export class Bar { + a: string; + b?: string; + declare c: string; + #d: string; + public e: string; + protected f: string; + private g: string; + ["h"]: string; + [i]: string; + } + + export abstract class Baz { + abstract a: string; + abstract method(): void; + } //// [namespace.d.ts] //// export declare namespace ns { namespace internal { diff --git a/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts b/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts index 11bf4c1415dec..9a8ae29958252 100644 --- a/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts +++ b/tests/baselines/reference/transpile/declarationCrossFileInferences.d.ts @@ -18,5 +18,31 @@ export declare class A { } //// [consumes.d.ts] //// export declare function create(): any; + + +//// [Diagnostics reported] +consumes.ts(2,17): error TS9007: Function must have an explicit return type annotation with --isolatedDeclarations. + + +==== consumes.ts (1 errors) ==== + import {A} from "./defines.js"; + export function create() { + ~~~~~~ +!!! error TS9007: Function must have an explicit return type annotation with --isolatedDeclarations. +!!! related TS9031 consumes.ts:2:17: Add a return type to the function declaration. + return new A(); + } //// [exposes.d.ts] //// export declare const value: any; + + +//// [Diagnostics reported] +exposes.ts(2,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. + + +==== exposes.ts (1 errors) ==== + import {create} from "./consumes.js"; + export const value = create(); + ~~~~~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 exposes.ts:2:14: Add a type annotation to the variable value. diff --git a/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts b/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts index 0383a7f32d20a..6952247996ea0 100644 --- a/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts +++ b/tests/baselines/reference/transpile/declarationSingleFileHasErrors.d.ts @@ -2,3 +2,14 @@ export const a number = "missing colon"; //// [declarationSingleFileHasErrors.d.ts] //// export declare const a: any, number = "missing colon"; + + +//// [Diagnostics reported] +declarationSingleFileHasErrors.ts(1,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. + + +==== declarationSingleFileHasErrors.ts (1 errors) ==== + export const a number = "missing colon"; + ~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 declarationSingleFileHasErrors.ts:1:14: Add a type annotation to the variable a. diff --git a/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts b/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts index 4848aba78729d..46cadeff0df51 100644 --- a/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts +++ b/tests/baselines/reference/transpile/declarationSingleFileHasErrorsReported.d.ts @@ -5,10 +5,14 @@ export declare const a: any, string = "missing colon"; //// [Diagnostics reported] +declarationSingleFileHasErrorsReported.ts(1,14): error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. declarationSingleFileHasErrorsReported.ts(1,16): error TS1005: ',' expected. -==== declarationSingleFileHasErrorsReported.ts (1 errors) ==== +==== declarationSingleFileHasErrorsReported.ts (2 errors) ==== export const a string = "missing colon"; + ~ +!!! error TS9010: Variable must have an explicit type annotation with --isolatedDeclarations. +!!! related TS9027 declarationSingleFileHasErrorsReported.ts:1:14: Add a type annotation to the variable a. ~~~~~~ !!! error TS1005: ',' expected. From b0a4b72e2ae57574c30449557e0528c82314e88d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 19 Apr 2024 16:56:26 -0700 Subject: [PATCH 5/6] Lint feedback --- src/testRunner/transpileRunner.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/testRunner/transpileRunner.ts b/src/testRunner/transpileRunner.ts index 1f4213a06dc1f..fd8526d79a69d 100644 --- a/src/testRunner/transpileRunner.ts +++ b/src/testRunner/transpileRunner.ts @@ -14,10 +14,6 @@ export class TranspileRunner extends RunnerBase { protected basePath = "tests/cases/transpile"; protected testSuiteName: TestRunnerKind = "transpile"; - constructor() { - super(); - } - public enumerateTestFiles() { // see also: `enumerateTestFiles` in tests/webTestServer.ts return this.enumerateFiles(this.basePath, /\.[cm]?[tj]sx?/i, { recursive: true }); @@ -64,7 +60,7 @@ class TranspileTestCase { return settingConfigurations?.map(c => { const desc = Object.entries(c).map(([key, value]) => `${key}=${value}`).join(","); return new TranspileTestCase(`${justName}(${desc})`, ext, content, { ...settings, ...c }); - }) || [new TranspileTestCase(justName, ext, content, settings)]; + }) ?? [new TranspileTestCase(justName, ext, content, settings)]; } private jsOutName; From 764f8617c3cf8b3707d4ff016cb9954732d56d93 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Tue, 23 Apr 2024 16:53:21 -0700 Subject: [PATCH 6/6] Remove TODO comment, consensus is to keep these --- src/services/transpile.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/services/transpile.ts b/src/services/transpile.ts index 59f68124fde39..a815243923825 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -205,7 +205,6 @@ function transpileWorker(input: string, transpileOptions: TranspileOptions, decl // Emit const result = program.emit(/*targetSourceFile*/ undefined, /*writeFile*/ undefined, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ declaration, transpileOptions.transformers, /*forceDtsEmit*/ declaration); - // TODO: Should this require `reportDiagnostics`? addRange(/*to*/ diagnostics, /*from*/ result.diagnostics); if (outputText === undefined) return Debug.fail("Output generation failed");