mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-03-15 05:55:11 -05:00
add test and spit commandLineParser changes to another PR
This commit is contained in:
@@ -727,22 +727,10 @@ namespace ts {
|
||||
const supportedExtensions = getSupportedExtensions(options);
|
||||
Debug.assert(indexOf(supportedExtensions, ".ts") < indexOf(supportedExtensions, ".d.ts"), "Changed priority of extensions to pick");
|
||||
|
||||
const potentialFiles: string[] = [];
|
||||
if (host.readDirectoryWithMultipleExtensions) {
|
||||
addRange(potentialFiles, host.readDirectoryWithMultipleExtensions(basePath, supportedExtensions, exclude));
|
||||
}
|
||||
else {
|
||||
for (const extension of supportedExtensions) {
|
||||
addRange(potentialFiles, host.readDirectory(basePath, extension, exclude));
|
||||
}
|
||||
}
|
||||
// Get files of supported extensions in their order of resolution
|
||||
for (const extension of supportedExtensions) {
|
||||
for (const fileName of potentialFiles) {
|
||||
if (!fileExtensionIs(fileName, extension)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const filesInDirWithExtension = host.readDirectory(basePath, extension, exclude);
|
||||
for (const fileName of filesInDirWithExtension) {
|
||||
// .ts extension would read the .d.ts extension files too but since .d.ts is lower priority extension,
|
||||
// lets pick them when its turn comes up
|
||||
if (extension === ".ts" && fileExtensionIs(fileName, ".d.ts")) {
|
||||
|
||||
@@ -27,7 +27,6 @@ namespace ts {
|
||||
getCurrentDirectory(): string;
|
||||
getDirectories(path: string): string[];
|
||||
readDirectory(path: string, extension?: string, exclude?: string[]): string[];
|
||||
readDirectoryWithMultipleExtensions?(path: string, extensions: string[], exclude?: string[]): string[];
|
||||
getModifiedTime?(path: string): Date;
|
||||
createHash?(data: string): string;
|
||||
getMemoryUsage?(): number;
|
||||
@@ -416,23 +415,25 @@ namespace ts {
|
||||
return filter<string>(_fs.readdirSync(path), p => fileSystemEntryExists(combinePaths(path, p), FileSystemEntryKind.Directory));
|
||||
}
|
||||
|
||||
function visitDirectory(path: string, result: string[], extension: string | string[], exclude: string[]) {
|
||||
const files = _fs.readdirSync(path || ".").sort();
|
||||
const directories: string[] = [];
|
||||
for (const current of files) {
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
const result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path);
|
||||
return result;
|
||||
function visitDirectory(path: string) {
|
||||
const files = _fs.readdirSync(path || ".").sort();
|
||||
const directories: string[] = [];
|
||||
for (const current of files) {
|
||||
// This is necessary because on some file system node fails to exclude
|
||||
// "." and "..". See https://github.com/nodejs/node/issues/4002
|
||||
if (current === "." || current === "..") {
|
||||
continue;
|
||||
}
|
||||
const name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
// fs.statSync would throw an exception if the file is a symlink
|
||||
// whose linked file doesn't exist.
|
||||
try {
|
||||
const name = combinePaths(path, current);
|
||||
if (!contains(exclude, getCanonicalPath(name))) {
|
||||
const stat = _fs.statSync(name);
|
||||
if (stat.isFile()) {
|
||||
if (checkExtension(name)) {
|
||||
if (!extension || fileExtensionIs(name, extension)) {
|
||||
result.push(name);
|
||||
}
|
||||
}
|
||||
@@ -440,38 +441,11 @@ namespace ts {
|
||||
directories.push(name);
|
||||
}
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
for (const current of directories) {
|
||||
visitDirectory(current);
|
||||
}
|
||||
}
|
||||
for (const current of directories) {
|
||||
visitDirectory(current, result, extension, exclude);
|
||||
}
|
||||
|
||||
function checkExtension(name: string) {
|
||||
if (!extension) {
|
||||
return true;
|
||||
}
|
||||
if (typeof extension === "string") {
|
||||
return fileExtensionIs(name, extension);
|
||||
}
|
||||
else {
|
||||
return forEach(extension, ext => fileExtensionIs(name, ext));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function readDirectoryWithMultipleExtensions(path: string, extensions: string[], exclude?: string[]): string[] {
|
||||
const result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path, result, extensions, exclude);
|
||||
return result;
|
||||
}
|
||||
|
||||
function readDirectory(path: string, extension?: string, exclude?: string[]): string[] {
|
||||
const result: string[] = [];
|
||||
exclude = map(exclude, s => getCanonicalPath(combinePaths(path, s)));
|
||||
visitDirectory(path, result, extension, exclude);
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -548,7 +522,6 @@ namespace ts {
|
||||
},
|
||||
getDirectories,
|
||||
readDirectory,
|
||||
readDirectoryWithMultipleExtensions,
|
||||
getModifiedTime(path) {
|
||||
try {
|
||||
return _fs.statSync(path).mtime;
|
||||
|
||||
@@ -1670,7 +1670,6 @@ namespace ts {
|
||||
|
||||
export interface ParseConfigHost {
|
||||
readDirectory(rootDir: string, extension: string, exclude: string[]): string[];
|
||||
readDirectoryWithMultipleExtensions?(rootDir: string, extensions: string[], exclude: string[]): string[];
|
||||
}
|
||||
|
||||
export interface WriteFileCallback {
|
||||
|
||||
@@ -1184,12 +1184,10 @@ namespace ts.server {
|
||||
* @param fileContent is a known version of the file content that is more up to date than the one on disk
|
||||
*/
|
||||
openClientFile(fileName: string, fileContent?: string, scriptKind?: ScriptKind): { configFileName?: string, configFileErrors?: Diagnostic[] } {
|
||||
this.log("start openClientFile: " + new Date().getTime());
|
||||
const { configFileName, configFileErrors } = this.openOrUpdateConfiguredProjectForFile(fileName);
|
||||
const info = this.openFile(fileName, /*openedByClient*/ true, fileContent, scriptKind);
|
||||
this.addOpenFile(info);
|
||||
this.printProjects();
|
||||
this.log("end openClientFile: " + new Date().getTime());
|
||||
return { configFileName, configFileErrors };
|
||||
}
|
||||
|
||||
@@ -1199,7 +1197,6 @@ namespace ts.server {
|
||||
* the tsconfig file content and update the project; otherwise we create a new one.
|
||||
*/
|
||||
openOrUpdateConfiguredProjectForFile(fileName: string): { configFileName?: string, configFileErrors?: Diagnostic[] } {
|
||||
this.log("start openOrUpdateConfiguredProjectForFile: " + new Date().getTime());
|
||||
const searchPath = ts.normalizePath(getDirectoryPath(fileName));
|
||||
this.log("Search path: " + searchPath, "Info");
|
||||
const configFileName = this.findConfigFile(searchPath);
|
||||
@@ -1228,7 +1225,6 @@ namespace ts.server {
|
||||
else {
|
||||
this.log("No config files found.");
|
||||
}
|
||||
this.log("end openOrUpdateConfiguredProjectForFile: " + new Date().getTime());
|
||||
return configFileName ? { configFileName } : {};
|
||||
}
|
||||
|
||||
@@ -1368,11 +1364,8 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
openConfigFile(configFilename: string, clientFileName?: string): { success: boolean, project?: Project, errors?: Diagnostic[] } {
|
||||
this.log("start openConfigFile: " + new Date().getTime());
|
||||
const { succeeded, projectOptions, errors } = this.configFileToProjectOptions(configFilename);
|
||||
this.log("finish reading config file: " + new Date().getTime());
|
||||
if (!succeeded) {
|
||||
this.log("finish openConfigFile: " + new Date().getTime());
|
||||
return { success: false, errors };
|
||||
}
|
||||
else {
|
||||
@@ -1408,7 +1401,6 @@ namespace ts.server {
|
||||
path => this.directoryWatchedForSourceFilesChanged(project, path),
|
||||
/*recursive*/ true
|
||||
);
|
||||
this.log("finish openConfigFile: " + new Date().getTime());
|
||||
return { success: true, project: project, errors };
|
||||
}
|
||||
}
|
||||
|
||||
4
src/server/protocol.d.ts
vendored
4
src/server/protocol.d.ts
vendored
@@ -124,8 +124,8 @@ declare namespace ts.server.protocol {
|
||||
*/
|
||||
fileNames?: string[];
|
||||
/**
|
||||
* Indicates if the project has a active language service instance
|
||||
*/
|
||||
* Indicates if the project has a active language service instance
|
||||
*/
|
||||
languageServiceDisabled?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -421,7 +421,6 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
private getProjectInfo(fileName: string, needFileNameList: boolean): protocol.ProjectInfo {
|
||||
this.logger.info("start getProjectInfo:" + new Date().getTime());
|
||||
fileName = ts.normalizePath(fileName);
|
||||
const project = this.projectService.getProjectForFile(fileName);
|
||||
if (!project) {
|
||||
@@ -436,7 +435,6 @@ namespace ts.server {
|
||||
if (needFileNameList) {
|
||||
projectInfo.fileNames = project.getFileNames();
|
||||
}
|
||||
this.logger.info("end getProjectInfo:" + new Date().getTime());
|
||||
return projectInfo;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace ts {
|
||||
interface FileOrFolder {
|
||||
path: string;
|
||||
content?: string;
|
||||
fileSize?: number;
|
||||
}
|
||||
|
||||
interface FSEntry {
|
||||
@@ -34,6 +35,7 @@ namespace ts {
|
||||
|
||||
interface File extends FSEntry {
|
||||
content: string;
|
||||
fileSize?: number;
|
||||
}
|
||||
|
||||
interface Folder extends FSEntry {
|
||||
@@ -157,7 +159,7 @@ namespace ts {
|
||||
const path = this.toPath(fileOrFolder.path);
|
||||
const fullPath = getNormalizedAbsolutePath(fileOrFolder.path, this.currentDirectory);
|
||||
if (typeof fileOrFolder.content === "string") {
|
||||
const entry = { path, content: fileOrFolder.content, fullPath };
|
||||
const entry = { path, content: fileOrFolder.content, fullPath, fileSize: fileOrFolder.fileSize };
|
||||
this.fs.set(path, entry);
|
||||
addFolder(getDirectoryPath(fullPath), this.toPath, this.fs).entries.push(entry);
|
||||
}
|
||||
@@ -172,6 +174,17 @@ namespace ts {
|
||||
return this.fs.contains(path) && isFile(this.fs.get(path));
|
||||
};
|
||||
|
||||
getFileSize(s: string) {
|
||||
const path = this.toPath(s);
|
||||
if (this.fs.contains(path)) {
|
||||
const entry = this.fs.get(path);
|
||||
if (isFile(entry)) {
|
||||
return entry.fileSize ? entry.fileSize : entry.content.length;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
directoryExists(s: string) {
|
||||
const path = this.toPath(s);
|
||||
return this.fs.contains(path) && isFolder(this.fs.get(path));
|
||||
@@ -567,5 +580,38 @@ namespace ts {
|
||||
checkConfiguredProjectActualFiles(project, [file1.path, classicModuleFile.path]);
|
||||
checkNumberOfInferredProjects(projectService, 1);
|
||||
});
|
||||
|
||||
it("should disable language service for project with too many non-ts files", () => {
|
||||
const jsFiles: FileOrFolder[] = [];
|
||||
const configFile: FileOrFolder = {
|
||||
path: `/a/b/jsconfig.json`,
|
||||
content: "{}"
|
||||
};
|
||||
jsFiles.push(configFile);
|
||||
for (let i = 0; i < 1000; i++) {
|
||||
jsFiles.push({
|
||||
path: `/a/b/file${i}.js`,
|
||||
content: "",
|
||||
fileSize: 50000
|
||||
});
|
||||
}
|
||||
|
||||
const host = new TestServerHost(/*useCaseSensitiveFileNames*/ false, getExecutingFilePathFromLibFile(libFile), "/", jsFiles);
|
||||
const projectService = new server.ProjectService(host, nullLogger);
|
||||
projectService.openClientFile(jsFiles[1].path);
|
||||
projectService.openClientFile(jsFiles[2].path);
|
||||
checkNumberOfConfiguredProjects(projectService, 1);
|
||||
checkNumberOfInferredProjects(projectService, 0);
|
||||
|
||||
const project = projectService.configuredProjects[0];
|
||||
assert(project.languageServiceDiabled, "the project's language service is expected to be disabled");
|
||||
|
||||
configFile.content = `{
|
||||
"files": ["/a/b/file1.js", "/a/b/file2.js", "/a/b/file3.js"]
|
||||
}`;
|
||||
host.reloadFS(jsFiles);
|
||||
host.triggerFileWatcherCallback(configFile.path);
|
||||
assert(!project.languageServiceDiabled, "after the config file change, the project's language service is expected to be enabled.");
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user