diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 2aa3008dc01a3..c14408ad5ef7d 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -70,6 +70,7 @@ import { getResolvedExternalModuleName, getSetAccessorValueParameter, getSourceFileOfNode, + getSourceFilesToEmit, GetSymbolAccessibilityDiagnostic, getTextOfNode, getThisParameter, @@ -214,7 +215,16 @@ import { /** @internal */ export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined { const compilerOptions = host.getCompilerOptions(); - const result = transformNodes(resolver, host, factory, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJson), [transformDeclarations], /*allowDtsFiles*/ false); + const files = filter(getSourceFilesToEmit(host, file), isSourceFileNotJson); + const result = transformNodes( + resolver, + host, + factory, + compilerOptions, + file ? contains(files, file) ? [file] : emptyArray : files, + [transformDeclarations], + /*allowDtsFiles*/ false, + ); return result.diagnostics; } diff --git a/src/testRunner/unittests/tsserver/projectReferenceErrors.ts b/src/testRunner/unittests/tsserver/projectReferenceErrors.ts index b6a5c0e366277..d8950ebe20f87 100644 --- a/src/testRunner/unittests/tsserver/projectReferenceErrors.ts +++ b/src/testRunner/unittests/tsserver/projectReferenceErrors.ts @@ -1,11 +1,21 @@ +import * as ts from "../../_namespaces/ts"; +import { dedent } from "../../_namespaces/Utils"; import { jsonToReadableText } from "../helpers"; +import { libContent } from "../helpers/contents"; import { + baselineTsserverLogs, GetErrForProjectDiagnostics, + openFilesForSession, + TestSession, verifyGetErrScenario, } from "../helpers/tsserver"; -import { File } from "../helpers/virtualFileSystemWithWatch"; +import { + File, + libFile, + TestServerHost, +} from "../helpers/virtualFileSystemWithWatch"; -describe("unittests:: tsserver:: with project references and error reporting", () => { +describe("unittests:: tsserver:: projectReferenceErrors:: with project references and error reporting", () => { const dependecyLocation = `/user/username/projects/myproject/dependency`; const usageLocation = `/user/username/projects/myproject/usage`; @@ -133,4 +143,52 @@ fnErr(); }; verifyUsageAndDependency("with non module", dependencyTs, dependencyConfig, usageTs, usageConfig); }); + + it("when options for dependency project are different from usage project", () => { + const host = new TestServerHost({ + "/home/src/projects/project/a/index.ts": dedent` + export function f2() { + return console.log() + } + `, + "/home/src/projects/project/a/tsconfig.json": jsonToReadableText({ + compilerOptions: { + composite: true, + outDir: "../dist/a", + }, + include: ["."], + }), + "/home/src/projects/project/b/index.ts": dedent` + import { f2 } from '../a/index.js' + export function f() { + f2() + return console.log('') + } + `, + "/home/src/projects/project/b/tsconfig.json": jsonToReadableText({ + compilerOptions: { + composite: true, + isolatedDeclarations: true, + outDir: "../dist/b", + }, + references: [{ path: "../a/" }], + include: ["."], + }), + [libFile.path]: libContent, + }); + const session = new TestSession(host); + openFilesForSession(["/home/src/projects/project/b/index.ts"], session); + + session.executeCommandSeq({ + command: ts.server.protocol.CommandTypes.GeterrForProject, + arguments: { delay: 0, file: "/home/src/projects/project/b/index.ts" }, + }); + host.runQueuedTimeoutCallbacks(); + host.runQueuedImmediateCallbacks(); + host.runQueuedImmediateCallbacks(); + host.runQueuedTimeoutCallbacks(); + host.runQueuedImmediateCallbacks(); + host.runQueuedImmediateCallbacks(); + baselineTsserverLogs("projectReferenceErrors", "when options for dependency project are different from usage project", session); + }); }); diff --git a/tests/baselines/reference/tsserver/projectReferenceErrors/when-options-for-dependency-project-are-different-from-usage-project.js b/tests/baselines/reference/tsserver/projectReferenceErrors/when-options-for-dependency-project-are-different-from-usage-project.js new file mode 100644 index 0000000000000..9ebcabbce9303 --- /dev/null +++ b/tests/baselines/reference/tsserver/projectReferenceErrors/when-options-for-dependency-project-are-different-from-usage-project.js @@ -0,0 +1,440 @@ +currentDirectory:: / useCaseSensitiveFileNames: false +Info seq [hh:mm:ss:mss] Provided types map file "/typesMap.json" doesn't exist +Before request +//// [/home/src/projects/project/a/index.ts] +export function f2() { + return console.log() +} + + +//// [/home/src/projects/project/a/tsconfig.json] +{ + "compilerOptions": { + "composite": true, + "outDir": "../dist/a" + }, + "include": [ + "." + ] +} + +//// [/home/src/projects/project/b/index.ts] +import { f2 } from '../a/index.js' +export function f() { + f2() + return console.log('') +} + + +//// [/home/src/projects/project/b/tsconfig.json] +{ + "compilerOptions": { + "composite": true, + "isolatedDeclarations": true, + "outDir": "../dist/b" + }, + "references": [ + { + "path": "../a/" + } + ], + "include": [ + "." + ] +} + +//// [/a/lib/lib.d.ts] +/// +interface Boolean {} +interface Function {} +interface CallableFunction {} +interface NewableFunction {} +interface IArguments {} +interface Number { toExponential: any; } +interface Object {} +interface RegExp {} +interface String { charAt: any; } +interface Array { length: number; [n: number]: T; } +interface ReadonlyArray {} +declare const console: { log(msg: any): void; }; + + +Info seq [hh:mm:ss:mss] request: + { + "command": "open", + "arguments": { + "file": "/home/src/projects/project/b/index.ts" + }, + "seq": 1, + "type": "request" + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /home/src/projects/project/b/index.ts ProjectRootPath: undefined:: Result: /home/src/projects/project/b/tsconfig.json +Info seq [hh:mm:ss:mss] Creating configuration project /home/src/projects/project/b/tsconfig.json +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/b/tsconfig.json 2000 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Config file +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "projectLoadingStart", + "body": { + "projectName": "/home/src/projects/project/b/tsconfig.json", + "reason": "Creating possible configured project for /home/src/projects/project/b/index.ts to open" + } + } +Info seq [hh:mm:ss:mss] Config: /home/src/projects/project/b/tsconfig.json : { + "rootNames": [ + "/home/src/projects/project/b/index.ts" + ], + "options": { + "composite": true, + "isolatedDeclarations": true, + "outDir": "/home/src/projects/project/dist/b", + "configFilePath": "/home/src/projects/project/b/tsconfig.json" + }, + "projectReferences": [ + { + "path": "/home/src/projects/project/a", + "originalPath": "../a/" + } + ] +} +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/b 1 undefined Config: /home/src/projects/project/b/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/b 1 undefined Config: /home/src/projects/project/b/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] Starting updateGraphWorker: Project: /home/src/projects/project/b/tsconfig.json +Info seq [hh:mm:ss:mss] Config: /home/src/projects/project/a/tsconfig.json : { + "rootNames": [ + "/home/src/projects/project/a/index.ts" + ], + "options": { + "composite": true, + "outDir": "/home/src/projects/project/dist/a", + "configFilePath": "/home/src/projects/project/a/tsconfig.json" + } +} +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/a/tsconfig.json 2000 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Config file +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/a 1 undefined Config: /home/src/projects/project/a/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/a 1 undefined Config: /home/src/projects/project/a/tsconfig.json WatchType: Wild card directory +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/a/index.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 500 undefined WatchType: Closed Script info +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/a/package.json 2000 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: File location affecting resolution +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/package.json 2000 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: File location affecting resolution +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/package.json 2000 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: File location affecting resolution +Info seq [hh:mm:ss:mss] FileWatcher:: Added:: WatchInfo: /home/src/projects/project/b/package.json 2000 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: File location affecting resolution +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/b/node_modules/@types 1 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Type roots +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/b/node_modules/@types 1 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Type roots +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules/@types 1 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Type roots +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/project/node_modules/@types 1 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Type roots +Info seq [hh:mm:ss:mss] DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/node_modules/@types 1 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Type roots +Info seq [hh:mm:ss:mss] Elapsed:: *ms DirectoryWatcher:: Added:: WatchInfo: /home/src/projects/node_modules/@types 1 undefined Project: /home/src/projects/project/b/tsconfig.json WatchType: Type roots +Info seq [hh:mm:ss:mss] Finishing updateGraphWorker: Project: /home/src/projects/project/b/tsconfig.json projectStateVersion: 1 projectProgramVersion: 0 structureChanged: true structureIsReused:: Not Elapsed:: *ms +Info seq [hh:mm:ss:mss] Project '/home/src/projects/project/b/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (3) + /a/lib/lib.d.ts Text-1 "/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }\ninterface ReadonlyArray {}\ndeclare const console: { log(msg: any): void; };" + /home/src/projects/project/a/index.ts Text-1 "export function f2() {\n return console.log()\n}\n" + /home/src/projects/project/b/index.ts SVC-1-0 "import { f2 } from '../a/index.js'\nexport function f() {\n f2()\n return console.log('')\n}\n" + + + ../../../../../a/lib/lib.d.ts + Default library for target 'es5' + ../a/index.ts + Imported via '../a/index.js' from file 'index.ts' + index.ts + Matched by include pattern '.' in 'tsconfig.json' + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "projectLoadingFinish", + "body": { + "projectName": "/home/src/projects/project/b/tsconfig.json" + } + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "telemetry", + "body": { + "telemetryEventName": "projectInfo", + "payload": { + "projectId": "12d5481057bdbc86f3fdf4eacf0490fc5694acf3db8d1f7545c8f4d4a37f2175", + "fileStats": { + "js": 0, + "jsSize": 0, + "jsx": 0, + "jsxSize": 0, + "ts": 2, + "tsSize": 145, + "tsx": 0, + "tsxSize": 0, + "dts": 1, + "dtsSize": 413, + "deferred": 0, + "deferredSize": 0 + }, + "compilerOptions": { + "composite": true, + "isolatedDeclarations": true, + "outDir": "" + }, + "typeAcquisition": { + "enable": false, + "include": false, + "exclude": false + }, + "extends": false, + "files": false, + "include": true, + "exclude": false, + "compileOnSave": false, + "configFileName": "tsconfig.json", + "projectType": "configured", + "languageServiceEnabled": true, + "version": "FakeVersion" + } + } + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "configFileDiag", + "body": { + "triggerFile": "/home/src/projects/project/b/index.ts", + "configFile": "/home/src/projects/project/b/tsconfig.json", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] getConfigFileNameForFile:: File: /home/src/projects/project/b/tsconfig.json ProjectRootPath: undefined:: Result: undefined +Info seq [hh:mm:ss:mss] Project '/home/src/projects/project/b/tsconfig.json' (Configured) +Info seq [hh:mm:ss:mss] Files (3) + +Info seq [hh:mm:ss:mss] ----------------------------------------------- +Info seq [hh:mm:ss:mss] Open files: +Info seq [hh:mm:ss:mss] FileName: /home/src/projects/project/b/index.ts ProjectRootPath: undefined +Info seq [hh:mm:ss:mss] Projects: /home/src/projects/project/b/tsconfig.json +Info seq [hh:mm:ss:mss] response: + { + "responseRequired": false + } +After request + +PolledWatches:: +/home/src/projects/node_modules/@types: *new* + {"pollingInterval":500} +/home/src/projects/package.json: *new* + {"pollingInterval":2000} +/home/src/projects/project/a/package.json: *new* + {"pollingInterval":2000} +/home/src/projects/project/b/node_modules/@types: *new* + {"pollingInterval":500} +/home/src/projects/project/b/package.json: *new* + {"pollingInterval":2000} +/home/src/projects/project/node_modules/@types: *new* + {"pollingInterval":500} +/home/src/projects/project/package.json: *new* + {"pollingInterval":2000} + +FsWatches:: +/a/lib/lib.d.ts: *new* + {} +/home/src/projects/project/a/index.ts: *new* + {} +/home/src/projects/project/a/tsconfig.json: *new* + {} +/home/src/projects/project/b/tsconfig.json: *new* + {} + +FsWatchesRecursive:: +/home/src/projects/project/a: *new* + {} +/home/src/projects/project/b: *new* + {} + +Projects:: +/home/src/projects/project/b/tsconfig.json (Configured) *new* + projectStateVersion: 1 + projectProgramVersion: 1 + +ScriptInfos:: +/a/lib/lib.d.ts *new* + version: Text-1 + containingProjects: 1 + /home/src/projects/project/b/tsconfig.json +/home/src/projects/project/a/index.ts *new* + version: Text-1 + containingProjects: 1 + /home/src/projects/project/b/tsconfig.json +/home/src/projects/project/b/index.ts (Open) *new* + version: SVC-1-0 + containingProjects: 1 + /home/src/projects/project/b/tsconfig.json *default* + +Before request + +Info seq [hh:mm:ss:mss] request: + { + "command": "geterrForProject", + "arguments": { + "delay": 0, + "file": "/home/src/projects/project/b/index.ts" + }, + "seq": 2, + "type": "request" + } +Info seq [hh:mm:ss:mss] response: + { + "responseRequired": false + } +After request + +Timeout callback:: count: 1 +1: checkOne *new* + +Before running Timeout callback:: count: 1 +1: checkOne + +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "syntaxDiag", + "body": { + "file": "/home/src/projects/project/b/index.ts", + "diagnostics": [] + } + } +After running Timeout callback:: count: 0 + +Immedidate callback:: count: 1 +1: semanticCheck *new* + +Before running Immedidate callback:: count: 1 +1: semanticCheck + +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "semanticDiag", + "body": { + "file": "/home/src/projects/project/b/index.ts", + "diagnostics": [ + { + "start": { + "line": 2, + "offset": 17 + }, + "end": { + "line": 2, + "offset": 18 + }, + "text": "Function must have an explicit return type annotation with --isolatedDeclarations.", + "code": 9007, + "category": "error", + "relatedInformation": [ + { + "span": { + "start": { + "line": 2, + "offset": 17 + }, + "end": { + "line": 2, + "offset": 18 + }, + "file": "/home/src/projects/project/b/index.ts" + }, + "message": "Add a return type to the function declaration.", + "category": "error", + "code": 9031 + } + ] + } + ] + } + } +After running Immedidate callback:: count: 1 + +Immedidate callback:: count: 1 +2: suggestionCheck *new* + +Before running Immedidate callback:: count: 1 +2: suggestionCheck + +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "suggestionDiag", + "body": { + "file": "/home/src/projects/project/b/index.ts", + "diagnostics": [] + } + } +After running Immedidate callback:: count: 0 + +Timeout callback:: count: 1 +2: checkOne *new* + +Before running Timeout callback:: count: 1 +2: checkOne + +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "syntaxDiag", + "body": { + "file": "/home/src/projects/project/a/index.ts", + "diagnostics": [] + } + } +After running Timeout callback:: count: 0 + +Immedidate callback:: count: 1 +3: semanticCheck *new* + +Before running Immedidate callback:: count: 1 +3: semanticCheck + +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "semanticDiag", + "body": { + "file": "/home/src/projects/project/a/index.ts", + "diagnostics": [] + } + } +After running Immedidate callback:: count: 1 + +Immedidate callback:: count: 1 +4: suggestionCheck *new* + +Before running Immedidate callback:: count: 1 +4: suggestionCheck + +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "suggestionDiag", + "body": { + "file": "/home/src/projects/project/a/index.ts", + "diagnostics": [] + } + } +Info seq [hh:mm:ss:mss] event: + { + "seq": 0, + "type": "event", + "event": "requestCompleted", + "body": { + "request_seq": 2 + } + } +After running Immedidate callback:: count: 0