diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if_statement.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if_statement.py new file mode 100644 index 0000000000..65b21e30e9 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/if_statement.py @@ -0,0 +1,37 @@ +if x == y: # trailing if condition + pass # trailing `pass` comment + # Root `if` trailing comment + +# Leading elif comment +elif x < y: # trailing elif condition + pass + # `elif` trailing comment + +# Leading else comment +else: # trailing else condition + pass + # `else` trailing comment + + +if x == y: + if y == z: + ... + + if a == b: + ... + else: # trailing comment + ... + + # trailing else comment + +# leading else if comment +elif aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [ + 11111111111111111111111111, + 2222222222222222222222, + 3333333333 + ]: + ... + + +else: + ... diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index 10a9db7baa..730544dac1 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -215,6 +215,26 @@ fn handle_in_between_bodies_own_line_comment<'a>( return CommentPlacement::Default(comment); } + // If there's any non-trivia token between the preceding node and the comment, than it means that + // we're past the case of the alternate branch, defer to the default rules + // ```python + // if a: + // pass + // else: + // # leading comment + // def inline_after_else(): ... + // ``` + if SimpleTokenizer::new( + locator.contents(), + TextRange::new(preceding.end(), comment.slice().start()), + ) + .skip_trivia() + .next() + .is_some() + { + return CommentPlacement::Default(comment); + } + // it now depends on the indentation level of the comment if it is a leading comment for e.g. // the following `elif` or indeed a trailing comment of the previous body's last statement. let comment_indentation = diff --git a/crates/ruff_python_formatter/src/lib.rs b/crates/ruff_python_formatter/src/lib.rs index 193e5f546f..51d03c375b 100644 --- a/crates/ruff_python_formatter/src/lib.rs +++ b/crates/ruff_python_formatter/src/lib.rs @@ -248,7 +248,8 @@ if True: # trailing "#; let expected = r#"# preceding -NOT_YET_IMPLEMENTED_StmtIf +if True: + NOT_IMPLEMENTED_call() # trailing "#; let actual = format_module(input)?.as_code().to_string(); @@ -436,6 +437,11 @@ def with_leading_comment(): ... // .document() // .display(formatted.context().source_code())); + // dbg!(formatted + // .context() + // .comments() + // .debug(formatted.context().source_code())); + let printed = formatted.print().unwrap(); assert_eq!( diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap index 180c446c5f..81c681bc72 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__attribute_access_on_number_literals_py.snap @@ -35,7 +35,7 @@ y = 100(no) ```diff --- Black +++ Ruff -@@ -1,22 +1,21 @@ +@@ -1,22 +1,22 @@ -x = (123456789).bit_count() -x = (123456).__abs__() -x = (0.1).is_integer() @@ -70,8 +70,8 @@ y = 100(no) +x = NOT_YET_IMPLEMENTED_ExprUnaryOp -if (10).real: -- ... -+NOT_YET_IMPLEMENTED_StmtIf ++if 10 .NOT_IMPLEMENTED_attr: + ... -y = 100[no] -y = 100(no) @@ -99,7 +99,8 @@ x = 0O777 .NOT_IMPLEMENTED_attr x = NOT_IMPLEMENTED_call() x = NOT_YET_IMPLEMENTED_ExprUnaryOp -NOT_YET_IMPLEMENTED_StmtIf +if 10 .NOT_IMPLEMENTED_attr: + ... y = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key] y = NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap index 6105a55016..16be7db816 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap @@ -84,7 +84,7 @@ if True: ```diff --- Black +++ Ruff -@@ -1,99 +1,46 @@ +@@ -1,99 +1,52 @@ -import core, time, a +NOT_YET_IMPLEMENTED_StmtImport @@ -186,14 +186,16 @@ if True: +division_result_tuple = (1, 2) +NOT_IMPLEMENTED_call() --if True: + if True: - IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( - Config.IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING - | {pylons.controllers.WSGIController} - ) -+NOT_YET_IMPLEMENTED_StmtIf ++ IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = Config.NOT_IMPLEMENTED_attr | { ++ pylons.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr, ++ } --if True: + if True: - ec2client.get_waiter("instance_stopped").wait( - InstanceIds=[instance.id], - WaiterConfig={ @@ -212,7 +214,9 @@ if True: - "Delay": 5, - }, - ) -+NOT_YET_IMPLEMENTED_StmtIf ++ NOT_IMPLEMENTED_call() ++ NOT_IMPLEMENTED_call() ++ NOT_IMPLEMENTED_call() ``` ## Ruff Output @@ -261,9 +265,15 @@ NOT_YET_IMPLEMENTED_StmtFor division_result_tuple = (1, 2) NOT_IMPLEMENTED_call() -NOT_YET_IMPLEMENTED_StmtIf +if True: + IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = Config.NOT_IMPLEMENTED_attr | { + pylons.NOT_IMPLEMENTED_attr.NOT_IMPLEMENTED_attr, + } -NOT_YET_IMPLEMENTED_StmtIf +if True: + NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call() ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap index 44a3cffad7..90b9263196 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap @@ -227,7 +227,7 @@ instruction()#comment with bad spacing ] not_shareables = [ -@@ -37,51 +33,24 @@ +@@ -37,50 +33,51 @@ # builtin types and objects type, object, @@ -249,29 +249,42 @@ instruction()#comment with bad spacing -if "PYTHON" in os.environ: - add_compiler(compiler_from_env()) --else: -- # for compiler in compilers.values(): -- # add_compiler(compiler) ++if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_IMPLEMENTED_call() + else: + # for compiler in compilers.values(): + # add_compiler(compiler) - add_compiler(compilers[(7.0, 32)]) -- # add_compiler(compilers[(7.1, 64)]) -+NOT_YET_IMPLEMENTED_StmtIf ++ NOT_IMPLEMENTED_call() + # add_compiler(compilers[(7.1, 64)]) # Comment before function. def inline_comments_in_brackets_ruin_everything(): -- if typedargslist: + if typedargslist: - parameters.children = [children[0], body, children[-1]] # (1 # )1 - parameters.children = [ - children[0], -- body, ++ parameters.NOT_IMPLEMENTED_attr = [ ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # (1 ++ body, ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # )1 ++ ] ++ parameters.NOT_IMPLEMENTED_attr = [ ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], + body, - children[-1], # type: ignore -- ] -- else: ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # type: ignore + ] + else: - parameters.children = [ - parameters.children[0], # (2 what if this was actually long -- body, ++ parameters.NOT_IMPLEMENTED_attr = [ ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # (2 what if this was actually long + body, - parameters.children[-1], # )2 -- ] ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # )2 + ] - parameters.children = [parameters.what_if_this_was_actually_long.children[0], body, parameters.children[-1]] # type: ignore - if ( - self._proc is not None @@ -281,13 +294,16 @@ instruction()#comment with bad spacing - # transport hasn't been notified yet? - and self._proc.poll() is None - ): -- pass -+ NOT_YET_IMPLEMENTED_StmtIf -+ NOT_YET_IMPLEMENTED_StmtIf ++ parameters.NOT_IMPLEMENTED_attr = [ ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], ++ body, ++ NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], ++ ] # type: ignore ++ if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + pass # no newline before or after short = [ - # one -@@ -91,75 +60,26 @@ +@@ -91,75 +88,29 @@ ] # no newline after @@ -339,11 +355,11 @@ instruction()#comment with bad spacing + lcomp2 = [i for i in []] + lcomp3 = [i for i in []] while True: -- if False: + if False: - continue -- -- # and round and round we go -+ NOT_YET_IMPLEMENTED_StmtIf ++ NOT_YET_IMPLEMENTED_StmtContinue + + # and round and round we go # and round and round we go # let's return @@ -372,7 +388,7 @@ instruction()#comment with bad spacing ####################### -@@ -167,7 +87,7 @@ +@@ -167,7 +118,7 @@ ####################### @@ -432,13 +448,41 @@ not_shareables = [ NOT_IMPLEMENTED_call(), ] -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_IMPLEMENTED_call() +else: + # for compiler in compilers.values(): + # add_compiler(compiler) + NOT_IMPLEMENTED_call() + # add_compiler(compilers[(7.1, 64)]) # Comment before function. def inline_comments_in_brackets_ruin_everything(): - NOT_YET_IMPLEMENTED_StmtIf - NOT_YET_IMPLEMENTED_StmtIf + if typedargslist: + parameters.NOT_IMPLEMENTED_attr = [ + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # (1 + body, + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # )1 + ] + parameters.NOT_IMPLEMENTED_attr = [ + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], + body, + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # type: ignore + ] + else: + parameters.NOT_IMPLEMENTED_attr = [ + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # (2 what if this was actually long + body, + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], # )2 + ] + parameters.NOT_IMPLEMENTED_attr = [ + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], + body, + NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key], + ] # type: ignore + if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + pass # no newline before or after short = [ # one @@ -457,7 +501,10 @@ def inline_comments_in_brackets_ruin_everything(): lcomp2 = [i for i in []] lcomp3 = [i for i in []] while True: - NOT_YET_IMPLEMENTED_StmtIf + if False: + NOT_YET_IMPLEMENTED_StmtContinue + + # and round and round we go # and round and round we go # let's return diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap index 32cc7618fa..1d64b8c286 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap @@ -61,7 +61,7 @@ def func(): ```diff --- Black +++ Ruff -@@ -3,46 +3,13 @@ +@@ -3,46 +3,15 @@ # %% def func(): @@ -80,7 +80,8 @@ def func(): + lcomp3 = [i for i in []] # Capture each of the exceptions in the MultiError along with each of their causes and contexts - if isinstance(exc_value, MultiError): -- embedded = [] ++ if NOT_IMPLEMENTED_call(): + embedded = [] - for exc in exc_value.exceptions: - if exc not in _seen: - embedded.append( @@ -96,7 +97,7 @@ def func(): - ) - # This should be left alone (after) - ) -+ NOT_YET_IMPLEMENTED_StmtIf ++ NOT_YET_IMPLEMENTED_StmtFor # everything is fine if the expression isn't nested - traceback.TracebackException.from_exception( @@ -125,7 +126,9 @@ def func(): x = "NOT_YET_IMPLEMENTED_STRING" lcomp3 = [i for i in []] # Capture each of the exceptions in the MultiError along with each of their causes and contexts - NOT_YET_IMPLEMENTED_StmtIf + if NOT_IMPLEMENTED_call(): + embedded = [] + NOT_YET_IMPLEMENTED_StmtFor # everything is fine if the expression isn't nested NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap index addd145645..4cdfd0bf99 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap @@ -86,46 +86,47 @@ if __name__ == "__main__": ```diff --- Black +++ Ruff -@@ -1,33 +1,18 @@ +@@ -1,33 +1,20 @@ while True: - if something.changed: - do.stuff() # trailing comment -- # Comment belongs to the `if` block. -+ NOT_YET_IMPLEMENTED_StmtIf ++ if something.NOT_IMPLEMENTED_attr: ++ NOT_IMPLEMENTED_call() # trailing comment + # Comment belongs to the `if` block. # This one belongs to the `while` block. # Should this one, too? I guess so. # This one is properly standalone now. - +- -for i in range(100): - # first we do this - if i % 33 == 0: - break -+NOT_YET_IMPLEMENTED_StmtFor - # then we do this - print(i) - # and finally we loop around -+NOT_YET_IMPLEMENTED_StmtWith ++NOT_YET_IMPLEMENTED_StmtFor -with open(some_temp_file) as f: - data = f.read() -+NOT_YET_IMPLEMENTED_StmtTry - +- -try: - with open(some_other_file) as w: - w.write(data) -- ++NOT_YET_IMPLEMENTED_StmtWith + -except OSError: - print("problems") -- ++NOT_YET_IMPLEMENTED_StmtTry + -import sys +NOT_YET_IMPLEMENTED_StmtImport # leading function comment -@@ -42,7 +27,7 @@ +@@ -42,7 +29,7 @@ # leading 1 @deco1 # leading 2 @@ -134,7 +135,7 @@ if __name__ == "__main__": # leading 3 @deco3 def decorated1(): -@@ -52,7 +37,7 @@ +@@ -52,7 +39,7 @@ # leading 1 @deco1 # leading 2 @@ -143,20 +144,23 @@ if __name__ == "__main__": # leading function comment def decorated1(): ... -@@ -69,5 +54,4 @@ +@@ -69,5 +56,5 @@ ... -if __name__ == "__main__": - main() -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_IMPLEMENTED_call() ``` ## Ruff Output ```py while True: - NOT_YET_IMPLEMENTED_StmtIf + if something.NOT_IMPLEMENTED_attr: + NOT_IMPLEMENTED_call() # trailing comment + # Comment belongs to the `if` block. # This one belongs to the `while` block. # Should this one, too? I guess so. @@ -211,7 +215,8 @@ def g(): ... -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_IMPLEMENTED_call() ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap index 49e1cc324f..cddd66b042 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap @@ -210,42 +210,25 @@ def bar(): # leading 3 @deco3 -@@ -98,41 +94,13 @@ - - - def main(): -- if a: -- # Leading comment before inline function -- def inline(): -- pass -- -- # Another leading comment -- def another_inline(): -- pass -+ NOT_YET_IMPLEMENTED_StmtIf - -- else: -- # More leading comments -- def inline_after_else(): -- pass - -+NOT_YET_IMPLEMENTED_StmtIf - --if a: -- # Leading comment before "top-level inline" function -- def top_level_quote_inline(): -- pass - -- # Another leading comment -- def another_top_level_quote_inline_inline(): -- pass -- --else: -- # More leading comments -- def top_level_quote_inline_after_else(): -- pass +@@ -106,7 +102,6 @@ + # Another leading comment + def another_inline(): + pass - + else: + # More leading comments + def inline_after_else(): +@@ -121,18 +116,13 @@ + # Another leading comment + def another_top_level_quote_inline_inline(): + pass - + else: + # More leading comments + def top_level_quote_inline_after_else(): + pass + + -class MyClass: - # First method has no empty lines between bare class def. - # More comments. @@ -356,10 +339,32 @@ def decorated_with_split_leading_comments(): def main(): - NOT_YET_IMPLEMENTED_StmtIf + if a: + # Leading comment before inline function + def inline(): + pass + + # Another leading comment + def another_inline(): + pass + else: + # More leading comments + def inline_after_else(): + pass -NOT_YET_IMPLEMENTED_StmtIf +if a: + # Leading comment before "top-level inline" function + def top_level_quote_inline(): + pass + + # Another leading comment + def another_top_level_quote_inline_inline(): + pass +else: + # More leading comments + def top_level_quote_inline_after_else(): + pass NOT_YET_IMPLEMENTED_StmtClassDef diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap index 594d47fcf3..ec61d99846 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap @@ -117,30 +117,30 @@ async def wat(): - -Possibly also many, many lines. -""" -+"NOT_YET_IMPLEMENTED_STRING" - +- -import os.path -import sys -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport - +- -import a -from b.c import X # some noqa comment -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment ++"NOT_YET_IMPLEMENTED_STRING" -try: - import fast -except ImportError: - import slow as fast -- -- ++NOT_YET_IMPLEMENTED_StmtImport ++NOT_YET_IMPLEMENTED_StmtImport + ++NOT_YET_IMPLEMENTED_StmtImport ++NOT_YET_IMPLEMENTED_StmtImportFrom # some noqa comment + -# Some comment before a function. +NOT_YET_IMPLEMENTED_StmtTry y = 1 ( # some strings -@@ -30,67 +21,39 @@ +@@ -30,67 +21,46 @@ def function(default=None): @@ -154,11 +154,13 @@ async def wat(): + NOT_YET_IMPLEMENTED_StmtImport - if inner_imports.are_evil(): -- # Explains why we have this if. -- # In great detail indeed. ++ if NOT_IMPLEMENTED_call(): + # Explains why we have this if. + # In great detail indeed. - x = X() - return x.method1() # type: ignore -+ NOT_YET_IMPLEMENTED_StmtIf ++ x = NOT_IMPLEMENTED_call() ++ return NOT_IMPLEMENTED_call() # type: ignore # This return is also commented for some reason. return default @@ -171,7 +173,7 @@ async def wat(): # Another comment! # This time two lines. -- + -class Foo: - """Docstring for class Foo. Example from Sphinx docs.""" @@ -179,7 +181,7 @@ async def wat(): - #: Doc comment for class attribute Foo.bar. - #: It can have multiple lines. - bar = 1 - +- - flox = 1.5 #: Doc comment for Foo.flox. One line only. - - baz = 2 @@ -206,11 +208,12 @@ async def wat(): - result = await x.method1() + NOT_YET_IMPLEMENTED_StmtAsyncWith # Some more comments # Comment after ending a block. -- if result: + if result: - print("A OK", file=sys.stdout) -- # Comment between things. ++ NOT_IMPLEMENTED_call() + # Comment between things. - print() -+ NOT_YET_IMPLEMENTED_StmtIf ++ NOT_IMPLEMENTED_call() # Some closing comments. @@ -250,7 +253,11 @@ def function(default=None): # FIXME: Some comment about why this function is crap but still in production. NOT_YET_IMPLEMENTED_StmtImport - NOT_YET_IMPLEMENTED_StmtIf + if NOT_IMPLEMENTED_call(): + # Explains why we have this if. + # In great detail indeed. + x = NOT_IMPLEMENTED_call() + return NOT_IMPLEMENTED_call() # type: ignore # This return is also commented for some reason. return default @@ -276,7 +283,10 @@ async def wat(): # contains a trailing backslash. NOT_YET_IMPLEMENTED_StmtAsyncWith # Some more comments # Comment after ending a block. - NOT_YET_IMPLEMENTED_StmtIf + if result: + NOT_IMPLEMENTED_call() + # Comment between things. + NOT_IMPLEMENTED_call() # Some closing comments. diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap index f2f0d7ebcd..5446adf8cc 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap @@ -105,7 +105,7 @@ def g(): ```diff --- Black +++ Ruff -@@ -1,89 +1,45 @@ +@@ -1,89 +1,70 @@ -"""Docstring.""" +"NOT_YET_IMPLEMENTED_STRING" @@ -115,31 +115,36 @@ def g(): - NO = "" - SPACE = " " - DOUBLESPACE = " " -- -- t = leaf.type -- p = leaf.parent # trailing comment -- v = leaf.value -- -- if t in ALWAYS_NO_SPACE: -- pass -- if t == token.COMMENT: # another trailing comment -- return DOUBLESPACE + NO = "NOT_YET_IMPLEMENTED_STRING" + SPACE = "NOT_YET_IMPLEMENTED_STRING" + DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" -- assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}" +- t = leaf.type +- p = leaf.parent # trailing comment +- v = leaf.value + t = leaf.NOT_IMPLEMENTED_attr + p = leaf.NOT_IMPLEMENTED_attr # trailing comment + v = leaf.NOT_IMPLEMENTED_attr +- if t in ALWAYS_NO_SPACE: ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + pass +- if t == token.COMMENT: # another trailing comment ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: # another trailing comment + return DOUBLESPACE + +- assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}" ++ NOT_YET_IMPLEMENTED_StmtAssert + - prev = leaf.prev_sibling - if not prev: - prevp = preceding_leaf(p) - if not prevp or prevp.type in OPENING_BRACKETS: -- return NO -+ NOT_YET_IMPLEMENTED_StmtIf -+ NOT_YET_IMPLEMENTED_StmtIf # another trailing comment ++ prev = leaf.NOT_IMPLEMENTED_attr ++ if NOT_YET_IMPLEMENTED_ExprUnaryOp: ++ prevp = NOT_IMPLEMENTED_call() ++ if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO - if prevp.type == token.EQUAL: - if prevp.parent and prevp.parent.type in { @@ -149,8 +154,9 @@ def g(): - syms.arglist, - syms.argument, - }: -- return NO -+ NOT_YET_IMPLEMENTED_StmtAssert ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO - elif prevp.type == token.DOUBLESTAR: - if prevp.parent and prevp.parent.type in { @@ -160,9 +166,9 @@ def g(): - syms.arglist, - syms.dictsetmaker, - }: -- return NO -+ prev = leaf.NOT_IMPLEMENTED_attr -+ NOT_YET_IMPLEMENTED_StmtIf ++ elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO ############################################################################### @@ -188,25 +194,29 @@ def g(): # Comment because comments - if t in ALWAYS_NO_SPACE: -- pass ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + pass - if t == token.COMMENT: -- return DOUBLESPACE -+ NOT_YET_IMPLEMENTED_StmtIf -+ NOT_YET_IMPLEMENTED_StmtIf ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + return DOUBLESPACE # Another comment because more comments - assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}" -- ++ NOT_YET_IMPLEMENTED_StmtAssert + - prev = leaf.prev_sibling - if not prev: - prevp = preceding_leaf(p) -+ NOT_YET_IMPLEMENTED_StmtAssert ++ prev = leaf.NOT_IMPLEMENTED_attr ++ if NOT_YET_IMPLEMENTED_ExprUnaryOp: ++ prevp = NOT_IMPLEMENTED_call() - if not prevp or prevp.type in OPENING_BRACKETS: -- # Start of the line or a bracketed expression. -- # More than one line for the comment. -- return NO -- ++ if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + # Start of the line or a bracketed expression. + # More than one line for the comment. + return NO + - if prevp.type == token.EQUAL: - if prevp.parent and prevp.parent.type in { - syms.typedargslist, @@ -215,9 +225,9 @@ def g(): - syms.arglist, - syms.argument, - }: -- return NO -+ prev = leaf.NOT_IMPLEMENTED_attr -+ NOT_YET_IMPLEMENTED_StmtIf ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO ``` ## Ruff Output @@ -236,13 +246,26 @@ def f(): p = leaf.NOT_IMPLEMENTED_attr # trailing comment v = leaf.NOT_IMPLEMENTED_attr - NOT_YET_IMPLEMENTED_StmtIf - NOT_YET_IMPLEMENTED_StmtIf # another trailing comment + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + pass + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: # another trailing comment + return DOUBLESPACE NOT_YET_IMPLEMENTED_StmtAssert prev = leaf.NOT_IMPLEMENTED_attr - NOT_YET_IMPLEMENTED_StmtIf + if NOT_YET_IMPLEMENTED_ExprUnaryOp: + prevp = NOT_IMPLEMENTED_call() + if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO + + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO + + elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO ############################################################################### @@ -260,14 +283,26 @@ def g(): # Comment because comments - NOT_YET_IMPLEMENTED_StmtIf - NOT_YET_IMPLEMENTED_StmtIf + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + pass + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + return DOUBLESPACE # Another comment because more comments NOT_YET_IMPLEMENTED_StmtAssert prev = leaf.NOT_IMPLEMENTED_attr - NOT_YET_IMPLEMENTED_StmtIf + if NOT_YET_IMPLEMENTED_ExprUnaryOp: + prevp = NOT_IMPLEMENTED_call() + + if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + # Start of the line or a bracketed expression. + # More than one line for the comment. + return NO + + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return NO ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap index a08717b4bb..5733bbfdd7 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap @@ -276,7 +276,7 @@ last_call() Name None True -@@ -7,346 +8,245 @@ +@@ -7,294 +8,236 @@ 1 1.0 1j @@ -395,6 +395,11 @@ last_call() - *a, 4, 5, +-] +-[ +- 4, +- *a, +- 5, + 6, + 7, + 8, @@ -403,11 +408,6 @@ last_call() + (NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2), + (NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2), ] --[ -- 4, -- *a, -- 5, --] +[1, 2, 3] +[NOT_YET_IMPLEMENTED_ExprStarred] +[NOT_YET_IMPLEMENTED_ExprStarred] @@ -541,9 +541,6 @@ last_call() - int, - float, - dict[str, int], --] --very_long_variable_name_filters: t.List[ -- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]], +[ + 1, + 2, @@ -558,6 +555,9 @@ last_call() + NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2, + NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2, ] +-very_long_variable_name_filters: t.List[ +- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]], +-] -xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore - sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__) -) @@ -756,49 +756,50 @@ last_call() - and threading.current_thread() != threading.main_thread() - or signal.getsignal(signal.SIGINT) != signal.default_int_handler -): -- return True --if ( -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --): -- return True --if ( -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --): -- return True --if ( -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --): -- return True --if ( -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --): -- return True --if ( -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --): -- return True --if ( -- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -- / aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --): -- return True --if ( ++NOT_YET_IMPLEMENTED_StmtFor ++a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right ++a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right ++a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right ++a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right ++if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return True + if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +@@ -327,24 +270,44 @@ + ): + return True + if ( - ~aaaa.a + aaaa.b - aaaa.c * aaaa.d / aaaa.e - | aaaa.f & aaaa.g % aaaa.h ^ aaaa.i << aaaa.k >> aaaa.l**aaaa.m // aaaa.n --): -- return True --if ( ++ NOT_YET_IMPLEMENTED_ExprUnaryOp ++ + aaaa.NOT_IMPLEMENTED_attr ++ - aaaa.NOT_IMPLEMENTED_attr * aaaa.NOT_IMPLEMENTED_attr / aaaa.NOT_IMPLEMENTED_attr ++ | aaaa.NOT_IMPLEMENTED_attr ++ & aaaa.NOT_IMPLEMENTED_attr % aaaa.NOT_IMPLEMENTED_attr ++ ^ aaaa.NOT_IMPLEMENTED_attr ++ << aaaa.NOT_IMPLEMENTED_attr ++ >> aaaa.NOT_IMPLEMENTED_attr**aaaa.NOT_IMPLEMENTED_attr // aaaa.NOT_IMPLEMENTED_attr + ): + return True + if ( - ~aaaaaaaa.a + aaaaaaaa.b - aaaaaaaa.c @ aaaaaaaa.d / aaaaaaaa.e - | aaaaaaaa.f & aaaaaaaa.g % aaaaaaaa.h - ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n --): -- return True --if ( ++ NOT_YET_IMPLEMENTED_ExprUnaryOp ++ + aaaaaaaa.NOT_IMPLEMENTED_attr ++ - aaaaaaaa.NOT_IMPLEMENTED_attr ++ @ aaaaaaaa.NOT_IMPLEMENTED_attr ++ / aaaaaaaa.NOT_IMPLEMENTED_attr ++ | aaaaaaaa.NOT_IMPLEMENTED_attr ++ & aaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaa.NOT_IMPLEMENTED_attr ++ ^ aaaaaaaa.NOT_IMPLEMENTED_attr ++ << aaaaaaaa.NOT_IMPLEMENTED_attr ++ >> aaaaaaaa.NOT_IMPLEMENTED_attr ++ **aaaaaaaa.NOT_IMPLEMENTED_attr ++ // aaaaaaaa.NOT_IMPLEMENTED_attr + ): + return True + if ( - ~aaaaaaaaaaaaaaaa.a - + aaaaaaaaaaaaaaaa.b - - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e @@ -806,27 +807,22 @@ last_call() - ^ aaaaaaaaaaaaaaaa.i - << aaaaaaaaaaaaaaaa.k - >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n --): -- return True -+NOT_YET_IMPLEMENTED_StmtFor -+a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf -+NOT_YET_IMPLEMENTED_StmtIf ++ NOT_YET_IMPLEMENTED_ExprUnaryOp ++ + aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ - aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ * aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ @ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ | aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ & aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ ^ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ << aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ >> aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ **aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr ++ // aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + ): + return True ( - aaaaaaaaaaaaaaaa - + aaaaaaaaaaaaaaaa -@@ -363,8 +263,9 @@ +@@ -363,8 +326,9 @@ bbbb >> bbbb * bbbb ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa @@ -1082,16 +1078,79 @@ a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right a = NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + return True +if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + return True +if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + return True +if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + return True +if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + return True +if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + return True +if ( + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + / aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +): + return True +if ( + NOT_YET_IMPLEMENTED_ExprUnaryOp + + aaaa.NOT_IMPLEMENTED_attr + - aaaa.NOT_IMPLEMENTED_attr * aaaa.NOT_IMPLEMENTED_attr / aaaa.NOT_IMPLEMENTED_attr + | aaaa.NOT_IMPLEMENTED_attr + & aaaa.NOT_IMPLEMENTED_attr % aaaa.NOT_IMPLEMENTED_attr + ^ aaaa.NOT_IMPLEMENTED_attr + << aaaa.NOT_IMPLEMENTED_attr + >> aaaa.NOT_IMPLEMENTED_attr**aaaa.NOT_IMPLEMENTED_attr // aaaa.NOT_IMPLEMENTED_attr +): + return True +if ( + NOT_YET_IMPLEMENTED_ExprUnaryOp + + aaaaaaaa.NOT_IMPLEMENTED_attr + - aaaaaaaa.NOT_IMPLEMENTED_attr + @ aaaaaaaa.NOT_IMPLEMENTED_attr + / aaaaaaaa.NOT_IMPLEMENTED_attr + | aaaaaaaa.NOT_IMPLEMENTED_attr + & aaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaa.NOT_IMPLEMENTED_attr + ^ aaaaaaaa.NOT_IMPLEMENTED_attr + << aaaaaaaa.NOT_IMPLEMENTED_attr + >> aaaaaaaa.NOT_IMPLEMENTED_attr + **aaaaaaaa.NOT_IMPLEMENTED_attr + // aaaaaaaa.NOT_IMPLEMENTED_attr +): + return True +if ( + NOT_YET_IMPLEMENTED_ExprUnaryOp + + aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + - aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + * aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + @ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + | aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + & aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr % aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + ^ aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + << aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + >> aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + **aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr + // aaaaaaaaaaaaaaaa.NOT_IMPLEMENTED_attr +): + return True ( aaaaaaaaaaaaaaaa + aaaaaaaaaaaaaaaa diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap index ec7df09c26..7582c7cdee 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap @@ -97,7 +97,7 @@ elif unformatted: ```diff --- Black +++ Ruff -@@ -1,87 +1,33 @@ +@@ -1,33 +1,15 @@ # Regression test for https://github.com/psf/black/issues/3129. -setup( - entry_points={ @@ -130,25 +130,23 @@ elif unformatted: def test_func(): # yapf: disable - if unformatted( args ): -- return True -- # yapf: enable -- elif b: -- return True -+ NOT_YET_IMPLEMENTED_StmtIf - - return False - - ++ if NOT_IMPLEMENTED_call(): + return True + # yapf: enable + elif b: +@@ -39,49 +21,27 @@ # Regression test for https://github.com/psf/black/issues/2567. --if True: -- # fmt: off + if True: + # fmt: off - for _ in range( 1 ): - # fmt: on - print ( "This won't be formatted" ) - print ( "This won't be formatted either" ) --else: ++ NOT_YET_IMPLEMENTED_StmtFor ++ NOT_IMPLEMENTED_call() + else: - print("This will be formatted") -+NOT_YET_IMPLEMENTED_StmtIf ++ NOT_IMPLEMENTED_call() # Regression test for https://github.com/psf/black/issues/3184. @@ -161,14 +159,14 @@ elif unformatted: - ) : - # fmt: on - print ( "This won't be formatted" ) -+NOT_YET_IMPLEMENTED_StmtClassDef - +- - elif param[0:4] in ("ZZZZ",): - print ( "This won't be formatted either" ) - +- - print("This will be formatted") -- -- ++NOT_YET_IMPLEMENTED_StmtClassDef + + # Regression test for https://github.com/psf/black/issues/2985. -class Named(t.Protocol): - # fmt: off @@ -186,13 +184,14 @@ elif unformatted: # Regression test for https://github.com/psf/black/issues/3436. --if x: -- return x --# fmt: off + if x: + return x + # fmt: off -elif unformatted: -- # fmt: on ++elif unformatted: + # fmt: on - will_be_formatted() -+NOT_YET_IMPLEMENTED_StmtIf ++ NOT_IMPLEMENTED_call() ``` ## Ruff Output @@ -209,13 +208,22 @@ NOT_IMPLEMENTED_call() # Regression test for https://github.com/psf/black/issues/3026. def test_func(): # yapf: disable - NOT_YET_IMPLEMENTED_StmtIf + if NOT_IMPLEMENTED_call(): + return True + # yapf: enable + elif b: + return True return False # Regression test for https://github.com/psf/black/issues/2567. -NOT_YET_IMPLEMENTED_StmtIf +if True: + # fmt: off + NOT_YET_IMPLEMENTED_StmtFor + NOT_IMPLEMENTED_call() +else: + NOT_IMPLEMENTED_call() # Regression test for https://github.com/psf/black/issues/3184. @@ -230,7 +238,12 @@ NOT_YET_IMPLEMENTED_StmtClassDef # Regression test for https://github.com/psf/black/issues/3436. -NOT_YET_IMPLEMENTED_StmtIf +if x: + return x +# fmt: off +elif unformatted: + # fmt: on + NOT_IMPLEMENTED_call() ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap index 7e6b71b7ad..febe1c8ba1 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap @@ -222,7 +222,7 @@ d={'a':1, # Comment 1 # Comment 2 -@@ -18,109 +16,109 @@ +@@ -18,109 +16,111 @@ # fmt: off def func_no_args(): @@ -237,8 +237,10 @@ d={'a':1, + a + b + c -+ NOT_YET_IMPLEMENTED_StmtIf -+ NOT_YET_IMPLEMENTED_StmtIf ++ if True: ++ NOT_YET_IMPLEMENTED_StmtRaise ++ if False: ++ ... + NOT_YET_IMPLEMENTED_StmtFor + NOT_IMPLEMENTED_call() + return None @@ -392,7 +394,7 @@ d={'a':1, # fmt: off # hey, that won't work -@@ -130,13 +128,15 @@ +@@ -130,13 +130,15 @@ def on_and_off_broken(): @@ -413,11 +415,10 @@ d={'a':1, # fmt: on # fmt: off # ...but comments still get reformatted even though they should not be -@@ -144,81 +144,18 @@ - +@@ -145,80 +147,21 @@ def long_lines(): -- if True: + if True: - typedargslist.extend( - gen_annotated_params( - ast_args.kwonlyargs, @@ -426,11 +427,13 @@ d={'a':1, - implicit_default=True, - ) - ) -- # fmt: off ++ NOT_IMPLEMENTED_call() + # fmt: off - a = ( - unnecessary_bracket() - ) -- # fmt: on ++ a = NOT_IMPLEMENTED_call() + # fmt: on - _type_comment_re = re.compile( - r""" - ^ @@ -455,7 +458,6 @@ d={'a':1, - re.MULTILINE|re.VERBOSE - # fmt: on - ) -+ NOT_YET_IMPLEMENTED_StmtIf + _type_comment_re = NOT_IMPLEMENTED_call() @@ -529,8 +531,10 @@ def func_no_args(): a b c - NOT_YET_IMPLEMENTED_StmtIf - NOT_YET_IMPLEMENTED_StmtIf + if True: + NOT_YET_IMPLEMENTED_StmtRaise + if False: + ... NOT_YET_IMPLEMENTED_StmtFor NOT_IMPLEMENTED_call() return None @@ -654,7 +658,11 @@ def on_and_off_broken(): def long_lines(): - NOT_YET_IMPLEMENTED_StmtIf + if True: + NOT_IMPLEMENTED_call() + # fmt: off + a = NOT_IMPLEMENTED_call() + # fmt: on _type_comment_re = NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip5_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip5_py.snap index 2f7b4982c8..9f346191a9 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip5_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip5_py.snap @@ -22,7 +22,7 @@ else: ```diff --- Black +++ Ruff -@@ -1,9 +1,2 @@ +@@ -1,9 +1,5 @@ -a, b, c = 3, 4, 5 -if ( - a == 3 @@ -30,17 +30,22 @@ else: - and c is not None -): - print("I'm good!") --else: -- print("I'm bad") +(1, 2) = (1, 2) -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: ++ NOT_IMPLEMENTED_call() + else: +- print("I'm bad") ++ NOT_IMPLEMENTED_call() ``` ## Ruff Output ```py (1, 2) = (1, 2) -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + NOT_IMPLEMENTED_call() +else: + NOT_IMPLEMENTED_call() ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip8_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip8_py.snap index 1b9c54b048..f8d1d415c3 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip8_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip8_py.snap @@ -75,7 +75,7 @@ async def test_async_with(): ```diff --- Black +++ Ruff -@@ -1,62 +1,40 @@ +@@ -1,62 +1,46 @@ # Make sure a leading comment is not removed. -def some_func( unformatted, args ): # fmt: skip - print("I am some_func") @@ -109,12 +109,17 @@ async def test_async_with(): # Make sure a leading comment is not removed. -if unformatted_call( args ): # fmt: skip - print("First branch") -- # Make sure this is not removed. ++if NOT_IMPLEMENTED_call(): # fmt: skip ++ NOT_IMPLEMENTED_call() + # Make sure this is not removed. -elif another_unformatted_call( args ): # fmt: skip - print("Second branch") -else : # fmt: skip - print("Last branch") -+NOT_YET_IMPLEMENTED_StmtIf # fmt: skip ++elif NOT_IMPLEMENTED_call(): # fmt: skip ++ NOT_IMPLEMENTED_call() ++else: # fmt: skip ++ NOT_IMPLEMENTED_call() -while some_condition( unformatted, args ): # fmt: skip @@ -175,7 +180,13 @@ NOT_YET_IMPLEMENTED_StmtClassDef # Make sure a leading comment is not removed. -NOT_YET_IMPLEMENTED_StmtIf # fmt: skip +if NOT_IMPLEMENTED_call(): # fmt: skip + NOT_IMPLEMENTED_call() + # Make sure this is not removed. +elif NOT_IMPLEMENTED_call(): # fmt: skip + NOT_IMPLEMENTED_call() +else: # fmt: skip + NOT_IMPLEMENTED_call() while NOT_IMPLEMENTED_call(): # fmt: skip diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap index d4b5749cd3..44b9556da9 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap @@ -66,7 +66,7 @@ with hmm_but_this_should_get_two_preceding_newlines(): ```diff --- Black +++ Ruff -@@ -2,64 +2,27 @@ +@@ -2,64 +2,39 @@ a, **kwargs, ) -> A: @@ -99,42 +99,46 @@ with hmm_but_this_should_get_two_preceding_newlines(): def h(): def inner(): -- pass -- -- print("Inner defs should breathe a little.") -- -- --if os.name == "posix": -- import termios -- -- def i_should_be_followed_by_only_one_newline(): pass +- print("Inner defs should breathe a little.") ++ NOT_IMPLEMENTED_call() + + +-if os.name == "posix": +- import termios ++if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_YET_IMPLEMENTED_StmtImport + + def i_should_be_followed_by_only_one_newline(): + pass +- -elif os.name == "nt": - try: - import msvcrt -+ NOT_IMPLEMENTED_call() - -- def i_should_be_followed_by_only_one_newline(): -- pass - -- except ImportError: -+NOT_YET_IMPLEMENTED_StmtIf - +- - def i_should_be_followed_by_only_one_newline(): - pass - --elif False: +- except ImportError: +- +- def i_should_be_followed_by_only_one_newline(): +- pass ++elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_YET_IMPLEMENTED_StmtTry + + elif False: - - class IHopeYouAreHavingALovelyDay: - def __call__(self): - print("i_should_be_followed_by_only_one_newline") - --else: -- -- def foo(): -- pass ++ NOT_YET_IMPLEMENTED_StmtClassDef + else: - + def foo(): + pass + - -with hmm_but_this_should_get_two_preceding_newlines(): - pass @@ -169,7 +173,19 @@ def h(): NOT_IMPLEMENTED_call() -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_YET_IMPLEMENTED_StmtImport + + def i_should_be_followed_by_only_one_newline(): + pass +elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_YET_IMPLEMENTED_StmtTry + +elif False: + NOT_YET_IMPLEMENTED_StmtClassDef +else: + def foo(): + pass NOT_YET_IMPLEMENTED_StmtWith ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap index 4990f6f531..3e8b74e6cf 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap @@ -108,37 +108,36 @@ def __await__(): return (yield) ```diff --- Black +++ Ruff -@@ -1,148 +1,94 @@ +@@ -1,12 +1,11 @@ #!/usr/bin/env python3 -import asyncio -import sys -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport - +- -from third_party import X, Y, Z -+NOT_YET_IMPLEMENTED_StmtImportFrom ++NOT_YET_IMPLEMENTED_StmtImport ++NOT_YET_IMPLEMENTED_StmtImport -from library import some_connection, some_decorator +NOT_YET_IMPLEMENTED_StmtImportFrom -+NOT_YET_IMPLEMENTED_ExprJoinedStr -f"trigger 3.6 mode" -- ++NOT_YET_IMPLEMENTED_StmtImportFrom ++NOT_YET_IMPLEMENTED_ExprJoinedStr + def func_no_args(): - a +@@ -14,135 +13,86 @@ b c -- if True: + if True: - raise RuntimeError -- if False: -- ... ++ NOT_YET_IMPLEMENTED_StmtRaise + if False: + ... - for i in range(10): - print(i) - continue - exec("new-style exec", {}, {}) -+ NOT_YET_IMPLEMENTED_StmtIf -+ NOT_YET_IMPLEMENTED_StmtIf + NOT_YET_IMPLEMENTED_StmtFor + NOT_IMPLEMENTED_call() return None @@ -229,7 +228,7 @@ def __await__(): return (yield) def long_lines(): -- if True: + if True: - typedargslist.extend( - gen_annotated_params( - ast_args.kwonlyargs, @@ -269,7 +268,8 @@ def __await__(): return (yield) - """, - re.MULTILINE | re.VERBOSE, - ) -+ NOT_YET_IMPLEMENTED_StmtIf ++ NOT_IMPLEMENTED_call() ++ NOT_IMPLEMENTED_call() + _type_comment_re = NOT_IMPLEMENTED_call() @@ -319,8 +319,10 @@ def func_no_args(): a b c - NOT_YET_IMPLEMENTED_StmtIf - NOT_YET_IMPLEMENTED_StmtIf + if True: + NOT_YET_IMPLEMENTED_StmtRaise + if False: + ... NOT_YET_IMPLEMENTED_StmtFor NOT_IMPLEMENTED_call() return None @@ -382,7 +384,9 @@ def example(session): def long_lines(): - NOT_YET_IMPLEMENTED_StmtIf + if True: + NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call() _type_comment_re = NOT_IMPLEMENTED_call() diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap index 9850280e89..ecc5c3010f 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap @@ -74,7 +74,7 @@ some_module.some_function( ```diff --- Black +++ Ruff -@@ -1,69 +1,29 @@ +@@ -1,69 +1,30 @@ def f( a, ): @@ -130,11 +130,11 @@ some_module.some_function( - "h": 8, - }["a"] - ): -- pass + NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call() + x = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key] -+ NOT_YET_IMPLEMENTED_StmtIf ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + pass -def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( @@ -154,7 +154,7 @@ some_module.some_function( # The type annotation shouldn't get a trailing comma since that would change its type. -@@ -80,35 +40,16 @@ +@@ -80,35 +41,16 @@ pass @@ -220,7 +220,8 @@ def f( NOT_IMPLEMENTED_call() NOT_IMPLEMENTED_call() x = NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key] - NOT_YET_IMPLEMENTED_StmtIf + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + pass def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> NOT_IMPLEMENTED_value[NOT_IMPLEMENTED_key]: diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap index 56b3a0ef5a..7c3bdb253a 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap @@ -76,7 +76,7 @@ return np.divide( ```diff --- Black +++ Ruff -@@ -8,56 +8,48 @@ +@@ -8,56 +8,49 @@ def function_dont_replace_spaces(): @@ -164,7 +164,8 @@ return np.divide( - out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] - where=view.sum_of_weights**2 > view.sum_of_weights_squared, # type: ignore[union-attr] - ) -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_call(): ++ return NOT_IMPLEMENTED_call() -return np.divide( - where=view.sum_of_weights_of_weight_long**2 > view.sum_of_weights_squared, # type: ignore @@ -227,7 +228,8 @@ q = [i for i in []] # WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_call(): + return NOT_IMPLEMENTED_call() return NOT_IMPLEMENTED_call() ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_newline_after_code_block_open_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_newline_after_code_block_open_py.snap index 6bf44926b1..79f86d3478 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_newline_after_code_block_open_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_newline_after_code_block_open_py.snap @@ -121,7 +121,7 @@ with open("/path/to/file.txt", mode="r") as read_file: ```diff --- Black +++ Ruff -@@ -1,78 +1,64 @@ +@@ -1,78 +1,68 @@ -import random +NOT_YET_IMPLEMENTED_StmtImport @@ -175,18 +175,22 @@ with open("/path/to/file.txt", mode="r") as read_file: -if random.randint(0, 3) == 0: - print("The new line above me is about to be removed!") -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_IMPLEMENTED_call() -if random.randint(0, 3) == 0: - print("The new lines above me is about to be removed!") -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_IMPLEMENTED_call() -if random.randint(0, 3) == 0: - if random.uniform(0, 1) > 0.5: - print("Two lines above me are about to be removed!") -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: ++ NOT_IMPLEMENTED_call() while True: @@ -259,13 +263,17 @@ NOT_YET_IMPLEMENTED_StmtFor NOT_YET_IMPLEMENTED_StmtFor -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_IMPLEMENTED_call() -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_IMPLEMENTED_call() -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + NOT_IMPLEMENTED_call() while True: diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap index dd2cf4c4ad..1528c308d1 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap @@ -38,16 +38,16 @@ class A: ```diff --- Black +++ Ruff -@@ -1,34 +1,9 @@ +@@ -1,34 +1,12 @@ -if e1234123412341234.winerror not in ( - _winapi.ERROR_SEM_TIMEOUT, - _winapi.ERROR_PIPE_BUSY, -) or _check_timeout(t): -- pass -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + pass --if x: -- if y: + if x: + if y: - new_id = ( - max( - Vegetable.objects.order_by("-id")[0].id, @@ -55,7 +55,7 @@ class A: - ) - + 1 - ) -+NOT_YET_IMPLEMENTED_StmtIf ++ new_id = NOT_IMPLEMENTED_call() + 1 -class X: @@ -82,9 +82,12 @@ class A: ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + pass -NOT_YET_IMPLEMENTED_StmtIf +if x: + if y: + new_id = NOT_IMPLEMENTED_call() + 1 NOT_YET_IMPLEMENTED_StmtClassDef diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap index 6512172b1d..2f591416f5 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap @@ -16,20 +16,21 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or ```diff --- Black +++ Ruff -@@ -1,6 +1 @@ +@@ -1,6 +1,2 @@ -if e123456.get_tk_patchlevel() >= (8, 6, 0, "final") or ( - 8, - 5, - 8, -) <= get_tk_patchlevel() < (8, 6): -- pass -+NOT_YET_IMPLEMENTED_StmtIf ++if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + pass ``` ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtIf +if NOT_IMPLEMENTED_bool_op1 and NOT_IMPLEMENTED_bool_op2: + pass ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap index cd0d0a2216..889aaf9c58 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap @@ -21,22 +21,31 @@ if True: ```diff --- Black +++ Ruff -@@ -1,8 +1 @@ --if True: -- if True: -- if True: +@@ -1,8 +1,7 @@ + if True: + if True: + if True: - return _( - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas " - + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.", - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe", - ) % {"reported_username": reported_username, "report_reason": report_reason} -+NOT_YET_IMPLEMENTED_StmtIf ++ return ( ++ NOT_IMPLEMENTED_call() ++ % {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value} ++ ) ``` ## Ruff Output ```py -NOT_YET_IMPLEMENTED_StmtIf +if True: + if True: + if True: + return ( + NOT_IMPLEMENTED_call() + % {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value} + ) ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_statement_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_statement_py.snap new file mode 100644 index 0000000000..a58a992e81 --- /dev/null +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_statement_py.snap @@ -0,0 +1,88 @@ +--- +source: crates/ruff_python_formatter/src/lib.rs +expression: snapshot +--- +## Input +```py +if x == y: # trailing if condition + pass # trailing `pass` comment + # Root `if` trailing comment + +# Leading elif comment +elif x < y: # trailing elif condition + pass + # `elif` trailing comment + +# Leading else comment +else: # trailing else condition + pass + # `else` trailing comment + + +if x == y: + if y == z: + ... + + if a == b: + ... + else: # trailing comment + ... + + # trailing else comment + +# leading else if comment +elif aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [ + 11111111111111111111111111, + 2222222222222222222222, + 3333333333 + ]: + ... + + +else: + ... +``` + + + +## Output +```py +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: # trailing if condition + pass # trailing `pass` comment + # Root `if` trailing comment + +# Leading elif comment +elif NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: # trailing elif condition + pass + # `elif` trailing comment + +# Leading else comment +else: # trailing else condition + pass + # `else` trailing comment + + +if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + ... + + if NOT_IMPLEMENTED_left < NOT_IMPLEMENTED_right: + ... + else: # trailing comment + ... + + # trailing else comment + +# leading else if comment +elif aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + [ + 11111111111111111111111111, + 2222222222222222222222, + 3333333333, +]: + ... + +else: + ... +``` + + diff --git a/crates/ruff_python_formatter/src/statement/stmt_if.rs b/crates/ruff_python_formatter/src/statement/stmt_if.rs index bbef308f49..33fad5466f 100644 --- a/crates/ruff_python_formatter/src/statement/stmt_if.rs +++ b/crates/ruff_python_formatter/src/statement/stmt_if.rs @@ -1,12 +1,130 @@ -use crate::{not_yet_implemented, FormatNodeRule, PyFormatter}; -use ruff_formatter::{write, Buffer, FormatResult}; -use rustpython_parser::ast::StmtIf; +use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment}; +use crate::expression::parentheses::Parenthesize; +use crate::prelude::*; +use crate::FormatNodeRule; +use ruff_formatter::{write, FormatError}; +use rustpython_parser::ast::{Ranged, Stmt, StmtIf, Suite}; #[derive(Default)] pub struct FormatStmtIf; impl FormatNodeRule for FormatStmtIf { fn fmt_fields(&self, item: &StmtIf, f: &mut PyFormatter) -> FormatResult<()> { - write!(f, [not_yet_implemented(item)]) + let comments = f.context().comments().clone(); + + let mut current = IfOrElIf::If(item); + let mut else_comments: &[SourceComment]; + let mut last_node_of_previous_body = None; + + loop { + let current_statement = current.statement(); + let StmtIf { + test, body, orelse, .. + } = current_statement; + + let first_statement = body.first().ok_or(FormatError::SyntaxError)?; + let trailing = comments.dangling_comments(current_statement.into()); + + let trailing_if_comments_end = trailing + .partition_point(|comment| comment.slice().start() < first_statement.start()); + + let (if_trailing_comments, trailing_alternate_comments) = + trailing.split_at(trailing_if_comments_end); + + if current.is_elif() { + let elif_leading = comments.leading_comments(current_statement.into()); + // Manually format the leading comments because the formatting bypasses `NodeRule::fmt` + write!( + f, + [ + leading_alternate_branch_comments(elif_leading, last_node_of_previous_body), + source_position(current_statement.start()) + ] + )?; + } + + write!( + f, + [ + text(current.keyword()), + space(), + test.format().with_options(Parenthesize::IfBreaks), + text(":"), + trailing_comments(if_trailing_comments), + block_indent(&body.format()) + ] + )?; + + // RustPython models `elif` by setting the body to a single `if` statement. The `orelse` + // of the most inner `if` statement then becomes the `else` of the whole `if` chain. + // That's why it's necessary to take the comments here from the most inner `elif`. + else_comments = trailing_alternate_comments; + last_node_of_previous_body = body.last(); + + if let Some(elif) = else_if(orelse) { + current = elif; + } else { + break; + } + } + + let orelse = ¤t.statement().orelse; + + if !orelse.is_empty() { + // Leading comments are always own line comments + let leading_else_comments_end = + else_comments.partition_point(|comment| comment.position().is_own_line()); + let (else_leading, else_trailing) = else_comments.split_at(leading_else_comments_end); + + write!( + f, + [ + leading_alternate_branch_comments(else_leading, last_node_of_previous_body), + text("else:"), + trailing_comments(else_trailing), + block_indent(&orelse.format()) + ] + )?; + } + + Ok(()) + } + + fn fmt_dangling_comments(&self, _node: &StmtIf, _f: &mut PyFormatter) -> FormatResult<()> { + // Handled by `fmt_fields` + Ok(()) + } +} + +fn else_if(or_else: &Suite) -> Option { + if let [Stmt::If(if_stmt)] = or_else.as_slice() { + Some(IfOrElIf::ElIf(if_stmt)) + } else { + None + } +} + +enum IfOrElIf<'a> { + If(&'a StmtIf), + ElIf(&'a StmtIf), +} + +impl<'a> IfOrElIf<'a> { + const fn statement(&self) -> &'a StmtIf { + match self { + IfOrElIf::If(statement) => statement, + IfOrElIf::ElIf(statement) => statement, + } + } + + const fn keyword(&self) -> &'static str { + match self { + IfOrElIf::If(_) => "if", + IfOrElIf::ElIf(_) => "elif", + } + } + + const fn is_elif(&self) -> bool { + matches!(self, IfOrElIf::ElIf(_)) } }