mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-16 07:13:45 -05:00
Merge pull request #36383 from uniqueiniquity/redirectInfo
Redirect info
This commit is contained in:
@@ -3124,19 +3124,24 @@ namespace ts.server {
|
||||
return result;
|
||||
}
|
||||
|
||||
private collectChanges(lastKnownProjectVersions: protocol.ProjectVersionInfo[], currentProjects: Project[], result: ProjectFilesWithTSDiagnostics[]): void {
|
||||
private collectChanges(
|
||||
lastKnownProjectVersions: protocol.ProjectVersionInfo[],
|
||||
currentProjects: Project[],
|
||||
includeProjectReferenceRedirectInfo: boolean | undefined,
|
||||
result: ProjectFilesWithTSDiagnostics[]
|
||||
): void {
|
||||
for (const proj of currentProjects) {
|
||||
const knownProject = find(lastKnownProjectVersions, p => p.projectName === proj.getProjectName());
|
||||
result.push(proj.getChangesSinceVersion(knownProject && knownProject.version));
|
||||
result.push(proj.getChangesSinceVersion(knownProject && knownProject.version, includeProjectReferenceRedirectInfo));
|
||||
}
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
synchronizeProjectList(knownProjects: protocol.ProjectVersionInfo[]): ProjectFilesWithTSDiagnostics[] {
|
||||
synchronizeProjectList(knownProjects: protocol.ProjectVersionInfo[], includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics[] {
|
||||
const files: ProjectFilesWithTSDiagnostics[] = [];
|
||||
this.collectChanges(knownProjects, this.externalProjects, files);
|
||||
this.collectChanges(knownProjects, arrayFrom(this.configuredProjects.values()), files);
|
||||
this.collectChanges(knownProjects, this.inferredProjects, files);
|
||||
this.collectChanges(knownProjects, this.externalProjects, includeProjectReferenceRedirectInfo, files);
|
||||
this.collectChanges(knownProjects, arrayFrom(this.configuredProjects.values()), includeProjectReferenceRedirectInfo, files);
|
||||
this.collectChanges(knownProjects, this.inferredProjects, includeProjectReferenceRedirectInfo, files);
|
||||
return files;
|
||||
}
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ namespace ts.server {
|
||||
/**
|
||||
* Set of files that was returned from the last call to getChangesSinceVersion.
|
||||
*/
|
||||
private lastReportedFileNames: Map<true> | undefined;
|
||||
private lastReportedFileNames: Map<boolean> | undefined;
|
||||
/**
|
||||
* Last version that was reported.
|
||||
*/
|
||||
@@ -803,6 +803,14 @@ namespace ts.server {
|
||||
return result;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
getFileNamesWithRedirectInfo(includeProjectReferenceRedirectInfo: boolean) {
|
||||
return this.getFileNames().map((fileName): protocol.FileWithProjectReferenceRedirectInfo => ({
|
||||
fileName,
|
||||
isSourceOfProjectReferenceRedirect: includeProjectReferenceRedirectInfo && this.isSourceOfProjectReferenceRedirect(fileName)
|
||||
}));
|
||||
}
|
||||
|
||||
hasConfigFile(configFilePath: NormalizedPath) {
|
||||
if (this.program && this.languageServiceEnabled) {
|
||||
const configFile = this.program.getCompilerOptions().configFile;
|
||||
@@ -1300,7 +1308,15 @@ namespace ts.server {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
getChangesSinceVersion(lastKnownVersion?: number): ProjectFilesWithTSDiagnostics {
|
||||
getChangesSinceVersion(lastKnownVersion?: number, includeProjectReferenceRedirectInfo?: boolean): ProjectFilesWithTSDiagnostics {
|
||||
const includeProjectReferenceRedirectInfoIfRequested =
|
||||
includeProjectReferenceRedirectInfo
|
||||
? (files: Map<boolean>) => arrayFrom(files.entries(), ([fileName, isSourceOfProjectReferenceRedirect]): protocol.FileWithProjectReferenceRedirectInfo => ({
|
||||
fileName,
|
||||
isSourceOfProjectReferenceRedirect
|
||||
}))
|
||||
: (files: Map<boolean>) => arrayFrom(files.keys());
|
||||
|
||||
// Update the graph only if initial configured project load is not pending
|
||||
if (!this.isInitialLoadPending()) {
|
||||
updateProjectIfDirty(this);
|
||||
@@ -1324,35 +1340,75 @@ namespace ts.server {
|
||||
}
|
||||
// compute and return the difference
|
||||
const lastReportedFileNames = this.lastReportedFileNames;
|
||||
const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f));
|
||||
const currentFiles = arrayToSet(this.getFileNames().concat(externalFiles));
|
||||
const externalFiles = this.getExternalFiles().map((f): protocol.FileWithProjectReferenceRedirectInfo => ({
|
||||
fileName: toNormalizedPath(f),
|
||||
isSourceOfProjectReferenceRedirect: false
|
||||
}));
|
||||
const currentFiles = arrayToMap(
|
||||
this.getFileNamesWithRedirectInfo(!!includeProjectReferenceRedirectInfo).concat(externalFiles),
|
||||
info => info.fileName,
|
||||
info => info.isSourceOfProjectReferenceRedirect
|
||||
);
|
||||
|
||||
const added: Map<boolean> = new Map<boolean>();
|
||||
const removed: Map<boolean> = new Map<boolean>();
|
||||
|
||||
const added: string[] = [];
|
||||
const removed: string[] = [];
|
||||
const updated: string[] = updatedFileNames ? arrayFrom(updatedFileNames.keys()) : [];
|
||||
const updatedRedirects: protocol.FileWithProjectReferenceRedirectInfo[] = [];
|
||||
|
||||
forEachKey(currentFiles, id => {
|
||||
if (!lastReportedFileNames.has(id)) {
|
||||
added.push(id);
|
||||
forEachEntry(currentFiles, (isSourceOfProjectReferenceRedirect, fileName) => {
|
||||
if (!lastReportedFileNames.has(fileName)) {
|
||||
added.set(fileName, isSourceOfProjectReferenceRedirect);
|
||||
}
|
||||
else if (includeProjectReferenceRedirectInfo && isSourceOfProjectReferenceRedirect !== lastReportedFileNames.get(fileName)){
|
||||
updatedRedirects.push({
|
||||
fileName,
|
||||
isSourceOfProjectReferenceRedirect
|
||||
});
|
||||
}
|
||||
});
|
||||
forEachKey(lastReportedFileNames, id => {
|
||||
if (!currentFiles.has(id)) {
|
||||
removed.push(id);
|
||||
forEachEntry(lastReportedFileNames, (isSourceOfProjectReferenceRedirect, fileName) => {
|
||||
if (!currentFiles.has(fileName)) {
|
||||
removed.set(fileName, isSourceOfProjectReferenceRedirect);
|
||||
}
|
||||
});
|
||||
this.lastReportedFileNames = currentFiles;
|
||||
this.lastReportedVersion = this.projectProgramVersion;
|
||||
return { info, changes: { added, removed, updated }, projectErrors: this.getGlobalProjectErrors() };
|
||||
return {
|
||||
info,
|
||||
changes: {
|
||||
added: includeProjectReferenceRedirectInfoIfRequested(added),
|
||||
removed: includeProjectReferenceRedirectInfoIfRequested(removed),
|
||||
updated: includeProjectReferenceRedirectInfoIfRequested
|
||||
? updated.map((fileName): protocol.FileWithProjectReferenceRedirectInfo => ({
|
||||
fileName,
|
||||
isSourceOfProjectReferenceRedirect: this.isSourceOfProjectReferenceRedirect(fileName)
|
||||
}))
|
||||
: updated,
|
||||
updatedRedirects: includeProjectReferenceRedirectInfo ? updatedRedirects : undefined
|
||||
},
|
||||
projectErrors: this.getGlobalProjectErrors()
|
||||
};
|
||||
}
|
||||
else {
|
||||
// unknown version - return everything
|
||||
const projectFileNames = this.getFileNames();
|
||||
const externalFiles = this.getExternalFiles().map(f => toNormalizedPath(f));
|
||||
const projectFileNames = this.getFileNamesWithRedirectInfo(!!includeProjectReferenceRedirectInfo);
|
||||
const externalFiles = this.getExternalFiles().map((f): protocol.FileWithProjectReferenceRedirectInfo => ({
|
||||
fileName: toNormalizedPath(f),
|
||||
isSourceOfProjectReferenceRedirect: false
|
||||
}));
|
||||
const allFiles = projectFileNames.concat(externalFiles);
|
||||
this.lastReportedFileNames = arrayToSet(allFiles);
|
||||
this.lastReportedFileNames = arrayToMap(
|
||||
allFiles,
|
||||
info => info.fileName,
|
||||
info => info.isSourceOfProjectReferenceRedirect
|
||||
);
|
||||
this.lastReportedVersion = this.projectProgramVersion;
|
||||
return { info, files: allFiles, projectErrors: this.getGlobalProjectErrors() };
|
||||
return {
|
||||
info,
|
||||
files: includeProjectReferenceRedirectInfo ? allFiles : allFiles.map(f => f.fileName),
|
||||
projectErrors: this.getGlobalProjectErrors()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1324,6 +1324,18 @@ namespace ts.server.protocol {
|
||||
lastFileExceededProgramSize?: string;
|
||||
}
|
||||
|
||||
export interface FileWithProjectReferenceRedirectInfo {
|
||||
/**
|
||||
* Name of file
|
||||
*/
|
||||
fileName: string;
|
||||
|
||||
/**
|
||||
* True if the file is primarily included in a referenced project
|
||||
*/
|
||||
isSourceOfProjectReferenceRedirect: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a set of changes that happen in project
|
||||
*/
|
||||
@@ -1331,15 +1343,20 @@ namespace ts.server.protocol {
|
||||
/**
|
||||
* List of added files
|
||||
*/
|
||||
added: string[];
|
||||
added: string[] | FileWithProjectReferenceRedirectInfo[];
|
||||
/**
|
||||
* List of removed files
|
||||
*/
|
||||
removed: string[];
|
||||
removed: string[] | FileWithProjectReferenceRedirectInfo[];
|
||||
/**
|
||||
* List of updated files
|
||||
*/
|
||||
updated: string[];
|
||||
updated: string[] | FileWithProjectReferenceRedirectInfo[];
|
||||
/**
|
||||
* List of files that have had their project reference redirect status updated
|
||||
* Only provided when the synchronizeProjectList request has includeProjectReferenceRedirectInfo set to true
|
||||
*/
|
||||
updatedRedirects?: FileWithProjectReferenceRedirectInfo[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1357,8 +1374,10 @@ namespace ts.server.protocol {
|
||||
info?: ProjectVersionInfo;
|
||||
/**
|
||||
* List of files in project (might be omitted if current state of project can be computed using only information from 'changes')
|
||||
* This property will have type FileWithProjectReferenceRedirectInfo[] if includeProjectReferenceRedirectInfo is set to true in
|
||||
* the corresponding SynchronizeProjectList request; otherwise, it will have type string[].
|
||||
*/
|
||||
files?: string[];
|
||||
files?: string[] | FileWithProjectReferenceRedirectInfo[];
|
||||
/**
|
||||
* Set of changes in project (omitted if the entire set of files in project should be replaced)
|
||||
*/
|
||||
@@ -1621,6 +1640,11 @@ namespace ts.server.protocol {
|
||||
* List of last known projects
|
||||
*/
|
||||
knownProjects: ProjectVersionInfo[];
|
||||
/**
|
||||
* If true, response specifies whether or not each file in each project
|
||||
* is a source from a project reference redirect
|
||||
*/
|
||||
includeProjectReferenceRedirectInfo?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2265,7 +2265,7 @@ namespace ts.server {
|
||||
return this.requiredResponse(/*response*/ true);
|
||||
},
|
||||
[CommandNames.SynchronizeProjectList]: (request: protocol.SynchronizeProjectListRequest) => {
|
||||
const result = this.projectService.synchronizeProjectList(request.arguments.knownProjects);
|
||||
const result = this.projectService.synchronizeProjectList(request.arguments.knownProjects, request.arguments.includeProjectReferenceRedirectInfo);
|
||||
if (!result.some(p => p.projectErrors && p.projectErrors.length !== 0)) {
|
||||
return this.requiredResponse(result);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user