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

Tree-sitter rolling fixes, 1.125 (or 1.124.1) edition #1172

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
176 changes: 172 additions & 4 deletions packages/language-python/grammars/ts/indents.scm
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
; Excluding dictionary key/value separators…

; IGNORE NON-BLOCK-STARTING COLONS
; ================================

; First, exclude dictionary key/value separators…
(dictionary
(pair ":" @_IGNORE_
(#set! capture.final)))
Expand All @@ -7,22 +11,186 @@
((lambda ":" @_IGNORE_)
(#set! capture.final))

; …and type annotations on function parameters/class members…
; …list subscript syntax…
(slice ":" @_IGNORE_
(#set! capture.final))

; …and type annotations on function parameters/class members.
(":" @_IGNORE_ . (type) (#set! capture.final))

; …all other colons we encounter hint at upcoming indents.
; IGNORE BLOCK-STARTING COLONS BEFORE ONE-LINERS
; ==============================================

; Now that we've done that, all block-starting colons that have their
; consequence block start and end on the same line should be filtered out.
;
; We also test for `lastTextOnRow` to ensure we're not followed by an _empty_
; consequence block, which is surprisingly common. Probably a bug, but it's got
; to be worked around in the meantime.
;
; We check for adjacency between the `:` and the `block` because otherwise we
; might incorrectly match cases like
;
; if 2 > 1: # some comment
;
; since those comments can also be followed by an empty `block` node on the same
; line.
;
(if_statement
":" @_IGNORE_
.
consequence: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(elif_clause
":" @_IGNORE_
.
consequence: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(else_clause
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(match_statement
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(case_clause
":" @_IGNORE_
.
consequence: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(while_statement
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(for_statement
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(try_statement
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(except_clause
":" @_IGNORE_
.
(block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

; Special case for try/except statements, since they don't seem to be valid
; until they're fully intact. If we don't do this, `except` doesn't dedent.
;
; This is like the `elif`/`else` problem below, but it's trickier because an
; identifier could plausibly begin with the string `except` and we don't want
; to make an across-the-board assumption.
(ERROR
"try"
":" @indent
(block
(expression_statement
(identifier) @dedent
(#match? @dedent "except")
)
)
)

(function_definition
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)

(class_definition
":" @_IGNORE_
.
body: (block)
(#is-not? test.lastTextOnRow)
(#is? test.startsOnSameRowAs "nextSibling.endPosition")
(#set! capture.final)
)


; REMAINING COLONS
; ================

; Now that we've done this work, all other colons we encounter hint at upcoming
; indents.
;
; TODO: Based on the stuff we're doing above, it's arguable that the
; exclude-all-counterexamples approach is no longer useful and we should
; instead be opting into indentation. Revisit this!
":" @indent

; MISCELLANEOUS
; =============

; When typing out "else" after an "if" statement, tree-sitter-python won't
; acknowlege it as an `else` statement until it's indented properly, which is
; acknowledge it as an `else` statement until it's indented properly, which is
; quite the dilemma for us. Before that happens, it's an identifier named
; "else". This has a chance of spuriously dedenting if you're typing out a
; variable called `elsewhere` or something, but I'm OK with that.
;
; This also means that we _should not_ mark an actual `else` keyword with
; `@dedent`, because if it's recognized as such, that's a sign that it's
; already indented correctly and we shouldn't touch it.
;
; All this also applies to `elif`.
((identifier) @dedent (#match? @dedent "^(elif|else)$"))

; Likewise, typing `case` at the beginning of a line within a match block — in
; cases where it's interpreted as an identifier — strongly suggests that we
; should dedent one level so it's properly recognized as a new `case` keyword.
(
(identifier) @dedent
(#equals? @dedent "case")
(#is? test.descendantOfType "case_clause")
)


; All instances of brackets/braces should be indented if they span multiple
; lines.
["(" "[" "{"] @indent
[")" "]" "}"] @dedent
14 changes: 14 additions & 0 deletions packages/language-python/spec/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
module.exports = {
env: { jasmine: true },
globals: {
waitsForPromise: true,
runGrammarTests: true,
runFoldsTests: true
},
rules: {
"node/no-unpublished-require": "off",
"node/no-extraneous-require": "off",
"no-unused-vars": "off",
"no-empty": "off"
}
};
Loading
Loading