-
Notifications
You must be signed in to change notification settings - Fork 47
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
Add formatter for the parse AST #820
base: master
Are you sure you want to change the base?
Conversation
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.
I think that we really don't need all of these reformat
override defns. Please find some way to avoid most of them (see my suggestion for how).
@@ -318,7 +335,9 @@ case class PVersionedIdnUseExp(name: String, version: String, separator: String | |||
trait PAnyFormalArgDecl extends PNode with PUnnamedTypedDeclaration with PPrettySubnodes | |||
|
|||
/** The declaration of an argument to a domain function. Not a `PDeclaration` as it will never clash. */ | |||
case class PDomainFunctionArg(name: Option[PIdnDef], c: Option[PSym.Colon], typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl | |||
case class PDomainFunctionArg(name: Option[PIdnDef], c: Option[PSym.Colon], typ: PType)(val pos: (Position, Position)) extends PAnyFormalArgDecl { | |||
override def reformat(implicit ctx: ReformatterContext): List[RNode] = showOption(name) <> showOption(c) <+> show(typ) |
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.
I really have a feeling we could avoid a lot of these functions by simply using the PPrettySubnodes
trait (and e.g. adding a reformat
function there or even just merge pretty
and reformat
).
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 I've gotten rid of quite a few implementations in ecbb283, let me know if it is better now. There are still quite a few implementations, but they are kind of unavoidable because a lot of nodes need custom handling.
I can try to move the Reformattable
trait into PPrettySubNodes. I'm not a 100% sure about merging pretty
and reformat
, since I'm not sure if someone maybe relies on the API and I want to avoid breaking/interfering with existing code as much as possible. Not to mention that it would result in an even bigger git diff, so I think if at all it would make sense to do it in a separate PR? As you want, though!
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.
Sorry for the slow response, I was on holiday. pretty
is only used in the IDE e.g. to display the function signature of a function call when hovered: I imagine that it should match quite closely to what reformat does. For example, pretty
is already able to handle printing this PDomainFunctionArg
- the PSym.Colon
itself adds the space. I imagine reformat
could be made to work the same way, with little custom handling here.
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 just to be clear, you still want me to replace pretty
completely in this PR? Or would it be fine to open an issue for that and for now, I just focus on trying to merge this into PPrettySubNodes
and seeing whether I can remove some more impls?
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.
I would like this PR to do things the way that pretty
does. That means that the vast majority of classes in ParseAst.scala
don't have a pretty
or reformat
implementation (looking over it now, I even see some overrides of pretty
that are unnecessary), except for the unparseable types and 2 or 3 special pnodes maybe. If you're not sure how to achieve this, I'm happy to help out a bit.
If pretty
is deleted once that is done is not super important. I imagine it would simply be implemented as .reformat.toString
or whatever the calls are.
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.
Got it, I’ve already managed to remove a couple more overrides, I will keep trying a few more things and see how far I can get.
@@ -19,6 +22,8 @@ trait LeftSpace extends PReservedString { override def leftPad = " " } | |||
trait RightSpace extends PReservedString { override def rightPad = " " } | |||
case class PReserved[+T <: PReservedString](rs: T)(val pos: (Position, Position)) extends PNode with PLeaf { | |||
override def display = rs.display | |||
// Need to override implementation because pretty-printing will add space padding | |||
override def reformat(implicit ctx: ReformatterContext): List[RNode] = rt(rs.token) |
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.
I would change leftPad
and rightPad
to be Boolean (I think currently they only are ""
or " "
) and then add a space to the left/right based on that. I think you can do the majority of spaces this way. You could also add a addNewline
field which is set for e.g. all stmt keywords and function
/method
/requires
etc. which adds a newline before the keyword. Lastly, I would define a some things as "grouping" in the sense that they add two spaces after a newline for all contained RNode
s, which would probably handle most cases of indentation (I think you already do this below, but I'm not 100% sure).
So, overall, I think I've managed to get rid of a bunch of overrides, thanks for the hints, they helped a lot! :D However, there still are quite a few remaining but I think it will be rather hard to remove those... :/ I'll try to add explanations for some of them below. Some other notes: Regarding some of the overridden
Similar problems apply to the remaining ones. Regarding your comments:
I changed that!
I tried this, unfortunately this doesn't seem to work very well in my case... The problem is that I had to implement a somewhat sophisticated logic to preserve newlines in the existing program while also respecting the intended formatting, and it doesn't work well if I just always prepend a newline. Just to give you an idea, if you have for example:
After reformatting, it should preferably stay the same, while if you have something like:
The reformatted result will now look like:
instead of:
Things get even more complicated if there are comments in between the members where I need to look at the whitespaces before and after the outer comments, so this is why the logic for reformatting is pretty delicate, and just prepending a newline before each members unfortunately trips it up.
Yes I have the Let me know what you think, I hope it's at least an improvement to before. |
No description provided.