private async Task PopulateWorkspaceFromDeferredProjectInfoAsync( CancellationToken cancellationToken) { // NOTE: We need to check cancellationToken after each await, in case the user has // already closed the solution. AssertIsForeground(); var componentModel = _serviceProvider.GetService(typeof(SComponentModel)) as IComponentModel; var workspaceProjectContextFactory = componentModel.GetService <IWorkspaceProjectContextFactory>(); var dte = _serviceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var solutionConfig = (EnvDTE80.SolutionConfiguration2)dte.Solution.SolutionBuild.ActiveConfiguration; OutputToOutputWindow($"Getting project information - start"); var start = DateTimeOffset.UtcNow; var projectInfos = SpecializedCollections.EmptyReadOnlyDictionary <string, DeferredProjectInformation>(); // Note that `solutionConfig` may be null. For example: if the solution doesn't actually // contain any projects. if (solutionConfig != null) { // Capture the context so that we come back on the UI thread, and do the actual project creation there. var deferredProjectWorkspaceService = _workspaceServices.GetService <IDeferredProjectWorkspaceService>(); projectInfos = await deferredProjectWorkspaceService.GetDeferredProjectInfoForConfigurationAsync( $"{solutionConfig.Name}|{solutionConfig.PlatformName}", cancellationToken).ConfigureAwait(true); } AssertIsForeground(); cancellationToken.ThrowIfCancellationRequested(); OutputToOutputWindow($"Getting project information - done (took {DateTimeOffset.UtcNow - start})"); OutputToOutputWindow($"Creating projects - start"); start = DateTimeOffset.UtcNow; var targetPathsToProjectPaths = BuildTargetPathMap(projectInfos); var analyzerAssemblyLoader = _workspaceServices.GetRequiredService <IAnalyzerService>().GetLoader(); foreach (var projectFilename in projectInfos.Keys) { cancellationToken.ThrowIfCancellationRequested(); GetOrCreateProjectFromArgumentsAndReferences( workspaceProjectContextFactory, analyzerAssemblyLoader, projectFilename, projectInfos, targetPathsToProjectPaths); } OutputToOutputWindow($"Creating projects - done (took {DateTimeOffset.UtcNow - start})"); OutputToOutputWindow($"Pushing to workspace - start"); start = DateTimeOffset.UtcNow; FinishLoad(); OutputToOutputWindow($"Pushing to workspace - done (took {DateTimeOffset.UtcNow - start})"); }
private async Task <ActiveStatementsMap> GetBaseActiveStatementsAsync(CancellationToken cancellationToken) { try { return(CreateActiveStatementsMap(_baseSolution, await _activeStatementProvider.GetActiveStatementsAsync(cancellationToken).ConfigureAwait(false))); } catch (Exception e) when(FatalError.ReportWithoutCrashUnlessCanceled(e)) { return(new ActiveStatementsMap( SpecializedCollections.EmptyReadOnlyDictionary <DocumentId, ImmutableArray <ActiveStatement> >(), SpecializedCollections.EmptyReadOnlyDictionary <ActiveInstructionId, ActiveStatement>())); } }
private async Task PopulateWorkspaceFromDeferredProjectInfoAsync( CancellationToken cancellationToken) { // NOTE: We need to check cancellationToken after each await, in case the user has // already closed the solution. AssertIsForeground(); var start = DateTimeOffset.UtcNow; var dte = _serviceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var solutionConfig = (EnvDTE80.SolutionConfiguration2)dte.Solution.SolutionBuild.ActiveConfiguration; OutputToOutputWindow($"Getting project information - start"); var projectInfos = SpecializedCollections.EmptyReadOnlyDictionary <string, DeferredProjectInformation>(); // Note that `solutionConfig` may be null. For example: if the solution doesn't actually // contain any projects. if (solutionConfig != null) { // Capture the context so that we come back on the UI thread, and do the actual project creation there. var deferredProjectWorkspaceService = _workspaceServices.GetService <IDeferredProjectWorkspaceService>(); projectInfos = await deferredProjectWorkspaceService.GetDeferredProjectInfoForConfigurationAsync( $"{solutionConfig.Name}|{solutionConfig.PlatformName}", cancellationToken).ConfigureAwait(true); } AssertIsForeground(); cancellationToken.ThrowIfCancellationRequested(); OutputToOutputWindow($"Getting project information - done (took {DateTimeOffset.UtcNow - start})"); ForceLoadProjectsWhoseDesignTimeBuildFailed(projectInfos); CreateDeferredProjects(projectInfos, cancellationToken); CallWithTimingLog("Pushing to workspace", FinishLoad); }
/// <summary> /// Calculate the set of changes up to top-level types. The result /// will be used as a filter when traversing the module. /// /// Note that these changes only include user-defined source symbols, not synthesized symbols since those will be /// generated during lowering of the changed user-defined symbols. /// </summary> private static void CalculateChanges(IEnumerable <SemanticEdit> edits, out IReadOnlyDictionary <ISymbol, SymbolChange> changes, out ISet <ISymbol> replaceSymbols, out IReadOnlyDictionary <ISymbol, ISet <ISymbol> > deletedMembers) { var changesBuilder = new Dictionary <ISymbol, SymbolChange>(); HashSet <ISymbol>?lazyReplaceSymbolsBuilder = null; Dictionary <ISymbol, ISet <ISymbol> >?lazyDeletedMembersBuilder = null; foreach (var edit in edits) { SymbolChange change; switch (edit.Kind) { case SemanticEditKind.Update: change = SymbolChange.Updated; break; case SemanticEditKind.Insert: change = SymbolChange.Added; break; case SemanticEditKind.Replace: Debug.Assert(edit.NewSymbol != null); (lazyReplaceSymbolsBuilder ??= new HashSet <ISymbol>()).Add(edit.NewSymbol); change = SymbolChange.Added; break; case SemanticEditKind.Delete: // We allow method deletions only at the moment. // For deletions NewSymbol is actually containing symbol if (edit.OldSymbol is IMethodSymbol && edit.NewSymbol is { } newContainingSymbol) { Debug.Assert(edit.OldSymbol != null); lazyDeletedMembersBuilder ??= new(); if (!lazyDeletedMembersBuilder.TryGetValue(newContainingSymbol, out var set)) { set = new HashSet <ISymbol>(); lazyDeletedMembersBuilder.Add(newContainingSymbol, set); } set.Add(edit.OldSymbol); // We need to make sure we track the containing type of the member being // deleted, from the new compilation, in case the deletion is the only change. if (!changesBuilder.ContainsKey(newContainingSymbol)) { changesBuilder.Add(newContainingSymbol, SymbolChange.ContainsChanges); AddContainingTypesAndNamespaces(changesBuilder, newContainingSymbol); } } continue; default: throw ExceptionUtilities.UnexpectedValue(edit.Kind); } var member = edit.NewSymbol; RoslynDebug.AssertNotNull(member); // Partial methods are supplied as implementations but recorded // internally as definitions since definitions are used in emit. if (member.Kind == SymbolKind.Method) { var method = (IMethodSymbol)member; // Partial methods should be implementations, not definitions. Debug.Assert(method.PartialImplementationPart == null); Debug.Assert((edit.OldSymbol == null) || (((IMethodSymbol)edit.OldSymbol).PartialImplementationPart == null)); var definitionPart = method.PartialDefinitionPart; if (definitionPart != null) { member = definitionPart; } } AddContainingTypesAndNamespaces(changesBuilder, member); changesBuilder.Add(member, change); } changes = changesBuilder; replaceSymbols = lazyReplaceSymbolsBuilder ?? SpecializedCollections.EmptySet <ISymbol>(); deletedMembers = lazyDeletedMembersBuilder ?? SpecializedCollections.EmptyReadOnlyDictionary <ISymbol, ISet <ISymbol> >(); }