From eee5ae65a6704e1292548e558a53d243e28dd4ff Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Jun 2025 10:26:42 +0200 Subject: [PATCH 1/6] Don't yield empty iteration scopes --- .../c/name.argument.formal.iteration2.scope | 6 --- .../scopes/c/name.iteration.block2.scope | 8 +--- ...rgument.formal.constructor.iteration.scope | 6 --- .../cpp/name.argument.formal.iteration.scope | 6 --- ...ame.argument.formal.method.iteration.scope | 6 --- ...rgument.formal.constructor.iteration.scope | 6 --- .../name.argument.formal.iteration.scope | 6 --- ...ame.argument.formal.method.iteration.scope | 6 --- .../scopes/csharp/name.iteration.block2.scope | 8 +--- .../csharp/name.iteration.document.scope | 10 +---- .../csharp/statement.iteration.document.scope | 10 +---- ...rgument.formal.constructor.iteration.scope | 6 --- .../type.argument.formal.iteration.scope | 10 +---- ...ype.argument.formal.method.iteration.scope | 6 --- ...rgument.formal.constructor.iteration.scope | 6 --- .../value.argument.formal.iteration.scope | 10 +---- ...lue.argument.formal.method.iteration.scope | 6 --- ...collectionItem.unenclosed.iteration2.scope | 18 +++------ .../scopes/java/name.iteration.block.scope | 17 ++------- .../name.iteration.block.scope | 8 +--- .../name.iteration.block2.scope | 8 +--- .../fixtures/scopes/latex/comment.block.scope | 10 ----- data/fixtures/scopes/latex/comment.line.scope | 14 ------- .../scopes/latex/disqualifyDelimiter.scope | 6 --- data/fixtures/scopes/latex/element.scope | 10 ----- data/fixtures/scopes/latex/endTag.scope | 18 --------- data/fixtures/scopes/latex/environment.scope | 10 ----- .../scopes/latex/interior.element.scope | 37 ++++--------------- data/fixtures/scopes/latex/startTag.scope | 18 --------- data/fixtures/scopes/latex/tags.scope | 30 --------------- ...collectionItem.unenclosed.iteration3.scope | 14 ++----- ...collectionItem.unenclosed.iteration4.scope | 8 ++-- .../scss/name.argument.formal.iteration.scope | 6 --- .../value.argument.formal.iteration.scope | 6 --- .../textual/surroundingPair.iteration.scope | 16 +------- .../textual/surroundingPair.iteration2.scope | 16 +------- .../modifiers/EveryScopeStage.ts | 2 + .../modifiers/getContainingScopeTarget.ts | 9 ++++- .../getPreferredScopeTouchingPosition.ts | 2 + .../scopeHandlers/BaseScopeHandler.ts | 1 + .../scopeHandlers/scopeHandler.types.ts | 10 +++++ .../scopeHandlers/shouldYieldScope.ts | 8 ++++ .../scopeProviders/getIterationScopeRanges.ts | 1 + 43 files changed, 74 insertions(+), 351 deletions(-) diff --git a/data/fixtures/scopes/c/name.argument.formal.iteration2.scope b/data/fixtures/scopes/c/name.argument.formal.iteration2.scope index 4d651af334..bc0277a46c 100644 --- a/data/fixtures/scopes/c/name.argument.formal.iteration2.scope +++ b/data/fixtures/scopes/c/name.argument.formal.iteration2.scope @@ -11,9 +11,3 @@ void aaa(int bbb, int ccc) {} [#2 Domain] = 0:9-0:25 >----------------< 0| void aaa(int bbb, int ccc) {} - - -[#3 Range] = -[#3 Domain] = 0:28-0:28 - >< -0| void aaa(int bbb, int ccc) {} diff --git a/data/fixtures/scopes/c/name.iteration.block2.scope b/data/fixtures/scopes/c/name.iteration.block2.scope index 73e54b7c16..dd07df8311 100644 --- a/data/fixtures/scopes/c/name.iteration.block2.scope +++ b/data/fixtures/scopes/c/name.iteration.block2.scope @@ -8,12 +8,6 @@ void foo() { } [#2 Range] = -[#2 Domain] = 0:9-0:9 - >< -0| void foo() { } - - -[#3 Range] = -[#3 Domain] = 0:12-0:13 +[#2 Domain] = 0:12-0:13 >-< 0| void foo() { } diff --git a/data/fixtures/scopes/cpp/name.argument.formal.constructor.iteration.scope b/data/fixtures/scopes/cpp/name.argument.formal.constructor.iteration.scope index 64ed1e42bd..9d6f2a4747 100644 --- a/data/fixtures/scopes/cpp/name.argument.formal.constructor.iteration.scope +++ b/data/fixtures/scopes/cpp/name.argument.formal.constructor.iteration.scope @@ -25,9 +25,3 @@ class MyClass { [#3 Domain] = 1:12-1:32 >--------------------< 1| MyClass(int aaa, int bbb = 2) {} - - -[#4 Range] = -[#4 Domain] = 1:35-1:35 - >< -1| MyClass(int aaa, int bbb = 2) {} diff --git a/data/fixtures/scopes/cpp/name.argument.formal.iteration.scope b/data/fixtures/scopes/cpp/name.argument.formal.iteration.scope index c94fac1f7f..c4e65a1da0 100644 --- a/data/fixtures/scopes/cpp/name.argument.formal.iteration.scope +++ b/data/fixtures/scopes/cpp/name.argument.formal.iteration.scope @@ -11,9 +11,3 @@ void aaa(int bbb = 0, int ccc = 0) {} [#2 Domain] = 0:9-0:33 >------------------------< 0| void aaa(int bbb = 0, int ccc = 0) {} - - -[#3 Range] = -[#3 Domain] = 0:36-0:36 - >< -0| void aaa(int bbb = 0, int ccc = 0) {} diff --git a/data/fixtures/scopes/cpp/name.argument.formal.method.iteration.scope b/data/fixtures/scopes/cpp/name.argument.formal.method.iteration.scope index 9b6a131190..f103bb7282 100644 --- a/data/fixtures/scopes/cpp/name.argument.formal.method.iteration.scope +++ b/data/fixtures/scopes/cpp/name.argument.formal.method.iteration.scope @@ -25,9 +25,3 @@ class MyClass { [#3 Domain] = 1:13-1:33 >--------------------< 1| void foo(int aaa, int bbb = 2) {} - - -[#4 Range] = -[#4 Domain] = 1:36-1:36 - >< -1| void foo(int aaa, int bbb = 2) {} diff --git a/data/fixtures/scopes/csharp/name.argument.formal.constructor.iteration.scope b/data/fixtures/scopes/csharp/name.argument.formal.constructor.iteration.scope index 9c96bc5807..85f5d68136 100644 --- a/data/fixtures/scopes/csharp/name.argument.formal.constructor.iteration.scope +++ b/data/fixtures/scopes/csharp/name.argument.formal.constructor.iteration.scope @@ -25,9 +25,3 @@ class MyClass { [#3 Domain] = 1:12-1:28 >----------------< 1| MyClass(int foo, int bar) {} - - -[#4 Range] = -[#4 Domain] = 1:31-1:31 - >< -1| MyClass(int foo, int bar) {} diff --git a/data/fixtures/scopes/csharp/name.argument.formal.iteration.scope b/data/fixtures/scopes/csharp/name.argument.formal.iteration.scope index cf46c08764..d259181d93 100644 --- a/data/fixtures/scopes/csharp/name.argument.formal.iteration.scope +++ b/data/fixtures/scopes/csharp/name.argument.formal.iteration.scope @@ -11,9 +11,3 @@ void myFunk(String name, int value) {} [#2 Domain] = 0:12-0:34 >----------------------< 0| void myFunk(String name, int value) {} - - -[#3 Range] = -[#3 Domain] = 0:37-0:37 - >< -0| void myFunk(String name, int value) {} diff --git a/data/fixtures/scopes/csharp/name.argument.formal.method.iteration.scope b/data/fixtures/scopes/csharp/name.argument.formal.method.iteration.scope index e621de9367..ba1fb12c7a 100644 --- a/data/fixtures/scopes/csharp/name.argument.formal.method.iteration.scope +++ b/data/fixtures/scopes/csharp/name.argument.formal.method.iteration.scope @@ -25,9 +25,3 @@ class MyClass { [#3 Domain] = 1:14-1:30 >----------------< 1| void funk(int foo, int bar) {} - - -[#4 Range] = -[#4 Domain] = 1:33-1:33 - >< -1| void funk(int foo, int bar) {} diff --git a/data/fixtures/scopes/csharp/name.iteration.block2.scope b/data/fixtures/scopes/csharp/name.iteration.block2.scope index 4ae59561fa..3736f6b85b 100644 --- a/data/fixtures/scopes/csharp/name.iteration.block2.scope +++ b/data/fixtures/scopes/csharp/name.iteration.block2.scope @@ -8,12 +8,6 @@ void MyFunk() { } [#2 Range] = -[#2 Domain] = 0:12-0:12 - >< -0| void MyFunk() { } - - -[#3 Range] = -[#3 Domain] = 0:15-0:16 +[#2 Domain] = 0:15-0:16 >-< 0| void MyFunk() { } diff --git a/data/fixtures/scopes/csharp/name.iteration.document.scope b/data/fixtures/scopes/csharp/name.iteration.document.scope index a1948c1fe5..482a9e9476 100644 --- a/data/fixtures/scopes/csharp/name.iteration.document.scope +++ b/data/fixtures/scopes/csharp/name.iteration.document.scope @@ -3,16 +3,10 @@ class MyClass {} --- -[#1 Range] = -[#1 Domain] = 0:0-2:0 +[Range] = +[Domain] = 0:0-2:0 > 0| 1| class MyClass {} 2| < - - -[#2 Range] = -[#2 Domain] = 1:15-1:15 - >< -1| class MyClass {} diff --git a/data/fixtures/scopes/csharp/statement.iteration.document.scope b/data/fixtures/scopes/csharp/statement.iteration.document.scope index a1948c1fe5..482a9e9476 100644 --- a/data/fixtures/scopes/csharp/statement.iteration.document.scope +++ b/data/fixtures/scopes/csharp/statement.iteration.document.scope @@ -3,16 +3,10 @@ class MyClass {} --- -[#1 Range] = -[#1 Domain] = 0:0-2:0 +[Range] = +[Domain] = 0:0-2:0 > 0| 1| class MyClass {} 2| < - - -[#2 Range] = -[#2 Domain] = 1:15-1:15 - >< -1| class MyClass {} diff --git a/data/fixtures/scopes/csharp/type.argument.formal.constructor.iteration.scope b/data/fixtures/scopes/csharp/type.argument.formal.constructor.iteration.scope index 5f46efab43..63f840500e 100644 --- a/data/fixtures/scopes/csharp/type.argument.formal.constructor.iteration.scope +++ b/data/fixtures/scopes/csharp/type.argument.formal.constructor.iteration.scope @@ -16,9 +16,3 @@ class MyClass { [#2 Domain] = 1:12-1:24 >------------< 1| MyClass(int a, int b) {} - - -[#3 Range] = -[#3 Domain] = 1:27-1:27 - >< -1| MyClass(int a, int b) {} diff --git a/data/fixtures/scopes/csharp/type.argument.formal.iteration.scope b/data/fixtures/scopes/csharp/type.argument.formal.iteration.scope index 772228f4b6..abc43026fe 100644 --- a/data/fixtures/scopes/csharp/type.argument.formal.iteration.scope +++ b/data/fixtures/scopes/csharp/type.argument.formal.iteration.scope @@ -1,13 +1,7 @@ void myFunk(String name, int value) {} --- -[#1 Range] = -[#1 Domain] = 0:12-0:34 +[Range] = +[Domain] = 0:12-0:34 >----------------------< 0| void myFunk(String name, int value) {} - - -[#2 Range] = -[#2 Domain] = 0:37-0:37 - >< -0| void myFunk(String name, int value) {} diff --git a/data/fixtures/scopes/csharp/type.argument.formal.method.iteration.scope b/data/fixtures/scopes/csharp/type.argument.formal.method.iteration.scope index 9fd010aa96..b8d7f6461c 100644 --- a/data/fixtures/scopes/csharp/type.argument.formal.method.iteration.scope +++ b/data/fixtures/scopes/csharp/type.argument.formal.method.iteration.scope @@ -16,9 +16,3 @@ class MyClass { [#2 Domain] = 1:14-1:26 >------------< 1| void funk(int a, int b) {} - - -[#3 Range] = -[#3 Domain] = 1:29-1:29 - >< -1| void funk(int a, int b) {} diff --git a/data/fixtures/scopes/csharp/value.argument.formal.constructor.iteration.scope b/data/fixtures/scopes/csharp/value.argument.formal.constructor.iteration.scope index e7cd07a8e1..089441dbd5 100644 --- a/data/fixtures/scopes/csharp/value.argument.formal.constructor.iteration.scope +++ b/data/fixtures/scopes/csharp/value.argument.formal.constructor.iteration.scope @@ -16,9 +16,3 @@ class MyClass { [#2 Domain] = 1:12-1:32 >--------------------< 1| MyClass(int a = 1, int b = 2) {} - - -[#3 Range] = -[#3 Domain] = 1:35-1:35 - >< -1| MyClass(int a = 1, int b = 2) {} diff --git a/data/fixtures/scopes/csharp/value.argument.formal.iteration.scope b/data/fixtures/scopes/csharp/value.argument.formal.iteration.scope index f5e17fbc98..963f3d58ac 100644 --- a/data/fixtures/scopes/csharp/value.argument.formal.iteration.scope +++ b/data/fixtures/scopes/csharp/value.argument.formal.iteration.scope @@ -1,13 +1,7 @@ void myFunk(String name, int value = 5) {} --- -[#1 Range] = -[#1 Domain] = 0:12-0:38 +[Range] = +[Domain] = 0:12-0:38 >--------------------------< 0| void myFunk(String name, int value = 5) {} - - -[#2 Range] = -[#2 Domain] = 0:41-0:41 - >< -0| void myFunk(String name, int value = 5) {} diff --git a/data/fixtures/scopes/csharp/value.argument.formal.method.iteration.scope b/data/fixtures/scopes/csharp/value.argument.formal.method.iteration.scope index c96c7e651f..ee8e38be0c 100644 --- a/data/fixtures/scopes/csharp/value.argument.formal.method.iteration.scope +++ b/data/fixtures/scopes/csharp/value.argument.formal.method.iteration.scope @@ -16,9 +16,3 @@ class MyClass { [#2 Domain] = 1:14-1:34 >--------------------< 1| void funk(int a = 1, int b = 2) {} - - -[#3 Range] = -[#3 Domain] = 1:37-1:37 - >< -1| void funk(int a = 1, int b = 2) {} diff --git a/data/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope b/data/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope index 2920e986f2..c618ca69cd 100644 --- a/data/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope +++ b/data/fixtures/scopes/java/collectionItem.unenclosed.iteration2.scope @@ -22,17 +22,11 @@ public class MyClass { < -[#2 Range] = -[#2 Domain] = 1:23-1:23 - >< -1| public void myFunk() { - - -[#3 Range] = 2:8-2:24 +[#2 Range] = 2:8-2:24 >----------------< 2| String foo, bar; -[#3 Domain] = 1:26-3:4 +[#2 Domain] = 1:26-3:4 > 1| public void myFunk() { 2| String foo, bar; @@ -40,19 +34,19 @@ public class MyClass { ----< -[#4 Range] = 2:8-2:24 +[#3 Range] = 2:8-2:24 >----------------< 2| String foo, bar; -[#4 Domain] = 2:0-2:24 +[#3 Domain] = 2:0-2:24 >------------------------< 2| String foo, bar; -[#5 Range] = 2:15-2:23 +[#4 Range] = 2:15-2:23 >--------< 2| String foo, bar; -[#5 Domain] = 2:8-2:24 +[#4 Domain] = 2:8-2:24 >----------------< 2| String foo, bar; diff --git a/data/fixtures/scopes/java/name.iteration.block.scope b/data/fixtures/scopes/java/name.iteration.block.scope index a6a24213a1..e5ad7fb760 100644 --- a/data/fixtures/scopes/java/name.iteration.block.scope +++ b/data/fixtures/scopes/java/name.iteration.block.scope @@ -27,17 +27,8 @@ public class MyClass { < -[#3 Range] = 1:22-1:22 - >< -1| public void myFunk() { - -[#3 Domain] = 1:21-1:23 - >--< -1| public void myFunk() { - - -[#4 Range] = -[#4 Domain] = 1:25-3:3 +[#3 Range] = +[#3 Domain] = 1:25-3:3 > 1| public void myFunk() { 2| if (true) { } @@ -45,7 +36,7 @@ public class MyClass { ---< -[#5 Range] = -[#5 Domain] = 2:15-2:16 +[#4 Range] = +[#4 Domain] = 2:15-2:16 >-< 2| if (true) { } diff --git a/data/fixtures/scopes/javascript.core/name.iteration.block.scope b/data/fixtures/scopes/javascript.core/name.iteration.block.scope index e1eb393319..cb73f4ef7c 100644 --- a/data/fixtures/scopes/javascript.core/name.iteration.block.scope +++ b/data/fixtures/scopes/javascript.core/name.iteration.block.scope @@ -22,12 +22,6 @@ class MyClass { [#3 Range] = -[#3 Domain] = 1:11-1:11 - >< -1| myFunk() { } - - -[#4 Range] = -[#4 Domain] = 1:14-1:15 +[#3 Domain] = 1:14-1:15 >-< 1| myFunk() { } diff --git a/data/fixtures/scopes/javascript.core/name.iteration.block2.scope b/data/fixtures/scopes/javascript.core/name.iteration.block2.scope index 3cac5d8be0..da00f553fb 100644 --- a/data/fixtures/scopes/javascript.core/name.iteration.block2.scope +++ b/data/fixtures/scopes/javascript.core/name.iteration.block2.scope @@ -8,12 +8,6 @@ function myFunk() { } [#2 Range] = -[#2 Domain] = 0:16-0:16 - >< -0| function myFunk() { } - - -[#3 Range] = -[#3 Domain] = 0:19-0:20 +[#2 Domain] = 0:19-0:20 >-< 0| function myFunk() { } diff --git a/data/fixtures/scopes/latex/comment.block.scope b/data/fixtures/scopes/latex/comment.block.scope index 05e52078e5..b820bdf1d2 100644 --- a/data/fixtures/scopes/latex/comment.block.scope +++ b/data/fixtures/scopes/latex/comment.block.scope @@ -3,13 +3,3 @@ some comment \fi --- -[Content] = -[Removal] = -[Domain] = 0:0-2:3 - >-------- -0| \iffalse -1| some comment -2| \fi - ---< - -[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/comment.line.scope b/data/fixtures/scopes/latex/comment.line.scope index 8269ee28b6..828952b740 100644 --- a/data/fixtures/scopes/latex/comment.line.scope +++ b/data/fixtures/scopes/latex/comment.line.scope @@ -1,17 +1,3 @@ \LaTeX % some comment --- -[Content] = -[Domain] = 0:7-0:21 - >--------------< -0| \LaTeX % some comment - -[Removal] = 0:6-0:21 - >---------------< -0| \LaTeX % some comment - -[Leading delimiter] = 0:6-0:7 - >-< -0| \LaTeX % some comment - -[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/disqualifyDelimiter.scope b/data/fixtures/scopes/latex/disqualifyDelimiter.scope index 489ca6ced4..cca58cd4e3 100644 --- a/data/fixtures/scopes/latex/disqualifyDelimiter.scope +++ b/data/fixtures/scopes/latex/disqualifyDelimiter.scope @@ -1,10 +1,4 @@ 1 < 2 1 > 2 --- -[#1 Content] = 0:2-0:3 - >-< -0| 1 < 2 -[#2 Content] = 1:2-1:3 - >-< -1| 1 > 2 diff --git a/data/fixtures/scopes/latex/element.scope b/data/fixtures/scopes/latex/element.scope index 8d938b3d62..abcbe87536 100644 --- a/data/fixtures/scopes/latex/element.scope +++ b/data/fixtures/scopes/latex/element.scope @@ -3,13 +3,3 @@ \end{quote} --- -[Content] = -[Removal] = -[Domain] = 0:0-2:11 - >------------- -0| \begin{quote} -1| Hello -2| \end{quote} - -----------< - -[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/endTag.scope b/data/fixtures/scopes/latex/endTag.scope index 2c5db50e7b..abcbe87536 100644 --- a/data/fixtures/scopes/latex/endTag.scope +++ b/data/fixtures/scopes/latex/endTag.scope @@ -3,21 +3,3 @@ \end{quote} --- -[Content] = 2:0-2:11 - >-----------< -2| \end{quote} - -[Removal] = 1:9-2:11 - > -1| Hello -2| \end{quote} - -----------< - -[Domain] = 0:0-2:11 - >------------- -0| \begin{quote} -1| Hello -2| \end{quote} - -----------< - -[Insertion delimiter] = " " diff --git a/data/fixtures/scopes/latex/environment.scope b/data/fixtures/scopes/latex/environment.scope index 8d938b3d62..abcbe87536 100644 --- a/data/fixtures/scopes/latex/environment.scope +++ b/data/fixtures/scopes/latex/environment.scope @@ -3,13 +3,3 @@ \end{quote} --- -[Content] = -[Removal] = -[Domain] = 0:0-2:11 - >------------- -0| \begin{quote} -1| Hello -2| \end{quote} - -----------< - -[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/interior.element.scope b/data/fixtures/scopes/latex/interior.element.scope index a3235c56a0..8d2eefc2ad 100644 --- a/data/fixtures/scopes/latex/interior.element.scope +++ b/data/fixtures/scopes/latex/interior.element.scope @@ -3,46 +3,25 @@ \end{quote} --- -[#1 Content] = 1:4-1:9 - >-----< -1| Hello - -[#1 Removal] = 0:13-2:0 - > -0| \begin{quote} -1| Hello -2| \end{quote} - < - -[#1 Domain] = 0:0-2:11 - >------------- -0| \begin{quote} -1| Hello -2| \end{quote} - -----------< - -[#1 Insertion delimiter] = " " - - -[#2 Content] = -[#2 Removal] = 0:7-0:12 +[#1 Content] = +[#1 Removal] = 0:7-0:12 >-----< 0| \begin{quote} -[#2 Domain] = 0:6-0:13 +[#1 Domain] = 0:6-0:13 >-------< 0| \begin{quote} -[#2 Insertion delimiter] = " " +[#1 Insertion delimiter] = " " -[#3 Content] = -[#3 Removal] = 2:5-2:10 +[#2 Content] = +[#2 Removal] = 2:5-2:10 >-----< 2| \end{quote} -[#3 Domain] = 2:4-2:11 +[#2 Domain] = 2:4-2:11 >-------< 2| \end{quote} -[#3 Insertion delimiter] = " " +[#2 Insertion delimiter] = " " diff --git a/data/fixtures/scopes/latex/startTag.scope b/data/fixtures/scopes/latex/startTag.scope index e429ab9e96..abcbe87536 100644 --- a/data/fixtures/scopes/latex/startTag.scope +++ b/data/fixtures/scopes/latex/startTag.scope @@ -3,21 +3,3 @@ \end{quote} --- -[Content] = 0:0-0:13 - >-------------< -0| \begin{quote} - -[Removal] = 0:0-1:0 - >------------- -0| \begin{quote} -1| Hello - < - -[Domain] = 0:0-2:11 - >------------- -0| \begin{quote} -1| Hello -2| \end{quote} - -----------< - -[Insertion delimiter] = " " diff --git a/data/fixtures/scopes/latex/tags.scope b/data/fixtures/scopes/latex/tags.scope index 43eb2a03b0..abcbe87536 100644 --- a/data/fixtures/scopes/latex/tags.scope +++ b/data/fixtures/scopes/latex/tags.scope @@ -3,33 +3,3 @@ \end{quote} --- -[.1 Content] = 0:0-0:13 - >-------------< -0| \begin{quote} - -[.1 Removal] = 0:0-1:0 - >------------- -0| \begin{quote} -1| Hello - < - -[.1 Insertion delimiter] = " " - -[.2 Content] = 2:0-2:11 - >-----------< -2| \end{quote} - -[.2 Removal] = 1:9-2:11 - > -1| Hello -2| \end{quote} - -----------< - -[.2 Insertion delimiter] = " " - -[Domain] = 0:0-2:11 - >------------- -0| \begin{quote} -1| Hello -2| \end{quote} - -----------< diff --git a/data/fixtures/scopes/python/collectionItem.unenclosed.iteration3.scope b/data/fixtures/scopes/python/collectionItem.unenclosed.iteration3.scope index badf04bc7e..fdee8ecd9e 100644 --- a/data/fixtures/scopes/python/collectionItem.unenclosed.iteration3.scope +++ b/data/fixtures/scopes/python/collectionItem.unenclosed.iteration3.scope @@ -2,25 +2,19 @@ def foo(): global bar, baz --- -[#1 Range] = -[#1 Domain] = 0:8-0:8 - >< -0| def foo(): - - -[#2 Range] = 1:4-1:19 +[#1 Range] = 1:4-1:19 >---------------< 1| global bar, baz -[#2 Domain] = 1:0-1:19 +[#1 Domain] = 1:0-1:19 >-------------------< 1| global bar, baz -[#3 Range] = 1:11-1:19 +[#2 Range] = 1:11-1:19 >--------< 1| global bar, baz -[#3 Domain] = 1:4-1:19 +[#2 Domain] = 1:4-1:19 >---------------< 1| global bar, baz diff --git a/data/fixtures/scopes/python/collectionItem.unenclosed.iteration4.scope b/data/fixtures/scopes/python/collectionItem.unenclosed.iteration4.scope index c5748186a1..c91ff7fbd7 100644 --- a/data/fixtures/scopes/python/collectionItem.unenclosed.iteration4.scope +++ b/data/fixtures/scopes/python/collectionItem.unenclosed.iteration4.scope @@ -3,12 +3,12 @@ for key, value in map.items(): --- [#1 Range] = -[#1 Domain] = 0:4-0:14 - >----------< +[#1 Domain] = 0:0-0:30 + >------------------------------< 0| for key, value in map.items(): [#2 Range] = -[#2 Domain] = 0:28-0:28 - >< +[#2 Domain] = 0:4-0:14 + >----------< 0| for key, value in map.items(): diff --git a/data/fixtures/scopes/scss/name.argument.formal.iteration.scope b/data/fixtures/scopes/scss/name.argument.formal.iteration.scope index 26a2864393..cb850e1273 100644 --- a/data/fixtures/scopes/scss/name.argument.formal.iteration.scope +++ b/data/fixtures/scopes/scss/name.argument.formal.iteration.scope @@ -14,9 +14,3 @@ [#2 Domain] = 0:19-0:40 >---------------------< 0| @mixin replace-text($image, $color: red) {} - - -[#3 Range] = -[#3 Domain] = 0:42-0:42 - >< -0| @mixin replace-text($image, $color: red) {} diff --git a/data/fixtures/scopes/scss/value.argument.formal.iteration.scope b/data/fixtures/scopes/scss/value.argument.formal.iteration.scope index 26a2864393..cb850e1273 100644 --- a/data/fixtures/scopes/scss/value.argument.formal.iteration.scope +++ b/data/fixtures/scopes/scss/value.argument.formal.iteration.scope @@ -14,9 +14,3 @@ [#2 Domain] = 0:19-0:40 >---------------------< 0| @mixin replace-text($image, $color: red) {} - - -[#3 Range] = -[#3 Domain] = 0:42-0:42 - >< -0| @mixin replace-text($image, $color: red) {} diff --git a/data/fixtures/scopes/textual/surroundingPair.iteration.scope b/data/fixtures/scopes/textual/surroundingPair.iteration.scope index 98176cda69..26b2ab7e16 100644 --- a/data/fixtures/scopes/textual/surroundingPair.iteration.scope +++ b/data/fixtures/scopes/textual/surroundingPair.iteration.scope @@ -3,19 +3,7 @@ --- -[#1 Range] = -[#1 Domain] = 0:0-0:0 - >< -0| - - -[#2 Range] = -[#2 Domain] = 1:0-1:3 +[Range] = +[Domain] = 1:0-1:3 >---< 1| ( ) - - -[#3 Range] = -[#3 Domain] = 2:0-2:0 - >< -2| diff --git a/data/fixtures/scopes/textual/surroundingPair.iteration2.scope b/data/fixtures/scopes/textual/surroundingPair.iteration2.scope index 5fc343d946..6fb4190a50 100644 --- a/data/fixtures/scopes/textual/surroundingPair.iteration2.scope +++ b/data/fixtures/scopes/textual/surroundingPair.iteration2.scope @@ -3,19 +3,7 @@ hello --- -[#1 Range] = -[#1 Domain] = 0:0-0:0 - >< -0| - - -[#2 Range] = -[#2 Domain] = 1:0-1:5 +[Range] = +[Domain] = 1:0-1:5 >-----< 1| hello - - -[#3 Range] = -[#3 Domain] = 2:0-2:0 - >< -2| diff --git a/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts index 582ad2920e..df8bd7fe57 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts @@ -111,6 +111,8 @@ export class EveryScopeStage implements ModifierStage { const iterationScopeTarget = getContainingScopeTarget( target, iterationScopeHandler, + 0, // ancestorIndex + true, // skipEmptyScopes ); if (iterationScopeTarget == null) { diff --git a/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts b/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts index ffa852105b..9652450ac4 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts @@ -17,6 +17,7 @@ export function getContainingScopeTarget( target: Target, scopeHandler: ScopeHandler, ancestorIndex: number = 0, + skipEmptyScopes?: boolean, ): Target[] | undefined { const { isReversed, @@ -26,7 +27,13 @@ export function getContainingScopeTarget( if (end.isEqual(start)) { // Input target is empty; return the preferred scope touching target - let scope = getPreferredScopeTouchingPosition(scopeHandler, editor, start); + let scope = getPreferredScopeTouchingPosition( + scopeHandler, + editor, + start, + undefined, + skipEmptyScopes, + ); if (scope == null) { return undefined; diff --git a/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts b/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts index 40871e41ca..9ada592f6c 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts @@ -29,6 +29,7 @@ export function getPreferredScopeTouchingPosition( editor: TextEditor, position: Position, forceDirection?: Direction, + skipEmptyScopes?: boolean, ): TargetScope | undefined { /** * We're looking for the minimal scopes that contain position. We'll get: @@ -43,6 +44,7 @@ export function getPreferredScopeTouchingPosition( containment: "required", allowAdjacentScopes: true, skipAncestorScopes: true, + skipEmptyScopes: skipEmptyScopes ?? false, }), ); diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts index 32daa91003..0ea5d32205 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts @@ -19,6 +19,7 @@ const DEFAULT_REQUIREMENTS: Omit = allowAdjacentScopes: false, skipAncestorScopes: false, includeDescendantScopes: false, + skipEmptyScopes: false, }; /** diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts index 0242b87780..370432682b 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts @@ -178,6 +178,16 @@ export interface ScopeIteratorRequirements { */ skipAncestorScopes: boolean; + /** + * Indicates whether the ScopeHandler should skip yielding a scope if it's + * range is empty. + * - `true` means that empty scopes will not be yielded. + * - `false` means that empty scopes will be yielded + * + * @default false + */ + skipEmptyScopes: boolean; + /** * Indicates whether the ScopeHandler should yield a scope if it is a * descendant of any scope that has been previously yielded. diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts index 3035692255..e20ae5ad6c 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts @@ -57,6 +57,7 @@ function checkRequirements( distalPosition, allowAdjacentScopes, skipAncestorScopes, + skipEmptyScopes, } = requirements; const { domain } = scope; @@ -87,6 +88,13 @@ function checkRequirements( return false; } + if ( + skipEmptyScopes && + !scope.getTargets(false).some((t) => !t.contentRange.isEmpty) + ) { + return false; + } + return partiallyContains( new Range(position, distalPosition), domain, diff --git a/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts b/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts index d4c9de3bb4..bd5a9aae4e 100644 --- a/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts +++ b/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts @@ -41,6 +41,7 @@ export function getIterationScopeRanges( { includeDescendantScopes: true, distalPosition: iterationRange.end, + skipEmptyScopes: true, }, ), (scope) => { From 2eaba5fd25bc3b3fa3f928e4168b0a4487b81613 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Jun 2025 11:14:37 +0200 Subject: [PATCH 2/6] Restore latex tests --- .../fixtures/scopes/latex/comment.block.scope | 10 +++++ data/fixtures/scopes/latex/comment.line.scope | 14 +++++++ .../scopes/latex/disqualifyDelimiter.scope | 6 +++ data/fixtures/scopes/latex/element.scope | 10 +++++ data/fixtures/scopes/latex/endTag.scope | 18 +++++++++ data/fixtures/scopes/latex/environment.scope | 10 +++++ .../scopes/latex/interior.element.scope | 37 +++++++++++++++---- data/fixtures/scopes/latex/startTag.scope | 18 +++++++++ data/fixtures/scopes/latex/tags.scope | 30 +++++++++++++++ 9 files changed, 145 insertions(+), 8 deletions(-) diff --git a/data/fixtures/scopes/latex/comment.block.scope b/data/fixtures/scopes/latex/comment.block.scope index b820bdf1d2..05e52078e5 100644 --- a/data/fixtures/scopes/latex/comment.block.scope +++ b/data/fixtures/scopes/latex/comment.block.scope @@ -3,3 +3,13 @@ some comment \fi --- +[Content] = +[Removal] = +[Domain] = 0:0-2:3 + >-------- +0| \iffalse +1| some comment +2| \fi + ---< + +[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/comment.line.scope b/data/fixtures/scopes/latex/comment.line.scope index 828952b740..8269ee28b6 100644 --- a/data/fixtures/scopes/latex/comment.line.scope +++ b/data/fixtures/scopes/latex/comment.line.scope @@ -1,3 +1,17 @@ \LaTeX % some comment --- +[Content] = +[Domain] = 0:7-0:21 + >--------------< +0| \LaTeX % some comment + +[Removal] = 0:6-0:21 + >---------------< +0| \LaTeX % some comment + +[Leading delimiter] = 0:6-0:7 + >-< +0| \LaTeX % some comment + +[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/disqualifyDelimiter.scope b/data/fixtures/scopes/latex/disqualifyDelimiter.scope index cca58cd4e3..489ca6ced4 100644 --- a/data/fixtures/scopes/latex/disqualifyDelimiter.scope +++ b/data/fixtures/scopes/latex/disqualifyDelimiter.scope @@ -1,4 +1,10 @@ 1 < 2 1 > 2 --- +[#1 Content] = 0:2-0:3 + >-< +0| 1 < 2 +[#2 Content] = 1:2-1:3 + >-< +1| 1 > 2 diff --git a/data/fixtures/scopes/latex/element.scope b/data/fixtures/scopes/latex/element.scope index abcbe87536..8d938b3d62 100644 --- a/data/fixtures/scopes/latex/element.scope +++ b/data/fixtures/scopes/latex/element.scope @@ -3,3 +3,13 @@ \end{quote} --- +[Content] = +[Removal] = +[Domain] = 0:0-2:11 + >------------- +0| \begin{quote} +1| Hello +2| \end{quote} + -----------< + +[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/endTag.scope b/data/fixtures/scopes/latex/endTag.scope index abcbe87536..2c5db50e7b 100644 --- a/data/fixtures/scopes/latex/endTag.scope +++ b/data/fixtures/scopes/latex/endTag.scope @@ -3,3 +3,21 @@ \end{quote} --- +[Content] = 2:0-2:11 + >-----------< +2| \end{quote} + +[Removal] = 1:9-2:11 + > +1| Hello +2| \end{quote} + -----------< + +[Domain] = 0:0-2:11 + >------------- +0| \begin{quote} +1| Hello +2| \end{quote} + -----------< + +[Insertion delimiter] = " " diff --git a/data/fixtures/scopes/latex/environment.scope b/data/fixtures/scopes/latex/environment.scope index abcbe87536..8d938b3d62 100644 --- a/data/fixtures/scopes/latex/environment.scope +++ b/data/fixtures/scopes/latex/environment.scope @@ -3,3 +3,13 @@ \end{quote} --- +[Content] = +[Removal] = +[Domain] = 0:0-2:11 + >------------- +0| \begin{quote} +1| Hello +2| \end{quote} + -----------< + +[Insertion delimiter] = "\n" diff --git a/data/fixtures/scopes/latex/interior.element.scope b/data/fixtures/scopes/latex/interior.element.scope index 8d2eefc2ad..a3235c56a0 100644 --- a/data/fixtures/scopes/latex/interior.element.scope +++ b/data/fixtures/scopes/latex/interior.element.scope @@ -3,25 +3,46 @@ \end{quote} --- -[#1 Content] = -[#1 Removal] = 0:7-0:12 - >-----< +[#1 Content] = 1:4-1:9 + >-----< +1| Hello + +[#1 Removal] = 0:13-2:0 + > 0| \begin{quote} +1| Hello +2| \end{quote} + < -[#1 Domain] = 0:6-0:13 - >-------< +[#1 Domain] = 0:0-2:11 + >------------- 0| \begin{quote} +1| Hello +2| \end{quote} + -----------< [#1 Insertion delimiter] = " " [#2 Content] = -[#2 Removal] = 2:5-2:10 +[#2 Removal] = 0:7-0:12 + >-----< +0| \begin{quote} + +[#2 Domain] = 0:6-0:13 + >-------< +0| \begin{quote} + +[#2 Insertion delimiter] = " " + + +[#3 Content] = +[#3 Removal] = 2:5-2:10 >-----< 2| \end{quote} -[#2 Domain] = 2:4-2:11 +[#3 Domain] = 2:4-2:11 >-------< 2| \end{quote} -[#2 Insertion delimiter] = " " +[#3 Insertion delimiter] = " " diff --git a/data/fixtures/scopes/latex/startTag.scope b/data/fixtures/scopes/latex/startTag.scope index abcbe87536..e429ab9e96 100644 --- a/data/fixtures/scopes/latex/startTag.scope +++ b/data/fixtures/scopes/latex/startTag.scope @@ -3,3 +3,21 @@ \end{quote} --- +[Content] = 0:0-0:13 + >-------------< +0| \begin{quote} + +[Removal] = 0:0-1:0 + >------------- +0| \begin{quote} +1| Hello + < + +[Domain] = 0:0-2:11 + >------------- +0| \begin{quote} +1| Hello +2| \end{quote} + -----------< + +[Insertion delimiter] = " " diff --git a/data/fixtures/scopes/latex/tags.scope b/data/fixtures/scopes/latex/tags.scope index abcbe87536..43eb2a03b0 100644 --- a/data/fixtures/scopes/latex/tags.scope +++ b/data/fixtures/scopes/latex/tags.scope @@ -3,3 +3,33 @@ \end{quote} --- +[.1 Content] = 0:0-0:13 + >-------------< +0| \begin{quote} + +[.1 Removal] = 0:0-1:0 + >------------- +0| \begin{quote} +1| Hello + < + +[.1 Insertion delimiter] = " " + +[.2 Content] = 2:0-2:11 + >-----------< +2| \end{quote} + +[.2 Removal] = 1:9-2:11 + > +1| Hello +2| \end{quote} + -----------< + +[.2 Insertion delimiter] = " " + +[Domain] = 0:0-2:11 + >------------- +0| \begin{quote} +1| Hello +2| \end{quote} + -----------< From e3f077239b4fd474b0736b61f1b0735a63edde02 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Jun 2025 14:30:02 +0200 Subject: [PATCH 3/6] Cleanup --- .../languages/TreeSitterQuery/TreeSitterQuery.ts | 2 +- .../src/processTargets/modifiers/EveryScopeStage.ts | 2 -- .../modifiers/getContainingScopeTarget.ts | 9 +-------- .../modifiers/getPreferredScopeTouchingPosition.ts | 2 -- .../modifiers/scopeHandlers/BaseScopeHandler.ts | 1 - .../SurroundingPairScopeHandler.ts | 13 ++++++++++--- .../TreeSitterIterationScopeHandler.ts | 4 ++++ .../modifiers/scopeHandlers/scopeHandler.types.ts | 10 ---------- .../modifiers/scopeHandlers/shouldYieldScope.ts | 8 -------- .../src/scopeProviders/getIterationScopeRanges.ts | 1 - 10 files changed, 16 insertions(+), 36 deletions(-) diff --git a/packages/cursorless-engine/src/languages/TreeSitterQuery/TreeSitterQuery.ts b/packages/cursorless-engine/src/languages/TreeSitterQuery/TreeSitterQuery.ts index 60d3763a02..aee2165257 100644 --- a/packages/cursorless-engine/src/languages/TreeSitterQuery/TreeSitterQuery.ts +++ b/packages/cursorless-engine/src/languages/TreeSitterQuery/TreeSitterQuery.ts @@ -110,7 +110,7 @@ export class TreeSitterQuery { match: treeSitter.QueryMatch, ): MutableQueryMatch { return { - patternIdx: match.pattern, + patternIdx: match.patternIndex, captures: match.captures.map(({ name, node }) => ({ name, node, diff --git a/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts b/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts index df8bd7fe57..582ad2920e 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/EveryScopeStage.ts @@ -111,8 +111,6 @@ export class EveryScopeStage implements ModifierStage { const iterationScopeTarget = getContainingScopeTarget( target, iterationScopeHandler, - 0, // ancestorIndex - true, // skipEmptyScopes ); if (iterationScopeTarget == null) { diff --git a/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts b/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts index 9652450ac4..ffa852105b 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/getContainingScopeTarget.ts @@ -17,7 +17,6 @@ export function getContainingScopeTarget( target: Target, scopeHandler: ScopeHandler, ancestorIndex: number = 0, - skipEmptyScopes?: boolean, ): Target[] | undefined { const { isReversed, @@ -27,13 +26,7 @@ export function getContainingScopeTarget( if (end.isEqual(start)) { // Input target is empty; return the preferred scope touching target - let scope = getPreferredScopeTouchingPosition( - scopeHandler, - editor, - start, - undefined, - skipEmptyScopes, - ); + let scope = getPreferredScopeTouchingPosition(scopeHandler, editor, start); if (scope == null) { return undefined; diff --git a/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts b/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts index 9ada592f6c..40871e41ca 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/getPreferredScopeTouchingPosition.ts @@ -29,7 +29,6 @@ export function getPreferredScopeTouchingPosition( editor: TextEditor, position: Position, forceDirection?: Direction, - skipEmptyScopes?: boolean, ): TargetScope | undefined { /** * We're looking for the minimal scopes that contain position. We'll get: @@ -44,7 +43,6 @@ export function getPreferredScopeTouchingPosition( containment: "required", allowAdjacentScopes: true, skipAncestorScopes: true, - skipEmptyScopes: skipEmptyScopes ?? false, }), ); diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts index 0ea5d32205..32daa91003 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/BaseScopeHandler.ts @@ -19,7 +19,6 @@ const DEFAULT_REQUIREMENTS: Omit = allowAdjacentScopes: false, skipAncestorScopes: false, includeDescendantScopes: false, - skipEmptyScopes: false, }; /** diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/SurroundingPairScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/SurroundingPairScopeHandler.ts index 615873b833..eeafbdead3 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/SurroundingPairScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/SurroundingPairScopeHandler.ts @@ -4,13 +4,16 @@ import type { SurroundingPairScopeType, TextEditor, } from "@cursorless/common"; -import { showError, type ScopeType } from "@cursorless/common"; +import { showError } from "@cursorless/common"; import type { LanguageDefinitions } from "../../../../languages/LanguageDefinitions"; import { ide } from "../../../../singletons/ide.singleton"; import { BaseScopeHandler } from "../BaseScopeHandler"; import { compareTargetScopes } from "../compareTargetScopes"; import type { TargetScope } from "../scope.types"; -import type { ScopeIteratorRequirements } from "../scopeHandler.types"; +import type { + ConditionalScopeType, + ScopeIteratorRequirements, +} from "../scopeHandler.types"; import { createTargetScope } from "./createTargetScope"; import { getDelimiterOccurrences } from "./getDelimiterOccurrences"; import { getIndividualDelimiters } from "./getIndividualDelimiters"; @@ -18,7 +21,11 @@ import { getSurroundingPairOccurrences } from "./getSurroundingPairOccurrences"; import type { SurroundingPairOccurrence } from "./types"; export class SurroundingPairScopeHandler extends BaseScopeHandler { - public readonly iterationScopeType: ScopeType = { type: "line" }; + public readonly iterationScopeType: ConditionalScopeType = { + type: "conditional", + scopeType: { type: "line" }, + predicate: (scope) => !scope.domain.isEmpty, + }; protected isHierarchical = true; constructor( diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts index 55c299c4cb..bde9e8d8df 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts @@ -47,6 +47,10 @@ export class TreeSitterIterationScopeHandler extends BaseTreeSitterScopeHandler const { range: contentRange, allowMultiple } = capture; + if (contentRange.isEmpty) { + return undefined; + } + const domain = getRelatedRange(match, scopeTypeType, "iteration.domain", false) ?? contentRange; diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts index 370432682b..0242b87780 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/scopeHandler.types.ts @@ -178,16 +178,6 @@ export interface ScopeIteratorRequirements { */ skipAncestorScopes: boolean; - /** - * Indicates whether the ScopeHandler should skip yielding a scope if it's - * range is empty. - * - `true` means that empty scopes will not be yielded. - * - `false` means that empty scopes will be yielded - * - * @default false - */ - skipEmptyScopes: boolean; - /** * Indicates whether the ScopeHandler should yield a scope if it is a * descendant of any scope that has been previously yielded. diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts index e20ae5ad6c..3035692255 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/shouldYieldScope.ts @@ -57,7 +57,6 @@ function checkRequirements( distalPosition, allowAdjacentScopes, skipAncestorScopes, - skipEmptyScopes, } = requirements; const { domain } = scope; @@ -88,13 +87,6 @@ function checkRequirements( return false; } - if ( - skipEmptyScopes && - !scope.getTargets(false).some((t) => !t.contentRange.isEmpty) - ) { - return false; - } - return partiallyContains( new Range(position, distalPosition), domain, diff --git a/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts b/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts index bd5a9aae4e..d4c9de3bb4 100644 --- a/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts +++ b/packages/cursorless-engine/src/scopeProviders/getIterationScopeRanges.ts @@ -41,7 +41,6 @@ export function getIterationScopeRanges( { includeDescendantScopes: true, distalPosition: iterationRange.end, - skipEmptyScopes: true, }, ), (scope) => { From a22c4034695cc7af6f6fb495697ddd9f65974507 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Jun 2025 14:31:58 +0200 Subject: [PATCH 4/6] Added comment --- .../TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts index bde9e8d8df..e3cfca770c 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts @@ -47,6 +47,7 @@ export class TreeSitterIterationScopeHandler extends BaseTreeSitterScopeHandler const { range: contentRange, allowMultiple } = capture; + // Don't yield empty iteration scopes if (contentRange.isEmpty) { return undefined; } From 8f4ed5c2d31fcd238beea809aac6841a73bc290d Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Jun 2025 15:38:38 +0200 Subject: [PATCH 5/6] Update tests --- .../collectionItemTextualIterationScopeHandler.ts | 10 +++++++--- .../src/suite/scopeProvider/runBasicScopeInfoTest.ts | 12 +++--------- .../scopeProvider/runSurroundingPairScopeInfoTest.ts | 5 +---- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts index 6c08500cb5..6e7fcec136 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts @@ -7,15 +7,19 @@ export const collectionItemTextualIterationScopeHandler: ComplexScopeType = { type: "fallback", scopeTypes: [ { - type: "surroundingPairInterior", - delimiter: "collectionBoundary", + type: "conditional", + scopeType: { + type: "surroundingPairInterior", + delimiter: "collectionBoundary", + }, + predicate: (scope) => !scope.domain.isEmpty, }, { type: "conditional", scopeType: { type: "line", }, - predicate: (scope: TargetScope) => { + predicate: (scope) => { const text = scope.editor.document.getText(scope.domain); return testRegex(separatorRegex, text); }, diff --git a/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runBasicScopeInfoTest.ts b/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runBasicScopeInfoTest.ts index f3de48e5f4..1bd4beb106 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runBasicScopeInfoTest.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runBasicScopeInfoTest.ts @@ -54,14 +54,11 @@ function helloWorld() { } `; -function getExpectedScope( - scopeSupport: ScopeSupport, - iterationScopeSupport?: ScopeSupport, -): ScopeSupportInfo { +function getExpectedScope(scopeSupport: ScopeSupport): ScopeSupportInfo { return { humanReadableName: "named function", isLanguageSpecific: true, - iterationScopeSupport: iterationScopeSupport ?? scopeSupport, + iterationScopeSupport: scopeSupport, scopeType: { type: "namedFunction", }, @@ -74,8 +71,5 @@ function getExpectedScope( } const unsupported = getExpectedScope(ScopeSupport.unsupported); -const supported = getExpectedScope( - ScopeSupport.supportedButNotPresentInEditor, - ScopeSupport.supportedAndPresentInEditor, -); +const supported = getExpectedScope(ScopeSupport.supportedButNotPresentInEditor); const present = getExpectedScope(ScopeSupport.supportedAndPresentInEditor); diff --git a/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runSurroundingPairScopeInfoTest.ts b/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runSurroundingPairScopeInfoTest.ts index 344aab4610..b0d054d984 100644 --- a/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runSurroundingPairScopeInfoTest.ts +++ b/packages/cursorless-vscode-e2e/src/suite/scopeProvider/runSurroundingPairScopeInfoTest.ts @@ -39,10 +39,7 @@ function getExpectedScope(scopeSupport: ScopeSupport): ScopeSupportInfo { return { humanReadableName: "Matching pair of parentheses", isLanguageSpecific: false, - iterationScopeSupport: - scopeSupport === ScopeSupport.unsupported - ? ScopeSupport.unsupported - : ScopeSupport.supportedAndPresentInEditor, + iterationScopeSupport: scopeSupport, scopeType: { type: "surroundingPair", delimiter: "parentheses" }, spokenForm: { spokenForms: ["round"], From 37360b8a48359145f18d62d85908f6f531f25a3d Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Jun 2025 15:56:11 +0200 Subject: [PATCH 6/6] Clean up --- .../collectionItemTextualIterationScopeHandler.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts index 6e7fcec136..d570a7c7ae 100644 --- a/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts +++ b/packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/CollectionItemScopeHandler/collectionItemTextualIterationScopeHandler.ts @@ -1,5 +1,4 @@ import { testRegex } from "@cursorless/common"; -import type { TargetScope } from "../scope.types"; import type { ComplexScopeType } from "../scopeHandler.types"; import { separatorRegex } from "./getSeparatorOccurrences";