mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-08 07:44:33 +01:00
Improves observable debugging helper
This commit is contained in:
committed by
Henning Dieterichs
parent
331be293ce
commit
f2499f2a67
@@ -95,11 +95,6 @@ export interface IObservableWithChange<T, TChange = unknown> {
|
||||
*/
|
||||
readonly debugName: string;
|
||||
|
||||
/**
|
||||
* ONLY FOR DEBUGGING!
|
||||
*/
|
||||
debugGetDependencyGraph(): string;
|
||||
|
||||
/**
|
||||
* This property captures the type of the change object. Do not use it at runtime!
|
||||
*/
|
||||
|
||||
@@ -40,10 +40,10 @@ import { addLogger, setLogObservableFn } from './logging/logging.js';
|
||||
import { ConsoleObservableLogger, logObservableToConsole } from './logging/consoleObservableLogger.js';
|
||||
import { DevToolsLogger } from './logging/debugger/devToolsLogger.js';
|
||||
import { env } from '../process.js';
|
||||
import { _setDebugGetDependencyGraph } from './observables/baseObservable.js';
|
||||
import { debugGetDependencyGraph } from './logging/debugGetDependencyGraph.js';
|
||||
import { _setDebugGetObservableGraph } from './observables/baseObservable.js';
|
||||
import { debugGetObservableGraph } from './logging/debugGetDependencyGraph.js';
|
||||
|
||||
_setDebugGetDependencyGraph(debugGetDependencyGraph);
|
||||
_setDebugGetObservableGraph(debugGetObservableGraph);
|
||||
setLogObservableFn(logObservableToConsole);
|
||||
|
||||
// Remove "//" in the next line to enable logging
|
||||
|
||||
@@ -10,7 +10,12 @@ import { ObservableValue } from '../observables/observableValue.js';
|
||||
import { AutorunObserver } from '../reactions/autorunImpl.js';
|
||||
import { formatValue } from './consoleObservableLogger.js';
|
||||
|
||||
export function debugGetDependencyGraph(obs: IObservable<any> | IObserver, options?: { debugNamePostProcessor?: (name: string) => string }): string {
|
||||
interface IOptions {
|
||||
type: 'dependencies' | 'observers';
|
||||
debugNamePostProcessor?: (name: string) => string;
|
||||
}
|
||||
|
||||
export function debugGetObservableGraph(obs: IObservable<any> | IObserver, options: IOptions): string {
|
||||
const debugNamePostProcessor = options?.debugNamePostProcessor ?? ((str: string) => str);
|
||||
const info = Info.from(obs, debugNamePostProcessor);
|
||||
if (!info) {
|
||||
@@ -18,10 +23,15 @@ export function debugGetDependencyGraph(obs: IObservable<any> | IObserver, optio
|
||||
}
|
||||
|
||||
const alreadyListed = new Set<IObservable<any> | IObserver>();
|
||||
return formatObservableInfo(info, 0, alreadyListed).trim();
|
||||
|
||||
if (options.type === 'observers') {
|
||||
return formatObservableInfoWithObservers(info, 0, alreadyListed, options).trim();
|
||||
} else {
|
||||
return formatObservableInfoWithDependencies(info, 0, alreadyListed, options).trim();
|
||||
}
|
||||
}
|
||||
|
||||
function formatObservableInfo(info: Info, indentLevel: number, alreadyListed: Set<IObservable<any> | IObserver>): string {
|
||||
function formatObservableInfoWithDependencies(info: Info, indentLevel: number, alreadyListed: Set<IObservable<any> | IObserver>, options: IOptions): string {
|
||||
const indent = '\t\t'.repeat(indentLevel);
|
||||
const lines: string[] = [];
|
||||
|
||||
@@ -40,7 +50,35 @@ function formatObservableInfo(info: Info, indentLevel: number, alreadyListed: Se
|
||||
if (info.dependencies.length > 0) {
|
||||
lines.push(`${indent} dependencies:`);
|
||||
for (const dep of info.dependencies) {
|
||||
lines.push(formatObservableInfo(dep, indentLevel + 1, alreadyListed));
|
||||
const info = Info.from(dep, options.debugNamePostProcessor ?? (name => name)) ?? Info.unknown(dep);
|
||||
lines.push(formatObservableInfoWithDependencies(info, indentLevel + 1, alreadyListed, options));
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
function formatObservableInfoWithObservers(info: Info, indentLevel: number, alreadyListed: Set<IObservable<any> | IObserver>, options: IOptions): string {
|
||||
const indent = '\t\t'.repeat(indentLevel);
|
||||
const lines: string[] = [];
|
||||
|
||||
const isAlreadyListed = alreadyListed.has(info.sourceObj);
|
||||
if (isAlreadyListed) {
|
||||
lines.push(`${indent}* ${info.type} ${info.name} (already listed)`);
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
alreadyListed.add(info.sourceObj);
|
||||
|
||||
lines.push(`${indent}* ${info.type} ${info.name}:`);
|
||||
lines.push(`${indent} value: ${formatValue(info.value, 50)}`);
|
||||
lines.push(`${indent} state: ${info.state}`);
|
||||
|
||||
if (info.observers.length > 0) {
|
||||
lines.push(`${indent} observers:`);
|
||||
for (const observer of info.observers) {
|
||||
const info = Info.from(observer, options.debugNamePostProcessor ?? (name => name)) ?? Info.unknown(observer);
|
||||
lines.push(formatObservableInfoWithObservers(info, indentLevel + 1, alreadyListed, options));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +95,8 @@ class Info {
|
||||
'autorun',
|
||||
undefined,
|
||||
state.stateStr,
|
||||
Array.from(state.dependencies).map(dep => Info.from(dep, debugNamePostProcessor) || Info.unknown(dep))
|
||||
Array.from(state.dependencies),
|
||||
[]
|
||||
);
|
||||
} else if (obs instanceof Derived) {
|
||||
const state = obs.debugGetState();
|
||||
@@ -67,7 +106,8 @@ class Info {
|
||||
'derived',
|
||||
state.value,
|
||||
state.stateStr,
|
||||
Array.from(state.dependencies).map(dep => Info.from(dep, debugNamePostProcessor) || Info.unknown(dep))
|
||||
Array.from(state.dependencies),
|
||||
Array.from(obs.debugGetObservers())
|
||||
);
|
||||
} else if (obs instanceof ObservableValue) {
|
||||
const state = obs.debugGetState();
|
||||
@@ -77,7 +117,8 @@ class Info {
|
||||
'observableValue',
|
||||
state.value,
|
||||
'upToDate',
|
||||
[]
|
||||
[],
|
||||
Array.from(obs.debugGetObservers())
|
||||
);
|
||||
} else if (obs instanceof FromEventObservable) {
|
||||
const state = obs.debugGetState();
|
||||
@@ -87,7 +128,8 @@ class Info {
|
||||
'fromEvent',
|
||||
state.value,
|
||||
state.hasValue ? 'upToDate' : 'initial',
|
||||
[]
|
||||
[],
|
||||
Array.from(obs.debugGetObservers())
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
@@ -100,6 +142,7 @@ class Info {
|
||||
'unknown',
|
||||
undefined,
|
||||
'unknown',
|
||||
[],
|
||||
[]
|
||||
);
|
||||
}
|
||||
@@ -110,6 +153,7 @@ class Info {
|
||||
public readonly type: string,
|
||||
public readonly value: any,
|
||||
public readonly state: string,
|
||||
public readonly dependencies: Info[]
|
||||
public readonly dependencies: (IObservable<any> | IObserver)[],
|
||||
public readonly observers: (IObservable<any> | IObserver)[],
|
||||
) { }
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import { IObservableWithChange, IObserver, IReader, IObservable } from '../base.
|
||||
import { DisposableStore } from '../commonFacade/deps.js';
|
||||
import { DebugLocation } from '../debugLocation.js';
|
||||
import { DebugOwner, getFunctionName } from '../debugName.js';
|
||||
import { debugGetDependencyGraph } from '../logging/debugGetDependencyGraph.js';
|
||||
import { debugGetObservableGraph } from '../logging/debugGetDependencyGraph.js';
|
||||
import { getLogger, logObservable } from '../logging/logging.js';
|
||||
import type { keepObserved, recomputeInitiallyAndOnChange } from '../utils/utils.js';
|
||||
import { derivedOpts } from './derived.js';
|
||||
@@ -31,9 +31,9 @@ export function _setKeepObserved(keepObserved: typeof _keepObserved) {
|
||||
_keepObserved = keepObserved;
|
||||
}
|
||||
|
||||
let _debugGetDependencyGraph: typeof debugGetDependencyGraph;
|
||||
export function _setDebugGetDependencyGraph(debugGetDependencyGraph: typeof _debugGetDependencyGraph) {
|
||||
_debugGetDependencyGraph = debugGetDependencyGraph;
|
||||
let _debugGetObservableGraph: typeof debugGetObservableGraph;
|
||||
export function _setDebugGetObservableGraph(debugGetObservableGraph: typeof _debugGetObservableGraph) {
|
||||
_debugGetObservableGraph = debugGetObservableGraph;
|
||||
}
|
||||
|
||||
export abstract class ConvenientObservable<T, TChange> implements IObservableWithChange<T, TChange> {
|
||||
@@ -128,8 +128,21 @@ export abstract class ConvenientObservable<T, TChange> implements IObservableWit
|
||||
return this.get();
|
||||
}
|
||||
|
||||
debugGetDependencyGraph(): string {
|
||||
return _debugGetDependencyGraph(this);
|
||||
get debug(): DebugHelper {
|
||||
return new DebugHelper(this);
|
||||
}
|
||||
}
|
||||
|
||||
class DebugHelper {
|
||||
constructor(public readonly observable: IObservableWithChange<any, any>) {
|
||||
}
|
||||
|
||||
getDependencyGraph(): string {
|
||||
return _debugGetObservableGraph(this.observable, { type: 'dependencies' });
|
||||
}
|
||||
|
||||
getObserverGraph(): string {
|
||||
return _debugGetObservableGraph(this.observable, { type: 'observers' });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -225,7 +225,8 @@ export function mapObservableArrayCached<TIn, TOut, TKey = TIn>(owner: DebugOwne
|
||||
m = new ArrayMap(map);
|
||||
}
|
||||
}, (reader) => {
|
||||
m.setItems(items.read(reader));
|
||||
const i = items.read(reader);
|
||||
m.setItems(i);
|
||||
return m.getItems();
|
||||
});
|
||||
return self;
|
||||
|
||||
@@ -7,7 +7,7 @@ import assert from 'assert';
|
||||
import { observableValue, derived, autorun } from '../../../common/observable.js';
|
||||
import { ensureNoDisposablesAreLeakedInTestSuite } from '../utils.js';
|
||||
// eslint-disable-next-line local/code-no-deep-import-of-internal
|
||||
import { debugGetDependencyGraph } from '../../../common/observableInternal/logging/debugGetDependencyGraph.js';
|
||||
import { debugGetObservableGraph } from '../../../common/observableInternal/logging/debugGetDependencyGraph.js';
|
||||
|
||||
suite('debug', () => {
|
||||
const ds = ensureNoDisposablesAreLeakedInTestSuite();
|
||||
@@ -50,7 +50,7 @@ suite('debug', () => {
|
||||
|
||||
let idx = 0;
|
||||
assert.deepStrictEqual(
|
||||
debugGetDependencyGraph(myComputed3, { debugNamePostProcessor: name => `name${++idx}` }),
|
||||
debugGetObservableGraph(myComputed3, { type: 'dependencies', debugNamePostProcessor: name => `name${++idx}` }),
|
||||
'* derived name1:\n value: 0\n state: upToDate\n dependencies:\n\t\t* derived name2:\n\t\t value: 0\n\t\t state: upToDate\n\t\t dependencies:\n\t\t\t\t* derived name3:\n\t\t\t\t value: 0\n\t\t\t\t state: upToDate\n\t\t\t\t dependencies:\n\t\t\t\t\t\t* observableValue name4:\n\t\t\t\t\t\t value: 0\n\t\t\t\t\t\t state: upToDate\n\t\t\t\t\t\t* observableValue name5:\n\t\t\t\t\t\t value: 0\n\t\t\t\t\t\t state: upToDate\n\t\t\t\t* observableValue name6 (already listed)\n\t\t\t\t* observableValue name7 (already listed)\n\t\t* observableValue name8 (already listed)\n\t\t* observableValue name9 (already listed)',
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user