From 88bf9277ff83f3474ad302e9cb579ba279dd24c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Tue, 8 May 2018 12:26:34 +0800 Subject: [PATCH 01/44] add support for readonly modifier --- .../generateGetAccessorAndSetAccessor.ts | 72 ++++++++++++++++--- ...efactorConvertToGetAccessAndSetAccess14.ts | 13 +++- ...efactorConvertToGetAccessAndSetAccess33.ts | 24 +++++++ ...efactorConvertToGetAccessAndSetAccess34.ts | 24 +++++++ ...efactorConvertToGetAccessAndSetAccess35.ts | 24 +++++++ ...efactorConvertToGetAccessAndSetAccess36.ts | 24 +++++++ ...efactorConvertToGetAccessAndSetAccess37.ts | 28 ++++++++ 7 files changed, 198 insertions(+), 11 deletions(-) create mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts create mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts create mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts create mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts create mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 523ad97e5fa..799fa58d6d7 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -11,6 +11,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { interface Info { container: ContainerDeclaration; isStatic: boolean; + isReadonly: boolean; type: TypeNode | undefined; declaration: AcceptedDeclaration; fieldName: AcceptedNameType; @@ -41,21 +42,40 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { const isJS = isSourceFileJavaScript(file); const changeTracker = textChanges.ChangeTracker.fromContext(context); - const { isStatic, fieldName, accessorName, type, container, declaration } = fieldInfo; + const { isStatic, isReadonly, fieldName, accessorName, type, container, declaration } = fieldInfo; + + suppressLeadingAndTrailingTrivia(fieldName); + suppressLeadingAndTrailingTrivia(declaration); + suppressLeadingAndTrailingTrivia(container); const isInClassLike = isClassLike(container); + // avoid Readonly modifier because it will convert to get accessor + const modifierFlags = getModifierFlags(declaration) & ~ModifierFlags.Readonly; const accessorModifiers = isInClassLike - ? !declaration.modifiers || getModifierFlags(declaration) & ModifierFlags.Private ? getModifiers(isJS, isStatic, SyntaxKind.PublicKeyword) : declaration.modifiers + ? !modifierFlags || modifierFlags & ModifierFlags.Private + ? getModifiers(isJS, isStatic, SyntaxKind.PublicKeyword) + : createNodeArray(createModifiersFromModifierFlags(modifierFlags)) : undefined; const fieldModifiers = isInClassLike ? getModifiers(isJS, isStatic, SyntaxKind.PrivateKeyword) : undefined; updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers); const getAccessor = generateGetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); - const setAccessor = generateSetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); - + suppressLeadingAndTrailingTrivia(getAccessor); insertAccessor(changeTracker, file, getAccessor, declaration, container); - insertAccessor(changeTracker, file, setAccessor, declaration, container); + + if (isReadonly) { + // readonly modifier only existed in classLikeDeclaration + const constructor = getFirstConstructorWithBody(container); + if (constructor) { + updateReadonlyPropertyInitializerStatementConstructor(changeTracker, file, constructor, accessorName, fieldName); + } + } + else { + const setAccessor = generateSetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container); + suppressLeadingAndTrailingTrivia(setAccessor); + insertAccessor(changeTracker, file, setAccessor, declaration, container); + } const edits = changeTracker.getChanges(); const renameFilename = file.fileName; @@ -92,16 +112,15 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { function getConvertibleFieldAtPosition(file: SourceFile, startPosition: number): Info | undefined { const node = getTokenAtPosition(file, startPosition, /*includeJsDocComment*/ false); const declaration = findAncestor(node.parent, isAcceptedDeclaration); - // make sure propertyDeclaration have AccessibilityModifier or Static Modifier - const meaning = ModifierFlags.AccessibilityModifier | ModifierFlags.Static; + // make sure declaration have AccessibilityModifier or Static Modifier or Readonly Modifier + const meaning = ModifierFlags.AccessibilityModifier | ModifierFlags.Static | ModifierFlags.Readonly; if (!declaration || !isConvertableName(declaration.name) || (getModifierFlags(declaration) | meaning) !== meaning) return undefined; const fieldName = createPropertyName(getUniqueName(`_${declaration.name.text}`, file.text), declaration.name); const accessorName = createPropertyName(declaration.name.text, declaration.name); - suppressLeadingAndTrailingTrivia(fieldName); - suppressLeadingAndTrailingTrivia(declaration); return { isStatic: hasStaticModifier(declaration), + isReadonly: hasReadonlyModifier(declaration), type: getTypeAnnotationNode(declaration), container: declaration.kind === SyntaxKind.Parameter ? declaration.parent.parent : declaration.parent, declaration, @@ -159,7 +178,6 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { declaration.type, declaration.initializer ); - changeTracker.replaceNode(file, declaration, property); } @@ -186,4 +204,38 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { ? changeTracker.insertNodeAtClassStart(file, container, accessor) : changeTracker.insertNodeAfter(file, declaration, accessor); } + + function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, file: SourceFile, constructor: ConstructorDeclaration, accessorName: AcceptedNameType, fieldName: AcceptedNameType) { + if (constructor.body) { + const initializerStatement = find(constructor.body.statements, (stmt => + isExpressionStatement(stmt) && + isAssignmentExpression(stmt.expression) && + stmt.expression.operatorToken.kind === SyntaxKind.EqualsToken && + (isPropertyAccessExpression(stmt.expression.left) || isElementAccessExpression(stmt.expression.left)) && + isThis(stmt.expression.left.expression) && + (isPropertyAccessExpression(stmt.expression.left) + ? (getNameFromPropertyName(stmt.expression.left.name) === accessorName.text) + : (isPropertyName(stmt.expression.left.argumentExpression) && isConvertableName(stmt.expression.left.argumentExpression) && getNameFromPropertyName(stmt.expression.left.argumentExpression) === accessorName.text + )) + )); + if (initializerStatement) { + const initializerLeftHead = ((>>(initializerStatement).expression).left); + + if (isPropertyAccessExpression(initializerLeftHead)) { + changeTracker.replaceNode(file, initializerLeftHead, updatePropertyAccess( + initializerLeftHead, + initializerLeftHead.expression, + createIdentifier(fieldName.text) + )); + } + else { + changeTracker.replaceNode(file, initializerLeftHead, updateElementAccess( + initializerLeftHead, + initializerLeftHead.expression, + createPropertyName(fieldName.text, initializerLeftHead.argumentExpression) + )); + } + } + } + } } diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess14.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess14.ts index 36789b29826..095cc4fdd79 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess14.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess14.ts @@ -5,4 +5,15 @@ //// } goTo.select("a", "b"); -verify.not.refactorAvailable("Generate 'get' and 'set' accessors"); \ No newline at end of file +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `class A { + private /*RENAME*/_a: string = "foo"; + public get a(): string { + return this._a; + } +}`, +}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts new file mode 100644 index 00000000000..0a2897212df --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts @@ -0,0 +1,24 @@ +/// + +//// class A { +//// public readonly /*a*/a/*b*/: number; +//// constructor () { +//// this.a = 1; +//// } +//// } + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `class A { + private /*RENAME*/_a: number; + public get a(): number { + return this._a; + } + constructor () { + this._a = 1; + } +}`, +}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts new file mode 100644 index 00000000000..170db65d21c --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts @@ -0,0 +1,24 @@ +/// + +//// class A { +//// public readonly /*a*/a/*b*/: number; +//// constructor () { +//// this["a"] = 1; +//// } +//// } + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `class A { + private /*RENAME*/_a: number; + public get a(): number { + return this._a; + } + constructor () { + this["_a"] = 1; + } +}`, +}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts new file mode 100644 index 00000000000..36cc668ef69 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts @@ -0,0 +1,24 @@ +/// + +//// class A { +//// public readonly /*a*/"a"/*b*/: number; +//// constructor () { +//// this["a"] = 1; +//// } +//// } + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `class A { + private /*RENAME*/"_a": number; + public get "a"(): number { + return this["_a"]; + } + constructor () { + this["_a"] = 1; + } +}`, +}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts new file mode 100644 index 00000000000..f75caa271db --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts @@ -0,0 +1,24 @@ +/// + +//// class A { +//// public readonly /*a*/"a-a"/*b*/: number; +//// constructor () { +//// this["a-a"] = 1; +//// } +//// } + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `class A { + private /*RENAME*/"_a-a": number; + public get "a-a"(): number { + return this["_a-a"]; + } + constructor () { + this["_a-a"] = 1; + } +}`, +}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts new file mode 100644 index 00000000000..60ba795d448 --- /dev/null +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts @@ -0,0 +1,28 @@ +/// + +//// class A { +//// public readonly /*a*/a/*b*/: number; +//// constructor () { +//// if (Math.random()) { +//// this.a = 1; // only top level assignment +//// } +//// } +//// } + +goTo.select("a", "b"); +edit.applyRefactor({ + refactorName: "Generate 'get' and 'set' accessors", + actionName: "Generate 'get' and 'set' accessors", + actionDescription: "Generate 'get' and 'set' accessors", + newContent: `class A { + private /*RENAME*/_a: number; + public get a(): number { + return this._a; + } + constructor () { + if (Math.random()) { + this.a = 1; // only top level assignment + } + } +}`, +}); From f09c350471eacb2e4c4f3b558b0b99c6697dfb3d Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 8 May 2018 13:18:38 -0700 Subject: [PATCH 02/44] Batch enumerateFiles for multiple configurations into a single web request --- src/harness/compilerRunner.ts | 78 +++++++++----- src/harness/externalCompileRunner.ts | 2 +- src/harness/fourslashRunner.ts | 24 +++-- src/harness/harness.ts | 28 ++++- src/harness/parallel/host.ts | 3 +- src/harness/projectsRunner.ts | 2 +- src/harness/runnerbase.ts | 7 +- src/harness/rwcRunner.ts | 3 +- src/harness/test262Runner.ts | 3 +- tests/webTestServer.ts | 147 +++++++++++++++++++++++++-- 10 files changed, 234 insertions(+), 63 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index 1ffa2fc63a7..a04f77709ac 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -12,6 +12,10 @@ const enum CompilerTestType { Test262 } +interface CompilerFileBasedTest extends Harness.FileBasedTest { + payload?: Harness.TestCaseParser.TestCaseContent; +} + class CompilerBaselineRunner extends RunnerBase { private basePath = "tests/cases"; private testSuiteName: TestRunnerKind; @@ -42,7 +46,8 @@ class CompilerBaselineRunner extends RunnerBase { } public enumerateTestFiles() { - return this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }); + // see also: `enumerateTestFiles` in tests/webTestServer.ts + return this.enumerateFiles(this.basePath, /\.tsx?$/, { recursive: true }).map(CompilerTest.getConfigurations); } public initializeTests() { @@ -52,24 +57,32 @@ class CompilerBaselineRunner extends RunnerBase { }); // this will set up a series of describe/it blocks to run between the setup and cleanup phases - const files = this.tests.length > 0 ? this.tests : this.enumerateTestFiles(); - files.forEach(file => { this.checkTestCodeOutput(vpath.normalizeSeparators(file)); }); + const files = this.tests.length > 0 ? this.tests : Harness.IO.enumerateTestFiles(this); + files.forEach(test => { + const file = typeof test === "string" ? test : test.file; + this.checkTestCodeOutput(vpath.normalizeSeparators(file), typeof test === "string" ? CompilerTest.getConfigurations(test) : test); + }); }); } - public checkTestCodeOutput(fileName: string) { - for (const { name, payload } of CompilerTest.getConfigurations(fileName)) { - describe(`${this.testSuiteName} tests for ${fileName}${name ? ` (${name})` : ``}`, () => { - this.runSuite(fileName, payload); + public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest) { + if (test && test.configurations) { + test.configurations.forEach(configuration => { + describe(`${this.testSuiteName} tests for ${fileName}${configuration && configuration.name ? ` (${configuration.name})` : ``}`, () => { + this.runSuite(fileName, test, configuration); + }); }); } + describe(`${this.testSuiteName} tests for ${fileName}}`, () => { + this.runSuite(fileName, test); + }); } - private runSuite(fileName: string, testCaseContent: Harness.TestCaseParser.TestCaseContent) { + private runSuite(fileName: string, test?: CompilerFileBasedTest, configuration?: Harness.FileBasedTestConfiguration) { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let compilerTest: CompilerTest | undefined; - before(() => { compilerTest = new CompilerTest(fileName, testCaseContent); }); + before(() => { compilerTest = new CompilerTest(fileName, test && test.payload, configuration && configuration.settings); }); it(`Correct errors for ${fileName}`, () => { compilerTest.verifyDiagnostics(); }); it(`Correct module resolution tracing for ${fileName}`, () => { compilerTest.verifyModuleResolution(); }); it(`Correct sourcemap content for ${fileName}`, () => { compilerTest.verifySourceMapRecord(); }); @@ -97,11 +110,6 @@ class CompilerBaselineRunner extends RunnerBase { } } -interface CompilerTestConfiguration { - name: string; - payload: Harness.TestCaseParser.TestCaseContent; -} - class CompilerTest { private fileName: string; private justName: string; @@ -116,10 +124,20 @@ class CompilerTest { // equivalent to other files on the file system not directly passed to the compiler (ie things that are referenced by other files) private otherFiles: Harness.Compiler.TestFile[]; - constructor(fileName: string, testCaseContent: Harness.TestCaseParser.TestCaseContent) { + constructor(fileName: string, testCaseContent?: Harness.TestCaseParser.TestCaseContent, configurationOverrides?: Harness.TestCaseParser.CompilerSettings) { this.fileName = fileName; this.justName = vpath.basename(fileName); + const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; + + if (testCaseContent === undefined) { + testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(Harness.IO.readFile(fileName), fileName, rootDir); + } + + if (configurationOverrides) { + testCaseContent = { ...testCaseContent, settings: { ...testCaseContent.settings, ...configurationOverrides } }; + } + const units = testCaseContent.testUnitData; this.harnessSettings = testCaseContent.settings; let tsConfigOptions: ts.CompilerOptions; @@ -174,32 +192,38 @@ class CompilerTest { this.options = this.result.options; } - public static getConfigurations(fileName: string) { - const content = Harness.IO.readFile(fileName); - const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; - const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName, rootDir); - const configurations: CompilerTestConfiguration[] = []; - const scriptTargets = this._split(testCaseContent.settings.target); - const moduleKinds = this._split(testCaseContent.settings.module); + public static getConfigurations(file: string): CompilerFileBasedTest { + // also see `parseCompilerTestConfigurations` in tests/webTestServer.ts + const content = Harness.IO.readFile(file); + const rootDir = file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(file) + "/"; + const payload = Harness.TestCaseParser.makeUnitsFromTest(content, file, rootDir); + const settings = Harness.TestCaseParser.extractCompilerSettings(content); + const scriptTargets = CompilerTest._split(settings.target); + const moduleKinds = CompilerTest._split(settings.module); + if (scriptTargets.length <= 1 && moduleKinds.length <= 1) { + return { file, payload }; + } + + const configurations: Harness.FileBasedTestConfiguration[] = []; for (const scriptTarget of scriptTargets) { for (const moduleKind of moduleKinds) { + const settings: Record = {}; let name = ""; if (moduleKinds.length > 1) { + settings.module = moduleKind; name += `@module: ${moduleKind || "none"}`; } if (scriptTargets.length > 1) { + settings.target = scriptTarget; if (name) name += ", "; name += `@target: ${scriptTarget || "none"}`; } - const settings = { ...testCaseContent.settings }; - if (scriptTarget) settings.target = scriptTarget; - if (moduleKind) settings.module = moduleKind; - configurations.push({ name, payload: { ...testCaseContent, settings } }); + configurations.push({ name, settings }); } } - return configurations; + return { file, payload, configurations }; } public verifyDiagnostics() { diff --git a/src/harness/externalCompileRunner.ts b/src/harness/externalCompileRunner.ts index 1d45351114d..c60fc4526ac 100644 --- a/src/harness/externalCompileRunner.ts +++ b/src/harness/externalCompileRunner.ts @@ -28,7 +28,7 @@ abstract class ExternalCompileRunnerBase extends RunnerBase { describe(`${this.kind()} code samples`, () => { for (const test of testList) { - this.runTest(test); + this.runTest(typeof test === "string" ? test : test.file); } }); } diff --git a/src/harness/fourslashRunner.ts b/src/harness/fourslashRunner.ts index d835054a868..d0ad139205a 100644 --- a/src/harness/fourslashRunner.ts +++ b/src/harness/fourslashRunner.ts @@ -36,6 +36,7 @@ class FourSlashRunner extends RunnerBase { } public enumerateTestFiles() { + // see also: `enumerateTestFiles` in tests/webTestServer.ts return this.enumerateFiles(this.basePath, /\.ts/i, { recursive: false }); } @@ -45,22 +46,23 @@ class FourSlashRunner extends RunnerBase { public initializeTests() { if (this.tests.length === 0) { - this.tests = this.enumerateTestFiles(); + this.tests = Harness.IO.enumerateTestFiles(this); } describe(this.testSuiteName + " tests", () => { - this.tests.forEach((fn: string) => { - describe(fn, () => { - fn = ts.normalizeSlashes(fn); - const justName = fn.replace(/^.*[\\\/]/, ""); + this.tests.forEach(test => { + const file = typeof test === "string" ? test : test.file; + describe(file, () => { + let fn = ts.normalizeSlashes(file); + const justName = fn.replace(/^.*[\\\/]/, ""); - // Convert to relative path - const testIndex = fn.indexOf("tests/"); - if (testIndex >= 0) fn = fn.substr(testIndex); + // Convert to relative path + const testIndex = fn.indexOf("tests/"); + if (testIndex >= 0) fn = fn.substr(testIndex); - if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) { - it(this.testSuiteName + " test " + justName + " runs correctly", () => { - FourSlash.runFourSlashTest(this.basePath, this.testType, fn); + if (justName && !justName.match(/fourslash\.ts$/i) && !justName.match(/\.d\.ts$/i)) { + it(this.testSuiteName + " test " + justName + " runs correctly", () => { + FourSlash.runFourSlashTest(this.basePath, this.testType, fn); }); } }); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index d73bfd2ed63..6b718f58841 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -499,6 +499,16 @@ namespace Utils { } namespace Harness { + export interface FileBasedTest { + file: string; + configurations?: FileBasedTestConfiguration[]; + } + + export interface FileBasedTestConfiguration { + name: string; + settings?: Record; + } + // tslint:disable-next-line:interface-name export interface IO { newLine(): string; @@ -514,6 +524,7 @@ namespace Harness { fileExists(fileName: string): boolean; directoryExists(path: string): boolean; deleteFile(fileName: string): void; + enumerateTestFiles(runner: RunnerBase): (string | FileBasedTest)[]; listFiles(path: string, filter?: RegExp, options?: { recursive?: boolean }): string[]; log(text: string): void; args(): string[]; @@ -559,6 +570,10 @@ namespace Harness { return dirPath === path ? undefined : dirPath; } + function enumerateTestFiles(runner: RunnerBase) { + return runner.enumerateTestFiles(); + } + function listFiles(path: string, spec: RegExp, options?: { recursive?: boolean }) { options = options || {}; @@ -639,6 +654,7 @@ namespace Harness { directoryExists: path => ts.sys.directoryExists(path), deleteFile, listFiles, + enumerateTestFiles, log: s => console.log(s), args: () => ts.sys.args, getExecutingFilePath: () => ts.sys.getExecutingFilePath(), @@ -913,6 +929,11 @@ namespace Harness { return ts.getDirectoryPath(ts.normalizeSlashes(url.pathname || "/")); } + function enumerateTestFiles(runner: RunnerBase): (string | FileBasedTest)[] { + const response = send(HttpRequestMessage.post(new URL("/api/enumerateTestFiles", serverRoot), HttpContent.text(runner.kind()))); + return hasJsonContent(response) ? JSON.parse(response.content.content) : []; + } + function listFiles(dirname: string, spec?: RegExp, options?: { recursive?: boolean }): string[] { if (spec || (options && !options.recursive)) { let results = IO.listFiles(dirname); @@ -959,6 +980,7 @@ namespace Harness { directoryExists, deleteFile, listFiles: Utils.memoize(listFiles, (path, spec, options) => `${path}|${spec}|${options ? options.recursive === true : true}`), + enumerateTestFiles: Utils.memoize(enumerateTestFiles, runner => runner.kind()), log: s => console.log(s), args: () => [], getExecutingFilePath: () => "", @@ -1779,7 +1801,7 @@ namespace Harness { // Regex for parsing options in the format "@Alpha: Value of any sort" const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines - function extractCompilerSettings(content: string): CompilerSettings { + export function extractCompilerSettings(content: string): CompilerSettings { const opts: CompilerSettings = {}; let match: RegExpExecArray; @@ -1800,9 +1822,7 @@ namespace Harness { } /** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */ - export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): TestCaseContent { - const settings = extractCompilerSettings(code); - + export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string, settings = extractCompilerSettings(code)): TestCaseContent { // List of all the subfiles we've parsed out const testUnitData: TestUnitData[] = []; diff --git a/src/harness/parallel/host.ts b/src/harness/parallel/host.ts index 75712bc7d9b..47c5216e16e 100644 --- a/src/harness/parallel/host.ts +++ b/src/harness/parallel/host.ts @@ -81,7 +81,8 @@ namespace Harness.Parallel.Host { const { statSync }: { statSync(path: string): { size: number }; } = require("fs"); const path: { join: (...args: string[]) => string } = require("path"); for (const runner of runners) { - for (const file of runner.enumerateTestFiles()) { + for (const test of runner.enumerateTestFiles()) { + const file = typeof test === "string" ? test : test.file; let size: number; if (!perfData) { try { diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index 8c396ec44f1..08e92a73be2 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -51,7 +51,7 @@ namespace project { describe("projects tests", () => { const tests = this.tests.length === 0 ? this.enumerateTestFiles() : this.tests; for (const test of tests) { - this.runProjectTestCase(test); + this.runProjectTestCase(typeof test === "string" ? test : test.file); } }); } diff --git a/src/harness/runnerbase.ts b/src/harness/runnerbase.ts index 80532d30b6f..b29ebb7f920 100644 --- a/src/harness/runnerbase.ts +++ b/src/harness/runnerbase.ts @@ -1,13 +1,10 @@ -/// - - type TestRunnerKind = CompilerTestKind | FourslashTestKind | "project" | "rwc" | "test262" | "user" | "dt"; type CompilerTestKind = "conformance" | "compiler"; type FourslashTestKind = "fourslash" | "fourslash-shims" | "fourslash-shims-pp" | "fourslash-server"; abstract class RunnerBase { // contains the tests to run - public tests: string[] = []; + public tests: (string | Harness.FileBasedTest)[] = []; /** Add a source file to the runner's list of tests that need to be initialized with initializeTests */ public addTest(fileName: string) { @@ -20,7 +17,7 @@ abstract class RunnerBase { abstract kind(): TestRunnerKind; - abstract enumerateTestFiles(): string[]; + abstract enumerateTestFiles(): (string | Harness.FileBasedTest)[]; /** The working directory where tests are found. Needed for batch testing where the input path will differ from the output path inside baselines */ public workingDirectory = ""; diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index bfd0153466c..d2adc112df8 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -232,6 +232,7 @@ namespace RWC { class RWCRunner extends RunnerBase { public enumerateTestFiles() { + // see also: `enumerateTestFiles` in tests/webTestServer.ts return Harness.IO.getDirectories("internal/cases/rwc/"); } @@ -245,7 +246,7 @@ class RWCRunner extends RunnerBase { public initializeTests(): void { // Read in and evaluate the test list for (const test of this.tests && this.tests.length ? this.tests : this.enumerateTestFiles()) { - this.runTest(test); + this.runTest(typeof test === "string" ? test : test.file); } } diff --git a/src/harness/test262Runner.ts b/src/harness/test262Runner.ts index 08a42ed2ff7..7f83d9101bd 100644 --- a/src/harness/test262Runner.ts +++ b/src/harness/test262Runner.ts @@ -101,6 +101,7 @@ class Test262BaselineRunner extends RunnerBase { } public enumerateTestFiles() { + // see also: `enumerateTestFiles` in tests/webTestServer.ts return ts.map(this.enumerateFiles(Test262BaselineRunner.basePath, Test262BaselineRunner.testFileExtensionRegex, { recursive: true }), ts.normalizePath); } @@ -113,7 +114,7 @@ class Test262BaselineRunner extends RunnerBase { }); } else { - this.tests.forEach(test => this.runTest(test)); + this.tests.forEach(test => this.runTest(typeof test === "string" ? test : test.file)); } } } diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts index 5309d58f768..372a4bdffad 100644 --- a/tests/webTestServer.ts +++ b/tests/webTestServer.ts @@ -24,6 +24,16 @@ let browser = "IE"; let grep: string | undefined; let verbose = false; +interface FileTest { + file: string; + configurations?: FileTestConfiguration[]; +} + +interface FileTestConfiguration { + name: string; + settings: Record; +} + function isFileSystemCaseSensitive(): boolean { // win32\win64 are case insensitive platforms const platform = os.platform(); @@ -84,6 +94,20 @@ function toClientPath(pathname: string) { return clientPath; } +function flatMap(array: T[], selector: (value: T) => U | U[]) { + let result: U[] = []; + for (const item of array) { + const mapped = selector(item); + if (Array.isArray(mapped)) { + result = result.concat(mapped); + } + else { + result.push(mapped); + } + } + return result; +} + declare module "http" { interface IncomingHttpHeaders { "if-match"?: string; @@ -640,24 +664,104 @@ function handleApiResolve(req: http.ServerRequest, res: http.ServerResponse) { }); } +function handleApiEnumerateTestFiles(req: http.ServerRequest, res: http.ServerResponse) { + readContent(req, (err, content) => { + try { + if (err) return sendInternalServerError(res, err); + if (!content) return sendBadRequest(res); + const tests: (string | FileTest)[] = enumerateTestFiles(content); + return sendJson(res, /*statusCode*/ 200, tests); + } + catch (e) { + return sendInternalServerError(res, e); + } + }); +} + +function enumerateTestFiles(runner: string) { + switch (runner) { + case "conformance": + case "compiler": + return listFiles(`tests/cases/${runner}`, /*serverDirname*/ undefined, /\.tsx?$/, { recursive: true }).map(parseCompilerTestConfigurations); + case "fourslash": + return listFiles(`tests/cases/fourslash`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); + case "fourslash-shims": + return listFiles(`tests/cases/fourslash/shims`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); + case "fourslash-shims-pp": + return listFiles(`tests/cases/fourslash/shims-pp`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); + case "fourslash-server": + return listFiles(`tests/cases/fourslash/server`, /*serverDirname*/ undefined, /\.ts/i, { recursive: false }); + default: + throw new Error(`Runner '${runner}' not supported in browser tests.`); + } +} + +// Regex for parsing options in the format "@Alpha: Value of any sort" +const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines + +function extractCompilerSettings(content: string): Record { + const opts: Record = {}; + + let match: RegExpExecArray; + /* tslint:disable:no-null-keyword */ + while ((match = optionRegex.exec(content)) !== null) { + /* tslint:enable:no-null-keyword */ + opts[match[1]] = match[2].trim(); + } + + return opts; +} + +function split(text: string) { + const entries = text && text.split(",").map(s => s.toLowerCase().trim()).filter(s => s.length > 0); + return entries && entries.length > 0 ? entries : [""]; +} + +function parseCompilerTestConfigurations(file: string): FileTest { + const content = fs.readFileSync(path.join(rootDir, file), "utf8"); + const settings = extractCompilerSettings(content); + const scriptTargets = split(settings.target); + const moduleKinds = split(settings.module); + if (scriptTargets.length <= 1 && moduleKinds.length <= 1) { + return { file }; + } + + const configurations: FileTestConfiguration[] = []; + for (const scriptTarget of scriptTargets) { + for (const moduleKind of moduleKinds) { + const settings: Record = {}; + let name = ""; + if (moduleKinds.length > 1) { + settings.module = moduleKind; + name += `@module: ${moduleKind || "none"}`; + } + if (scriptTargets.length > 1) { + settings.target = scriptTarget; + if (name) name += ", "; + name += `@target: ${scriptTarget || "none"}`; + } + configurations.push({ name, settings }); + } + } + + return { file, configurations }; +} + +function parseProjectTestConfigurations(file: string): FileTest { + return { file, configurations: [ + { name: `@module: commonjs`, settings: { module: "commonjs" } }, + { name: `@module: amd`, settings: { module: "amd" } }, + ] }; +} + function handleApiListFiles(req: http.ServerRequest, res: http.ServerResponse) { readContent(req, (err, content) => { try { if (err) return sendInternalServerError(res, err); if (!content) return sendBadRequest(res); const serverPath = toServerPath(content); - const files: string[] = []; - visit(serverPath, content, files); + const files = listFiles(content, serverPath, /*spec*/ undefined, { recursive: true }); return sendJson(res, /*statusCode*/ 200, files); - function visit(dirname: string, relative: string, results: string[]) { - const { files, directories } = getAccessibleFileSystemEntries(dirname); - for (const file of files) { - results.push(path.join(relative, file)); - } - for (const directory of directories) { - visit(path.join(dirname, directory), path.join(relative, directory), results); - } - } } catch (e) { return sendInternalServerError(res, e); @@ -665,6 +769,26 @@ function handleApiListFiles(req: http.ServerRequest, res: http.ServerResponse) { }); } +function listFiles(clientDirname: string, serverDirname: string = path.resolve(rootDir, clientDirname), spec?: RegExp, options: { recursive?: boolean } = {}): string[] { + const files: string[] = []; + visit(serverDirname, clientDirname, files); + return files; + + function visit(dirname: string, relative: string, results: string[]) { + const { files, directories } = getAccessibleFileSystemEntries(dirname); + for (const file of files) { + if (!spec || file.match(spec)) { + results.push(path.join(relative, file)); + } + } + for (const directory of directories) { + if (options.recursive) { + visit(path.join(dirname, directory), path.join(relative, directory), results); + } + } + } +} + function handleApiDirectoryExists(req: http.ServerRequest, res: http.ServerResponse) { readContent(req, (err, content) => { try { @@ -707,6 +831,7 @@ function handlePostRequest(req: http.ServerRequest, res: http.ServerResponse) { switch (new URL(req.url, baseUrl).pathname) { case "/api/resolve": return handleApiResolve(req, res); case "/api/listFiles": return handleApiListFiles(req, res); + case "/api/enumerateTestFiles": return handleApiEnumerateTestFiles(req, res); case "/api/directoryExists": return handleApiDirectoryExists(req, res); case "/api/getAccessibleFileSystemEntries": return handleApiGetAccessibleFileSystemEntries(req, res); default: return sendMethodNotAllowed(res, ["HEAD", "GET", "PUT", "DELETE", "OPTIONS"]); From 8414a962bad1a29cb851778a3cf098994ac5b8ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Wed, 9 May 2018 18:41:46 +0800 Subject: [PATCH 03/44] update all reference in constructor --- .../generateGetAccessorAndSetAccessor.ts | 54 ++++++++----------- ...efactorConvertToGetAccessAndSetAccess33.ts | 22 +++++++- ...efactorConvertToGetAccessAndSetAccess34.ts | 24 --------- ...efactorConvertToGetAccessAndSetAccess35.ts | 24 --------- ...efactorConvertToGetAccessAndSetAccess36.ts | 24 --------- ...efactorConvertToGetAccessAndSetAccess37.ts | 28 ---------- 6 files changed, 41 insertions(+), 135 deletions(-) delete mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts delete mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts delete mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts delete mode 100644 tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts diff --git a/src/services/refactors/generateGetAccessorAndSetAccessor.ts b/src/services/refactors/generateGetAccessorAndSetAccessor.ts index 799fa58d6d7..55e0780b9e8 100644 --- a/src/services/refactors/generateGetAccessorAndSetAccessor.ts +++ b/src/services/refactors/generateGetAccessorAndSetAccessor.ts @@ -16,6 +16,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { declaration: AcceptedDeclaration; fieldName: AcceptedNameType; accessorName: AcceptedNameType; + originalName: AcceptedNameType; } function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined { @@ -42,7 +43,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { const isJS = isSourceFileJavaScript(file); const changeTracker = textChanges.ChangeTracker.fromContext(context); - const { isStatic, isReadonly, fieldName, accessorName, type, container, declaration } = fieldInfo; + const { isStatic, isReadonly, fieldName, accessorName, originalName, type, container, declaration } = fieldInfo; suppressLeadingAndTrailingTrivia(fieldName); suppressLeadingAndTrailingTrivia(declaration); @@ -68,7 +69,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { // readonly modifier only existed in classLikeDeclaration const constructor = getFirstConstructorWithBody(container); if (constructor) { - updateReadonlyPropertyInitializerStatementConstructor(changeTracker, file, constructor, accessorName, fieldName); + updateReadonlyPropertyInitializerStatementConstructor(changeTracker, context, constructor, fieldName, originalName); } } else { @@ -123,6 +124,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { isReadonly: hasReadonlyModifier(declaration), type: getTypeAnnotationNode(declaration), container: declaration.kind === SyntaxKind.Parameter ? declaration.parent.parent : declaration.parent, + originalName: declaration.name, declaration, fieldName, accessorName, @@ -205,37 +207,23 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor { : changeTracker.insertNodeAfter(file, declaration, accessor); } - function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, file: SourceFile, constructor: ConstructorDeclaration, accessorName: AcceptedNameType, fieldName: AcceptedNameType) { - if (constructor.body) { - const initializerStatement = find(constructor.body.statements, (stmt => - isExpressionStatement(stmt) && - isAssignmentExpression(stmt.expression) && - stmt.expression.operatorToken.kind === SyntaxKind.EqualsToken && - (isPropertyAccessExpression(stmt.expression.left) || isElementAccessExpression(stmt.expression.left)) && - isThis(stmt.expression.left.expression) && - (isPropertyAccessExpression(stmt.expression.left) - ? (getNameFromPropertyName(stmt.expression.left.name) === accessorName.text) - : (isPropertyName(stmt.expression.left.argumentExpression) && isConvertableName(stmt.expression.left.argumentExpression) && getNameFromPropertyName(stmt.expression.left.argumentExpression) === accessorName.text - )) - )); - if (initializerStatement) { - const initializerLeftHead = ((>>(initializerStatement).expression).left); + function updateReadonlyPropertyInitializerStatementConstructor(changeTracker: textChanges.ChangeTracker, context: RefactorContext, constructor: ConstructorDeclaration, fieldName: AcceptedNameType, originalName: AcceptedNameType) { + if (!constructor.body) return; + const { file, program, cancellationToken } = context; - if (isPropertyAccessExpression(initializerLeftHead)) { - changeTracker.replaceNode(file, initializerLeftHead, updatePropertyAccess( - initializerLeftHead, - initializerLeftHead.expression, - createIdentifier(fieldName.text) - )); - } - else { - changeTracker.replaceNode(file, initializerLeftHead, updateElementAccess( - initializerLeftHead, - initializerLeftHead.expression, - createPropertyName(fieldName.text, initializerLeftHead.argumentExpression) - )); - } - } - } + const referenceEntries = mapDefined(FindAllReferences.getReferenceEntriesForNode(-1, originalName, program, [file], cancellationToken), entry => ( + (entry.type === "node" && rangeContainsRange(constructor, entry.node) && isIdentifier(entry.node) && isWriteAccess(entry.node)) ? entry.node : undefined + )); + + forEach(referenceEntries, entry => { + const parent = entry.parent; + const accessorName = createIdentifier(fieldName.text); + const node = isBinaryExpression(parent) + ? updateBinary(parent, accessorName, parent.right, parent.operatorToken) + : isPropertyAccessExpression(parent) + ? updatePropertyAccess(parent, parent.expression, accessorName) + : Debug.fail("Unexpected write access token"); + changeTracker.replaceNode(file, parent, node); + }); } } diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts index 0a2897212df..d74f246fdfe 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess33.ts @@ -2,9 +2,18 @@ //// class A { //// public readonly /*a*/a/*b*/: number; +//// public b: number; //// constructor () { -//// this.a = 1; +//// this.a = 1; // convert +//// this.a++; // convert +//// ++this.a; // convert +//// if (Math.random()) { +//// this.a = 2; // convert +//// } +//// console.log(this.a); // preserve +//// this.b = this.a; // preserve //// } +//// foo () { this.a = 2; } //// } goTo.select("a", "b"); @@ -17,8 +26,17 @@ edit.applyRefactor({ public get a(): number { return this._a; } + public b: number; constructor () { - this._a = 1; + this._a = 1; // convert + this._a++; // convert + ++this._a; // convert + if (Math.random()) { + this._a = 2; // convert + } + console.log(this.a); // preserve + this.b = this.a; // preserve } + foo () { this.a = 2; } }`, }); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts deleted file mode 100644 index 170db65d21c..00000000000 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess34.ts +++ /dev/null @@ -1,24 +0,0 @@ -/// - -//// class A { -//// public readonly /*a*/a/*b*/: number; -//// constructor () { -//// this["a"] = 1; -//// } -//// } - -goTo.select("a", "b"); -edit.applyRefactor({ - refactorName: "Generate 'get' and 'set' accessors", - actionName: "Generate 'get' and 'set' accessors", - actionDescription: "Generate 'get' and 'set' accessors", - newContent: `class A { - private /*RENAME*/_a: number; - public get a(): number { - return this._a; - } - constructor () { - this["_a"] = 1; - } -}`, -}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts deleted file mode 100644 index 36cc668ef69..00000000000 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess35.ts +++ /dev/null @@ -1,24 +0,0 @@ -/// - -//// class A { -//// public readonly /*a*/"a"/*b*/: number; -//// constructor () { -//// this["a"] = 1; -//// } -//// } - -goTo.select("a", "b"); -edit.applyRefactor({ - refactorName: "Generate 'get' and 'set' accessors", - actionName: "Generate 'get' and 'set' accessors", - actionDescription: "Generate 'get' and 'set' accessors", - newContent: `class A { - private /*RENAME*/"_a": number; - public get "a"(): number { - return this["_a"]; - } - constructor () { - this["_a"] = 1; - } -}`, -}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts deleted file mode 100644 index f75caa271db..00000000000 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess36.ts +++ /dev/null @@ -1,24 +0,0 @@ -/// - -//// class A { -//// public readonly /*a*/"a-a"/*b*/: number; -//// constructor () { -//// this["a-a"] = 1; -//// } -//// } - -goTo.select("a", "b"); -edit.applyRefactor({ - refactorName: "Generate 'get' and 'set' accessors", - actionName: "Generate 'get' and 'set' accessors", - actionDescription: "Generate 'get' and 'set' accessors", - newContent: `class A { - private /*RENAME*/"_a-a": number; - public get "a-a"(): number { - return this["_a-a"]; - } - constructor () { - this["_a-a"] = 1; - } -}`, -}); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts deleted file mode 100644 index 60ba795d448..00000000000 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess37.ts +++ /dev/null @@ -1,28 +0,0 @@ -/// - -//// class A { -//// public readonly /*a*/a/*b*/: number; -//// constructor () { -//// if (Math.random()) { -//// this.a = 1; // only top level assignment -//// } -//// } -//// } - -goTo.select("a", "b"); -edit.applyRefactor({ - refactorName: "Generate 'get' and 'set' accessors", - actionName: "Generate 'get' and 'set' accessors", - actionDescription: "Generate 'get' and 'set' accessors", - newContent: `class A { - private /*RENAME*/_a: number; - public get a(): number { - return this._a; - } - constructor () { - if (Math.random()) { - this.a = 1; // only top level assignment - } - } -}`, -}); From 9b04dc3897e24ae3d72bf4dd8cbe66402bde9c48 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 9 May 2018 12:57:48 -0700 Subject: [PATCH 04/44] PR Feedback --- src/harness/compilerRunner.ts | 35 ++------------- src/harness/harness.ts | 78 ++++++++++++++++++++++++++++----- tests/webTestServer.ts | 82 ++++++++++++++++++----------------- 3 files changed, 113 insertions(+), 82 deletions(-) diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index a04f77709ac..91a95e22c89 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -68,7 +68,7 @@ class CompilerBaselineRunner extends RunnerBase { public checkTestCodeOutput(fileName: string, test?: CompilerFileBasedTest) { if (test && test.configurations) { test.configurations.forEach(configuration => { - describe(`${this.testSuiteName} tests for ${fileName}${configuration && configuration.name ? ` (${configuration.name})` : ``}`, () => { + describe(`${this.testSuiteName} tests for ${fileName}${configuration ? ` (${Harness.getFileBasedTestConfigurationDescription(configuration)})` : ``}`, () => { this.runSuite(fileName, test, configuration); }); }); @@ -82,7 +82,7 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let compilerTest: CompilerTest | undefined; - before(() => { compilerTest = new CompilerTest(fileName, test && test.payload, configuration && configuration.settings); }); + before(() => { compilerTest = new CompilerTest(fileName, test && test.payload, configuration); }); it(`Correct errors for ${fileName}`, () => { compilerTest.verifyDiagnostics(); }); it(`Correct module resolution tracing for ${fileName}`, () => { compilerTest.verifyModuleResolution(); }); it(`Correct sourcemap content for ${fileName}`, () => { compilerTest.verifySourceMapRecord(); }); @@ -198,31 +198,7 @@ class CompilerTest { const rootDir = file.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(file) + "/"; const payload = Harness.TestCaseParser.makeUnitsFromTest(content, file, rootDir); const settings = Harness.TestCaseParser.extractCompilerSettings(content); - const scriptTargets = CompilerTest._split(settings.target); - const moduleKinds = CompilerTest._split(settings.module); - if (scriptTargets.length <= 1 && moduleKinds.length <= 1) { - return { file, payload }; - } - - const configurations: Harness.FileBasedTestConfiguration[] = []; - for (const scriptTarget of scriptTargets) { - for (const moduleKind of moduleKinds) { - const settings: Record = {}; - let name = ""; - if (moduleKinds.length > 1) { - settings.module = moduleKind; - name += `@module: ${moduleKind || "none"}`; - } - if (scriptTargets.length > 1) { - settings.target = scriptTarget; - if (name) name += ", "; - name += `@target: ${scriptTarget || "none"}`; - } - - configurations.push({ name, settings }); - } - } - + const configurations = Harness.getFileBasedTestConfigurations(settings, /*varyBy*/ ["module", "target"]); return { file, payload, configurations }; } @@ -291,11 +267,6 @@ class CompilerTest { this.toBeCompiled.concat(this.otherFiles).filter(file => !!this.result.program.getSourceFile(file.unitName))); } - private static _split(text: string) { - const entries = text && text.split(",").map(s => s.toLowerCase().trim()).filter(s => s.length > 0); - return entries && entries.length > 0 ? entries : [""]; - } - private makeUnitName(name: string, root: string) { const path = ts.toPath(name, root, ts.identity); const pathStart = ts.toPath(Harness.IO.getCurrentDirectory(), "", ts.identity); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 6b718f58841..28233b797da 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -499,16 +499,6 @@ namespace Utils { } namespace Harness { - export interface FileBasedTest { - file: string; - configurations?: FileBasedTestConfiguration[]; - } - - export interface FileBasedTestConfiguration { - name: string; - settings?: Record; - } - // tslint:disable-next-line:interface-name export interface IO { newLine(): string; @@ -1783,6 +1773,74 @@ namespace Harness { } } + export interface FileBasedTest { + file: string; + configurations?: FileBasedTestConfiguration[]; + } + + export interface FileBasedTestConfiguration { + [key: string]: string; + } + + function splitVaryBySettingValue(text: string): string[] | undefined { + if (!text) return undefined; + const entries = text.split(/,/).map(s => s.trim().toLowerCase()).filter(s => s.length > 0); + return entries && entries.length > 1 ? entries : undefined; + } + + function computeFileBasedTestConfigurationVariations(configurations: FileBasedTestConfiguration[], variationState: FileBasedTestConfiguration, varyByEntries: [string, string[]][], offset: number) { + if (offset >= varyByEntries.length) { + // make a copy of the current variation state + configurations.push({ ...variationState }); + return; + } + + const [varyBy, entries] = varyByEntries[offset]; + for (const entry of entries) { + // set or overwrite the variation, then compute the next variation + variationState[varyBy] = entry; + computeFileBasedTestConfigurationVariations(configurations, variationState, varyByEntries, offset + 1); + } + } + + /** + * Compute FileBasedTestConfiguration variations based on a supplied list of variable settings. + */ + export function getFileBasedTestConfigurations(settings: TestCaseParser.CompilerSettings, varyBy: string[]): FileBasedTestConfiguration[] | undefined { + let varyByEntries: [string, string[]][] | undefined; + for (const varyByKey of varyBy) { + if (ts.hasProperty(settings, varyByKey)) { + // we only consider variations when there are 2 or more variable entries. + const entries = splitVaryBySettingValue(settings[varyByKey]); + if (entries) { + if (!varyByEntries) varyByEntries = []; + varyByEntries.push([varyByKey, entries]); + } + } + } + + if (!varyByEntries) return undefined; + + const configurations: FileBasedTestConfiguration[] = []; + computeFileBasedTestConfigurationVariations(configurations, /*variationState*/ {}, varyByEntries, /*offset*/ 0); + return configurations; + } + + /** + * Compute a description for this configuration based on its entries + */ + export function getFileBasedTestConfigurationDescription(configuration: FileBasedTestConfiguration) { + let name = ""; + if (configuration) { + const keys = Object.keys(configuration).sort(); + for (const key of keys) { + if (name) name += ", "; + name += `@${key}: ${configuration[key]}`; + } + } + return name; + } + export namespace TestCaseParser { /** all the necessary information to set the right compiler settings */ export interface CompilerSettings { diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts index 372a4bdffad..22f066bbf85 100644 --- a/tests/webTestServer.ts +++ b/tests/webTestServer.ts @@ -24,14 +24,13 @@ let browser = "IE"; let grep: string | undefined; let verbose = false; -interface FileTest { +interface FileBasedTest { file: string; - configurations?: FileTestConfiguration[]; + configurations?: FileBasedTestConfiguration[]; } -interface FileTestConfiguration { - name: string; - settings: Record; +interface FileBasedTestConfiguration { + [setting: string]: string; } function isFileSystemCaseSensitive(): boolean { @@ -669,7 +668,7 @@ function handleApiEnumerateTestFiles(req: http.ServerRequest, res: http.ServerRe try { if (err) return sendInternalServerError(res, err); if (!content) return sendBadRequest(res); - const tests: (string | FileTest)[] = enumerateTestFiles(content); + const tests: (string | FileBasedTest)[] = enumerateTestFiles(content); return sendJson(res, /*statusCode*/ 200, tests); } catch (e) { @@ -699,59 +698,62 @@ function enumerateTestFiles(runner: string) { // Regex for parsing options in the format "@Alpha: Value of any sort" const optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*([^\r\n]*)/gm; // multiple matches on multiple lines -function extractCompilerSettings(content: string): Record { - const opts: Record = {}; +function extractCompilerSettings(content: string): Record { + const opts: Record = {}; let match: RegExpExecArray; - /* tslint:disable:no-null-keyword */ while ((match = optionRegex.exec(content)) !== null) { - /* tslint:enable:no-null-keyword */ opts[match[1]] = match[2].trim(); } return opts; } -function split(text: string) { - const entries = text && text.split(",").map(s => s.toLowerCase().trim()).filter(s => s.length > 0); - return entries && entries.length > 0 ? entries : [""]; +function splitVaryBySettingValue(text: string): string[] | undefined { + if (!text) return undefined; + const entries = text.split(/,/).map(s => s.trim().toLowerCase()).filter(s => s.length > 0); + return entries && entries.length > 1 ? entries : undefined; } -function parseCompilerTestConfigurations(file: string): FileTest { - const content = fs.readFileSync(path.join(rootDir, file), "utf8"); - const settings = extractCompilerSettings(content); - const scriptTargets = split(settings.target); - const moduleKinds = split(settings.module); - if (scriptTargets.length <= 1 && moduleKinds.length <= 1) { - return { file }; +function computeFileBasedTestConfigurationVariations(configurations: FileBasedTestConfiguration[], variationState: FileBasedTestConfiguration, varyByEntries: [string, string[]][], offset: number) { + if (offset >= varyByEntries.length) { + // make a copy of the current variation state + configurations.push({ ...variationState }); + return; } - const configurations: FileTestConfiguration[] = []; - for (const scriptTarget of scriptTargets) { - for (const moduleKind of moduleKinds) { - const settings: Record = {}; - let name = ""; - if (moduleKinds.length > 1) { - settings.module = moduleKind; - name += `@module: ${moduleKind || "none"}`; + const [varyBy, entries] = varyByEntries[offset]; + for (const entry of entries) { + // set or overwrite the variation + variationState[varyBy] = entry; + computeFileBasedTestConfigurationVariations(configurations, variationState, varyByEntries, offset + 1); + } +} + +function getFileBasedTestConfigurations(settings: Record, varyBy: string[]): FileBasedTestConfiguration[] | undefined { + let varyByEntries: [string, string[]][] | undefined; + for (const varyByKey of varyBy) { + if (Object.prototype.hasOwnProperty.call(settings, varyByKey)) { + const entries = splitVaryBySettingValue(settings[varyByKey]); + if (entries) { + if (!varyByEntries) varyByEntries = []; + varyByEntries.push([varyByKey, entries]); } - if (scriptTargets.length > 1) { - settings.target = scriptTarget; - if (name) name += ", "; - name += `@target: ${scriptTarget || "none"}`; - } - configurations.push({ name, settings }); } } - return { file, configurations }; + if (!varyByEntries) return undefined; + + const configurations: FileBasedTestConfiguration[] = []; + computeFileBasedTestConfigurationVariations(configurations, {}, varyByEntries, 0); + return configurations; } -function parseProjectTestConfigurations(file: string): FileTest { - return { file, configurations: [ - { name: `@module: commonjs`, settings: { module: "commonjs" } }, - { name: `@module: amd`, settings: { module: "amd" } }, - ] }; +function parseCompilerTestConfigurations(file: string): FileBasedTest { + const content = fs.readFileSync(path.join(rootDir, file), "utf8"); + const settings = extractCompilerSettings(content); + const configurations = getFileBasedTestConfigurations(settings, ["module", "target"]); + return { file, configurations }; } function handleApiListFiles(req: http.ServerRequest, res: http.ServerResponse) { From fc3ba76ab72df37d82dfaeefcaf8865a8ef017d8 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Wed, 9 May 2018 22:22:46 +0200 Subject: [PATCH 05/44] Add createRegularExpressionLiteral and expose createStringLiteral Fixes: #23992 --- src/compiler/factory.ts | 8 +++++++- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 ++ tests/baselines/reference/api/typescript.d.ts | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index e8916ac62e5..bcbf7a1bed1 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -93,12 +93,18 @@ namespace ts { return node; } - function createStringLiteral(text: string): StringLiteral { + export function createStringLiteral(text: string): StringLiteral { const node = createSynthesizedNode(SyntaxKind.StringLiteral); node.text = text; return node; } + export function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { + const node = createSynthesizedNode(SyntaxKind.RegularExpressionLiteral); + node.text = text; + return node; + } + function createLiteralFromNode(sourceNode: PropertyNameLiteral): StringLiteral { const node = createStringLiteral(getTextOfIdentifierOrLiteral(sourceNode)); node.textSourceNode = sourceNode; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 845ce42b5dc..96749475081 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -3484,6 +3484,8 @@ declare namespace ts { function createLiteral(value: boolean): BooleanLiteral; function createLiteral(value: string | number | boolean): PrimaryExpression; function createNumericLiteral(value: string): NumericLiteral; + function createStringLiteral(text: string): StringLiteral; + function createRegularExpressionLiteral(text: string): RegularExpressionLiteral; function createIdentifier(text: string): Identifier; function updateIdentifier(node: Identifier): Identifier; /** Create a unique temporary variable. */ diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index de20defcdcb..4203c56bf95 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -3484,6 +3484,8 @@ declare namespace ts { function createLiteral(value: boolean): BooleanLiteral; function createLiteral(value: string | number | boolean): PrimaryExpression; function createNumericLiteral(value: string): NumericLiteral; + function createStringLiteral(text: string): StringLiteral; + function createRegularExpressionLiteral(text: string): RegularExpressionLiteral; function createIdentifier(text: string): Identifier; function updateIdentifier(node: Identifier): Identifier; /** Create a unique temporary variable. */ From ec9c1556ad848298621d4af86f545ef39d445807 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 9 May 2018 14:30:07 -0700 Subject: [PATCH 06/44] Fix publish nightly on case sensitive FS (#23997) --- Gulpfile.js | 2 +- Jakefile.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gulpfile.js b/Gulpfile.js index 9a082bb4479..4dd0be70672 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -160,7 +160,7 @@ const generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessag * 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg' * generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json */ -const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"] +const localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"] .map(f => path.join(builtLocalDirectory, f, "diagnosticMessages.generated.json")) .concat(generatedLCGFile); diff --git a/Jakefile.js b/Jakefile.js index 2eeccdd7a4f..7c8c302ce11 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -131,7 +131,7 @@ var generatedLCGFile = path.join(builtLocalDirectory, "enu", "diagnosticMessages * 2. 'src\compiler\diagnosticMessages.generated.json' => 'built\local\ENU\diagnosticMessages.generated.json.lcg' * generate the lcg file (source of messages to localize) from the diagnosticMessages.generated.json */ -var localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-BR", "ru", "tr", "zh-CN", "zh-TW"].map(function (f) { +var localizationTargets = ["cs", "de", "es", "fr", "it", "ja", "ko", "pl", "pt-br", "ru", "tr", "zh-cn", "zh-tw"].map(function (f) { return path.join(builtLocalDirectory, f); }).concat(path.dirname(generatedLCGFile)); From d06f9c29b0d0a5eda43752b5d4d4323b3f89e672 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 9 May 2018 14:16:34 -0700 Subject: [PATCH 07/44] Default to 'edge' instead of 'IE' for browser tests --- Gulpfile.js | 2 +- Jakefile.js | 2 +- tests/webTestServer.ts | 174 ++++++++++++++++++++++++++--------------- 3 files changed, 112 insertions(+), 66 deletions(-) diff --git a/Gulpfile.js b/Gulpfile.js index 9a082bb4479..cf6f0a7410d 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -54,7 +54,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), { debug: process.env.debug || process.env["debug-brk"] || process.env.d, inspect: process.env.inspect || process.env["inspect-brk"] || process.env.i, host: process.env.TYPESCRIPT_HOST || process.env.host || "node", - browser: process.env.browser || process.env.b || "IE", + browser: process.env.browser || process.env.b || (os.platform() === "win32" ? "edge" : "chrome"), timeout: process.env.timeout || 40000, tests: process.env.test || process.env.tests || process.env.t, runners: process.env.runners || process.env.runner || process.env.ru, diff --git a/Jakefile.js b/Jakefile.js index 2eeccdd7a4f..0cf794edd28 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -922,7 +922,7 @@ desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is task("runtests-browser", ["browserify", nodeServerOutFile], function () { cleanTestDirs(); host = "node"; - var browser = process.env.browser || process.env.b || (os.platform() === "linux" ? "chrome" : "IE"); + var browser = process.env.browser || process.env.b || (os.platform() === "win32" ? "edge" : "chrome"); var runners = process.env.runners || process.env.runner || process.env.ru; var tests = process.env.test || process.env.tests || process.env.t; var light = process.env.light || false; diff --git a/tests/webTestServer.ts b/tests/webTestServer.ts index 22f066bbf85..c33196a99ca 100644 --- a/tests/webTestServer.ts +++ b/tests/webTestServer.ts @@ -1,6 +1,7 @@ /// // tslint:disable:no-null-keyword +import minimist = require("minimist"); import http = require("http"); import fs = require("fs"); import path = require("path"); @@ -20,7 +21,8 @@ const baseUrl = new URL(`http://localhost:${port}/`); const rootDir = path.dirname(__dirname); const useCaseSensitiveFileNames = isFileSystemCaseSensitive(); -let browser = "IE"; +const defaultBrowser = os.platform() === "win32" ? "edge" : "chrome"; +let browser: "edge" | "chrome" | "none" = defaultBrowser; let grep: string | undefined; let verbose = false; @@ -862,50 +864,101 @@ function startServer() { return http.createServer(handleRequest).listen(port); } +const REG_COLUMN_PADDING = 4; + +function queryRegistryValue(keyPath: string, callback: (error: Error | null, value: string) => void) { + const args = ["query", keyPath]; + child_process.execFile("reg", ["query", keyPath, "/ve"], { encoding: "utf8" }, (error, stdout) => { + if (error) return callback(error, null); + + const valueLine = stdout.replace(/^\r\n.+?\r\n|\r\n\r\n$/g, ""); + if (!valueLine) { + return callback(new Error("Unable to retrieve value."), null); + } + + const valueNameColumnOffset = REG_COLUMN_PADDING; + if (valueLine.lastIndexOf("(Default)", valueNameColumnOffset) !== valueNameColumnOffset) { + return callback(new Error("Unable to retrieve value."), null); + } + + const dataTypeColumnOffset = valueNameColumnOffset + "(Default)".length + REG_COLUMN_PADDING; + if (valueLine.lastIndexOf("REG_SZ", dataTypeColumnOffset) !== dataTypeColumnOffset) { + return callback(new Error("Unable to retrieve value."), null); + } + + const valueColumnOffset = dataTypeColumnOffset + "REG_SZ".length + REG_COLUMN_PADDING; + const value = valueLine.slice(valueColumnOffset); + return callback(null, value); + }); +} + +interface Browser { + description: string; + command: string; +} + +function createBrowserFromPath(path: string): Browser { + return { description: path, command: path }; +} + +function getChromePath(callback: (error: Error | null, browser: Browser | string | null) => void) { + switch (os.platform()) { + case "win32": + return queryRegistryValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\chrome.exe", (error, value) => { + if (error) return callback(null, "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"); + return callback(null, createBrowserFromPath(value)); + }); + case "darwin": return callback(null, "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"); + case "linux": return callback(null, "/opt/google/chrome/chrome"); + default: return callback(new Error(`Chrome location is unknown for platform '${os.platform()}'`), null); + } +} + +function getEdgePath(callback: (error: Error | null, browser: Browser | null) => void) { + switch (os.platform()) { + case "win32": return callback(null, { description: "Microsoft Edge", command: "cmd /c start microsoft-edge:%1" }); + default: return callback(new Error(`Edge location is unknown for platform '${os.platform()}'`), null); + } +} + +function getBrowserPath(callback: (error: Error | null, browser: Browser | null) => void) { + switch (browser) { + case "chrome": return getChromePath(afterGetBrowserPath); + case "edge": return getEdgePath(afterGetBrowserPath); + default: return callback(new Error(`Browser location is unknown for '${browser}'`), null); + } + + function afterGetBrowserPath(error: Error | null, browser: Browser | string | null) { + if (error) return callback(error, null); + if (typeof browser === "object") return callback(null, browser); + return fs.stat(browser, (error, stats) => { + if (!error && stats.isFile()) { + return callback(null, createBrowserFromPath(browser)); + } + if (browser === "chrome") return callback(null, createBrowserFromPath("chrome")); + return callback(new Error(`Browser location is unknown for '${browser}'`), null); + }); + } +} + function startClient(server: http.Server) { let browserPath: string; if (browser === "none") { return; } - if (browser === "chrome") { - let defaultChromePath = ""; - switch (os.platform()) { - case "win32": - defaultChromePath = "C:/Program Files (x86)/Google/Chrome/Application/chrome.exe"; - break; - case "darwin": - defaultChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; - break; - case "linux": - defaultChromePath = "/opt/google/chrome/chrome"; - break; - default: - console.log(`default Chrome location is unknown for platform '${os.platform()}'`); - break; - } - if (fs.existsSync(defaultChromePath)) { - browserPath = defaultChromePath; + getBrowserPath((error, browser) => { + if (error) return console.error(error); + console.log(`Using browser: ${browser.description}`); + const queryString = grep ? `?grep=${grep}` : ""; + const args = [`http://localhost:${port}/tests/webTestResults.html${queryString}`]; + if (browser.command.indexOf("%") === -1) { + child_process.spawn(browser.command, args); } else { - browserPath = browser; + const command = browser.command.replace(/%(\d+)/g, (_, offset) => args[+offset - 1]); + child_process.exec(command); } - } - else { - const defaultIEPath = "C:/Program Files/Internet Explorer/iexplore.exe"; - if (fs.existsSync(defaultIEPath)) { - browserPath = defaultIEPath; - } - else { - browserPath = browser; - } - } - - console.log(`Using browser: ${browserPath}`); - - const queryString = grep ? `?grep=${grep}` : ""; - const child = child_process.spawn(browserPath, [`http://localhost:${port}/tests/webTestResults.html${queryString}`], { - stdio: "inherit" }); } @@ -913,42 +966,35 @@ function printHelp() { console.log("Runs an http server on port 8888, looking for tests folder in the current directory\n"); console.log("Syntax: node webTestServer.js [browser] [tests] [--verbose]\n"); console.log("Options:"); - console.log(" The browser to launch. One of 'IE', 'chrome', or 'none' (default 'IE')."); + console.log(" The browser to launch. One of 'edge', 'chrome', or 'none' (default 'edge' on Windows, otherwise `chrome`)."); console.log(" A regular expression to pass to Mocha."); console.log(" --verbose Enables verbose logging."); } function parseCommandLine(args: string[]) { - let offset = 0; - for (const arg of args) { - const argLower = arg.toLowerCase(); - if (argLower === "--help") { - printHelp(); - return false; - } - else if (argLower === "--verbose") { - verbose = true; - } - else { - if (offset === 0) { - browser = arg; - } - else if (offset === 1) { - grep = arg; - } - else { - console.log(`Unrecognized argument: ${arg}\n`); - return false; - } - offset++; - } - } - - if (browser !== "IE" && browser !== "chrome" && browser !== "none") { - console.log(`Unrecognized browser '${browser}', expected 'IE' or 'chrome'.`); + const parsed = minimist(args, { boolean: ["help", "verbose"] }); + if (parsed.help) { + printHelp(); return false; } + if (parsed.verbose) { + verbose = true; + } + + const [parsedBrowser = defaultBrowser, parsedGrep, ...unrecognized] = parsed._; + if (parsedBrowser !== "edge" && parsedBrowser !== "chrome" && parsedBrowser !== "none") { + console.log(`Unrecognized browser '${parsedBrowser}', expected 'edge', 'chrome', or 'none'.`); + return false; + } + + if (unrecognized.length > 0) { + console.log(`Unrecognized argument: ${unrecognized[0]}`); + return false; + } + + browser = parsedBrowser; + grep = parsedGrep; return true; } From 3166278ef9c1ae0330fc5f3ea7a636d1c7465eb4 Mon Sep 17 00:00:00 2001 From: csigs Date: Wed, 9 May 2018 22:10:50 +0000 Subject: [PATCH 08/44] LEGO: check in for master to temporary branch. --- .../diagnosticMessages.generated.json.lcl | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl index 1a9638ca02d..1dc680c5cae 100644 --- a/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl +++ b/src/loc/lcl/ita/diagnosticMessages/diagnosticMessages.generated.json.lcl @@ -1107,6 +1107,15 @@ + + + + + + + + + @@ -2043,6 +2052,15 @@ + + + + + + + + + @@ -2421,6 +2439,15 @@ + + + + + + + + + @@ -3144,6 +3171,15 @@ + + + + + + + + + @@ -3699,6 +3735,15 @@ + + + + + + + + + @@ -4305,6 +4350,9 @@ + + + @@ -5607,6 +5655,9 @@ + + + @@ -5628,6 +5679,24 @@ + + + + + + + + + + + + + + + + + + @@ -6024,6 +6093,24 @@ + + + + + + + + + + + + + + + + + + @@ -6450,6 +6537,15 @@ + + + + + + + + + @@ -6462,6 +6558,15 @@ + + + + + + + + + From da413d6fefe27be6b1ef56d8c202bf5936883383 Mon Sep 17 00:00:00 2001 From: Andy Date: Wed, 9 May 2018 15:18:45 -0700 Subject: [PATCH 09/44] Remove unnecessary filtering of tsx completions (#24004) --- src/harness/fourslash.ts | 2 +- src/services/completions.ts | 10 +++------ .../cases/fourslash/completionsImport_tsx.ts | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 tests/cases/fourslash/completionsImport_tsx.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 5e7dede93ee..a62be540854 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -899,7 +899,7 @@ namespace FourSlash { } else { const found = actualByName.get(exclude.name); - if (found.source === exclude.source) { + if (found && found.source === exclude.source) { this.raiseError(`Did not expect to get a completion named ${exclude.name} with source ${exclude.source}`); } } diff --git a/src/services/completions.ts b/src/services/completions.ts index 4950d1370e1..27869ca572c 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -972,12 +972,8 @@ namespace ts.Completions { } else if (isRightOfOpenTag) { const tagSymbols = Debug.assertEachDefined(typeChecker.getJsxIntrinsicTagNamesAt(location), "getJsxIntrinsicTagNames() should all be defined"); - if (tryGetGlobalSymbols()) { - symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & (SymbolFlags.Value | SymbolFlags.Alias)))); - } - else { - symbols = tagSymbols; - } + tryGetGlobalSymbols(); + symbols = tagSymbols.concat(symbols); completionKind = CompletionKind.MemberLike; } else if (isStartingCloseTag) { @@ -1298,7 +1294,7 @@ namespace ts.Completions { const exportedSymbols = typeChecker.getExportsOfModule(symbol); // If the exported symbols contains type, // symbol can be referenced at locations where type is allowed - return forEach(exportedSymbols, symbolCanBeReferencedAtTypeLocation); + return exportedSymbols.some(symbolCanBeReferencedAtTypeLocation); } } diff --git a/tests/cases/fourslash/completionsImport_tsx.ts b/tests/cases/fourslash/completionsImport_tsx.ts new file mode 100644 index 00000000000..ff9d79a3e3b --- /dev/null +++ b/tests/cases/fourslash/completionsImport_tsx.ts @@ -0,0 +1,21 @@ +/// + +// @noLib: true +// @nolib: true +// @jsx: preserve + +// @Filename: /a.tsx +////export type Bar = 0; +////export default function Foo() {}; + +// @Filename: /b.tsx +////; + +verify.completions({ + marker: "", + includes: { name: "Foo", source: "/a.tsx", hasAction: true }, + excludes: "Bar", + preferences: { + includeCompletionsForModuleExports: true, + }, +}); From 58c7d7c23683ca4307fbb56f9efeb1812789db6d Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 9 May 2018 18:08:58 -0700 Subject: [PATCH 10/44] Fix RWC test case sensitivity (#24012) * Fix RWC test case sensitivity * Fix lint --- src/harness/rwcRunner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index f63a3ac109a..ec620e6611b 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -126,7 +126,7 @@ namespace RWC { compilerResult = Harness.Compiler.compileFiles( inputFiles, otherFiles, - /* harnessOptions */ undefined, + { useCaseSensitiveFileNames: "" + (ioLog.useCaseSensitiveFileNames || false) }, opts.options, // Since each RWC json file specifies its current directory in its json file, we need // to pass this information in explicitly instead of acquiring it from the process. From 20f9493f04810f6e3eb1fcb0898dd6dec99d03ef Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 9 May 2018 19:53:44 -0700 Subject: [PATCH 11/44] Allow all private declarations to be emitted in declaration output (#23351) * Mostly functional WIP * Fix accessors, symbol stringification * Accept/update changed baselines * Move type definition so file build order doesnt matter * Accept post-merge test update * Rename function, add doc --- src/compiler/checker.ts | 75 +- src/compiler/transformers/declarations.ts | 159 +- src/compiler/types.ts | 19 +- src/compiler/utilities.ts | 18 +- .../DeclarationErrorsNoEmitOnError.errors.txt | 10 - .../DeclarationErrorsNoEmitOnError.js | 19 + .../DeclarationErrorsNoEmitOnError.types | 6 +- .../aliasInaccessibleModule.errors.txt | 11 - .../reference/aliasInaccessibleModule.js | 8 + .../aliasInaccessibleModule2.errors.txt | 15 - .../reference/aliasInaccessibleModule2.js | 9 + .../allowJscheckJsTypeParameterNoCrash.types | 6 +- .../controlFlowBinaryOrExpression.types | 12 +- ...otationVisibilityErrorAccessors.errors.txt | 132 -- ...eTypeAnnotationVisibilityErrorAccessors.js | 30 + ...ibilityErrorParameterOfFunction.errors.txt | 59 - ...ationVisibilityErrorParameterOfFunction.js | 19 + ...bilityErrorReturnTypeOfFunction.errors.txt | 71 - ...tionVisibilityErrorReturnTypeOfFunction.js | 19 + ...otationVisibilityErrorTypeAlias.errors.txt | 55 - ...eTypeAnnotationVisibilityErrorTypeAlias.js | 35 + ...peAnnotationVisibilityErrorTypeAlias.types | 6 +- ...ationVisibilityErrorTypeLiteral.errors.txt | 90 -- ...ypeAnnotationVisibilityErrorTypeLiteral.js | 36 + ...ibilityErrorVariableDeclaration.errors.txt | 47 - ...ationVisibilityErrorVariableDeclaration.js | 19 + .../reference/declInput-2.errors.txt | 39 - tests/baselines/reference/declInput-2.js | 28 + ...ionEmitClassPrivateConstructor2.errors.txt | 20 - ...declarationEmitClassPrivateConstructor2.js | 13 + .../declarationEmitDefaultExport7.errors.txt | 9 - .../declarationEmitDefaultExport7.js | 7 + ...onEmitDestructuringPrivacyError.errors.txt | 11 - ...eclarationEmitDestructuringPrivacyError.js | 8 + ...arationEmitExpressionInExtends3.errors.txt | 51 - .../declarationEmitExpressionInExtends3.js | 29 + ...fierPredicatesWithPrivateName01.errors.txt | 13 - ...itIdentifierPredicatesWithPrivateName01.js | 8 + .../declarationEmitInferredTypeAlias9.js | 6 +- .../declarationEmitInferredTypeAlias9.types | 14 +- ...clarationEmitLocalClassDeclarationMixin.js | 1 + ...ThisPredicatesWithPrivateName01.errors.txt | 14 - ...tionEmitThisPredicatesWithPrivateName01.js | 9 + ...ThisPredicatesWithPrivateName02.errors.txt | 5 +- ...tionEmitThisPredicatesWithPrivateName02.js | 12 + ...mitTypeAliasWithTypeParameters5.errors.txt | 15 - ...arationEmitTypeAliasWithTypeParameters5.js | 8 + ...tionEmitTypeAliasWithTypeParameters5.types | 16 +- ...nFunctionTypeNonlocalShouldNotBeAnError.js | 3 +- .../declarationNoDanglingGenerics.js | 1 + tests/baselines/reference/dynamicNames.types | 48 +- .../emitClassExpressionInDeclarationFile.js | 1 + .../exportClassExtendingIntersection.js | 1 + .../getEmitOutputWithEmitterErrors.baseline | 10 +- .../getEmitOutputWithEmitterErrors2.baseline | 11 +- .../indexedAccessTypeConstraints.types | 26 +- .../jsxSpreadFirstUnionNoErrors.types | 24 +- ...eAugmentationImportsAndExports2.errors.txt | 8 +- .../moduleAugmentationImportsAndExports2.js | 21 + ...eAugmentationImportsAndExports3.errors.txt | 8 +- .../moduleAugmentationImportsAndExports3.js | 20 + ...eAugmentationImportsAndExports5.errors.txt | 45 - .../moduleAugmentationImportsAndExports5.js | 63 + ...licitAnyDestructuringInPrivateMethod.types | 6 +- .../noUnusedLocals_selfReference.types | 6 +- .../privacyAccessorDeclFile.errors.txt | 1167 -------------- .../reference/privacyAccessorDeclFile.js | 532 +++++++ .../privacyCheckTypeOfFunction.errors.txt | 11 - .../reference/privacyCheckTypeOfFunction.js | 7 + ...CheckTypeOfInvisibleModuleError.errors.txt | 14 - .../privacyCheckTypeOfInvisibleModuleError.js | 9 + ...eckTypeOfInvisibleModuleNoError.errors.txt | 14 - ...rivacyCheckTypeOfInvisibleModuleNoError.js | 9 + ...ivacyClassExtendsClauseDeclFile.errors.txt | 19 +- .../privacyClassExtendsClauseDeclFile.js | 57 + ...cyClassImplementsClauseDeclFile.errors.txt | 112 -- .../privacyClassImplementsClauseDeclFile.js | 55 + ...rivacyFunctionParameterDeclFile.errors.txt | 866 ---------- .../privacyFunctionParameterDeclFile.js | 572 +++++++ ...ivacyFunctionReturnTypeDeclFile.errors.txt | 1391 ----------------- .../privacyFunctionReturnTypeDeclFile.js | 648 ++++++++ .../reference/privacyGloImport.errors.txt | 161 -- tests/baselines/reference/privacyGloImport.js | 83 + .../privacyGloImportParseErrors.errors.txt | 8 +- .../reference/privacyGloImportParseErrors.js | 108 ++ .../reference/privacyImport.errors.txt | 365 ----- tests/baselines/reference/privacyImport.js | 59 + ...yInterfaceExtendsClauseDeclFile.errors.txt | 112 -- .../privacyInterfaceExtendsClauseDeclFile.js | 55 + ...ternalReferenceImportWithExport.errors.txt | 176 --- ...yLocalInternalReferenceImportWithExport.js | 157 ++ ...nalReferenceImportWithoutExport.errors.txt | 170 -- ...calInternalReferenceImportWithoutExport.js | 149 ++ ...ternalReferenceImportWithExport.errors.txt | 123 -- ...pLevelInternalReferenceImportWithExport.js | 72 + ...nalReferenceImportWithoutExport.errors.txt | 117 -- ...velInternalReferenceImportWithoutExport.js | 68 + ...TypeParameterOfFunctionDeclFile.errors.txt | 549 ------- .../privacyTypeParameterOfFunctionDeclFile.js | 305 ++++ ...cyTypeParametersOfClassDeclFile.errors.txt | 169 -- .../privacyTypeParametersOfClassDeclFile.js | 115 ++ ...peParametersOfInterfaceDeclFile.errors.txt | 253 --- ...rivacyTypeParametersOfInterfaceDeclFile.js | 201 +++ .../reference/privacyVarDeclFile.errors.txt | 515 ------ .../baselines/reference/privacyVarDeclFile.js | 412 +++++ .../reference/recursiveTypeRelations.types | 54 +- .../reference/strictFunctionTypesErrors.types | 282 ++-- .../symbolDeclarationEmit12.errors.txt | 14 +- .../reference/symbolDeclarationEmit12.js | 14 + .../reference/tsxAttributeResolution16.types | 6 +- .../tsxSpreadAttributesResolution6.types | 10 +- .../tsxSpreadAttributesResolution7.types | 14 +- .../reference/tsxUnionTypeComponent2.types | 6 +- ...uniqueSymbolsDeclarationsErrors.errors.txt | 68 - .../uniqueSymbolsDeclarationsErrors.js | 47 + ...unusedLocalsAndParametersTypeAliases.types | 32 +- ...nusedLocalsAndParametersTypeAliases2.types | 2 +- .../fourslash/getDeclarationDiagnostics.ts | 7 +- .../getSemanticDiagnosticForDeclaration.ts | 7 +- .../shims-pp/getSemanticDiagnostics.ts | 7 +- .../fourslash/shims/getSemanticDiagnostics.ts | 7 +- 121 files changed, 4663 insertions(+), 7522 deletions(-) delete mode 100644 tests/baselines/reference/DeclarationErrorsNoEmitOnError.errors.txt create mode 100644 tests/baselines/reference/DeclarationErrorsNoEmitOnError.js delete mode 100644 tests/baselines/reference/aliasInaccessibleModule.errors.txt delete mode 100644 tests/baselines/reference/aliasInaccessibleModule2.errors.txt delete mode 100644 tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt delete mode 100644 tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.errors.txt delete mode 100644 tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.errors.txt delete mode 100644 tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.errors.txt delete mode 100644 tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.errors.txt delete mode 100644 tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.errors.txt delete mode 100644 tests/baselines/reference/declInput-2.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitClassPrivateConstructor2.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitDefaultExport7.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitDestructuringPrivacyError.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitExpressionInExtends3.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.errors.txt delete mode 100644 tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.errors.txt delete mode 100644 tests/baselines/reference/moduleAugmentationImportsAndExports5.errors.txt delete mode 100644 tests/baselines/reference/privacyAccessorDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyCheckTypeOfFunction.errors.txt delete mode 100644 tests/baselines/reference/privacyCheckTypeOfInvisibleModuleError.errors.txt delete mode 100644 tests/baselines/reference/privacyCheckTypeOfInvisibleModuleNoError.errors.txt delete mode 100644 tests/baselines/reference/privacyClassImplementsClauseDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyFunctionParameterDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyFunctionReturnTypeDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyGloImport.errors.txt delete mode 100644 tests/baselines/reference/privacyImport.errors.txt delete mode 100644 tests/baselines/reference/privacyInterfaceExtendsClauseDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyLocalInternalReferenceImportWithExport.errors.txt delete mode 100644 tests/baselines/reference/privacyLocalInternalReferenceImportWithoutExport.errors.txt delete mode 100644 tests/baselines/reference/privacyTopLevelInternalReferenceImportWithExport.errors.txt delete mode 100644 tests/baselines/reference/privacyTopLevelInternalReferenceImportWithoutExport.errors.txt delete mode 100644 tests/baselines/reference/privacyTypeParameterOfFunctionDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyTypeParametersOfClassDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyTypeParametersOfInterfaceDeclFile.errors.txt delete mode 100644 tests/baselines/reference/privacyVarDeclFile.errors.txt delete mode 100644 tests/baselines/reference/uniqueSymbolsDeclarationsErrors.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c6dab75dc80..fa1efdb7bb9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2837,6 +2837,11 @@ namespace ts { isDeclarationVisible(declaration.parent.parent.parent)) { return addVisibleAlias(declaration, declaration.parent.parent); } + else if (isLateVisibilityPaintedStatement(declaration) // unexported top-level statement + && !hasModifier(declaration, ModifierFlags.Export) + && isDeclarationVisible(declaration.parent)) { + return addVisibleAlias(declaration, declaration); + } // Declaration is not visible return false; @@ -3694,7 +3699,17 @@ namespace ts { return typeParameterNodes; } - function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags): TypeQueryNode | TypeReferenceNode | ImportTypeNode { + /** + * Given A[B][C][D], finds A[B] + */ + function getTopmostIndexedAccessType(top: IndexedAccessTypeNode): IndexedAccessTypeNode { + if (isIndexedAccessTypeNode(top.objectType)) { + return getTopmostIndexedAccessType(top.objectType); + } + return top; + } + + function symbolToTypeNode(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags): TypeNode { const chain = lookupSymbolChain(symbol, context, meaning); context.flags |= NodeBuilderFlags.InInitialEntityName; @@ -3704,15 +3719,26 @@ namespace ts { const isTypeOf = meaning === SymbolFlags.Value; if (ambientModuleSymbolRegex.test(rootName)) { // module is root, must use `ImportTypeNode` - const nonRootParts = chain.length > 1 ? createEntityNameFromSymbolChain(chain, chain.length - 1, 1) : undefined; + const nonRootParts = chain.length > 1 ? createAccessFromSymbolChain(chain, chain.length - 1, 1) : undefined; const typeParameterNodes = lookupTypeParameterNodes(chain, 0, context); - return createImportTypeNode(createLiteralTypeNode(createLiteral(rootName.substring(1, rootName.length - 1))), nonRootParts, typeParameterNodes as ReadonlyArray, isTypeOf); + const lit = createLiteralTypeNode(createLiteral(rootName.substring(1, rootName.length - 1))); + if (!nonRootParts || isEntityName(nonRootParts)) { + return createImportTypeNode(lit, nonRootParts as EntityName, typeParameterNodes as ReadonlyArray, isTypeOf); + } + else { + const splitNode = getTopmostIndexedAccessType(nonRootParts); + const qualifier = (splitNode.objectType as TypeReferenceNode).typeName; + return createIndexedAccessTypeNode(createImportTypeNode(lit, qualifier, typeParameterNodes as ReadonlyArray, isTypeOf), splitNode.indexType); + } } - const entityName = createEntityNameFromSymbolChain(chain, chain.length - 1, 0); + const entityName = createAccessFromSymbolChain(chain, chain.length - 1, 0); + if (isIndexedAccessTypeNode(entityName)) { + return entityName; // Indexed accesses can never be `typeof` + } return isTypeOf ? createTypeQueryNode(entityName) : createTypeReferenceNode(entityName, /*typeArguments*/ undefined); - function createEntityNameFromSymbolChain(chain: Symbol[], index: number, stopper: number): EntityName { + function createAccessFromSymbolChain(chain: Symbol[], index: number, stopper: number): EntityName | IndexedAccessTypeNode { const typeParameterNodes = lookupTypeParameterNodes(chain, index, context); const symbol = chain[index]; @@ -3723,10 +3749,30 @@ namespace ts { if (index === 0) { context.flags ^= NodeBuilderFlags.InInitialEntityName; } + + const parent = chain[index - 1]; + if (parent && getMembersOfSymbol(parent) && getMembersOfSymbol(parent).get(symbol.escapedName) === symbol) { + // Should use an indexed access + const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); + if (isIndexedAccessTypeNode(LHS)) { + return createIndexedAccessTypeNode(LHS, createLiteralTypeNode(createLiteral(symbolName))); + } + else { + return createIndexedAccessTypeNode(createTypeReferenceNode(LHS, typeParameterNodes as ReadonlyArray), createLiteralTypeNode(createLiteral(symbolName))); + } + } + const identifier = setEmitFlags(createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); identifier.symbol = symbol; - return index > stopper ? createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1, stopper), identifier) : identifier; + if (index > stopper) { + const LHS = createAccessFromSymbolChain(chain, index - 1, stopper); + if (!isEntityName(LHS)) { + return Debug.fail("Impossible construct - an export of an indexed access cannot be reachable"); + } + return createQualifiedName(LHS, identifier); + } + return identifier; } } @@ -26598,7 +26644,22 @@ namespace ts { const symbol = node && getSymbolOfNode(node); return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late); }, - getJsxFactoryEntity: location => location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity + getJsxFactoryEntity: location => location ? (getJsxNamespace(location), (getSourceFileOfNode(location).localJsxFactory || _jsxFactoryEntity)) : _jsxFactoryEntity, + getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { + accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration); + const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; + const otherAccessor = getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); + const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; + const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; + const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor; + const getAccessor = accessor.kind === SyntaxKind.GetAccessor ? accessor : otherAccessor; + return { + firstAccessor, + secondAccessor, + setAccessor, + getAccessor + }; + } }; function isInHeritageClause(node: PropertyAccessEntityNameExpression) { diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 0a7cf397ddd..203620864cc 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -28,7 +28,7 @@ namespace ts { let enclosingDeclaration: Node; let necessaryTypeRefernces: Map; let lateMarkedStatements: LateVisibilityPaintedStatement[]; - let lateStatementReplacementMap: Map; + let lateStatementReplacementMap: Map>; let suppressNewDiagnosticContexts: boolean; const symbolTracker: SymbolTracker = { @@ -155,13 +155,13 @@ namespace ts { [], [createModifier(SyntaxKind.DeclareKeyword)], createLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)), - createModuleBlock(setTextRange(createNodeArray(filterCandidateImports(statements)), sourceFile.statements)) + createModuleBlock(setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements)) )], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false); return newFile; } needsDeclare = true; const updated = visitNodes(sourceFile.statements, visitDeclarationStatements); - return updateSourceFileNode(sourceFile, filterCandidateImports(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false); + return updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false); } ), mapDefined(node.prepends, prepend => { if (prepend.kind === SyntaxKind.InputFiles) { @@ -196,7 +196,7 @@ namespace ts { const referenceVisitor = mapReferencesIntoArray(references, outputFilePath); refs.forEach(referenceVisitor); const statements = visitNodes(node.statements, visitDeclarationStatements); - let combinedStatements = setTextRange(createNodeArray(filterCandidateImports(statements)), node.statements); + let combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements); const emittedImports = filter(combinedStatements, isAnyImportSyntax); if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) { combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements); @@ -258,7 +258,7 @@ namespace ts { forEach(sourceFile.referencedFiles, f => { const elem = tryResolveScriptReference(host, sourceFile, f); if (elem) { - ret.set("" + getNodeId(elem), elem); + ret.set("" + getOriginalNodeId(elem), elem); } }); return ret; @@ -538,7 +538,7 @@ namespace ts { // Nothing visible } - function filterCandidateImports(statements: NodeArray): NodeArray { + function transformAndReplaceLatePaintedStatements(statements: NodeArray): NodeArray { // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during // error handling which must now be included in the output and themselves checked for errors. // For example: @@ -553,65 +553,50 @@ namespace ts { // In such a scenario, only Q and D are initially visible, but we don't consider imports as private names - instead we say they if they are referenced they must // be recorded. So while checking D's visibility we mark C as visible, then we must check C which in turn marks B, completing the chain of // dependent imports and allowing a valid declaration file output. Today, this dependent alias marking only happens for internal import aliases. - const unconsideredStatements: LateVisibilityPaintedStatement[] = []; while (length(lateMarkedStatements)) { const i = lateMarkedStatements.shift(); - if ((isSourceFile(i.parent) ? i.parent : i.parent.parent) !== enclosingDeclaration) { // Filter to only declarations in the current scope - unconsideredStatements.push(i); - continue; - } if (!isLateVisibilityPaintedStatement(i)) { - return Debug.fail(`Late replaced statement was foudn which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`); - } - switch (i.kind) { - case SyntaxKind.ImportEqualsDeclaration: { - const result = transformImportEqualsDeclaration(i); - lateStatementReplacementMap.set("" + getNodeId(i), result); - break; - } - case SyntaxKind.ImportDeclaration: { - const result = transformImportDeclaration(i); - lateStatementReplacementMap.set("" + getNodeId(i), result); - break; - } - case SyntaxKind.VariableStatement: { - const result = transformVariableStatement(i, /*privateDeclaration*/ true); // Transform the statement (potentially again, possibly revealing more sub-nodes) - lateStatementReplacementMap.set("" + getNodeId(i), result); - break; - } - default: Debug.assertNever(i, "Unhandled late painted statement!"); + return Debug.fail(`Late replaced statement was found which is not handled by the declaration transformer!: ${(ts as any).SyntaxKind ? (ts as any).SyntaxKind[(i as any).kind] : (i as any).kind}`); } + const result = transformTopLevelDeclaration(i, /*privateDeclaration*/ true); + lateStatementReplacementMap.set("" + getOriginalNodeId(i), result); } - // Filtering available imports is the last thing done within a scope, so the possible set becomes those which could not - // be considered in the child scope - lateMarkedStatements = unconsideredStatements; // And lastly, we need to get the final form of all those indetermine import declarations from before and add them to the output list // (and remove them from the set to examine for outter declarations) return visitNodes(statements, visitLateVisibilityMarkedStatements); - } - function visitLateVisibilityMarkedStatements(statement: Statement) { - if (isLateVisibilityPaintedStatement(statement)) { - const key = "" + getNodeId(statement); - if (lateStatementReplacementMap.has(key)) { - const result = lateStatementReplacementMap.get(key); - lateStatementReplacementMap.delete(key); - if (result && isSourceFile(statement.parent) && !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export)) { - // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier - needsScopeFixMarker = true; + function visitLateVisibilityMarkedStatements(statement: Statement) { + if (isLateVisibilityPaintedStatement(statement)) { + const key = "" + getOriginalNodeId(statement); + if (lateStatementReplacementMap.has(key)) { + const result = lateStatementReplacementMap.get(key); + lateStatementReplacementMap.delete(key); + if (result && isSourceFile(statement.parent)) { + if (isArray(result) ? some(result, needsScopeMarker) : needsScopeMarker(result)) { + // Top-level declarations in .d.ts files are always considered exported even without a modifier unless there's an export assignment or specifier + needsScopeFixMarker = true; + } + if (isArray(result) ? some(result, isExternalModuleIndicator) : isExternalModuleIndicator(result)) { + resultHasExternalModuleIndicator = true; + } + } + return result; } - return result; } - else { - return getParseTreeNode(statement) ? undefined : statement; - } - } - else { return statement; } } + function isExternalModuleIndicator(result: LateVisibilityPaintedStatement) { + // Exported top-level member indicates moduleness + return isAnyImportOrReExport(result) || isExportAssignment(result) || hasModifier(result, ModifierFlags.Export); + } + + function needsScopeMarker(result: LateVisibilityPaintedStatement) { + return !isAnyImportOrReExport(result) && !isExportAssignment(result) && !hasModifier(result, ModifierFlags.Export) && !isAmbientModule(result); + } + function visitDeclarationSubtree(input: Node): VisitResult { if (shouldStripInternal(input)) return; if (isDeclaration(input)) { @@ -866,13 +851,22 @@ namespace ts { return [statement, updateExportAssignment(input, input.decorators, input.modifiers, newId)]; } } - case SyntaxKind.ImportEqualsDeclaration: + } + + const result = transformTopLevelDeclaration(input); + // Don't actually transform yet; just leave as original node - will be elided/swapped by late pass + lateStatementReplacementMap.set("" + getOriginalNodeId(input), result); + return input; + } + + function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement, isPrivate?: boolean) { + if (shouldStripInternal(input)) return; + switch (input.kind) { + case SyntaxKind.ImportEqualsDeclaration: { + return transformImportEqualsDeclaration(input); + } case SyntaxKind.ImportDeclaration: { - // Different parts of the import may be marked visible at different times (via visibility checking), so we defer our first look until later - // to reduce the likelihood we need to rewrite it - lateMarkedStatements = lateMarkedStatements || []; - pushIfUnique(lateMarkedStatements, input); - return input; + return transformImportDeclaration(input); } } if (isDeclaration(input) && isDeclarationAndNotVisible(input)) return; @@ -885,21 +879,20 @@ namespace ts { previousEnclosingDeclaration = enclosingDeclaration; enclosingDeclaration = input as Declaration; } - let previousNeedsDeclare: typeof needsDeclare; const canProdiceDiagnostic = canProduceDiagnostics(input); const oldDiag = getSymbolAccessibilityDiagnostic; if (canProdiceDiagnostic) { getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input as DeclarationDiagnosticProducing); } - let oldPossibleImports: typeof lateMarkedStatements; + const previousNeedsDeclare = needsDeclare; switch (input.kind) { case SyntaxKind.TypeAliasDeclaration: // Type aliases get `declare`d if need be (for legacy support), but that's all return cleanup(updateTypeAliasDeclaration( input, /*decorators*/ undefined, - ensureModifiers(input), + ensureModifiers(input, isPrivate), input.name, visitNodes(input.typeParameters, visitDeclarationSubtree, isTypeParameterDeclaration), visitNode(input.type, visitDeclarationSubtree, isTypeNode) @@ -908,7 +901,7 @@ namespace ts { return cleanup(updateInterfaceDeclaration( input, /*decorators*/ undefined, - ensureModifiers(input), + ensureModifiers(input, isPrivate), input.name, ensureTypeParams(input, input.typeParameters), transformHeritageClauses(input.heritageClauses), @@ -920,7 +913,7 @@ namespace ts { return cleanup(updateFunctionDeclaration( input, /*decorators*/ undefined, - ensureModifiers(input), + ensureModifiers(input, isPrivate), /*asteriskToken*/ undefined, input.name, ensureTypeParams(input, input.typeParameters), @@ -930,16 +923,13 @@ namespace ts { )); } case SyntaxKind.ModuleDeclaration: { - previousNeedsDeclare = needsDeclare; needsDeclare = false; - oldPossibleImports = lateMarkedStatements; - lateMarkedStatements = undefined; const inner = input.body; if (inner && inner.kind === SyntaxKind.ModuleBlock) { const statements = visitNodes(inner.statements, visitDeclarationStatements); - const body = updateModuleBlock(inner, filterCandidateImports(statements)); + const body = updateModuleBlock(inner, transformAndReplaceLatePaintedStatements(statements)); needsDeclare = previousNeedsDeclare; - const mods = ensureModifiers(input); + const mods = ensureModifiers(input, isPrivate); return cleanup(updateModuleDeclaration( input, /*decorators*/ undefined, @@ -950,19 +940,24 @@ namespace ts { } else { needsDeclare = previousNeedsDeclare; - const mods = ensureModifiers(input); + const mods = ensureModifiers(input, isPrivate); needsDeclare = false; + visitNode(inner, visitDeclarationStatements); + // eagerly transform nested namespaces (the nesting doesn't need any elision or painting done) + const id = "" + getOriginalNodeId(inner); + const body = lateStatementReplacementMap.get(id); + lateStatementReplacementMap.delete(id); return cleanup(updateModuleDeclaration( input, /*decorators*/ undefined, mods, input.name, - visitNode(inner, visitDeclarationStatements) + body as ModuleBody )); } } case SyntaxKind.ClassDeclaration: { - const modifiers = createNodeArray(ensureModifiers(input)); + const modifiers = createNodeArray(ensureModifiers(input, isPrivate)); const typeParameters = ensureTypeParams(input, input.typeParameters); const ctor = getFirstConstructorWithBody(input); let parameterProperties: PropertyDeclaration[]; @@ -1055,12 +1050,10 @@ namespace ts { } } case SyntaxKind.VariableStatement: { - const result = transformVariableStatement(input); - lateStatementReplacementMap.set("" + getNodeId(input), result); // Don't actually elide yet; just leave as original node - will be elided/swapped by late pass - return cleanup(input); + return cleanup(transformVariableStatement(input, isPrivate)); } case SyntaxKind.EnumDeclaration: { - return cleanup(updateEnumDeclaration(input, /*decorators*/ undefined, createNodeArray(ensureModifiers(input)), input.name, createNodeArray(mapDefined(input.members, m => { + return cleanup(updateEnumDeclaration(input, /*decorators*/ undefined, createNodeArray(ensureModifiers(input, isPrivate)), input.name, createNodeArray(mapDefined(input.members, m => { if (shouldStripInternal(m)) return; // Rewrite enum values to their constants, if available const constValue = resolver.getConstantValue(m); @@ -1068,31 +1061,23 @@ namespace ts { })))); } } - // Anything left unhandled is an error, so this should be unreachable return Debug.assertNever(input, `Unhandled top-level node in declaration emit: ${(ts as any).SyntaxKind[(input as any).kind]}`); - function cleanup(returnValue: T | undefined): T { + function cleanup(node: T | undefined): T { if (isEnclosingDeclaration(input)) { enclosingDeclaration = previousEnclosingDeclaration; } - if (input.kind === SyntaxKind.ModuleDeclaration) { - needsDeclare = previousNeedsDeclare; - lateMarkedStatements = concatenate(oldPossibleImports, lateMarkedStatements); - } if (canProdiceDiagnostic) { getSymbolAccessibilityDiagnostic = oldDiag; } - if (returnValue && (!isLateVisibilityPaintedStatement(input) || lateStatementReplacementMap.get("" + getNodeId(input)))) { - if (!resultHasExternalModuleIndicator && hasModifier(input, ModifierFlags.Export) && isSourceFile(input.parent)) { - // Exported top-level member indicates moduleness - resultHasExternalModuleIndicator = true; - } + if (input.kind === SyntaxKind.ModuleDeclaration) { + needsDeclare = previousNeedsDeclare; } - if (returnValue === input) { - return returnValue; + if (node as Node === input) { + return node; } - return returnValue && setOriginalNode(preserveJsDoc(returnValue, input), input); + return node && setOriginalNode(preserveJsDoc(node, input), input); } } @@ -1175,7 +1160,7 @@ namespace ts { } function ensureAccessor(node: AccessorDeclaration): PropertyDeclaration | undefined { - const accessors = getAllAccessorDeclarations((node.parent as ClassDeclaration).members, node); + const accessors = resolver.getAllAccessorDeclarations(node); if (node.kind !== accessors.firstAccessor.kind) { return; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1ac84792152..f8986ec40c2 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3263,7 +3263,15 @@ namespace ts { export type RequireOrImportCall = CallExpression & { arguments: [StringLiteralLike] }; /* @internal */ - export type LateVisibilityPaintedStatement = AnyImportSyntax | VariableStatement; + export type LateVisibilityPaintedStatement = + | AnyImportSyntax + | VariableStatement + | ClassDeclaration + | FunctionDeclaration + | ModuleDeclaration + | TypeAliasDeclaration + | InterfaceDeclaration + | EnumDeclaration; /* @internal */ export interface SymbolVisibilityResult { @@ -3278,6 +3286,14 @@ namespace ts { errorModuleName?: string; // If the symbol is not visible from module, module's name } + /* @internal */ + export interface AllAccessorDeclarations { + firstAccessor: AccessorDeclaration; + secondAccessor: AccessorDeclaration; + getAccessor: AccessorDeclaration; + setAccessor: AccessorDeclaration; + } + /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator metadata */ /* @internal */ export enum TypeReferenceSerializationKind { @@ -3334,6 +3350,7 @@ namespace ts { getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[]; isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean; getJsxFactoryEntity(location?: Node): EntityName; + getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations; } export const enum SymbolFlags { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7afc862bba4..c75022fd5c0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -542,6 +542,12 @@ namespace ts { case SyntaxKind.ImportDeclaration: case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.VariableStatement: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.EnumDeclaration: return true; default: return false; @@ -3008,13 +3014,6 @@ namespace ts { return id.originalKeywordKind === SyntaxKind.ThisKeyword; } - export interface AllAccessorDeclarations { - firstAccessor: AccessorDeclaration; - secondAccessor: AccessorDeclaration; - getAccessor: AccessorDeclaration; - setAccessor: AccessorDeclaration; - } - export function getAllAccessorDeclarations(declarations: NodeArray, accessor: AccessorDeclaration): AllAccessorDeclarations { let firstAccessor: AccessorDeclaration; let secondAccessor: AccessorDeclaration; @@ -4890,6 +4889,11 @@ namespace ts { return node.kind === SyntaxKind.IndexSignature; } + /* @internal */ + export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration { + return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor; + } + // Type export function isTypePredicateNode(node: Node): node is TypePredicateNode { diff --git a/tests/baselines/reference/DeclarationErrorsNoEmitOnError.errors.txt b/tests/baselines/reference/DeclarationErrorsNoEmitOnError.errors.txt deleted file mode 100644 index 0a8f03a504a..00000000000 --- a/tests/baselines/reference/DeclarationErrorsNoEmitOnError.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -tests/cases/compiler/DeclarationErrorsNoEmitOnError.ts(3,8): error TS4033: Property 'f' of exported interface has or is using private name 'T'. - - -==== tests/cases/compiler/DeclarationErrorsNoEmitOnError.ts (1 errors) ==== - type T = { x : number } - export interface I { - f: T; - ~ -!!! error TS4033: Property 'f' of exported interface has or is using private name 'T'. - } \ No newline at end of file diff --git a/tests/baselines/reference/DeclarationErrorsNoEmitOnError.js b/tests/baselines/reference/DeclarationErrorsNoEmitOnError.js new file mode 100644 index 00000000000..73c312a018b --- /dev/null +++ b/tests/baselines/reference/DeclarationErrorsNoEmitOnError.js @@ -0,0 +1,19 @@ +//// [DeclarationErrorsNoEmitOnError.ts] +type T = { x : number } +export interface I { + f: T; +} + +//// [DeclarationErrorsNoEmitOnError.js] +"use strict"; +exports.__esModule = true; + + +//// [DeclarationErrorsNoEmitOnError.d.ts] +declare type T = { + x: number; +}; +export interface I { + f: T; +} +export {}; diff --git a/tests/baselines/reference/DeclarationErrorsNoEmitOnError.types b/tests/baselines/reference/DeclarationErrorsNoEmitOnError.types index 08a65d9c146..d2598dfe748 100644 --- a/tests/baselines/reference/DeclarationErrorsNoEmitOnError.types +++ b/tests/baselines/reference/DeclarationErrorsNoEmitOnError.types @@ -1,12 +1,12 @@ === tests/cases/compiler/DeclarationErrorsNoEmitOnError.ts === type T = { x : number } ->T : { x: number; } +>T : T >x : number export interface I { >I : I f: T; ->f : { x: number; } ->T : { x: number; } +>f : T +>T : T } diff --git a/tests/baselines/reference/aliasInaccessibleModule.errors.txt b/tests/baselines/reference/aliasInaccessibleModule.errors.txt deleted file mode 100644 index 3a9c64e50ab..00000000000 --- a/tests/baselines/reference/aliasInaccessibleModule.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/aliasInaccessibleModule.ts(4,23): error TS4000: Import declaration 'X' is using private name 'N'. - - -==== tests/cases/compiler/aliasInaccessibleModule.ts (1 errors) ==== - module M { - module N { - } - export import X = N; - ~ -!!! error TS4000: Import declaration 'X' is using private name 'N'. - } \ No newline at end of file diff --git a/tests/baselines/reference/aliasInaccessibleModule.js b/tests/baselines/reference/aliasInaccessibleModule.js index a0ecf3361fc..66a59a9f0ee 100644 --- a/tests/baselines/reference/aliasInaccessibleModule.js +++ b/tests/baselines/reference/aliasInaccessibleModule.js @@ -9,3 +9,11 @@ module M { var M; (function (M) { })(M || (M = {})); + + +//// [aliasInaccessibleModule.d.ts] +declare module M { + module N { + } + export import X = N; +} diff --git a/tests/baselines/reference/aliasInaccessibleModule2.errors.txt b/tests/baselines/reference/aliasInaccessibleModule2.errors.txt deleted file mode 100644 index 03a37147aba..00000000000 --- a/tests/baselines/reference/aliasInaccessibleModule2.errors.txt +++ /dev/null @@ -1,15 +0,0 @@ -tests/cases/compiler/aliasInaccessibleModule2.ts(7,16): error TS4000: Import declaration 'R' is using private name 'N'. - - -==== tests/cases/compiler/aliasInaccessibleModule2.ts (1 errors) ==== - module M { - module N { - class C { - } - - } - import R = N; - ~ -!!! error TS4000: Import declaration 'R' is using private name 'N'. - export import X = R; - } \ No newline at end of file diff --git a/tests/baselines/reference/aliasInaccessibleModule2.js b/tests/baselines/reference/aliasInaccessibleModule2.js index be208c07ca2..324581ce622 100644 --- a/tests/baselines/reference/aliasInaccessibleModule2.js +++ b/tests/baselines/reference/aliasInaccessibleModule2.js @@ -23,3 +23,12 @@ var M; var R = N; M.X = R; })(M || (M = {})); + + +//// [aliasInaccessibleModule2.d.ts] +declare module M { + module N { + } + import R = N; + export import X = R; +} diff --git a/tests/baselines/reference/allowJscheckJsTypeParameterNoCrash.types b/tests/baselines/reference/allowJscheckJsTypeParameterNoCrash.types index 396cdd4445e..e1b331019bf 100644 --- a/tests/baselines/reference/allowJscheckJsTypeParameterNoCrash.types +++ b/tests/baselines/reference/allowJscheckJsTypeParameterNoCrash.types @@ -4,12 +4,12 @@ interface ComponentOptions { >V : V watch: Record>; ->watch : Record void> +>watch : Record> >Record : Record ->WatchHandler : (val: T) => void +>WatchHandler : WatchHandler } type WatchHandler = (val: T) => void; ->WatchHandler : (val: T) => void +>WatchHandler : WatchHandler >T : T >val : T >T : T diff --git a/tests/baselines/reference/controlFlowBinaryOrExpression.types b/tests/baselines/reference/controlFlowBinaryOrExpression.types index e843844ebf1..2cdf6b6bc19 100644 --- a/tests/baselines/reference/controlFlowBinaryOrExpression.types +++ b/tests/baselines/reference/controlFlowBinaryOrExpression.types @@ -62,21 +62,21 @@ declare function isHTMLCollection(sourceObj: any): sourceObj is HTMLCollection; >HTMLCollection : HTMLCollection type EventTargetLike = {a: string} | HTMLCollection | NodeList; ->EventTargetLike : NodeList | HTMLCollection | { a: string; } +>EventTargetLike : EventTargetLike >a : string >HTMLCollection : HTMLCollection >NodeList : NodeList var sourceObj: EventTargetLike = undefined; ->sourceObj : NodeList | HTMLCollection | { a: string; } ->EventTargetLike : NodeList | HTMLCollection | { a: string; } +>sourceObj : EventTargetLike +>EventTargetLike : EventTargetLike >undefined : any >undefined : undefined if (isNodeList(sourceObj)) { >isNodeList(sourceObj) : boolean >isNodeList : (sourceObj: any) => sourceObj is NodeList ->sourceObj : NodeList | HTMLCollection | { a: string; } +>sourceObj : EventTargetLike sourceObj.length; >sourceObj.length : number @@ -87,7 +87,7 @@ if (isNodeList(sourceObj)) { if (isHTMLCollection(sourceObj)) { >isHTMLCollection(sourceObj) : boolean >isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection ->sourceObj : NodeList | HTMLCollection | { a: string; } +>sourceObj : EventTargetLike sourceObj.length; >sourceObj.length : number @@ -99,7 +99,7 @@ if (isNodeList(sourceObj) || isHTMLCollection(sourceObj)) { >isNodeList(sourceObj) || isHTMLCollection(sourceObj) : boolean >isNodeList(sourceObj) : boolean >isNodeList : (sourceObj: any) => sourceObj is NodeList ->sourceObj : NodeList | HTMLCollection | { a: string; } +>sourceObj : EventTargetLike >isHTMLCollection(sourceObj) : boolean >isHTMLCollection : (sourceObj: any) => sourceObj is HTMLCollection >sourceObj : { a: string; } diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt deleted file mode 100644 index 4ea18c15901..00000000000 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.errors.txt +++ /dev/null @@ -1,132 +0,0 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(15,21): error TS4043: Return type of public getter 'foo1' from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(20,13): error TS4043: Return type of public getter 'foo2' from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(25,25): error TS4037: Parameter type of public setter 'foo3' from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(32,25): error TS4037: Parameter type of public setter 'foo4' from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(36,21): error TS4043: Return type of public getter 'foo5' from exported class has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(71,23): error TS4043: Return type of public getter 'foo111' from exported class has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(76,13): error TS4042: Return type of public getter 'foo112' from exported class has or is using name 'm2.public2' from private module 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(81,27): error TS4037: Parameter type of public setter 'foo113' from exported class has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(88,27): error TS4037: Parameter type of public setter 'foo114' from exported class has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts(92,23): error TS4043: Return type of public getter 'foo115' from exported class has or is using private name 'm2'. - - -==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorAccessors.ts (10 errors) ==== - module m { - class private1 { - } - - export class public1 { - } - - module m2 { - export class public2 { - } - } - - export class c { - // getter with annotation - get foo1(): private1 { - ~~~~~~~~ -!!! error TS4043: Return type of public getter 'foo1' from exported class has or is using private name 'private1'. - return; - } - - // getter without annotation - get foo2() { - ~~~~ -!!! error TS4043: Return type of public getter 'foo2' from exported class has or is using private name 'private1'. - return new private1(); - } - - // setter with annotation - set foo3(param: private1) { - ~~~~~~~~ -!!! error TS4037: Parameter type of public setter 'foo3' from exported class has or is using private name 'private1'. - } - - // Both - getter without annotation, setter with annotation - get foo4() { - return new private1(); - } - set foo4(param: private1) { - ~~~~~~~~ -!!! error TS4037: Parameter type of public setter 'foo4' from exported class has or is using private name 'private1'. - } - - // Both - with annotation - get foo5(): private1 { - ~~~~~~~~ -!!! error TS4043: Return type of public getter 'foo5' from exported class has or is using private name 'private1'. - return; - } - set foo5(param: private1) { - } - - // getter with annotation - get foo11(): public1 { - return; - } - - // getter without annotation - get foo12() { - return new public1(); - } - - // setter with annotation - set foo13(param: public1) { - } - - // Both - getter without annotation, setter with annotation - get foo14() { - return new public1(); - } - set foo14(param: public1) { - } - - // Both - with annotation - get foo15(): public1 { - return; - } - set foo15(param: public1) { - } - - // getter with annotation - get foo111(): m2.public2 { - ~~ -!!! error TS4043: Return type of public getter 'foo111' from exported class has or is using private name 'm2'. - return; - } - - // getter without annotation - get foo112() { - ~~~~~~ -!!! error TS4042: Return type of public getter 'foo112' from exported class has or is using name 'm2.public2' from private module 'm2'. - return new m2.public2(); - } - - // setter with annotation - set foo113(param: m2.public2) { - ~~ -!!! error TS4037: Parameter type of public setter 'foo113' from exported class has or is using private name 'm2'. - } - - // Both - getter without annotation, setter with annotation - get foo114() { - return new m2.public2(); - } - set foo114(param: m2.public2) { - ~~ -!!! error TS4037: Parameter type of public setter 'foo114' from exported class has or is using private name 'm2'. - } - - // Both - with annotation - get foo115(): m2.public2 { - ~~ -!!! error TS4043: Return type of public getter 'foo115' from exported class has or is using private name 'm2'. - return; - } - set foo115(param: m2.public2) { - } - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js index c02807207ca..20d784489d9 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorAccessors.js @@ -258,3 +258,33 @@ var m; }()); m.c = c; })(m || (m = {})); + + +//// [declFileTypeAnnotationVisibilityErrorAccessors.d.ts] +declare module m { + class private1 { + } + class public1 { + } + module m2 { + class public2 { + } + } + class c { + readonly foo1: private1; + readonly foo2: private1; + foo3: private1; + foo4: private1; + foo5: private1; + readonly foo11: public1; + readonly foo12: public1; + foo13: public1; + foo14: public1; + foo15: public1; + readonly foo111: m2.public2; + readonly foo112: m2.public2; + foo113: m2.public2; + foo114: m2.public2; + foo115: m2.public2; + } +} diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.errors.txt deleted file mode 100644 index 339ae67eea4..00000000000 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.errors.txt +++ /dev/null @@ -1,59 +0,0 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorParameterOfFunction.ts(14,34): error TS4078: Parameter 'param' of exported function has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorParameterOfFunction.ts(16,26): error TS4078: Parameter 'param' of exported function has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorParameterOfFunction.ts(39,35): error TS4078: Parameter 'param' of exported function has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorParameterOfFunction.ts(41,28): error TS4077: Parameter 'param' of exported function has or is using name 'm2.public2' from private module 'm2'. - - -==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorParameterOfFunction.ts (4 errors) ==== - module m { - class private1 { - } - - export class public1 { - } - - // Directly using names from this module - function foo1(param: private1) { - } - function foo2(param = new private1()) { - } - - export function foo3(param : private1) { - ~~~~~~~~ -!!! error TS4078: Parameter 'param' of exported function has or is using private name 'private1'. - } - export function foo4(param = new private1()) { - ~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4078: Parameter 'param' of exported function has or is using private name 'private1'. - } - - function foo11(param: public1) { - } - function foo12(param = new public1()) { - } - - export function foo13(param: public1) { - } - export function foo14(param = new public1()) { - } - - module m2 { - export class public2 { - } - } - - function foo111(param: m2.public2) { - } - function foo112(param = new m2.public2()) { - } - - export function foo113(param: m2.public2) { - ~~ -!!! error TS4078: Parameter 'param' of exported function has or is using private name 'm2'. - } - export function foo114(param = new m2.public2()) { - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4077: Parameter 'param' of exported function has or is using name 'm2.public2' from private module 'm2'. - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.js index 1c4a27cee61..4e1edd7fe39 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorParameterOfFunction.js @@ -105,3 +105,22 @@ var m; } m.foo114 = foo114; })(m || (m = {})); + + +//// [declFileTypeAnnotationVisibilityErrorParameterOfFunction.d.ts] +declare module m { + class private1 { + } + class public1 { + } + function foo3(param: private1): void; + function foo4(param?: private1): void; + function foo13(param: public1): void; + function foo14(param?: public1): void; + module m2 { + class public2 { + } + } + function foo113(param: m2.public2): void; + function foo114(param?: m2.public2): void; +} diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.errors.txt deleted file mode 100644 index 492e6615efa..00000000000 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.errors.txt +++ /dev/null @@ -1,71 +0,0 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.ts(16,29): error TS4060: Return type of exported function has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.ts(19,21): error TS4060: Return type of exported function has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.ts(49,31): error TS4060: Return type of exported function has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.ts(52,21): error TS4059: Return type of exported function has or is using name 'm2.public2' from private module 'm2'. - - -==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.ts (4 errors) ==== - module m { - class private1 { - } - - export class public1 { - } - - // Directly using names from this module - function foo1(): private1 { - return; - } - function foo2() { - return new private1(); - } - - export function foo3(): private1 { - ~~~~~~~~ -!!! error TS4060: Return type of exported function has or is using private name 'private1'. - return; - } - export function foo4() { - ~~~~ -!!! error TS4060: Return type of exported function has or is using private name 'private1'. - return new private1(); - } - - function foo11(): public1 { - return; - } - function foo12() { - return new public1(); - } - - export function foo13(): public1 { - return; - } - export function foo14() { - return new public1(); - } - - module m2 { - export class public2 { - } - } - - function foo111(): m2.public2 { - return; - } - function foo112() { - return new m2.public2(); - } - - export function foo113(): m2.public2 { - ~~ -!!! error TS4060: Return type of exported function has or is using private name 'm2'. - return; - } - export function foo114() { - ~~~~~~ -!!! error TS4059: Return type of exported function has or is using name 'm2.public2' from private module 'm2'. - return new m2.public2(); - } - } - \ No newline at end of file diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.js index a0e43b6521d..8a2437a2ac4 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.js @@ -123,3 +123,22 @@ var m; } m.foo114 = foo114; })(m || (m = {})); + + +//// [declFileTypeAnnotationVisibilityErrorReturnTypeOfFunction.d.ts] +declare module m { + class private1 { + } + class public1 { + } + function foo3(): private1; + function foo4(): private1; + function foo13(): public1; + function foo14(): public1; + module m2 { + class public2 { + } + } + function foo113(): m2.public2; + function foo114(): m2.public2; +} diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.errors.txt deleted file mode 100644 index 919fd5cd657..00000000000 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.errors.txt +++ /dev/null @@ -1,55 +0,0 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeAlias.ts(9,23): error TS4025: Exported variable 'p' has or is using private name 'W'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeAlias.ts(32,22): error TS4081: Exported type alias 't2' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeAlias.ts(35,23): error TS4081: Exported type alias 't12' has or is using private name 'public1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeAlias.ts(38,24): error TS4081: Exported type alias 't112' has or is using private name 'm3'. - - -==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeAlias.ts (4 errors) ==== - interface Window { - someMethod(); - } - - module M { - type W = Window | string; - export module N { - export class Window { } - export var p: W; // Should report error that W is private - ~ -!!! error TS4025: Exported variable 'p' has or is using private name 'W'. - } - } - - module M1 { - export type W = Window | string; - export module N { - export class Window { } - export var p: W; // No error - } - } - - module M2 { - class private1 { - } - class public1 { - } - module m3 { - export class public1 { - } - } - - type t1 = private1; - export type t2 = private1; // error - ~~~~~~~~ -!!! error TS4081: Exported type alias 't2' has or is using private name 'private1'. - - type t11 = public1; - export type t12 = public1; - ~~~~~~~ -!!! error TS4081: Exported type alias 't12' has or is using private name 'public1'. - - type t111 = m3.public1; - export type t112 = m3.public1; // error - ~~ -!!! error TS4081: Exported type alias 't112' has or is using private name 'm3'. - } - \ No newline at end of file diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.js index 2d1e3d1880e..fd39a6e20d9 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.js @@ -87,3 +87,38 @@ var M2; m3.public1 = public1; })(m3 || (m3 = {})); })(M2 || (M2 = {})); + + +//// [declFileTypeAnnotationVisibilityErrorTypeAlias.d.ts] +interface Window { + someMethod(): any; +} +declare module M { + type W = Window | string; + module N { + class Window { + } + var p: W; + } +} +declare module M1 { + type W = Window | string; + module N { + class Window { + } + var p: W; + } +} +declare module M2 { + class private1 { + } + class public1 { + } + module m3 { + class public1 { + } + } + type t2 = private1; + type t12 = public1; + type t112 = m3.public1; +} diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.types b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.types index 5d467f07df4..24911343bea 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.types +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeAlias.types @@ -10,7 +10,7 @@ module M { >M : typeof M type W = Window | string; ->W : string | Window +>W : W >Window : Window export module N { @@ -20,8 +20,8 @@ module M { >Window : Window export var p: W; // Should report error that W is private ->p : string | Window ->W : string | Window +>p : W +>W : W } } diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.errors.txt deleted file mode 100644 index a8d8023e830..00000000000 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.errors.txt +++ /dev/null @@ -1,90 +0,0 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(10,12): error TS4025: Exported variable 'x' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(11,12): error TS4025: Exported variable 'x' has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(12,13): error TS4025: Exported variable 'x' has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(13,19): error TS4025: Exported variable 'x' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(14,22): error TS4025: Exported variable 'x' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(15,22): error TS4025: Exported variable 'x' has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(17,16): error TS4024: Exported variable 'x2' has or is using name 'm2.public1' from private module 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(17,16): error TS4025: Exported variable 'x2' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(24,16): error TS4024: Exported variable 'x3' has or is using name 'm2.public1' from private module 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(24,16): error TS4025: Exported variable 'x3' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(27,23): error TS4025: Exported variable 'y' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(27,36): error TS4025: Exported variable 'y' has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(28,16): error TS4024: Exported variable 'y2' has or is using name 'm2.public1' from private module 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(28,16): error TS4025: Exported variable 'y2' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(31,27): error TS4025: Exported variable 'z' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(31,40): error TS4025: Exported variable 'z' has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(32,16): error TS4024: Exported variable 'z2' has or is using name 'm2.public1' from private module 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts(32,16): error TS4025: Exported variable 'z2' has or is using private name 'private1'. - - -==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorTypeLiteral.ts (18 errors) ==== - module m { - class private1 { - } - module m2 { - export class public1 { - } - } - - export var x: { - x: private1; - ~~~~~~~~ -!!! error TS4025: Exported variable 'x' has or is using private name 'private1'. - y: m2.public1; - ~~ -!!! error TS4025: Exported variable 'x' has or is using private name 'm2'. - (): m2.public1[]; - ~~ -!!! error TS4025: Exported variable 'x' has or is using private name 'm2'. - method(): private1; - ~~~~~~~~ -!!! error TS4025: Exported variable 'x' has or is using private name 'private1'. - [n: number]: private1; - ~~~~~~~~ -!!! error TS4025: Exported variable 'x' has or is using private name 'private1'. - [s: string]: m2.public1; - ~~ -!!! error TS4025: Exported variable 'x' has or is using private name 'm2'. - }; - export var x2 = { - ~~ -!!! error TS4024: Exported variable 'x2' has or is using name 'm2.public1' from private module 'm2'. - ~~ -!!! error TS4025: Exported variable 'x2' has or is using private name 'private1'. - x: new private1(), - y: new m2.public1(), - method() { - return new private1(); - } - }; - export var x3 = x; - ~~ -!!! error TS4024: Exported variable 'x3' has or is using name 'm2.public1' from private module 'm2'. - ~~ -!!! error TS4025: Exported variable 'x3' has or is using private name 'private1'. - - // Function type - export var y: (a: private1) => m2.public1; - ~~~~~~~~ -!!! error TS4025: Exported variable 'y' has or is using private name 'private1'. - ~~ -!!! error TS4025: Exported variable 'y' has or is using private name 'm2'. - export var y2 = y; - ~~ -!!! error TS4024: Exported variable 'y2' has or is using name 'm2.public1' from private module 'm2'. - ~~ -!!! error TS4025: Exported variable 'y2' has or is using private name 'private1'. - - // constructor type - export var z: new (a: private1) => m2.public1; - ~~~~~~~~ -!!! error TS4025: Exported variable 'z' has or is using private name 'private1'. - ~~ -!!! error TS4025: Exported variable 'z' has or is using private name 'm2'. - export var z2 = z; - ~~ -!!! error TS4024: Exported variable 'z2' has or is using name 'm2.public1' from private module 'm2'. - ~~ -!!! error TS4025: Exported variable 'z2' has or is using private name 'private1'. - } \ No newline at end of file diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.js index 687ab02fdb6..ecb3e035e2a 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorTypeLiteral.js @@ -61,3 +61,39 @@ var m; m.y2 = m.y; m.z2 = m.z; })(m || (m = {})); + + +//// [declFileTypeAnnotationVisibilityErrorTypeLiteral.d.ts] +declare module m { + class private1 { + } + module m2 { + class public1 { + } + } + var x: { + x: private1; + y: m2.public1; + (): m2.public1[]; + method(): private1; + [n: number]: private1; + [s: string]: m2.public1; + }; + var x2: { + x: private1; + y: m2.public1; + method(): private1; + }; + var x3: { + (): m2.public1[]; + [s: string]: m2.public1; + [n: number]: private1; + x: private1; + y: m2.public1; + method(): private1; + }; + var y: (a: private1) => m2.public1; + var y2: (a: private1) => m2.public1; + var z: new (a: private1) => m2.public1; + var z2: new (a: private1) => m2.public1; +} diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.errors.txt b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.errors.txt deleted file mode 100644 index 6a9e5961831..00000000000 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.errors.txt +++ /dev/null @@ -1,47 +0,0 @@ -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorVariableDeclaration.ts(12,19): error TS4025: Exported variable 'k' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorVariableDeclaration.ts(13,16): error TS4025: Exported variable 'l' has or is using private name 'private1'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorVariableDeclaration.ts(29,20): error TS4025: Exported variable 'k3' has or is using private name 'm2'. -tests/cases/compiler/declFileTypeAnnotationVisibilityErrorVariableDeclaration.ts(30,16): error TS4024: Exported variable 'l3' has or is using name 'm2.public2' from private module 'm2'. - - -==== tests/cases/compiler/declFileTypeAnnotationVisibilityErrorVariableDeclaration.ts (4 errors) ==== - module m { - class private1 { - } - - export class public1 { - } - - // Directly using names from this module - var x: private1; - var y = new private1(); - - export var k: private1; - ~~~~~~~~ -!!! error TS4025: Exported variable 'k' has or is using private name 'private1'. - export var l = new private1(); - ~ -!!! error TS4025: Exported variable 'l' has or is using private name 'private1'. - - var x2: public1; - var y2 = new public1(); - - export var k2: public1; - export var l2 = new public1(); - - module m2 { - export class public2 { - } - } - - var x3: m2.public2; - var y3 = new m2.public2(); - - export var k3: m2.public2; - ~~ -!!! error TS4025: Exported variable 'k3' has or is using private name 'm2'. - export var l3 = new m2.public2(); - ~~ -!!! error TS4024: Exported variable 'l3' has or is using name 'm2.public2' from private module 'm2'. - } - \ No newline at end of file diff --git a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.js b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.js index 56f959a1356..6bdcedae7d7 100644 --- a/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.js +++ b/tests/baselines/reference/declFileTypeAnnotationVisibilityErrorVariableDeclaration.js @@ -66,3 +66,22 @@ var m; var y3 = new m2.public2(); m.l3 = new m2.public2(); })(m || (m = {})); + + +//// [declFileTypeAnnotationVisibilityErrorVariableDeclaration.d.ts] +declare module m { + class private1 { + } + class public1 { + } + var k: private1; + var l: private1; + var k2: public1; + var l2: public1; + module m2 { + class public2 { + } + } + var k3: m2.public2; + var l3: m2.public2; +} diff --git a/tests/baselines/reference/declInput-2.errors.txt b/tests/baselines/reference/declInput-2.errors.txt deleted file mode 100644 index f151f3e7122..00000000000 --- a/tests/baselines/reference/declInput-2.errors.txt +++ /dev/null @@ -1,39 +0,0 @@ -tests/cases/compiler/declInput-2.ts(10,21): error TS4031: Public property 'm22' of exported class has or is using private name 'C'. -tests/cases/compiler/declInput-2.ts(13,21): error TS4031: Public property 'm25' of exported class has or is using private name 'I2'. -tests/cases/compiler/declInput-2.ts(16,24): error TS4055: Return type of public method from exported class has or is using private name 'I2'. -tests/cases/compiler/declInput-2.ts(18,23): error TS4073: Parameter 'i' of public method from exported class has or is using private name 'I2'. -tests/cases/compiler/declInput-2.ts(19,21): error TS4055: Return type of public method from exported class has or is using private name 'C'. - - -==== tests/cases/compiler/declInput-2.ts (5 errors) ==== - module M { - class C { } - export class E {} - export interface I1 {} - interface I2 {} - export class D { - private c: C; // don't generate - public m1: number; - public m2: string; - public m22: C; // don't generate - ~ -!!! error TS4031: Public property 'm22' of exported class has or is using private name 'C'. - public m23: E; - public m24: I1; - public m25: I2; // don't generate - ~~ -!!! error TS4031: Public property 'm25' of exported class has or is using private name 'I2'. - public m232(): E { return null;} - public m242(): I1 { return null; } - public m252(): I2 { return null; } // don't generate - ~~ -!!! error TS4055: Return type of public method from exported class has or is using private name 'I2'. - public m26(i:I1) {} - public m262(i:I2) {} - ~~ -!!! error TS4073: Parameter 'i' of public method from exported class has or is using private name 'I2'. - public m3():C { return new C(); } - ~ -!!! error TS4055: Return type of public method from exported class has or is using private name 'C'. - } - } \ No newline at end of file diff --git a/tests/baselines/reference/declInput-2.js b/tests/baselines/reference/declInput-2.js index 02dc3cd2819..f1f23b7f22e 100644 --- a/tests/baselines/reference/declInput-2.js +++ b/tests/baselines/reference/declInput-2.js @@ -48,3 +48,31 @@ var M; }()); M.D = D; })(M || (M = {})); + + +//// [declInput-2.d.ts] +declare module M { + class C { + } + class E { + } + interface I1 { + } + interface I2 { + } + class D { + private c; + m1: number; + m2: string; + m22: C; + m23: E; + m24: I1; + m25: I2; + m232(): E; + m242(): I1; + m252(): I2; + m26(i: I1): void; + m262(i: I2): void; + m3(): C; + } +} diff --git a/tests/baselines/reference/declarationEmitClassPrivateConstructor2.errors.txt b/tests/baselines/reference/declarationEmitClassPrivateConstructor2.errors.txt deleted file mode 100644 index a31454a4760..00000000000 --- a/tests/baselines/reference/declarationEmitClassPrivateConstructor2.errors.txt +++ /dev/null @@ -1,20 +0,0 @@ -tests/cases/compiler/declarationEmitClassPrivateConstructor2.ts(5,38): error TS4031: Public property 'data' of exported class has or is using private name 'PrivateInterface'. -tests/cases/compiler/declarationEmitClassPrivateConstructor2.ts(10,33): error TS4063: Parameter 'data' of constructor from exported class has or is using private name 'PrivateInterface'. - - -==== tests/cases/compiler/declarationEmitClassPrivateConstructor2.ts (2 errors) ==== - interface PrivateInterface { - } - - export class ExportedClass1 { - private constructor(public data: PrivateInterface) { } - ~~~~~~~~~~~~~~~~ -!!! error TS4031: Public property 'data' of exported class has or is using private name 'PrivateInterface'. - } - - - export class ExportedClass2 { - protected constructor(data: PrivateInterface) { } - ~~~~~~~~~~~~~~~~ -!!! error TS4063: Parameter 'data' of constructor from exported class has or is using private name 'PrivateInterface'. - } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitClassPrivateConstructor2.js b/tests/baselines/reference/declarationEmitClassPrivateConstructor2.js index 863b295751f..445270e00c5 100644 --- a/tests/baselines/reference/declarationEmitClassPrivateConstructor2.js +++ b/tests/baselines/reference/declarationEmitClassPrivateConstructor2.js @@ -27,3 +27,16 @@ var ExportedClass2 = /** @class */ (function () { return ExportedClass2; }()); exports.ExportedClass2 = ExportedClass2; + + +//// [declarationEmitClassPrivateConstructor2.d.ts] +interface PrivateInterface { +} +export declare class ExportedClass1 { + data: PrivateInterface; + private constructor(); +} +export declare class ExportedClass2 { + protected constructor(data: PrivateInterface); +} +export {}; diff --git a/tests/baselines/reference/declarationEmitDefaultExport7.errors.txt b/tests/baselines/reference/declarationEmitDefaultExport7.errors.txt deleted file mode 100644 index f19766cbb00..00000000000 --- a/tests/baselines/reference/declarationEmitDefaultExport7.errors.txt +++ /dev/null @@ -1,9 +0,0 @@ -tests/cases/compiler/declarationEmitDefaultExport7.ts(2,1): error TS4082: Default export of the module has or is using private name 'A'. - - -==== tests/cases/compiler/declarationEmitDefaultExport7.ts (1 errors) ==== - class A {} - export default new A(); - ~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4082: Default export of the module has or is using private name 'A'. - \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitDefaultExport7.js b/tests/baselines/reference/declarationEmitDefaultExport7.js index 99751113dd6..e0c72ee4225 100644 --- a/tests/baselines/reference/declarationEmitDefaultExport7.js +++ b/tests/baselines/reference/declarationEmitDefaultExport7.js @@ -7,3 +7,10 @@ export default new A(); class A { } export default new A(); + + +//// [declarationEmitDefaultExport7.d.ts] +declare class A { +} +declare const _default: A; +export default _default; diff --git a/tests/baselines/reference/declarationEmitDestructuringPrivacyError.errors.txt b/tests/baselines/reference/declarationEmitDestructuringPrivacyError.errors.txt deleted file mode 100644 index e464b96a8bf..00000000000 --- a/tests/baselines/reference/declarationEmitDestructuringPrivacyError.errors.txt +++ /dev/null @@ -1,11 +0,0 @@ -tests/cases/compiler/declarationEmitDestructuringPrivacyError.ts(4,20): error TS4025: Exported variable 'y' has or is using private name 'c'. - - -==== tests/cases/compiler/declarationEmitDestructuringPrivacyError.ts (1 errors) ==== - module m { - class c { - } - export var [x, y, z] = [10, new c(), 30]; - ~ -!!! error TS4025: Exported variable 'y' has or is using private name 'c'. - } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitDestructuringPrivacyError.js b/tests/baselines/reference/declarationEmitDestructuringPrivacyError.js index 23b93d14e15..0d1e16af797 100644 --- a/tests/baselines/reference/declarationEmitDestructuringPrivacyError.js +++ b/tests/baselines/reference/declarationEmitDestructuringPrivacyError.js @@ -16,3 +16,11 @@ var m; _a = [10, new c(), 30], m.x = _a[0], m.y = _a[1], m.z = _a[2]; var _a; })(m || (m = {})); + + +//// [declarationEmitDestructuringPrivacyError.d.ts] +declare module m { + class c { + } + var x: number, y: c, z: number; +} diff --git a/tests/baselines/reference/declarationEmitExpressionInExtends3.errors.txt b/tests/baselines/reference/declarationEmitExpressionInExtends3.errors.txt deleted file mode 100644 index 4864a3bcdc2..00000000000 --- a/tests/baselines/reference/declarationEmitExpressionInExtends3.errors.txt +++ /dev/null @@ -1,51 +0,0 @@ -tests/cases/compiler/declarationEmitExpressionInExtends3.ts(28,30): error TS4020: 'extends' clause of exported class 'MyClass' has or is using private name 'LocalClass'. -tests/cases/compiler/declarationEmitExpressionInExtends3.ts(36,75): error TS4020: 'extends' clause of exported class 'MyClass3' has or is using private name 'LocalInterface'. - - -==== tests/cases/compiler/declarationEmitExpressionInExtends3.ts (2 errors) ==== - export class ExportedClass { - x: T; - } - - class LocalClass { - x: T; - y: U; - } - - export interface ExportedInterface { - x: number; - } - - interface LocalInterface { - x: number; - } - - function getLocalClass(c: T) { - return LocalClass; - } - - function getExportedClass(c: T) { - return ExportedClass; - } - - - - export class MyClass extends getLocalClass(undefined) { // error LocalClass is inaccisible - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS4020: 'extends' clause of exported class 'MyClass' has or is using private name 'LocalClass'. - } - - - export class MyClass2 extends getExportedClass(undefined) { // OK - } - - - export class MyClass3 extends getExportedClass(undefined) { // Error LocalInterface is inaccisble - ~~~~~~~~~~~~~~ -!!! error TS4020: 'extends' clause of exported class 'MyClass3' has or is using private name 'LocalInterface'. - } - - - export class MyClass4 extends getExportedClass(undefined) { // OK - } - \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitExpressionInExtends3.js b/tests/baselines/reference/declarationEmitExpressionInExtends3.js index c97587620fd..c73268f7c55 100644 --- a/tests/baselines/reference/declarationEmitExpressionInExtends3.js +++ b/tests/baselines/reference/declarationEmitExpressionInExtends3.js @@ -104,3 +104,32 @@ var MyClass4 = /** @class */ (function (_super) { return MyClass4; }(getExportedClass(undefined))); exports.MyClass4 = MyClass4; + + +//// [declarationEmitExpressionInExtends3.d.ts] +export declare class ExportedClass { + x: T; +} +declare class LocalClass { + x: T; + y: U; +} +export interface ExportedInterface { + x: number; +} +interface LocalInterface { + x: number; +} +declare const MyClass_base: typeof LocalClass; +export declare class MyClass extends MyClass_base { +} +declare const MyClass2_base: typeof ExportedClass; +export declare class MyClass2 extends MyClass2_base { +} +declare const MyClass3_base: typeof ExportedClass; +export declare class MyClass3 extends MyClass3_base { +} +declare const MyClass4_base: typeof ExportedClass; +export declare class MyClass4 extends MyClass4_base { +} +export {}; diff --git a/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.errors.txt b/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.errors.txt deleted file mode 100644 index 37a4853b649..00000000000 --- a/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.errors.txt +++ /dev/null @@ -1,13 +0,0 @@ -tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicatesWithPrivateName01.ts(5,33): error TS4060: Return type of exported function has or is using private name 'I'. - - -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitIdentifierPredicatesWithPrivateName01.ts (1 errors) ==== - interface I { - a: number; - } - - export function f(x: any): x is I { - ~ -!!! error TS4060: Return type of exported function has or is using private name 'I'. - return typeof x.a === "number"; - } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.js b/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.js index 74da01ce683..1531d09a88f 100644 --- a/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.js +++ b/tests/baselines/reference/declarationEmitIdentifierPredicatesWithPrivateName01.js @@ -14,3 +14,11 @@ function f(x) { return typeof x.a === "number"; } exports.f = f; + + +//// [declarationEmitIdentifierPredicatesWithPrivateName01.d.ts] +interface I { + a: number; +} +export declare function f(x: any): x is I; +export {}; diff --git a/tests/baselines/reference/declarationEmitInferredTypeAlias9.js b/tests/baselines/reference/declarationEmitInferredTypeAlias9.js index 8d03c6b70d2..8539cfaf03e 100644 --- a/tests/baselines/reference/declarationEmitInferredTypeAlias9.js +++ b/tests/baselines/reference/declarationEmitInferredTypeAlias9.js @@ -17,6 +17,8 @@ exports.returnSomeGlobalValue = returnSomeGlobalValue; //// [declarationEmitInferredTypeAlias9.d.ts] -export declare function returnSomeGlobalValue(): number[] | { - x: number[] | any; +declare type Foo = T | { + x: Foo; }; +export declare function returnSomeGlobalValue(): Foo; +export {}; diff --git a/tests/baselines/reference/declarationEmitInferredTypeAlias9.types b/tests/baselines/reference/declarationEmitInferredTypeAlias9.types index 30a15aff6fb..ab03db6da4f 100644 --- a/tests/baselines/reference/declarationEmitInferredTypeAlias9.types +++ b/tests/baselines/reference/declarationEmitInferredTypeAlias9.types @@ -1,19 +1,19 @@ === tests/cases/compiler/declarationEmitInferredTypeAlias9.ts === type Foo = T | { x: Foo }; ->Foo : T | { x: T | any; } +>Foo : Foo >T : T >T : T ->x : T | { x: T | any; } ->Foo : T | { x: T | any; } +>x : Foo +>Foo : Foo >T : T var x: Foo; ->x : number[] | { x: number[] | any; } ->Foo : T | { x: T | any; } +>x : Foo +>Foo : Foo export function returnSomeGlobalValue() { ->returnSomeGlobalValue : () => number[] | { x: number[] | any; } +>returnSomeGlobalValue : () => Foo return x; ->x : number[] | { x: number[] | any; } +>x : Foo } diff --git a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js index 352520ff575..3cbbc0e0763 100644 --- a/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js +++ b/tests/baselines/reference/declarationEmitLocalClassDeclarationMixin.js @@ -107,3 +107,4 @@ declare const FilteredThing_base: { export declare class FilteredThing extends FilteredThing_base { match(path: string): boolean; } +export {}; diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.errors.txt deleted file mode 100644 index ea59c8fa9e8..00000000000 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.errors.txt +++ /dev/null @@ -1,14 +0,0 @@ -tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName01.ts(2,18): error TS4055: Return type of public method from exported class has or is using private name 'D'. - - -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName01.ts (1 errors) ==== - export class C { - m(): this is D { - ~ -!!! error TS4055: Return type of public method from exported class has or is using private name 'D'. - return this instanceof D; - } - } - - class D extends C { - } \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.js b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.js index 5bb662b5907..10305b8ed64 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.js +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName01.js @@ -37,3 +37,12 @@ var D = /** @class */ (function (_super) { } return D; }(C)); + + +//// [declarationEmitThisPredicatesWithPrivateName01.d.ts] +export declare class C { + m(): this is D; +} +declare class D extends C { +} +export {}; diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt index f80c2bd0d6f..a01ebbb4864 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.errors.txt @@ -1,8 +1,7 @@ -tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(7,14): error TS4025: Exported variable 'obj' has or is using private name 'Foo'. tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts(8,10): error TS2526: A 'this' type is available only in a non-static member of a class or interface. -==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts (2 errors) ==== +==== tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredicatesWithPrivateName02.ts (1 errors) ==== interface Foo { a: string; b: number; @@ -10,8 +9,6 @@ tests/cases/conformance/declarationEmit/typePredicates/declarationEmitThisPredic } export const obj = { - ~~~ -!!! error TS4025: Exported variable 'obj' has or is using private name 'Foo'. m(): this is Foo { ~~~~ !!! error TS2526: A 'this' type is available only in a non-static member of a class or interface. diff --git a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js index 86fb2e05607..96b580a68b9 100644 --- a/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js +++ b/tests/baselines/reference/declarationEmitThisPredicatesWithPrivateName02.js @@ -21,3 +21,15 @@ exports.obj = { return dis.a != null && dis.b != null && dis.c != null; } }; + + +//// [declarationEmitThisPredicatesWithPrivateName02.d.ts] +interface Foo { + a: string; + b: number; + c: boolean; +} +export declare const obj: { + m(): this is Foo; +}; +export {}; diff --git a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.errors.txt b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.errors.txt deleted file mode 100644 index 9552adfc0af..00000000000 --- a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.errors.txt +++ /dev/null @@ -1,15 +0,0 @@ -tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters5.ts(4,25): error TS4081: Exported type alias 'SubFoo' has or is using private name 'Foo'. - - -==== tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters5.ts (1 errors) ==== - type Foo = { - foo(): Foo - }; - export type SubFoo = Foo; - ~~~ -!!! error TS4081: Exported type alias 'SubFoo' has or is using private name 'Foo'. - - function foo() { - return {} as SubFoo; - } - \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.js b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.js index cee701c0455..1b29acc164e 100644 --- a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.js +++ b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.js @@ -15,3 +15,11 @@ exports.__esModule = true; function foo() { return {}; } + + +//// [declarationEmitTypeAliasWithTypeParameters5.d.ts] +declare type Foo = { + foo(): Foo; +}; +export declare type SubFoo = Foo; +export {}; diff --git a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.types b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.types index 18ef901dbdc..cd98b3706f6 100644 --- a/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.types +++ b/tests/baselines/reference/declarationEmitTypeAliasWithTypeParameters5.types @@ -1,30 +1,30 @@ === tests/cases/compiler/declarationEmitTypeAliasWithTypeParameters5.ts === type Foo = { ->Foo : { foo(): Foo; } +>Foo : Foo >T : T >Y : Y foo(): Foo ->foo : () => { foo(): Foo; } +>foo : () => Foo >U : U >J : J ->Foo : { foo(): Foo; } +>Foo : Foo >U : U >J : J }; export type SubFoo = Foo; ->SubFoo : { foo(): Foo; } +>SubFoo : Foo >R : R ->Foo : { foo(): Foo; } +>Foo : Foo >R : R function foo() { ->foo : () => { foo(): Foo; } +>foo : () => Foo return {} as SubFoo; ->{} as SubFoo : { foo(): Foo; } +>{} as SubFoo : Foo >{} : {} ->SubFoo : { foo(): Foo; } +>SubFoo : Foo } diff --git a/tests/baselines/reference/declarationFunctionTypeNonlocalShouldNotBeAnError.js b/tests/baselines/reference/declarationFunctionTypeNonlocalShouldNotBeAnError.js index 6faa0bfca60..88343a7d08e 100644 --- a/tests/baselines/reference/declarationFunctionTypeNonlocalShouldNotBeAnError.js +++ b/tests/baselines/reference/declarationFunctionTypeNonlocalShouldNotBeAnError.js @@ -20,7 +20,8 @@ var foo; //// [declarationFunctionTypeNonlocalShouldNotBeAnError.d.ts] declare namespace foo { + function bar(): void; const obj: { - bar: () => void; + bar: typeof bar; }; } diff --git a/tests/baselines/reference/declarationNoDanglingGenerics.js b/tests/baselines/reference/declarationNoDanglingGenerics.js index 9045be6827b..fdd7f05564a 100644 --- a/tests/baselines/reference/declarationNoDanglingGenerics.js +++ b/tests/baselines/reference/declarationNoDanglingGenerics.js @@ -123,3 +123,4 @@ declare const CKind_base: { }; export declare class CKind extends CKind_base { } +export {}; diff --git a/tests/baselines/reference/dynamicNames.types b/tests/baselines/reference/dynamicNames.types index 8535d7454a1..174aff77424 100644 --- a/tests/baselines/reference/dynamicNames.types +++ b/tests/baselines/reference/dynamicNames.types @@ -213,7 +213,7 @@ declare class T10 extends T9 { >T9 : T9 } declare type T11 = { ->T11 : { [c4]: number; [c5]: string; [s2]: boolean; } +>T11 : T11 [c4]: number; >[c4] : number @@ -261,7 +261,7 @@ declare class T14 extends T13 { >T13 : T13 } declare type T15 = { ->T15 : { a: number; 1: string; [s2]: boolean; } +>T15 : T15 a: number; >a : number @@ -341,9 +341,9 @@ let t6: N.T6; >T6 : N.T6 let t7: N.T7; ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >N : any ->T7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>T7 : N.T7 let t8: T8; >t8 : T8 @@ -358,8 +358,8 @@ let t10: T10; >T10 : T10 let t11: T11; ->t11 : { [c4]: number; [c5]: string; [s2]: boolean; } ->T11 : { [c4]: number; [c5]: string; [s2]: boolean; } +>t11 : T11 +>T11 : T11 let t12: T12; >t12 : T12 @@ -374,8 +374,8 @@ let t14: T14; >T14 : T14 let t15: T15; ->t15 : { a: number; 1: string; [s2]: boolean; } ->T15 : { a: number; 1: string; [s2]: boolean; } +>t15 : T15 +>T15 : T15 // assignability t0 = t1, t0 = t2, t0 = t3, t1 = t0, t1 = t2, t1 = t3, t2 = t0, t2 = t1, t2 = t3, t3 = t0, t3 = t1, t3 = t2; @@ -431,13 +431,13 @@ t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7, >t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7, t7 = t4, t7 = t5, t7 = t6 : N.T6 >t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7, t7 = t4, t7 = t5 : N.T5 >t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7, t7 = t4 : N.T4 ->t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7 : N.T7 >t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5 : N.T5 >t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4 : N.T4 ->t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7 : N.T7 >t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6 : N.T6 >t4 = t5, t4 = t6, t4 = t7, t5 = t4 : N.T4 ->t4 = t5, t4 = t6, t4 = t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t4 = t5, t4 = t6, t4 = t7 : N.T7 >t4 = t5, t4 = t6 : N.T6 >t4 = t5 : N.T5 >t4 : N.T4 @@ -445,35 +445,35 @@ t4 = t5, t4 = t6, t4 = t7, t5 = t4, t5 = t6, t5 = t7, t6 = t4, t6 = t5, t6 = t7, >t4 = t6 : N.T6 >t4 : N.T4 >t6 : N.T6 ->t4 = t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t4 = t7 : N.T7 >t4 : N.T4 ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >t5 = t4 : N.T4 >t5 : N.T5 >t4 : N.T4 >t5 = t6 : N.T6 >t5 : N.T5 >t6 : N.T6 ->t5 = t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t5 = t7 : N.T7 >t5 : N.T5 ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >t6 = t4 : N.T4 >t6 : N.T6 >t4 : N.T4 >t6 = t5 : N.T5 >t6 : N.T6 >t5 : N.T5 ->t6 = t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t6 = t7 : N.T7 >t6 : N.T6 ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >t7 = t4 : N.T4 ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >t4 : N.T4 >t7 = t5 : N.T5 ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >t5 : N.T5 >t7 = t6 : N.T6 ->t7 : { [N.c2]: number; [N.c3]: string; [N.s1]: boolean; } +>t7 : N.T7 >t6 : N.T6 t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0, t13 = t0, t14 = t0, t15 = t0; @@ -481,7 +481,7 @@ t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0, t13 = t0, t14 = t0, t15 = t0; >t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0, t13 = t0, t14 = t0 : T0 >t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0, t13 = t0 : T0 >t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0 : T0 ->t0 = t12, t0 = t13, t0 = t14, t0 = t15 : { a: number; 1: string; [s2]: boolean; } +>t0 = t12, t0 = t13, t0 = t14, t0 = t15 : T15 >t0 = t12, t0 = t13, t0 = t14 : T14 >t0 = t12, t0 = t13 : T13 >t0 = t12 : T12 @@ -493,9 +493,9 @@ t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0, t13 = t0, t14 = t0, t15 = t0; >t0 = t14 : T14 >t0 : T0 >t14 : T14 ->t0 = t15 : { a: number; 1: string; [s2]: boolean; } +>t0 = t15 : T15 >t0 : T0 ->t15 : { a: number; 1: string; [s2]: boolean; } +>t15 : T15 >t12 = t0 : T0 >t12 : T12 >t0 : T0 @@ -506,7 +506,7 @@ t0 = t12, t0 = t13, t0 = t14, t0 = t15, t12 = t0, t13 = t0, t14 = t0, t15 = t0; >t14 : T14 >t0 : T0 >t15 = t0 : T0 ->t15 : { a: number; 1: string; [s2]: boolean; } +>t15 : T15 >t0 : T0 t0 = C; // static side diff --git a/tests/baselines/reference/emitClassExpressionInDeclarationFile.js b/tests/baselines/reference/emitClassExpressionInDeclarationFile.js index 53fead2d987..cc8848a1a20 100644 --- a/tests/baselines/reference/emitClassExpressionInDeclarationFile.js +++ b/tests/baselines/reference/emitClassExpressionInDeclarationFile.js @@ -130,3 +130,4 @@ declare const Test_base: { } & typeof FooItem; export declare class Test extends Test_base { } +export {}; diff --git a/tests/baselines/reference/exportClassExtendingIntersection.js b/tests/baselines/reference/exportClassExtendingIntersection.js index 9b99e90d511..70ea0b3b53a 100644 --- a/tests/baselines/reference/exportClassExtendingIntersection.js +++ b/tests/baselines/reference/exportClassExtendingIntersection.js @@ -118,5 +118,6 @@ declare const MyExtendedClass_base: typeof MyBaseClass & (new (...args: any[]) = export declare class MyExtendedClass extends MyExtendedClass_base { extendedClassProperty: number; } +export {}; //// [Main.d.ts] export {}; diff --git a/tests/baselines/reference/getEmitOutputWithEmitterErrors.baseline b/tests/baselines/reference/getEmitOutputWithEmitterErrors.baseline index e21f677a7ea..d2b26ca48c8 100644 --- a/tests/baselines/reference/getEmitOutputWithEmitterErrors.baseline +++ b/tests/baselines/reference/getEmitOutputWithEmitterErrors.baseline @@ -1,6 +1,4 @@ -EmitSkipped: true -Diagnostics: - Exported variable 'foo' has or is using private name 'C'. +EmitSkipped: false FileName : /tests/cases/fourslash/inputFile.js var M; (function (M) { @@ -11,4 +9,10 @@ var M; }()); M.foo = new C(); })(M || (M = {})); +FileName : /tests/cases/fourslash/inputFile.d.ts +declare module M { + class C { + } + var foo: C; +} diff --git a/tests/baselines/reference/getEmitOutputWithEmitterErrors2.baseline b/tests/baselines/reference/getEmitOutputWithEmitterErrors2.baseline index 5cc4df243d0..77131f89dd5 100644 --- a/tests/baselines/reference/getEmitOutputWithEmitterErrors2.baseline +++ b/tests/baselines/reference/getEmitOutputWithEmitterErrors2.baseline @@ -1,6 +1,4 @@ -EmitSkipped: true -Diagnostics: - Exported variable 'foo' has or is using private name 'C'. +EmitSkipped: false FileName : /tests/cases/fourslash/inputFile.js define(["require", "exports"], function (require, exports) { "use strict"; @@ -15,4 +13,11 @@ define(["require", "exports"], function (require, exports) { M.foo = new C(); })(M = exports.M || (exports.M = {})); }); +FileName : /tests/cases/fourslash/inputFile.d.ts +class C { +} +export declare module M { + var foo: C; +} +export {}; diff --git a/tests/baselines/reference/indexedAccessTypeConstraints.types b/tests/baselines/reference/indexedAccessTypeConstraints.types index dad5fd7d617..f2002aff900 100644 --- a/tests/baselines/reference/indexedAccessTypeConstraints.types +++ b/tests/baselines/reference/indexedAccessTypeConstraints.types @@ -11,7 +11,7 @@ interface IData { } type Data = { ->Data : { get: (prop: K) => T[K]; } +>Data : Data >T : T get: (prop: K) => T[K]; @@ -30,19 +30,19 @@ class Parent { >M : M constructor(private data: Data) {} ->data : { get: (prop: K) => M[K]; } ->Data : { get: (prop: K) => T[K]; } +>data : Data +>Data : Data >M : M getData(): Data { ->getData : () => { get: (prop: K) => M[K]; } ->Data : { get: (prop: K) => T[K]; } +>getData : () => Data +>Data : Data >M : M return this.data; ->this.data : { get: (prop: K) => M[K]; } +>this.data : Data >this : this ->data : { get: (prop: K) => M[K]; } +>data : Data } } @@ -60,10 +60,10 @@ export class Foo extends Parent> { return this.getData().get('content'); >this.getData().get('content') : C >this.getData().get : (prop: K) => IData[K] ->this.getData() : { get: (prop: K) => IData[K]; } ->this.getData : () => { get: (prop: K) => IData[K]; } +>this.getData() : Data> +>this.getData : () => Data> >this : this ->getData : () => { get: (prop: K) => IData[K]; } +>getData : () => Data> >get : (prop: K) => IData[K] >'content' : "content" } @@ -85,10 +85,10 @@ export class Bar> extends Parent { return this.getData().get('content'); >this.getData().get('content') : T["content"] >this.getData().get : (prop: K) => T[K] ->this.getData() : { get: (prop: K) => T[K]; } ->this.getData : () => { get: (prop: K) => T[K]; } +>this.getData() : Data +>this.getData : () => Data >this : this ->getData : () => { get: (prop: K) => T[K]; } +>getData : () => Data >get : (prop: K) => T[K] >'content' : "content" } diff --git a/tests/baselines/reference/jsxSpreadFirstUnionNoErrors.types b/tests/baselines/reference/jsxSpreadFirstUnionNoErrors.types index d96c88d1c41..0e97c588a64 100644 --- a/tests/baselines/reference/jsxSpreadFirstUnionNoErrors.types +++ b/tests/baselines/reference/jsxSpreadFirstUnionNoErrors.types @@ -3,7 +3,7 @@ import React from "react"; >React : typeof React type InfoProps = ->InfoProps : { status: "hidden"; } | { status: "visible"; content: string; } +>InfoProps : InfoProps | { status: "hidden" } >status : "hidden" @@ -13,16 +13,16 @@ type InfoProps = >content : string const Info = (props: InfoProps) => ->Info : (props: { status: "hidden"; } | { status: "visible"; content: string; }) => JSX.Element ->(props: InfoProps) =>props.status === "hidden" ?