Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 130 additions & 29 deletions src/harness/projectServiceStateLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import {
arrayFrom,
compareStringsCaseSensitive,
Debug,
DocumentPositionMapper,
emptyArray,
identity,
identitySourceMapConsumer,
isString,
noop,
SourceMapper,
} from "./_namespaces/ts";
import {
AutoImportProviderProject,
Expand All @@ -30,6 +34,7 @@ interface ProjectData {
isClosed: ReturnType<Project["isClosed"]>;
isOrphan: ReturnType<Project["isOrphan"]>;
noOpenRef: boolean;
documentPositionMappers: SourceMapper["documentPositionMappers"];
autoImportProviderHost: Project["autoImportProviderHost"];
noDtsResolutionProject: Project["noDtsResolutionProject"];
originalConfiguredProjects: Project["originalConfiguredProjects"];
Expand Down Expand Up @@ -66,14 +71,21 @@ export function patchServiceForStateBaseline(service: ProjectService) {

const projects = new Map<Project, ProjectData>();
const scriptInfos = new Map<ScriptInfo, ScriptInfoData>();
const documentPositionMappers = new Map<DocumentPositionMapper, DocumentPositionMapper>();
let nextDocumentPositionMapperId = 1;
const mapperToId = new Map<DocumentPositionMapper, number>();
const logger = service.logger as LoggerWithInMemoryLogs;
service.baseline = title => {
const projectLogs = baselineProjects();
const infoLogs = baselineScriptInfos();
if (projectLogs?.length || infoLogs?.length) {
const currentMappers = new Set<DocumentPositionMapper>();
const projectLogs = baselineProjects(currentMappers);
const infoLogs = baselineScriptInfos(currentMappers);
currentMappers.delete(identitySourceMapConsumer);
const mapperLogs = baselineDocumentPositionMappers(currentMappers);
if (projectLogs?.length || infoLogs?.length || mapperLogs?.length) {
if (title) logger.log(title);
sendLogsToLogger("Projects::", projectLogs);
sendLogsToLogger("ScriptInfos::", infoLogs);
sendLogsToLogger("DocumentPositionMappers::", mapperLogs);
}
};

Expand All @@ -88,7 +100,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
logger.log("");
}

function baselineProjects() {
function baselineProjects(currentMappers: Set<DocumentPositionMapper>) {
const autoImportProviderProjects = [] as AutoImportProviderProject[];
const auxiliaryProjects = [] as AuxiliaryProject[];
return baselineState(
Expand All @@ -97,6 +109,8 @@ export function patchServiceForStateBaseline(service: ProjectService) {
(logs, project, data) => {
if (project.autoImportProviderHost) autoImportProviderProjects.push(project.autoImportProviderHost);
if (project.noDtsResolutionProject) auxiliaryProjects.push(project.noDtsResolutionProject);
const documentMappers = getSourceMapper(project)?.documentPositionMappers;
if (documentMappers) documentMappers.forEach(mapper => currentMappers.add(mapper));
let projectDiff = newOrDeleted(project, projects, data);
const projectPropertyLogs = [] as string[];
projectDiff = printProperty(PrintPropertyWhen.Always, data, "projectStateVersion", project.projectStateVersion, projectDiff, projectPropertyLogs);
Expand All @@ -105,6 +119,15 @@ export function patchServiceForStateBaseline(service: ProjectService) {
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "isClosed", project.isClosed(), projectDiff, projectPropertyLogs);
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "isOrphan", !isBackgroundProject(project) && project.isOrphan(), projectDiff, projectPropertyLogs);
projectDiff = printProperty(PrintPropertyWhen.TruthyOrChangedOrNew, data, "noOpenRef", isConfiguredProject(project) && !project.hasOpenRef(), projectDiff, projectPropertyLogs);
projectDiff = printMapPropertyValue(
PrintPropertyWhen.Changed,
data?.documentPositionMappers,
"documentPositionMappers",
getSourceMapper(project)?.documentPositionMappers,
projectDiff,
projectPropertyLogs,
toStringDocumentPostionMapper,
);
projectDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "autoImportProviderHost", project.autoImportProviderHost, projectDiff, projectPropertyLogs, project.autoImportProviderHost ? project.autoImportProviderHost.projectName : project.autoImportProviderHost);
projectDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "noDtsResolutionProject", project.noDtsResolutionProject, projectDiff, projectPropertyLogs, project.noDtsResolutionProject ? project.noDtsResolutionProject.projectName : project.noDtsResolutionProject);
return printSetPropertyAndCreateStatementLog(
Expand All @@ -129,15 +152,17 @@ export function patchServiceForStateBaseline(service: ProjectService) {
autoImportProviderHost: project.autoImportProviderHost,
noDtsResolutionProject: project.noDtsResolutionProject,
originalConfiguredProjects: project.originalConfiguredProjects && new Set(project.originalConfiguredProjects),
documentPositionMappers: new Map(getSourceMapper(project)?.documentPositionMappers),
}),
);
}

function baselineScriptInfos() {
function baselineScriptInfos(currentMappers: Set<DocumentPositionMapper>) {
return baselineState(
[service.filenameToScriptInfo],
scriptInfos,
(logs, info, data) => {
if (info.documentPositionMapper) currentMappers.add(info.documentPositionMapper);
let infoDiff = newOrDeleted(info, scriptInfos, data);
const infoPropertyLogs = [] as string[];
const isOpen = info.isScriptOpen();
Expand All @@ -147,7 +172,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
infoDiff = printScriptInfoSourceMapFilePath(data, info, infoDiff, infoPropertyLogs);
infoDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "declarationInfoPath", info.declarationInfoPath, infoDiff, infoPropertyLogs);
infoDiff = printSetPropertyValueWorker(PrintPropertyWhen.DefinedOrChangedOrNew, data?.sourceInfos, "sourceInfos", info.sourceInfos, infoDiff, infoPropertyLogs, identity);
infoDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "documentPositionMapper", info.documentPositionMapper, infoDiff, infoPropertyLogs, info.documentPositionMapper ? "DocumentPositionMapper" : undefined);
infoDiff = printProperty(PrintPropertyWhen.DefinedOrChangedOrNew, data, "documentPositionMapper", info.documentPositionMapper, infoDiff, infoPropertyLogs, info.documentPositionMapper ? toStringDocumentPostionMapper(info.documentPositionMapper) : undefined);
let defaultProject: Project | undefined;
try {
if (isOpen) defaultProject = info.getDefaultProject();
Expand Down Expand Up @@ -182,8 +207,28 @@ export function patchServiceForStateBaseline(service: ProjectService) {
);
}

function baselineDocumentPositionMappers(currentMappers: Set<DocumentPositionMapper>) {
const result = baselineState(
[currentMappers],
documentPositionMappers,
(logs, mapper, data) => {
const mapperDiff = newOrDeleted(mapper, documentPositionMappers, data);
logs.push([
`${toStringDocumentPostionMapper(mapper)}${mapperDiff}`,
emptyArray,
]);
return mapperDiff;
},
identity,
);
mapperToId.forEach((_id, mapper) => {
if (!documentPositionMappers.has(mapper)) mapperToId.delete(mapper);
});
return result;
}

function baselineState<T, Data>(
currentCaches: (T[] | Map<any, T>)[],
currentCaches: (T[] | Map<any, T> | Set<T>)[],
dataMap: Map<T, Data>,
printWorker: (logs: StateItemLog[], current: T, data: Data | undefined) => Diff,
toData: (current: T) => Data,
Expand Down Expand Up @@ -235,8 +280,7 @@ export function patchServiceForStateBaseline(service: ProjectService) {
return printPropertyWorker(
printWhen,
value,
!!data && data[key] !== value,
Diff.Change,
!!data && data[key] !== value ? Diff.Change : Diff.None,
dataDiff,
propertyLogs,
`${key}: ${stringValue === undefined ? value : stringValue}`,
Expand All @@ -252,48 +296,92 @@ export function patchServiceForStateBaseline(service: ProjectService) {
propertyLogs: StatePropertyLog[],
toStringPropertyValue: (v: T) => string,
) {
const setPropertyLogs = [] as string[];
let setPropertyDiff = Diff.None;
propertyValue?.forEach(p =>
setPropertyDiff = printPropertyWorker(
return printMapOrSetPropertyValueWorker(
printWhen,
dataValue,
propertyName,
propertyValue,
dataDiff,
propertyLogs,
value => dataDiff !== Diff.New && !dataValue?.has(value) ? Diff.New : Diff.None,
toStringPropertyValue,
);
}

function printMapPropertyValue<T>(
printWhen: PrintPropertyWhen.Changed,
dataValue: Map<string, T> | undefined,
propertyName: string,
propertyValue: Map<string, T> | undefined,
dataDiff: Diff,
propertyLogs: StatePropertyLog[],
toStringPropertyValue: (v: T) => string,
) {
return printMapOrSetPropertyValueWorker(
printWhen,
dataValue,
propertyName,
propertyValue,
dataDiff,
propertyLogs,
(value, key) =>
dataDiff !== Diff.New && dataValue?.get(key) !== value ?
!dataValue?.has(key) ? Diff.New : Diff.Change : Diff.None,
(value, key) => `${key}: ${toStringPropertyValue(value)}`,
);
}

type MapOrSetPropertyKey<T> = T extends Map<infer U, any> ? U : T extends Set<infer U> ? U : never;
type MapOrSetPropertyValue<T> = T extends Map<any, infer U> ? U : T extends Set<infer U> ? U : never;
function printMapOrSetPropertyValueWorker<T extends Map<string, any> | Set<any>>(
printWhen: PrintPropertyWhen.Always | PrintPropertyWhen.DefinedOrChangedOrNew | PrintPropertyWhen.Changed,
dataValue: T | undefined,
propertyName: string,
propertyValue: T | undefined,
dataDiff: Diff,
propertyLogs: StatePropertyLog[],
getPropertyDiff: (value: MapOrSetPropertyValue<T>, key: MapOrSetPropertyKey<T>) => Diff,
toStringPropertyValue: (value: MapOrSetPropertyValue<T>, key: MapOrSetPropertyKey<T>) => string,
) {
// Print changes
const mapPropertyLogs = [] as string[];
let mapPropertyDiff = Diff.None;
propertyValue?.forEach((p, key) =>
mapPropertyDiff = printPropertyWorker(
PrintPropertyWhen.Always,
p,
dataDiff !== Diff.New && !dataValue?.has(p),
Diff.New,
setPropertyDiff,
setPropertyLogs,
` ${toStringPropertyValue(p)}`,
getPropertyDiff(p, key),
mapPropertyDiff,
mapPropertyLogs,
` ${toStringPropertyValue(p, key)}`,
)
);
dataValue?.forEach(p => {
if (propertyValue?.has(p)) return;
setPropertyDiff = Diff.Change;
setPropertyLogs.push(` ${toStringPropertyValue(p)}${Diff.Deleted}`);
dataValue?.forEach((p, key) => {
if (propertyValue?.has(key)) return;
mapPropertyDiff = Diff.Change;
mapPropertyLogs.push(` ${toStringPropertyValue(p, key)}${Diff.Deleted}`);
});
dataDiff = printPropertyWorker(
printWhen,
propertyValue,
!!setPropertyDiff,
Diff.Change,
!!mapPropertyDiff ? Diff.Change : Diff.None,
dataDiff,
propertyLogs,
`${propertyName}: ${propertyValue?.size || 0}`,
);
propertyLogs.push(setPropertyLogs);
if (printWhen !== PrintPropertyWhen.Changed || mapPropertyDiff) propertyLogs.push(mapPropertyLogs);
return dataDiff;
}

function printPropertyWorker(
printWhen: PrintPropertyWhen,
value: any,
propertyChanged: boolean,
propertyChangeDiff: Diff.Change | Diff.New,
propertyDiff: Diff,
dataDiff: Diff,
propertyLogs: StatePropertyLog[],
stringValue: string,
) {
const propertyDiff = propertyChanged ? propertyChangeDiff : Diff.None;
const result = !dataDiff && propertyDiff ? propertyChangeDiff : dataDiff;
const result = !dataDiff && propertyDiff ? Diff.Change : dataDiff;
switch (printWhen) {
case PrintPropertyWhen.Changed:
if (!propertyDiff) return result;
Expand Down Expand Up @@ -365,4 +453,17 @@ export function patchServiceForStateBaseline(service: ProjectService) {
identity,
);
}

function toStringDocumentPostionMapper(documentPositionMapper: DocumentPositionMapper) {
if (documentPositionMapper === identitySourceMapConsumer) return "identitySourceMapConsumer";
let id = mapperToId.get(documentPositionMapper);
if (!id) mapperToId.set(documentPositionMapper, id = nextDocumentPositionMapperId++);
return `DocumentPositionMapper${id}`;
}

function getSourceMapper(project: Project) {
return project.projectKind !== ProjectKind.AutoImportProvider ?
project.getLanguageService(/*ensureSynchronized*/ false)?.getSourceMapper() :
undefined;
}
}
9 changes: 8 additions & 1 deletion src/services/sourcemaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface SourceMapper {
tryGetSourcePosition(info: DocumentPosition): DocumentPosition | undefined;
tryGetGeneratedPosition(info: DocumentPosition): DocumentPosition | undefined;
clearCache(): void;
documentPositionMappers: Map<string, DocumentPositionMapper>;
}

/** @internal */
Expand All @@ -56,7 +57,13 @@ export function getSourceMapper(host: SourceMapperHost): SourceMapper {
const currentDirectory = host.getCurrentDirectory();
const sourceFileLike = new Map<string, SourceFileLike | false>();
const documentPositionMappers = new Map<string, DocumentPositionMapper>();
return { tryGetSourcePosition, tryGetGeneratedPosition, toLineColumnOffset, clearCache };
return {
tryGetSourcePosition,
tryGetGeneratedPosition,
toLineColumnOffset,
clearCache,
documentPositionMappers,
};

function toPath(fileName: string) {
return ts_toPath(fileName, currentDirectory, getCanonicalFileName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ Projects::
/dev/null/inferredProject1* (Inferred) *changed*
projectStateVersion: 1
projectProgramVersion: 1
documentPositionMappers: 1 *changed*
/b.d.ts: identitySourceMapConsumer *new*
noDtsResolutionProject: /dev/null/auxiliaryProject1* *changed*

ScriptInfos::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ Projects::
/dev/null/inferredProject1* (Inferred) *changed*
projectStateVersion: 1
projectProgramVersion: 1
documentPositionMappers: 1 *changed*
/user/users/projects/myproject/node_modules/@types/yargs/callback.d.ts: identitySourceMapConsumer *new*
noDtsResolutionProject: /dev/null/auxiliaryProject1* *changed*

ScriptInfos::
Expand Down Expand Up @@ -377,6 +379,18 @@ Info seq [hh:mm:ss:mss] response:
}
After request

Projects::
/dev/null/auxiliaryProject1* (Auxiliary)
projectStateVersion: 2
projectProgramVersion: 2
/dev/null/inferredProject1* (Inferred) *changed*
projectStateVersion: 1
projectProgramVersion: 1
documentPositionMappers: 2 *changed*
/user/users/projects/myproject/node_modules/@types/yargs/callback.d.ts: identitySourceMapConsumer
/user/users/projects/myproject/node_modules/@types/yargs/index.d.ts: identitySourceMapConsumer *new*
noDtsResolutionProject: /dev/null/auxiliaryProject1*

ScriptInfos::
/a/lib/lib.d.ts
version: Text-1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,8 @@ Projects::
/dev/null/inferredProject1* (Inferred) *changed*
projectStateVersion: 1
projectProgramVersion: 1
documentPositionMappers: 1 *changed*
/user/users/projects/myproject/node_modules/@types/yargs/callback.d.ts: identitySourceMapConsumer *new*
noDtsResolutionProject: /dev/null/auxiliaryProject1* *changed*

ScriptInfos::
Expand Down
Loading