Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/util/vs/base/common/observableInternal/debugName.ts
13406 views
1
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'
2
3
/*---------------------------------------------------------------------------------------------
4
* Copyright (c) Microsoft Corporation. All rights reserved.
5
* Licensed under the MIT License. See License.txt in the project root for license information.
6
*--------------------------------------------------------------------------------------------*/
7
8
export interface IDebugNameData {
9
/**
10
* The owner object of an observable.
11
* Used for debugging only, such as computing a name for the observable by iterating over the fields of the owner.
12
*/
13
readonly owner?: DebugOwner | undefined;
14
15
/**
16
* A string or function that returns a string that represents the name of the observable.
17
* Used for debugging only.
18
*/
19
readonly debugName?: DebugNameSource | undefined;
20
21
/**
22
* A function that points to the defining function of the object.
23
* Used for debugging only.
24
*/
25
readonly debugReferenceFn?: Function | undefined;
26
}
27
28
export class DebugNameData {
29
constructor(
30
public readonly owner: DebugOwner | undefined,
31
public readonly debugNameSource: DebugNameSource | undefined,
32
public readonly referenceFn: Function | undefined,
33
) { }
34
35
public getDebugName(target: object): string | undefined {
36
return getDebugName(target, this);
37
}
38
}
39
40
/**
41
* The owning object of an observable.
42
* Is only used for debugging purposes, such as computing a name for the observable by iterating over the fields of the owner.
43
*/
44
export type DebugOwner = object | undefined;
45
export type DebugNameSource = string | (() => string | undefined);
46
47
const countPerName = new Map<string, number>();
48
const cachedDebugName = new WeakMap<object, string>();
49
50
export function getDebugName(target: object, data: DebugNameData): string | undefined {
51
const cached = cachedDebugName.get(target);
52
if (cached) {
53
return cached;
54
}
55
56
const dbgName = computeDebugName(target, data);
57
if (dbgName) {
58
let count = countPerName.get(dbgName) ?? 0;
59
count++;
60
countPerName.set(dbgName, count);
61
const result = count === 1 ? dbgName : `${dbgName}#${count}`;
62
cachedDebugName.set(target, result);
63
return result;
64
}
65
return undefined;
66
}
67
68
function computeDebugName(self: object, data: DebugNameData): string | undefined {
69
const cached = cachedDebugName.get(self);
70
if (cached) {
71
return cached;
72
}
73
74
const ownerStr = data.owner ? formatOwner(data.owner) + `.` : '';
75
76
let result: string | undefined;
77
const debugNameSource = data.debugNameSource;
78
if (debugNameSource !== undefined) {
79
if (typeof debugNameSource === 'function') {
80
result = debugNameSource();
81
if (result !== undefined) {
82
return ownerStr + result;
83
}
84
} else {
85
return ownerStr + debugNameSource;
86
}
87
}
88
89
const referenceFn = data.referenceFn;
90
if (referenceFn !== undefined) {
91
result = getFunctionName(referenceFn);
92
if (result !== undefined) {
93
return ownerStr + result;
94
}
95
}
96
97
if (data.owner !== undefined) {
98
const key = findKey(data.owner, self);
99
if (key !== undefined) {
100
return ownerStr + key;
101
}
102
}
103
return undefined;
104
}
105
106
function findKey(obj: object, value: object): string | undefined {
107
for (const key in obj) {
108
if ((obj as Record<string, unknown>)[key] === value) {
109
return key;
110
}
111
}
112
return undefined;
113
}
114
115
const countPerClassName = new Map<string, number>();
116
const ownerId = new WeakMap<object, string>();
117
118
function formatOwner(owner: object): string {
119
const id = ownerId.get(owner);
120
if (id) {
121
return id;
122
}
123
const className = getClassName(owner) ?? 'Object';
124
let count = countPerClassName.get(className) ?? 0;
125
count++;
126
countPerClassName.set(className, count);
127
const result = count === 1 ? className : `${className}#${count}`;
128
ownerId.set(owner, result);
129
return result;
130
}
131
132
export function getClassName(obj: object): string | undefined {
133
const ctor = obj.constructor;
134
if (ctor) {
135
if (ctor.name === 'Object') {
136
return undefined;
137
}
138
return ctor.name;
139
}
140
return undefined;
141
}
142
143
export function getFunctionName(fn: Function): string | undefined {
144
const fnSrc = fn.toString();
145
// Pattern: /** @description ... */
146
const regexp = /\/\*\*\s*@description\s*([^*]*)\*\//;
147
const match = regexp.exec(fnSrc);
148
const result = match ? match[1] : undefined;
149
return result?.trim();
150
}
151
152