Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate python scopes #2045

Merged
merged 9 commits into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 1 addition & 36 deletions packages/cursorless-engine/src/languages/python.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
import { Selection } from "@cursorless/common";
import { Selection, SimpleScopeTypeType } from "@cursorless/common";
import type { SyntaxNode } from "web-tree-sitter";
import { SimpleScopeTypeType } from "@cursorless/common";
import { NodeFinder, NodeMatcherAlternative } from "../typings/Types";
import { argumentNodeFinder, patternFinder } from "../util/nodeFinders";
import {
argumentMatcher,
cascadingMatcher,
conditionMatcher,
createPatternMatchers,
leadingMatcher,
matcher,
patternMatcher,
trailingMatcher,
} from "../util/nodeMatchers";
import {
argumentSelectionExtractor,
childRangeSelector,
} from "../util/nodeSelectors";
import { branchMatcher } from "./branchMatcher";
import { ternaryBranchMatcher } from "./ternaryBranchMatcher";

export const getTypeNode = (node: SyntaxNode) =>
node.children.find((child) => child.type === "type") ?? null;
Expand Down Expand Up @@ -55,38 +48,10 @@ const nodeMatchers: Partial<
argumentSelectionExtractor(),
),
),
collectionKey: trailingMatcher(["pair[key]"], [":"]),
ifStatement: "if_statement",
anonymousFunction: "lambda?.lambda",
pokey marked this conversation as resolved.
Show resolved Hide resolved
functionCall: "call",
functionCallee: "call[function]",
condition: cascadingMatcher(
conditionMatcher("*[condition]"),
pokey marked this conversation as resolved.
Show resolved Hide resolved

// Comprehensions and match statements
leadingMatcher(["*.if_clause![0]"], ["if"]),

// Ternaries
patternMatcher("conditional_expression[1]"),
),
argumentOrParameter: cascadingMatcher(
argumentMatcher("parameters", "argument_list"),
matcher(patternFinder("call.generator_expression!"), childRangeSelector()),
),
branch: cascadingMatcher(
patternMatcher("case_clause"),
branchMatcher("if_statement", ["else_clause", "elif_clause"]),
branchMatcher("while_statement", ["else_clause"]),
branchMatcher("for_statement", ["else_clause"]),
branchMatcher("try_statement", [
"except_clause",
"finally_clause",
"else_clause",
"except_group_clause",
]),
ternaryBranchMatcher("conditional_expression", [0, 2]),
),
["private.switchStatementSubject"]: "match_statement[subject]",
};

export default createPatternMatchers(nodeMatchers);
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ initialState:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
marks: {}
thrownError: {name: NoContainingScopeError}
finalState:
documentContents: |-
for in bbb:
pass
selections:
- anchor: {line: 0, character: 4}
active: {line: 0, character: 4}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
languageId: python
command:
version: 6
spokenForm: change name
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: name}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
for name in value:
pass
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
marks: {}
finalState:
documentContents: |-
for in value:
pass
selections:
- anchor: {line: 0, character: 4}
active: {line: 0, character: 4}
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ initialState:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
marks: {}
thrownError: {name: NoContainingScopeError}
finalState:
documentContents: |-
for aaa in :
pass
selections:
- anchor: {line: 0, character: 11}
active: {line: 0, character: 11}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
languageId: python
command:
version: 6
spokenForm: change value
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: value}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
for name in value:
pass
selections:
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
marks: {}
finalState:
documentContents: |-
for name in :
pass
selections:
- anchor: {line: 0, character: 12}
active: {line: 0, character: 12}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ initialState:
finalState:
documentContents: |-
match 0:
case a if :
case :
pass
selections:
- anchor: {line: 1, character: 14}
active: {line: 1, character: 14}
- anchor: {line: 1, character: 9}
active: {line: 1, character: 9}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ initialState:
finalState:
documentContents: |-
match 0:
case a :
case:
pass
selections:
- anchor: {line: 2, character: 8}
Expand Down
166 changes: 166 additions & 0 deletions queries/python.scm
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,169 @@
"(" @value.iteration.start.endOf @name.iteration.start.endOf @type.iteration.start.endOf
")" @value.iteration.end.startOf @name.iteration.end.startOf @type.iteration.end.startOf
)

;;!! if true: pass
;;! ^^^^^^^^^^^^^
(if_statement) @ifStatement

;;!! foo()
;;! ^^^^^
(call) @functionCall

;;!! foo()
;;! ^^^^^
(call
function: (_) @functionCallee
) @_.domain

;;!! lambda _: pass
;;! ^^^^^^^^^^^^^^
(lambda) @anonymousFunction

;;!! match value:
;;! ^^^^^
(match_statement
subject: (_) @private.switchStatementSubject
) @_.domain

;;!! { "value": 0 }
;;! ^^^^^^^
;;! xxxxxxxxx
(pair
key: (_) @collectionKey @collectionKey.trailing.start.endOf
value: (_) @collectionKey.trailing.end.startOf
) @_.domain

;;!! if True:
;;! ^^^^
;;!! elif True:
;;! ^^^^
;;!! while True:
;;! ^^^^
(_
condition: (_) @condition
) @_.domain

;;!! match value:
;;! ^^^^^
(case_clause
pattern: (_) @condition.start
guard: (_)? @condition.end
) @_.domain

;;!! case 0: pass
;;! ^^^^^^^^^^^^
(case_clause) @branch

(match_statement) @branch.iteration @condition.iteration

;;!! 1 if True else 0
;;! ^^^^
;;! ----------------
(
(conditional_expression
"if"
.
(_) @condition
) @_.domain
)

;;!! 1 if True else 0
;;! ^
(
(conditional_expression
(_) @branch
.
"if"
)
)

;;!! 1 if True else 0
;;! ^
(
(conditional_expression
"else"
.
(_) @branch
)
)

(conditional_expression) @branch.iteration

;;!! [aaa for aaa in bbb if ccc]
;;!! (aaa for aaa in bbb if ccc)
;;!! {aaa for aaa in bbb if ccc}
;;! ^^^
;;! xxxxxx
;;! ---------------------------
;;!! {aaa: aaa for aaa in bbb if ccc}
;;! ^^^
;;! xxxxxx
;;! --------------------------------
(_
(if_clause
"if"
(_) @condition
) @_.removal
(#not-parent-type? @_.removal case_clause)
) @_.domain

;;!! for name in value:
;;! ^^^^ ^^^^^
;;! ------------------
(for_statement
left: (_) @name
right: (_) @value
) @_.domain

;;!! if True: pass
;;! ^^^^^^^^^^^^^
(if_statement
"if" @branch.start
consequence: (_) @branch.end
)

;;!! elif True: pass
;;! ^^^^^^^^^^^^^^^
(elif_clause) @branch

;;!! else: pass
;;! ^^^^^^^^^^
(else_clause) @branch

(if_statement) @branch.iteration

;;!! try: pass
;;! ^^^^^^^^^
(try_statement
"try" @branch.start
body: (_) @branch.end
)

;;!! except: pass
;;! ^^^^^^^^^^^^
(except_clause) @branch

;;!! finally: pass
;;! ^^^^^^^^^^^^^
(finally_clause) @branch

(try_statement) @branch.iteration

;;!! while True: pass
;;! ^^^^^^^^^^^^^^^^
(while_statement
"while" @branch.start
body: (_) @branch.end
)

(while_statement) @branch.iteration

;;!! for aaa in bbb: pass
;;! ^^^^^^^^^^^^^^^^^^^^
(for_statement
"for" @branch.start
body: (_) @branch.end
)

(for_statement) @branch.iteration