Skip to content

Commit f90cde4

Browse files
authored
Fix completions when the ts installation and project are on two different windows drive (#35733)
* Fix completions when the ts installation and project are on two different windows drive Fixes #35512 * Fix typo
1 parent c73af61 commit f90cde4

File tree

3 files changed

+139
-4
lines changed

3 files changed

+139
-4
lines changed

src/compiler/moduleSpecifiers.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ namespace ts.moduleSpecifiers {
171171
return match ? match.length : 0;
172172
}
173173

174-
function comparePathsByNumberOfDirectrorySeparators(a: string, b: string) {
174+
function comparePathsByNumberOfDirectorySeparators(a: string, b: string) {
175175
return compareValues(
176176
numberOfDirectorySeparators(a),
177177
numberOfDirectorySeparators(b)
@@ -216,7 +216,6 @@ namespace ts.moduleSpecifiers {
216216
for (
217217
let directory = getDirectoryPath(toPath(importingFileName, cwd, getCanonicalFileName));
218218
allFileNames.size !== 0;
219-
directory = getDirectoryPath(directory)
220219
) {
221220
const directoryStart = ensureTrailingDirectorySeparator(directory);
222221
let pathsInDirectory: string[] | undefined;
@@ -228,10 +227,18 @@ namespace ts.moduleSpecifiers {
228227
});
229228
if (pathsInDirectory) {
230229
if (pathsInDirectory.length > 1) {
231-
pathsInDirectory.sort(comparePathsByNumberOfDirectrorySeparators);
230+
pathsInDirectory.sort(comparePathsByNumberOfDirectorySeparators);
232231
}
233232
sortedPaths.push(...pathsInDirectory);
234233
}
234+
const newDirectory = getDirectoryPath(directory);
235+
if (newDirectory === directory) break;
236+
directory = newDirectory;
237+
}
238+
if (allFileNames.size) {
239+
const remainingPaths = arrayFrom(allFileNames.values());
240+
if (remainingPaths.length > 1) remainingPaths.sort(comparePathsByNumberOfDirectorySeparators);
241+
sortedPaths.push(...remainingPaths);
235242
}
236243
return sortedPaths;
237244
}

src/harness/virtualFileSystemWithWatch.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ interface Array<T> { length: number; [n: number]: T; }`
645645
}
646646
else {
647647
// root folder
648-
Debug.assert(this.fs.size === 0);
648+
Debug.assert(this.fs.size === 0 || !!this.windowsStyleRoot);
649649
this.fs.set(path, folder);
650650
}
651651
}

src/testRunner/unittests/tsserver/completions.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,5 +118,133 @@ namespace ts.projectSystem {
118118
}
119119
]);
120120
});
121+
122+
it("works when files are included from two different drives of windows", () => {
123+
const projectRoot = "e:/myproject";
124+
const appPackage: File = {
125+
path: `${projectRoot}/package.json`,
126+
content: JSON.stringify({
127+
name: "test",
128+
version: "0.1.0",
129+
dependencies: {
130+
"react": "^16.12.0",
131+
"react-router-dom": "^5.1.2",
132+
}
133+
})
134+
};
135+
const appFile: File = {
136+
path: `${projectRoot}/src/app.js`,
137+
content: `import React from 'react';
138+
import {
139+
BrowserRouter as Router,
140+
} from "react-router-dom";
141+
`
142+
};
143+
const localNodeModules = `${projectRoot}/node_modules`;
144+
const localAtTypes = `${localNodeModules}/@types`;
145+
const localReactPackage: File = {
146+
path: `${localAtTypes}/react/package.json`,
147+
content: JSON.stringify({
148+
name: "@types/react",
149+
version: "16.9.14",
150+
})
151+
};
152+
const localReact: File = {
153+
path: `${localAtTypes}/react/index.d.ts`,
154+
content: `import * as PropTypes from 'prop-types';
155+
`
156+
};
157+
const localReactRouterDomPackage: File = {
158+
path: `${localNodeModules}/react-router-dom/package.json`,
159+
content: JSON.stringify({
160+
name: "react-router-dom",
161+
version: "5.1.2",
162+
})
163+
};
164+
const localReactRouterDom: File = {
165+
path: `${localNodeModules}/react-router-dom/index.js`,
166+
content: `export function foo() {}`
167+
};
168+
const localPropTypesPackage: File = {
169+
path: `${localAtTypes}/prop-types/package.json`,
170+
content: JSON.stringify({
171+
name: "@types/prop-types",
172+
version: "15.7.3",
173+
})
174+
};
175+
const localPropTypes: File = {
176+
path: `${localAtTypes}/prop-types/index.d.ts`,
177+
content: `export type ReactComponentLike =
178+
| string
179+
| ((props: any, context?: any) => any)
180+
| (new (props: any, context?: any) => any);
181+
`
182+
};
183+
184+
const globalCacheLocation = `c:/typescript`;
185+
const globalAtTypes = `${globalCacheLocation}/node_modules/@types`;
186+
const globalReactRouterDomPackage: File = {
187+
path: `${globalAtTypes}/react-router-dom/package.json`,
188+
content: JSON.stringify({
189+
name: "@types/react-router-dom",
190+
version: "5.1.2",
191+
})
192+
};
193+
const globalReactRouterDom: File = {
194+
path: `${globalAtTypes}/react-router-dom/index.d.ts`,
195+
content: `import * as React from 'react';
196+
export interface BrowserRouterProps {
197+
basename?: string;
198+
getUserConfirmation?: ((message: string, callback: (ok: boolean) => void) => void);
199+
forceRefresh?: boolean;
200+
keyLength?: number;
201+
}`
202+
};
203+
const globalReactPackage: File = {
204+
path: `${globalAtTypes}/react/package.json`,
205+
content: localReactPackage.content
206+
};
207+
const globalReact: File = {
208+
path: `${globalAtTypes}/react/index.d.ts`,
209+
content: localReact.content
210+
};
211+
212+
const filesInProject = [
213+
appFile,
214+
localReact,
215+
localPropTypes,
216+
globalReactRouterDom,
217+
globalReact,
218+
];
219+
const files = [
220+
...filesInProject,
221+
appPackage, libFile,
222+
localReactPackage,
223+
localReactRouterDomPackage, localReactRouterDom,
224+
localPropTypesPackage,
225+
globalReactRouterDomPackage,
226+
globalReactPackage,
227+
];
228+
229+
const host = createServerHost(files, { windowsStyleRoot: "c:/" });
230+
const session = createSession(host, {
231+
typingsInstaller: new TestTypingsInstaller(globalCacheLocation, /*throttleLimit*/ 5, host),
232+
});
233+
const service = session.getProjectService();
234+
openFilesForSession([appFile], session);
235+
checkNumberOfProjects(service, { inferredProjects: 1 });
236+
const windowsStyleLibFilePath = "c:/" + libFile.path.substring(1);
237+
checkProjectActualFiles(service.inferredProjects[0], filesInProject.map(f => f.path).concat(windowsStyleLibFilePath));
238+
session.executeCommandSeq<protocol.CompletionsRequest>({
239+
command: protocol.CommandTypes.CompletionInfo,
240+
arguments: {
241+
file: appFile.path,
242+
line: 5,
243+
offset: 1,
244+
includeExternalModuleExports: true,
245+
includeInsertTextCompletions: true
246+
}
247+
});
248+
});
121249
});
122250
}

0 commit comments

Comments
 (0)