-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Applying code fixes outside Visual Studio #2020
Comments
You haven't missed anything, and it's definitely something that we're up for changing. We'd love to have projects like Omnisharp-Roslyn be able to use our However, we probably won't have time to devote to it before VS 2015 ships. If you'd like to take a stab at it though, we'd be happy to consult! |
Thanks for the quick feedback. In that case, I would like to take a look at this, though it may be a little while before I get a chance to do so in much detail. As a first step, I'll look at specifying an API so it can be discussed and iterated here before coding anything. I have some usage examples from the @nosami - any thoughts on this as far as what would work best for Omnisharp-Roslyn? |
Right now, we are using some CodeFixProviders from NRefactory6. The code we are using is probably pretty naive but is working fine for the small number of fixes that we have available to us. I think we just need 1 API method :- public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan range, CancellationToken cancellationToken) |
Tagging some other people who might be interested: @mattwar @heejaechang @mavasani @srivatsn @shyamnamboodiripad @jmarolf |
how do you intent to use it? if you are using it with Workspace and MEF, then, anything in feature layer should/most likely just work as long as it is somehow exposed to public. only thing needed will be cleaning up APIs. ... if you intent to use it without MEF, then we probably need to do some work to move services to be based on feature pack rather than MEF directly (even if feature pack internally could use MEF). ... if you intent to use it even without Workspace, then.. it would be quite a bit of work and design change. |
if we want to follow existing pattern of SymbolFinder, Formatter, Renamer and etc then, we probably need to move to FeaturePack and let it accepts CodeFixProviders. and make that CodeFixer to return Solution rather than CodeActions so that caller doesn't need to deal with CodeActionOperations. |
The only reasonable consumer of this API is one that also operates like the IDE. Given a diagnostic, one or more code fixes (represented as code actions) are returned. From this, an actual user has to be presented with options to choose which action. The chosen action can then be executed and applied. |
@mattwar I'm not sure that "the only reasonable consumer of this API is one that also operates like the IDE" (though I agree that's certainly the most obvious). It also happens to be the use case I'm currently looking at (writing, testing, and applying code fixes in LINQPad). However, I could envision scenarios where code fixes are used as a programmatic code re-writing system. Why create a new capability for identifying target locations, specifying transforms on the syntax tree, and applying them when we already have something that does exactly that? |
There can be more than one code fix provider offering fixes for a diagnostic, and code fix providers can offer more than one possible fix. Someone has to choose which fix to apply. The only information to go on is the description text, which is meant to be read by either an actual person or some futuristic AI. So, code fixes, themselves, don't work well as programmatic operations, because there is no way to programmatically distinguish between them. You could, however, also offer an API that does the same operation as the code fix. |
@mattwar What about the use case where we already know which I guess what I'm trying to address with this is the use case where I have a code fix written by someone else (say, "make all class names uppercase") and I want to write an automated tool that applies it across the board, to specific documents, etc. I wouldn't want to rewrite that code fix using the standard syntax APIs or rip out the logic that manipulates the trees when I've already got everything right there. And in reverse, if I'm doing some general code rewriting it would be nice to write and maintain that logic in one place and use it for programmatic as well as interactive use. That aside, there's still also the question of how to make use of code fixes even if you have an interactive envionment. For example, the Omnisharp use case or my use case where I'm trying to make use of code fixes in a totally independent "IDE" or text editor. I suppose you could probably make this work today with a lot of rigging code, but a more standard API for this would go a long way towards making it easier. (unrelated to above, but had already started typing when your comment came in...) Here's what I'm thinking in terms of requirements for a public API:
And some questions/comments:
|
@daveaglick I'm providing some information hopefully answering some of your questions from the second half. A CodeAction is basically a delegate with a description. The delegate does some action (on inputs that it has already captured) and yields CodeActionOperation's. These operations represent the output of the action, with all the changes already made. You get them by calling CodeAction.GetOperationsAsync(), which invokes action and returns the operations produced. However, none of these changes have affected the workspace yet. They've all been done to a isolated copy of the solution (the captured input). You push these changes back into the workspace by calling the CodeActionOperation.Apply method on each operation. The primary reason CodeActionOperations exist in the API and not just implied by the code action, is so the Apply methods can get called on the UI thread (a constraint imposed by VS), and the code action author is free to operate in blissful ignorance. There is already a way to get code fixes that apply to all occurrences in a solution. It's called a FixAll provider and can be accessed from a normal provider. It doesn't have scopes like Document and Project, but possibly could in the future. The reason this is a separate provider that produces aggregate code actions and not some aggregate operation over multiple code actions is that often fixes need to have special case handling in order to avoid conflicting with one another. There is a default FixAll provider that can be used by an author if they know their fixes can be applied correctly in sequence. Other than that there is no way to apply a code fix to other scopes, because the scope of the fix has already been captured within each CodeAction instance. |
@mattwar
However, constructor for |
I think CodeActionOperation except ApplyChangeOpeartion is a bit host specific such as opening a file in host, providing its own preview and etc. with ProjectCodeFixProvider (not MEF based CodeFixProvider) we might be able to get around it but still CodeFixProvider work on top of Document where Host might have its own IWorkspaceService specific to the Host, so I think it would be safer not to expose CodeActionOperation and make CodeFixer work like others where it is solely a solution to a solution transformation API. |
Slightly related to this issue - I've been using the Can I submit a PR to move it to the |
Sure! |
Since #2709 is now closed, shouldn't this issue be too? |
This would need to go through an API proposal. in general, the reason we don't just make things public is because it increases maintenance costs and locks down our ability to change things in teh future. |
I'm having a hard time tracking down how to do this, and I'm starting to wonder if it's even possible.
In finding all uses of
CodeFixProvider
, it looks isolated to theWorkspaces
,Features
, andDiagnostics
libraries. None of them appear to have an API for actually applying code fixes. In fact, in theCodeFixTestBase
class I noticed that the application of a code fix appears to be performed manually by rigging up aCodeFixContext
and calling the methods ofCodeFixProvider
directly.If I haven't missed something, than my next question would be if there are plans to expose code fixes in the same way other functionality is exposed. For example, analyzers can be run (fairly) easily outside the confines of Visual Studio. If it's not already on the table, would this be a proposal the team would be amenable to considering (at which point I could write up a proposal)?
The text was updated successfully, but these errors were encountered: