From 3b9fc6de36558070d337cd71a125034721d8b3a4 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 20 Sep 2026 00:55:58 +0200 Subject: [PATCH 1/2] Improved sorting of collection item iteration scopes --- .../CollectionItemCompoundScopeHandler.ts | 59 +++++++++++++++++ .../CollectionItemScopeHandler.ts | 11 ++-- ...lectionItemTextualIterationScopeHandler.ts | 4 +- .../scopeHandlers/SortedScopeHandler.ts | 21 ++++-- .../modifiers/everyScope/changeEveryItem.yml | 31 +++++++++ ...collectionItem.unenclosed.iteration2.scope | 13 +--- .../collectionItem.unenclosed.iteration.scope | 8 +-- .../collectionItem.unenclosed.iteration.scope | 13 +--- ...collectionItem.unenclosed.iteration2.scope | 13 +--- ...collectionItem.unenclosed.iteration3.scope | 13 +--- ...collectionItem.unenclosed.iteration4.scope | 10 +++ ...collectionItem.unenclosed.iteration5.scope | 10 +++ ...collectionItem.unenclosed.multiLine4.scope | 59 +++++++++++++++++ ...collectionItem.unenclosed.multiLine5.scope | 59 +++++++++++++++++ ...ollectionItem.unenclosed.singleLine4.scope | 65 +++++++++++++++++++ ...ollectionItem.unenclosed.singleLine5.scope | 65 +++++++++++++++++++ .../collectionItem.unenclosed.iteration.scope | 12 +--- ...collectionItem.unenclosed.iteration3.scope | 13 +--- ...collectionItem.unenclosed.iteration4.scope | 10 +-- resources/queries/java.scm | 23 +++++++ 20 files changed, 420 insertions(+), 92 deletions(-) create mode 100644 packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemCompoundScopeHandler.ts create mode 100644 resources/fixtures/recorded/modifiers/everyScope/changeEveryItem.yml create mode 100644 resources/fixtures/scopes/java/collectionItem.unenclosed.iteration4.scope create mode 100644 resources/fixtures/scopes/java/collectionItem.unenclosed.iteration5.scope create mode 100644 resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine4.scope create mode 100644 resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine5.scope create mode 100644 resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine4.scope create mode 100644 resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine5.scope diff --git a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemCompoundScopeHandler.ts b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemCompoundScopeHandler.ts new file mode 100644 index 0000000000..60c05f1344 --- /dev/null +++ b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemCompoundScopeHandler.ts @@ -0,0 +1,59 @@ +import type { Direction, Position } from "@cursorless/lib-common"; +import { ensureSingleTarget } from "../../../../util/targetUtils"; +import type { TargetScope } from "../scope.types"; +import type { CustomScopeType } from "../scopeHandler.types"; +import { SortedScopeHandler } from "../SortedScopeHandler"; + +export class CollectionItemCompoundScopeHandler extends SortedScopeHandler { + private isIterator: boolean = false; + + get iterationScopeType(): CustomScopeType { + if (this.iterationScopeHandler == null) { + const iterationScopeHandlers = this.scopeHandlers.map((s) => + this.scopeHandlerFactory.create(s.iterationScopeType, this.languageId), + ); + const iterationScopeHandler = new CollectionItemCompoundScopeHandler( + this.scopeHandlerFactory, + this.languageId, + iterationScopeHandlers, + ); + iterationScopeHandler.isIterator = true; + this.iterationScopeHandler = iterationScopeHandler; + } + return { + type: "custom", + scopeHandler: this.iterationScopeHandler, + }; + } + + protected override compareScopes( + direction: Direction, + position: Position, + a: TargetScope, + b: TargetScope, + ): number { + if (!this.isIterator) { + return super.compareScopes(direction, position, a, b); + } + + const intersection = a.domain.intersection(b.domain); + + if (intersection == null || intersection.isEmpty) { + return super.compareScopes(direction, position, a, b); + } + + const aIsLine = isLine(a); + const bIsLine = isLine(b); + + // Prefer non-line targets over line targets + if (aIsLine !== bIsLine) { + return Number(aIsLine) - Number(bIsLine); + } + + return super.compareScopes(direction, position, a, b); + } +} + +function isLine(scope: TargetScope): boolean { + return ensureSingleTarget(scope.getTargets(false)).textualType === "line"; +} diff --git a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemScopeHandler.ts b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemScopeHandler.ts index c904cff854..cdb95ec3ce 100644 --- a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemScopeHandler.ts +++ b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/CollectionItemScopeHandler.ts @@ -13,7 +13,7 @@ import type { ScopeIteratorRequirements, } from "../scopeHandler.types"; import type { ScopeHandlerFactory } from "../ScopeHandlerFactory"; -import { SortedScopeHandler } from "../SortedScopeHandler"; +import { CollectionItemCompoundScopeHandler } from "./CollectionItemCompoundScopeHandler"; import { CollectionItemTextualScopeHandler } from "./CollectionItemTextualScopeHandler"; export class CollectionItemScopeHandler extends BaseScopeHandler { @@ -46,10 +46,11 @@ export class CollectionItemScopeHandler extends BaseScopeHandler { return textualScopeHandler; } - return new SortedScopeHandler(scopeHandlerFactory, languageId, [ - languageScopeHandler, - textualScopeHandler, - ]); + return new CollectionItemCompoundScopeHandler( + scopeHandlerFactory, + languageId, + [languageScopeHandler, textualScopeHandler], + ); })(); } diff --git a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts index 555a629de3..a1d1ddfbc7 100644 --- a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts +++ b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts @@ -1,8 +1,8 @@ import { testRegex } from "@cursorless/lib-common"; -import type { ComplexScopeType } from "../scopeHandler.types"; +import type { FallbackScopeType } from "../scopeHandler.types"; import { separatorRegex } from "./getSeparatorOccurrences"; -export const collectionItemTextualIterationScopeHandler: ComplexScopeType = { +export const collectionItemTextualIterationScopeHandler: FallbackScopeType = { type: "fallback", scopeTypes: [ { diff --git a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/SortedScopeHandler.ts b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/SortedScopeHandler.ts index 028368d204..b257fe4e21 100644 --- a/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/SortedScopeHandler.ts +++ b/packages/lib-engine/src/processTargets/modifiers/scopeHandlers/SortedScopeHandler.ts @@ -14,7 +14,7 @@ import type { ScopeHandlerFactory } from "./ScopeHandlerFactory"; export class SortedScopeHandler extends BaseScopeHandler { protected isHierarchical = true; public scopeType = undefined; - private iterationScopeHandler: SortedScopeHandler | undefined; + protected iterationScopeHandler: SortedScopeHandler | undefined; private lastYieldedIndex: number | undefined; static maybeCreate( @@ -46,9 +46,9 @@ export class SortedScopeHandler extends BaseScopeHandler { } constructor( - private scopeHandlerFactory: ScopeHandlerFactory, - private languageId: string, - private scopeHandlers: ScopeHandler[], + protected scopeHandlerFactory: ScopeHandlerFactory, + protected languageId: string, + protected scopeHandlers: ScopeHandler[], ) { super(); } @@ -98,7 +98,7 @@ export class SortedScopeHandler extends BaseScopeHandler { while (iteratorInfos.length > 0) { iteratorInfos.sort((a, b) => - compareTargetScopes(direction, position, a.value, b.value), + this.compareScopes(direction, position, a.value, b.value), ); // Pick minimum scope according to canonical scope ordering @@ -112,8 +112,17 @@ export class SortedScopeHandler extends BaseScopeHandler { iteratorInfos = advanceIteratorsUntil( iteratorInfos, (scope) => - compareTargetScopes(direction, position, currentScope, scope) < 0, + this.compareScopes(direction, position, currentScope, scope) < 0, ); } } + + protected compareScopes( + direction: Direction, + position: Position, + a: TargetScope, + b: TargetScope, + ): number { + return compareTargetScopes(direction, position, a, b); + } } diff --git a/resources/fixtures/recorded/modifiers/everyScope/changeEveryItem.yml b/resources/fixtures/recorded/modifiers/everyScope/changeEveryItem.yml new file mode 100644 index 0000000000..1a0f88a857 --- /dev/null +++ b/resources/fixtures/recorded/modifiers/everyScope/changeEveryItem.yml @@ -0,0 +1,31 @@ +languageId: java +command: + version: 7 + spokenForm: change every item + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: collectionItem} + usePrePhraseSnapshot: false +initialState: + documentContents: |- + sealed interface Foo + permits Bar, + Baz {} + selections: + - anchor: {line: 1, character: 14} + active: {line: 1, character: 14} + marks: {} +finalState: + documentContents: |- + sealed interface Foo + permits , + {} + selections: + - anchor: {line: 1, character: 12} + active: {line: 1, character: 12} + - anchor: {line: 2, character: 4} + active: {line: 2, character: 4} diff --git a/resources/fixtures/scopes/csharp/collectionItem.unenclosed.iteration2.scope b/resources/fixtures/scopes/csharp/collectionItem.unenclosed.iteration2.scope index 531c2a9864..68f7087baa 100644 --- a/resources/fixtures/scopes/csharp/collectionItem.unenclosed.iteration2.scope +++ b/resources/fixtures/scopes/csharp/collectionItem.unenclosed.iteration2.scope @@ -15,19 +15,10 @@ class Foo { < -[#2 Content] = 1:4-1:25 - >---------------------< -1| private int bar, baz; - -[#2 Domain] = 1:0-1:25 - >-------------------------< -1| private int bar, baz; - - -[#3 Content] = 1:16-1:24 +[#2 Content] = 1:16-1:24 >--------< 1| private int bar, baz; -[#3 Domain] = 1:4-1:25 +[#2 Domain] = 1:4-1:25 >---------------------< 1| private int bar, baz; diff --git a/resources/fixtures/scopes/go/collectionItem.unenclosed.iteration.scope b/resources/fixtures/scopes/go/collectionItem.unenclosed.iteration.scope index dfd6e14f6c..367bc50efe 100644 --- a/resources/fixtures/scopes/go/collectionItem.unenclosed.iteration.scope +++ b/resources/fixtures/scopes/go/collectionItem.unenclosed.iteration.scope @@ -8,12 +8,6 @@ foo, bar := 1, 2 [#2 Content] = -[#2 Domain] = 0:0-0:16 - >----------------< -0| foo, bar := 1, 2 - - -[#3 Content] = -[#3 Domain] = 0:12-0:16 +[#2 Domain] = 0:12-0:16 >----< 0| foo, bar := 1, 2 diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration.scope index b29f3941ca..c04adac099 100644 --- a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration.scope +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration.scope @@ -15,19 +15,10 @@ public class Foo { < -[#2 Content] = 1:4-1:17 - >-------------< -1| int aaa, bbb; - -[#2 Domain] = 1:0-1:17 - >-----------------< -1| int aaa, bbb; - - -[#3 Content] = 1:8-1:16 +[#2 Content] = 1:8-1:16 >--------< 1| int aaa, bbb; -[#3 Domain] = 1:4-1:17 +[#2 Domain] = 1:4-1:17 >-------------< 1| int aaa, bbb; diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope index c03d91de48..b6e0bd3902 100644 --- a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope @@ -34,19 +34,10 @@ class Foo { ----< -[#3 Content] = 2:8-2:21 - >-------------< -2| int aaa, bbb; - -[#3 Domain] = 2:0-2:21 - >---------------------< -2| int aaa, bbb; - - -[#4 Content] = 2:12-2:20 +[#3 Content] = 2:12-2:20 >--------< 2| int aaa, bbb; -[#4 Domain] = 2:8-2:21 +[#3 Domain] = 2:8-2:21 >-------------< 2| int aaa, bbb; diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration3.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration3.scope index 9f5f3c4958..3339e8e823 100644 --- a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration3.scope +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration3.scope @@ -15,19 +15,10 @@ class Foo { < -[#2 Content] = 1:4-1:47 - >-------------------------------------------< -1| void bar() throws AException, BException {} - -[#2 Domain] = 1:0-1:47 - >-----------------------------------------------< -1| void bar() throws AException, BException {} - - -[#3 Content] = 1:22-1:44 +[#2 Content] = 1:22-1:44 >----------------------< 1| void bar() throws AException, BException {} -[#3 Domain] = 1:15-1:44 +[#2 Domain] = 1:15-1:44 >-----------------------------< 1| void bar() throws AException, BException {} diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration4.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration4.scope new file mode 100644 index 0000000000..b39f3b0cf9 --- /dev/null +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration4.scope @@ -0,0 +1,10 @@ +sealed class Foo implements Bar, Baz {} +--- + +[Content] = 0:28-0:36 + >--------< +0| sealed class Foo implements Bar, Baz {} + +[Domain] = 0:17-0:36 + >-------------------< +0| sealed class Foo implements Bar, Baz {} diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration5.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration5.scope new file mode 100644 index 0000000000..b595d5b96b --- /dev/null +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.iteration5.scope @@ -0,0 +1,10 @@ +sealed interface Foo permits Bar, Baz {} +--- + +[Content] = 0:29-0:37 + >--------< +0| sealed interface Foo permits Bar, Baz {} + +[Domain] = 0:21-0:37 + >----------------< +0| sealed interface Foo permits Bar, Baz {} diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine4.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine4.scope new file mode 100644 index 0000000000..f2f77c2a7e --- /dev/null +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine4.scope @@ -0,0 +1,59 @@ +sealed class Foo + implements Bar, + Baz {} +--- + +[#1 Content] = +[#1 Domain] = 1:4-1:18 + >--------------< +1| implements Bar, + +[#1 Removal] = 1:4-1:19 + >---------------< +1| implements Bar, + +[#1 Trailing delimiter] = 1:18-1:19 + >-< +1| implements Bar, + +[#1 Insertion delimiter] = ", " + + +[#2 Content] = +[#2 Domain] = 1:15-1:18 + >---< +1| implements Bar, + +[#2 Removal] = 1:15-2:4 + >---- +1| implements Bar, +2| Baz {} + ----< + +[#2 Trailing delimiter] = 1:18-2:4 + >- +1| implements Bar, +2| Baz {} + ----< + +[#2 Insertion delimiter] = ",\n" + + +[#3 Content] = +[#3 Domain] = 2:4-2:7 + >---< +2| Baz {} + +[#3 Removal] = 1:18-2:7 + >- +1| implements Bar, +2| Baz {} + -------< + +[#3 Leading delimiter] = 1:18-2:4 + >- +1| implements Bar, +2| Baz {} + ----< + +[#3 Insertion delimiter] = ",\n" diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine5.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine5.scope new file mode 100644 index 0000000000..dbf105f589 --- /dev/null +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.multiLine5.scope @@ -0,0 +1,59 @@ +sealed interface Foo + permits Bar, + Baz {} +--- + +[#1 Content] = +[#1 Domain] = 1:4-1:15 + >-----------< +1| permits Bar, + +[#1 Removal] = 1:4-1:16 + >------------< +1| permits Bar, + +[#1 Trailing delimiter] = 1:15-1:16 + >-< +1| permits Bar, + +[#1 Insertion delimiter] = ", " + + +[#2 Content] = +[#2 Domain] = 1:12-1:15 + >---< +1| permits Bar, + +[#2 Removal] = 1:12-2:4 + >---- +1| permits Bar, +2| Baz {} + ----< + +[#2 Trailing delimiter] = 1:15-2:4 + >- +1| permits Bar, +2| Baz {} + ----< + +[#2 Insertion delimiter] = ",\n" + + +[#3 Content] = +[#3 Domain] = 2:4-2:7 + >---< +2| Baz {} + +[#3 Removal] = 1:15-2:7 + >- +1| permits Bar, +2| Baz {} + -------< + +[#3 Leading delimiter] = 1:15-2:4 + >- +1| permits Bar, +2| Baz {} + ----< + +[#3 Insertion delimiter] = ",\n" diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine4.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine4.scope new file mode 100644 index 0000000000..b5c9394123 --- /dev/null +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine4.scope @@ -0,0 +1,65 @@ +sealed class Foo implements Bar, Baz {} +--- + +[#1 Content] = +[#1 Domain] = 0:0-0:31 + >-------------------------------< +0| sealed class Foo implements Bar, Baz {} + +[#1 Removal] = 0:0-0:33 + >---------------------------------< +0| sealed class Foo implements Bar, Baz {} + +[#1 Trailing delimiter] = 0:31-0:33 + >--< +0| sealed class Foo implements Bar, Baz {} + +[#1 Insertion delimiter] = ", " + + +[#2 Content] = +[#2 Domain] = 0:28-0:31 + >---< +0| sealed class Foo implements Bar, Baz {} + +[#2 Removal] = 0:28-0:33 + >-----< +0| sealed class Foo implements Bar, Baz {} + +[#2 Trailing delimiter] = 0:31-0:33 + >--< +0| sealed class Foo implements Bar, Baz {} + +[#2 Insertion delimiter] = ", " + + +[#3 Content] = +[#3 Domain] = 0:33-0:36 + >---< +0| sealed class Foo implements Bar, Baz {} + +[#3 Removal] = 0:31-0:36 + >-----< +0| sealed class Foo implements Bar, Baz {} + +[#3 Leading delimiter] = 0:31-0:33 + >--< +0| sealed class Foo implements Bar, Baz {} + +[#3 Insertion delimiter] = ", " + + +[#4 Content] = +[#4 Domain] = 0:33-0:39 + >------< +0| sealed class Foo implements Bar, Baz {} + +[#4 Removal] = 0:31-0:39 + >--------< +0| sealed class Foo implements Bar, Baz {} + +[#4 Leading delimiter] = 0:31-0:33 + >--< +0| sealed class Foo implements Bar, Baz {} + +[#4 Insertion delimiter] = ", " diff --git a/resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine5.scope b/resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine5.scope new file mode 100644 index 0000000000..27ed9c8f38 --- /dev/null +++ b/resources/fixtures/scopes/java/collectionItem.unenclosed.singleLine5.scope @@ -0,0 +1,65 @@ +sealed interface Foo permits Bar, Baz {} +--- + +[#1 Content] = +[#1 Domain] = 0:0-0:32 + >--------------------------------< +0| sealed interface Foo permits Bar, Baz {} + +[#1 Removal] = 0:0-0:34 + >----------------------------------< +0| sealed interface Foo permits Bar, Baz {} + +[#1 Trailing delimiter] = 0:32-0:34 + >--< +0| sealed interface Foo permits Bar, Baz {} + +[#1 Insertion delimiter] = ", " + + +[#2 Content] = +[#2 Domain] = 0:29-0:32 + >---< +0| sealed interface Foo permits Bar, Baz {} + +[#2 Removal] = 0:29-0:34 + >-----< +0| sealed interface Foo permits Bar, Baz {} + +[#2 Trailing delimiter] = 0:32-0:34 + >--< +0| sealed interface Foo permits Bar, Baz {} + +[#2 Insertion delimiter] = ", " + + +[#3 Content] = +[#3 Domain] = 0:34-0:37 + >---< +0| sealed interface Foo permits Bar, Baz {} + +[#3 Removal] = 0:32-0:37 + >-----< +0| sealed interface Foo permits Bar, Baz {} + +[#3 Leading delimiter] = 0:32-0:34 + >--< +0| sealed interface Foo permits Bar, Baz {} + +[#3 Insertion delimiter] = ", " + + +[#4 Content] = +[#4 Domain] = 0:34-0:40 + >------< +0| sealed interface Foo permits Bar, Baz {} + +[#4 Removal] = 0:32-0:40 + >--------< +0| sealed interface Foo permits Bar, Baz {} + +[#4 Leading delimiter] = 0:32-0:34 + >--< +0| sealed interface Foo permits Bar, Baz {} + +[#4 Insertion delimiter] = ", " diff --git a/resources/fixtures/scopes/lua/collectionItem.unenclosed.iteration.scope b/resources/fixtures/scopes/lua/collectionItem.unenclosed.iteration.scope index f776cb2a9d..6379864dd7 100644 --- a/resources/fixtures/scopes/lua/collectionItem.unenclosed.iteration.scope +++ b/resources/fixtures/scopes/lua/collectionItem.unenclosed.iteration.scope @@ -2,18 +2,12 @@ local a, b, c = 1, 2, 3 --- [#1 Content] = -[#1 Domain] = 0:0-0:23 - >-----------------------< -0| local a, b, c = 1, 2, 3 - - -[#2 Content] = -[#2 Domain] = 0:6-0:13 +[#1 Domain] = 0:6-0:13 >-------< 0| local a, b, c = 1, 2, 3 -[#3 Content] = -[#3 Domain] = 0:16-0:23 +[#2 Content] = +[#2 Domain] = 0:16-0:23 >-------< 0| local a, b, c = 1, 2, 3 diff --git a/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration3.scope b/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration3.scope index dca32858f2..2752d9ca21 100644 --- a/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration3.scope +++ b/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration3.scope @@ -2,19 +2,10 @@ def foo(): global bar, baz --- -[#1 Content] = 1:4-1:19 - >---------------< -1| global bar, baz - -[#1 Domain] = 1:0-1:19 - >-------------------< -1| global bar, baz - - -[#2 Content] = 1:11-1:19 +[Content] = 1:11-1:19 >--------< 1| global bar, baz -[#2 Domain] = 1:4-1:19 +[Domain] = 1:4-1:19 >---------------< 1| global bar, baz diff --git a/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration4.scope b/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration4.scope index 465717220c..16abf29cce 100644 --- a/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration4.scope +++ b/resources/fixtures/scopes/python/collectionItem/collectionItem.unenclosed.iteration4.scope @@ -2,13 +2,7 @@ for key, value in map.items(): pass --- -[#1 Content] = -[#1 Domain] = 0:0-0:30 - >------------------------------< -0| for key, value in map.items(): - - -[#2 Content] = -[#2 Domain] = 0:4-0:14 +[Content] = +[Domain] = 0:4-0:14 >----------< 0| for key, value in map.items(): diff --git a/resources/queries/java.scm b/resources/queries/java.scm index 46590c0cba..df21527f47 100644 --- a/resources/queries/java.scm +++ b/resources/queries/java.scm @@ -521,6 +521,29 @@ . ) @collectionItem.iteration.domain +;;!! class Foo implements Bar, Baz {} +;;! ^^^ ^^^ +;;!! interface Foo permits Bar, Baz {} +;;! ^^^ ^^^ +(_ + (type_list + (_)? @_.leading.endOf + . + (_) @collectionItem + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @collectionItem @_dummy ", " ",\n") +) + +;;!! class Foo implements Bar, Baz {} +;;! ^^^^^^^^ +;;!! interface Foo permits Bar, Baz {} +;;! ^^^^^^^^ +(_ + (type_list) @collectionItem.iteration +) @collectionItem.iteration.domain + ;;!! value = 1; ;;! ^ ;;! xxxx From 4093b45b9f9da648ddc791e1d666ff9597aeb88f Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 20 Sep 2026 00:57:31 +0200 Subject: [PATCH 2/2] Meta Updater --- .../docs/user/languages/fixtures/csharp.json | 8 - .../src/docs/user/languages/fixtures/go.json | 8 - .../docs/user/languages/fixtures/java.json | 208 +++++++++++++-- .../src/docs/user/languages/fixtures/lua.json | 8 - .../docs/user/languages/fixtures/python.json | 16 -- .../src/docs/user/languages/java.mdx | 12 + .../src/docs/user/scopes/collectionItem.mdx | 12 + .../user/scopes/fixtures/collectionItem.json | 248 +++++++++++++----- 8 files changed, 398 insertions(+), 122 deletions(-) diff --git a/packages/app-web-docs/src/docs/user/languages/fixtures/csharp.json b/packages/app-web-docs/src/docs/user/languages/fixtures/csharp.json index f8bb633e7b..91c743a4cf 100644 --- a/packages/app-web-docs/src/docs/user/languages/fixtures/csharp.json +++ b/packages/app-web-docs/src/docs/user/languages/fixtures/csharp.json @@ -1233,14 +1233,6 @@ ], "domain": "0:11-2:0" }, - { - "targets": [ - { - "content": "1:4-1:25" - } - ], - "domain": "1:0-1:25" - }, { "targets": [ { diff --git a/packages/app-web-docs/src/docs/user/languages/fixtures/go.json b/packages/app-web-docs/src/docs/user/languages/fixtures/go.json index f98497e527..bee803acff 100644 --- a/packages/app-web-docs/src/docs/user/languages/fixtures/go.json +++ b/packages/app-web-docs/src/docs/user/languages/fixtures/go.json @@ -836,14 +836,6 @@ ], "domain": "0:0-0:8" }, - { - "targets": [ - { - "content": "0:0-0:16" - } - ], - "domain": "0:0-0:16" - }, { "targets": [ { diff --git a/packages/app-web-docs/src/docs/user/languages/fixtures/java.json b/packages/app-web-docs/src/docs/user/languages/fixtures/java.json index 1906c13af3..3c4d5eaa15 100644 --- a/packages/app-web-docs/src/docs/user/languages/fixtures/java.json +++ b/packages/app-web-docs/src/docs/user/languages/fixtures/java.json @@ -1251,14 +1251,6 @@ ], "domain": "0:18-2:0" }, - { - "targets": [ - { - "content": "1:4-1:17" - } - ], - "domain": "1:0-1:17" - }, { "targets": [ { @@ -1291,14 +1283,6 @@ ], "domain": "1:16-3:4" }, - { - "targets": [ - { - "content": "2:8-2:21" - } - ], - "domain": "2:0-2:21" - }, { "targets": [ { @@ -1326,18 +1310,42 @@ { "targets": [ { - "content": "1:4-1:47" + "content": "1:22-1:44" } ], - "domain": "1:0-1:47" - }, + "domain": "1:15-1:44" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.iteration4", + "languageId": "java", + "facet": "collectionItem.unenclosed.iteration", + "code": "sealed class Foo implements Bar, Baz {}", + "scopes": [ { "targets": [ { - "content": "1:22-1:44" + "content": "0:28-0:36" } ], - "domain": "1:15-1:44" + "domain": "0:17-0:36" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.iteration5", + "languageId": "java", + "facet": "collectionItem.unenclosed.iteration", + "code": "sealed interface Foo permits Bar, Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "0:29-0:37" + } + ], + "domain": "0:21-0:37" } ] }, @@ -1482,6 +1490,76 @@ } ] }, + { + "name": "scopes/java/collectionItem.unenclosed.multiLine4", + "languageId": "java", + "facet": "collectionItem.unenclosed.multiLine", + "code": "sealed class Foo\n implements Bar,\n Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "1:4-1:18", + "removal": "1:4-1:19" + } + ], + "domain": "1:4-1:18" + }, + { + "targets": [ + { + "content": "1:15-1:18", + "removal": "1:15-2:4" + } + ], + "domain": "1:15-1:18" + }, + { + "targets": [ + { + "content": "2:4-2:7", + "removal": "1:18-2:7" + } + ], + "domain": "2:4-2:7" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.multiLine5", + "languageId": "java", + "facet": "collectionItem.unenclosed.multiLine", + "code": "sealed interface Foo\n permits Bar,\n Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "1:4-1:15", + "removal": "1:4-1:16" + } + ], + "domain": "1:4-1:15" + }, + { + "targets": [ + { + "content": "1:12-1:15", + "removal": "1:12-2:4" + } + ], + "domain": "1:12-1:15" + }, + { + "targets": [ + { + "content": "2:4-2:7", + "removal": "1:15-2:7" + } + ], + "domain": "2:4-2:7" + } + ] + }, { "name": "scopes/java/collectionItem.unenclosed.singleLine", "languageId": "java", @@ -1623,6 +1701,94 @@ } ] }, + { + "name": "scopes/java/collectionItem.unenclosed.singleLine4", + "languageId": "java", + "facet": "collectionItem.unenclosed.singleLine", + "code": "sealed class Foo implements Bar, Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "0:0-0:31", + "removal": "0:0-0:33" + } + ], + "domain": "0:0-0:31" + }, + { + "targets": [ + { + "content": "0:28-0:31", + "removal": "0:28-0:33" + } + ], + "domain": "0:28-0:31" + }, + { + "targets": [ + { + "content": "0:33-0:36", + "removal": "0:31-0:36" + } + ], + "domain": "0:33-0:36" + }, + { + "targets": [ + { + "content": "0:33-0:39", + "removal": "0:31-0:39" + } + ], + "domain": "0:33-0:39" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.singleLine5", + "languageId": "java", + "facet": "collectionItem.unenclosed.singleLine", + "code": "sealed interface Foo permits Bar, Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "0:0-0:32", + "removal": "0:0-0:34" + } + ], + "domain": "0:0-0:32" + }, + { + "targets": [ + { + "content": "0:29-0:32", + "removal": "0:29-0:34" + } + ], + "domain": "0:29-0:32" + }, + { + "targets": [ + { + "content": "0:34-0:37", + "removal": "0:32-0:37" + } + ], + "domain": "0:34-0:37" + }, + { + "targets": [ + { + "content": "0:34-0:40", + "removal": "0:32-0:40" + } + ], + "domain": "0:34-0:40" + } + ] + }, { "name": "scopes/java/comment.block", "languageId": "java", diff --git a/packages/app-web-docs/src/docs/user/languages/fixtures/lua.json b/packages/app-web-docs/src/docs/user/languages/fixtures/lua.json index 8fb4167955..665256d6bd 100644 --- a/packages/app-web-docs/src/docs/user/languages/fixtures/lua.json +++ b/packages/app-web-docs/src/docs/user/languages/fixtures/lua.json @@ -711,14 +711,6 @@ "facet": "collectionItem.unenclosed.iteration", "code": "local a, b, c = 1, 2, 3", "scopes": [ - { - "targets": [ - { - "content": "0:0-0:23" - } - ], - "domain": "0:0-0:23" - }, { "targets": [ { diff --git a/packages/app-web-docs/src/docs/user/languages/fixtures/python.json b/packages/app-web-docs/src/docs/user/languages/fixtures/python.json index fb2f663d26..7a7d7f3905 100644 --- a/packages/app-web-docs/src/docs/user/languages/fixtures/python.json +++ b/packages/app-web-docs/src/docs/user/languages/fixtures/python.json @@ -1377,14 +1377,6 @@ "facet": "collectionItem.unenclosed.iteration", "code": "def foo():\n global bar, baz", "scopes": [ - { - "targets": [ - { - "content": "1:4-1:19" - } - ], - "domain": "1:0-1:19" - }, { "targets": [ { @@ -1401,14 +1393,6 @@ "facet": "collectionItem.unenclosed.iteration", "code": "for key, value in map.items():\n pass", "scopes": [ - { - "targets": [ - { - "content": "0:0-0:30" - } - ], - "domain": "0:0-0:30" - }, { "targets": [ { diff --git a/packages/app-web-docs/src/docs/user/languages/java.mdx b/packages/app-web-docs/src/docs/user/languages/java.mdx index 895a4ccee7..3e2a1d2425 100644 --- a/packages/app-web-docs/src/docs/user/languages/java.mdx +++ b/packages/app-web-docs/src/docs/user/languages/java.mdx @@ -385,6 +385,10 @@ Below are visualizations of all our scope tests for this language. These were cr + + + + #### 2. Collection item: Unenclosed single line An item in a comma-separated single-line list without enclosing delimiters. This could be multi-variable declarations, import statements, etc. @@ -395,6 +399,10 @@ Below are visualizations of all our scope tests for this language. These were cr + + + + #### 3. Collection item: Unenclosed (iteration) Iteration scope for items in a comma-separated list without enclosing delimiters @@ -405,6 +413,10 @@ Below are visualizations of all our scope tests for this language. These were cr + + + + ### Comment #### 1. Comment: Block diff --git a/packages/app-web-docs/src/docs/user/scopes/collectionItem.mdx b/packages/app-web-docs/src/docs/user/scopes/collectionItem.mdx index bf1b91aed5..f1e44760ac 100644 --- a/packages/app-web-docs/src/docs/user/scopes/collectionItem.mdx +++ b/packages/app-web-docs/src/docs/user/scopes/collectionItem.mdx @@ -97,6 +97,10 @@ Default: `item` + + + + ##### JavaScript @@ -151,6 +155,10 @@ Default: `item` + + + + ##### JavaScript @@ -227,6 +235,10 @@ Default: `item` + + + + ##### JavaScript diff --git a/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionItem.json b/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionItem.json index 1de3d58c3e..b052bfb74f 100644 --- a/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionItem.json +++ b/packages/app-web-docs/src/docs/user/scopes/fixtures/collectionItem.json @@ -124,14 +124,6 @@ ], "domain": "0:11-2:0" }, - { - "targets": [ - { - "content": "1:4-1:25" - } - ], - "domain": "1:0-1:25" - }, { "targets": [ { @@ -469,14 +461,6 @@ ], "domain": "0:0-0:8" }, - { - "targets": [ - { - "content": "0:0-0:16" - } - ], - "domain": "0:0-0:16" - }, { "targets": [ { @@ -607,14 +591,6 @@ ], "domain": "0:18-2:0" }, - { - "targets": [ - { - "content": "1:4-1:17" - } - ], - "domain": "1:0-1:17" - }, { "targets": [ { @@ -647,14 +623,6 @@ ], "domain": "1:16-3:4" }, - { - "targets": [ - { - "content": "2:8-2:21" - } - ], - "domain": "2:0-2:21" - }, { "targets": [ { @@ -682,18 +650,42 @@ { "targets": [ { - "content": "1:4-1:47" + "content": "1:22-1:44" } ], - "domain": "1:0-1:47" - }, + "domain": "1:15-1:44" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.iteration4", + "languageId": "java", + "facet": "collectionItem.unenclosed.iteration", + "code": "sealed class Foo implements Bar, Baz {}", + "scopes": [ { "targets": [ { - "content": "1:22-1:44" + "content": "0:28-0:36" } ], - "domain": "1:15-1:44" + "domain": "0:17-0:36" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.iteration5", + "languageId": "java", + "facet": "collectionItem.unenclosed.iteration", + "code": "sealed interface Foo permits Bar, Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "0:29-0:37" + } + ], + "domain": "0:21-0:37" } ] }, @@ -838,6 +830,76 @@ } ] }, + { + "name": "scopes/java/collectionItem.unenclosed.multiLine4", + "languageId": "java", + "facet": "collectionItem.unenclosed.multiLine", + "code": "sealed class Foo\n implements Bar,\n Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "1:4-1:18", + "removal": "1:4-1:19" + } + ], + "domain": "1:4-1:18" + }, + { + "targets": [ + { + "content": "1:15-1:18", + "removal": "1:15-2:4" + } + ], + "domain": "1:15-1:18" + }, + { + "targets": [ + { + "content": "2:4-2:7", + "removal": "1:18-2:7" + } + ], + "domain": "2:4-2:7" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.multiLine5", + "languageId": "java", + "facet": "collectionItem.unenclosed.multiLine", + "code": "sealed interface Foo\n permits Bar,\n Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "1:4-1:15", + "removal": "1:4-1:16" + } + ], + "domain": "1:4-1:15" + }, + { + "targets": [ + { + "content": "1:12-1:15", + "removal": "1:12-2:4" + } + ], + "domain": "1:12-1:15" + }, + { + "targets": [ + { + "content": "2:4-2:7", + "removal": "1:15-2:7" + } + ], + "domain": "2:4-2:7" + } + ] + }, { "name": "scopes/java/collectionItem.unenclosed.singleLine", "languageId": "java", @@ -979,6 +1041,94 @@ } ] }, + { + "name": "scopes/java/collectionItem.unenclosed.singleLine4", + "languageId": "java", + "facet": "collectionItem.unenclosed.singleLine", + "code": "sealed class Foo implements Bar, Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "0:0-0:31", + "removal": "0:0-0:33" + } + ], + "domain": "0:0-0:31" + }, + { + "targets": [ + { + "content": "0:28-0:31", + "removal": "0:28-0:33" + } + ], + "domain": "0:28-0:31" + }, + { + "targets": [ + { + "content": "0:33-0:36", + "removal": "0:31-0:36" + } + ], + "domain": "0:33-0:36" + }, + { + "targets": [ + { + "content": "0:33-0:39", + "removal": "0:31-0:39" + } + ], + "domain": "0:33-0:39" + } + ] + }, + { + "name": "scopes/java/collectionItem.unenclosed.singleLine5", + "languageId": "java", + "facet": "collectionItem.unenclosed.singleLine", + "code": "sealed interface Foo permits Bar, Baz {}", + "scopes": [ + { + "targets": [ + { + "content": "0:0-0:32", + "removal": "0:0-0:34" + } + ], + "domain": "0:0-0:32" + }, + { + "targets": [ + { + "content": "0:29-0:32", + "removal": "0:29-0:34" + } + ], + "domain": "0:29-0:32" + }, + { + "targets": [ + { + "content": "0:34-0:37", + "removal": "0:32-0:37" + } + ], + "domain": "0:34-0:37" + }, + { + "targets": [ + { + "content": "0:34-0:40", + "removal": "0:32-0:40" + } + ], + "domain": "0:34-0:40" + } + ] + }, { "name": "scopes/javascript.core/collectionItem.unenclosed.iteration", "languageId": "javascript.core", @@ -1156,14 +1306,6 @@ "facet": "collectionItem.unenclosed.iteration", "code": "local a, b, c = 1, 2, 3", "scopes": [ - { - "targets": [ - { - "content": "0:0-0:23" - } - ], - "domain": "0:0-0:23" - }, { "targets": [ { @@ -2088,14 +2230,6 @@ "facet": "collectionItem.unenclosed.iteration", "code": "def foo():\n global bar, baz", "scopes": [ - { - "targets": [ - { - "content": "1:4-1:19" - } - ], - "domain": "1:0-1:19" - }, { "targets": [ { @@ -2112,14 +2246,6 @@ "facet": "collectionItem.unenclosed.iteration", "code": "for key, value in map.items():\n pass", "scopes": [ - { - "targets": [ - { - "content": "0:0-0:30" - } - ], - "domain": "0:0-0:30" - }, { "targets": [ {