@opensumi/ide-editor 2.21.13 → 2.22.0
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/browser/breadcrumb/default.js.map +1 -1
- package/lib/browser/breadcrumb/document-symbol.js.map +1 -1
- package/lib/browser/breadcrumb/index.js.map +1 -1
- package/lib/browser/component.js.map +1 -1
- package/lib/browser/decoration-applier.js.map +1 -1
- package/lib/browser/diff/compare.js.map +1 -1
- package/lib/browser/diff/index.d.ts.map +1 -1
- package/lib/browser/diff/index.js +1 -1
- package/lib/browser/diff/index.js.map +1 -1
- package/lib/browser/doc-cache/empty-doc-cache.js.map +1 -1
- package/lib/browser/doc-cache/local-storage-cache.js.map +1 -1
- package/lib/browser/doc-model/editor-document-model-service.js +3 -3
- package/lib/browser/doc-model/editor-document-model-service.js.map +1 -1
- package/lib/browser/doc-model/editor-document-model.d.ts +8 -0
- package/lib/browser/doc-model/editor-document-model.d.ts.map +1 -1
- package/lib/browser/doc-model/editor-document-model.js +61 -11
- package/lib/browser/doc-model/editor-document-model.js.map +1 -1
- package/lib/browser/doc-model/editor-document-registry.js.map +1 -1
- package/lib/browser/doc-model/override.js.map +1 -1
- package/lib/browser/doc-model/save-task.js +1 -1
- package/lib/browser/doc-model/save-task.js.map +1 -1
- package/lib/browser/doc-model/saveParticipants.d.ts +7 -7
- package/lib/browser/doc-model/saveParticipants.d.ts.map +1 -1
- package/lib/browser/doc-model/saveParticipants.js +69 -38
- package/lib/browser/doc-model/saveParticipants.js.map +1 -1
- package/lib/browser/doc-model/types.d.ts +1 -1
- package/lib/browser/doc-model/types.d.ts.map +1 -1
- package/lib/browser/editor-collection.service.d.ts +8 -3
- package/lib/browser/editor-collection.service.d.ts.map +1 -1
- package/lib/browser/editor-collection.service.js +75 -66
- package/lib/browser/editor-collection.service.js.map +1 -1
- package/lib/browser/editor-opener.js.map +1 -1
- package/lib/browser/editor.contribution.d.ts.map +1 -1
- package/lib/browser/editor.contribution.js +31 -3
- package/lib/browser/editor.contribution.js.map +1 -1
- package/lib/browser/editor.decoration.service.d.ts +5 -6
- package/lib/browser/editor.decoration.service.d.ts.map +1 -1
- package/lib/browser/editor.decoration.service.js +9 -1
- package/lib/browser/editor.decoration.service.js.map +1 -1
- package/lib/browser/editor.override.js +2 -2
- package/lib/browser/editor.override.js.map +1 -1
- package/lib/browser/editor.status-bar.service.js.map +1 -1
- package/lib/browser/editor.view.d.ts.map +1 -1
- package/lib/browser/editor.view.js +20 -23
- package/lib/browser/editor.view.js.map +1 -1
- package/lib/browser/error.d.ts +1 -1
- package/lib/browser/error.d.ts.map +1 -1
- package/lib/browser/feature.js.map +1 -1
- package/lib/browser/format/format.service.js.map +1 -1
- package/lib/browser/format/formatterSelect.js.map +1 -1
- package/lib/browser/fs-resource/file-tree-set.js +6 -6
- package/lib/browser/fs-resource/file-tree-set.js.map +1 -1
- package/lib/browser/fs-resource/fs-editor-doc.js +1 -1
- package/lib/browser/fs-resource/fs-editor-doc.js.map +1 -1
- package/lib/browser/fs-resource/fs-resource.js.map +1 -1
- package/lib/browser/fs-resource/index.js.map +1 -1
- package/lib/browser/history/index.d.ts.map +1 -1
- package/lib/browser/history/index.js +2 -1
- package/lib/browser/history/index.js.map +1 -1
- package/lib/browser/index.d.ts.map +1 -1
- package/lib/browser/index.js +2 -0
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/language/diagnostic-collection.d.ts +5 -5
- package/lib/browser/language/diagnostic-collection.d.ts.map +1 -1
- package/lib/browser/language/diagnostic-collection.js +1 -1
- package/lib/browser/language/diagnostic-collection.js.map +1 -1
- package/lib/browser/language/language-status.contribution.js.map +1 -1
- package/lib/browser/language/language-status.service.js.map +1 -1
- package/lib/browser/language/language.service.d.ts +4 -3
- package/lib/browser/language/language.service.d.ts.map +1 -1
- package/lib/browser/language/language.service.js +8 -2
- package/lib/browser/language/language.service.js.map +1 -1
- package/lib/browser/menu/editor.context.js +3 -3
- package/lib/browser/menu/editor.context.js.map +1 -1
- package/lib/browser/menu/editor.menu.d.ts +2 -2
- package/lib/browser/menu/editor.menu.d.ts.map +1 -1
- package/lib/browser/menu/editor.menu.js +6 -8
- package/lib/browser/menu/editor.menu.js.map +1 -1
- package/lib/browser/menu/open-type-menu.contribution.js +9 -9
- package/lib/browser/menu/open-type-menu.contribution.js.map +1 -1
- package/lib/browser/menu/title-context.menu.js.map +1 -1
- package/lib/browser/merge-editor/merge-editor.contribution.d.ts +8 -0
- package/lib/browser/merge-editor/merge-editor.contribution.d.ts.map +1 -0
- package/lib/browser/merge-editor/merge-editor.contribution.js +29 -0
- package/lib/browser/merge-editor/merge-editor.contribution.js.map +1 -0
- package/lib/browser/merge-editor/merge-editor.provider.d.ts +8 -0
- package/lib/browser/merge-editor/merge-editor.provider.d.ts.map +1 -0
- package/lib/browser/merge-editor/merge-editor.provider.js +44 -0
- package/lib/browser/merge-editor/merge-editor.provider.js.map +1 -0
- package/lib/browser/monaco-contrib/callHierarchy/callHierarchy.contribution.js.map +1 -1
- package/lib/browser/monaco-contrib/callHierarchy/callHierarchy.service.js +7 -7
- package/lib/browser/monaco-contrib/callHierarchy/callHierarchy.service.js.map +1 -1
- package/lib/browser/monaco-contrib/command/command.service.d.ts +1 -1
- package/lib/browser/monaco-contrib/command/command.service.d.ts.map +1 -1
- package/lib/browser/monaco-contrib/command/command.service.js.map +1 -1
- package/lib/browser/monaco-contrib/tokenizer/textmate-registry.js.map +1 -1
- package/lib/browser/monaco-contrib/tokenizer/textmate.service.d.ts +2 -1
- package/lib/browser/monaco-contrib/tokenizer/textmate.service.d.ts.map +1 -1
- package/lib/browser/monaco-contrib/tokenizer/textmate.service.js +5 -2
- package/lib/browser/monaco-contrib/tokenizer/textmate.service.js.map +1 -1
- package/lib/browser/monaco-contrib/typeHierarchy/typeHierarchy.contribution.js.map +1 -1
- package/lib/browser/monaco-contrib/typeHierarchy/typeHierarchy.service.js +7 -7
- package/lib/browser/monaco-contrib/typeHierarchy/typeHierarchy.service.js.map +1 -1
- package/lib/browser/navigation.module.less +1 -1
- package/lib/browser/navigation.view.d.ts.map +1 -1
- package/lib/browser/navigation.view.js +26 -15
- package/lib/browser/navigation.view.js.map +1 -1
- package/lib/browser/preference/contribution.js.map +1 -1
- package/lib/browser/preference/converter.d.ts +3 -3
- package/lib/browser/preference/converter.d.ts.map +1 -1
- package/lib/browser/preference/schema.d.ts +1 -1
- package/lib/browser/preference/schema.d.ts.map +1 -1
- package/lib/browser/preference/schema.js +8 -8
- package/lib/browser/preference/schema.js.map +1 -1
- package/lib/browser/quick-open/go-to-line.js.map +1 -1
- package/lib/browser/quick-open/workspace-symbol-quickopen.d.ts.map +1 -1
- package/lib/browser/quick-open/workspace-symbol-quickopen.js +2 -2
- package/lib/browser/quick-open/workspace-symbol-quickopen.js.map +1 -1
- package/lib/browser/resource.service.js.map +1 -1
- package/lib/browser/tab.view.d.ts +1 -1
- package/lib/browser/tab.view.d.ts.map +1 -1
- package/lib/browser/tab.view.js +2 -2
- package/lib/browser/tab.view.js.map +1 -1
- package/lib/browser/types.d.ts +5 -5
- package/lib/browser/types.d.ts.map +1 -1
- package/lib/browser/untitled-resource.js +1 -1
- package/lib/browser/untitled-resource.js.map +1 -1
- package/lib/browser/view/suggest-widget.js.map +1 -1
- package/lib/browser/workbench-editor.service.d.ts +17 -0
- package/lib/browser/workbench-editor.service.d.ts.map +1 -1
- package/lib/browser/workbench-editor.service.js +259 -176
- package/lib/browser/workbench-editor.service.js.map +1 -1
- package/lib/common/doc-cache.d.ts +2 -2
- package/lib/common/doc-cache.d.ts.map +1 -1
- package/lib/common/editor.d.ts +20 -6
- package/lib/common/editor.d.ts.map +1 -1
- package/lib/common/editor.js +12 -1
- package/lib/common/editor.js.map +1 -1
- package/lib/common/language.d.ts +18 -7
- package/lib/common/language.d.ts.map +1 -1
- package/lib/common/language.js +15 -7
- package/lib/common/language.js.map +1 -1
- package/lib/common/mocks/workbench-editor.service.js.map +1 -1
- package/lib/common/resource.d.ts +8 -2
- package/lib/common/resource.d.ts.map +1 -1
- package/lib/common/resource.js +1 -0
- package/lib/common/resource.js.map +1 -1
- package/package.json +17 -16
- package/src/browser/breadcrumb/default.ts +299 -0
- package/src/browser/breadcrumb/document-symbol.ts +187 -0
- package/src/browser/breadcrumb/index.ts +96 -0
- package/src/browser/component.ts +204 -0
- package/src/browser/decoration-applier.ts +256 -0
- package/src/browser/diff/compare.ts +99 -0
- package/src/browser/diff/index.ts +81 -0
- package/src/browser/doc-cache/empty-doc-cache.ts +26 -0
- package/src/browser/doc-cache/index.ts +2 -0
- package/src/browser/doc-cache/local-storage-cache.ts +67 -0
- package/src/browser/doc-model/editor-document-error.ts +10 -0
- package/src/browser/doc-model/editor-document-model-service.ts +346 -0
- package/src/browser/doc-model/editor-document-model.ts +690 -0
- package/src/browser/doc-model/editor-document-registry.ts +119 -0
- package/src/browser/doc-model/editor-is-fn.ts +9 -0
- package/src/browser/doc-model/main.ts +4 -0
- package/src/browser/doc-model/override.ts +49 -0
- package/src/browser/doc-model/save-task.ts +88 -0
- package/src/browser/doc-model/saveParticipants.ts +227 -0
- package/src/browser/doc-model/types.ts +350 -0
- package/src/browser/editor-collection.service.ts +790 -0
- package/src/browser/editor-opener.ts +44 -0
- package/src/browser/editor.contribution.ts +1438 -0
- package/src/browser/editor.decoration.service.ts +247 -0
- package/src/browser/editor.less +4 -0
- package/src/browser/editor.module.less +548 -0
- package/src/browser/editor.override.ts +133 -0
- package/src/browser/editor.status-bar.service.ts +116 -0
- package/src/browser/editor.view.tsx +623 -0
- package/src/browser/error.ts +21 -0
- package/src/browser/feature.ts +63 -0
- package/src/browser/format/format.service.ts +95 -0
- package/src/browser/format/formatterSelect.ts +82 -0
- package/src/browser/fs-resource/file-tree-set.ts +126 -0
- package/src/browser/fs-resource/fs-editor-doc.ts +213 -0
- package/src/browser/fs-resource/fs-resource.ts +247 -0
- package/src/browser/fs-resource/index.ts +27 -0
- package/src/browser/grid/grid.service.ts +288 -0
- package/src/browser/history/index.ts +228 -0
- package/src/browser/index.ts +236 -0
- package/src/browser/language/diagnostic-collection.ts +83 -0
- package/src/browser/language/language-status.contribution.ts +81 -0
- package/src/browser/language/language-status.service.ts +32 -0
- package/src/browser/language/language.service.ts +185 -0
- package/src/browser/menu/editor.context.ts +186 -0
- package/src/browser/menu/editor.menu.ts +45 -0
- package/src/browser/menu/open-type-menu.contribution.ts +90 -0
- package/src/browser/menu/title-context.menu.ts +54 -0
- package/src/browser/merge-editor/merge-editor.contribution.ts +25 -0
- package/src/browser/merge-editor/merge-editor.provider.ts +36 -0
- package/src/browser/monaco-contrib/callHierarchy/callHierarchy.contribution.ts +78 -0
- package/src/browser/monaco-contrib/callHierarchy/callHierarchy.service.ts +160 -0
- package/src/browser/monaco-contrib/command/command.service.ts +438 -0
- package/src/browser/monaco-contrib/index.ts +4 -0
- package/src/browser/monaco-contrib/tokenizer/textmate-registry.ts +107 -0
- package/src/browser/monaco-contrib/tokenizer/textmate-tokenizer.ts +104 -0
- package/src/browser/monaco-contrib/tokenizer/textmate.service.ts +925 -0
- package/src/browser/monaco-contrib/typeHierarchy/typeHierarchy.contribution.ts +78 -0
- package/src/browser/monaco-contrib/typeHierarchy/typeHierarchy.service.ts +154 -0
- package/src/browser/navigation.module.less +96 -0
- package/src/browser/navigation.view.tsx +254 -0
- package/src/browser/preference/contribution.ts +8 -0
- package/src/browser/preference/converter.ts +793 -0
- package/src/browser/preference/schema.ts +1896 -0
- package/src/browser/preference/util.ts +14 -0
- package/src/browser/quick-open/go-to-line.ts +164 -0
- package/src/browser/quick-open/workspace-symbol-quickopen.ts +276 -0
- package/src/browser/resource.service.ts +263 -0
- package/src/browser/tab.view.tsx +514 -0
- package/src/browser/types.ts +467 -0
- package/src/browser/untitled-resource.ts +223 -0
- package/src/browser/view/editor.react.tsx +82 -0
- package/src/browser/view/react-hook.tsx +7 -0
- package/src/browser/view/suggest-widget.ts +77 -0
- package/src/browser/view/topPadding.ts +18 -0
- package/src/browser/workbench-editor.service.ts +2291 -0
- package/src/common/doc-cache.ts +117 -0
- package/src/common/editor.ts +799 -0
- package/src/common/index.ts +6 -0
- package/src/common/language-status.ts +33 -0
- package/src/common/language.ts +206 -0
- package/src/common/mocks/workbench-editor.service.ts +52 -0
- package/src/common/resource.ts +147 -0
- package/src/common/utils.ts +10 -0
- package/src/index.ts +1 -0
- package/lib/browser/component/scroll/scroll.d.ts +0 -2
- package/lib/browser/component/scroll/scroll.d.ts.map +0 -1
- package/lib/browser/component/scroll/scroll.js +0 -5
- package/lib/browser/component/scroll/scroll.js.map +0 -1
- package/lib/browser/component/scroll/scroll.module.less +0 -86
|
@@ -0,0 +1,925 @@
|
|
|
1
|
+
import { OnigScanner, loadWASM, OnigString } from 'vscode-oniguruma';
|
|
2
|
+
import {
|
|
3
|
+
Registry,
|
|
4
|
+
IRawGrammar,
|
|
5
|
+
IOnigLib,
|
|
6
|
+
parseRawGrammar,
|
|
7
|
+
IEmbeddedLanguagesMap,
|
|
8
|
+
ITokenTypeMap,
|
|
9
|
+
INITIAL,
|
|
10
|
+
} from 'vscode-textmate';
|
|
11
|
+
|
|
12
|
+
import { Injectable, Autowired } from '@opensumi/di';
|
|
13
|
+
import {
|
|
14
|
+
WithEventBus,
|
|
15
|
+
parseWithComments,
|
|
16
|
+
PreferenceService,
|
|
17
|
+
ILogger,
|
|
18
|
+
ExtensionActivateEvent,
|
|
19
|
+
getDebugLogger,
|
|
20
|
+
electronEnv,
|
|
21
|
+
AppConfig,
|
|
22
|
+
} from '@opensumi/ide-core-browser';
|
|
23
|
+
import { URI, Disposable, isObject } from '@opensumi/ide-core-common';
|
|
24
|
+
import { IFileServiceClient } from '@opensumi/ide-file-service/lib/common';
|
|
25
|
+
import {
|
|
26
|
+
GrammarsContribution,
|
|
27
|
+
ITextmateTokenizerService,
|
|
28
|
+
ScopeMap,
|
|
29
|
+
} from '@opensumi/ide-monaco/lib/browser/contrib/tokenizer';
|
|
30
|
+
import { monaco } from '@opensumi/ide-monaco/lib/browser/monaco-api';
|
|
31
|
+
import {
|
|
32
|
+
EnterAction,
|
|
33
|
+
FoldingRules,
|
|
34
|
+
IAutoClosingPair,
|
|
35
|
+
IAutoClosingPairConditional,
|
|
36
|
+
IndentationRule,
|
|
37
|
+
LanguageConfiguration,
|
|
38
|
+
OnEnterRule,
|
|
39
|
+
} from '@opensumi/ide-monaco/lib/browser/monaco-api/types';
|
|
40
|
+
import {
|
|
41
|
+
CommentRule,
|
|
42
|
+
IIndentationRule,
|
|
43
|
+
IndentAction,
|
|
44
|
+
IndentationRuleDto,
|
|
45
|
+
IRegExp,
|
|
46
|
+
LanguageConfigurationDto,
|
|
47
|
+
LanguagesContribution,
|
|
48
|
+
} from '@opensumi/ide-monaco/lib/common';
|
|
49
|
+
import { IThemeData } from '@opensumi/ide-theme';
|
|
50
|
+
import { ThemeChangedEvent } from '@opensumi/ide-theme/lib/common/event';
|
|
51
|
+
import { asStringArray } from '@opensumi/ide-utils/lib/arrays';
|
|
52
|
+
import { ILanguageExtensionPoint } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages/language';
|
|
53
|
+
import { ILanguageService } from '@opensumi/monaco-editor-core/esm/vs/editor/common/languages/language';
|
|
54
|
+
import { StandaloneServices } from '@opensumi/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
|
|
55
|
+
|
|
56
|
+
import { IEditorDocumentModelService } from '../../doc-model/types';
|
|
57
|
+
|
|
58
|
+
import { TextmateRegistry } from './textmate-registry';
|
|
59
|
+
import { TextMateTokenizer, TokenizerOption } from './textmate-tokenizer';
|
|
60
|
+
|
|
61
|
+
let wasmLoaded = false;
|
|
62
|
+
|
|
63
|
+
export function getEncodedLanguageId(languageId: string): number {
|
|
64
|
+
return monaco.languages.getEncodedLanguageId(languageId);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function getLegalThemeName(name: string) {
|
|
68
|
+
return name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
class OnigasmLib implements IOnigLib {
|
|
72
|
+
createOnigScanner(source: string[]) {
|
|
73
|
+
return new OnigScanner(source);
|
|
74
|
+
}
|
|
75
|
+
createOnigString(source: string) {
|
|
76
|
+
return new OnigString(source);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isStringArr(something: string[] | null): something is string[] {
|
|
81
|
+
if (!Array.isArray(something)) {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
for (let i = 0, len = something.length; i < len; i++) {
|
|
85
|
+
if (typeof something[i] !== 'string') {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return true;
|
|
90
|
+
}
|
|
91
|
+
export type CharacterPair = [string, string];
|
|
92
|
+
function isCharacterPair(something: CharacterPair | null): boolean {
|
|
93
|
+
return isStringArr(something) && something.length === 2;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@Injectable()
|
|
97
|
+
export class TextmateService extends WithEventBus implements ITextmateTokenizerService {
|
|
98
|
+
@Autowired()
|
|
99
|
+
private textmateRegistry: TextmateRegistry;
|
|
100
|
+
|
|
101
|
+
@Autowired(IFileServiceClient)
|
|
102
|
+
private fileServiceClient: IFileServiceClient;
|
|
103
|
+
|
|
104
|
+
@Autowired(PreferenceService)
|
|
105
|
+
preferenceService: PreferenceService;
|
|
106
|
+
|
|
107
|
+
@Autowired(ILogger)
|
|
108
|
+
private logger: ILogger;
|
|
109
|
+
|
|
110
|
+
@Autowired(IEditorDocumentModelService)
|
|
111
|
+
editorDocumentModelService: IEditorDocumentModelService;
|
|
112
|
+
|
|
113
|
+
@Autowired(AppConfig)
|
|
114
|
+
private readonly appConfig: AppConfig;
|
|
115
|
+
|
|
116
|
+
public grammarRegistry: Registry;
|
|
117
|
+
|
|
118
|
+
private registeredGrammarDisposableCollection = new Map<string, Disposable>();
|
|
119
|
+
|
|
120
|
+
private injections = new Map<string, string[]>();
|
|
121
|
+
|
|
122
|
+
private activatedLanguage = new Set<string>();
|
|
123
|
+
|
|
124
|
+
private languageConfigLocation: Map<string, URI> = new Map();
|
|
125
|
+
private languageConfiguration: Map<string, LanguagesContribution> = new Map();
|
|
126
|
+
|
|
127
|
+
public initialized = false;
|
|
128
|
+
|
|
129
|
+
private dynamicLanguages: ILanguageExtensionPoint[] = [];
|
|
130
|
+
|
|
131
|
+
private editorTheme?: IThemeData;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* start contribution 做初始化
|
|
135
|
+
*/
|
|
136
|
+
init() {
|
|
137
|
+
this.initGrammarRegistry();
|
|
138
|
+
this.listenThemeChange();
|
|
139
|
+
this.listenPreferenceChange();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// themeName要求:/^[a-z0-9\-]+$/ 来源vscode源码
|
|
143
|
+
listenThemeChange() {
|
|
144
|
+
this.eventBus.on(ThemeChangedEvent, (e) => {
|
|
145
|
+
const themeData = e.payload.theme.themeData;
|
|
146
|
+
if (themeData !== this.editorTheme) {
|
|
147
|
+
this.editorTheme = themeData;
|
|
148
|
+
this.setTheme(themeData);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async registerLanguage(language: LanguagesContribution, extPath: URI) {
|
|
154
|
+
return this.registerLanguages([language], extPath);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
private reviveLanguageConfiguration(id: string, configuration: LanguageConfigurationDto): LanguageConfiguration {
|
|
158
|
+
return {
|
|
159
|
+
wordPattern: this.createRegex(configuration.wordPattern),
|
|
160
|
+
autoClosingPairs: this.extractValidAutoClosingPairs(id, configuration),
|
|
161
|
+
brackets: this.extractValidBrackets(id, configuration),
|
|
162
|
+
comments: this.extractValidCommentRule(id, configuration),
|
|
163
|
+
folding: this.convertFolding(configuration.folding),
|
|
164
|
+
surroundingPairs: this.extractValidSurroundingPairs(id, configuration),
|
|
165
|
+
indentationRules: this.convertIndentationRules(configuration.indentationRules),
|
|
166
|
+
autoCloseBefore: configuration.autoCloseBefore,
|
|
167
|
+
colorizedBracketPairs: this.extractValidColorizedBracketPairs(id, configuration),
|
|
168
|
+
onEnterRules: this.extractValidOnEnterRules(id, configuration),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
get monacoLanguageService() {
|
|
173
|
+
return StandaloneServices.get(ILanguageService);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
private isEmbeddedLanguageOnly(language: LanguagesContribution): boolean {
|
|
177
|
+
return (
|
|
178
|
+
!language.filenames &&
|
|
179
|
+
!language.extensions &&
|
|
180
|
+
!language.filenamePatterns &&
|
|
181
|
+
!language.firstLine &&
|
|
182
|
+
!language.mimetypes &&
|
|
183
|
+
(!language.aliases || language.aliases.length === 0)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
async registerLanguages(languages: LanguagesContribution[], baseUri: URI) {
|
|
188
|
+
const newLanguages = languages.map((language) => ({
|
|
189
|
+
id: language.id,
|
|
190
|
+
aliases: language.aliases,
|
|
191
|
+
extensions: language.extensions,
|
|
192
|
+
filenamePatterns: language.filenamePatterns,
|
|
193
|
+
filenames: language.filenames,
|
|
194
|
+
firstLine: language.firstLine,
|
|
195
|
+
mimetypes: language.mimetypes,
|
|
196
|
+
}));
|
|
197
|
+
|
|
198
|
+
this.dynamicLanguages.push(...newLanguages.filter((lang) => !this.isEmbeddedLanguageOnly(lang)));
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* ModesRegistry.registerLanguage 性能很差
|
|
202
|
+
*/
|
|
203
|
+
this.monacoLanguageService['_registry']['_registerLanguages'](newLanguages);
|
|
204
|
+
languages.forEach(async (language) => {
|
|
205
|
+
this.languageConfigLocation.set(language.id, baseUri);
|
|
206
|
+
this.addDispose(
|
|
207
|
+
monaco.languages.onLanguage(language.id, async () => {
|
|
208
|
+
await this.loadLanguageConfiguration(language, baseUri);
|
|
209
|
+
this.activateLanguage(language.id);
|
|
210
|
+
}),
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
this.languageConfiguration.set(language.id, language);
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
if (this.initialized) {
|
|
217
|
+
const uris = this.editorDocumentModelService.getAllModels().map((m) => m.uri);
|
|
218
|
+
for (const uri of uris) {
|
|
219
|
+
const model = this.editorDocumentModelService.getModelReference(URI.parse(uri.codeUri.toString()));
|
|
220
|
+
if (model && model.instance) {
|
|
221
|
+
const langId = model.instance.getMonacoModel().getLanguageId();
|
|
222
|
+
if (this.languageConfiguration.has(langId)) {
|
|
223
|
+
await this.loadLanguageConfiguration(this.languageConfiguration.get(langId)!, baseUri);
|
|
224
|
+
this.activateLanguage(langId);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
model?.dispose();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async registerGrammar(grammar: GrammarsContribution, extPath: URI) {
|
|
233
|
+
if (grammar.path) {
|
|
234
|
+
const grammarPath = grammar.path.replace(/^\.\//, '');
|
|
235
|
+
// get content in `initGrammarRegistry`
|
|
236
|
+
grammar.location = extPath.resolve(grammarPath);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
this.doRegisterGrammar(grammar);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
unregisterGrammar(grammar: GrammarsContribution) {
|
|
243
|
+
const toDispose = this.registeredGrammarDisposableCollection.get(grammar.scopeName);
|
|
244
|
+
|
|
245
|
+
if (toDispose) {
|
|
246
|
+
toDispose.dispose();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
doRegisterGrammar(grammar: GrammarsContribution) {
|
|
251
|
+
const toDispose = new Disposable();
|
|
252
|
+
|
|
253
|
+
if (grammar.injectTo) {
|
|
254
|
+
for (const injectScope of grammar.injectTo) {
|
|
255
|
+
let injections = this.injections.get(injectScope);
|
|
256
|
+
if (!injections) {
|
|
257
|
+
injections = [];
|
|
258
|
+
|
|
259
|
+
toDispose.addDispose(
|
|
260
|
+
Disposable.create(() => {
|
|
261
|
+
this.injections.delete(injectScope);
|
|
262
|
+
}),
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
this.injections.set(injectScope, injections);
|
|
266
|
+
}
|
|
267
|
+
injections.push(grammar.scopeName);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
toDispose.addDispose(
|
|
272
|
+
Disposable.create(
|
|
273
|
+
this.textmateRegistry.registerTextmateGrammarScope(grammar.scopeName, {
|
|
274
|
+
async getGrammarDefinition() {
|
|
275
|
+
return {
|
|
276
|
+
format: /\.json$/.test(grammar.path) ? 'json' : 'plist',
|
|
277
|
+
location: grammar.location!,
|
|
278
|
+
content: await grammar.resolvedConfiguration,
|
|
279
|
+
};
|
|
280
|
+
},
|
|
281
|
+
getInjections: (scopeName: string) => {
|
|
282
|
+
const scopeParts = scopeName.split('.');
|
|
283
|
+
let injections: string[] = [];
|
|
284
|
+
for (let i = 1; i <= scopeParts.length; i++) {
|
|
285
|
+
const subScopeName = scopeParts.slice(0, i).join('.');
|
|
286
|
+
injections = [...injections, ...(this.injections.get(subScopeName) || [])];
|
|
287
|
+
}
|
|
288
|
+
return injections;
|
|
289
|
+
},
|
|
290
|
+
}),
|
|
291
|
+
),
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
if (grammar.language) {
|
|
295
|
+
toDispose.addDispose(
|
|
296
|
+
Disposable.create(this.textmateRegistry.mapLanguageIdToTextmateGrammar(grammar.language, grammar.scopeName)),
|
|
297
|
+
);
|
|
298
|
+
toDispose.addDispose(
|
|
299
|
+
Disposable.create(
|
|
300
|
+
this.textmateRegistry.registerGrammarConfiguration(grammar.language, () => ({
|
|
301
|
+
embeddedLanguages: this.convertEmbeddedLanguages(grammar.embeddedLanguages),
|
|
302
|
+
tokenTypes: this.convertTokenTypes(grammar.tokenTypes),
|
|
303
|
+
balancedBracketSelectors: asStringArray(grammar.balancedBracketScopes, ['*']),
|
|
304
|
+
unbalancedBracketSelectors: asStringArray(grammar.unbalancedBracketScopes, []),
|
|
305
|
+
})),
|
|
306
|
+
),
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
this.registeredGrammarDisposableCollection.set(grammar.scopeName, toDispose);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private async loadLanguageConfiguration(language: LanguagesContribution, baseUri: URI) {
|
|
314
|
+
let configuration: LanguageConfiguration | undefined;
|
|
315
|
+
if (typeof language.resolvedConfiguration === 'object') {
|
|
316
|
+
const config = await language.resolvedConfiguration;
|
|
317
|
+
configuration = this.reviveLanguageConfiguration(language.id, config);
|
|
318
|
+
} else if (language.configuration) {
|
|
319
|
+
// remove `./` prefix
|
|
320
|
+
const langPath = language.configuration.replace(/^\.\//, '');
|
|
321
|
+
// http 的不作支持
|
|
322
|
+
const configurationPath = baseUri.resolve(langPath);
|
|
323
|
+
const ret = await this.fileServiceClient.resolveContent(configurationPath.toString());
|
|
324
|
+
const content = ret.content;
|
|
325
|
+
if (content) {
|
|
326
|
+
const jsonContent = this.safeParseJSON<LanguageConfigurationDto>(content);
|
|
327
|
+
if (jsonContent) {
|
|
328
|
+
configuration = this.reviveLanguageConfiguration(language.id, jsonContent);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (configuration) {
|
|
334
|
+
monaco.languages.setLanguageConfiguration(language.id, configuration);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async activateLanguage(languageId: string) {
|
|
339
|
+
// 允许后来的插件上车
|
|
340
|
+
this.eventBus.fire(new ExtensionActivateEvent({ topic: 'onLanguage', data: languageId }));
|
|
341
|
+
if (this.activatedLanguage.has(languageId)) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
this.activatedLanguage.add(languageId);
|
|
345
|
+
this.setTokensProviderByLanguageId(languageId);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private async setTokensProviderByLanguageId(languageId: string) {
|
|
349
|
+
const scopeName = this.textmateRegistry.getScope(languageId);
|
|
350
|
+
if (!scopeName) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const provider = this.textmateRegistry.getProvider(scopeName);
|
|
354
|
+
if (!provider) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const tokenizerOption: TokenizerOption = {
|
|
358
|
+
lineLimit: this.preferenceService.getValid('editor.maxTokenizationLineLength', 20000),
|
|
359
|
+
};
|
|
360
|
+
const configuration = this.textmateRegistry.getGrammarConfiguration(languageId)();
|
|
361
|
+
const initialLanguage = getEncodedLanguageId(languageId);
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
const grammar = await this.grammarRegistry.loadGrammarWithConfiguration(
|
|
365
|
+
scopeName,
|
|
366
|
+
initialLanguage,
|
|
367
|
+
configuration,
|
|
368
|
+
);
|
|
369
|
+
const options = configuration.tokenizerOption ? configuration.tokenizerOption : tokenizerOption;
|
|
370
|
+
const containsEmbeddedLanguages =
|
|
371
|
+
configuration.embeddedLanguages && Object.keys(configuration.embeddedLanguages).length > 0;
|
|
372
|
+
|
|
373
|
+
// 要保证grammar把所有的languageID关联的语法都注册好了
|
|
374
|
+
if (grammar) {
|
|
375
|
+
const tokenizer = new TextMateTokenizer(grammar, options, containsEmbeddedLanguages);
|
|
376
|
+
this.addDispose(
|
|
377
|
+
tokenizer.onDidEncounterLanguage(async (language) => {
|
|
378
|
+
// https://github.com/microsoft/vscode/blob/301f450d9260d6e1c900e7e93b85aae5151bf11c/src/vs/editor/common/services/languagesRegistry.ts#L140
|
|
379
|
+
const languageId = this.monacoLanguageService['_registry']['languageIdCodec']['decodeLanguageId'](language);
|
|
380
|
+
const location = this.languageConfigLocation.get(languageId);
|
|
381
|
+
if (location && this.languageConfiguration.has(languageId)) {
|
|
382
|
+
await this.loadLanguageConfiguration(this.languageConfiguration.get(languageId)!, location);
|
|
383
|
+
this.activateLanguage(languageId);
|
|
384
|
+
}
|
|
385
|
+
}),
|
|
386
|
+
);
|
|
387
|
+
monaco.languages.setTokensProvider(languageId, tokenizer);
|
|
388
|
+
}
|
|
389
|
+
} catch (error) {
|
|
390
|
+
this.logger.warn('No grammar for this language id', languageId, error);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
public setTheme(theme: IThemeData) {
|
|
395
|
+
this.generateEncodedTokenColors(theme);
|
|
396
|
+
monaco.editor.defineTheme(getLegalThemeName(theme.name), theme);
|
|
397
|
+
monaco.editor.setTheme(getLegalThemeName(theme.name));
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
private generateEncodedTokenColors(themeData: IThemeData) {
|
|
401
|
+
// load时会转换customTokenColors
|
|
402
|
+
this.grammarRegistry.setTheme(themeData);
|
|
403
|
+
themeData.encodedTokensColors = this.grammarRegistry.getColorMap();
|
|
404
|
+
// index 0 has to be set to null as it is 'undefined' by default, but monaco code expects it to be null
|
|
405
|
+
themeData.encodedTokensColors[0] = null!;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// 字符串转正则
|
|
409
|
+
private createRegex(value?: IRegExp): RegExp | undefined {
|
|
410
|
+
if (typeof value === 'string') {
|
|
411
|
+
return new RegExp(value, '');
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
if (isObject(value)) {
|
|
415
|
+
if (typeof value.pattern !== 'string') {
|
|
416
|
+
return undefined;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (typeof value.flags !== 'undefined' && typeof value.flags !== 'string') {
|
|
420
|
+
return undefined;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
return new RegExp(value.pattern, value.flags);
|
|
425
|
+
} catch (err) {
|
|
426
|
+
return undefined;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return undefined;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
private safeParseJSON<T = any>(content): T | undefined {
|
|
433
|
+
let json;
|
|
434
|
+
try {
|
|
435
|
+
json = parseWithComments(content);
|
|
436
|
+
return json;
|
|
437
|
+
} catch (error) {
|
|
438
|
+
this.logger.error('语言配置文件解析出错!', content);
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// 将foldingRule里的字符串转为正则
|
|
444
|
+
private convertFolding(folding?: IndentationRuleDto): FoldingRules | undefined {
|
|
445
|
+
if (!folding) {
|
|
446
|
+
return undefined;
|
|
447
|
+
}
|
|
448
|
+
const result: FoldingRules = {
|
|
449
|
+
offSide: folding.offSide,
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
if (folding.markers) {
|
|
453
|
+
result.markers = {
|
|
454
|
+
end: folding.markers.end!,
|
|
455
|
+
start: folding.markers.start!,
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return result;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
// 字符串定义转正则
|
|
463
|
+
private convertIndentationRules(rules?: IIndentationRule): IndentationRule | undefined {
|
|
464
|
+
if (!rules) {
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
const result: IndentationRule = {
|
|
468
|
+
decreaseIndentPattern: this.createRegex(rules.decreaseIndentPattern)!,
|
|
469
|
+
increaseIndentPattern: this.createRegex(rules.increaseIndentPattern)!,
|
|
470
|
+
};
|
|
471
|
+
if (rules.indentNextLinePattern) {
|
|
472
|
+
result.indentNextLinePattern = this.createRegex(rules.indentNextLinePattern);
|
|
473
|
+
}
|
|
474
|
+
if (rules.unIndentedLinePattern) {
|
|
475
|
+
result.unIndentedLinePattern = this.createRegex(rules.unIndentedLinePattern);
|
|
476
|
+
}
|
|
477
|
+
return result;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
private convertEmbeddedLanguages(languages?: ScopeMap): IEmbeddedLanguagesMap | undefined {
|
|
481
|
+
if (typeof languages === 'undefined' || languages === null) {
|
|
482
|
+
return undefined;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const result = Object.create(null);
|
|
486
|
+
const scopes = Object.keys(languages);
|
|
487
|
+
const len = scopes.length;
|
|
488
|
+
for (let i = 0; i < len; i++) {
|
|
489
|
+
const scope = scopes[i];
|
|
490
|
+
const langId = languages[scope];
|
|
491
|
+
result[scope] = getEncodedLanguageId(langId);
|
|
492
|
+
// TODO 后置到 tokenize 使用到对应的 scope 时激活(vscode逻辑),现在先激活一个 language 时激活所有 embed language
|
|
493
|
+
if (!this.activatedLanguage.has(langId)) {
|
|
494
|
+
this.activateLanguage(langId);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
return result;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
private convertTokenTypes(tokenTypes?: ScopeMap): ITokenTypeMap | undefined {
|
|
501
|
+
if (typeof tokenTypes === 'undefined' || tokenTypes === null) {
|
|
502
|
+
return undefined;
|
|
503
|
+
}
|
|
504
|
+
const result = Object.create(null);
|
|
505
|
+
const scopes = Object.keys(tokenTypes);
|
|
506
|
+
const len = scopes.length;
|
|
507
|
+
for (let i = 0; i < len; i++) {
|
|
508
|
+
const scope = scopes[i];
|
|
509
|
+
const tokenType = tokenTypes[scope];
|
|
510
|
+
switch (tokenType) {
|
|
511
|
+
case 'string':
|
|
512
|
+
result[scope] = 2; // StandardTokenType.String;
|
|
513
|
+
break;
|
|
514
|
+
case 'other':
|
|
515
|
+
result[scope] = 0; // StandardTokenType.Other;
|
|
516
|
+
break;
|
|
517
|
+
case 'comment':
|
|
518
|
+
result[scope] = 1; // StandardTokenType.Comment;
|
|
519
|
+
break;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
return result;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
private extractValidSurroundingPairs(
|
|
526
|
+
languageId: string,
|
|
527
|
+
configuration: LanguageConfigurationDto,
|
|
528
|
+
): IAutoClosingPair[] | undefined {
|
|
529
|
+
if (!configuration) {
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
const source = configuration.surroundingPairs;
|
|
533
|
+
if (typeof source === 'undefined') {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (!Array.isArray(source)) {
|
|
537
|
+
this.logger.warn(`[${languageId}: language configuration: expected \`surroundingPairs\` to be an array.`);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
let result: IAutoClosingPair[] | undefined;
|
|
542
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
543
|
+
const pair = source[i];
|
|
544
|
+
if (Array.isArray(pair)) {
|
|
545
|
+
if (!isCharacterPair(pair as unknown as [string, string])) {
|
|
546
|
+
this.logger.warn(
|
|
547
|
+
`[${languageId}: language configuration: expected \`surroundingPairs[${i}]\` to be an array of two strings or an object.`,
|
|
548
|
+
);
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
result = result || [];
|
|
552
|
+
result.push({ open: pair[0], close: pair[1] });
|
|
553
|
+
} else {
|
|
554
|
+
if (typeof pair !== 'object') {
|
|
555
|
+
this.logger.warn(
|
|
556
|
+
`[${languageId}: language configuration: expected \`surroundingPairs[${i}]\` to be an array of two strings or an object.`,
|
|
557
|
+
);
|
|
558
|
+
continue;
|
|
559
|
+
}
|
|
560
|
+
if (typeof pair.open !== 'string') {
|
|
561
|
+
this.logger.warn(
|
|
562
|
+
`[${languageId}: language configuration: expected \`surroundingPairs[${i}].open\` to be a string.`,
|
|
563
|
+
);
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
if (typeof pair.close !== 'string') {
|
|
567
|
+
this.logger.warn(
|
|
568
|
+
`[${languageId}: language configuration: expected \`surroundingPairs[${i}].close\` to be a string.`,
|
|
569
|
+
);
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
result = result || [];
|
|
573
|
+
result.push({ open: pair.open, close: pair.close });
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return result;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
private extractValidColorizedBracketPairs(
|
|
580
|
+
languageId: string,
|
|
581
|
+
configuration: LanguageConfigurationDto,
|
|
582
|
+
): CharacterPair[] | undefined {
|
|
583
|
+
const source = configuration.colorizedBracketPairs;
|
|
584
|
+
if (typeof source === 'undefined') {
|
|
585
|
+
return undefined;
|
|
586
|
+
}
|
|
587
|
+
if (!Array.isArray(source)) {
|
|
588
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`colorizedBracketPairs\` to be an array.`);
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const result: CharacterPair[] = [];
|
|
593
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
594
|
+
const pair = source[i];
|
|
595
|
+
if (!isCharacterPair(pair)) {
|
|
596
|
+
this.logger.warn(
|
|
597
|
+
`[${languageId}]: language configuration: expected \`colorizedBracketPairs[${i}]\` to be an array of two strings.`,
|
|
598
|
+
);
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
result.push([pair[0], pair[1]]);
|
|
602
|
+
}
|
|
603
|
+
return result;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
private extractValidOnEnterRules(
|
|
607
|
+
languageId: string,
|
|
608
|
+
configuration: LanguageConfigurationDto,
|
|
609
|
+
): OnEnterRule[] | undefined {
|
|
610
|
+
const source = configuration.onEnterRules;
|
|
611
|
+
if (typeof source === 'undefined') {
|
|
612
|
+
return undefined;
|
|
613
|
+
}
|
|
614
|
+
if (!Array.isArray(source)) {
|
|
615
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`onEnterRules\` to be an array.`);
|
|
616
|
+
return undefined;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
let result: OnEnterRule[] | undefined;
|
|
620
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
621
|
+
const onEnterRule = source[i];
|
|
622
|
+
if (!isObject(onEnterRule)) {
|
|
623
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`onEnterRules[${i}]\` to be an object.`);
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
if (!isObject(onEnterRule.action)) {
|
|
627
|
+
this.logger.warn(
|
|
628
|
+
`[${languageId}]: language configuration: expected \`onEnterRules[${i}].action\` to be an object.`,
|
|
629
|
+
);
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
632
|
+
let indentAction: IndentAction;
|
|
633
|
+
if (onEnterRule.action.indent === 'none') {
|
|
634
|
+
indentAction = IndentAction.None;
|
|
635
|
+
} else if (onEnterRule.action.indent === 'indent') {
|
|
636
|
+
indentAction = IndentAction.Indent;
|
|
637
|
+
} else if (onEnterRule.action.indent === 'indentOutdent') {
|
|
638
|
+
indentAction = IndentAction.IndentOutdent;
|
|
639
|
+
} else if (onEnterRule.action.indent === 'outdent') {
|
|
640
|
+
indentAction = IndentAction.Outdent;
|
|
641
|
+
} else {
|
|
642
|
+
this.logger.warn(
|
|
643
|
+
`[${languageId}]: language configuration: expected \`onEnterRules[${i}].action.indent\` to be 'none', 'indent', 'indentOutdent' or 'outdent'.`,
|
|
644
|
+
);
|
|
645
|
+
continue;
|
|
646
|
+
}
|
|
647
|
+
const action: EnterAction = { indentAction };
|
|
648
|
+
if (onEnterRule.action.appendText) {
|
|
649
|
+
if (typeof onEnterRule.action.appendText === 'string') {
|
|
650
|
+
action.appendText = onEnterRule.action.appendText;
|
|
651
|
+
} else {
|
|
652
|
+
this.logger.warn(
|
|
653
|
+
`[${languageId}]: language configuration: expected \`onEnterRules[${i}].action.appendText\` to be undefined or a string.`,
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
if (onEnterRule.action.removeText) {
|
|
658
|
+
if (typeof onEnterRule.action.removeText === 'number') {
|
|
659
|
+
action.removeText = onEnterRule.action.removeText;
|
|
660
|
+
} else {
|
|
661
|
+
this.logger.warn(
|
|
662
|
+
`[${languageId}]: language configuration: expected \`onEnterRules[${i}].action.removeText\` to be undefined or a number.`,
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
const beforeText = this.createRegex(onEnterRule.beforeText);
|
|
667
|
+
if (!beforeText) {
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
const resultingOnEnterRule: OnEnterRule = { beforeText, action };
|
|
671
|
+
if (onEnterRule.afterText) {
|
|
672
|
+
const afterText = this.createRegex(onEnterRule.afterText);
|
|
673
|
+
if (afterText) {
|
|
674
|
+
resultingOnEnterRule.afterText = afterText;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
if (onEnterRule.previousLineText) {
|
|
678
|
+
const previousLineText = this.createRegex(onEnterRule.previousLineText);
|
|
679
|
+
if (previousLineText) {
|
|
680
|
+
resultingOnEnterRule.previousLineText = previousLineText;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
result = result || [];
|
|
684
|
+
result.push(resultingOnEnterRule);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
return result;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
private extractValidBrackets(
|
|
691
|
+
languageId: string,
|
|
692
|
+
configuration: LanguageConfigurationDto,
|
|
693
|
+
): CharacterPair[] | undefined {
|
|
694
|
+
const source = configuration.brackets;
|
|
695
|
+
if (typeof source === 'undefined') {
|
|
696
|
+
return undefined;
|
|
697
|
+
}
|
|
698
|
+
if (!Array.isArray(source)) {
|
|
699
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`brackets\` to be an array.`);
|
|
700
|
+
return undefined;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
let result: CharacterPair[] | undefined;
|
|
704
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
705
|
+
const pair = source[i];
|
|
706
|
+
if (!isCharacterPair(pair)) {
|
|
707
|
+
this.logger.warn(
|
|
708
|
+
`[${languageId}]: language configuration: expected \`brackets[${i}]\` to be an array of two strings.`,
|
|
709
|
+
);
|
|
710
|
+
continue;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
result = result || [];
|
|
714
|
+
result.push(pair);
|
|
715
|
+
}
|
|
716
|
+
return result;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
private extractValidAutoClosingPairs(
|
|
720
|
+
languageId: string,
|
|
721
|
+
configuration: LanguageConfigurationDto,
|
|
722
|
+
): IAutoClosingPairConditional[] | undefined {
|
|
723
|
+
const source = configuration.autoClosingPairs;
|
|
724
|
+
if (typeof source === 'undefined') {
|
|
725
|
+
return undefined;
|
|
726
|
+
}
|
|
727
|
+
if (!Array.isArray(source)) {
|
|
728
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`autoClosingPairs\` to be an array.`);
|
|
729
|
+
return undefined;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
let result: IAutoClosingPairConditional[] | undefined;
|
|
733
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
734
|
+
const pair = source[i];
|
|
735
|
+
if (Array.isArray(pair)) {
|
|
736
|
+
if (!isCharacterPair(pair as unknown as [string, string])) {
|
|
737
|
+
this.logger.warn(
|
|
738
|
+
`[${languageId}]: language configuration: expected \`autoClosingPairs[${i}]\` to be an array of two strings or an object.`,
|
|
739
|
+
);
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
result = result || [];
|
|
743
|
+
result.push({ open: pair[0], close: pair[1] });
|
|
744
|
+
} else {
|
|
745
|
+
if (typeof pair !== 'object') {
|
|
746
|
+
this.logger.warn(
|
|
747
|
+
`[${languageId}]: language configuration: expected \`autoClosingPairs[${i}]\` to be an array of two strings or an object.`,
|
|
748
|
+
);
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
if (typeof pair.open !== 'string') {
|
|
752
|
+
this.logger.warn(
|
|
753
|
+
`[${languageId}]: language configuration: expected \`autoClosingPairs[${i}].open\` to be a string.`,
|
|
754
|
+
);
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
if (typeof pair.close !== 'string') {
|
|
758
|
+
this.logger.warn(
|
|
759
|
+
`[${languageId}]: language configuration: expected \`autoClosingPairs[${i}].close\` to be a string.`,
|
|
760
|
+
);
|
|
761
|
+
continue;
|
|
762
|
+
}
|
|
763
|
+
if (typeof pair.notIn !== 'undefined') {
|
|
764
|
+
if (!isStringArr(pair.notIn)) {
|
|
765
|
+
this.logger.warn(
|
|
766
|
+
`[${languageId}]: language configuration: expected \`autoClosingPairs[${i}].notIn\` to be a string array.`,
|
|
767
|
+
);
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
result = result || [];
|
|
772
|
+
result.push({ open: pair.open, close: pair.close, notIn: pair.notIn });
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
return result;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
private extractValidCommentRule(
|
|
779
|
+
languageId: string,
|
|
780
|
+
configuration: LanguageConfigurationDto,
|
|
781
|
+
): CommentRule | undefined {
|
|
782
|
+
const source = configuration.comments;
|
|
783
|
+
if (typeof source === 'undefined') {
|
|
784
|
+
return undefined;
|
|
785
|
+
}
|
|
786
|
+
if (typeof source !== 'object') {
|
|
787
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`comments\` to be an object.`);
|
|
788
|
+
return undefined;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
let result: CommentRule | undefined;
|
|
792
|
+
if (typeof source.lineComment !== 'undefined') {
|
|
793
|
+
if (typeof source.lineComment !== 'string') {
|
|
794
|
+
this.logger.warn(`[${languageId}]: language configuration: expected \`comments.lineComment\` to be a string.`);
|
|
795
|
+
} else {
|
|
796
|
+
result = result || {};
|
|
797
|
+
result.lineComment = source.lineComment;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (typeof source.blockComment !== 'undefined') {
|
|
801
|
+
if (!isCharacterPair(source.blockComment)) {
|
|
802
|
+
this.logger.warn(
|
|
803
|
+
`[${languageId}]: language configuration: expected \`comments.blockComment\` to be an array of two strings.`,
|
|
804
|
+
);
|
|
805
|
+
} else {
|
|
806
|
+
result = result || {};
|
|
807
|
+
result.blockComment = source.blockComment;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
return result;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
private async initGrammarRegistry() {
|
|
814
|
+
this.grammarRegistry = new Registry({
|
|
815
|
+
onigLib: this.getOnigLib(),
|
|
816
|
+
loadGrammar: async (scopeName: string) => {
|
|
817
|
+
const provider = this.textmateRegistry.getProvider(scopeName);
|
|
818
|
+
if (provider) {
|
|
819
|
+
const definition = await provider.getGrammarDefinition();
|
|
820
|
+
if (!definition.content) {
|
|
821
|
+
const ret = await this.fileServiceClient.resolveContent(definition.location.toString());
|
|
822
|
+
const content = ret.content;
|
|
823
|
+
definition.content = definition.format === 'json' ? this.safeParseJSON(content) : content;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
let rawGrammar: IRawGrammar;
|
|
827
|
+
if (typeof definition.content === 'string') {
|
|
828
|
+
rawGrammar = parseRawGrammar(
|
|
829
|
+
definition.content,
|
|
830
|
+
definition.format === 'json' ? 'grammar.json' : 'grammar.plist',
|
|
831
|
+
);
|
|
832
|
+
} else {
|
|
833
|
+
rawGrammar = definition.content as IRawGrammar;
|
|
834
|
+
}
|
|
835
|
+
return rawGrammar;
|
|
836
|
+
}
|
|
837
|
+
return undefined;
|
|
838
|
+
},
|
|
839
|
+
getInjections: (scopeName: string) => {
|
|
840
|
+
const provider = this.textmateRegistry.getProvider(scopeName);
|
|
841
|
+
if (provider && provider.getInjections) {
|
|
842
|
+
return provider.getInjections(scopeName);
|
|
843
|
+
}
|
|
844
|
+
return [];
|
|
845
|
+
},
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
this.activateLanguages();
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
getLanguages(): ILanguageExtensionPoint[] {
|
|
852
|
+
return [...monaco.languages.getLanguages(), ...this.dynamicLanguages];
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
private activateLanguages() {
|
|
856
|
+
for (const { id: languageId } of this.getLanguages()) {
|
|
857
|
+
if (this.editorDocumentModelService.hasLanguage(languageId)) {
|
|
858
|
+
this.activateLanguage(languageId);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
private async getOnigLib(): Promise<IOnigLib> {
|
|
864
|
+
// loadWasm 二次加载会报错 https://github.com/microsoft/vscode-oniguruma/blob/main/src/index.ts#L378
|
|
865
|
+
if (wasmLoaded) {
|
|
866
|
+
return new OnigasmLib();
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
let wasmUri: string;
|
|
870
|
+
if (this.appConfig.isElectronRenderer && electronEnv.onigWasmPath) {
|
|
871
|
+
wasmUri = URI.file(electronEnv.onigWasmPath).codeUri.toString();
|
|
872
|
+
} else if (this.appConfig.isElectronRenderer && electronEnv.onigWasmUri) {
|
|
873
|
+
wasmUri = electronEnv.onigWasmUri;
|
|
874
|
+
} else {
|
|
875
|
+
wasmUri =
|
|
876
|
+
this.appConfig.onigWasmUri ||
|
|
877
|
+
this.appConfig.onigWasmPath ||
|
|
878
|
+
'https://g.alicdn.com/kaitian/vscode-oniguruma-wasm/1.5.1/onig.wasm';
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
const response = await fetch(wasmUri);
|
|
882
|
+
const bytes = await response.arrayBuffer();
|
|
883
|
+
await loadWASM(bytes);
|
|
884
|
+
wasmLoaded = true;
|
|
885
|
+
return new OnigasmLib();
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
private listenPreferenceChange() {
|
|
889
|
+
this.preferenceService.onPreferenceChanged((e) => {
|
|
890
|
+
if (e.preferenceName === 'editor.maxTokenizationLineLength') {
|
|
891
|
+
for (const languageId of this.activatedLanguage) {
|
|
892
|
+
this.setTokensProviderByLanguageId(languageId);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
async testTokenize(line: string, languageId: string) {
|
|
899
|
+
const scopeName = this.textmateRegistry.getScope(languageId);
|
|
900
|
+
if (!scopeName) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
const configuration = this.textmateRegistry.getGrammarConfiguration(languageId)();
|
|
904
|
+
const initialLanguage = getEncodedLanguageId(languageId);
|
|
905
|
+
const grammar = (await this.grammarRegistry.loadGrammarWithConfiguration(
|
|
906
|
+
scopeName,
|
|
907
|
+
initialLanguage,
|
|
908
|
+
configuration,
|
|
909
|
+
))!;
|
|
910
|
+
let ruleStack = INITIAL;
|
|
911
|
+
const lineTokens = grammar.tokenizeLine(line, ruleStack);
|
|
912
|
+
const debugLogger = getDebugLogger('tokenize');
|
|
913
|
+
debugLogger.log(`\nTokenizing line: ${line}`);
|
|
914
|
+
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
915
|
+
for (let j = 0; j < lineTokens.tokens.length; j++) {
|
|
916
|
+
const token = lineTokens.tokens[j];
|
|
917
|
+
debugLogger.log(
|
|
918
|
+
` - token from ${token.startIndex} to ${token.endIndex} ` +
|
|
919
|
+
`(${line.substring(token.startIndex, token.endIndex)}) ` +
|
|
920
|
+
`with scopes ${token.scopes.join(', ')}`,
|
|
921
|
+
);
|
|
922
|
+
}
|
|
923
|
+
ruleStack = lineTokens.ruleStack;
|
|
924
|
+
}
|
|
925
|
+
}
|