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 import * as Parser from '../parser/jsonParser';
6 import * as Strings from '../utils/strings';
7 import { colorFromHex } from '../utils/colors';
8 import { Range, TextEdit, SymbolKind, Location } from "../jsonLanguageTypes";
9 var JSONDocumentSymbols = /** @class */ (function () {
10 function JSONDocumentSymbols(schemaService) {
11 this.schemaService = schemaService;
13 JSONDocumentSymbols.prototype.findDocumentSymbols = function (document, doc, context) {
15 if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; }
20 var limit = context.resultLimit || Number.MAX_VALUE;
21 // special handling for key bindings
22 var resourceString = document.uri;
23 if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
24 if (root.type === 'array') {
26 for (var _i = 0, _a = root.items; _i < _a.length; _i++) {
28 if (item.type === 'object') {
29 for (var _b = 0, _c = item.properties; _b < _c.length; _b++) {
30 var property = _c[_b];
31 if (property.keyNode.value === 'key' && property.valueNode) {
32 var location = Location.create(document.uri, getRange(document, item));
33 result_1.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, location: location });
36 if (context && context.onResultLimitExceeded) {
37 context.onResultLimitExceeded(resourceString);
49 { node: root, containerName: '' }
52 var limitExceeded = false;
54 var collectOutlineEntries = function (node, containerName) {
55 if (node.type === 'array') {
56 node.items.forEach(function (node) {
58 toVisit.push({ node: node, containerName: containerName });
62 else if (node.type === 'object') {
63 node.properties.forEach(function (property) {
64 var valueNode = property.valueNode;
68 var location = Location.create(document.uri, getRange(document, property));
69 var childContainerName = containerName ? containerName + '.' + property.keyNode.value : property.keyNode.value;
70 result.push({ name: _this.getKeyLabel(property), kind: _this.getSymbolKind(valueNode.type), location: location, containerName: containerName });
71 toVisit.push({ node: valueNode, containerName: childContainerName });
80 // breath first traversal
81 while (nextToVisit < toVisit.length) {
82 var next = toVisit[nextToVisit++];
83 collectOutlineEntries(next.node, next.containerName);
85 if (limitExceeded && context && context.onResultLimitExceeded) {
86 context.onResultLimitExceeded(resourceString);
90 JSONDocumentSymbols.prototype.findDocumentSymbols2 = function (document, doc, context) {
92 if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; }
97 var limit = context.resultLimit || Number.MAX_VALUE;
98 // special handling for key bindings
99 var resourceString = document.uri;
100 if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
101 if (root.type === 'array') {
103 for (var _i = 0, _a = root.items; _i < _a.length; _i++) {
105 if (item.type === 'object') {
106 for (var _b = 0, _c = item.properties; _b < _c.length; _b++) {
107 var property = _c[_b];
108 if (property.keyNode.value === 'key' && property.valueNode) {
109 var range = getRange(document, item);
110 var selectionRange = getRange(document, property.keyNode);
111 result_2.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, range: range, selectionRange: selectionRange });
114 if (context && context.onResultLimitExceeded) {
115 context.onResultLimitExceeded(resourceString);
128 { node: root, result: result }
131 var limitExceeded = false;
132 var collectOutlineEntries = function (node, result) {
133 if (node.type === 'array') {
134 node.items.forEach(function (node, index) {
138 var range = getRange(document, node);
139 var selectionRange = range;
140 var name = String(index);
141 var symbol = { name: name, kind: _this.getSymbolKind(node.type), range: range, selectionRange: selectionRange, children: [] };
143 toVisit.push({ result: symbol.children, node: node });
146 limitExceeded = true;
151 else if (node.type === 'object') {
152 node.properties.forEach(function (property) {
153 var valueNode = property.valueNode;
157 var range = getRange(document, property);
158 var selectionRange = getRange(document, property.keyNode);
160 var symbol = { name: _this.getKeyLabel(property), kind: _this.getSymbolKind(valueNode.type), range: range, selectionRange: selectionRange, children: children, detail: _this.getDetail(valueNode) };
162 toVisit.push({ result: children, node: valueNode });
165 limitExceeded = true;
171 // breath first traversal
172 while (nextToVisit < toVisit.length) {
173 var next = toVisit[nextToVisit++];
174 collectOutlineEntries(next.node, next.result);
176 if (limitExceeded && context && context.onResultLimitExceeded) {
177 context.onResultLimitExceeded(resourceString);
181 JSONDocumentSymbols.prototype.getSymbolKind = function (nodeType) {
184 return SymbolKind.Module;
186 return SymbolKind.String;
188 return SymbolKind.Number;
190 return SymbolKind.Array;
192 return SymbolKind.Boolean;
194 return SymbolKind.Variable;
197 JSONDocumentSymbols.prototype.getKeyLabel = function (property) {
198 var name = property.keyNode.value;
200 name = name.replace(/[\n]/g, '↵');
202 if (name && name.trim()) {
205 return "\"" + name + "\"";
207 JSONDocumentSymbols.prototype.getDetail = function (node) {
211 if (node.type === 'boolean' || node.type === 'number' || node.type === 'null' || node.type === 'string') {
212 return String(node.value);
215 if (node.type === 'array') {
216 return node.children.length ? undefined : '[]';
218 else if (node.type === 'object') {
219 return node.children.length ? undefined : '{}';
224 JSONDocumentSymbols.prototype.findDocumentColors = function (document, doc, context) {
225 return this.schemaService.getSchemaForResource(document.uri, doc).then(function (schema) {
228 var limit = context && typeof context.resultLimit === 'number' ? context.resultLimit : Number.MAX_VALUE;
229 var matchingSchemas = doc.getMatchingSchemas(schema.schema);
230 var visitedNode = {};
231 for (var _i = 0, matchingSchemas_1 = matchingSchemas; _i < matchingSchemas_1.length; _i++) {
232 var s = matchingSchemas_1[_i];
233 if (!s.inverted && s.schema && (s.schema.format === 'color' || s.schema.format === 'color-hex') && s.node && s.node.type === 'string') {
234 var nodeId = String(s.node.offset);
235 if (!visitedNode[nodeId]) {
236 var color = colorFromHex(Parser.getNodeValue(s.node));
238 var range = getRange(document, s.node);
239 result.push({ color: color, range: range });
241 visitedNode[nodeId] = true;
244 if (context && context.onResultLimitExceeded) {
245 context.onResultLimitExceeded(document.uri);
256 JSONDocumentSymbols.prototype.getColorPresentations = function (document, doc, color, range) {
258 var red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255);
259 function toTwoDigitHex(n) {
260 var r = n.toString(16);
261 return r.length !== 2 ? '0' + r : r;
264 if (color.alpha === 1) {
265 label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256);
268 label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256) + toTwoDigitHex(Math.round(color.alpha * 255));
270 result.push({ label: label, textEdit: TextEdit.replace(range, JSON.stringify(label)) });
273 return JSONDocumentSymbols;
275 export { JSONDocumentSymbols };
276 function getRange(document, node) {
277 return Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length));