From dd0dce512e8caef4c8b9ac7fc7869c8751b58432 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 12 Jul 2025 21:56:35 +0200 Subject: [PATCH 1/4] Remove legacy code and comments --- .../DisabledLanguageDefinitions.ts | 4 - .../src/languages/LanguageDefinition.ts | 3 +- .../src/languages/LanguageDefinitions.ts | 9 - .../modifiers/RelativeScopeStage.ts | 12 +- .../modifiers/relativeScopeLegacy.ts | 207 ------------------ .../scopeHandlers/ScopeHandlerFactoryImpl.ts | 11 +- 6 files changed, 4 insertions(+), 242 deletions(-) delete mode 100644 packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts diff --git a/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts b/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts index f66c20136e..d726d37ba9 100644 --- a/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts +++ b/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts @@ -16,10 +16,6 @@ export class DisabledLanguageDefinitions implements LanguageDefinitions { return undefined; } - getNodeAtLocation(_document: TextDocument, _range: Range): Node | undefined { - return undefined; - } - dispose(): void { // Do nothing } diff --git a/packages/cursorless-engine/src/languages/LanguageDefinition.ts b/packages/cursorless-engine/src/languages/LanguageDefinition.ts index 366daeb4c8..37f1957b50 100644 --- a/packages/cursorless-engine/src/languages/LanguageDefinition.ts +++ b/packages/cursorless-engine/src/languages/LanguageDefinition.ts @@ -75,8 +75,7 @@ export class LanguageDefinition { /** * @param scopeType The scope type for which to get a scope handler * @returns A scope handler for the given scope type and language id, or - * undefined if the given scope type / language id combination is still using - * legacy pathways + * undefined if the given scope type is not supported by this language. */ getScopeHandler(scopeType: ScopeType) { if (!this.query.hasCapture(scopeType.type)) { diff --git a/packages/cursorless-engine/src/languages/LanguageDefinitions.ts b/packages/cursorless-engine/src/languages/LanguageDefinitions.ts index a0c255816a..25affc6063 100644 --- a/packages/cursorless-engine/src/languages/LanguageDefinitions.ts +++ b/packages/cursorless-engine/src/languages/LanguageDefinitions.ts @@ -32,11 +32,6 @@ export interface LanguageDefinitions { * the given language id doesn't have a new-style query definition */ get(languageId: string): LanguageDefinition | undefined; - - /** - * @deprecated Only for use in legacy containing scope stage - */ - getNodeAtLocation(document: TextDocument, range: Range): Node | undefined; } /** @@ -160,10 +155,6 @@ export class LanguageDefinitionsImpl return definition === LANGUAGE_UNDEFINED ? undefined : definition; } - public getNodeAtLocation(document: TextDocument, range: Range): Node { - return this.treeSitter.getNodeAtLocation(document, range); - } - onDidChangeDefinition = this.notifier.registerListener; dispose() { diff --git a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts index 60a05a93e7..b4a2298053 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts @@ -12,7 +12,6 @@ import type { import { constructScopeRangeTarget } from "./constructScopeRangeTarget"; import { getPreferredScopeTouchingPosition } from "./getPreferredScopeTouchingPosition"; import { OutOfRangeError } from "./listUtils"; -import { runLegacy } from "./relativeScopeLegacy"; import type { ScopeHandlerFactory } from "./scopeHandlers/ScopeHandlerFactory"; import type { TargetScope } from "./scopeHandlers/scope.types"; import type { @@ -34,20 +33,11 @@ export class RelativeScopeStage implements ModifierStage { ) {} run(target: Target, options: ModifierStateOptions): Target[] { - const scopeHandler = this.scopeHandlerFactory.maybeCreate( + const scopeHandler = this.scopeHandlerFactory.create( this.modifier.scopeType, target.editor.document.languageId, ); - if (scopeHandler == null) { - return runLegacy( - this.modifierStageFactory, - this.modifier, - target, - options, - ); - } - const scopes = Array.from( this.modifier.offset === 0 ? generateScopesInclusive(scopeHandler, target, this.modifier) diff --git a/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts b/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts deleted file mode 100644 index 77223d02f4..0000000000 --- a/packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts +++ /dev/null @@ -1,207 +0,0 @@ -import type { Range, RelativeScopeModifier } from "@cursorless/common"; -import { findLastIndex } from "lodash-es"; -import type { Target } from "../../typings/target.types"; -import type { ModifierStageFactory } from "../ModifierStageFactory"; -import type { ModifierStateOptions } from "../PipelineStages.types"; -import { UntypedTarget } from "../targets"; -import { OutOfRangeError } from "./listUtils"; -import { - createRangeTargetFromIndices, - getEveryScopeTargets, -} from "./targetSequenceUtils"; -import { TooFewScopesError } from "./TooFewScopesError"; - -interface ContainingIndices { - start: number; - end: number; -} - -export function runLegacy( - modifierStageFactory: ModifierStageFactory, - modifier: RelativeScopeModifier, - target: Target, - options: ModifierStateOptions, -): Target[] { - /** - * A list of targets in the iteration scope for the input {@link target}. - * Note that we convert {@link target} to have no explicit range so that we - * get all targets in the iteration scope rather than just the intersecting - * targets. - * - * FIXME: In the future we should probably use a better abstraction for this, but - * that will rely on #629 - */ - const targets = getEveryScopeTargets( - modifierStageFactory, - createTargetWithoutExplicitRange(target), - options, - modifier.scopeType, - ); - - const containingIndices = getContainingIndices(target.contentRange, targets); - - return calculateIndicesAndCreateTarget( - modifier, - target, - targets, - containingIndices, - ); -} - -function calculateIndicesAndCreateTarget( - modifier: RelativeScopeModifier, - target: Target, - targets: Target[], - containingIndices: ContainingIndices | undefined, -): Target[] { - const isForward = modifier.direction === "forward"; - - /** Proximal index. This is the index closest to the target content range. */ - const proximalIndex = computeProximalIndex( - modifier, - target.contentRange, - targets, - isForward, - containingIndices, - ); - - /** Index of range farther from input target */ - const distalIndex = isForward - ? proximalIndex + modifier.length - 1 - : proximalIndex - modifier.length + 1; - - const startIndex = Math.min(proximalIndex, distalIndex); - const endIndex = Math.max(proximalIndex, distalIndex); - - return [ - createRangeTargetFromIndices( - modifier.scopeType, - target.isReversed, - targets, - startIndex, - endIndex, - ), - ]; -} - -/** - * Compute the index of the target that will form the near end of the range. - * - * @param inputTargetRange The range of the input target to the modifier stage - * @param targets A list of all targets under consideration (eg in iteration - * scope) - * @param isForward `true` if we are handling "next", `false` if "previous" - * @returns The index into {@link targets} that will form the near end of the range. - */ -function computeProximalIndex( - modifier: RelativeScopeModifier, - inputTargetRange: Range, - targets: Target[], - isForward: boolean, - containingIndices: ContainingIndices | undefined, -) { - const includeIntersectingScopes = modifier.offset === 0; - - if (containingIndices == null) { - const adjacentTargetIndex = isForward - ? targets.findIndex((t) => - t.contentRange.start.isAfter(inputTargetRange.start), - ) - : findLastIndex(targets, (t) => - t.contentRange.start.isBefore(inputTargetRange.start), - ); - - if (adjacentTargetIndex === -1) { - throw new OutOfRangeError(modifier.scopeType); - } - - // For convenience, if they ask to include intersecting indices, we just - // start with the nearest one in the correct direction. So eg if you say - // "two funks" between functions, it will take two functions to the right - // of you. - if (includeIntersectingScopes) { - return adjacentTargetIndex; - } - - return isForward - ? adjacentTargetIndex + modifier.offset - 1 - : adjacentTargetIndex - modifier.offset + 1; - } - - // If we've made it here, then there are scopes intersecting with - // {@link inputTargetRange} - const intersectingStartIndex = containingIndices.start; - const intersectingEndIndex = containingIndices.end; - - if (includeIntersectingScopes) { - // Number of scopes intersecting with input target is already greater than - // desired length; throw error. This occurs if user says "two funks", and - // they have 3 functions selected. Not clear what to do in that case so - // we throw error. - const intersectingLength = - intersectingEndIndex - intersectingStartIndex + 1; - if (intersectingLength > modifier.length) { - throw new TooFewScopesError( - modifier.length, - intersectingLength, - modifier.scopeType.type, - ); - } - - // This ensures that we count intersecting scopes in "three funks", so - // that we will never get more than 3 functions. - return isForward ? intersectingStartIndex : intersectingEndIndex; - } - - // If we are excluding the intersecting scopes, then we set 0 to be such - // that the next scope will be the first non-intersecting. - return isForward - ? intersectingEndIndex + modifier.offset - : intersectingStartIndex - modifier.offset; -} - -/** Get indices of all targets in {@link targets} intersecting with - * {@link inputTargetRange} */ -function getContainingIndices( - inputTargetRange: Range, - targets: Target[], -): ContainingIndices | undefined { - const targetsWithIntersection = targets - .map((t, i) => ({ - index: i, - intersection: t.contentRange.intersection(inputTargetRange), - })) - .filter((t) => t.intersection != null); - - // Input target range is empty. Use rightmost target and accept weak - // containment. - if (inputTargetRange.isEmpty) { - if (targetsWithIntersection.length === 0) { - return undefined; - } - const index = targetsWithIntersection.at(-1)!.index; - return { start: index, end: index }; - } - - // Input target range is not empty. Use all targets with non empty - // intersections. - const targetsWithNonEmptyIntersection = targetsWithIntersection - .filter((t) => !t.intersection!.isEmpty) - .map((t) => t.index); - if (targetsWithNonEmptyIntersection.length === 0) { - return undefined; - } - return { - start: targetsWithNonEmptyIntersection[0], - end: targetsWithNonEmptyIntersection.at(-1)!, - }; -} - -function createTargetWithoutExplicitRange(target: Target) { - return new UntypedTarget({ - editor: target.editor, - isReversed: target.isReversed, - contentRange: target.contentRange, - hasExplicitRange: false, - }); -} diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts index 9facfd1f11..046a25fe12 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts @@ -33,20 +33,13 @@ import { WordScopeHandler } from "./WordScopeHandler/WordScopeHandler"; /** * Returns a scope handler for the given scope type and language id, or - * undefined if the given scope type / language id combination is still using - * legacy pathways. - * - * Note that once all our scope types are migrated to the new scope handler - * setup for all languages, we can stop returning `undefined`, change the return - * type of this function, and remove the legacy checks in the clients of this - * function. + * undefined if the given scope type / language id combination is not supported. * * @param scopeType The scope type for which to get a scope handler * @param languageId The language id of the document where the scope handler * will be used * @returns A scope handler for the given scope type and language id, or - * undefined if the given scope type / language id combination is still using - * legacy pathways + * undefined if the given scope type / language id combination is not supported. */ export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory { constructor(private languageDefinitions: LanguageDefinitions) { From f87493d9d39a12d04fc3b3d8755d71e2ddaa787e Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 12 Jul 2025 22:00:20 +0200 Subject: [PATCH 2/4] Clean up --- .../src/processTargets/modifiers/RelativeScopeStage.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts index b4a2298053..1bb6788d8a 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts @@ -5,10 +5,7 @@ import { import { islice, itake } from "itertools"; import type { Target } from "../../typings/target.types"; import type { ModifierStageFactory } from "../ModifierStageFactory"; -import type { - ModifierStage, - ModifierStateOptions, -} from "../PipelineStages.types"; +import type { ModifierStage } from "../PipelineStages.types"; import { constructScopeRangeTarget } from "./constructScopeRangeTarget"; import { getPreferredScopeTouchingPosition } from "./getPreferredScopeTouchingPosition"; import { OutOfRangeError } from "./listUtils"; @@ -32,7 +29,7 @@ export class RelativeScopeStage implements ModifierStage { private modifier: RelativeScopeModifier, ) {} - run(target: Target, options: ModifierStateOptions): Target[] { + run(target: Target): Target[] { const scopeHandler = this.scopeHandlerFactory.create( this.modifier.scopeType, target.editor.document.languageId, From f8c5a6ec4109a14a63ce1e238fc5208259d2d316 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 12 Jul 2025 22:01:30 +0200 Subject: [PATCH 3/4] More clean up --- .../src/processTargets/ModifierStageFactoryImpl.ts | 2 +- .../src/processTargets/modifiers/RelativeScopeStage.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts b/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts index 92f011e5a8..1bfc0cb3fa 100644 --- a/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts +++ b/packages/cursorless-engine/src/processTargets/ModifierStageFactoryImpl.ts @@ -83,7 +83,7 @@ export class ModifierStageFactoryImpl implements ModifierStageFactory { if (modifier.scopeType.type === "instance") { return new InstanceStage(this, this.storedTargets, modifier); } - return new RelativeScopeStage(this, this.scopeHandlerFactory, modifier); + return new RelativeScopeStage(this.scopeHandlerFactory, modifier); case "keepContentFilter": return new KeepContentFilterStage(modifier); case "keepEmptyFilter": diff --git a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts index 1bb6788d8a..27641d1bfb 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts @@ -4,7 +4,6 @@ import { } from "@cursorless/common"; import { islice, itake } from "itertools"; import type { Target } from "../../typings/target.types"; -import type { ModifierStageFactory } from "../ModifierStageFactory"; import type { ModifierStage } from "../PipelineStages.types"; import { constructScopeRangeTarget } from "./constructScopeRangeTarget"; import { getPreferredScopeTouchingPosition } from "./getPreferredScopeTouchingPosition"; @@ -24,7 +23,6 @@ import type { */ export class RelativeScopeStage implements ModifierStage { constructor( - private modifierStageFactory: ModifierStageFactory, private scopeHandlerFactory: ScopeHandlerFactory, private modifier: RelativeScopeModifier, ) {} From 83808444bc4c01bf7e47d5f51a3a1f5030715898 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 12 Jul 2025 22:05:18 +0200 Subject: [PATCH 4/4] Remove unused imports --- .../src/disabledComponents/DisabledLanguageDefinitions.ts | 3 +-- .../cursorless-engine/src/languages/LanguageDefinitions.ts | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts b/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts index d726d37ba9..8712704168 100644 --- a/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts +++ b/packages/cursorless-engine/src/disabledComponents/DisabledLanguageDefinitions.ts @@ -1,5 +1,4 @@ -import type { TextDocument, Range, Listener } from "@cursorless/common"; -import type { Node } from "web-tree-sitter"; +import type { Listener } from "@cursorless/common"; import type { LanguageDefinition } from "../languages/LanguageDefinition"; import type { LanguageDefinitions } from "../languages/LanguageDefinitions"; diff --git a/packages/cursorless-engine/src/languages/LanguageDefinitions.ts b/packages/cursorless-engine/src/languages/LanguageDefinitions.ts index 25affc6063..3afd0358a7 100644 --- a/packages/cursorless-engine/src/languages/LanguageDefinitions.ts +++ b/packages/cursorless-engine/src/languages/LanguageDefinitions.ts @@ -1,4 +1,4 @@ -import type { Disposable, Range, TextDocument } from "@cursorless/common"; +import type { Disposable } from "@cursorless/common"; import { Notifier, showError, @@ -8,7 +8,6 @@ import { type TreeSitter, } from "@cursorless/common"; import { toString } from "lodash-es"; -import type { Node } from "web-tree-sitter"; import { LanguageDefinition } from "./LanguageDefinition"; import { treeSitterQueryCache } from "./TreeSitterQuery/treeSitterQueryCache";