add test and spit commandLineParser changes to another PR

This commit is contained in:
zhengbli
2016-06-10 01:42:35 -07:00
parent 4383f1a15f
commit e41b10bbc7
7 changed files with 66 additions and 70 deletions

View File

@@ -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")) {

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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 };
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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.");
});
});
}