Skip to content

Commit 35a6426

Browse files
authored
Merge pull request #33647 from microsoft/defaultProject
Use correct default project for file if that project is opened at later time
2 parents 57d7edb + 144b81c commit 35a6426

24 files changed

+412
-481
lines changed

src/server/editorServices.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,6 +1533,14 @@ namespace ts.server {
15331533
return undefined;
15341534
}
15351535

1536+
/*@internal*/
1537+
findDefaultConfiguredProject(info: ScriptInfo) {
1538+
if (!info.isScriptOpen()) return undefined;
1539+
const configFileName = this.getConfigFileNameForFile(info);
1540+
return configFileName &&
1541+
this.findConfiguredProjectByProjectName(configFileName);
1542+
}
1543+
15361544
/**
15371545
* This function tries to search for a tsconfig.json for the given file.
15381546
* This is different from the method the compiler uses because

src/server/scriptInfo.ts

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -491,21 +491,40 @@ namespace ts.server {
491491
case 1:
492492
return this.containingProjects[0];
493493
default:
494-
// if this file belongs to multiple projects, the first configured project should be
495-
// the default project; if no configured projects, the first external project should
496-
// be the default project; otherwise the first inferred project should be the default.
494+
// If this file belongs to multiple projects, below is the order in which default project is used
495+
// - for open script info, its default configured project during opening is default if info is part of it
496+
// - first configured project of which script info is not a source of project reference redirect
497+
// - first configured project
498+
// - first external project
499+
// - first inferred project
497500
let firstExternalProject;
498501
let firstConfiguredProject;
499-
for (const project of this.containingProjects) {
502+
let firstNonSourceOfProjectReferenceRedirect;
503+
let defaultConfiguredProject: ConfiguredProject | false | undefined;
504+
for (let index = 0; index < this.containingProjects.length; index++) {
505+
const project = this.containingProjects[index];
500506
if (project.projectKind === ProjectKind.Configured) {
501-
if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) return project;
507+
if (!project.isSourceOfProjectReferenceRedirect(this.fileName)) {
508+
// If we havent found default configuredProject and
509+
// its not the last one, find it and use that one if there
510+
if (defaultConfiguredProject === undefined &&
511+
index !== this.containingProjects.length - 1) {
512+
defaultConfiguredProject = project.projectService.findDefaultConfiguredProject(this) || false;
513+
}
514+
if (defaultConfiguredProject === project) return project;
515+
if (!firstNonSourceOfProjectReferenceRedirect) firstNonSourceOfProjectReferenceRedirect = project;
516+
}
502517
if (!firstConfiguredProject) firstConfiguredProject = project;
503518
}
504519
else if (project.projectKind === ProjectKind.External && !firstExternalProject) {
505520
firstExternalProject = project;
506521
}
507522
}
508-
return firstConfiguredProject || firstExternalProject || this.containingProjects[0];
523+
return defaultConfiguredProject ||
524+
firstNonSourceOfProjectReferenceRedirect ||
525+
firstConfiguredProject ||
526+
firstExternalProject ||
527+
this.containingProjects[0];
509528
}
510529
}
511530

src/testRunner/unittests/tscWatch/emitAndErrorUpdates.ts

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
namespace ts.tscWatch {
22
describe("unittests:: tsc-watch:: Emit times and Error updates in builder after program changes", () => {
3-
const currentDirectory = "/user/username/projects/myproject";
43
const config: File = {
5-
path: `${currentDirectory}/tsconfig.json`,
4+
path: `${projectRoot}/tsconfig.json`,
65
content: `{}`
76
};
87
function getOutputFileStampAndError(host: WatchedSystem, watch: Watch, file: File) {
@@ -83,7 +82,7 @@ namespace ts.tscWatch {
8382
const nonLibFiles = [...filesWithNewEmit, ...filesWithOnlyErrorRefresh, ...filesNotTouched];
8483
const files = [...nonLibFiles, configFile, libFile];
8584
const compilerOptions = (JSON.parse(configFile.content).compilerOptions || {}) as CompilerOptions;
86-
const host = createWatchedSystem(files, { currentDirectory });
85+
const host = createWatchedSystem(files, { currentDirectory: projectRoot });
8786
const watch = createWatchOfConfigFile("tsconfig.json", host);
8887
checkProgramActualFiles(watch(), [...nonLibFiles.map(f => f.path), libFile.path]);
8988
checkOutputErrorsInitial(host, getInitialErrors(watch));
@@ -167,7 +166,7 @@ namespace ts.tscWatch {
167166

168167
describe("deep import changes", () => {
169168
const aFile: File = {
170-
path: `${currentDirectory}/a.ts`,
169+
path: `${projectRoot}/a.ts`,
171170
content: `import {B} from './b';
172171
declare var console: any;
173172
let b = new B();
@@ -203,15 +202,15 @@ console.log(b.c.d);`
203202

204203
describe("updates errors when deep import file changes", () => {
205204
const bFile: File = {
206-
path: `${currentDirectory}/b.ts`,
205+
path: `${projectRoot}/b.ts`,
207206
content: `import {C} from './c';
208207
export class B
209208
{
210209
c = new C();
211210
}`
212211
};
213212
const cFile: File = {
214-
path: `${currentDirectory}/c.ts`,
213+
path: `${projectRoot}/c.ts`,
215214
content: `export class C
216215
{
217216
d = 1;
@@ -222,15 +221,15 @@ export class B
222221

223222
describe("updates errors when deep import through declaration file changes", () => {
224223
const bFile: File = {
225-
path: `${currentDirectory}/b.d.ts`,
224+
path: `${projectRoot}/b.d.ts`,
226225
content: `import {C} from './c';
227226
export class B
228227
{
229228
c: C;
230229
}`
231230
};
232231
const cFile: File = {
233-
path: `${currentDirectory}/c.d.ts`,
232+
path: `${projectRoot}/c.d.ts`,
234233
content: `export class C
235234
{
236235
d: number;
@@ -242,7 +241,7 @@ export class B
242241

243242
describe("updates errors in file not exporting a deep multilevel import that changes", () => {
244243
const aFile: File = {
245-
path: `${currentDirectory}/a.ts`,
244+
path: `${projectRoot}/a.ts`,
246245
content: `export interface Point {
247246
name: string;
248247
c: Coords;
@@ -253,13 +252,13 @@ export interface Coords {
253252
}`
254253
};
255254
const bFile: File = {
256-
path: `${currentDirectory}/b.ts`,
255+
path: `${projectRoot}/b.ts`,
257256
content: `import { Point } from "./a";
258257
export interface PointWrapper extends Point {
259258
}`
260259
};
261260
const cFile: File = {
262-
path: `${currentDirectory}/c.ts`,
261+
path: `${projectRoot}/c.ts`,
263262
content: `import { PointWrapper } from "./b";
264263
export function getPoint(): PointWrapper {
265264
return {
@@ -272,12 +271,12 @@ export function getPoint(): PointWrapper {
272271
};`
273272
};
274273
const dFile: File = {
275-
path: `${currentDirectory}/d.ts`,
274+
path: `${projectRoot}/d.ts`,
276275
content: `import { getPoint } from "./c";
277276
getPoint().c.x;`
278277
};
279278
const eFile: File = {
280-
path: `${currentDirectory}/e.ts`,
279+
path: `${projectRoot}/e.ts`,
281280
content: `import "./d";`
282281
};
283282
verifyEmitAndErrorUpdates({
@@ -301,14 +300,14 @@ getPoint().c.x;`
301300

302301
describe("updates errors when file transitively exported file changes", () => {
303302
const config: File = {
304-
path: `${currentDirectory}/tsconfig.json`,
303+
path: `${projectRoot}/tsconfig.json`,
305304
content: JSON.stringify({
306305
files: ["app.ts"],
307306
compilerOptions: { baseUrl: "." }
308307
})
309308
};
310309
const app: File = {
311-
path: `${currentDirectory}/app.ts`,
310+
path: `${projectRoot}/app.ts`,
312311
content: `import { Data } from "lib2/public";
313312
export class App {
314313
public constructor() {
@@ -317,11 +316,11 @@ export class App {
317316
}`
318317
};
319318
const lib2Public: File = {
320-
path: `${currentDirectory}/lib2/public.ts`,
319+
path: `${projectRoot}/lib2/public.ts`,
321320
content: `export * from "./data";`
322321
};
323322
const lib2Data: File = {
324-
path: `${currentDirectory}/lib2/data.ts`,
323+
path: `${projectRoot}/lib2/data.ts`,
325324
content: `import { ITest } from "lib1/public";
326325
export class Data {
327326
public test() {
@@ -333,15 +332,15 @@ export class Data {
333332
}`
334333
};
335334
const lib1Public: File = {
336-
path: `${currentDirectory}/lib1/public.ts`,
335+
path: `${projectRoot}/lib1/public.ts`,
337336
content: `export * from "./tools/public";`
338337
};
339338
const lib1ToolsPublic: File = {
340-
path: `${currentDirectory}/lib1/tools/public.ts`,
339+
path: `${projectRoot}/lib1/tools/public.ts`,
341340
content: `export * from "./tools.interface";`
342341
};
343342
const lib1ToolsInterface: File = {
344-
path: `${currentDirectory}/lib1/tools/tools.interface.ts`,
343+
path: `${projectRoot}/lib1/tools/tools.interface.ts`,
345344
content: `export interface ITest {
346345
title: string;
347346
}`
@@ -372,7 +371,7 @@ export class Data {
372371

373372
describe("when there are circular import and exports", () => {
374373
const lib2Data: File = {
375-
path: `${currentDirectory}/lib2/data.ts`,
374+
path: `${projectRoot}/lib2/data.ts`,
376375
content: `import { ITest } from "lib1/public"; import { Data2 } from "./data2";
377376
export class Data {
378377
public dat?: Data2; public test() {
@@ -384,7 +383,7 @@ export class Data {
384383
}`
385384
};
386385
const lib2Data2: File = {
387-
path: `${currentDirectory}/lib2/data2.ts`,
386+
path: `${projectRoot}/lib2/data2.ts`,
388387
content: `import { Data } from "./data";
389388
export class Data2 {
390389
public dat?: Data;

src/testRunner/unittests/tscWatch/helpers.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
namespace ts {
2+
export const projects = `/user/username/projects`;
3+
export const projectRoot = `${projects}/myproject`;
4+
}
15
namespace ts.tscWatch {
26
export import WatchedSystem = TestFSWithWatch.TestServerHost;
37
export type File = TestFSWithWatch.File;

0 commit comments

Comments
 (0)