forked from TypeFox/monaco-languageclient
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
128 lines (109 loc) · 5.56 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* --------------------------------------------------------------------------------------------
* Copyright (c) 2024 TypeFox GmbH (http://www.typefox.io). All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { languages, workspace, TextDocument as VsCodeTextDocument } from 'vscode';
import { getLanguageService, TextDocument } from 'vscode-json-languageservice';
import { createConverter as createCodeConverter } from 'vscode-languageclient/lib/common/codeConverter.js';
import { createConverter as createProtocolConverter } from 'vscode-languageclient/lib/common/protocolConverter.js';
import { createDefaultJsonContent, createJsonEditor, performInit } from '../json/client/main.js';
import '@codingame/monaco-vscode-theme-defaults-default-extension';
import '@codingame/monaco-vscode-json-default-extension';
const codeConverter = createCodeConverter();
const protocolConverter = createProtocolConverter(undefined, true, true);
export const startBrowserEditor = async () => {
let mainVscodeDocument: VsCodeTextDocument | undefined;
const languageId = 'json';
await performInit(true);
workspace.onDidOpenTextDocument((_event) => {
mainVscodeDocument = workspace.textDocuments[0];
});
const jsonEditor = await createJsonEditor({
htmlElement: document.getElementById('container')!,
content: createDefaultJsonContent()
});
const createDocument = (vscodeDocument: VsCodeTextDocument) => {
return TextDocument.create(vscodeDocument.uri.toString(), vscodeDocument.languageId, vscodeDocument.version, vscodeDocument.getText());
};
const resolveSchema = (url: string): Promise<string> => {
const promise = new Promise<string>((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onload = () => resolve(xhr.responseText);
xhr.onerror = () => reject(xhr.statusText);
xhr.open('GET', url, true);
xhr.send();
});
return promise;
};
const jsonService = getLanguageService({
schemaRequestService: resolveSchema
});
const pendingValidationRequests = new Map<string, number>();
languages.registerCompletionItemProvider(languageId, {
async provideCompletionItems(vscodeDocument, position, _token, _context) {
const document = createDocument(vscodeDocument);
const jsonDocument = jsonService.parseJSONDocument(document);
const completionList = await jsonService.doComplete(document, codeConverter.asPosition(position), jsonDocument);
return protocolConverter.asCompletionResult(completionList);
},
async resolveCompletionItem(item, _token) {
return await jsonService.doResolve(codeConverter.asCompletionItem(item)).then(result => protocolConverter.asCompletionItem(result));
}
});
languages.registerDocumentRangeFormattingEditProvider(languageId, {
provideDocumentRangeFormattingEdits(vscodeDocument, range, options, _token) {
const document = createDocument(vscodeDocument);
const edits = jsonService.format(document, codeConverter.asRange(range), codeConverter.asFormattingOptions(options, {}));
return protocolConverter.asTextEdits(edits);
}
});
languages.registerDocumentSymbolProvider(languageId, {
provideDocumentSymbols(vscodeDocument, _token) {
const document = createDocument(vscodeDocument);
const jsonDocument = jsonService.parseJSONDocument(document);
return protocolConverter.asSymbolInformations(jsonService.findDocumentSymbols(document, jsonDocument));
}
});
languages.registerHoverProvider(languageId, {
async provideHover(vscodeDocument, position, _token) {
const document = createDocument(vscodeDocument);
const jsonDocument = jsonService.parseJSONDocument(document);
return await jsonService.doHover(document, codeConverter.asPosition(position), jsonDocument).then((hover) => {
return protocolConverter.asHover(hover)!;
});
}
});
const validate = () => {
const document = createDocument(mainVscodeDocument!);
cleanPendingValidation(document);
pendingValidationRequests.set(document.uri, window.setTimeout(() => {
pendingValidationRequests.delete(document.uri);
doValidate(document);
}));
};
const cleanPendingValidation = (document: TextDocument) => {
const request = pendingValidationRequests.get(document.uri);
if (request !== undefined) {
window.clearTimeout(request);
pendingValidationRequests.delete(document.uri);
}
};
const diagnosticCollection = languages.createDiagnosticCollection('json');
const doValidate = (document: TextDocument) => {
if (document.getText().length === 0) {
cleanDiagnostics();
return;
}
const jsonDocument = jsonService.parseJSONDocument(document);
jsonService.doValidation(document, jsonDocument).then(async (pDiagnostics) => {
const diagnostics = await protocolConverter.asDiagnostics(pDiagnostics);
diagnosticCollection.set(jsonEditor.uri, diagnostics);
});
};
const cleanDiagnostics = () => {
diagnosticCollection.clear();
};
jsonEditor.modelRef.object.textEditorModel!.onDidChangeContent(() => {
validate();
});
};