// ***************************************************************************** // Copyright (C) 2025 1C-Soft LLC and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** /*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ // copied and modified from https://github.com/microsoft/vscode/blob/1.96.3/src/vs/workbench/contrib/mergeEditor/browser/model/rangeUtils.ts, // https://github.com/microsoft/vscode/blob/1.96.3/src/vs/editor/common/core/range.ts, // https://github.com/microsoft/vscode/blob/1.96.3/src/vs/editor/common/core/position.ts, // https://github.com/microsoft/vscode/blob/1.96.3/src/vs/editor/common/core/textLength.ts import { Position, Range } from '@theia/core/shared/vscode-languageserver-protocol'; export namespace RangeUtils { export function isEmpty(range: Range): boolean { return range.start.line === range.end.line && range.start.character === range.end.character; } export function containsPosition(range: Range, position: Position): boolean { if (position.line < range.start.line || position.line > range.end.line) { return false; } if (position.line === range.start.line && position.character < range.start.character) { return false; } if (position.line === range.end.line && position.character >= range.end.character) { return false; } return true; } /** * Returns `false` iff there is at least one character between `range` and `other`. */ export function touches(range: Range, other: Range): boolean { return PositionUtils.isBeforeOrEqual(range.start, other.end) && PositionUtils.isBeforeOrEqual(other.start, range.end); } export function isBefore(range: Range, other: Range): boolean { return ( range.end.line < other.start.line || (range.end.line === other.start.line && range.end.character <= other.start.character) ); } export function union(range: Range, other: Range): Range { const start = PositionUtils.isBeforeOrEqual(range.start, other.start) ? range.start : other.start; const end = PositionUtils.isBeforeOrEqual(range.end, other.end) ? other.end : range.end; return { start, end }; } /** * A function that compares ranges, useful for sorting ranges. * It will first compare ranges on the start position and then on the end position. */ export function compareUsingStarts(range: Range, other: Range): number { if (range.start.line === other.start.line) { if (range.start.character === other.start.character) { if (range.end.line === other.end.line) { return range.end.character - other.end.character; } return range.end.line - other.end.line; } return range.start.character - other.start.character; } return range.start.line - other.start.line; } } export namespace PositionUtils { export function isBeforeOrEqual(position: Position, other: Position): boolean { return compare(position, other) <= 0; } export function compare(position: Position, other: Position): number { if (position.line === other.line) { return position.character - other.character; } return position.line - other.line; } /** * Given two positions, computes the relative position of the greater position against the lesser position. */ export function relativize(position: Position, other: Position): Position { if (compare(position, other) > 0) { [position, other] = [other, position]; } if (position.line === other.line) { return Position.create(0, other.character - position.character); } else { return Position.create(other.line - position.line, other.character); } } /** * Resolves the given relative position against the given position and returns the resulting position. */ export function resolve(position: Position, relativePosition: Position): Position { if (relativePosition.line === 0) { return Position.create(position.line, position.character + relativePosition.character); } else { return Position.create(position.line + relativePosition.line, relativePosition.character); } } }