Skip to content

Commit

Permalink
Refactor without looking continuing to look for tsconfig
Browse files Browse the repository at this point in the history
This handles the config file change to be similar to what happens when file opens
  • Loading branch information
sheetalkamat committed May 9, 2024
1 parent 8bb01ab commit 32dcb7a
Show file tree
Hide file tree
Showing 70 changed files with 1,613 additions and 2,293 deletions.
6 changes: 5 additions & 1 deletion src/harness/projectServiceStateLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ export function patchServiceForStateBaseline(service: ProjectService) {
function baselineProjects(currentMappers: Set<DocumentPositionMapper>) {
const autoImportProviderProjects = [] as AutoImportProviderProject[];
const auxiliaryProjects = [] as AuxiliaryProject[];
const orphanConfiguredProjects = service.getOrphanConfiguredProjects(/*toRetainConfiguredProjects*/ undefined);
const orphanConfiguredProjects = service.getOrphanConfiguredProjects(
/*toRetainConfiguredProjects*/ undefined,
/*openFilesWithRetainedConfiguredProject*/ undefined,
/*externalProjectsRetainingConfiguredProjects*/ undefined,
);
const noOpenRef = (project: Project) => isConfiguredProject(project) && (project.isClosed() || orphanConfiguredProjects.has(project));
return baselineState(
[service.externalProjects, service.configuredProjects, service.inferredProjects, autoImportProviderProjects, auxiliaryProjects],
Expand Down
1,306 changes: 808 additions & 498 deletions src/server/editorServices.ts

Large diffs are not rendered by default.

89 changes: 4 additions & 85 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,12 @@ import {
emptyArray,
Errors,
FileStats,
forEachResolvedProjectReferenceProject,
LogLevel,
ModuleImportResult,
Msg,
NormalizedPath,
PackageJsonWatcher,
projectContainsInfoDirectly,
ProjectOptions,
ProjectReferenceProjectLoadKind,
ProjectService,
ScriptInfo,
ServerHost,
Expand Down Expand Up @@ -2211,7 +2208,7 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
private isDefaultProjectForOpenFiles(): boolean {
return !!forEachEntry(
this.projectService.openFiles,
(_, fileName) => this.projectService.tryGetDefaultProjectForFile(toNormalizedPath(fileName)) === this,
(_projectRootPath, path) => this.projectService.tryGetDefaultProjectForFile(this.projectService.getScriptInfoForPath(path)!) === this,
);
}

Expand Down Expand Up @@ -2376,7 +2373,7 @@ export class InferredProject extends Project {
}

override removeRoot(info: ScriptInfo) {
this.projectService.stopWatchingConfigFilesForInferredProjectRoot(info);
this.projectService.stopWatchingConfigFilesForScriptInfo(info);
super.removeRoot(info);
// Delay toggling to isJsInferredProject = false till we actually need it again
if (!this.isOrphan() && this._isJsInferredProject && info.isJavaScript()) {
Expand All @@ -2400,7 +2397,7 @@ export class InferredProject extends Project {
}

override close() {
forEach(this.getRootScriptInfos(), info => this.projectService.stopWatchingConfigFilesForInferredProjectRoot(info));
forEach(this.getRootScriptInfos(), info => this.projectService.stopWatchingConfigFilesForScriptInfo(info));
super.close();
}

Expand Down Expand Up @@ -2751,9 +2748,6 @@ export class ConfiguredProject extends Project {
/** @internal */
canConfigFileJsonReportNoInputFiles = false;

/** Ref count to the project when opened from external project */
private externalProjectRefCount = 0;

private projectReferences: readonly ProjectReference[] | undefined;

/**
Expand Down Expand Up @@ -2861,8 +2855,7 @@ export class ConfiguredProject extends Project {
case ProgramUpdateLevel.Full:
this.openFileWatchTriggered.clear();
const reason = Debug.checkDefined(this.pendingUpdateReason);
this.pendingUpdateReason = undefined;
this.projectService.reloadConfiguredProject(this, reason, /*clearSemanticCache*/ false);
this.projectService.reloadConfiguredProject(this, reason);
result = true;
break;
default:
Expand Down Expand Up @@ -2986,91 +2979,17 @@ export class ConfiguredProject extends Project {
super.markAsDirty();
}

/** @internal */
addExternalProjectReference() {
this.externalProjectRefCount++;
}

/** @internal */
deleteExternalProjectReference() {
this.externalProjectRefCount--;
}

/** @internal */
isSolution() {
return this.getRootFilesMap().size === 0 &&
!this.canConfigFileJsonReportNoInputFiles;
}

/**
* Find the configured project from the project references in project which contains the info directly
*
* @internal
*/
getDefaultChildProjectFromProjectWithReferences(info: ScriptInfo) {
return forEachResolvedProjectReferenceProject(
this,
info.path,
child =>
projectContainsInfoDirectly(child, info) ?
child :
undefined,
ProjectReferenceProjectLoadKind.Find,
);
}

/**
* Returns true if the project is needed by any of the open script info/external project
*
* @internal
*/
hasOpenRef() {
if (!!this.externalProjectRefCount) {
return true;
}

// Closed project doesnt have any reference
if (this.isClosed()) {
return false;
}

const configFileExistenceInfo = this.projectService.configFileExistenceInfoCache.get(this.canonicalConfigFilePath)!;
if (this.deferredClose) return !!configFileExistenceInfo.openFilesImpactedByConfigFile?.size;
if (this.projectService.hasPendingProjectUpdate(this)) {
// If there is pending update for this project,
// we dont know if this project would be needed by any of the open files impacted by this config file
// In that case keep the project alive if there are open files impacted by this project
return !!configFileExistenceInfo.openFilesImpactedByConfigFile?.size;
}

// If there is no pending update for this project,
// We know exact set of open files that get impacted by this configured project as the files in the project
// The project is referenced only if open files impacted by this project are present in this project
return !!configFileExistenceInfo.openFilesImpactedByConfigFile && forEachEntry(
configFileExistenceInfo.openFilesImpactedByConfigFile,
(_value, infoPath) => {
const info = this.projectService.getScriptInfoForPath(infoPath)!;
return this.containsScriptInfo(info) ||
!!forEachResolvedProjectReferenceProject(
this,
info.path,
child => child.containsScriptInfo(info),
ProjectReferenceProjectLoadKind.Find,
);
},
) || false;
}

/** @internal */
override isOrphan(): boolean {
return !!this.deferredClose;
}

/** @internal */
hasExternalProjectRef() {
return !!this.externalProjectRefCount;
}

getEffectiveTypeRoots() {
return getEffectiveTypeRoots(this.getCompilationSettings(), this) || [];
}
Expand Down
38 changes: 10 additions & 28 deletions src/server/scriptInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import {
AbsolutePositionAndLineText,
ConfiguredProject,
Errors,
ExternalProject,
InferredProject,
isBackgroundProject,
isConfiguredProject,
Expand Down Expand Up @@ -580,18 +579,16 @@ export class ScriptInfo {
case 0:
return Errors.ThrowNoProject();
case 1:
return ensurePrimaryProjectKind(
!isProjectDeferredClose(this.containingProjects[0]) ?
this.containingProjects[0] : undefined,
);
return isProjectDeferredClose(this.containingProjects[0]) || isBackgroundProject(this.containingProjects[0]) ?
Errors.ThrowNoProject() :
this.containingProjects[0];
default:
// If this file belongs to multiple projects, below is the order in which default project is used
// - first external project
// - for open script info, its default configured project during opening is default if info is part of it
// - first configured project of which script info is not a source of project reference redirect
// - first configured project
// - first external project
// - first inferred project
let firstExternalProject: ExternalProject | undefined;
let firstConfiguredProject: ConfiguredProject | undefined;
let firstInferredProject: InferredProject | undefined;
let firstNonSourceOfProjectReferenceRedirect: ConfiguredProject | undefined;
Expand All @@ -614,20 +611,17 @@ export class ScriptInfo {
}
if (!firstConfiguredProject) firstConfiguredProject = project;
}
else if (!firstExternalProject && isExternalProject(project)) {
firstExternalProject = project;
else if (isExternalProject(project)) {
return project;
}
else if (!firstInferredProject && isInferredProject(project)) {
firstInferredProject = project;
}
}
return ensurePrimaryProjectKind(
defaultConfiguredProject ||
firstNonSourceOfProjectReferenceRedirect ||
firstConfiguredProject ||
firstExternalProject ||
firstInferredProject,
);
return (defaultConfiguredProject ||
firstNonSourceOfProjectReferenceRedirect ||
firstConfiguredProject ||
firstInferredProject) ?? Errors.ThrowNoProject();
}
}

Expand Down Expand Up @@ -742,18 +736,6 @@ export class ScriptInfo {
}
}

/**
* Throws an error if `project` is an AutoImportProvider or AuxiliaryProject,
* which are used in the background by other Projects and should never be
* reported as the default project for a ScriptInfo.
*/
function ensurePrimaryProjectKind(project: Project | undefined) {
if (!project || isBackgroundProject(project)) {
return Errors.ThrowNoProject();
}
return project;
}

function failIfInvalidPosition(position: number) {
Debug.assert(typeof position === "number", `Expected position ${position} to be a number.`);
Debug.assert(position >= 0, `Expected position to be non-negative.`);
Expand Down
4 changes: 2 additions & 2 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3190,7 +3190,7 @@ export class Session<TMessage = string> implements EventSender {
return this.requiredResponse(response);
},
[protocol.CommandTypes.OpenExternalProject]: (request: protocol.OpenExternalProjectRequest) => {
this.projectService.openExternalProject(request.arguments, /*print*/ true);
this.projectService.openExternalProject(request.arguments, /*cleanupAfter*/ true);
// TODO: GH#20447 report errors
return this.requiredResponse(/*response*/ true);
},
Expand All @@ -3200,7 +3200,7 @@ export class Session<TMessage = string> implements EventSender {
return this.requiredResponse(/*response*/ true);
},
[protocol.CommandTypes.CloseExternalProject]: (request: protocol.CloseExternalProjectRequest) => {
this.projectService.closeExternalProject(request.arguments.projectFileName, /*print*/ true);
this.projectService.closeExternalProject(request.arguments.projectFileName, /*cleanupAfter*/ true);
// TODO: GH#20447 report errors
return this.requiredResponse(/*response*/ true);
},
Expand Down
2 changes: 1 addition & 1 deletion src/testRunner/unittests/tsserver/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ describe("unittests:: tsserver:: projects::", () => {
};
session.host.baselineHost("Before request");
session.logger.info(`request:${ts.server.stringifyIndented(request)}`);
session.getProjectService().openExternalProject(request.arguments, /*print*/ true);
session.getProjectService().openExternalProject(request.arguments, /*cleanupAfter*/ true);
session.host.baselineHost("After request");
baselineTsserverLogs("projects", "external project including config file", session);
});
Expand Down

0 comments on commit 32dcb7a

Please sign in to comment.