forked from irinazheltisheva/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheditor.ts
More file actions
182 lines (143 loc) · 5.71 KB
/
Copy patheditor.ts
File metadata and controls
182 lines (143 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { EditorInput } from 'vs/workbench/common/editor';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
import { IConstructorSignature0, IInstantiationService, BrandedService } from 'vs/platform/instantiation/common/instantiation';
import { insert } from 'vs/base/common/arrays';
import { IDisposable, toDisposable } from 'vs/base/common/lifecycle';
export interface IEditorDescriptor {
getId(): string;
getName(): string;
instantiate(instantiationService: IInstantiationService): EditorPane;
describes(obj: unknown): boolean;
}
export interface IEditorRegistry {
/**
* Registers an editor to the platform for the given input type. The second parameter also supports an
* array of input classes to be passed in. If the more than one editor is registered for the same editor
* input, the input itself will be asked which editor it prefers if this method is provided. Otherwise
* the first editor in the list will be returned.
*
* @param inputDescriptors A set of constructor functions that return an instance of EditorInput for which the
* registered editor should be used for.
*/
registerEditor(descriptor: IEditorDescriptor, inputDescriptors: readonly SyncDescriptor<EditorInput>[]): IDisposable;
/**
* Returns the editor descriptor for the given input or `undefined` if none.
*/
getEditor(input: EditorInput): IEditorDescriptor | undefined;
/**
* Returns the editor descriptor for the given identifier or `undefined` if none.
*/
getEditorById(editorId: string): IEditorDescriptor | undefined;
/**
* Returns an array of registered editors known to the platform.
*/
getEditors(): readonly IEditorDescriptor[];
}
/**
* A lightweight descriptor of an editor. The descriptor is deferred so that heavy editors
* can load lazily in the workbench.
*/
export class EditorDescriptor implements IEditorDescriptor {
static create<Services extends BrandedService[]>(
ctor: { new(...services: Services): EditorPane },
id: string,
name: string
): EditorDescriptor {
return new EditorDescriptor(ctor as IConstructorSignature0<EditorPane>, id, name);
}
constructor(
private readonly ctor: IConstructorSignature0<EditorPane>,
private readonly id: string,
private readonly name: string
) { }
instantiate(instantiationService: IInstantiationService): EditorPane {
return instantiationService.createInstance(this.ctor);
}
getId(): string {
return this.id;
}
getName(): string {
return this.name;
}
describes(obj: unknown): boolean {
return obj instanceof EditorPane && obj.getId() === this.id;
}
}
class EditorRegistry implements IEditorRegistry {
private readonly editors: EditorDescriptor[] = [];
private readonly mapEditorToInputs = new Map<EditorDescriptor, readonly SyncDescriptor<EditorInput>[]>();
registerEditor(descriptor: EditorDescriptor, inputDescriptors: readonly SyncDescriptor<EditorInput>[]): IDisposable {
this.mapEditorToInputs.set(descriptor, inputDescriptors);
const remove = insert(this.editors, descriptor);
return toDisposable(() => {
this.mapEditorToInputs.delete(descriptor);
remove();
});
}
getEditor(input: EditorInput): EditorDescriptor | undefined {
const findEditorDescriptors = (input: EditorInput, byInstanceOf?: boolean): EditorDescriptor[] => {
const matchingDescriptors: EditorDescriptor[] = [];
for (const editor of this.editors) {
const inputDescriptors = this.mapEditorToInputs.get(editor) || [];
for (const inputDescriptor of inputDescriptors) {
const inputClass = inputDescriptor.ctor;
// Direct check on constructor type (ignores prototype chain)
if (!byInstanceOf && input.constructor === inputClass) {
matchingDescriptors.push(editor);
break;
}
// Normal instanceof check
else if (byInstanceOf && input instanceof inputClass) {
matchingDescriptors.push(editor);
break;
}
}
}
// If no descriptors found, continue search using instanceof and prototype chain
if (!byInstanceOf && matchingDescriptors.length === 0) {
return findEditorDescriptors(input, true);
}
if (byInstanceOf) {
return matchingDescriptors;
}
return matchingDescriptors;
};
const descriptors = findEditorDescriptors(input);
if (descriptors.length > 0) {
// Ask the input for its preferred Editor
const preferredEditorId = input.getPreferredEditorId(descriptors.map(d => d.getId()));
if (preferredEditorId) {
return this.getEditorById(preferredEditorId);
}
// Otherwise, first come first serve
return descriptors[0];
}
return undefined;
}
getEditorById(editorId: string): EditorDescriptor | undefined {
return this.editors.find(editor => editor.getId() === editorId);
}
getEditors(): readonly EditorDescriptor[] {
return this.editors.slice(0);
}
getEditorInputs(): SyncDescriptor<EditorInput>[] {
const inputClasses: SyncDescriptor<EditorInput>[] = [];
for (const editor of this.editors) {
const editorInputDescriptors = this.mapEditorToInputs.get(editor);
if (editorInputDescriptors) {
inputClasses.push(...editorInputDescriptors.map(descriptor => descriptor.ctor));
}
}
return inputClasses;
}
}
export const Extensions = {
Editors: 'workbench.contributions.editors'
};
Registry.add(Extensions.Editors, new EditorRegistry());