@theia/plugin-ext 1.75.0-next.21 → 1.75.0-next.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/errors.d.ts +1 -14
- package/lib/common/errors.d.ts.map +1 -1
- package/lib/common/errors.js +3 -16
- package/lib/common/errors.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +45 -648
- package/lib/common/plugin-protocol.d.ts.map +1 -1
- package/lib/common/plugin-protocol.js +11 -34
- package/lib/common/plugin-protocol.js.map +1 -1
- package/lib/hosted/browser/worker/plugin-manifest-loader.d.ts.map +1 -1
- package/lib/hosted/browser/worker/plugin-manifest-loader.js +5 -36
- package/lib/hosted/browser/worker/plugin-manifest-loader.js.map +1 -1
- package/lib/hosted/browser/worker/worker-main.js +2 -1
- package/lib/hosted/browser/worker/worker-main.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
- package/lib/hosted/node/hosted-plugin-localization-service.js +4 -68
- package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
- package/lib/hosted/node/plugin-host-rpc.d.ts.map +1 -1
- package/lib/hosted/node/plugin-host-rpc.js +2 -2
- package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
- package/lib/hosted/node/plugin-reader.d.ts.map +1 -1
- package/lib/hosted/node/plugin-reader.js +4 -3
- package/lib/hosted/node/plugin-reader.js.map +1 -1
- package/lib/hosted/node/scanners/grammars-reader.d.ts +3 -2
- package/lib/hosted/node/scanners/grammars-reader.d.ts.map +1 -1
- package/lib/hosted/node/scanners/grammars-reader.js +5 -23
- package/lib/hosted/node/scanners/grammars-reader.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.d.ts +38 -71
- package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +117 -768
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.spec.js +191 -0
- package/lib/hosted/node/scanners/scanner-theia.spec.js.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.js +1 -1
- package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
- package/lib/main/browser/plugin-icon-service.d.ts.map +1 -1
- package/lib/main/browser/plugin-icon-service.js +2 -1
- package/lib/main/browser/plugin-icon-service.js.map +1 -1
- package/lib/main/browser/plugin-icon-theme-service.d.ts.map +1 -1
- package/lib/main/browser/plugin-icon-theme-service.js +2 -1
- package/lib/main/browser/plugin-icon-theme-service.js.map +1 -1
- package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
- package/lib/main/browser/plugin-shared-style.js +2 -1
- package/lib/main/browser/plugin-shared-style.js.map +1 -1
- package/package.json +31 -30
- package/src/common/errors.ts +1 -25
- package/src/common/plugin-protocol.ts +195 -662
- package/src/hosted/browser/worker/plugin-manifest-loader.ts +8 -41
- package/src/hosted/browser/worker/worker-main.ts +2 -1
- package/src/hosted/node/hosted-plugin-localization-service.ts +3 -82
- package/src/hosted/node/plugin-host-rpc.ts +3 -3
- package/src/hosted/node/plugin-reader.ts +4 -3
- package/src/hosted/node/scanners/grammars-reader.ts +14 -23
- package/src/hosted/node/scanners/scanner-theia.spec.ts +225 -1
- package/src/hosted/node/scanners/scanner-theia.ts +204 -881
- package/src/main/browser/plugin-contribution-handler.ts +1 -1
- package/src/main/browser/plugin-icon-service.ts +2 -1
- package/src/main/browser/plugin-icon-theme-service.ts +2 -1
- package/src/main/browser/plugin-shared-style.ts +2 -1
- package/lib/hosted/node/plugin-activation-events.d.ts +0 -7
- package/lib/hosted/node/plugin-activation-events.d.ts.map +0 -1
- package/lib/hosted/node/plugin-activation-events.js +0 -95
- package/lib/hosted/node/plugin-activation-events.js.map +0 -1
- package/lib/hosted/node/plugin-manifest-loader.d.ts +0 -3
- package/lib/hosted/node/plugin-manifest-loader.d.ts.map +0 -1
- package/lib/hosted/node/plugin-manifest-loader.js +0 -34
- package/lib/hosted/node/plugin-manifest-loader.js.map +0 -1
- package/lib/main/node/errors.spec.d.ts +0 -2
- package/lib/main/node/errors.spec.d.ts.map +0 -1
- package/lib/main/node/errors.spec.js +0 -36
- package/lib/main/node/errors.spec.js.map +0 -1
- package/src/hosted/node/plugin-activation-events.ts +0 -112
- package/src/hosted/node/plugin-manifest-loader.ts +0 -32
- package/src/main/node/errors.spec.ts +0 -37
|
@@ -18,151 +18,104 @@
|
|
|
18
18
|
|
|
19
19
|
import { inject, injectable, unmanaged, named } from '@theia/core/shared/inversify';
|
|
20
20
|
import {
|
|
21
|
-
|
|
22
|
-
AutoClosingPairConditional,
|
|
23
|
-
buildFrontendModuleName,
|
|
21
|
+
CustomEditor,
|
|
24
22
|
DebuggerContribution,
|
|
25
|
-
IconThemeContribution,
|
|
26
23
|
IconContribution,
|
|
24
|
+
IconThemeContribution,
|
|
27
25
|
IconUrl,
|
|
28
26
|
Keybinding,
|
|
29
|
-
LanguageConfiguration,
|
|
30
27
|
LanguageContribution,
|
|
28
|
+
Localization,
|
|
31
29
|
Menu,
|
|
32
30
|
PluginCommand,
|
|
33
31
|
PluginContribution,
|
|
34
32
|
PluginEngine,
|
|
33
|
+
PluginEntryPoint,
|
|
35
34
|
PluginLifecycle,
|
|
36
35
|
PluginModel,
|
|
37
36
|
PluginPackage,
|
|
38
37
|
PluginPackageCommand,
|
|
38
|
+
PluginPackageCustomEditor,
|
|
39
39
|
PluginPackageDebuggersContribution,
|
|
40
40
|
PluginPackageKeybinding,
|
|
41
41
|
PluginPackageLanguageContribution,
|
|
42
|
-
|
|
42
|
+
PluginPackageLocalization,
|
|
43
43
|
PluginPackageMenu,
|
|
44
44
|
PluginPackageSubmenu,
|
|
45
|
+
PluginPackageTranslation,
|
|
45
46
|
PluginPackageView,
|
|
46
47
|
PluginPackageViewContainer,
|
|
47
48
|
PluginPackageViewWelcome,
|
|
48
49
|
PluginScanner,
|
|
49
50
|
PluginTaskDefinitionContribution,
|
|
51
|
+
PluginIdentifiers,
|
|
50
52
|
SnippetContribution,
|
|
51
53
|
Submenu,
|
|
54
|
+
TerminalProfile,
|
|
52
55
|
ThemeContribution,
|
|
56
|
+
Translation,
|
|
53
57
|
View,
|
|
54
58
|
ViewContainer,
|
|
55
59
|
ViewWelcome,
|
|
56
|
-
|
|
57
|
-
CustomEditor,
|
|
58
|
-
CustomEditorPriority,
|
|
59
|
-
PluginPackageLocalization,
|
|
60
|
-
Localization,
|
|
61
|
-
PluginPackageTranslation,
|
|
62
|
-
Translation,
|
|
63
|
-
PluginIdentifiers,
|
|
64
|
-
TerminalProfile,
|
|
65
|
-
PluginIconContribution,
|
|
66
|
-
PluginEntryPoint,
|
|
67
|
-
PluginPackageContribution
|
|
60
|
+
WalkthroughContribution,
|
|
68
61
|
} from '../../../common/plugin-protocol';
|
|
69
|
-
import { promises as fs
|
|
62
|
+
import { promises as fs } from 'fs';
|
|
70
63
|
import * as path from 'path';
|
|
71
|
-
import { isObject, isStringArray } from '@theia/core/lib/common/types';
|
|
72
|
-
import { GrammarsReader } from './grammars-reader';
|
|
73
|
-
import { CharacterPair } from '../../../common/plugin-api-rpc';
|
|
74
|
-
import { isENOENT } from '../../../common/errors';
|
|
75
64
|
import * as jsoncparser from 'jsonc-parser';
|
|
76
|
-
import {
|
|
77
|
-
import {
|
|
78
|
-
import { deepClone } from '@theia/core/lib/common/objects';
|
|
79
|
-
import { PreferenceSchema, PreferenceDataProperty } from '@theia/core/lib/common/preferences/preference-schema';
|
|
80
|
-
import { TaskDefinition } from '@theia/task/lib/common/task-protocol';
|
|
81
|
-
import { ColorDefinition } from '@theia/core/lib/common/color';
|
|
82
|
-
import { CSSIcon } from '@theia/core/lib/common/markdown-rendering/icon-utilities';
|
|
65
|
+
import { GrammarsReader } from './grammars-reader';
|
|
66
|
+
import { isENOENT } from '@theia/plugin-utils/lib/common/utils';
|
|
83
67
|
import { PluginUriFactory } from './plugin-uri-factory';
|
|
84
|
-
import { PreferenceScope } from '@theia/core/lib/common/preferences/preference-scope';
|
|
85
68
|
import { ILogger } from '@theia/core';
|
|
69
|
+
import { IJSONSchema } from '@theia/core/lib/common/json-schema';
|
|
70
|
+
import { PreferenceSchema } from '@theia/core/lib/common/preferences/preference-schema';
|
|
71
|
+
import { PreferenceScope } from '@theia/core/lib/common/preferences/preference-scope';
|
|
72
|
+
import { TaskDefinition } from '@theia/task/lib/common/task-protocol';
|
|
73
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
74
|
+
import {
|
|
75
|
+
extractPluginViewsIds as extractPluginViewsIdsShared,
|
|
76
|
+
getScope as getScopeShared,
|
|
77
|
+
normalizeContributions,
|
|
78
|
+
readColors as readColorsShared,
|
|
79
|
+
readCommand as readCommandShared,
|
|
80
|
+
readConfiguration as readConfigurationShared,
|
|
81
|
+
readCustomEditor as readCustomEditorShared,
|
|
82
|
+
readDebugger as readDebuggerShared,
|
|
83
|
+
readIcons as readIconsShared,
|
|
84
|
+
readIconThemes as readIconThemesShared,
|
|
85
|
+
readKeybinding as readKeybindingShared,
|
|
86
|
+
readLanguage as readLanguageShared,
|
|
87
|
+
readMenu as readMenuShared,
|
|
88
|
+
readSnippets as readSnippetsShared,
|
|
89
|
+
readSubmenu as readSubmenuShared,
|
|
90
|
+
readTaskDefinition as readTaskDefinitionShared,
|
|
91
|
+
readLocalization as readLocalizationShared,
|
|
92
|
+
readLocalizations as readLocalizationsShared,
|
|
93
|
+
readTerminals as readTerminalsShared,
|
|
94
|
+
readThemes as readThemesShared,
|
|
95
|
+
readTranslation as readTranslationShared,
|
|
96
|
+
readWalkthroughs as readWalkthroughsShared,
|
|
97
|
+
readView as readViewShared,
|
|
98
|
+
readViewContainer as readViewContainerShared,
|
|
99
|
+
readViewWelcome as readViewWelcomeShared,
|
|
100
|
+
toSchema as toSchemaShared,
|
|
101
|
+
transformIconUrl as transformIconUrlShared,
|
|
102
|
+
} from '@theia/plugin-utils/lib/node/normalize-contributions';
|
|
103
|
+
import type {
|
|
104
|
+
IConfigurationNode,
|
|
105
|
+
NormalizeContributionsContext,
|
|
106
|
+
} from '@theia/plugin-utils/lib/common/contribution-types';
|
|
107
|
+
import type { ColorDefinition } from '@theia/plugin-utils/lib/common/protocol-shims';
|
|
108
|
+
import {
|
|
109
|
+
applyTrustExtraction as applyTrustExtractionShared,
|
|
110
|
+
buildEntryPointForTheia as buildEntryPointForTheiaShared,
|
|
111
|
+
buildLifecycle,
|
|
112
|
+
buildModelForTheia as buildModelForTheiaShared,
|
|
113
|
+
toPluginUrl as toPluginUrlShared
|
|
114
|
+
} from '@theia/plugin-utils/lib/common/plugin-model';
|
|
115
|
+
import { getPluginRootFileUrl as getPluginRootFileUrlShared } from '@theia/plugin-utils/lib/node/plugin-model';
|
|
86
116
|
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
/** Maps the view container locations used by VS Code extensions to the Theia shell locations. */
|
|
91
|
-
const VIEW_CONTAINER_LOCATION_ALIASES: Record<string, string> = {
|
|
92
|
-
activitybar: 'left',
|
|
93
|
-
panel: 'bottom',
|
|
94
|
-
secondarySidebar: 'right',
|
|
95
|
-
auxiliarybar: 'right'
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
function getFileExtension(filePath: string): string {
|
|
99
|
-
const index = filePath.lastIndexOf('.');
|
|
100
|
-
return index === -1 ? '' : filePath.substring(index + 1);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Mirrors VS Code's `ConfigurationRegistry.getDefaultValue(type)`: plugins expect typed-but-defaultless properties to read as a type-based default, not `undefined`.
|
|
105
|
-
*/
|
|
106
|
-
function deriveDefaultForType(type: JsonType | JsonType[] | undefined): JSONValue {
|
|
107
|
-
const t = Array.isArray(type) ? type[0] : type;
|
|
108
|
-
switch (t) {
|
|
109
|
-
case 'boolean': return false;
|
|
110
|
-
case 'integer':
|
|
111
|
-
case 'number': return 0;
|
|
112
|
-
case 'string': return '';
|
|
113
|
-
case 'array': return [];
|
|
114
|
-
case 'object': return {};
|
|
115
|
-
default: return null;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
type PluginPackageWithContributes = PluginPackage & { contributes: PluginPackageContribution };
|
|
120
|
-
|
|
121
|
-
type ScopeString = 'machine-overridable' | 'window' | 'resource' | 'language-overridable' | 'application' | 'machine';
|
|
122
|
-
|
|
123
|
-
type EditPresentationTypes = 'multilineText' | 'singleLineText';
|
|
124
|
-
export interface IConfigurationPropertySchema extends IJSONSchema {
|
|
125
|
-
|
|
126
|
-
scope?: ScopeString;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* When `false` this property is excluded from the registry. Default is to include.
|
|
130
|
-
*/
|
|
131
|
-
included?: boolean;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* List of tags associated to the property.
|
|
135
|
-
* - A tag can be used for filtering
|
|
136
|
-
* - Use `experimental` tag for marking the setting as experimental.
|
|
137
|
-
* - Use `onExP` tag for marking that the default of the setting can be changed by running experiments.
|
|
138
|
-
*/
|
|
139
|
-
tags?: string[];
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* When specified, controls the presentation format of string settings.
|
|
143
|
-
* Otherwise, the presentation format defaults to `singleline`.
|
|
144
|
-
*/
|
|
145
|
-
editPresentation?: EditPresentationTypes;
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* When specified, gives an order number for the setting
|
|
149
|
-
* within the settings editor. Otherwise, the setting is placed at the end.
|
|
150
|
-
*/
|
|
151
|
-
order?: number;
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export interface IExtensionInfo {
|
|
156
|
-
id: string;
|
|
157
|
-
displayName?: string;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
export interface IConfigurationNode {
|
|
161
|
-
title?: string;
|
|
162
|
-
description?: string;
|
|
163
|
-
properties?: Record<string, IConfigurationPropertySchema>;
|
|
164
|
-
scope?: ScopeString;
|
|
165
|
-
}
|
|
117
|
+
/** Async-local contribution ctx — safe for concurrent scans on the singleton scanner. */
|
|
118
|
+
const contributionCtxStorage = new AsyncLocalStorage<NormalizeContributionsContext<PluginPackage>>();
|
|
166
119
|
|
|
167
120
|
@injectable()
|
|
168
121
|
export abstract class AbstractPluginScanner implements PluginScanner {
|
|
@@ -184,34 +137,23 @@ export abstract class AbstractPluginScanner implements PluginScanner {
|
|
|
184
137
|
|
|
185
138
|
getModel(plugin: PluginPackage): PluginModel {
|
|
186
139
|
const publisher = plugin.publisher ?? PluginIdentifiers.UNPUBLISHED;
|
|
187
|
-
const result
|
|
188
|
-
|
|
189
|
-
packageUri: this.pluginUriFactory.createUri(plugin).toString(),
|
|
190
|
-
// see id definition: https://github.com/microsoft/vscode/blob/15916055fe0cb9411a5f36119b3b012458fe0a1d/src/vs/platform/extensions/common/extensions.ts#L167-L169
|
|
191
|
-
id: `${publisher.toLowerCase()}.${plugin.name.toLowerCase()}`,
|
|
192
|
-
name: plugin.name,
|
|
140
|
+
const result = buildModelForTheiaShared({
|
|
141
|
+
...plugin,
|
|
193
142
|
publisher,
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
entryPoint: this.getEntryPoint(plugin),
|
|
203
|
-
licenseUrl: this.getLicenseUrl(plugin),
|
|
204
|
-
readmeUrl: this.getReadmeUrl(plugin)
|
|
205
|
-
};
|
|
143
|
+
packageUri: this.pluginUriFactory.createUri(plugin).toString(),
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
result.engine.type = this._apiType;
|
|
147
|
+
result.engine.version = plugin.engines[this._apiType] ?? '*';
|
|
148
|
+
result.entryPoint = this.getEntryPoint(plugin);
|
|
149
|
+
result.licenseUrl = this.getLicenseUrl(plugin);
|
|
150
|
+
result.readmeUrl = this.getReadmeUrl(plugin);
|
|
206
151
|
this.applyTrustExtraction(plugin, result);
|
|
207
152
|
return result;
|
|
208
153
|
}
|
|
209
154
|
|
|
210
155
|
protected applyTrustExtraction(plugin: PluginPackage, result: PluginModel): void {
|
|
211
|
-
|
|
212
|
-
if (untrustedWorkspacesSupport !== undefined) {
|
|
213
|
-
result.untrustedWorkspacesSupport = untrustedWorkspacesSupport;
|
|
214
|
-
}
|
|
156
|
+
applyTrustExtractionShared(plugin, result);
|
|
215
157
|
}
|
|
216
158
|
|
|
217
159
|
protected getReadmeUrl(plugin: PluginPackage): string | undefined {
|
|
@@ -223,32 +165,16 @@ export abstract class AbstractPluginScanner implements PluginScanner {
|
|
|
223
165
|
}
|
|
224
166
|
|
|
225
167
|
protected getPluginRootFileUrl(plugin: PluginPackage, names: string[]): string | undefined {
|
|
226
|
-
|
|
227
|
-
try {
|
|
228
|
-
const dir = readdirSync(plugin.packagePath, { withFileTypes: true });
|
|
229
|
-
for (const dirent of dir) {
|
|
230
|
-
if (dirent.isFile() && nameSet.has(dirent.name.toLowerCase())) {
|
|
231
|
-
return PluginPackage.toPluginUrl(plugin, dirent.name);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
} catch {
|
|
235
|
-
return undefined;
|
|
236
|
-
}
|
|
168
|
+
return getPluginRootFileUrlShared(plugin, names);
|
|
237
169
|
}
|
|
238
170
|
|
|
239
171
|
protected abstract getEntryPoint(plugin: PluginPackage): PluginEntryPoint;
|
|
240
172
|
|
|
241
173
|
getLifecycle(plugin: PluginPackage): PluginLifecycle {
|
|
242
|
-
const result
|
|
243
|
-
startMethod: 'start',
|
|
244
|
-
stopMethod: 'stop',
|
|
245
|
-
frontendModuleName: buildFrontendModuleName(plugin),
|
|
246
|
-
};
|
|
247
|
-
|
|
174
|
+
const result = buildLifecycle(plugin, 'theiaPlugin');
|
|
248
175
|
if (this._backendInitPath) {
|
|
249
176
|
result.backendInitPath = path.join(__dirname, this._backendInitPath);
|
|
250
177
|
}
|
|
251
|
-
|
|
252
178
|
return result;
|
|
253
179
|
}
|
|
254
180
|
|
|
@@ -270,10 +196,10 @@ export abstract class AbstractPluginScanner implements PluginScanner {
|
|
|
270
196
|
return contributions;
|
|
271
197
|
}
|
|
272
198
|
|
|
273
|
-
return this.readContributions(rawPlugin
|
|
199
|
+
return this.readContributions(rawPlugin, contributions);
|
|
274
200
|
}
|
|
275
201
|
|
|
276
|
-
protected async readContributions(rawPlugin:
|
|
202
|
+
protected async readContributions(rawPlugin: PluginPackage, contributions: PluginContribution): Promise<PluginContribution> {
|
|
277
203
|
return contributions;
|
|
278
204
|
}
|
|
279
205
|
|
|
@@ -289,824 +215,221 @@ export class TheiaPluginScanner extends AbstractPluginScanner {
|
|
|
289
215
|
protected readonly logger: ILogger;
|
|
290
216
|
|
|
291
217
|
protected getEntryPoint(plugin: PluginPackage): PluginEntryPoint {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
218
|
+
return buildEntryPointForTheiaShared(plugin);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static getScope(monacoScope: string | undefined): { scope: PreferenceScope | undefined; overridable: boolean } {
|
|
222
|
+
return getScopeShared(monacoScope);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
protected override async readContributions(rawPlugin: PluginPackage, contributions: PluginContribution): Promise<PluginContribution> {
|
|
226
|
+
const ctx = this.contributionCtx(rawPlugin);
|
|
227
|
+
return contributionCtxStorage.run(ctx, () => normalizeContributions(ctx, contributions));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
protected contributionCtx(pck: PluginPackage): NormalizeContributionsContext<PluginPackage> {
|
|
231
|
+
const active = contributionCtxStorage.getStore();
|
|
232
|
+
if (active?.plugin === pck) {
|
|
233
|
+
return active;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const ctx: NormalizeContributionsContext<PluginPackage> = {
|
|
237
|
+
plugin: pck,
|
|
238
|
+
resolveUrl: relativePath => this.toPluginUrl(pck, relativePath),
|
|
239
|
+
resolveUri: (_plugin, relativePath) => this.pluginUriFactory.createUri(pck, relativePath).toString(),
|
|
240
|
+
onError: (type, err, detail) => this.logger.error(`Could not read '${pck.name}' contribution '${type}'.`, detail, err),
|
|
241
|
+
onWarn: msg => this.logger.warn(msg),
|
|
242
|
+
readJsonFile: filePath => this.readJson(filePath),
|
|
243
|
+
// Route through protected methods so Inversify/subclass overrides still apply.
|
|
244
|
+
transformIconUrl: (plugin, original) => this.transformIconUrl(plugin, original),
|
|
245
|
+
readLocalization: (entry, pluginPath) => this.readLocalization(entry, pluginPath),
|
|
246
|
+
readTranslation: (entry, pluginPath) => this.readTranslation(entry, pluginPath),
|
|
247
|
+
toSchema: definition => this.toSchema(definition),
|
|
248
|
+
readConfiguration: this.readConfiguration.bind(this),
|
|
249
|
+
readCustomEditors: this.readCustomEditors.bind(this),
|
|
250
|
+
readViews: this.readViews.bind(this),
|
|
251
|
+
readKeybinding: this.readKeybinding.bind(this),
|
|
252
|
+
readDebuggers: this.readDebuggers.bind(this),
|
|
253
|
+
readSubmenus: (submenus, plugin) => this.readSubmenus(submenus, plugin),
|
|
254
|
+
readViewsContainers: (containers, plugin) => this.readViewsContainers(containers, plugin),
|
|
255
|
+
readViewsWelcome: (welcome, views) => this.readViewsWelcome(welcome, views),
|
|
256
|
+
readCommand: (command, plugin) => this.readCommand(command, plugin),
|
|
257
|
+
readMenus: menus => this.readMenus(menus),
|
|
258
|
+
readTaskDefinition: (pluginName, definition) => this.readTaskDefinition(pluginName, definition),
|
|
259
|
+
readSnippets: plugin => this.readSnippets(plugin),
|
|
260
|
+
readThemes: plugin => this.readThemes(plugin),
|
|
261
|
+
readIcons: plugin => this.readIcons(plugin),
|
|
262
|
+
readIconThemes: plugin => this.readIconThemes(plugin),
|
|
263
|
+
readColors: plugin => this.readColors(plugin),
|
|
264
|
+
readTerminals: plugin => this.readTerminals(plugin),
|
|
265
|
+
readLocalizations: plugin => this.readLocalizations(plugin),
|
|
266
|
+
readWalkthroughs: plugin => this.readWalkthroughs(plugin),
|
|
267
|
+
readLanguages: (languages, plugin) => this.readLanguages(languages, plugin),
|
|
295
268
|
};
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
static getScope(monacoScope: string | undefined): { scope: PreferenceScope | undefined, overridable: boolean } {
|
|
303
|
-
switch (monacoScope) {
|
|
304
|
-
case 'machine-overridable':
|
|
305
|
-
case 'window':
|
|
306
|
-
case 'resource':
|
|
307
|
-
return { scope: PreferenceScope.Folder, overridable: false };
|
|
308
|
-
case 'language-overridable':
|
|
309
|
-
return { scope: PreferenceScope.Folder, overridable: true };
|
|
310
|
-
case 'application':
|
|
311
|
-
case 'machine':
|
|
312
|
-
return { scope: PreferenceScope.User, overridable: false };
|
|
313
|
-
}
|
|
314
|
-
return { scope: undefined, overridable: false };
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
protected override async readContributions(rawPlugin: PluginPackageWithContributes, contributions: PluginContribution): Promise<PluginContribution> {
|
|
318
|
-
try {
|
|
319
|
-
if (rawPlugin.contributes.configuration) {
|
|
320
|
-
const configurations = Array.isArray(rawPlugin.contributes.configuration) ? rawPlugin.contributes.configuration : [rawPlugin.contributes.configuration];
|
|
321
|
-
const hasMultipleConfigs = configurations.length > 1;
|
|
322
|
-
contributions.configuration = [];
|
|
323
|
-
for (const c of configurations) {
|
|
324
|
-
const config = this.readConfiguration(c, rawPlugin.packagePath);
|
|
325
|
-
if (config) {
|
|
326
|
-
Object.values(config.properties).forEach(property => {
|
|
327
|
-
if (hasMultipleConfigs) {
|
|
328
|
-
// If there are multiple configuration contributions, we need to distinguish them by their title in the settings UI.
|
|
329
|
-
// They are placed directly under the plugin's name in the settings UI.
|
|
330
|
-
property.owner = rawPlugin.displayName;
|
|
331
|
-
property.group = config.title;
|
|
332
|
-
} else {
|
|
333
|
-
// If there's only one configuration contribution, we display the title in the settings UI.
|
|
334
|
-
property.owner = config.title;
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
contributions.configuration.push(config);
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
} catch (err) {
|
|
342
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'configuration'.`, rawPlugin.contributes.configuration, err);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
const configurationDefaults = rawPlugin.contributes.configurationDefaults;
|
|
346
|
-
contributions.configurationDefaults = isObject(configurationDefaults) ? configurationDefaults : undefined;
|
|
347
|
-
|
|
348
|
-
try {
|
|
349
|
-
if (rawPlugin.contributes.submenus) {
|
|
350
|
-
contributions.submenus = this.readSubmenus(rawPlugin.contributes.submenus, rawPlugin);
|
|
351
|
-
}
|
|
352
|
-
} catch (err) {
|
|
353
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'submenus'.`, rawPlugin.contributes.submenus, err);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
try {
|
|
357
|
-
if (rawPlugin.contributes.customEditors) {
|
|
358
|
-
const customEditors = this.readCustomEditors(rawPlugin.contributes.customEditors);
|
|
359
|
-
contributions.customEditors = customEditors;
|
|
360
|
-
}
|
|
361
|
-
} catch (err) {
|
|
362
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'customEditors'.`, rawPlugin.contributes.customEditors, err);
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
try {
|
|
366
|
-
if (rawPlugin.contributes.viewsContainers) {
|
|
367
|
-
const viewsContainers = rawPlugin.contributes.viewsContainers;
|
|
368
|
-
contributions.viewsContainers = {};
|
|
369
|
-
|
|
370
|
-
for (const location of Object.keys(viewsContainers)) {
|
|
371
|
-
const containers = this.readViewsContainers(viewsContainers[location], rawPlugin);
|
|
372
|
-
const loc = VIEW_CONTAINER_LOCATION_ALIASES[location] ?? location;
|
|
373
|
-
if (contributions.viewsContainers[loc]) {
|
|
374
|
-
contributions.viewsContainers[loc] = contributions.viewsContainers[loc].concat(containers);
|
|
375
|
-
} else {
|
|
376
|
-
contributions.viewsContainers[loc] = containers;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
} catch (err) {
|
|
381
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'viewsContainers'.`, rawPlugin.contributes.viewsContainers, err);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
try {
|
|
385
|
-
if (rawPlugin.contributes.views) {
|
|
386
|
-
contributions.views = {};
|
|
387
|
-
|
|
388
|
-
for (const location of Object.keys(rawPlugin.contributes.views)) {
|
|
389
|
-
const views = this.readViews(rawPlugin.contributes.views[location]);
|
|
390
|
-
contributions.views[location] = views;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} catch (err) {
|
|
394
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'views'.`, rawPlugin.contributes.views, err);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
try {
|
|
398
|
-
if (rawPlugin.contributes.viewsWelcome) {
|
|
399
|
-
contributions.viewsWelcome = this.readViewsWelcome(rawPlugin.contributes!.viewsWelcome, rawPlugin.contributes.views);
|
|
400
|
-
}
|
|
401
|
-
} catch (err) {
|
|
402
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'viewsWelcome'.`, rawPlugin.contributes.viewsWelcome, err);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
try {
|
|
406
|
-
const pluginCommands = rawPlugin.contributes.commands;
|
|
407
|
-
if (pluginCommands) {
|
|
408
|
-
const commands = Array.isArray(pluginCommands) ? pluginCommands : [pluginCommands];
|
|
409
|
-
contributions.commands = commands.map(command => this.readCommand(command, rawPlugin));
|
|
410
|
-
}
|
|
411
|
-
} catch (err) {
|
|
412
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'commands'.`, rawPlugin.contributes!.commands, err);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
try {
|
|
416
|
-
if (rawPlugin.contributes.menus) {
|
|
417
|
-
contributions.menus = {};
|
|
418
|
-
|
|
419
|
-
for (const location of Object.keys(rawPlugin.contributes.menus)) {
|
|
420
|
-
const menus = this.readMenus(rawPlugin.contributes.menus[location]);
|
|
421
|
-
contributions.menus[location] = menus;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
} catch (err) {
|
|
425
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'menus'.`, rawPlugin.contributes.menus, err);
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
try {
|
|
429
|
-
if (rawPlugin.contributes.keybindings) {
|
|
430
|
-
const rawKeybindings = Array.isArray(rawPlugin.contributes.keybindings) ? rawPlugin.contributes.keybindings : [rawPlugin.contributes.keybindings];
|
|
431
|
-
contributions.keybindings = rawKeybindings.map(rawKeybinding => this.readKeybinding(rawKeybinding));
|
|
432
|
-
}
|
|
433
|
-
} catch (err) {
|
|
434
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'keybindings'.`, rawPlugin.contributes.keybindings, err);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
try {
|
|
438
|
-
if (rawPlugin.contributes.debuggers) {
|
|
439
|
-
const debuggers = this.readDebuggers(rawPlugin.contributes.debuggers);
|
|
440
|
-
contributions.debuggers = debuggers;
|
|
441
|
-
}
|
|
442
|
-
} catch (err) {
|
|
443
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'debuggers'.`, rawPlugin.contributes.debuggers, err);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
try {
|
|
447
|
-
if (rawPlugin.contributes.taskDefinitions) {
|
|
448
|
-
const definitions = rawPlugin.contributes.taskDefinitions!;
|
|
449
|
-
contributions.taskDefinitions = definitions.map(definitionContribution => this.readTaskDefinition(rawPlugin.name, definitionContribution));
|
|
450
|
-
}
|
|
451
|
-
} catch (err) {
|
|
452
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'taskDefinitions'.`, rawPlugin.contributes.taskDefinitions, err);
|
|
453
|
-
}
|
|
454
|
-
|
|
455
|
-
try {
|
|
456
|
-
contributions.problemMatchers = rawPlugin.contributes.problemMatchers;
|
|
457
|
-
} catch (err) {
|
|
458
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'problemMatchers'.`, rawPlugin.contributes.problemMatchers, err);
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
try {
|
|
462
|
-
contributions.problemPatterns = rawPlugin.contributes.problemPatterns;
|
|
463
|
-
} catch (err) {
|
|
464
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'problemPatterns'.`, rawPlugin.contributes.problemPatterns, err);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
try {
|
|
468
|
-
contributions.resourceLabelFormatters = rawPlugin.contributes.resourceLabelFormatters;
|
|
469
|
-
} catch (err) {
|
|
470
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'resourceLabelFormatters'.`, rawPlugin.contributes.resourceLabelFormatters, err);
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
try {
|
|
474
|
-
contributions.authentication = rawPlugin.contributes.authentication;
|
|
475
|
-
} catch (err) {
|
|
476
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'authentication'.`, rawPlugin.contributes.authentication, err);
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
try {
|
|
480
|
-
contributions.notebooks = rawPlugin.contributes.notebooks;
|
|
481
|
-
} catch (err) {
|
|
482
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'notebooks'.`, rawPlugin.contributes.notebooks, err);
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
try {
|
|
486
|
-
contributions.notebookRenderer = rawPlugin.contributes.notebookRenderer;
|
|
487
|
-
} catch (err) {
|
|
488
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'notebook-renderer'.`, rawPlugin.contributes.notebookRenderer, err);
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
try {
|
|
492
|
-
contributions.notebookPreload = rawPlugin.contributes.notebookPreload;
|
|
493
|
-
} catch (err) {
|
|
494
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'notebooks-preload'.`, rawPlugin.contributes.notebookPreload, err);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
try {
|
|
498
|
-
contributions.snippets = this.readSnippets(rawPlugin);
|
|
499
|
-
} catch (err) {
|
|
500
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'snippets'.`, rawPlugin.contributes!.snippets, err);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
try {
|
|
504
|
-
contributions.themes = this.readThemes(rawPlugin);
|
|
505
|
-
} catch (err) {
|
|
506
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'themes'.`, rawPlugin.contributes.themes, err);
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
try {
|
|
510
|
-
contributions.icons = this.readIcons(rawPlugin);
|
|
511
|
-
} catch (err) {
|
|
512
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'icons'.`, rawPlugin.contributes.icons, err);
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
try {
|
|
516
|
-
contributions.iconThemes = this.readIconThemes(rawPlugin);
|
|
517
|
-
} catch (err) {
|
|
518
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'iconThemes'.`, rawPlugin.contributes.iconThemes, err);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
try {
|
|
522
|
-
contributions.colors = this.readColors(rawPlugin);
|
|
523
|
-
} catch (err) {
|
|
524
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'colors'.`, rawPlugin.contributes.colors, err);
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
try {
|
|
528
|
-
contributions.terminalProfiles = this.readTerminals(rawPlugin);
|
|
529
|
-
} catch (err) {
|
|
530
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'terminals'.`, rawPlugin.contributes.terminal, err);
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
try {
|
|
534
|
-
contributions.localizations = this.readLocalizations(rawPlugin);
|
|
535
|
-
} catch (err) {
|
|
536
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'localizations'.`, rawPlugin.contributes.localizations, err);
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
const [languagesResult, grammarsResult] = await Promise.allSettled([
|
|
540
|
-
rawPlugin.contributes.languages ? this.readLanguages(rawPlugin.contributes.languages, rawPlugin) : undefined,
|
|
541
|
-
rawPlugin.contributes.grammars ? this.grammarsReader.readGrammars(rawPlugin.contributes.grammars, rawPlugin.packagePath) : undefined
|
|
542
|
-
]);
|
|
543
|
-
|
|
544
|
-
if (rawPlugin.contributes.languages) {
|
|
545
|
-
if (languagesResult.status === 'fulfilled') {
|
|
546
|
-
contributions.languages = languagesResult.value;
|
|
547
|
-
} else {
|
|
548
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'languages'.`, rawPlugin.contributes.languages, languagesResult.reason);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
if (rawPlugin.contributes.grammars) {
|
|
553
|
-
if (grammarsResult.status === 'fulfilled') {
|
|
554
|
-
contributions.grammars = grammarsResult.value;
|
|
555
|
-
} else {
|
|
556
|
-
this.logger.error(`Could not read '${rawPlugin.name}' contribution 'grammars'.`, rawPlugin.contributes.grammars, grammarsResult.reason);
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
return contributions;
|
|
269
|
+
ctx.readGrammars = (grammars, pluginPath) => this.grammarsReader.readGrammars(
|
|
270
|
+
grammars,
|
|
271
|
+
pluginPath,
|
|
272
|
+
ctx
|
|
273
|
+
);
|
|
274
|
+
return ctx;
|
|
561
275
|
}
|
|
562
276
|
|
|
563
277
|
protected readTerminals(pck: PluginPackage): TerminalProfile[] | undefined {
|
|
564
|
-
|
|
565
|
-
return undefined;
|
|
566
|
-
}
|
|
567
|
-
return pck.contributes.terminal.profiles.filter(profile => profile.id && profile.title);
|
|
278
|
+
return readTerminalsShared(pck);
|
|
568
279
|
}
|
|
569
280
|
|
|
570
281
|
protected readLocalizations(pck: PluginPackage): Localization[] | undefined {
|
|
571
|
-
|
|
572
|
-
return undefined;
|
|
573
|
-
}
|
|
574
|
-
return pck.contributes.localizations.map(e => this.readLocalization(e, pck.packagePath));
|
|
282
|
+
return readLocalizationsShared(pck, this.contributionCtx(pck));
|
|
575
283
|
}
|
|
576
284
|
|
|
577
|
-
protected readLocalization(
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
localizedLanguageName,
|
|
582
|
-
translations: []
|
|
583
|
-
};
|
|
584
|
-
local.translations = translations.map(e => this.readTranslation(e, pluginPath));
|
|
585
|
-
return local;
|
|
285
|
+
protected readLocalization(entry: PluginPackageLocalization, pluginPath: string): Localization {
|
|
286
|
+
return readLocalizationShared(entry, pluginPath, {
|
|
287
|
+
readTranslation: (translation, translationPath) => this.readTranslation(translation, translationPath),
|
|
288
|
+
});
|
|
586
289
|
}
|
|
587
290
|
|
|
588
291
|
protected readTranslation(packageTranslation: PluginPackageTranslation, pluginPath: string): Translation {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
return
|
|
292
|
+
return readTranslationShared(packageTranslation, pluginPath);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
protected readWalkthroughs(pck: PluginPackage): WalkthroughContribution[] | undefined {
|
|
296
|
+
return readWalkthroughsShared(pck, this.contributionCtx(pck));
|
|
594
297
|
}
|
|
595
298
|
|
|
596
|
-
protected readCommand(
|
|
597
|
-
|
|
598
|
-
return { command, title, shortTitle, originalTitle: original, category, iconUrl, themeIcon, enablement };
|
|
299
|
+
protected readCommand(command: PluginPackageCommand, pck: PluginPackage): PluginCommand {
|
|
300
|
+
return readCommandShared(this.contributionCtx(pck), command, pck);
|
|
599
301
|
}
|
|
600
302
|
|
|
601
303
|
protected transformIconUrl(plugin: PluginPackage, original?: IconUrl): { iconUrl?: IconUrl; themeIcon?: string } | undefined {
|
|
602
|
-
|
|
603
|
-
if (typeof original === 'string') {
|
|
604
|
-
if (original.startsWith('$(')) {
|
|
605
|
-
return { themeIcon: original };
|
|
606
|
-
} else {
|
|
607
|
-
return { iconUrl: this.toPluginUrl(plugin, original) };
|
|
608
|
-
}
|
|
609
|
-
} else {
|
|
610
|
-
return {
|
|
611
|
-
iconUrl: {
|
|
612
|
-
light: this.toPluginUrl(plugin, original.light),
|
|
613
|
-
dark: this.toPluginUrl(plugin, original.dark)
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
}
|
|
617
|
-
}
|
|
304
|
+
return transformIconUrlShared(this.contributionCtx(plugin), plugin, original);
|
|
618
305
|
}
|
|
619
306
|
|
|
620
307
|
protected toPluginUrl(pck: PluginPackage, relativePath: string): string {
|
|
621
|
-
return
|
|
308
|
+
return toPluginUrlShared(pck, relativePath);
|
|
622
309
|
}
|
|
623
310
|
|
|
624
311
|
protected readColors(pck: PluginPackage): ColorDefinition[] | undefined {
|
|
625
|
-
|
|
626
|
-
return undefined;
|
|
627
|
-
}
|
|
628
|
-
const result: ColorDefinition[] = [];
|
|
629
|
-
for (const contribution of pck.contributes.colors) {
|
|
630
|
-
if (typeof contribution.id !== 'string' || contribution.id.length === 0) {
|
|
631
|
-
this.logger.error("'configuration.colors.id' must be defined and can not be empty");
|
|
632
|
-
continue;
|
|
633
|
-
}
|
|
634
|
-
if (!contribution.id.match(colorIdPattern)) {
|
|
635
|
-
this.logger.error("'configuration.colors.id' must follow the word[.word]*");
|
|
636
|
-
continue;
|
|
637
|
-
}
|
|
638
|
-
if (typeof contribution.description !== 'string' || contribution.id.length === 0) {
|
|
639
|
-
this.logger.error("'configuration.colors.description' must be defined and can not be empty");
|
|
640
|
-
continue;
|
|
641
|
-
}
|
|
642
|
-
const defaults = contribution.defaults;
|
|
643
|
-
if (!defaults || typeof defaults !== 'object' || typeof defaults.light !== 'string' || typeof defaults.dark !== 'string' || typeof defaults.highContrast !== 'string') {
|
|
644
|
-
this.logger.error("'configuration.colors.defaults' must be defined and must contain 'light', 'dark' and 'highContrast'");
|
|
645
|
-
continue;
|
|
646
|
-
}
|
|
647
|
-
result.push({
|
|
648
|
-
id: contribution.id,
|
|
649
|
-
description: contribution.description,
|
|
650
|
-
defaults: {
|
|
651
|
-
light: defaults.light,
|
|
652
|
-
dark: defaults.dark,
|
|
653
|
-
hc: defaults.highContrast
|
|
654
|
-
}
|
|
655
|
-
});
|
|
656
|
-
}
|
|
657
|
-
return result;
|
|
312
|
+
return readColorsShared(this.contributionCtx(pck), pck);
|
|
658
313
|
}
|
|
659
314
|
|
|
660
315
|
protected readThemes(pck: PluginPackage): ThemeContribution[] | undefined {
|
|
661
|
-
|
|
662
|
-
return undefined;
|
|
663
|
-
}
|
|
664
|
-
const result: ThemeContribution[] = [];
|
|
665
|
-
for (const contribution of pck.contributes.themes) {
|
|
666
|
-
if (contribution.path) {
|
|
667
|
-
result.push({
|
|
668
|
-
id: contribution.id,
|
|
669
|
-
uri: this.pluginUriFactory.createUri(pck, contribution.path).toString(),
|
|
670
|
-
description: contribution.description,
|
|
671
|
-
label: contribution.label,
|
|
672
|
-
uiTheme: contribution.uiTheme
|
|
673
|
-
});
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
return result;
|
|
316
|
+
return readThemesShared(this.contributionCtx(pck), pck);
|
|
677
317
|
}
|
|
678
318
|
|
|
679
319
|
protected readIconThemes(pck: PluginPackage): IconThemeContribution[] | undefined {
|
|
680
|
-
|
|
681
|
-
return undefined;
|
|
682
|
-
}
|
|
683
|
-
const result: IconThemeContribution[] = [];
|
|
684
|
-
for (const contribution of pck.contributes.iconThemes) {
|
|
685
|
-
if (typeof contribution.id !== 'string') {
|
|
686
|
-
this.logger.error('Expected string in `contributes.iconThemes.id`. Provided value:', contribution.id);
|
|
687
|
-
continue;
|
|
688
|
-
}
|
|
689
|
-
if (typeof contribution.path !== 'string') {
|
|
690
|
-
this.logger.error('Expected string in `contributes.iconThemes.path`. Provided value:', contribution.path);
|
|
691
|
-
continue;
|
|
692
|
-
}
|
|
693
|
-
result.push({
|
|
694
|
-
id: contribution.id,
|
|
695
|
-
uri: this.pluginUriFactory.createUri(pck, contribution.path).toString(),
|
|
696
|
-
description: contribution.description,
|
|
697
|
-
label: contribution.label,
|
|
698
|
-
uiTheme: contribution.uiTheme
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
return result;
|
|
320
|
+
return readIconThemesShared(this.contributionCtx(pck), pck);
|
|
702
321
|
}
|
|
703
322
|
|
|
704
323
|
protected readIcons(pck: PluginPackage): IconContribution[] | undefined {
|
|
705
|
-
|
|
706
|
-
return undefined;
|
|
707
|
-
}
|
|
708
|
-
const result: IconContribution[] = [];
|
|
709
|
-
const iconEntries = <PluginIconContribution>(<unknown>pck.contributes.icons);
|
|
710
|
-
for (const id in iconEntries) {
|
|
711
|
-
if (pck.contributes.icons.hasOwnProperty(id)) {
|
|
712
|
-
if (!id.match(iconIdPattern)) {
|
|
713
|
-
this.logger.error("'configuration.icons' keys represent the icon id and can only contain letter, digits and minuses. " +
|
|
714
|
-
'They need to consist of at least two segments in the form `component-iconname`.', 'extension: ', pck.name, 'icon id: ', id);
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
|
-
const iconContribution = iconEntries[id];
|
|
718
|
-
if (typeof iconContribution.description !== 'string' || iconContribution.description['length'] === 0) {
|
|
719
|
-
this.logger.error('configuration.icons.description must be defined and can not be empty, ', 'extension: ', pck.name, 'icon id: ', id);
|
|
720
|
-
return;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
const defaultIcon = iconContribution.default;
|
|
724
|
-
if (typeof defaultIcon === 'string') {
|
|
725
|
-
result.push({
|
|
726
|
-
id,
|
|
727
|
-
extensionId: pck.publisher + '.' + pck.name,
|
|
728
|
-
description: iconContribution.description,
|
|
729
|
-
defaults: { id: defaultIcon }
|
|
730
|
-
});
|
|
731
|
-
} else if (typeof defaultIcon === 'object' && typeof defaultIcon.fontPath === 'string' && typeof defaultIcon.fontCharacter === 'string') {
|
|
732
|
-
const format = getFileExtension(defaultIcon.fontPath);
|
|
733
|
-
if (['woff', 'woff2', 'ttf'].indexOf(format) === -1) {
|
|
734
|
-
this.logger.warn("Expected `contributes.icons.default.fontPath` to have file extension 'woff', woff2' or 'ttf', is '{0}'.", format);
|
|
735
|
-
return;
|
|
736
|
-
}
|
|
737
|
-
|
|
738
|
-
const iconFontLocation = this.pluginUriFactory.createUri(pck, defaultIcon.fontPath).toString();
|
|
739
|
-
result.push({
|
|
740
|
-
id,
|
|
741
|
-
extensionId: pck.publisher + '.' + pck.name,
|
|
742
|
-
description: iconContribution.description,
|
|
743
|
-
defaults: {
|
|
744
|
-
fontCharacter: defaultIcon.fontCharacter,
|
|
745
|
-
location: iconFontLocation
|
|
746
|
-
}
|
|
747
|
-
});
|
|
748
|
-
} else {
|
|
749
|
-
this.logger.error("'configuration.icons.default' must be either a reference to the id of an other theme icon (string) or a icon definition (object) with ",
|
|
750
|
-
'properties `fontPath` and `fontCharacter`.');
|
|
751
|
-
}
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
return result;
|
|
324
|
+
return readIconsShared(this.contributionCtx(pck), pck);
|
|
755
325
|
}
|
|
756
326
|
|
|
757
327
|
protected readSnippets(pck: PluginPackage): SnippetContribution[] | undefined {
|
|
758
|
-
|
|
759
|
-
return undefined;
|
|
760
|
-
}
|
|
761
|
-
const result: SnippetContribution[] = [];
|
|
762
|
-
for (const contribution of pck.contributes.snippets) {
|
|
763
|
-
if (contribution.path) {
|
|
764
|
-
result.push({
|
|
765
|
-
language: contribution.language,
|
|
766
|
-
source: pck.displayName || pck.name,
|
|
767
|
-
uri: this.pluginUriFactory.createUri(pck, contribution.path).toString()
|
|
768
|
-
});
|
|
769
|
-
}
|
|
770
|
-
}
|
|
771
|
-
return result;
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
protected async readJson<T>(filePath: string): Promise<T | undefined> {
|
|
775
|
-
const content = await this.readFile(filePath);
|
|
776
|
-
return content ? jsoncparser.parse(content, undefined, { disallowComments: false }) : undefined;
|
|
777
|
-
}
|
|
778
|
-
protected async readFile(filePath: string): Promise<string> {
|
|
779
|
-
try {
|
|
780
|
-
const content = await fs.readFile(filePath, { encoding: 'utf8' });
|
|
781
|
-
return content;
|
|
782
|
-
} catch (e) {
|
|
783
|
-
if (!isENOENT(e)) {
|
|
784
|
-
this.logger.error(e);
|
|
785
|
-
}
|
|
786
|
-
return '';
|
|
787
|
-
}
|
|
328
|
+
return readSnippetsShared(this.contributionCtx(pck), pck);
|
|
788
329
|
}
|
|
789
330
|
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
const { scope, overridable } = TheiaPluginScanner.getScope(rawConfiguration.scope);
|
|
793
|
-
const schema: PreferenceSchema = {
|
|
794
|
-
scope,
|
|
795
|
-
defaultOverridable: overridable,
|
|
796
|
-
title: rawConfiguration.title,
|
|
797
|
-
properties: {}
|
|
798
|
-
};
|
|
799
|
-
|
|
800
|
-
if (rawConfiguration.properties) {
|
|
801
|
-
for (const [key, property] of Object.entries(rawConfiguration.properties)) {
|
|
802
|
-
const scopeInfo = TheiaPluginScanner.getScope(property.scope);
|
|
803
|
-
const schemaProperty: PreferenceDataProperty = {
|
|
804
|
-
...property,
|
|
805
|
-
scope: scopeInfo.scope,
|
|
806
|
-
overridable: scopeInfo.overridable,
|
|
807
|
-
default: property.default !== undefined ? property.default : deriveDefaultForType(property.type)
|
|
808
|
-
};
|
|
809
|
-
|
|
810
|
-
schema.properties[key] = schemaProperty;
|
|
811
|
-
}
|
|
812
|
-
}
|
|
813
|
-
return schema;
|
|
331
|
+
protected readConfiguration(rawConfiguration: IConfigurationNode, pluginPath: string): PreferenceSchema | undefined {
|
|
332
|
+
return readConfigurationShared(rawConfiguration, pluginPath);
|
|
814
333
|
}
|
|
815
334
|
|
|
816
|
-
|
|
817
|
-
return
|
|
818
|
-
keybinding: rawKeybinding.key,
|
|
819
|
-
command: rawKeybinding.command,
|
|
820
|
-
when: rawKeybinding.when,
|
|
821
|
-
mac: rawKeybinding.mac,
|
|
822
|
-
linux: rawKeybinding.linux,
|
|
823
|
-
win: rawKeybinding.win,
|
|
824
|
-
args: rawKeybinding.args
|
|
825
|
-
};
|
|
335
|
+
protected readKeybinding(rawKeybinding: PluginPackageKeybinding): Keybinding {
|
|
336
|
+
return readKeybindingShared(rawKeybinding);
|
|
826
337
|
}
|
|
827
338
|
|
|
828
|
-
|
|
339
|
+
protected readCustomEditors(rawCustomEditors: PluginPackageCustomEditor[]): CustomEditor[] {
|
|
829
340
|
return rawCustomEditors.map(rawCustomEditor => this.readCustomEditor(rawCustomEditor));
|
|
830
341
|
}
|
|
831
342
|
|
|
832
|
-
|
|
833
|
-
return
|
|
834
|
-
viewType: rawCustomEditor.viewType,
|
|
835
|
-
displayName: rawCustomEditor.displayName,
|
|
836
|
-
selector: rawCustomEditor.selector || [],
|
|
837
|
-
priority: rawCustomEditor.priority || CustomEditorPriority.default
|
|
838
|
-
};
|
|
343
|
+
protected readCustomEditor(rawCustomEditor: PluginPackageCustomEditor): CustomEditor {
|
|
344
|
+
return readCustomEditorShared(rawCustomEditor);
|
|
839
345
|
}
|
|
840
346
|
|
|
841
|
-
|
|
842
|
-
return rawViewsContainers
|
|
347
|
+
protected readViewsContainers(rawViewsContainers: readonly PluginPackageViewContainer[], pck: PluginPackage): ViewContainer[] {
|
|
348
|
+
return rawViewsContainers
|
|
349
|
+
.map(rawViewContainer => this.readViewContainer(rawViewContainer, pck))
|
|
350
|
+
.filter((container): container is ViewContainer => container !== undefined);
|
|
843
351
|
}
|
|
844
352
|
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
const iconUrl = this.toPluginUrl(pck, rawViewContainer.icon);
|
|
848
|
-
return {
|
|
849
|
-
id: rawViewContainer.id,
|
|
850
|
-
title: rawViewContainer.title,
|
|
851
|
-
iconUrl,
|
|
852
|
-
themeIcon,
|
|
853
|
-
when: rawViewContainer.when,
|
|
854
|
-
};
|
|
353
|
+
protected readViewContainer(rawViewContainer: PluginPackageViewContainer, pck: PluginPackage): ViewContainer | undefined {
|
|
354
|
+
return readViewContainerShared(this.contributionCtx(pck), rawViewContainer, pck);
|
|
855
355
|
}
|
|
856
356
|
|
|
857
|
-
|
|
357
|
+
protected readViews(rawViews: PluginPackageView[]): View[] {
|
|
858
358
|
return rawViews.map(rawView => this.readView(rawView));
|
|
859
359
|
}
|
|
860
360
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
id: rawView.id,
|
|
864
|
-
name: rawView.name,
|
|
865
|
-
when: rawView.when,
|
|
866
|
-
type: rawView.type
|
|
867
|
-
};
|
|
868
|
-
|
|
869
|
-
return result;
|
|
361
|
+
protected readView(rawView: PluginPackageView): View {
|
|
362
|
+
return readViewShared(rawView);
|
|
870
363
|
}
|
|
871
364
|
|
|
872
|
-
|
|
365
|
+
protected readViewsWelcome(rawViewsWelcome: readonly PluginPackageViewWelcome[], rowViews: { [location: string]: readonly PluginPackageView[]; } | undefined): ViewWelcome[] {
|
|
873
366
|
return rawViewsWelcome.map(rawViewWelcome => this.readViewWelcome(rawViewWelcome, this.extractPluginViewsIds(rowViews)));
|
|
874
367
|
}
|
|
875
368
|
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
view: rawViewWelcome.view,
|
|
879
|
-
content: rawViewWelcome.contents,
|
|
880
|
-
when: rawViewWelcome.when,
|
|
881
|
-
enablement: rawViewWelcome.enablement,
|
|
882
|
-
// if the plugin contributes Welcome view to its own view - it will be ordered first
|
|
883
|
-
order: pluginViewsIds.findIndex(v => v === rawViewWelcome.view) > -1 ? 0 : 1
|
|
884
|
-
};
|
|
885
|
-
|
|
886
|
-
return result;
|
|
369
|
+
protected readViewWelcome(rawViewWelcome: PluginPackageViewWelcome, pluginViewsIds: string[]): ViewWelcome {
|
|
370
|
+
return readViewWelcomeShared(rawViewWelcome, pluginViewsIds);
|
|
887
371
|
}
|
|
888
372
|
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
if (views) {
|
|
892
|
-
for (const location of Object.keys(views)) {
|
|
893
|
-
const viewsIds = views[location].map(view => view.id);
|
|
894
|
-
pluginViewsIds.push(...viewsIds);
|
|
895
|
-
};
|
|
896
|
-
}
|
|
897
|
-
return pluginViewsIds;
|
|
373
|
+
protected extractPluginViewsIds(views: { [location: string]: readonly PluginPackageView[] } | undefined): string[] {
|
|
374
|
+
return extractPluginViewsIdsShared(views);
|
|
898
375
|
}
|
|
899
376
|
|
|
900
|
-
|
|
377
|
+
protected readMenus(rawMenus: readonly PluginPackageMenu[]): Menu[] {
|
|
901
378
|
return rawMenus.map(rawMenu => this.readMenu(rawMenu));
|
|
902
379
|
}
|
|
903
380
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
command: rawMenu.command,
|
|
907
|
-
submenu: rawMenu.submenu,
|
|
908
|
-
alt: rawMenu.alt,
|
|
909
|
-
group: rawMenu.group,
|
|
910
|
-
when: rawMenu.when
|
|
911
|
-
};
|
|
912
|
-
return result;
|
|
381
|
+
protected readMenu(rawMenu: PluginPackageMenu): Menu {
|
|
382
|
+
return readMenuShared(rawMenu);
|
|
913
383
|
}
|
|
914
384
|
|
|
915
|
-
|
|
385
|
+
protected async readLanguages(rawLanguages: readonly PluginPackageLanguageContribution[], plugin: PluginPackage): Promise<LanguageContribution[]> {
|
|
916
386
|
return Promise.all(rawLanguages.map(language => this.readLanguage(language, plugin)));
|
|
917
387
|
}
|
|
918
388
|
|
|
919
|
-
|
|
389
|
+
protected readSubmenus(rawSubmenus: readonly PluginPackageSubmenu[], plugin: PluginPackage): Submenu[] {
|
|
920
390
|
return rawSubmenus.map(submenu => this.readSubmenu(submenu, plugin));
|
|
921
391
|
}
|
|
922
392
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
return {
|
|
926
|
-
icon: icon?.iconUrl ?? icon?.themeIcon,
|
|
927
|
-
id: rawSubmenu.id,
|
|
928
|
-
label: rawSubmenu.label
|
|
929
|
-
};
|
|
930
|
-
|
|
393
|
+
protected readSubmenu(rawSubmenu: PluginPackageSubmenu, plugin: PluginPackage): Submenu {
|
|
394
|
+
return readSubmenuShared(this.contributionCtx(plugin), rawSubmenu, plugin);
|
|
931
395
|
}
|
|
932
396
|
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
const icon = this.transformIconUrl(plugin, rawLang.icon);
|
|
936
|
-
const result: LanguageContribution = {
|
|
937
|
-
id: rawLang.id,
|
|
938
|
-
aliases: rawLang.aliases,
|
|
939
|
-
extensions: rawLang.extensions,
|
|
940
|
-
filenamePatterns: rawLang.filenamePatterns,
|
|
941
|
-
filenames: rawLang.filenames,
|
|
942
|
-
firstLine: rawLang.firstLine,
|
|
943
|
-
mimetypes: rawLang.mimetypes,
|
|
944
|
-
icon: icon?.iconUrl ?? icon?.themeIcon
|
|
945
|
-
};
|
|
946
|
-
if (rawLang.configuration) {
|
|
947
|
-
const rawConfiguration = await this.readJson<PluginPackageLanguageContributionConfiguration>(path.resolve(plugin.packagePath, rawLang.configuration));
|
|
948
|
-
if (rawConfiguration) {
|
|
949
|
-
const configuration: LanguageConfiguration = {
|
|
950
|
-
brackets: rawConfiguration.brackets,
|
|
951
|
-
comments: rawConfiguration.comments,
|
|
952
|
-
folding: rawConfiguration.folding,
|
|
953
|
-
wordPattern: rawConfiguration.wordPattern,
|
|
954
|
-
autoClosingPairs: this.extractValidAutoClosingPairs(rawLang.id, rawConfiguration),
|
|
955
|
-
indentationRules: rawConfiguration.indentationRules,
|
|
956
|
-
surroundingPairs: this.extractValidSurroundingPairs(rawLang.id, rawConfiguration),
|
|
957
|
-
onEnterRules: rawConfiguration.onEnterRules,
|
|
958
|
-
};
|
|
959
|
-
result.configuration = configuration;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
return result;
|
|
963
|
-
|
|
397
|
+
protected async readLanguage(rawLang: PluginPackageLanguageContribution, plugin: PluginPackage): Promise<LanguageContribution> {
|
|
398
|
+
return readLanguageShared(this.contributionCtx(plugin), rawLang, plugin);
|
|
964
399
|
}
|
|
965
400
|
|
|
966
|
-
|
|
967
|
-
return rawDebuggers.map(
|
|
401
|
+
protected readDebuggers(rawDebuggers: PluginPackageDebuggersContribution[]): DebuggerContribution[] {
|
|
402
|
+
return rawDebuggers.map(rawDebugger => this.readDebugger(rawDebugger));
|
|
968
403
|
}
|
|
969
404
|
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
type: rawDebugger.type,
|
|
973
|
-
label: rawDebugger.label,
|
|
974
|
-
languages: rawDebugger.languages,
|
|
975
|
-
enableBreakpointsFor: rawDebugger.enableBreakpointsFor,
|
|
976
|
-
variables: rawDebugger.variables,
|
|
977
|
-
adapterExecutableCommand: rawDebugger.adapterExecutableCommand,
|
|
978
|
-
configurationSnippets: rawDebugger.configurationSnippets,
|
|
979
|
-
win: rawDebugger.win,
|
|
980
|
-
winx86: rawDebugger.winx86,
|
|
981
|
-
windows: rawDebugger.windows,
|
|
982
|
-
osx: rawDebugger.osx,
|
|
983
|
-
linux: rawDebugger.linux,
|
|
984
|
-
program: rawDebugger.program,
|
|
985
|
-
args: rawDebugger.args,
|
|
986
|
-
runtime: rawDebugger.runtime,
|
|
987
|
-
runtimeArgs: rawDebugger.runtimeArgs,
|
|
988
|
-
configurationAttributes: rawDebugger.configurationAttributes
|
|
989
|
-
};
|
|
990
|
-
|
|
991
|
-
return result;
|
|
405
|
+
protected readDebugger(rawDebugger: PluginPackageDebuggersContribution): DebuggerContribution {
|
|
406
|
+
return readDebuggerShared(rawDebugger);
|
|
992
407
|
}
|
|
993
408
|
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
taskType: definitionContribution.type,
|
|
999
|
-
source: pluginName,
|
|
1000
|
-
properties: {
|
|
1001
|
-
required: definitionContribution.required || [],
|
|
1002
|
-
all: propertyKeys,
|
|
1003
|
-
schema
|
|
1004
|
-
}
|
|
1005
|
-
};
|
|
409
|
+
protected readTaskDefinition(pluginName: string, definitionContribution: PluginTaskDefinitionContribution): TaskDefinition {
|
|
410
|
+
return readTaskDefinitionShared(pluginName, definitionContribution, {
|
|
411
|
+
toSchema: definition => this.toSchema(definition)
|
|
412
|
+
});
|
|
1006
413
|
}
|
|
1007
414
|
|
|
1008
415
|
protected toSchema(definition: PluginTaskDefinitionContribution): IJSONSchema {
|
|
1009
|
-
|
|
1010
|
-
const schema = deepClone(reconciliation);
|
|
1011
|
-
if (schema.properties === undefined) {
|
|
1012
|
-
schema.properties = Object.create(null);
|
|
1013
|
-
}
|
|
1014
|
-
schema.type = 'object';
|
|
1015
|
-
schema.properties!.type = { type: 'string', const: definition.type };
|
|
1016
|
-
return schema;
|
|
416
|
+
return toSchemaShared(definition);
|
|
1017
417
|
}
|
|
1018
418
|
|
|
1019
|
-
|
|
1020
|
-
const
|
|
1021
|
-
|
|
1022
|
-
return undefined;
|
|
1023
|
-
}
|
|
1024
|
-
if (!Array.isArray(source)) {
|
|
1025
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`autoClosingPairs\` to be an array.`);
|
|
1026
|
-
return undefined;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
let result: AutoClosingPairConditional[] | undefined = undefined;
|
|
1030
|
-
for (let i = 0, len = source.length; i < len; i++) {
|
|
1031
|
-
const pair = source[i];
|
|
1032
|
-
if (Array.isArray(pair)) {
|
|
1033
|
-
if (!isCharacterPair(pair)) {
|
|
1034
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`autoClosingPairs[${i}]\` to be an array of two strings or an object.`);
|
|
1035
|
-
continue;
|
|
1036
|
-
}
|
|
1037
|
-
result = result || [];
|
|
1038
|
-
result.push({ open: pair[0], close: pair[1] });
|
|
1039
|
-
} else {
|
|
1040
|
-
if (!isObject(pair)) {
|
|
1041
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`autoClosingPairs[${i}]\` to be an array of two strings or an object.`);
|
|
1042
|
-
continue;
|
|
1043
|
-
}
|
|
1044
|
-
if (typeof pair.open !== 'string') {
|
|
1045
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`autoClosingPairs[${i}].open\` to be a string.`);
|
|
1046
|
-
continue;
|
|
1047
|
-
}
|
|
1048
|
-
if (typeof pair.close !== 'string') {
|
|
1049
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`autoClosingPairs[${i}].close\` to be a string.`);
|
|
1050
|
-
continue;
|
|
1051
|
-
}
|
|
1052
|
-
if (typeof pair.notIn !== 'undefined') {
|
|
1053
|
-
if (!isStringArray(pair.notIn)) {
|
|
1054
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`autoClosingPairs[${i}].notIn\` to be a string array.`);
|
|
1055
|
-
continue;
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
result = result || [];
|
|
1059
|
-
result.push({ open: pair.open, close: pair.close, notIn: pair.notIn });
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
return result;
|
|
419
|
+
protected async readJson<T>(filePath: string): Promise<T | undefined> {
|
|
420
|
+
const content = await this.readFile(filePath);
|
|
421
|
+
return content ? jsoncparser.parse(content, undefined, { disallowComments: false }) : undefined;
|
|
1063
422
|
}
|
|
1064
423
|
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
return
|
|
1069
|
-
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
return undefined;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
let result: AutoClosingPair[] | undefined = undefined;
|
|
1076
|
-
for (let i = 0, len = source.length; i < len; i++) {
|
|
1077
|
-
const pair = source[i];
|
|
1078
|
-
if (Array.isArray(pair)) {
|
|
1079
|
-
if (!isCharacterPair(pair)) {
|
|
1080
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`surroundingPairs[${i}]\` to be an array of two strings or an object.`);
|
|
1081
|
-
continue;
|
|
1082
|
-
}
|
|
1083
|
-
result = result || [];
|
|
1084
|
-
result.push({ open: pair[0], close: pair[1] });
|
|
1085
|
-
} else {
|
|
1086
|
-
if (!isObject(pair)) {
|
|
1087
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`surroundingPairs[${i}]\` to be an array of two strings or an object.`);
|
|
1088
|
-
continue;
|
|
1089
|
-
}
|
|
1090
|
-
if (typeof pair.open !== 'string') {
|
|
1091
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`surroundingPairs[${i}].open\` to be a string.`);
|
|
1092
|
-
continue;
|
|
1093
|
-
}
|
|
1094
|
-
if (typeof pair.close !== 'string') {
|
|
1095
|
-
this.logger.warn(`[${langId}]: language configuration: expected \`surroundingPairs[${i}].close\` to be a string.`);
|
|
1096
|
-
continue;
|
|
1097
|
-
}
|
|
1098
|
-
result = result || [];
|
|
1099
|
-
result.push({ open: pair.open, close: pair.close });
|
|
424
|
+
protected async readFile(filePath: string): Promise<string> {
|
|
425
|
+
try {
|
|
426
|
+
const content = await fs.readFile(filePath, { encoding: 'utf8' });
|
|
427
|
+
return content;
|
|
428
|
+
} catch (e) {
|
|
429
|
+
if (!isENOENT(e)) {
|
|
430
|
+
this.logger.error(e);
|
|
1100
431
|
}
|
|
432
|
+
return '';
|
|
1101
433
|
}
|
|
1102
|
-
return result;
|
|
1103
434
|
}
|
|
1104
|
-
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
|
-
function isCharacterPair(something: CharacterPair): boolean {
|
|
1108
|
-
return (
|
|
1109
|
-
isStringArray(something)
|
|
1110
|
-
&& something.length === 2
|
|
1111
|
-
);
|
|
1112
435
|
}
|