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

DSLD needs a better auto-formatting for DSL builder pattern #603

Closed
ybayk opened this issue Jun 11, 2018 · 11 comments
Closed

DSLD needs a better auto-formatting for DSL builder pattern #603

ybayk opened this issue Jun 11, 2018 · 11 comments
Assignees

Comments

@ybayk
Copy link

ybayk commented Jun 11, 2018

Consider the following typical DSL representing a search query:

and {
  or {
     term 'foo'
     term 'bar'
  }
  not {
     term 'baz'
  }
}

Assume and(Closure block) method is proposed by the contribution block and the method does not contain required params besides trailing closure.
A much preferred state after autocompletion would be:

and {
  |
}

For a method with required parameters (e.g. method name: and, namedParams:[score:float]), desired autocompletion would look like this:

and (score: | ) {
  
}

Even when Eclipse Content Assist preferences set to "Use closure literals for closure arguments" and "Place trailing closure args after closing parens", the best that could be achieved today is

and { it }

Desired formatting rules are DSLD-specific, so I propose to add more formatting flags for the "method" tag in the contribution block. We already have noParens which is a good start but it is not sufficient.

We need at least four more options:

  1. option to suppress "it" as not making sense in this scenario
  2. option to set caret position next line and insert closing curly bracket one more line below
  3. option to override preference "Use closure literals for closure arguments"
  4. option to override preference "Place trailing closure args after closing parens"

I have not investigated how hard this will be to implement, just fishing if this is a sound proposal.

@eric-milles
Copy link
Member

I think you could get and(score: |) { } with some adjustments in MethodContributionElement, GroovyMethodProposal and GroovyJavaMethodCompletionProposal. The proposal for the DSLD method is built starting from the MCE. You should probably have a look at guessed-arguments mode in general to see how linked mode is used to set multiple caret positions that can be navigated with Tab. The API is quite powerful, but takes quite a bit of time to get familiar with.

@eric-milles
Copy link
Member

eric-milles commented Jun 12, 2018

At the moment I think named arguments/parameters are not automatically added when a method proposal is selected. They were kind of bolted on afterwards as proposals within the argument list expression.

As for { it } as the auto completion for Closure params, I have tried without the "it", but if I remember correctly there were issues with the selection management when removed. For now, I consider it a hint that the implicit param is available -- new Groovy users may not be aware of "it" vs. an explicit parameter.

@eric-milles
Copy link
Member

Note: If you type and { then press Enter, you should end up with:

and {
  |
}

@ybayk
Copy link
Author

ybayk commented Jun 12, 2018

Regarding { it } I understand that it is generally useful to suggest. My point is that for some cases (such as builders - see my search dsl example above or gradle scripts) it does not make sense and may only confuse DSL users. That is why I am proposing to make an option (e.g. extra boolean param with default value false for the contribute's "method" tag)

@ybayk
Copy link
Author

ybayk commented Jun 12, 2018

Regarding having to type and { yes, it will insert closing bracket next line after hitting enter, but that implies that user have to know to enter opening bracket.
Also if and(Closure block) is available in the autocomplete menu, when the user picks it, it just immediately inserts and { it }. So then the user will have to: 1) remove 'it' 2) move the closing bracket 3) put the caret in a middle - it is just cumbersome, IDE should simply do it for the user (again this behavior should be optional and configurable in DSLD)

@ybayk
Copy link
Author

ybayk commented Jun 12, 2018

To simply DSLD api change, I think it will make sense to combine all necessary options into one, e.g. isBuilder: (true | false)
The resulting contribute entry would look like the following:
method name: "and", type: "void", isBuilder: true, noParens: true, params: [block: 'groovy.lang.Closure'], provider:'And Query'

An attempt to pick this method from the auto-complete menu would result into desirable state (regardless of Eclipse Content Assist preferences):

and {
  |
}

@eric-milles
Copy link
Member

Before deciding on a final API, have you tried to implement any of the proposed changes? I suggest tackling them separately and when you have all the necessary parts, you could provide switchability from the DSLD API if still required.

For trailing Closure completion, if completion of the and(Closure) proposal results in and { | } then you press Enter, does it result in:

and {
  |
}```

Or does the trailing brace stay on the line of the caret?  I understand you want 100% the newline scenario, but I find myself wanting a single-line closure as much as a multi-line one.  So it's hard for me to accept always producing the multi-line version when the single-line should be convertible to the multi-line with just one keystroke.

@ybayk
Copy link
Author

ybayk commented Jun 13, 2018

After choosing and(Closure) proposal it looks like this:

image

The entire closure with brackets is selected and the editor is in the refactoring mode.
If you hit enter it will just clear the closure.

So in order to bring it to desired state one has to:

  1. move the caret (right) to reset selection state
  2. hit enter to reset refactoring mode
  3. move the current left (before closing bracket)
  4. hit backspace 4 times to remove 'it' and to set the caret right after opening bracket
  5. finally hit enter, after which the caret and the closing bracket get into the desired position

Is there any better way?

@eric-milles
Copy link
Member

Oh that's right. So the issue that I ran into when last I made changes was argument guessing. When that mode is enabled, the choices for a closure argument need to replace the literal { it }, not just "it". It's possible to adjust the selection for an argument replacement, but compatibility with guessing mode is sticky.

If you hit Tab, is there a tab stop for just "it"? Or what about Esc? I thought I set the exit position for the linked mode to cover the "it" param. Basically linked mode lets you set a sequence of selections that can be navigated with tab (or other trigger characters like a comma) and exiting linked mode (usually with a semicolon or Enter keypress) takes you to the API-set exit position.

Closure literal insertion is probably the messiest part of the areas you mentioned for improvement. You have to deal with names vs literals, trailing as a special case, "it" or not "it", and formatter preferences for brace position and spacing before and after braces. And params and the "->" could be inserted as well.

I'd say try and see if you can get the named arguments to be inserted when the proposal is applied as a first step. We could look into the Closure stuff after.

@eric-milles
Copy link
Member

There is a summary of the many combinations of content assist options near the end of #410 (see the embedded table images). Typing { to trigger the content assist proposal is another way to get varied behavior.

@eric-milles
Copy link
Member

"Place trailing closure arguments after closing parenthesis" preference defaults to checked

Other concerns will be addressed as individual issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants