/// <summary> /// Handles the <see cref="IActiveConfiguredProjectSubscriptionService"/> callback on the active configured project's /// design-time build change notification service. /// </summary> private async Task ProjectBuildRuleBlock_ChangedAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> e) { await ThreadingService.SwitchToUIThread(); using (ProjectAsynchronousTasksService.LoadedProject()) { foreach (var resolvedReferenceChange in e.Value.ProjectChanges.Values) { if (!WatchedDesignTimeBuildRules.Contains(resolvedReferenceChange.After.RuleName)) { // This is an evaluation rule. continue; } foreach (string resolvedReferencePath in resolvedReferenceChange.Difference.AddedItems) { // If this is a resolved project reference, we need to treat it specially. string originalItemSpec = resolvedReferenceChange.After.Items[resolvedReferencePath]["OriginalItemSpec"]; if (!string.IsNullOrEmpty(originalItemSpec)) { if (e.Value.CurrentState[ProjectReference.SchemaName].Items.ContainsKey(originalItemSpec)) { string originalFullPath = UnconfiguredProject.MakeRooted(originalItemSpec); ProjectReferenceState state; if (!_projectReferenceFullPaths.TryGetValue(originalFullPath, out state)) { _projectReferenceFullPaths = _projectReferenceFullPaths.Add(originalFullPath, state = new ProjectReferenceState()); } state.ResolvedPath = resolvedReferencePath; // Be careful to not add assembly references that overlap with project references. if (state.AsProjectReference) { continue; } } } Marshal.ThrowExceptionForHR(_intellisenseEngine.AddAssemblyReference(resolvedReferencePath)); } foreach (string resolvedReferencePath in resolvedReferenceChange.Difference.RemovedItems) { Marshal.ThrowExceptionForHR(_intellisenseEngine.RemoveAssemblyReference(resolvedReferencePath)); } Marshal.ThrowExceptionForHR(_intellisenseEngine.StartIntellisenseEngine()); } } }
/// <summary> /// Invoked when the UnconfiguredProject is first loaded to initialize language services. /// </summary> protected async Task InitializeAsync() { ProjectAsynchronousTasksService.UnloadCancellationToken.ThrowIfCancellationRequested(); // Don't start until the project has been loaded as far as the IDE is concerned. #pragma warning disable CA2007 // Do not directly await a Task (see https://github.com/dotnet/roslyn/issues/6770) await ProjectAsyncLoadDashboard.ProjectLoadedInHost; #pragma warning restore CA2007 // Do not directly await a Task // Defer this work until VS has idle time. Otherwise we'll block the UI thread to load the MSBuild project evaluation // during synchronous project load time. await ThreadHelper.JoinableTaskFactory.RunAsync( VsTaskRunContext.UIThreadBackgroundPriority, async delegate { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); await Task.Yield(); using (ProjectAsynchronousTasksService.LoadedProject()) { // hack to ensure webproj package is properly sited, by forcing it to load with a QueryService call for // one of the services it implements. var tmpObj = Package.GetGlobalService(typeof(SWebApplicationCtxSvc)) as IWebApplicationCtxSvc; Report.IfNotPresent(tmpObj); if (tmpObj == null) { return; } // Create the Intellisense engine for C# var registry = ServiceProvider.GetService(typeof(SLocalRegistry)) as ILocalRegistry3; Assumes.Present(registry); IntPtr pIntellisenseEngine = IntPtr.Zero; try { Marshal.ThrowExceptionForHR(registry.CreateInstance( IntelliSenseProviderGuid, null, typeof(IVsIntellisenseProject).GUID, (uint)CLSCTX.CLSCTX_INPROC_SERVER, out pIntellisenseEngine)); _intellisenseEngine = Marshal.GetObjectForIUnknown(pIntellisenseEngine) as IVsIntellisenseProject; } finally { if (pIntellisenseEngine != IntPtr.Zero) { Marshal.Release(pIntellisenseEngine); } } Marshal.ThrowExceptionForHR(_intellisenseEngine.Init(this)); #pragma warning disable CA2007 // Do not directly await a Task (see https://github.com/dotnet/roslyn/issues/6770) await LanguageServiceRegister.RegisterProjectAsync(this); #pragma warning restore CA2007 // Do not directly await a Task } }); // The rest of this can execute on a worker thread. await TaskScheduler.Default; using (ProjectAsynchronousTasksService.LoadedProject()) { var designTimeBuildBlock = new ActionBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> >( ProjectBuildRuleBlock_ChangedAsync); _designTimeBuildSubscriptionLink = ActiveConfiguredProjectSubscriptionService.JointRuleSource.SourceBlock.LinkTo( designTimeBuildBlock, ruleNames: WatchedEvaluationRules.Union(WatchedDesignTimeBuildRules)); var evaluationBlock = new ActionBlock <IProjectVersionedValue <IProjectSubscriptionUpdate> >( ProjectRuleBlock_ChangedAsync); _evaluationSubscriptionLink = ActiveConfiguredProjectSubscriptionService.JointRuleSource.SourceBlock.LinkTo( evaluationBlock, ruleNames: WatchedEvaluationRules); } }