Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/extension-editing/src/packageDocumentHelper.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as vscode from 'vscode';
7
import { getLocation, Location } from 'jsonc-parser';
8
import { implicitActivationEvent, redundantImplicitActivationEvent } from './constants';
9
10
11
export class PackageDocument {
12
13
constructor(private document: vscode.TextDocument) { }
14
15
public provideCompletionItems(position: vscode.Position, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.CompletionItem[]> {
16
const location = getLocation(this.document.getText(), this.document.offsetAt(position));
17
18
if (location.path.length >= 2 && location.path[1] === 'configurationDefaults') {
19
return this.provideLanguageOverridesCompletionItems(location, position);
20
}
21
22
return undefined;
23
}
24
25
public provideCodeActions(_range: vscode.Range, context: vscode.CodeActionContext, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.CodeAction[]> {
26
const codeActions: vscode.CodeAction[] = [];
27
for (const diagnostic of context.diagnostics) {
28
if (diagnostic.message === implicitActivationEvent || diagnostic.message === redundantImplicitActivationEvent) {
29
const codeAction = new vscode.CodeAction(vscode.l10n.t("Remove activation event"), vscode.CodeActionKind.QuickFix);
30
codeAction.edit = new vscode.WorkspaceEdit();
31
const rangeForCharAfter = diagnostic.range.with(diagnostic.range.end, diagnostic.range.end.translate(0, 1));
32
if (this.document.getText(rangeForCharAfter) === ',') {
33
codeAction.edit.delete(this.document.uri, diagnostic.range.with(undefined, diagnostic.range.end.translate(0, 1)));
34
} else {
35
codeAction.edit.delete(this.document.uri, diagnostic.range);
36
}
37
codeActions.push(codeAction);
38
}
39
}
40
return codeActions;
41
}
42
43
private provideLanguageOverridesCompletionItems(location: Location, position: vscode.Position): vscode.ProviderResult<vscode.CompletionItem[]> {
44
let range = this.getReplaceRange(location, position);
45
const text = this.document.getText(range);
46
47
if (location.path.length === 2) {
48
49
let snippet = '"[${1:language}]": {\n\t"$0"\n}';
50
51
// Suggestion model word matching includes quotes,
52
// hence exclude the starting quote from the snippet and the range
53
// ending quote gets replaced
54
if (text && text.startsWith('"')) {
55
range = new vscode.Range(new vscode.Position(range.start.line, range.start.character + 1), range.end);
56
snippet = snippet.substring(1);
57
}
58
59
return Promise.resolve([this.newSnippetCompletionItem({
60
label: vscode.l10n.t("Language specific editor settings"),
61
documentation: vscode.l10n.t("Override editor settings for language"),
62
snippet,
63
range
64
})]);
65
}
66
67
if (location.path.length === 3 && location.previousNode && typeof location.previousNode.value === 'string' && location.previousNode.value.startsWith('[')) {
68
69
// Suggestion model word matching includes starting quote and open sqaure bracket
70
// Hence exclude them from the proposal range
71
range = new vscode.Range(new vscode.Position(range.start.line, range.start.character + 2), range.end);
72
73
return vscode.languages.getLanguages().then(languages => {
74
return languages.map(l => {
75
76
// Suggestion model word matching includes closed sqaure bracket and ending quote
77
// Hence include them in the proposal to replace
78
return this.newSimpleCompletionItem(l, range, '', l + ']"');
79
});
80
});
81
}
82
return Promise.resolve([]);
83
}
84
85
private getReplaceRange(location: Location, position: vscode.Position) {
86
const node = location.previousNode;
87
if (node) {
88
const nodeStart = this.document.positionAt(node.offset), nodeEnd = this.document.positionAt(node.offset + node.length);
89
if (nodeStart.isBeforeOrEqual(position) && nodeEnd.isAfterOrEqual(position)) {
90
return new vscode.Range(nodeStart, nodeEnd);
91
}
92
}
93
return new vscode.Range(position, position);
94
}
95
96
private newSimpleCompletionItem(text: string, range: vscode.Range, description?: string, insertText?: string): vscode.CompletionItem {
97
const item = new vscode.CompletionItem(text);
98
item.kind = vscode.CompletionItemKind.Value;
99
item.detail = description;
100
item.insertText = insertText ? insertText : text;
101
item.range = range;
102
return item;
103
}
104
105
private newSnippetCompletionItem(o: { label: string; documentation?: string; snippet: string; range: vscode.Range }): vscode.CompletionItem {
106
const item = new vscode.CompletionItem(o.label);
107
item.kind = vscode.CompletionItemKind.Value;
108
item.documentation = o.documentation;
109
item.insertText = new vscode.SnippetString(o.snippet);
110
item.range = o.range;
111
return item;
112
}
113
}
114
115