Merge pull request #14846 from Microsoft/dev/billti/port14809ToMaster
Port 14809 to master
This commit is contained in:
commit
9e8b3d9c3b
4 changed files with 66 additions and 10 deletions
|
@ -1007,6 +1007,41 @@ namespace ts.projectSystem {
|
||||||
checkProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]);
|
checkProjectRootFiles(projectService.configuredProjects[0], [commonFile1.path, commonFile2.path]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should disable features when the files are too large", () => {
|
||||||
|
const file1 = {
|
||||||
|
path: "/a/b/f1.js",
|
||||||
|
content: "let x =1;",
|
||||||
|
fileSize: 10 * 1024 * 1024
|
||||||
|
};
|
||||||
|
const file2 = {
|
||||||
|
path: "/a/b/f2.js",
|
||||||
|
content: "let y =1;",
|
||||||
|
fileSize: 6 * 1024 * 1024
|
||||||
|
};
|
||||||
|
const file3 = {
|
||||||
|
path: "/a/b/f3.js",
|
||||||
|
content: "let y =1;",
|
||||||
|
fileSize: 6 * 1024 * 1024
|
||||||
|
};
|
||||||
|
|
||||||
|
const proj1name = "proj1", proj2name = "proj2", proj3name = "proj3";
|
||||||
|
|
||||||
|
const host = createServerHost([file1, file2, file3]);
|
||||||
|
const projectService = createProjectService(host);
|
||||||
|
|
||||||
|
projectService.openExternalProject({ rootFiles: toExternalFiles([file1.path]), options: {}, projectFileName: proj1name });
|
||||||
|
const proj1 = projectService.findProject(proj1name);
|
||||||
|
assert.isTrue(proj1.languageServiceEnabled);
|
||||||
|
|
||||||
|
projectService.openExternalProject({ rootFiles: toExternalFiles([file2.path]), options: {}, projectFileName: proj2name });
|
||||||
|
const proj2 = projectService.findProject(proj2name);
|
||||||
|
assert.isTrue(proj2.languageServiceEnabled);
|
||||||
|
|
||||||
|
projectService.openExternalProject({ rootFiles: toExternalFiles([file3.path]), options: {}, projectFileName: proj3name });
|
||||||
|
const proj3 = projectService.findProject(proj3name);
|
||||||
|
assert.isFalse(proj3.languageServiceEnabled);
|
||||||
|
});
|
||||||
|
|
||||||
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
|
it("should use only one inferred project if 'useOneInferredProject' is set", () => {
|
||||||
const file1 = {
|
const file1 = {
|
||||||
path: "/a/b/main.ts",
|
path: "/a/b/main.ts",
|
||||||
|
|
|
@ -254,6 +254,7 @@ namespace ts.server {
|
||||||
|
|
||||||
private compilerOptionsForInferredProjects: CompilerOptions;
|
private compilerOptionsForInferredProjects: CompilerOptions;
|
||||||
private compileOnSaveForInferredProjects: boolean;
|
private compileOnSaveForInferredProjects: boolean;
|
||||||
|
private readonly projectToSizeMap: Map<number> = createMap<number>();
|
||||||
private readonly directoryWatchers: DirectoryWatchers;
|
private readonly directoryWatchers: DirectoryWatchers;
|
||||||
private readonly throttledOperations: ThrottledOperations;
|
private readonly throttledOperations: ThrottledOperations;
|
||||||
|
|
||||||
|
@ -563,9 +564,11 @@ namespace ts.server {
|
||||||
switch (project.projectKind) {
|
switch (project.projectKind) {
|
||||||
case ProjectKind.External:
|
case ProjectKind.External:
|
||||||
removeItemFromSet(this.externalProjects, <ExternalProject>project);
|
removeItemFromSet(this.externalProjects, <ExternalProject>project);
|
||||||
|
this.projectToSizeMap.delete((project as ExternalProject).externalProjectName);
|
||||||
break;
|
break;
|
||||||
case ProjectKind.Configured:
|
case ProjectKind.Configured:
|
||||||
removeItemFromSet(this.configuredProjects, <ConfiguredProject>project);
|
removeItemFromSet(this.configuredProjects, <ConfiguredProject>project);
|
||||||
|
this.projectToSizeMap.delete((project as ConfiguredProject).canonicalConfigFilePath);
|
||||||
break;
|
break;
|
||||||
case ProjectKind.Inferred:
|
case ProjectKind.Inferred:
|
||||||
removeItemFromSet(this.inferredProjects, <InferredProject>project);
|
removeItemFromSet(this.inferredProjects, <InferredProject>project);
|
||||||
|
@ -852,10 +855,15 @@ namespace ts.server {
|
||||||
return { success: true, projectOptions, configFileErrors: errors };
|
return { success: true, projectOptions, configFileErrors: errors };
|
||||||
}
|
}
|
||||||
|
|
||||||
private exceededTotalSizeLimitForNonTsFiles<T>(options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader<T>) {
|
private exceededTotalSizeLimitForNonTsFiles<T>(name: string, options: CompilerOptions, fileNames: T[], propertyReader: FilePropertyReader<T>) {
|
||||||
if (options && options.disableSizeLimit || !this.host.getFileSize) {
|
if (options && options.disableSizeLimit || !this.host.getFileSize) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let availableSpace = maxProgramSizeForNonTsFiles;
|
||||||
|
this.projectToSizeMap.set(name, 0);
|
||||||
|
this.projectToSizeMap.forEach(val => (availableSpace -= (val || 0)));
|
||||||
|
|
||||||
let totalNonTsFileSize = 0;
|
let totalNonTsFileSize = 0;
|
||||||
for (const f of fileNames) {
|
for (const f of fileNames) {
|
||||||
const fileName = propertyReader.getFileName(f);
|
const fileName = propertyReader.getFileName(f);
|
||||||
|
@ -864,9 +872,16 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
totalNonTsFileSize += this.host.getFileSize(fileName);
|
totalNonTsFileSize += this.host.getFileSize(fileName);
|
||||||
if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) {
|
if (totalNonTsFileSize > maxProgramSizeForNonTsFiles) {
|
||||||
|
// Keep the size as zero since it's disabled
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (totalNonTsFileSize > availableSpace) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.projectToSizeMap.set(name, totalNonTsFileSize);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,7 +892,7 @@ namespace ts.server {
|
||||||
this,
|
this,
|
||||||
this.documentRegistry,
|
this.documentRegistry,
|
||||||
compilerOptions,
|
compilerOptions,
|
||||||
/*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, files, externalFilePropertyReader),
|
/*languageServiceEnabled*/ !this.exceededTotalSizeLimitForNonTsFiles(projectFileName, compilerOptions, files, externalFilePropertyReader),
|
||||||
options.compileOnSave === undefined ? true : options.compileOnSave);
|
options.compileOnSave === undefined ? true : options.compileOnSave);
|
||||||
|
|
||||||
this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typeAcquisition, /*configFileErrors*/ undefined);
|
this.addFilesToProjectAndUpdateGraph(project, files, externalFilePropertyReader, /*clientFileName*/ undefined, typeAcquisition, /*configFileErrors*/ undefined);
|
||||||
|
@ -897,7 +912,7 @@ namespace ts.server {
|
||||||
}
|
}
|
||||||
|
|
||||||
private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, configFileErrors: Diagnostic[], clientFileName?: string) {
|
private createAndAddConfiguredProject(configFileName: NormalizedPath, projectOptions: ProjectOptions, configFileErrors: Diagnostic[], clientFileName?: string) {
|
||||||
const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
|
const sizeLimitExceeded = this.exceededTotalSizeLimitForNonTsFiles(configFileName, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader);
|
||||||
const project = new ConfiguredProject(
|
const project = new ConfiguredProject(
|
||||||
configFileName,
|
configFileName,
|
||||||
this,
|
this,
|
||||||
|
@ -1050,7 +1065,7 @@ namespace ts.server {
|
||||||
return configFileErrors;
|
return configFileErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.exceededTotalSizeLimitForNonTsFiles(projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) {
|
if (this.exceededTotalSizeLimitForNonTsFiles(project.canonicalConfigFilePath, projectOptions.compilerOptions, projectOptions.files, fileNamePropertyReader)) {
|
||||||
project.setCompilerOptions(projectOptions.compilerOptions);
|
project.setCompilerOptions(projectOptions.compilerOptions);
|
||||||
if (!project.languageServiceEnabled) {
|
if (!project.languageServiceEnabled) {
|
||||||
// language service is already disabled
|
// language service is already disabled
|
||||||
|
@ -1414,7 +1429,7 @@ namespace ts.server {
|
||||||
if (externalProject) {
|
if (externalProject) {
|
||||||
if (!tsConfigFiles) {
|
if (!tsConfigFiles) {
|
||||||
const compilerOptions = convertCompilerOptions(proj.options);
|
const compilerOptions = convertCompilerOptions(proj.options);
|
||||||
if (this.exceededTotalSizeLimitForNonTsFiles(compilerOptions, proj.rootFiles, externalFilePropertyReader)) {
|
if (this.exceededTotalSizeLimitForNonTsFiles(proj.projectFileName, compilerOptions, proj.rootFiles, externalFilePropertyReader)) {
|
||||||
externalProject.disableLanguageService();
|
externalProject.disableLanguageService();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ namespace ts.server {
|
||||||
|
|
||||||
export class ExternalProject extends Project {
|
export class ExternalProject extends Project {
|
||||||
private typeAcquisition: TypeAcquisition;
|
private typeAcquisition: TypeAcquisition;
|
||||||
constructor(externalProjectName: string,
|
constructor(public externalProjectName: string,
|
||||||
projectService: ProjectService,
|
projectService: ProjectService,
|
||||||
documentRegistry: ts.DocumentRegistry,
|
documentRegistry: ts.DocumentRegistry,
|
||||||
compilerOptions: CompilerOptions,
|
compilerOptions: CompilerOptions,
|
||||||
|
|
|
@ -25,8 +25,14 @@ namespace ts.server {
|
||||||
return ((1e9 * seconds) + nanoseconds) / 1000000.0;
|
return ((1e9 * seconds) + nanoseconds) / 1000000.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function shouldSkipSematicCheck(project: Project) {
|
function shouldSkipSemanticCheck(project: Project) {
|
||||||
return (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) && project.isJsOnlyProject();
|
if (project.projectKind === ProjectKind.Inferred || project.projectKind === ProjectKind.External) {
|
||||||
|
return project.isJsOnlyProject();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// For configured projects, require that skipLibCheck be set also
|
||||||
|
return project.getCompilerOptions().skipLibCheck && project.isJsOnlyProject();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FileStart {
|
interface FileStart {
|
||||||
|
@ -447,7 +453,7 @@ namespace ts.server {
|
||||||
private semanticCheck(file: NormalizedPath, project: Project) {
|
private semanticCheck(file: NormalizedPath, project: Project) {
|
||||||
try {
|
try {
|
||||||
let diags: Diagnostic[] = [];
|
let diags: Diagnostic[] = [];
|
||||||
if (!shouldSkipSematicCheck(project)) {
|
if (!shouldSkipSemanticCheck(project)) {
|
||||||
diags = project.getLanguageService().getSemanticDiagnostics(file);
|
diags = project.getLanguageService().getSemanticDiagnostics(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -555,7 +561,7 @@ namespace ts.server {
|
||||||
|
|
||||||
private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
|
private getDiagnosticsWorker(args: protocol.FileRequestArgs, isSemantic: boolean, selector: (project: Project, file: string) => Diagnostic[], includeLinePosition: boolean) {
|
||||||
const { project, file } = this.getFileAndProject(args);
|
const { project, file } = this.getFileAndProject(args);
|
||||||
if (isSemantic && shouldSkipSematicCheck(project)) {
|
if (isSemantic && shouldSkipSemanticCheck(project)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
|
||||||
|
|
Loading…
Reference in a new issue