-
Notifications
You must be signed in to change notification settings - Fork 17
(fix) Proposing a workaround for superfluous indentation on multi-lines #66
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
base: main
Are you sure you want to change the base?
Conversation
Adding more clunk: Addressing the case of multi-lines F-string with parenthesis: #74 |
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.
Thanks so much @MementoRC for the PR (and so sorry for the delay on the review!!). I have a few suggestions / minor comments, let me know if you'd like to handle them (or I can also try to push them myself to your branch if that works for you)
Thank you very much for the review. This is a learning exercise for me! I would like to go through your review and update the PR, so that it becomes less work on your side. I first needed to know that the approach is acceptable |
refactor/ast.py
Outdated
def not_original(i: int) -> bool: | ||
common_chars: str = commonprefix([str(self.data[i]), str(source_lines.data[i].data)]) | ||
is_multiline_string: int = str(self.data[i]).find(common_chars) == 0 and common_chars in ["'''", '"""'] | ||
return not (i < len(source_lines.data) and (str(self.data[i]) == common_chars or is_multiline_string)) |
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.
So if we reduce it to bare minimum (let's drop the multiline strings for now, just to make this patch simpler), what this does is basically checking if the original line starts with the replaced line and if it is the case we skip indenting?
A better way to express it might be this:
for index, line in enumerate(self.data):
if index < len(source_lines):
original_line = source_lines[index]
else:
original_line = None
if index == 0:
self.data[index] = indentation + str(start_prefix) + str(line) # type: ignore
elif original_line is not None and original_line.startswith(line):
self.data[index] = line # type: ignore
else:
self.data[index] = indentation + line # type: ignore
But I am still unsure on how this should work in different scenarios, would love to see a few more examples (or actually tests) where the indentation is preserved for the first argument (when replacing the whole call), the middle arguments, the last argument (maybe introduce a new argument or remove one from the middle).
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 only works when the Call
is unchanged, removing or adding arguments does not maintain the original form, but collapses the Call
into one line. The case I was working with was wrapping the Call
in Await
and it works well in that case
There is something I don't understand though, I added a few tests (bear with my padawan-level) and the Issue #12 pass, but in the complete_rules it does not, it'd be great if you took a look at those tests, I must be doing something (or more) incorrectly
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.
Ok, the issue was that in the test_ast.py
, I use the full source_lines (with indent=0 and thus is not added to the failing line), but in the test_complete_rules.py
only the changed source line is passed (because of the view
), so the indentation is there and the test fails.
Now, the 'multi-line' issue is more of a "within parens" issue, so would it be acceptable to just have this:
elif original_line is not None and (original_line.startswith(line) or line[-1] in (")}]")):
This way the test passes
…o have 1 extra char, like closing parens
May address issue:#12
Was proposed to resolve wrapping a multi-line
ast.Call
into anast.Await
without having changes in the indentation of the secondary linesThe solution proposed is assuming that often the
Replace
would only change the first line of an ast.Expr and lose the original indentation (thus later on having to add it), however, the replacement ends-up having the original indentation for the lines that are left unchanged. The proposal is to check that the lines are indeed not the same before applying the block indentationThis is not robust, but more like a workaround