yaml-language-server
Version:
YAML language server
116 lines • 5.36 kB
JavaScript
(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) {
if (!document) {
return;
}
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);
}
if (!current) {
current = vscode_languageserver_types_1.SelectionRange.create({
start: position,
end: position,
});
}
return current;
});
function getRanges(position) {
const offset = document.offsetAt(position);
const result = [];
for (const ymlDoc of doc.documents) {
let currentNode;
let firstNodeOffset;
let isFirstNode = true;
ymlDoc.visit((node) => {
const endOffset = node.offset + node.length;
// Skip if end offset doesn't even reach cursor position
if (endOffset < offset) {
return true;
}
let startOffset = node.offset;
// Recheck start offset with the trimmed one in case of this
// key:
// - value
// ↑
if (startOffset > offset) {
const nodePosition = document.positionAt(startOffset);
if (nodePosition.line !== position.line) {
return true;
}
const lineBeginning = { line: nodePosition.line, character: 0 };
const text = document.getText({
start: lineBeginning,
end: nodePosition,
});
if (text.trim().length !== 0) {
return true;
}
startOffset = document.offsetAt(lineBeginning);
if (startOffset > offset) {
return true;
}
}
// Allow equal for children to override
if (!currentNode || startOffset >= currentNode.offset) {
currentNode = node;
firstNodeOffset = startOffset;
}
return true;
});
while (currentNode) {
const startOffset = isFirstNode ? firstNodeOffset : 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 = text.trimEnd();
const trimmedLength = text.length - trimmedText.length;
if (trimmedLength > 0) {
range.end = document.positionAt(endOffset - trimmedLength);
}
// 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;
isFirstNode = false;
}
// A position can't be in multiple documents
if (result.length > 0) {
break;
}
}
return result.reverse();
}
}
exports.getSelectionRanges = getSelectionRanges;
});
//# sourceMappingURL=yamlSelectionRanges.js.map