/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import * as Parser from '../parser/jsonParser'; import * as Strings from '../utils/strings'; import { colorFromHex } from '../utils/colors'; import { Range, TextEdit, SymbolKind, Location } from "../jsonLanguageTypes"; var JSONDocumentSymbols = /** @class */ (function () { function JSONDocumentSymbols(schemaService) { this.schemaService = schemaService; } JSONDocumentSymbols.prototype.findDocumentSymbols = function (document, doc, context) { var _this = this; if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; } var root = doc.root; if (!root) { return []; } var limit = context.resultLimit || Number.MAX_VALUE; // special handling for key bindings var resourceString = document.uri; if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) { if (root.type === 'array') { var result_1 = []; for (var _i = 0, _a = root.items; _i < _a.length; _i++) { var item = _a[_i]; if (item.type === 'object') { for (var _b = 0, _c = item.properties; _b < _c.length; _b++) { var property = _c[_b]; if (property.keyNode.value === 'key' && property.valueNode) { var location = Location.create(document.uri, getRange(document, item)); result_1.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, location: location }); limit--; if (limit <= 0) { if (context && context.onResultLimitExceeded) { context.onResultLimitExceeded(resourceString); } return result_1; } } } } } return result_1; } } var toVisit = [ { node: root, containerName: '' } ]; var nextToVisit = 0; var limitExceeded = false; var result = []; var collectOutlineEntries = function (node, containerName) { if (node.type === 'array') { node.items.forEach(function (node) { if (node) { toVisit.push({ node: node, containerName: containerName }); } }); } else if (node.type === 'object') { node.properties.forEach(function (property) { var valueNode = property.valueNode; if (valueNode) { if (limit > 0) { limit--; var location = Location.create(document.uri, getRange(document, property)); var childContainerName = containerName ? containerName + '.' + property.keyNode.value : property.keyNode.value; result.push({ name: _this.getKeyLabel(property), kind: _this.getSymbolKind(valueNode.type), location: location, containerName: containerName }); toVisit.push({ node: valueNode, containerName: childContainerName }); } else { limitExceeded = true; } } }); } }; // breath first traversal while (nextToVisit < toVisit.length) { var next = toVisit[nextToVisit++]; collectOutlineEntries(next.node, next.containerName); } if (limitExceeded && context && context.onResultLimitExceeded) { context.onResultLimitExceeded(resourceString); } return result; }; JSONDocumentSymbols.prototype.findDocumentSymbols2 = function (document, doc, context) { var _this = this; if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; } var root = doc.root; if (!root) { return []; } var limit = context.resultLimit || Number.MAX_VALUE; // special handling for key bindings var resourceString = document.uri; if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) { if (root.type === 'array') { var result_2 = []; for (var _i = 0, _a = root.items; _i < _a.length; _i++) { var item = _a[_i]; if (item.type === 'object') { for (var _b = 0, _c = item.properties; _b < _c.length; _b++) { var property = _c[_b]; if (property.keyNode.value === 'key' && property.valueNode) { var range = getRange(document, item); var selectionRange = getRange(document, property.keyNode); result_2.push({ name: Parser.getNodeValue(property.valueNode), kind: SymbolKind.Function, range: range, selectionRange: selectionRange }); limit--; if (limit <= 0) { if (context && context.onResultLimitExceeded) { context.onResultLimitExceeded(resourceString); } return result_2; } } } } } return result_2; } } var result = []; var toVisit = [ { node: root, result: result } ]; var nextToVisit = 0; var limitExceeded = false; var collectOutlineEntries = function (node, result) { if (node.type === 'array') { node.items.forEach(function (node, index) { if (node) { if (limit > 0) { limit--; var range = getRange(document, node); var selectionRange = range; var name = String(index); var symbol = { name: name, kind: _this.getSymbolKind(node.type), range: range, selectionRange: selectionRange, children: [] }; result.push(symbol); toVisit.push({ result: symbol.children, node: node }); } else { limitExceeded = true; } } }); } else if (node.type === 'object') { node.properties.forEach(function (property) { var valueNode = property.valueNode; if (valueNode) { if (limit > 0) { limit--; var range = getRange(document, property); var selectionRange = getRange(document, property.keyNode); var children = []; var symbol = { name: _this.getKeyLabel(property), kind: _this.getSymbolKind(valueNode.type), range: range, selectionRange: selectionRange, children: children, detail: _this.getDetail(valueNode) }; result.push(symbol); toVisit.push({ result: children, node: valueNode }); } else { limitExceeded = true; } } }); } }; // breath first traversal while (nextToVisit < toVisit.length) { var next = toVisit[nextToVisit++]; collectOutlineEntries(next.node, next.result); } if (limitExceeded && context && context.onResultLimitExceeded) { context.onResultLimitExceeded(resourceString); } return result; }; JSONDocumentSymbols.prototype.getSymbolKind = function (nodeType) { switch (nodeType) { case 'object': return SymbolKind.Module; case 'string': return SymbolKind.String; case 'number': return SymbolKind.Number; case 'array': return SymbolKind.Array; case 'boolean': return SymbolKind.Boolean; default: // 'null' return SymbolKind.Variable; } }; JSONDocumentSymbols.prototype.getKeyLabel = function (property) { var name = property.keyNode.value; if (name) { name = name.replace(/[\n]/g, '↵'); } if (name && name.trim()) { return name; } return "\"" + name + "\""; }; JSONDocumentSymbols.prototype.getDetail = function (node) { if (!node) { return undefined; } if (node.type === 'boolean' || node.type === 'number' || node.type === 'null' || node.type === 'string') { return String(node.value); } else { if (node.type === 'array') { return node.children.length ? undefined : '[]'; } else if (node.type === 'object') { return node.children.length ? undefined : '{}'; } } return undefined; }; JSONDocumentSymbols.prototype.findDocumentColors = function (document, doc, context) { return this.schemaService.getSchemaForResource(document.uri, doc).then(function (schema) { var result = []; if (schema) { var limit = context && typeof context.resultLimit === 'number' ? context.resultLimit : Number.MAX_VALUE; var matchingSchemas = doc.getMatchingSchemas(schema.schema); var visitedNode = {}; for (var _i = 0, matchingSchemas_1 = matchingSchemas; _i < matchingSchemas_1.length; _i++) { var s = matchingSchemas_1[_i]; if (!s.inverted && s.schema && (s.schema.format === 'color' || s.schema.format === 'color-hex') && s.node && s.node.type === 'string') { var nodeId = String(s.node.offset); if (!visitedNode[nodeId]) { var color = colorFromHex(Parser.getNodeValue(s.node)); if (color) { var range = getRange(document, s.node); result.push({ color: color, range: range }); } visitedNode[nodeId] = true; limit--; if (limit <= 0) { if (context && context.onResultLimitExceeded) { context.onResultLimitExceeded(document.uri); } return result; } } } } } return result; }); }; JSONDocumentSymbols.prototype.getColorPresentations = function (document, doc, color, range) { var result = []; var red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255); function toTwoDigitHex(n) { var r = n.toString(16); return r.length !== 2 ? '0' + r : r; } var label; if (color.alpha === 1) { label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256); } else { label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256) + toTwoDigitHex(Math.round(color.alpha * 255)); } result.push({ label: label, textEdit: TextEdit.replace(range, JSON.stringify(label)) }); return result; }; return JSONDocumentSymbols; }()); export { JSONDocumentSymbols }; function getRange(document, node) { return Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length)); }