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

Add reformat support to Rider #198

Closed
dubreuia opened this issue Oct 3, 2018 · 10 comments
Closed

Add reformat support to Rider #198

dubreuia opened this issue Oct 3, 2018 · 10 comments

Comments

@dubreuia
Copy link
Owner

dubreuia commented Oct 3, 2018

I can trigger the reformat with the following, ugly hack:

ActionManager.getInstance().getAction("ReformatCode")
    .actionPerformed(new AnActionEvent(null, DataManager.getInstance().getDataContext(),
        ActionPlaces.UNKNOWN, new Presentation(), ActionManager.getInstance(), 0));

This triggers the following logging in the frontend, which is the same when triggered from the menu/shortcut:

23:05:45.647 | INFO  | RiderActionOverride            | Executing ReSharper action 'RiderReformatCode'
23:05:45.647 | INFO  | RiderActionHandlers            | >> Begin backend 'RiderReformatCode' action session
23:05:45.649 | INFO  | RiderActionHandlers            | << End backend 'RiderReformatCode' action session

It does not play nice with any other action being executed simultaneously (such as "OptimizeImports"), so it is in no way an suitable solution.

So, it looks like the ReSharper action is simply not triggered/created when the CodeStyleManager is used. Do we really need to create a ReSharper plugin, which communicates with the frontend? (see https://www.jetbrains.com/help/resharper/sdk/Products/Rider.html). I cannot find really relevant documentation on this issue.

There are also some other issues when compiling the plugin with the Rider SDK, mostly missing classes, so I'm not sure if it's even possible to compile the current plugin for Rider. See bobvandevijver@0a1d0af for the classes I needed to remove in order to being able to build for Rider.

Edit: I also created a ticket at JetBrains: https://youtrack.jetbrains.com/issue/RIDER-20225

(btw, if you want to open an another issue for this discussion just let me know)

Originally posted by @bobvandevijver in #18 (comment)

@dubreuia
Copy link
Owner Author

dubreuia commented Oct 3, 2018

I guess it should be something like:
val actionId = ActionManager.getInstance().getAction(IdeActions.ACTION_EDITOR_REFORMAT)

var component  =  project.getComponent<EditorImpl>().component
var dataContext = DataManager.getInstance().getDataContext(component)
fun executeAction(actionId: String, dataContext: DataContext) {
    frameworkLogger.info("Execute action: '$actionId'")
    val actionManager = ActionManagerEx.getInstanceEx()
    val action = actionManager.getAction(actionId)
    //requireNotNull(action) { "action is null" }

    val event = AnActionEvent.createFromAnAction(action, null, "", dataContext)
    action.beforeActionPerformedUpdate(event)

    //require(event.presentation.isEnabled) { "presentation.isEnabled is false for $actionId" }

    actionManager.fireBeforeActionPerformed(action, event.dataContext, event)
    action.actionPerformed(event)
    actionManager.fireAfterActionPerformed(action, event.dataContext, event)
}

I will ask colleagues about calling reformat and OptimizeImports simultaneously.
I assume you are calling OptimizeImports with similar code above.
Surprisingly "OptimizeImports" is not listed in IdeActions, so just hardcode it.

Originally posted by @van800 in #18 (comment)

@dubreuia
Copy link
Owner Author

dubreuia commented Oct 3, 2018

I just used your examples (needed to retrieve the editor component with JComponent component = FileEditorManager.getInstance(myProject).getSelectedTextEditor().getComponent(); though), the result is the same: only one action is executed, which is the once that is called later.

Another thing noteworthy is the fact that your example triggers the save action handlers twice, while the version I posted earlier didn't... not sure what causes that though.

Another question I have with this solution: it probably doesn't support VCS changed code either... I really hope that JetBrains will just implement the CodeStyleManager in Rider 😅

Originally posted by @bobvandevijver in #18 (comment)

@dubreuia
Copy link
Owner Author

dubreuia commented Oct 3, 2018

@bobvandevijver I have asked about multiple commands but no workaround for now.

Not sure, what do you mean about vcs changed code. If you want to reformat everything in solution, you need to put solutionNode of SolutionExplorer to context like:

        val viewPane = SolutionExplorerViewPane.getInstance(project)
        val solutionNode = viewPane.model.root.children.filterIsInstance<SolutionExplorerModelNode>().single()

        val contextData = mapOf(
            Pair(PlatformDataKeys.SELECTED_ITEM.name, solutionNode),
            Pair(PlatformDataKeys.PROJECT.name, project),
            Pair(ProjectModelDataKeys.SOLUTION_VIEW.name, viewPane))

        var dataContext= SimpleDataContext.getSimpleContext(contextData, null)

Originally posted by @van800 in #18 (comment)

@dubreuia
Copy link
Owner Author

dubreuia commented Oct 3, 2018

@van800 To reformat only changed lines according to your VCS (eg. git) (which is one of the options of the ReformatCodeProcessor, which uses the CodeStyleManager internally)

Originally posted by @bobvandevijver in #18 (comment)

@dubreuia
Copy link
Owner Author

dubreuia commented Oct 3, 2018

(copy pasted issue comments from #18 for clarity)

@bobvandevijver
Copy link

So, for now I trimmed the plugin, leaving only the reformat action as suggested by @van800.
Unfortunately, it seems that such an action can only be triggered (or actually finished) once during plugin activation, as (even when it called multiple times) there is only a single file is reformatted when multiple files are saved at once.

A second thing I noticed is that after the reformatting action has finished, the file is still marked as modified an therefor not completely saved. Not sure how to fix that. This has probably to do with the fact that the action is scheduled after the save action. Not sure if the plugin behaves the same in the other IDEs, but there I've never noticed that.

I won't create a PR with what I have now, as it is nowhere near something that can be used here (as I deleted almost everything else from the code to make it compile and as simple as possible). However, it is available at the Rider support branch in my fork.

I attach the build version here, so others can use it when they don't mind the limitation (only reformatting, single file, not saved after reformat): Rider Save Action.zip

As I'm nowhere near finishing this functionality, I will also stop trying to fix it for now. Let's see what my ticket at JetBrains brings us.

@dubreuia
Copy link
Owner Author

dubreuia commented Oct 5, 2018

Unfortunately, it seems that such an action can only be triggered (or actually finished) once during plugin activation, as (even when it called multiple times) there is only a single file is reformatted when multiple files are saved at once.

That's weird. Right now, the plugin is triggered once per "dirty" file, the file is reformatted in the plugin, then it is saved (almost, see issue down here). It might be a threading issue.

A second thing I noticed is that after the reformatting action has finished, the file is still marked as modified an therefor not completely saved. Not sure how to fix that. This has probably to do with the fact that the action is scheduled after the save action. Not sure if the plugin behaves the same in the other IDEs, but there I've never noticed that.

This is a long lasting issue that we are unable the fix right now, see #39.

I won't create a PR with what I have now, as it is nowhere near something that can be used here (as I deleted almost everything else from the code to make it compile and as simple as possible). However, it is available at the Rider support branch in my fork.

Thanks a lot for your time!

@bobvandevijver
Copy link

That's weird. Right now, the plugin is triggered once per "dirty" file, the file is reformatted in the plugin, then it is saved (almost, see issue down here). It might be a threading issue.

It is probably the same issue as triggering "OptimizeImports" and "ReformatCode" at the same time. Only the AnAction that is triggered last (or first, not sure) is actually performed. I do see the plugin acting for the different files, but the reformat only works for one of them.

@van800
Copy link

van800 commented Oct 5, 2018

Please consider this code:
https://github.com/JetBrains/resharper-unity/blob/183/rider/src/main/kotlin/com/jetbrains/rider/plugins/unity/SaveAllTracker.kt#L23
If we use this datacontext (inside beforeActionPerformed), instead of active editor to datacontext, then all dirty files should get formatted and saved.

@dubreuia
Copy link
Owner Author

I'm working on #118 right now that might be used for that. Reopen if not enough

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

No branches or pull requests

3 participants