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 Plugins Capability #208

Closed
RichiCoder1 opened this issue May 6, 2015 · 35 comments
Closed

Add Plugins Capability #208

RichiCoder1 opened this issue May 6, 2015 · 35 comments
Labels

Comments

@RichiCoder1
Copy link

It'd be great to add some sort of plugin functionality to omnisharp to enable experiences like ScriptCs without shipping the functionality with omnisharp itself.

Came up as a result of discussion about adding Cake functionality to omnisharp-roslyn.

@nosami
Copy link
Contributor

nosami commented May 6, 2015

👍 to this. We could also maybe use it to add support to other languages, F# etc.

We are probably going to need to embrace MEF sooner or later, so we should probably consider using MEF to build the plugin layer with.

The biggest issue I think is deciding what the contract needs to look like.

@Yantrio
Copy link
Member

Yantrio commented May 7, 2015

I have a good feeling we are going to want this anyway for the code actions and refactorings to bring them in using MEF, the way roslyn intended.

@davidfowl
Copy link
Member

Sounds like a great plan

@borgdylan
Copy link

👍

@RichiCoder1
Copy link
Author

👉 Any movement on this? Interested in getting Cake support up and running and not sure how to progress.

@nosami
Copy link
Contributor

nosami commented Jul 8, 2015

No, sorry :(

@nosami
Copy link
Contributor

nosami commented Jul 8, 2015

@RichiCoder1 What would you want the interface to look like?

@RichiCoder1
Copy link
Author

I'm honestly not sure. It looks like for both my and ScriptCs's purposes, being able to implement IProjectSystem and having access to Workspace, Env, and Log is enough. I'm not sure if that tells the whole story though.

Edit: Should mention I created a CakeProjectSystem using ScriptCs as a template. Just had to swap a few things out by the looks of it, though I haven't figured out a good way to test. Also, aliases (a cake feature) require a little more thought.

@RichiCoder1
Copy link
Author

Realizing I should /cc @patriksvensson

@nosami
Copy link
Contributor

nosami commented Jul 30, 2015

@RichiCoder1 I just saw your message on Jabbr. Nobody is looking at this yet - any help would be appreciated. Thanks!

@RichiCoder1
Copy link
Author

👍 I'll see what I can do.

@nosami
Copy link
Contributor

nosami commented Jul 31, 2015

Thanks! I imagine that it would involve a lot of code shuffling.... so probably best to discuss any work that you are thinking of undertaking before you do it.

@RichiCoder1
Copy link
Author

In addition to ScriptCs and Cake, are there any current or future parts of OmniSharp that we'd like to see pulled our or made extensible?

@david-driscoll
Copy link
Member

I've heard Razor would probably be best as a plugin as well.

On Fri, Jul 31, 2015 at 11:23 AM, Richard Simpson notifications@github.com
wrote:

In addition to ScriptCs and Cake, are there any current or future parts of
OmniSharp that we'd like to see pulled in or made extensible?


Reply to this email directly or view it on GitHub
#208 (comment)
.

@RichiCoder1
Copy link
Author

That'd definitely be somewhere were we might look at VS for an example. Both ScriptCs and Cake are relatively simple since they mostly are implemented by preprocessing and organizing files, and then passing on to OmniSharp & Roslyn's existing C# scripting support. Razor would be much more complicated.

@nosami
Copy link
Contributor

nosami commented Aug 1, 2015

I think we also need to be able to support out of process plugins. ScriptCs currently won't work on CoreCLR and we might want to move omnisharp-roslyn to coreclr soon.

@nosami
Copy link
Contributor

nosami commented Aug 3, 2015

Possible f# support is another good reason to use (or at least allow) out of process plugins.

@borgdylan
Copy link

Also remember that coreclr is not available on all cpus that it will be available on at RTM. So do leave mono as an option.

@nosami
Copy link
Contributor

nosami commented Aug 3, 2015

95% certain that we will use coreclr for omnisharp-roslyn. If we go down the out of process plugin route, then plugins would be free to use desktop clr.

@borgdylan
Copy link

But remember that omnisharp's core will have to run on the machine in the first place. CoreCLR for x86 is still on the drawing board. I would agree that once CoreCLR gets released to all CPUs and OSes mentioned by MSFT i.e (Windows, Linux, Mac) x (x86,x64,ARM) then CoreCLR would be the best CLR to run omnisharp's core.

@david-driscoll
Copy link
Member

This is a proposal of what the plugin system might look like using MEF. Before any work is started on this epic venture, I figure it might make sense to have a proper plan and direction.

Also my knowledge of MEF might be off, I've only ever played with the technology, so be nice! 👍

What kind of plugins are we looking for?

Examples:

  • C#
  • VB
  • Cake
  • ScriptCs
  • Razor
  • F#?

The services these different plugins will need varies greatly from feature to feature. Some of them might need the Roslyn workspace (eg. C#, VB). Others won't need access to the Roslyn workspace (eg. F#).

On thing in common, they need to be able to surface our API endpoints of omnisharp. Autocomplete, Diagnostics, and so forth.

Default Services

My thought is that OmniSharp (either as a plugin, or just in the core library) would export would export services that would be needed for plugin consumption.

  • OmnisharpWorkspace
  • IEventEmitter

Endpoint Services

Each end point would get a corresponding interface, that each plugin would export, and then the API controller would import the exported services. (do we need an intermediary service to delegate this to, as a singleton?). On each incoming request, we would have another service (or perhaps a method on the service?) that would be used for selecting the best fit (if any).

An example might look like...

namespace OmniSharp.Mef.V1
{
    public interface ICodeCheck
    {
        Task<bool> IsApplicableTo(Request request);
        Task<QuickFixResponse> CodeCheck(Request request);
    }
}

Each plugin that exports ICodeCheck could then simply implement logic to detect if the request is applicable to it or not. (Should we apply some sort of priority ordering here to allow for plugins to override default behavior?)

Request Interception

Right now we use Request Filters to handle buffer updates, should we offer plugins the change to enter their own custom Mvc Requets Filters? (In this case we get the behavior for free!) Or make our interceptor that plugins can listen for, for their own buffer updates?

Default Services

Now each of our current project systems could be broken out into their on plugin. If you don't need MSBuild support it could be disabled by the editor invoking OmniSharp. This also leaves us with a strange case, where we have several project systems that all use the same default services (Dnx, MsBuild, ScriptCs). So in this scenario I propose that we just have default Roslyn Services, for our existing endpoint implementations (that are just roslyn based). For our C# services (like auto complete) we could have default CSharp services.

If in the future, we add for example VB support, we won't have to rewrite every service, we could just plugin support for VB and get most of the end points for free. There are some exceptions like Autocomplete for example.

One problem this may lead to, and should be documented, is which services are Roslyn services and which are CSharp, and what might have to be implemented in other scenarios.

Out of Process Plugins

Using out of process plugins should be a fairly trivial endeavor really. It would be almost identical to how any other plugin is built, just the async response would be waiting for the put of process plugin to produce a response. This theoretically would allow us to implement any language we wanted to through OmniSharp.

@paulyoung
Copy link

@7sharp9 – thought you might want to take a look at the above.

@RichiCoder1
Copy link
Author

@david-driscoll Nice! Looks great. Some of the things you're talking about could probably use something like MEF's export metadata for plugins to provide hints to omnisharp the plugin needs some bit loaded and present.

@7sharp9
Copy link

7sharp9 commented Aug 14, 2015

@paulyoung Thanks.

Interesting to see this moving now, I've never really been a big fan of MEF but if it works here then fine :-)

I was actually playing with a plugin setup for something similar using signalR the other week, not dynamic hubs but ones with strongly typed interfaces running with azure back plane. It was especially interesting as clients can be standard web sockets etc and servers can be non-dot net like Elixir etc. 😀

@nosami
Copy link
Contributor

nosami commented Aug 26, 2015

@7sharp9 I'm not a big fan of MEF either, but we are forced to use it already because of Roslyn and it will get the job done :)

@david-driscoll For out of process plugins, we should probably just stick to our existing stdio protocol to communicate between the core server and the plugin. I think we could have one core service that can talk to any of the OOP plugins.

For in process plugins, we could allow Request Filters.

The interface for CodeCheck would probably look a little more like this I think:-

public interface ICodeCheck
    {
        bool IsApplicableTo(Language language);
        Task<QuickFixResponse> CodeCheck(Request request);
    }

IsApplicableTo may not even be necessary. We might be able to use MEF attributes to select the correct plugin to handle a request. I don't think we need any sort of priority ordering - there is a one to one mapping between file extension and plugin as I see it.

C#, VB, ScriptCS and Cake could be handled with a single Roslyn plugin like you suggest. F# could be either in process or OOP. OmnisharpWorkspace is tied to Roslyn, so that would sit within the language plugin. ScriptCS and Cake could be candidates for OOP - last I heard , they are tied to using desktop CLR and we'd like to move to CoreCLR. @filipw?

I think we would need to handle ProjectSystems as separate plugins. We would have MSBuild (for maybe both F# and C#? There are a few differences), DNX, ScriptCS. The project system plugin would need to somehow populate the language plugin workspace.

I also think that making the refactorings an OOP plugin is possibly a good idea. We've been tied to NR6-alpha3 for some time now because of inter dependencies. It would be nice to start using RefactoringEssentials instead and not have to care about which Roslyn version it is using. Won't work unless we populated 2 separate workspaces

@nosami
Copy link
Contributor

nosami commented Aug 26, 2015

We can probably make any of the inproc plugins work OOP.

@rneatherway
Copy link

On the subject of the F# plugin, what kind of context is provided for the type checking? Currently we use the MSBuild API to determine the type checking context given a .fsproj file. Is that handled similarly for C#?

@david-driscoll
Copy link
Member

The intent will be based on whatever the plugin needs / requires.

If it's in process, and you don't have access to the proper API, you can
bring in your own code. In process assemblies will just be Assembly Loaded.

Out of process, you have a bigger advantage, you can basically build
whatever you want. Then the OmniSharp server would essentially act as a
proxy for your plugin, piping information back and forth.

The current goal for out of process is to have a configuration file of some
sort that lets OmniSharp know how to start the process, then all
comunication would happen very similar to how OmniSharps stdio interface
works today. With OmniSharp shipping requests to your application over
stdin, and then your application shipping responses over stdout.

We will also have to revamp the project system, to give each plugin the
opportunity to publish that information to downstream editors.

On Wed, Sep 2, 2015 at 7:37 AM, Robin Neatherway notifications@github.com
wrote:

On the subject of the F# plugin, what kind of context is provided for the
type checking? Currently we use the MSBuild API to determine the type
checking context given a .fsproj file. Is that handled similarly for C#?


Reply to this email directly or view it on GitHub
#208 (comment)
.

@DustinCampbell
Copy link
Contributor

I'm glad to see this underway as well. Being able to tailor OmniSharp's set of plug-ins will be a huge win.

@DustinCampbell
Copy link
Contributor

Would love to chat further about this and figure out what needs to happen here. I can help out. Grab me on Jabbr.

@david-driscoll
Copy link
Member

@DustinCampbell I've got a Proof of concept PR @ #293

I'll be kicking around on jabber tonight, or ping me on twitter @david_blacklite if I'm not answering.

@markrendle
Copy link
Contributor

I'm hoping to provide database-driven Intellisense for Simple.Data.Core, so once there's some guidance/examples on how to create a plug-in, I'd love to prototype that.

@willl
Copy link
Member

willl commented Sep 30, 2016

@markrendle I think plugins are still a work in progress. @david-driscoll recently submitted a new PR for it #640.

@RichiCoder1
Copy link
Author

@david-driscoll boop. Would love to light up Cake

@david-driscoll
Copy link
Member

Closing, moving to epic to handle the overall requirements. #1029

jmbeach pushed a commit to jmbeach/omnisharp-roslyn that referenced this issue Dec 17, 2017
OmniSharp#183 Add checks before exporting functionality that requires python
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests