mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 08:11:30 -06:00
Handle network style paths for watching (#32888)
* Refactoring * take windows style root as test server host parameter * Handle network style paths for watching Fixes #32796
This commit is contained in:
parent
1bf218291f
commit
5ac450510a
@ -90,14 +90,28 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
const nextDirectorySeparator = dirPath.indexOf(directorySeparator, rootLength);
|
||||
let nextDirectorySeparator = dirPath.indexOf(directorySeparator, rootLength);
|
||||
if (nextDirectorySeparator === -1) {
|
||||
// ignore "/user", "c:/users" or "c:/folderAtRoot"
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dirPath.charCodeAt(0) !== CharacterCodes.slash &&
|
||||
dirPath.substr(rootLength, nextDirectorySeparator).search(/users/i) === -1) {
|
||||
let pathPartForUserCheck = dirPath.substring(rootLength, nextDirectorySeparator + 1);
|
||||
const isNonDirectorySeparatorRoot = rootLength > 1 || dirPath.charCodeAt(0) !== CharacterCodes.slash;
|
||||
if (isNonDirectorySeparatorRoot &&
|
||||
dirPath.search(/[a-zA-Z]:/) !== 0 && // Non dos style paths
|
||||
pathPartForUserCheck.search(/[a-zA-z]\$\//) === 0) { // Dos style nextPart
|
||||
nextDirectorySeparator = dirPath.indexOf(directorySeparator, nextDirectorySeparator + 1);
|
||||
if (nextDirectorySeparator === -1) {
|
||||
// ignore "//vda1cs4850/c$/folderAtRoot"
|
||||
return false;
|
||||
}
|
||||
|
||||
pathPartForUserCheck = dirPath.substring(rootLength + pathPartForUserCheck.length, nextDirectorySeparator + 1);
|
||||
}
|
||||
|
||||
if (isNonDirectorySeparatorRoot &&
|
||||
pathPartForUserCheck.search(/users\//i) !== 0) {
|
||||
// Paths like c:/folderAtRoot/subFolder are allowed
|
||||
return true;
|
||||
}
|
||||
@ -105,7 +119,7 @@ namespace ts {
|
||||
for (let searchIndex = nextDirectorySeparator + 1, searchLevels = 2; searchLevels > 0; searchLevels--) {
|
||||
searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1;
|
||||
if (searchIndex === 0) {
|
||||
// Folder isnt at expected minimun levels
|
||||
// Folder isnt at expected minimum levels
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,38 +35,16 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
executingFilePath?: string;
|
||||
currentDirectory?: string;
|
||||
newLine?: string;
|
||||
useWindowsStylePaths?: boolean;
|
||||
windowsStyleRoot?: string;
|
||||
environmentVariables?: Map<string>;
|
||||
}
|
||||
|
||||
export function createWatchedSystem(fileOrFolderList: ReadonlyArray<FileOrFolderOrSymLink>, params?: TestServerHostCreationParameters): TestServerHost {
|
||||
if (!params) {
|
||||
params = {};
|
||||
}
|
||||
const host = new TestServerHost(/*withSafelist*/ false,
|
||||
params.useCaseSensitiveFileNames !== undefined ? params.useCaseSensitiveFileNames : false,
|
||||
params.executingFilePath || getExecutingFilePathFromLibFile(),
|
||||
params.currentDirectory || "/",
|
||||
fileOrFolderList,
|
||||
params.newLine,
|
||||
params.useWindowsStylePaths,
|
||||
params.environmentVariables);
|
||||
return host;
|
||||
return new TestServerHost(/*withSafelist*/ false, fileOrFolderList, params);
|
||||
}
|
||||
|
||||
export function createServerHost(fileOrFolderList: ReadonlyArray<FileOrFolderOrSymLink>, params?: TestServerHostCreationParameters): TestServerHost {
|
||||
if (!params) {
|
||||
params = {};
|
||||
}
|
||||
const host = new TestServerHost(/*withSafelist*/ true,
|
||||
params.useCaseSensitiveFileNames !== undefined ? params.useCaseSensitiveFileNames : false,
|
||||
params.executingFilePath || getExecutingFilePathFromLibFile(),
|
||||
params.currentDirectory || "/",
|
||||
fileOrFolderList,
|
||||
params.newLine,
|
||||
params.useWindowsStylePaths,
|
||||
params.environmentVariables);
|
||||
return host;
|
||||
return new TestServerHost(/*withSafelist*/ true, fileOrFolderList, params);
|
||||
}
|
||||
|
||||
export interface File {
|
||||
@ -326,6 +304,16 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
}
|
||||
|
||||
const timeIncrements = 1000;
|
||||
export interface TestServerHostOptions {
|
||||
useCaseSensitiveFileNames: boolean;
|
||||
executingFilePath: string;
|
||||
currentDirectory: string;
|
||||
fileOrFolderorSymLinkList: ReadonlyArray<FileOrFolderOrSymLink>;
|
||||
newLine?: string;
|
||||
useWindowsStylePaths?: boolean;
|
||||
environmentVariables?: Map<string>;
|
||||
}
|
||||
|
||||
export class TestServerHost implements server.ServerHost, FormatDiagnosticsHost, ModuleResolutionHost {
|
||||
args: string[] = [];
|
||||
|
||||
@ -342,16 +330,31 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
readonly watchedDirectories = createMultiMap<TestDirectoryWatcher>();
|
||||
readonly watchedDirectoriesRecursive = createMultiMap<TestDirectoryWatcher>();
|
||||
readonly watchedFiles = createMultiMap<TestFileWatcher>();
|
||||
public readonly useCaseSensitiveFileNames: boolean;
|
||||
public readonly newLine: string;
|
||||
public readonly windowsStyleRoot?: string;
|
||||
private readonly environmentVariables?: Map<string>;
|
||||
private readonly executingFilePath: string;
|
||||
private readonly currentDirectory: string;
|
||||
private readonly customWatchFile: HostWatchFile | undefined;
|
||||
private readonly customRecursiveWatchDirectory: HostWatchDirectory | undefined;
|
||||
public require: ((initialPath: string, moduleName: string) => server.RequireResult) | undefined;
|
||||
|
||||
constructor(public withSafeList: boolean, public useCaseSensitiveFileNames: boolean, executingFilePath: string, currentDirectory: string, fileOrFolderorSymLinkList: ReadonlyArray<FileOrFolderOrSymLink>, public readonly newLine = "\n", public readonly useWindowsStylePath?: boolean, private readonly environmentVariables?: Map<string>) {
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
constructor(
|
||||
public withSafeList: boolean,
|
||||
fileOrFolderorSymLinkList: ReadonlyArray<FileOrFolderOrSymLink>,
|
||||
{
|
||||
useCaseSensitiveFileNames, executingFilePath, currentDirectory,
|
||||
newLine, windowsStyleRoot, environmentVariables
|
||||
}: TestServerHostCreationParameters = {}) {
|
||||
this.useCaseSensitiveFileNames = !!useCaseSensitiveFileNames;
|
||||
this.newLine = newLine || "\n";
|
||||
this.windowsStyleRoot = windowsStyleRoot;
|
||||
this.environmentVariables = environmentVariables;
|
||||
currentDirectory = currentDirectory || "/";
|
||||
this.getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames);
|
||||
this.toPath = s => toPath(s, currentDirectory, this.getCanonicalFileName);
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath);
|
||||
this.executingFilePath = this.getHostSpecificPath(executingFilePath || getExecutingFilePathFromLibFile());
|
||||
this.currentDirectory = this.getHostSpecificPath(currentDirectory);
|
||||
this.reloadFS(fileOrFolderorSymLinkList);
|
||||
const tscWatchFile = this.environmentVariables && this.environmentVariables.get("TSC_WATCHFILE") as Tsc_WatchFile;
|
||||
@ -418,8 +421,8 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
}
|
||||
|
||||
getHostSpecificPath(s: string) {
|
||||
if (this.useWindowsStylePath && s.startsWith(directorySeparator)) {
|
||||
return "c:/" + s.substring(1);
|
||||
if (this.windowsStyleRoot && s.startsWith(directorySeparator)) {
|
||||
return this.windowsStyleRoot + s.substring(1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -433,7 +436,7 @@ interface Array<T> { length: number; [n: number]: T; }`
|
||||
const mapNewLeaves = createMap<true>();
|
||||
const isNewFs = this.fs.size === 0;
|
||||
fileOrFolderOrSymLinkList = fileOrFolderOrSymLinkList.concat(this.withSafeList ? safeList : []);
|
||||
const filesOrFoldersToLoad: ReadonlyArray<FileOrFolderOrSymLink> = !this.useWindowsStylePath ? fileOrFolderOrSymLinkList :
|
||||
const filesOrFoldersToLoad: ReadonlyArray<FileOrFolderOrSymLink> = !this.windowsStyleRoot ? fileOrFolderOrSymLinkList :
|
||||
fileOrFolderOrSymLinkList.map<FileOrFolderOrSymLink>(f => {
|
||||
const result = clone(f);
|
||||
result.path = this.getHostSpecificPath(f.path);
|
||||
|
||||
@ -1061,7 +1061,7 @@ namespace ts.projectSystem {
|
||||
content: "let x = 1;"
|
||||
};
|
||||
|
||||
const host = createServerHost([file1, configFile], { useWindowsStylePaths: true });
|
||||
const host = createServerHost([file1, configFile], { windowsStyleRoot: "c:/" });
|
||||
const projectService = createProjectService(host);
|
||||
|
||||
projectService.openClientFile(file1.path);
|
||||
|
||||
@ -99,7 +99,7 @@ namespace ts.projectSystem {
|
||||
content: "let y = 10;"
|
||||
};
|
||||
const files = [configFile, file1, file2, libFile];
|
||||
const host = createServerHost(files, { useWindowsStylePaths: true });
|
||||
const host = createServerHost(files, { windowsStyleRoot: "c:/" });
|
||||
const projectService = createProjectService(host);
|
||||
projectService.openClientFile(file1.path);
|
||||
const project = projectService.configuredProjects.get(configFile.path)!;
|
||||
@ -211,4 +211,39 @@ namespace ts.projectSystem {
|
||||
}
|
||||
});
|
||||
|
||||
describe("unittests:: tsserver:: watchEnvironment:: tsserverProjectSystem watching files with network style paths", () => {
|
||||
function verifyFilePathStyle(path: string) {
|
||||
const windowsStyleRoot = path.substr(0, getRootLength(path));
|
||||
const host = createServerHost(
|
||||
[libFile, { path, content: "const x = 10" }],
|
||||
{ windowsStyleRoot }
|
||||
);
|
||||
const service = createProjectService(host);
|
||||
service.openClientFile(path);
|
||||
checkNumberOfProjects(service, { inferredProjects: 1 });
|
||||
const libPath = `${windowsStyleRoot}${libFile.path.substring(1)}`;
|
||||
checkProjectActualFiles(service.inferredProjects[0], [path, libPath]);
|
||||
checkWatchedFiles(host, [libPath, `${getDirectoryPath(path)}/tsconfig.json`, `${getDirectoryPath(path)}/jsconfig.json`]);
|
||||
}
|
||||
|
||||
it("for file of style c:/myprojects/project/x.js", () => {
|
||||
verifyFilePathStyle("c:/myprojects/project/x.js");
|
||||
});
|
||||
|
||||
it("for file of style //vda1cs4850/myprojects/project/x.js", () => {
|
||||
verifyFilePathStyle("//vda1cs4850/myprojects/project/x.js");
|
||||
});
|
||||
|
||||
it("for file of style //vda1cs4850/c$/myprojects/project/x.js", () => {
|
||||
verifyFilePathStyle("//vda1cs4850/c$/myprojects/project/x.js");
|
||||
});
|
||||
|
||||
it("for file of style c:/users/username/myprojects/project/x.js", () => {
|
||||
verifyFilePathStyle("c:/users/username/myprojects/project/x.js");
|
||||
});
|
||||
|
||||
it("for file of style //vda1cs4850/c$/users/username/myprojects/project/x.js", () => {
|
||||
verifyFilePathStyle("//vda1cs4850/c$/users/username/myprojects/project/x.js");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user