jsonSelectionRanges.js 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  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 { Range, SelectionRange } from '../jsonLanguageTypes';
  6. import { createScanner } from 'jsonc-parser';
  7. export function getSelectionRanges(document, positions, doc) {
  8. function getSelectionRange(position) {
  9. var offset = document.offsetAt(position);
  10. var node = doc.getNodeFromOffset(offset, true);
  11. var result = [];
  12. while (node) {
  13. switch (node.type) {
  14. case 'string':
  15. case 'object':
  16. case 'array':
  17. // range without ", [ or {
  18. var cStart = node.offset + 1, cEnd = node.offset + node.length - 1;
  19. if (cStart < cEnd && offset >= cStart && offset <= cEnd) {
  20. result.push(newRange(cStart, cEnd));
  21. }
  22. result.push(newRange(node.offset, node.offset + node.length));
  23. break;
  24. case 'number':
  25. case 'boolean':
  26. case 'null':
  27. case 'property':
  28. result.push(newRange(node.offset, node.offset + node.length));
  29. break;
  30. }
  31. if (node.type === 'property' || node.parent && node.parent.type === 'array') {
  32. var afterCommaOffset = getOffsetAfterNextToken(node.offset + node.length, 5 /* CommaToken */);
  33. if (afterCommaOffset !== -1) {
  34. result.push(newRange(node.offset, afterCommaOffset));
  35. }
  36. }
  37. node = node.parent;
  38. }
  39. var current = undefined;
  40. for (var index = result.length - 1; index >= 0; index--) {
  41. current = SelectionRange.create(result[index], current);
  42. }
  43. if (!current) {
  44. current = SelectionRange.create(Range.create(position, position));
  45. }
  46. return current;
  47. }
  48. function newRange(start, end) {
  49. return Range.create(document.positionAt(start), document.positionAt(end));
  50. }
  51. var scanner = createScanner(document.getText(), true);
  52. function getOffsetAfterNextToken(offset, expectedToken) {
  53. scanner.setPosition(offset);
  54. var token = scanner.scan();
  55. if (token === expectedToken) {
  56. return scanner.getTokenOffset() + scanner.getTokenLength();
  57. }
  58. return -1;
  59. }
  60. return positions.map(getSelectionRange);
  61. }