vscode-json-languageservice 4.2.0 → 5.1.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/CHANGELOG.md +10 -1
- package/SECURITY.md +41 -0
- package/lib/esm/jsonLanguageService.js +22 -22
- package/lib/esm/jsonLanguageTypes.d.ts +3 -1
- package/lib/esm/jsonLanguageTypes.js +3 -2
- package/lib/esm/jsonSchema.d.ts +21 -2
- package/lib/esm/parser/jsonParser.js +488 -488
- package/lib/esm/services/configuration.js +9 -9
- package/lib/esm/services/jsonCompletion.js +280 -290
- package/lib/esm/services/jsonDocumentSymbols.js +88 -99
- package/lib/esm/services/jsonFolding.js +38 -39
- package/lib/esm/services/jsonHover.js +40 -43
- package/lib/esm/services/jsonLinks.js +12 -13
- package/lib/esm/services/jsonSchemaService.js +234 -253
- package/lib/esm/services/jsonSelectionRanges.js +9 -9
- package/lib/esm/services/jsonValidation.js +53 -51
- package/lib/esm/utils/colors.js +7 -8
- package/lib/esm/utils/glob.js +12 -12
- package/lib/esm/utils/json.js +7 -7
- package/lib/esm/utils/objects.js +3 -0
- package/lib/esm/utils/strings.js +3 -3
- package/lib/umd/jsonLanguageService.js +36 -32
- package/lib/umd/jsonLanguageTypes.d.ts +3 -1
- package/lib/umd/jsonLanguageTypes.js +5 -3
- package/lib/umd/jsonSchema.d.ts +21 -2
- package/lib/umd/parser/jsonParser.js +492 -482
- package/lib/umd/services/configuration.js +9 -9
- package/lib/umd/services/jsonCompletion.js +287 -296
- package/lib/umd/services/jsonDocumentSymbols.js +92 -102
- package/lib/umd/services/jsonFolding.js +40 -41
- package/lib/umd/services/jsonHover.js +42 -44
- package/lib/umd/services/jsonLinks.js +13 -14
- package/lib/umd/services/jsonSchemaService.js +241 -257
- package/lib/umd/services/jsonSelectionRanges.js +11 -11
- package/lib/umd/services/jsonValidation.js +56 -53
- package/lib/umd/utils/colors.js +7 -8
- package/lib/umd/utils/glob.js +12 -12
- package/lib/umd/utils/json.js +7 -7
- package/lib/umd/utils/objects.js +5 -1
- package/lib/umd/utils/strings.js +3 -3
- package/package.json +12 -12
|
@@ -6,68 +6,64 @@ import * as Parser from '../parser/jsonParser';
|
|
|
6
6
|
import * as Strings from '../utils/strings';
|
|
7
7
|
import { colorFromHex } from '../utils/colors';
|
|
8
8
|
import { Range, TextEdit, SymbolKind, Location } from "../jsonLanguageTypes";
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
export class JSONDocumentSymbols {
|
|
10
|
+
constructor(schemaService) {
|
|
11
11
|
this.schemaService = schemaService;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; }
|
|
16
|
-
var root = doc.root;
|
|
13
|
+
findDocumentSymbols(document, doc, context = { resultLimit: Number.MAX_VALUE }) {
|
|
14
|
+
const root = doc.root;
|
|
17
15
|
if (!root) {
|
|
18
16
|
return [];
|
|
19
17
|
}
|
|
20
|
-
|
|
18
|
+
let limit = context.resultLimit || Number.MAX_VALUE;
|
|
21
19
|
// special handling for key bindings
|
|
22
|
-
|
|
20
|
+
const resourceString = document.uri;
|
|
23
21
|
if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
|
|
24
22
|
if (root.type === 'array') {
|
|
25
|
-
|
|
26
|
-
for (
|
|
27
|
-
var item = _a[_i];
|
|
23
|
+
const result = [];
|
|
24
|
+
for (const item of root.items) {
|
|
28
25
|
if (item.type === 'object') {
|
|
29
|
-
for (
|
|
30
|
-
var property = _c[_b];
|
|
26
|
+
for (const property of item.properties) {
|
|
31
27
|
if (property.keyNode.value === 'key' && property.valueNode) {
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
const location = Location.create(document.uri, getRange(document, item));
|
|
29
|
+
result.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, location: location });
|
|
34
30
|
limit--;
|
|
35
31
|
if (limit <= 0) {
|
|
36
32
|
if (context && context.onResultLimitExceeded) {
|
|
37
33
|
context.onResultLimitExceeded(resourceString);
|
|
38
34
|
}
|
|
39
|
-
return
|
|
35
|
+
return result;
|
|
40
36
|
}
|
|
41
37
|
}
|
|
42
38
|
}
|
|
43
39
|
}
|
|
44
40
|
}
|
|
45
|
-
return
|
|
41
|
+
return result;
|
|
46
42
|
}
|
|
47
43
|
}
|
|
48
|
-
|
|
44
|
+
const toVisit = [
|
|
49
45
|
{ node: root, containerName: '' }
|
|
50
46
|
];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
let nextToVisit = 0;
|
|
48
|
+
let limitExceeded = false;
|
|
49
|
+
const result = [];
|
|
50
|
+
const collectOutlineEntries = (node, containerName) => {
|
|
55
51
|
if (node.type === 'array') {
|
|
56
|
-
node.items.forEach(
|
|
52
|
+
node.items.forEach(node => {
|
|
57
53
|
if (node) {
|
|
58
|
-
toVisit.push({ node
|
|
54
|
+
toVisit.push({ node, containerName });
|
|
59
55
|
}
|
|
60
56
|
});
|
|
61
57
|
}
|
|
62
58
|
else if (node.type === 'object') {
|
|
63
|
-
node.properties.forEach(
|
|
64
|
-
|
|
59
|
+
node.properties.forEach((property) => {
|
|
60
|
+
const valueNode = property.valueNode;
|
|
65
61
|
if (valueNode) {
|
|
66
62
|
if (limit > 0) {
|
|
67
63
|
limit--;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
result.push({ name:
|
|
64
|
+
const location = Location.create(document.uri, getRange(document, property));
|
|
65
|
+
const childContainerName = containerName ? containerName + '.' + property.keyNode.value : property.keyNode.value;
|
|
66
|
+
result.push({ name: this.getKeyLabel(property), kind: this.getSymbolKind(valueNode.type), location: location, containerName: containerName });
|
|
71
67
|
toVisit.push({ node: valueNode, containerName: childContainerName });
|
|
72
68
|
}
|
|
73
69
|
else {
|
|
@@ -79,68 +75,64 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
79
75
|
};
|
|
80
76
|
// breath first traversal
|
|
81
77
|
while (nextToVisit < toVisit.length) {
|
|
82
|
-
|
|
78
|
+
const next = toVisit[nextToVisit++];
|
|
83
79
|
collectOutlineEntries(next.node, next.containerName);
|
|
84
80
|
}
|
|
85
81
|
if (limitExceeded && context && context.onResultLimitExceeded) {
|
|
86
82
|
context.onResultLimitExceeded(resourceString);
|
|
87
83
|
}
|
|
88
84
|
return result;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; }
|
|
93
|
-
var root = doc.root;
|
|
85
|
+
}
|
|
86
|
+
findDocumentSymbols2(document, doc, context = { resultLimit: Number.MAX_VALUE }) {
|
|
87
|
+
const root = doc.root;
|
|
94
88
|
if (!root) {
|
|
95
89
|
return [];
|
|
96
90
|
}
|
|
97
|
-
|
|
91
|
+
let limit = context.resultLimit || Number.MAX_VALUE;
|
|
98
92
|
// special handling for key bindings
|
|
99
|
-
|
|
93
|
+
const resourceString = document.uri;
|
|
100
94
|
if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
|
|
101
95
|
if (root.type === 'array') {
|
|
102
|
-
|
|
103
|
-
for (
|
|
104
|
-
var item = _a[_i];
|
|
96
|
+
const result = [];
|
|
97
|
+
for (const item of root.items) {
|
|
105
98
|
if (item.type === 'object') {
|
|
106
|
-
for (
|
|
107
|
-
var property = _c[_b];
|
|
99
|
+
for (const property of item.properties) {
|
|
108
100
|
if (property.keyNode.value === 'key' && property.valueNode) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
101
|
+
const range = getRange(document, item);
|
|
102
|
+
const selectionRange = getRange(document, property.keyNode);
|
|
103
|
+
result.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, range, selectionRange });
|
|
112
104
|
limit--;
|
|
113
105
|
if (limit <= 0) {
|
|
114
106
|
if (context && context.onResultLimitExceeded) {
|
|
115
107
|
context.onResultLimitExceeded(resourceString);
|
|
116
108
|
}
|
|
117
|
-
return
|
|
109
|
+
return result;
|
|
118
110
|
}
|
|
119
111
|
}
|
|
120
112
|
}
|
|
121
113
|
}
|
|
122
114
|
}
|
|
123
|
-
return
|
|
115
|
+
return result;
|
|
124
116
|
}
|
|
125
117
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
{ node: root, result
|
|
118
|
+
const result = [];
|
|
119
|
+
const toVisit = [
|
|
120
|
+
{ node: root, result }
|
|
129
121
|
];
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
122
|
+
let nextToVisit = 0;
|
|
123
|
+
let limitExceeded = false;
|
|
124
|
+
const collectOutlineEntries = (node, result) => {
|
|
133
125
|
if (node.type === 'array') {
|
|
134
|
-
node.items.forEach(
|
|
126
|
+
node.items.forEach((node, index) => {
|
|
135
127
|
if (node) {
|
|
136
128
|
if (limit > 0) {
|
|
137
129
|
limit--;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
130
|
+
const range = getRange(document, node);
|
|
131
|
+
const selectionRange = range;
|
|
132
|
+
const name = String(index);
|
|
133
|
+
const symbol = { name, kind: this.getSymbolKind(node.type), range, selectionRange, children: [] };
|
|
142
134
|
result.push(symbol);
|
|
143
|
-
toVisit.push({ result: symbol.children, node
|
|
135
|
+
toVisit.push({ result: symbol.children, node });
|
|
144
136
|
}
|
|
145
137
|
else {
|
|
146
138
|
limitExceeded = true;
|
|
@@ -149,15 +141,15 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
149
141
|
});
|
|
150
142
|
}
|
|
151
143
|
else if (node.type === 'object') {
|
|
152
|
-
node.properties.forEach(
|
|
153
|
-
|
|
144
|
+
node.properties.forEach((property) => {
|
|
145
|
+
const valueNode = property.valueNode;
|
|
154
146
|
if (valueNode) {
|
|
155
147
|
if (limit > 0) {
|
|
156
148
|
limit--;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
149
|
+
const range = getRange(document, property);
|
|
150
|
+
const selectionRange = getRange(document, property.keyNode);
|
|
151
|
+
const children = [];
|
|
152
|
+
const symbol = { name: this.getKeyLabel(property), kind: this.getSymbolKind(valueNode.type), range, selectionRange, children, detail: this.getDetail(valueNode) };
|
|
161
153
|
result.push(symbol);
|
|
162
154
|
toVisit.push({ result: children, node: valueNode });
|
|
163
155
|
}
|
|
@@ -170,15 +162,15 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
170
162
|
};
|
|
171
163
|
// breath first traversal
|
|
172
164
|
while (nextToVisit < toVisit.length) {
|
|
173
|
-
|
|
165
|
+
const next = toVisit[nextToVisit++];
|
|
174
166
|
collectOutlineEntries(next.node, next.result);
|
|
175
167
|
}
|
|
176
168
|
if (limitExceeded && context && context.onResultLimitExceeded) {
|
|
177
169
|
context.onResultLimitExceeded(resourceString);
|
|
178
170
|
}
|
|
179
171
|
return result;
|
|
180
|
-
}
|
|
181
|
-
|
|
172
|
+
}
|
|
173
|
+
getSymbolKind(nodeType) {
|
|
182
174
|
switch (nodeType) {
|
|
183
175
|
case 'object':
|
|
184
176
|
return SymbolKind.Module;
|
|
@@ -193,18 +185,18 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
193
185
|
default: // 'null'
|
|
194
186
|
return SymbolKind.Variable;
|
|
195
187
|
}
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
|
|
188
|
+
}
|
|
189
|
+
getKeyLabel(property) {
|
|
190
|
+
let name = property.keyNode.value;
|
|
199
191
|
if (name) {
|
|
200
192
|
name = name.replace(/[\n]/g, '↵');
|
|
201
193
|
}
|
|
202
194
|
if (name && name.trim()) {
|
|
203
195
|
return name;
|
|
204
196
|
}
|
|
205
|
-
return "
|
|
206
|
-
}
|
|
207
|
-
|
|
197
|
+
return `"${name}"`;
|
|
198
|
+
}
|
|
199
|
+
getDetail(node) {
|
|
208
200
|
if (!node) {
|
|
209
201
|
return undefined;
|
|
210
202
|
}
|
|
@@ -220,23 +212,22 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
220
212
|
}
|
|
221
213
|
}
|
|
222
214
|
return undefined;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return this.schemaService.getSchemaForResource(document.uri, doc).then(
|
|
226
|
-
|
|
215
|
+
}
|
|
216
|
+
findDocumentColors(document, doc, context) {
|
|
217
|
+
return this.schemaService.getSchemaForResource(document.uri, doc).then(schema => {
|
|
218
|
+
const result = [];
|
|
227
219
|
if (schema) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
for (
|
|
232
|
-
var s = matchingSchemas_1[_i];
|
|
220
|
+
let limit = context && typeof context.resultLimit === 'number' ? context.resultLimit : Number.MAX_VALUE;
|
|
221
|
+
const matchingSchemas = doc.getMatchingSchemas(schema.schema);
|
|
222
|
+
const visitedNode = {};
|
|
223
|
+
for (const s of matchingSchemas) {
|
|
233
224
|
if (!s.inverted && s.schema && (s.schema.format === 'color' || s.schema.format === 'color-hex') && s.node && s.node.type === 'string') {
|
|
234
|
-
|
|
225
|
+
const nodeId = String(s.node.offset);
|
|
235
226
|
if (!visitedNode[nodeId]) {
|
|
236
|
-
|
|
227
|
+
const color = colorFromHex(Parser.getNodeValue(s.node));
|
|
237
228
|
if (color) {
|
|
238
|
-
|
|
239
|
-
result.push({ color
|
|
229
|
+
const range = getRange(document, s.node);
|
|
230
|
+
result.push({ color, range });
|
|
240
231
|
}
|
|
241
232
|
visitedNode[nodeId] = true;
|
|
242
233
|
limit--;
|
|
@@ -252,27 +243,25 @@ var JSONDocumentSymbols = /** @class */ (function () {
|
|
|
252
243
|
}
|
|
253
244
|
return result;
|
|
254
245
|
});
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
246
|
+
}
|
|
247
|
+
getColorPresentations(document, doc, color, range) {
|
|
248
|
+
const result = [];
|
|
249
|
+
const red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255);
|
|
259
250
|
function toTwoDigitHex(n) {
|
|
260
|
-
|
|
251
|
+
const r = n.toString(16);
|
|
261
252
|
return r.length !== 2 ? '0' + r : r;
|
|
262
253
|
}
|
|
263
|
-
|
|
254
|
+
let label;
|
|
264
255
|
if (color.alpha === 1) {
|
|
265
|
-
label =
|
|
256
|
+
label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}`;
|
|
266
257
|
}
|
|
267
258
|
else {
|
|
268
|
-
label =
|
|
259
|
+
label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}${toTwoDigitHex(Math.round(color.alpha * 255))}`;
|
|
269
260
|
}
|
|
270
261
|
result.push({ label: label, textEdit: TextEdit.replace(range, JSON.stringify(label)) });
|
|
271
262
|
return result;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
}());
|
|
275
|
-
export { JSONDocumentSymbols };
|
|
263
|
+
}
|
|
264
|
+
}
|
|
276
265
|
function getRange(document, node) {
|
|
277
266
|
return Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
|
|
278
267
|
}
|
|
@@ -5,31 +5,31 @@
|
|
|
5
5
|
import { createScanner } from 'jsonc-parser';
|
|
6
6
|
import { FoldingRangeKind, Position } from '../jsonLanguageTypes';
|
|
7
7
|
export function getFoldingRanges(document, context) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const ranges = [];
|
|
9
|
+
const nestingLevels = [];
|
|
10
|
+
const stack = [];
|
|
11
|
+
let prevStart = -1;
|
|
12
|
+
const scanner = createScanner(document.getText(), false);
|
|
13
|
+
let token = scanner.scan();
|
|
14
14
|
function addRange(range) {
|
|
15
15
|
ranges.push(range);
|
|
16
16
|
nestingLevels.push(stack.length);
|
|
17
17
|
}
|
|
18
|
-
while (token !== 17 /* EOF */) {
|
|
18
|
+
while (token !== 17 /* SyntaxKind.EOF */) {
|
|
19
19
|
switch (token) {
|
|
20
|
-
case 1 /* OpenBraceToken */:
|
|
21
|
-
case 3 /* OpenBracketToken */: {
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
case 1 /* SyntaxKind.OpenBraceToken */:
|
|
21
|
+
case 3 /* SyntaxKind.OpenBracketToken */: {
|
|
22
|
+
const startLine = document.positionAt(scanner.getTokenOffset()).line;
|
|
23
|
+
const range = { startLine, endLine: startLine, kind: token === 1 /* SyntaxKind.OpenBraceToken */ ? 'object' : 'array' };
|
|
24
24
|
stack.push(range);
|
|
25
25
|
break;
|
|
26
26
|
}
|
|
27
|
-
case 2 /* CloseBraceToken */:
|
|
28
|
-
case 4 /* CloseBracketToken */: {
|
|
29
|
-
|
|
27
|
+
case 2 /* SyntaxKind.CloseBraceToken */:
|
|
28
|
+
case 4 /* SyntaxKind.CloseBracketToken */: {
|
|
29
|
+
const kind = token === 2 /* SyntaxKind.CloseBraceToken */ ? 'object' : 'array';
|
|
30
30
|
if (stack.length > 0 && stack[stack.length - 1].kind === kind) {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const range = stack.pop();
|
|
32
|
+
const line = document.positionAt(scanner.getTokenOffset()).line;
|
|
33
33
|
if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
|
|
34
34
|
range.endLine = line - 1;
|
|
35
35
|
addRange(range);
|
|
@@ -38,36 +38,36 @@ export function getFoldingRanges(document, context) {
|
|
|
38
38
|
}
|
|
39
39
|
break;
|
|
40
40
|
}
|
|
41
|
-
case 13 /* BlockCommentTrivia */: {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (scanner.getTokenError() === 1 /* UnexpectedEndOfComment */ && startLine + 1 < document.lineCount) {
|
|
41
|
+
case 13 /* SyntaxKind.BlockCommentTrivia */: {
|
|
42
|
+
const startLine = document.positionAt(scanner.getTokenOffset()).line;
|
|
43
|
+
const endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
|
|
44
|
+
if (scanner.getTokenError() === 1 /* ScanError.UnexpectedEndOfComment */ && startLine + 1 < document.lineCount) {
|
|
45
45
|
scanner.setPosition(document.offsetAt(Position.create(startLine + 1, 0)));
|
|
46
46
|
}
|
|
47
47
|
else {
|
|
48
48
|
if (startLine < endLine) {
|
|
49
|
-
addRange({ startLine
|
|
49
|
+
addRange({ startLine, endLine, kind: FoldingRangeKind.Comment });
|
|
50
50
|
prevStart = startLine;
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
break;
|
|
54
54
|
}
|
|
55
|
-
case 12 /* LineCommentTrivia */: {
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
case 12 /* SyntaxKind.LineCommentTrivia */: {
|
|
56
|
+
const text = document.getText().substr(scanner.getTokenOffset(), scanner.getTokenLength());
|
|
57
|
+
const m = text.match(/^\/\/\s*#(region\b)|(endregion\b)/);
|
|
58
58
|
if (m) {
|
|
59
|
-
|
|
59
|
+
const line = document.positionAt(scanner.getTokenOffset()).line;
|
|
60
60
|
if (m[1]) { // start pattern match
|
|
61
|
-
|
|
61
|
+
const range = { startLine: line, endLine: line, kind: FoldingRangeKind.Region };
|
|
62
62
|
stack.push(range);
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
|
|
65
|
+
let i = stack.length - 1;
|
|
66
66
|
while (i >= 0 && stack[i].kind !== FoldingRangeKind.Region) {
|
|
67
67
|
i--;
|
|
68
68
|
}
|
|
69
69
|
if (i >= 0) {
|
|
70
|
-
|
|
70
|
+
const range = stack[i];
|
|
71
71
|
stack.length = i;
|
|
72
72
|
if (line > range.startLine && prevStart !== range.startLine) {
|
|
73
73
|
range.endLine = line;
|
|
@@ -82,24 +82,23 @@ export function getFoldingRanges(document, context) {
|
|
|
82
82
|
}
|
|
83
83
|
token = scanner.scan();
|
|
84
84
|
}
|
|
85
|
-
|
|
85
|
+
const rangeLimit = context && context.rangeLimit;
|
|
86
86
|
if (typeof rangeLimit !== 'number' || ranges.length <= rangeLimit) {
|
|
87
87
|
return ranges;
|
|
88
88
|
}
|
|
89
89
|
if (context && context.onRangeLimitExceeded) {
|
|
90
90
|
context.onRangeLimitExceeded(document.uri);
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
for (
|
|
94
|
-
var level = nestingLevels_1[_i];
|
|
92
|
+
const counts = [];
|
|
93
|
+
for (let level of nestingLevels) {
|
|
95
94
|
if (level < 30) {
|
|
96
95
|
counts[level] = (counts[level] || 0) + 1;
|
|
97
96
|
}
|
|
98
97
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
for (
|
|
102
|
-
|
|
98
|
+
let entries = 0;
|
|
99
|
+
let maxLevel = 0;
|
|
100
|
+
for (let i = 0; i < counts.length; i++) {
|
|
101
|
+
const n = counts[i];
|
|
103
102
|
if (n) {
|
|
104
103
|
if (n + entries > rangeLimit) {
|
|
105
104
|
maxLevel = i;
|
|
@@ -108,9 +107,9 @@ export function getFoldingRanges(document, context) {
|
|
|
108
107
|
entries += n;
|
|
109
108
|
}
|
|
110
109
|
}
|
|
111
|
-
|
|
112
|
-
for (
|
|
113
|
-
|
|
110
|
+
const result = [];
|
|
111
|
+
for (let i = 0; i < ranges.length; i++) {
|
|
112
|
+
const level = nestingLevels[i];
|
|
114
113
|
if (typeof level === 'number') {
|
|
115
114
|
if (level < maxLevel || (level === maxLevel && entries++ < rangeLimit)) {
|
|
116
115
|
result.push(ranges[i]);
|
|
@@ -4,23 +4,22 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as Parser from '../parser/jsonParser';
|
|
6
6
|
import { Range } from '../jsonLanguageTypes';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (contributions === void 0) { contributions = []; }
|
|
7
|
+
export class JSONHover {
|
|
8
|
+
constructor(schemaService, contributions = [], promiseConstructor) {
|
|
10
9
|
this.schemaService = schemaService;
|
|
11
10
|
this.contributions = contributions;
|
|
12
11
|
this.promise = promiseConstructor || Promise;
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
doHover(document, position, doc) {
|
|
14
|
+
const offset = document.offsetAt(position);
|
|
15
|
+
let node = doc.getNodeFromOffset(offset);
|
|
17
16
|
if (!node || (node.type === 'object' || node.type === 'array') && offset > node.offset + 1 && offset < node.offset + node.length - 1) {
|
|
18
17
|
return this.promise.resolve(null);
|
|
19
18
|
}
|
|
20
|
-
|
|
19
|
+
const hoverRangeNode = node;
|
|
21
20
|
// use the property description when hovering over an object key
|
|
22
21
|
if (node.type === 'string') {
|
|
23
|
-
|
|
22
|
+
const parent = node.parent;
|
|
24
23
|
if (parent && parent.type === 'property' && parent.keyNode === node) {
|
|
25
24
|
node = parent.valueNode;
|
|
26
25
|
if (!node) {
|
|
@@ -28,77 +27,75 @@ var JSONHover = /** @class */ (function () {
|
|
|
28
27
|
}
|
|
29
28
|
}
|
|
30
29
|
}
|
|
31
|
-
|
|
32
|
-
var createHover =
|
|
33
|
-
|
|
30
|
+
const hoverRange = Range.create(document.positionAt(hoverRangeNode.offset), document.positionAt(hoverRangeNode.offset + hoverRangeNode.length));
|
|
31
|
+
var createHover = (contents) => {
|
|
32
|
+
const result = {
|
|
34
33
|
contents: contents,
|
|
35
34
|
range: hoverRange
|
|
36
35
|
};
|
|
37
36
|
return result;
|
|
38
37
|
};
|
|
39
|
-
|
|
40
|
-
for (
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
const location = Parser.getNodePath(node);
|
|
39
|
+
for (let i = this.contributions.length - 1; i >= 0; i--) {
|
|
40
|
+
const contribution = this.contributions[i];
|
|
41
|
+
const promise = contribution.getInfoContribution(document.uri, location);
|
|
43
42
|
if (promise) {
|
|
44
|
-
return promise.then(
|
|
43
|
+
return promise.then(htmlContent => createHover(htmlContent));
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
|
-
return this.schemaService.getSchemaForResource(document.uri, doc).then(
|
|
46
|
+
return this.schemaService.getSchemaForResource(document.uri, doc).then((schema) => {
|
|
48
47
|
if (schema && node) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
matchingSchemas.every(
|
|
48
|
+
const matchingSchemas = doc.getMatchingSchemas(schema.schema, node.offset);
|
|
49
|
+
let title = undefined;
|
|
50
|
+
let markdownDescription = undefined;
|
|
51
|
+
let markdownEnumValueDescription = undefined, enumValue = undefined;
|
|
52
|
+
matchingSchemas.every((s) => {
|
|
54
53
|
if (s.node === node && !s.inverted && s.schema) {
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
title = title || s.schema.title;
|
|
55
|
+
markdownDescription = markdownDescription || s.schema.markdownDescription || toMarkdown(s.schema.description);
|
|
57
56
|
if (s.schema.enum) {
|
|
58
|
-
|
|
57
|
+
const idx = s.schema.enum.indexOf(Parser.getNodeValue(node));
|
|
59
58
|
if (s.schema.markdownEnumDescriptions) {
|
|
60
|
-
|
|
59
|
+
markdownEnumValueDescription = s.schema.markdownEnumDescriptions[idx];
|
|
61
60
|
}
|
|
62
61
|
else if (s.schema.enumDescriptions) {
|
|
63
|
-
|
|
62
|
+
markdownEnumValueDescription = toMarkdown(s.schema.enumDescriptions[idx]);
|
|
64
63
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
if (typeof
|
|
68
|
-
|
|
64
|
+
if (markdownEnumValueDescription) {
|
|
65
|
+
enumValue = s.schema.enum[idx];
|
|
66
|
+
if (typeof enumValue !== 'string') {
|
|
67
|
+
enumValue = JSON.stringify(enumValue);
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
70
|
}
|
|
72
71
|
}
|
|
73
72
|
return true;
|
|
74
73
|
});
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
result = toMarkdown(
|
|
74
|
+
let result = '';
|
|
75
|
+
if (title) {
|
|
76
|
+
result = toMarkdown(title);
|
|
78
77
|
}
|
|
79
|
-
if (
|
|
78
|
+
if (markdownDescription) {
|
|
80
79
|
if (result.length > 0) {
|
|
81
80
|
result += "\n\n";
|
|
82
81
|
}
|
|
83
|
-
result +=
|
|
82
|
+
result += markdownDescription;
|
|
84
83
|
}
|
|
85
|
-
if (
|
|
84
|
+
if (markdownEnumValueDescription) {
|
|
86
85
|
if (result.length > 0) {
|
|
87
86
|
result += "\n\n";
|
|
88
87
|
}
|
|
89
|
-
result +=
|
|
88
|
+
result += `\`${toMarkdownCodeBlock(enumValue)}\`: ${markdownEnumValueDescription}`;
|
|
90
89
|
}
|
|
91
90
|
return createHover([result]);
|
|
92
91
|
}
|
|
93
92
|
return null;
|
|
94
93
|
});
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
}());
|
|
98
|
-
export { JSONHover };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
99
96
|
function toMarkdown(plain) {
|
|
100
97
|
if (plain) {
|
|
101
|
-
|
|
98
|
+
const res = plain.replace(/([^\n\r])(\r?\n)([^\n\r])/gm, '$1\n\n$3'); // single new lines to \n\n (Markdown paragraph)
|
|
102
99
|
return res.replace(/[\\`*_{}[\]()#+\-.!]/g, "\\$&"); // escape markdown syntax tokens: http://daringfireball.net/projects/markdown/syntax#backslash
|
|
103
100
|
}
|
|
104
101
|
return undefined;
|