clariuslabs / clide Goto Github PK
View Code? Open in Web Editor NEWAn Enjoyable IDE Automation API
License: MIT License
An Enjoyable IDE Automation API
License: MIT License
Currently we just silently ignore errors like wrong package Guids and command ids.
Currently, they do not integrate with VS import/export settings capability.
We did a spike where this was tested, and it would require a new attribute at the package level at least. We could reuse a single IProfileManager implementation, I think.
Should trace useful information for authors leveraging clide.
Should be a custom toolwindow that allows filtering by source, setting the default tracing levels, etc.
There can only be one version of Clide exports in the VS global composition container.
We need to be diligent in informing users of wrongly configuring their VS MEF exports.
We should find a way to detect if the current package hosting Clide is attempting to expose its interfaces to the global container and fail with a meaningul error. Doing otherwise could bring random errors depending on what other extensions are installed that might also have made the same mistake.
Only the Clide official VSIX should be able to expose these interfaces globally.
Wiki page mentions "Take a look at the available how to code samples too." but couldn't find any sample.
Its great library however without good documentation or sample it looses all shine. It will be great if you could add some samples or some sample snippets.
I would like to do the equivalent of Unity's RegisterInstance with clide. Is this currently supported?
Currently we cache the managed nodes we create from the hierarchy, but we're not clearing that cache when the solution is closed. This is not serious since it would require long-running VS instances that open/close many solutions over time, which is not very typical VS usage.
But still, it should be done.
Modified IntegrationPackage\Adornment.cs:
[ExportMetadata("IsClide", true)]
[Export(typeof(IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
public sealed class TextAdornment1Factory : IWpfTextViewCreationListener
{
private IServiceProvider services;
[ImportingConstructor]
public TextAdornment1Factory([Import(Constants.ShellContractName)] IServiceProvider services, Foo foo)
{
this.services = services;
}
public void TextViewCreated(IWpfTextView textView)
{
Debug.Assert(Clide.DevEnv.Get(services) != null);
}
}
[Component] public class Foo { }
This seems to cause a silent failure - the Export is never loaded by Visual Studio. Is injecting components into visual studio extension points supported?
The Extensibility assembly is intended for advanced usage scenarios that will extend Clide itself.
This is currently just extending the solution nodes.
We don't bundle the assembly in Clide package, though. We should provide a Clide.Sdk with it.
Workaround for now is to reference it from the local machine installation, which now becomes an install dependency (since the same version or higher assembly will need to exist on the install target):
<Reference Include="Clide.Extensibility">
<HintPath>$(VsInstallRoot)\Common7\IDE\Extensions\Clide\Clide.Extensibility.dll</HintPath>
</Reference>
Probably with something like:
public override bool Accept(ISolutionVisitor visitor)
{
visitor.VisitEnter<ICustomNode>(this);
return visitor.VisitLeave<ICustomNode>(this);
}
Rather than just using the VSIX manifest, a custom attribute on the package/IServiceProvider class should be supported.
Currently, there's a single Clide version for everything. Some of the newer functionality (like #20 on async tasks) is supported natively by VS2012, but a backwards compatible version should be provided by Clide for VS2010.
This may happen more often in the future, as more APIs are leveraged by Clide. Not all APIs will have a corresponding backwards compatible implementation, btw.
This means that we need to solve two problems:
1 - Nuget packages, once installed, aren't dynamically referenced depending on any condition: there will be a single Clide.dll and optionally any supporting DLLs we ship with it. That single reference will have to know what version of VS is available and what version-specific supporting DLL to load.
2 - Composition might be leveraged for automatic wiring too, so maybe just bringing in Clide.10.dll vs Clide.12.dll would be enough? The challenge, however, is that Clide.11.dll and Clide.12.dll could share the same implementation (like the #20 already mentioned). Shared projects would be nice here, but we need to keep supporting VS2010 / .NET 4.0, so linked files might be our only choice there?
Clide current creates its own MEF catalog and container. This makes initialization of a Clide package slower than it otherwise could be.
If instead, Clide components registered themselves in their source.extension.vsixmanifest file as MEF assemblies, VS could cache the catalog and composition and achieve faster startup times for their users.
Hierarchical visitor pattern offers many advantages over the "plain" visitor pattern, especially for hierarchies.
Implement this for solution traversal.
On VS2012+, there are native APIs that return TaskScheduler instances for the various kinds of async work you might need to do:
http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.__vstaskruncontext.aspx
http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.ivstaskschedulerservice.aspx
The APIs are somewhat unfriendly (COM-ified) but should be wrapped by Clide, which should provide a clone of the underyling 2012+ functionality for 2010.
IDevEnv.Exit(bool saveAll = true)
If you have an IVsHierarchyItem
retrieved from the hierarchy manager,
you cannot convert it into a project node, even though it's just a matter
of invoking the node factory.
This should be exported and supported OOB.
Should return Task with success/fail result of the build. Should be a non-blocking build.
The way the CLR currently works means that if two extensions deploy:
if the extension deploying v1 is loaded first, code in the second extension that depends on v2 features will fail at runtime with an exception saying that the manifest of the loaded assembly doesn't match that of the referenced assembly (extension 2 expected Clide v2, but found v1 in the app domain).
In order to avoid this, custom assembly resolution can be added so that if there is a version mismatch, the custom assembly resolver gets called and has a chance to load the locally deployed version that the second extension has, v2. This way, if extension 1 gets loaded first, it will get Clide v1. When later on extension 2 gets loaded, the custom resolver gets called and we can load the Clide v2 assembly from its installation directory instead of reusing the previously loaded v1 which would fail.
If extensions are loaded the other way around, though, the CLR will not load the lower version afterwards, and the call to Assembly.LoadFrom will simply return the latest version loaded, which is fine as long as we keep strict backwards compatibility in Clide itself.
Currently we just load/save a flat list of settings, with complex properties only saved if they support a type converter to/from string.
It would be great to figure out a way to represent in the settings registry an object graph, so that we can have richer settings for extensions.
Thanks for this toolkit and the time invested on it.
On github there is another toolkit that helps in the development of Visual Studio extensions, Clide. It would be nice to merge the features of Community.VisualStudio.Toolkit and Clide.
We should buffer trace messages and log them when the IDE is idle.
I'm an engineer at Microsoft who works on Visual Studio. We are getting telemetry for VS 16.0.x indicating that the stack below is sometimes leading to thread pool starvation, which can cause UI delays or other performance issues.
The primary frame implicated appears to be Clide_Core!Clide.VsToSolutionAdapter.GetHierarchyItem(Microsoft.VisualStudio.Shell.Interop.IVsHierarchy.
ntdll!NtWaitForMultipleObjects
KERNELBASE!WaitForMultipleObjectsEx
clr!WaitForMultipleObjectsEx_SO_TOLERANT
clr!Thread::DoAppropriateAptStateWait
clr!Thread::DoAppropriateWaitWorker
clr!Thread::DoAppropriateWait
clr!CLREventBase::WaitEx
clr!CLREventBase::Wait
clr!Thread::Wait
clr!Thread::Block
clr!SyncBlock::Wait
clr!ObjHeader::Wait
clr!Object::Wait
clr!ObjectNative::WaitTimeout
mscorlib_ni!System.Threading.Monitor.Wait(System.Object, Int32, Boolean)
mscorlib_ni!System.Threading.Monitor.Wait(System.Object, Int32)
mscorlib_ni!System.Threading.ManualResetEventSlim.Wait(Int32, System.Threading.CancellationToken)
mscorlib_ni!System.Threading.Tasks.Task.SpinThenBlockingWait(Int32, System.Threading.CancellationToken)
mscorlib_ni!System.Threading.Tasks.Task.InternalWait(Int32, System.Threading.CancellationToken)
mscorlib_ni!System.Threading.Tasks.Task.Wait(Int32, System.Threading.CancellationToken)
mscorlib_ni!System.Threading.Tasks.Task.Wait(System.TimeSpan)
Microsoft_VisualStudio_Threading_ni!Microsoft.VisualStudio.Threading.JoinableTaskFactory.WaitSynchronouslyCore(System.Threading.Tasks.Task)
Microsoft_VisualStudio_Threading_ni!Microsoft.VisualStudio.Threading.JoinableTaskFactory.WaitSynchronously(System.Threading.Tasks.Task)
Microsoft_VisualStudio_Threading_ni!Microsoft.VisualStudio.Threading.JoinableTask.CompleteOnCurrentThread()
Clide_Core!Clide.VsToSolutionAdapter.GetHierarchyItem(Microsoft.VisualStudio.Shell.Interop.IVsHierarchy)
Clide_Core!Clide.VsToSolutionAdapter.Adapt(Microsoft.VisualStudio.Shell.Interop.IVsHierarchy)
Clide_Interfaces!AdapterFacade.AsProjectNode(Microsoft.VisualStudio.Shell.Interop.IVsHierarchy, Microsoft.VisualStudio.Shell.Interop.IVsHierarchy)
Xamarin_VisualStudio!Unknown
mscorlib_ni!System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.InvokeMoveNext(System.Object)
mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
mscorlib_ni!System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run()
Microsoft_VisualStudio_Threading_ni!Microsoft.VisualStudio.Threading.AwaitExtensions+TaskSchedulerAwaiter+<>c.b__5_0(System.Object)
mscorlib_ni!System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
mscorlib_ni!System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
mscorlib_ni!System.Threading.ThreadPoolWorkQueue.Dispatch()
mscorlib_ni!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
clr!CallDescrWorkerInternal
clr!CallDescrWorkerWithHandler
clr!MethodDescCallSite::CallTargetWorker
clr!MethodDescCallSite::Call_RetBool
clr!QueueUserWorkItemManagedCallback
clr!ManagedThreadBase_DispatchInner
clr!ManagedThreadBase_DispatchMiddle
clr!ManagedThreadBase_DispatchOuter
clr!ManagedThreadBase_FullTransitionWithAD
clr!ManagedThreadBase::ThreadPool
clr!ManagedPerAppDomainTPCount::DispatchWorkItem
clr!ThreadpoolMgr::ExecuteWorkRequest
clr!ThreadpoolMgr::WorkerThreadStart
clr!Thread::intermediateThreadProc
kernel32!BaseThreadInitThunk
ntdll!__RtlUserThreadStart
ntdll!_RtlUserThreadStart
Since the resolver must load before any custom resolution can be done, it should be a source package itself, since otherwise side-by-side versioning of this assembly would cause assembly load failures if other packages also have their own resolvers (since it would be too early to custom resolve itself!).
This allows multiple commands to use different built-in UIContext constraints, without requiring multiple classes that just inherit from each other for the actual implementation.
i.e.
class Deploy { }
[Command(.... )]
class DeployFromContextMenu : Deploy
[Command(....)]
class DeployFromToolbar : Deploy
This scenario is relevant since toolbar commands have by definition a visibility == true and would therefore turn on visibility of the command on every project. (say it's a Project context menu command).
For building and running all tests.
We need to split Clide.Interfaces from Clide.VisualStudio and Clide.XamarinStudio (eventually).
The nuget package can still be called Clide and include both interfaces and VS, whereas a Clide.XamarinStudio has interfaces + Xamarin implementation.
Clide should probably contain only the interfaces and be the only dependency that extensions take, so that they can be portable. The boostrapping extension mechanism should reference the additional Clide.VisualStudio|XamarinStudio and make the proper implementation available.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.