-
-
Notifications
You must be signed in to change notification settings - Fork 84
Migrate python scope "value" to new scope handler #1877
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
Changes from all commits
9df53f8
5a736b9
af74a74
1305812
3fa6e08
e354ab1
d963952
22bf6ea
fa803b5
092fd72
bec9772
43939f7
53debdf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# Useful commands: | ||
# "visualize value" | ||
# "visualize value iteration" | ||
# "take value" | ||
# "chuck value" | ||
# "chuck every value" | ||
|
||
# the argument value "True" that is part of "b=True" | ||
# is "value" scope | ||
def func(b=True, c=True): | ||
# the returned value "1" that is part of "return 1" | ||
# is "value" scope | ||
if b is True: | ||
return 1 | ||
else: | ||
return 0 | ||
|
||
# the argument value "False" that is part of "b=False" | ||
# is "value" scope | ||
func(b=False) | ||
# but here, there is no "value" scope for "False" since no argument | ||
func(False) | ||
|
||
# both "1.5" and "25" are "value" scope | ||
val = 1.5 | ||
val /= 25 | ||
|
||
val1, val2 = 0, 5 | ||
val1 = 0, val2 = 5 | ||
val1 = val2 | ||
|
||
def my_funk(value: str) -> str: | ||
print(value) | ||
|
||
def my_funk(value: str = "hello", other: bool=False) -> str: | ||
print(value) | ||
|
||
# we can say "change every value" to allow modifying all the values in one go | ||
def foo(): | ||
a = 0 | ||
b = 1 | ||
c = 2 | ||
|
||
# But we don't support outside of a function yet | ||
a = 0 | ||
b = 1 | ||
c = 2 | ||
|
||
# values of a Python "dictionary" are "value" scope | ||
# we can say "chuck every value" to convert the dict into a set | ||
d1 = {"a": 1, "b": 2, "c": 3} | ||
|
||
_ = {value: key for (key, value) in d1.items()} | ||
|
||
# complex ones | ||
_ = {{"a": 1, "b": 2, "c": 3}: 1, d1: 2} | ||
_ = {{1, 2, 3}: 1, {2, 3, 4}: 2} | ||
|
||
# we don't want the access to a a Python "dictionary" | ||
# value to be of "value" scope so we have it here | ||
# to be sure we ignore it | ||
d1["a"] | ||
|
||
value = "hello world" |
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: |- | ||
if (x := 0) < 1: | ||
pass | ||
selections: | ||
- anchor: {line: 0, character: 4} | ||
active: {line: 0, character: 4} | ||
marks: {} | ||
finalState: | ||
documentContents: |- | ||
if (x := ) < 1: | ||
pass | ||
selections: | ||
- anchor: {line: 0, character: 9} | ||
active: {line: 0, character: 9} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
languageId: python | ||
command: | ||
version: 6 | ||
spokenForm: change value | ||
action: | ||
name: clearAndSetSelection | ||
target: | ||
type: primitive | ||
modifiers: | ||
- type: containingScope | ||
scopeType: {type: value} | ||
usePrePhraseSnapshot: true | ||
initialState: | ||
documentContents: |- | ||
match aaa: | ||
case {"bbb": ccc}: | ||
pass | ||
selections: | ||
- anchor: {line: 1, character: 10} | ||
active: {line: 1, character: 10} | ||
marks: {} | ||
finalState: | ||
documentContents: |- | ||
match aaa: | ||
case {"bbb": }: | ||
pass | ||
selections: | ||
- anchor: {line: 1, character: 17} | ||
active: {line: 1, character: 17} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
languageId: python | ||
command: | ||
version: 6 | ||
spokenForm: chuck value | ||
action: | ||
name: remove | ||
target: | ||
type: primitive | ||
modifiers: | ||
- type: containingScope | ||
scopeType: {type: value} | ||
usePrePhraseSnapshot: true | ||
initialState: | ||
documentContents: |- | ||
if (x := 0) < 1: | ||
pass | ||
selections: | ||
- anchor: {line: 0, character: 4} | ||
active: {line: 0, character: 4} | ||
marks: {} | ||
finalState: | ||
documentContents: |- | ||
if (x) < 1: | ||
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,29 @@ | ||
languageId: python | ||
command: | ||
version: 6 | ||
spokenForm: chuck value | ||
action: | ||
name: remove | ||
target: | ||
type: primitive | ||
modifiers: | ||
- type: containingScope | ||
scopeType: {type: value} | ||
usePrePhraseSnapshot: true | ||
initialState: | ||
documentContents: |- | ||
match aaa: | ||
case {"bbb": ccc}: | ||
pass | ||
selections: | ||
- anchor: {line: 1, character: 10} | ||
active: {line: 1, character: 10} | ||
marks: {} | ||
finalState: | ||
documentContents: |- | ||
match aaa: | ||
case {"bbb"}: | ||
pass | ||
selections: | ||
- anchor: {line: 1, character: 10} | ||
active: {line: 1, character: 10} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
[tool.black] | ||
target-version = ["py39"] | ||
force-exclude = ["vendor", "data/playground"] | ||
|
||
[tool.ruff] | ||
select = ["E", "F", "C4", "I001", "UP", "SIM"] | ||
ignore = ["E501", "SIM105", "UP035"] | ||
target-version = "py39" | ||
extend-exclude = ["vendor"] | ||
extend-exclude = ["vendor", "data/playground/**/*.py"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,58 @@ | |
(with_statement) | ||
] @statement | ||
|
||
;;!! a = 25 | ||
;;! ^^ | ||
;;! xxxxx | ||
;;! ------ | ||
(assignment | ||
(_) @_.leading.start.endOf | ||
. | ||
right: (_) @value @_.leading.end.startOf | ||
) @_.domain | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fwiw I do think this pattern and the following one ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me it is the same as dictionary vs dictionary_comprehension as discussed in 36c2f4c There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed it is quite similar. In that case we managed to avoid duplication by rewriting the pattern another way, but I don't see a way out of it here other than |
||
|
||
;;!! a /= 25 | ||
;;! ^^ | ||
;;! xxxxxx | ||
;;! ------- | ||
(augmented_assignment | ||
(_) @_.leading.start.endOf | ||
. | ||
right: (_) @value @_.leading.end.startOf | ||
) @_.domain | ||
|
||
;;!! d = {"a": 1234} | ||
;;! ^^^^ | ||
;;! xxxxxx | ||
;;! --------- | ||
;;!! {value: key for (key, value) in d1.items()} | ||
;;! ^^^ | ||
;;! xxxxx | ||
;;! ---------- | ||
;;!! def func(value: str = ""): | ||
;;! ^^ | ||
;;! xxxxx | ||
;;! --------------- | ||
( | ||
(_ | ||
(_) @_.leading.start.endOf | ||
. | ||
value: (_) @value @_.leading.end.startOf | ||
) @_.domain | ||
(#not-type? @_.domain subscript) | ||
) | ||
|
||
;;!! return 1 | ||
;;! ^ | ||
;;! xx | ||
;;! -------- | ||
;; | ||
;; NOTE: in tree-sitter, both "return" and the "1" are children of `return_statement` | ||
;; but "return" is anonymous whereas "1" is named node, so no need to exclude explicitly | ||
Comment on lines
+76
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment might be overkill. We leverage this kind of assumption all over the place. For example, I'm leveraging this kind of assumption in my leading matchers above, where I rely on the fact that |
||
(return_statement | ||
(_) @value | ||
) @_.domain | ||
|
||
(comment) @comment @textFragment | ||
|
||
(string | ||
|
@@ -77,6 +129,26 @@ | |
(module) @statement.iteration | ||
(module) @namedFunction.iteration @functionName.iteration | ||
(class_definition) @namedFunction.iteration @functionName.iteration | ||
(_ | ||
body: (_) @statement.iteration | ||
|
||
;;!! def foo(): | ||
;;!! a = 0 | ||
;;! <***** | ||
;;!! b = 1 | ||
;;! ***** | ||
;;!! c = 2 | ||
;;! *****> | ||
(block) @statement.iteration @value.iteration | ||
|
||
;;!! {"a": 1, "b": 2, "c": 3} | ||
;;! ********************** | ||
(dictionary | ||
"{" @value.iteration.start.endOf | ||
"}" @value.iteration.end.startOf | ||
) | ||
|
||
;;!! def func(a=0, b=1): | ||
;;! ******** | ||
(parameters | ||
"(" @value.iteration.start.endOf | ||
")" @value.iteration.end.startOf | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like you've lost a bunch of value captures by making the types more specific here. Search in tree-sitter-python for
'value'
. Eg we lost values within match statement patterns, values in named expressions, etc. I'd be inclined to keep a genericvalue: (_)
of some sort as that is often what we want