jsonDocumentSymbols.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  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. (function (factory) {
  6. if (typeof module === "object" && typeof module.exports === "object") {
  7. var v = factory(require, exports);
  8. if (v !== undefined) module.exports = v;
  9. }
  10. else if (typeof define === "function" && define.amd) {
  11. define(["require", "exports", "../parser/jsonParser", "../utils/strings", "../utils/colors", "../jsonLanguageTypes"], factory);
  12. }
  13. })(function (require, exports) {
  14. "use strict";
  15. Object.defineProperty(exports, "__esModule", { value: true });
  16. exports.JSONDocumentSymbols = void 0;
  17. var Parser = require("../parser/jsonParser");
  18. var Strings = require("../utils/strings");
  19. var colors_1 = require("../utils/colors");
  20. var jsonLanguageTypes_1 = require("../jsonLanguageTypes");
  21. var JSONDocumentSymbols = /** @class */ (function () {
  22. function JSONDocumentSymbols(schemaService) {
  23. this.schemaService = schemaService;
  24. }
  25. JSONDocumentSymbols.prototype.findDocumentSymbols = function (document, doc, context) {
  26. var _this = this;
  27. if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; }
  28. var root = doc.root;
  29. if (!root) {
  30. return [];
  31. }
  32. var limit = context.resultLimit || Number.MAX_VALUE;
  33. // special handling for key bindings
  34. var resourceString = document.uri;
  35. if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
  36. if (root.type === 'array') {
  37. var result_1 = [];
  38. for (var _i = 0, _a = root.items; _i < _a.length; _i++) {
  39. var item = _a[_i];
  40. if (item.type === 'object') {
  41. for (var _b = 0, _c = item.properties; _b < _c.length; _b++) {
  42. var property = _c[_b];
  43. if (property.keyNode.value === 'key' && property.valueNode) {
  44. var location = jsonLanguageTypes_1.Location.create(document.uri, getRange(document, item));
  45. result_1.push({ name: Parser.getNodeValue(property.valueNode), kind: jsonLanguageTypes_1.SymbolKind.Function, location: location });
  46. limit--;
  47. if (limit <= 0) {
  48. if (context && context.onResultLimitExceeded) {
  49. context.onResultLimitExceeded(resourceString);
  50. }
  51. return result_1;
  52. }
  53. }
  54. }
  55. }
  56. }
  57. return result_1;
  58. }
  59. }
  60. var toVisit = [
  61. { node: root, containerName: '' }
  62. ];
  63. var nextToVisit = 0;
  64. var limitExceeded = false;
  65. var result = [];
  66. var collectOutlineEntries = function (node, containerName) {
  67. if (node.type === 'array') {
  68. node.items.forEach(function (node) {
  69. if (node) {
  70. toVisit.push({ node: node, containerName: containerName });
  71. }
  72. });
  73. }
  74. else if (node.type === 'object') {
  75. node.properties.forEach(function (property) {
  76. var valueNode = property.valueNode;
  77. if (valueNode) {
  78. if (limit > 0) {
  79. limit--;
  80. var location = jsonLanguageTypes_1.Location.create(document.uri, getRange(document, property));
  81. var childContainerName = containerName ? containerName + '.' + property.keyNode.value : property.keyNode.value;
  82. result.push({ name: _this.getKeyLabel(property), kind: _this.getSymbolKind(valueNode.type), location: location, containerName: containerName });
  83. toVisit.push({ node: valueNode, containerName: childContainerName });
  84. }
  85. else {
  86. limitExceeded = true;
  87. }
  88. }
  89. });
  90. }
  91. };
  92. // breath first traversal
  93. while (nextToVisit < toVisit.length) {
  94. var next = toVisit[nextToVisit++];
  95. collectOutlineEntries(next.node, next.containerName);
  96. }
  97. if (limitExceeded && context && context.onResultLimitExceeded) {
  98. context.onResultLimitExceeded(resourceString);
  99. }
  100. return result;
  101. };
  102. JSONDocumentSymbols.prototype.findDocumentSymbols2 = function (document, doc, context) {
  103. var _this = this;
  104. if (context === void 0) { context = { resultLimit: Number.MAX_VALUE }; }
  105. var root = doc.root;
  106. if (!root) {
  107. return [];
  108. }
  109. var limit = context.resultLimit || Number.MAX_VALUE;
  110. // special handling for key bindings
  111. var resourceString = document.uri;
  112. if ((resourceString === 'vscode://defaultsettings/keybindings.json') || Strings.endsWith(resourceString.toLowerCase(), '/user/keybindings.json')) {
  113. if (root.type === 'array') {
  114. var result_2 = [];
  115. for (var _i = 0, _a = root.items; _i < _a.length; _i++) {
  116. var item = _a[_i];
  117. if (item.type === 'object') {
  118. for (var _b = 0, _c = item.properties; _b < _c.length; _b++) {
  119. var property = _c[_b];
  120. if (property.keyNode.value === 'key' && property.valueNode) {
  121. var range = getRange(document, item);
  122. var selectionRange = getRange(document, property.keyNode);
  123. result_2.push({ name: Parser.getNodeValue(property.valueNode), kind: jsonLanguageTypes_1.SymbolKind.Function, range: range, selectionRange: selectionRange });
  124. limit--;
  125. if (limit <= 0) {
  126. if (context && context.onResultLimitExceeded) {
  127. context.onResultLimitExceeded(resourceString);
  128. }
  129. return result_2;
  130. }
  131. }
  132. }
  133. }
  134. }
  135. return result_2;
  136. }
  137. }
  138. var result = [];
  139. var toVisit = [
  140. { node: root, result: result }
  141. ];
  142. var nextToVisit = 0;
  143. var limitExceeded = false;
  144. var collectOutlineEntries = function (node, result) {
  145. if (node.type === 'array') {
  146. node.items.forEach(function (node, index) {
  147. if (node) {
  148. if (limit > 0) {
  149. limit--;
  150. var range = getRange(document, node);
  151. var selectionRange = range;
  152. var name = String(index);
  153. var symbol = { name: name, kind: _this.getSymbolKind(node.type), range: range, selectionRange: selectionRange, children: [] };
  154. result.push(symbol);
  155. toVisit.push({ result: symbol.children, node: node });
  156. }
  157. else {
  158. limitExceeded = true;
  159. }
  160. }
  161. });
  162. }
  163. else if (node.type === 'object') {
  164. node.properties.forEach(function (property) {
  165. var valueNode = property.valueNode;
  166. if (valueNode) {
  167. if (limit > 0) {
  168. limit--;
  169. var range = getRange(document, property);
  170. var selectionRange = getRange(document, property.keyNode);
  171. var children = [];
  172. var symbol = { name: _this.getKeyLabel(property), kind: _this.getSymbolKind(valueNode.type), range: range, selectionRange: selectionRange, children: children, detail: _this.getDetail(valueNode) };
  173. result.push(symbol);
  174. toVisit.push({ result: children, node: valueNode });
  175. }
  176. else {
  177. limitExceeded = true;
  178. }
  179. }
  180. });
  181. }
  182. };
  183. // breath first traversal
  184. while (nextToVisit < toVisit.length) {
  185. var next = toVisit[nextToVisit++];
  186. collectOutlineEntries(next.node, next.result);
  187. }
  188. if (limitExceeded && context && context.onResultLimitExceeded) {
  189. context.onResultLimitExceeded(resourceString);
  190. }
  191. return result;
  192. };
  193. JSONDocumentSymbols.prototype.getSymbolKind = function (nodeType) {
  194. switch (nodeType) {
  195. case 'object':
  196. return jsonLanguageTypes_1.SymbolKind.Module;
  197. case 'string':
  198. return jsonLanguageTypes_1.SymbolKind.String;
  199. case 'number':
  200. return jsonLanguageTypes_1.SymbolKind.Number;
  201. case 'array':
  202. return jsonLanguageTypes_1.SymbolKind.Array;
  203. case 'boolean':
  204. return jsonLanguageTypes_1.SymbolKind.Boolean;
  205. default: // 'null'
  206. return jsonLanguageTypes_1.SymbolKind.Variable;
  207. }
  208. };
  209. JSONDocumentSymbols.prototype.getKeyLabel = function (property) {
  210. var name = property.keyNode.value;
  211. if (name) {
  212. name = name.replace(/[\n]/g, '↵');
  213. }
  214. if (name && name.trim()) {
  215. return name;
  216. }
  217. return "\"" + name + "\"";
  218. };
  219. JSONDocumentSymbols.prototype.getDetail = function (node) {
  220. if (!node) {
  221. return undefined;
  222. }
  223. if (node.type === 'boolean' || node.type === 'number' || node.type === 'null' || node.type === 'string') {
  224. return String(node.value);
  225. }
  226. else {
  227. if (node.type === 'array') {
  228. return node.children.length ? undefined : '[]';
  229. }
  230. else if (node.type === 'object') {
  231. return node.children.length ? undefined : '{}';
  232. }
  233. }
  234. return undefined;
  235. };
  236. JSONDocumentSymbols.prototype.findDocumentColors = function (document, doc, context) {
  237. return this.schemaService.getSchemaForResource(document.uri, doc).then(function (schema) {
  238. var result = [];
  239. if (schema) {
  240. var limit = context && typeof context.resultLimit === 'number' ? context.resultLimit : Number.MAX_VALUE;
  241. var matchingSchemas = doc.getMatchingSchemas(schema.schema);
  242. var visitedNode = {};
  243. for (var _i = 0, matchingSchemas_1 = matchingSchemas; _i < matchingSchemas_1.length; _i++) {
  244. var s = matchingSchemas_1[_i];
  245. if (!s.inverted && s.schema && (s.schema.format === 'color' || s.schema.format === 'color-hex') && s.node && s.node.type === 'string') {
  246. var nodeId = String(s.node.offset);
  247. if (!visitedNode[nodeId]) {
  248. var color = colors_1.colorFromHex(Parser.getNodeValue(s.node));
  249. if (color) {
  250. var range = getRange(document, s.node);
  251. result.push({ color: color, range: range });
  252. }
  253. visitedNode[nodeId] = true;
  254. limit--;
  255. if (limit <= 0) {
  256. if (context && context.onResultLimitExceeded) {
  257. context.onResultLimitExceeded(document.uri);
  258. }
  259. return result;
  260. }
  261. }
  262. }
  263. }
  264. }
  265. return result;
  266. });
  267. };
  268. JSONDocumentSymbols.prototype.getColorPresentations = function (document, doc, color, range) {
  269. var result = [];
  270. var red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255);
  271. function toTwoDigitHex(n) {
  272. var r = n.toString(16);
  273. return r.length !== 2 ? '0' + r : r;
  274. }
  275. var label;
  276. if (color.alpha === 1) {
  277. label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256);
  278. }
  279. else {
  280. label = "#" + toTwoDigitHex(red256) + toTwoDigitHex(green256) + toTwoDigitHex(blue256) + toTwoDigitHex(Math.round(color.alpha * 255));
  281. }
  282. result.push({ label: label, textEdit: jsonLanguageTypes_1.TextEdit.replace(range, JSON.stringify(label)) });
  283. return result;
  284. };
  285. return JSONDocumentSymbols;
  286. }());
  287. exports.JSONDocumentSymbols = JSONDocumentSymbols;
  288. function getRange(document, node) {
  289. return jsonLanguageTypes_1.Range.create(document.positionAt(node.offset), document.positionAt(node.offset + node.length));
  290. }
  291. });