(function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "vscode-languageserver-types", "../parser/yaml-documents"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getSelectionRanges = void 0; const vscode_languageserver_types_1 = require("vscode-languageserver-types"); const yaml_documents_1 = require("../parser/yaml-documents"); function getSelectionRanges(document, positions) { const doc = yaml_documents_1.yamlDocumentsCache.getYamlDocument(document); return positions.map((position) => { const ranges = getRanges(position); let current; for (const range of ranges) { current = vscode_languageserver_types_1.SelectionRange.create(range, current); } return current ?? vscode_languageserver_types_1.SelectionRange.create({ start: position, end: position }); }); function getRanges(position) { const offset = document.offsetAt(position); const result = []; for (const ymlDoc of doc.documents) { let currentNode; let overrideStartOffset; ymlDoc.visit((node) => { const endOffset = node.offset + node.length; // Skip if end offset doesn't even reach cursor position if (endOffset < offset) { return true; } // Skip if we're ending at new line // times: // - second: 1 // millisecond: 10 // | - second: 2 // ↑ millisecond: 0 // (| is actually part of { second: 1, millisecond: 10 }) // \r\n doesn't matter here if (getTextFromOffsets(endOffset - 1, endOffset) === '\n') { if (endOffset - 1 < offset) { return true; } } let startOffset = node.offset; if (startOffset > offset) { // Recheck start offset for some special cases const newOffset = getStartOffsetForSpecialCases(node, position); if (!newOffset || newOffset > offset) { return true; } startOffset = newOffset; } // Allow equal for children to override if (!currentNode || startOffset >= currentNode.offset) { currentNode = node; overrideStartOffset = startOffset; } return true; }); while (currentNode) { const startOffset = overrideStartOffset ?? currentNode.offset; const endOffset = currentNode.offset + currentNode.length; const range = { start: document.positionAt(startOffset), end: document.positionAt(endOffset), }; const text = document.getText(range); const trimmedText = trimEndNewLine(text); const trimmedEndOffset = startOffset + trimmedText.length; if (trimmedEndOffset >= offset) { range.end = document.positionAt(trimmedEndOffset); } // Add a jump between '' "" {} [] const isSurroundedBy = (startCharacter, endCharacter) => { return trimmedText.startsWith(startCharacter) && trimmedText.endsWith(endCharacter || startCharacter); }; if ((currentNode.type === 'string' && (isSurroundedBy("'") || isSurroundedBy('"'))) || (currentNode.type === 'object' && isSurroundedBy('{', '}')) || (currentNode.type === 'array' && isSurroundedBy('[', ']'))) { result.push({ start: document.positionAt(startOffset + 1), end: document.positionAt(endOffset - 1), }); } result.push(range); currentNode = currentNode.parent; overrideStartOffset = undefined; } // A position can't be in multiple documents if (result.length > 0) { break; } } return result.reverse(); } function getStartOffsetForSpecialCases(node, position) { const nodeStartPosition = document.positionAt(node.offset); if (nodeStartPosition.line !== position.line) { return; } if (node.parent?.type === 'array') { // array: // - value // ↑ if (getTextFromOffsets(node.offset - 2, node.offset) === '- ') { return node.offset - 2; } } if (node.type === 'array' || node.type === 'object') { // array: // - value // ↑ const lineBeginning = { line: nodeStartPosition.line, character: 0 }; const text = document.getText({ start: lineBeginning, end: nodeStartPosition }); if (text.trim().length === 0) { return document.offsetAt(lineBeginning); } } } function getTextFromOffsets(startOffset, endOffset) { return document.getText({ start: document.positionAt(startOffset), end: document.positionAt(endOffset), }); } } exports.getSelectionRanges = getSelectionRanges; function trimEndNewLine(str) { if (str.endsWith('\r\n')) { return str.substring(0, str.length - 2); } if (str.endsWith('\n')) { return str.substring(0, str.length - 1); } return str; } }); //# sourceMappingURL=yamlSelectionRanges.js.map