Skip to content

Commit

Permalink
Run solution crawler on source generated documents that change
Browse files Browse the repository at this point in the history
  • Loading branch information
sharwell committed Feb 3, 2022
1 parent 49170ce commit 4be55f5
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,14 @@ protected Task<TestLspServer> CreateTestLspServerAsync(string[] markups, string[

private Task<TestLspServer> CreateTestLspServerAsync(string[] markups, string[] sourceGeneratedMarkups, string languageName)
{
var exportProvider = Composition.ExportProviderFactory.CreateExportProvider();
var globalOptions = exportProvider.GetExportedValue<IGlobalOptionService>();
globalOptions.SetGlobalOption(new OptionKey(WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspace), true);

var workspace = languageName switch
{
LanguageNames.CSharp => TestWorkspace.CreateCSharp(markups, sourceGeneratedMarkups, composition: Composition),
LanguageNames.VisualBasic => TestWorkspace.CreateVisualBasic(markups, sourceGeneratedMarkups, composition: Composition),
LanguageNames.CSharp => TestWorkspace.CreateCSharp(markups, sourceGeneratedMarkups, exportProvider: exportProvider),
LanguageNames.VisualBasic => TestWorkspace.CreateVisualBasic(markups, sourceGeneratedMarkups, exportProvider: exportProvider),
_ => throw new ArgumentException($"language name {languageName} is not valid for a test workspace"),
};

Expand Down
38 changes: 38 additions & 0 deletions src/Features/Core/Portable/SolutionCrawler/WorkCoordinator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Roslyn.Utilities;

Expand Down Expand Up @@ -434,6 +435,37 @@ private void EnqueueDocumentChangedEvent(Solution oldSolution, Solution newSolut
var newProject = newSolution.GetRequiredProject(documentId.ProjectId);

await EnqueueChangedDocumentWorkItemAsync(oldProject.GetRequiredDocument(documentId), newProject.GetRequiredDocument(documentId)).ConfigureAwait(false);

if (WorkspaceConfigurationOptions.ShouldConnectSourceGeneratedFilesToWorkspace(newSolution.Options))
{
var oldProjectSourceGeneratedDocuments = await oldProject.GetSourceGeneratedDocumentsAsync(_shutdownToken).ConfigureAwait(false);
var oldProjectSourceGeneratedDocumentsById = oldProjectSourceGeneratedDocuments.ToDictionary(static document => document.Id);
var newProjectSourceGeneratedDocuments = await newProject.GetSourceGeneratedDocumentsAsync(_shutdownToken).ConfigureAwait(false);
var newProjectSourceGeneratedDocumentsById = newProjectSourceGeneratedDocuments.ToDictionary(static document => document.Id);

foreach (var (oldDocumentId, _) in oldProjectSourceGeneratedDocumentsById)
{
if (!newProjectSourceGeneratedDocumentsById.ContainsKey(oldDocumentId))
{
// This source generated document was removed
EnqueueFullDocumentEvent(oldSolution, oldDocumentId, InvocationReasons.DocumentRemoved, "OnWorkspaceChanged");
}
}

foreach (var (newDocumentId, newDocument) in newProjectSourceGeneratedDocumentsById)
{
if (!oldProjectSourceGeneratedDocumentsById.TryGetValue(newDocumentId, out var oldDocument))
{
// This source generated document was added
EnqueueFullDocumentEvent(newSolution, newDocumentId, InvocationReasons.DocumentAdded, "OnWorkspaceChanged");
}
else
{
// This source generated document may have changed
await EnqueueChangedDocumentWorkItemAsync(oldDocument, newDocument).ConfigureAwait(continueOnCapturedContext: false);
}
}
}
},
_shutdownToken);
}
Expand Down Expand Up @@ -487,6 +519,12 @@ private async Task EnqueueFullProjectWorkItemAsync(Project project, InvocationRe

foreach (var documentId in project.AnalyzerConfigDocumentIds)
await EnqueueDocumentWorkItemAsync(project, documentId, document: null, invocationReasons).ConfigureAwait(false);

if (WorkspaceConfigurationOptions.ShouldConnectSourceGeneratedFilesToWorkspace(project.Solution.Options))
{
foreach (var document in await project.GetSourceGeneratedDocumentsAsync(_shutdownToken).ConfigureAwait(false))
await EnqueueDocumentWorkItemAsync(project, document.Id, document, invocationReasons).ConfigureAwait(false);
}
}

private async Task EnqueueWorkItemAsync(IIncrementalAnalyzer analyzer, ReanalyzeScope scope, bool highPriority)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ public AdvancedOptionPageControl(OptionStore optionStore, IComponentModel compon

BindToOption(RenameTrackingPreview, FeatureOnOffOptions.RenameTrackingPreview, LanguageNames.CSharp);
BindToOption(Underline_reassigned_variables, ClassificationOptions.Metadata.ClassifyReassignedVariables, LanguageNames.CSharp);
BindToOption(Enable_all_features_in_opened_files_from_source_generators, SourceGeneratedFileManager.Options.EnableOpeningInWorkspace, () =>
BindToOption(Enable_all_features_in_opened_files_from_source_generators, WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspace, () =>
{
// If the option has not been set by the user, check if the option is enabled from experimentation.
// If so, default to that.
return optionStore.GetOption(SourceGeneratedFileManager.Options.EnableOpeningInWorkspaceFeatureFlag);
return optionStore.GetOption(WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag);
});

BindToOption(DontPutOutOrRefOnStruct, ExtractMethodOptions.DontPutOutOrRefOnStruct, LanguageNames.CSharp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,7 @@ public async ValueTask RefreshFileAsync(CancellationToken cancellationToken)

// If the file isn't already open, open it now. We may transition between opening and closing
// if the file is repeatedly appearing and disappearing.
var connectToWorkspace = _workspace.Options.GetOption(Options.EnableOpeningInWorkspace) ??
_workspace.Options.GetOption(Options.EnableOpeningInWorkspaceFeatureFlag);
var connectToWorkspace = WorkspaceConfigurationOptions.ShouldConnectSourceGeneratedFilesToWorkspace(_workspace.Options);

if (connectToWorkspace && !_workspace.IsDocumentOpen(_documentIdentity.DocumentId))
{
Expand Down Expand Up @@ -505,31 +504,5 @@ public void NavigateToSpan(TextSpan sourceSpan, CancellationToken cancellationTo
_fileManager._visualStudioDocumentNavigationService.NavigateTo(_textBuffer, sourceText.GetVsTextSpanForSpan(sourceSpan), cancellationToken);
}
}

[Export(typeof(IOptionProvider))]
internal sealed class Options : IOptionProvider
{
private const string FeatureName = "SourceGeneratedFileManager";

/// <summary>
/// This option allows the user to enable this. We are putting this behind a feature flag for now since we could have extensions
/// surprised by this and we want some time to work through those issues.
/// </summary>
internal static readonly Option2<bool?> EnableOpeningInWorkspace = new(FeatureName, nameof(EnableOpeningInWorkspace), defaultValue: null,
new RoamingProfileStorageLocation("TextEditor.Roslyn.Specific.EnableOpeningSourceGeneratedFilesInWorkspaceExperiment"));

internal static readonly Option2<bool> EnableOpeningInWorkspaceFeatureFlag = new(FeatureName, nameof(EnableOpeningInWorkspaceFeatureFlag), defaultValue: false,
new FeatureFlagStorageLocation("Roslyn.SourceGeneratorsEnableOpeningInWorkspace"));

ImmutableArray<IOption> IOptionProvider.Options => ImmutableArray.Create<IOption>(
EnableOpeningInWorkspace,
EnableOpeningInWorkspaceFeatureFlag);

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
public Options()
{
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ public void SetFileScopedNamespaces(bool value)
public void SetEnableOpeningSourceGeneratedFilesInWorkspaceExperiment(bool value)
{
SetOption(
optionName: LanguageServices.Implementation.SourceGeneratedFileManager.Options.EnableOpeningInWorkspace.Name,
feature: LanguageServices.Implementation.SourceGeneratedFileManager.Options.EnableOpeningInWorkspace.Feature,
optionName: WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspace.Name,
feature: WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspace.Feature,
value: value);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,10 @@ Namespace Microsoft.VisualStudio.LanguageServices.VisualBasic.Options

' Go To Definition
BindToOption(NavigateToObjectBrowser, VisualStudioNavigationOptions.NavigateToObjectBrowser, LanguageNames.VisualBasic)
BindToOption(Enable_all_features_in_opened_files_from_source_generators, SourceGeneratedFileManager.Options.EnableOpeningInWorkspace,
BindToOption(Enable_all_features_in_opened_files_from_source_generators, WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspace,
Function()
' If the option has Not been set by the user, check if the option is enabled from experimentation.
Return optionStore.GetOption(SourceGeneratedFileManager.Options.EnableOpeningInWorkspaceFeatureFlag)
Return optionStore.GetOption(WorkspaceConfigurationOptions.EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag)
End Function)

' Regular expressions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,27 @@ internal class WorkspaceConfigurationOptions : IOptionProvider
nameof(WorkspaceConfigurationOptions), nameof(DisableProjectCacheService), defaultValue: false,
new FeatureFlagStorageLocation("Roslyn.DisableProjectCacheService"));

/// <summary>
/// This option allows the user to enable this. We are putting this behind a feature flag for now since we could have extensions
/// surprised by this and we want some time to work through those issues.
/// </summary>
internal static readonly Option2<bool?> EnableOpeningSourceGeneratedFilesInWorkspace = new("SourceGeneratedFileManager", "EnableOpeningInWorkspace", defaultValue: null,
new RoamingProfileStorageLocation("TextEditor.Roslyn.Specific.EnableOpeningSourceGeneratedFilesInWorkspaceExperiment"));

internal static readonly Option2<bool> EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag = new("SourceGeneratedFileManager", "EnableOpeningInWorkspaceFeatureFlag", defaultValue: false,
new FeatureFlagStorageLocation("Roslyn.SourceGeneratorsEnableOpeningInWorkspace"));

internal static bool ShouldConnectSourceGeneratedFilesToWorkspace(OptionSet options)
{
return options.GetOption(EnableOpeningSourceGeneratedFilesInWorkspace) ??
options.GetOption(EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag);
}

ImmutableArray<IOption> IOptionProvider.Options { get; } = ImmutableArray.Create<IOption>(
DisableRecoverableTrees,
DisableProjectCacheService);
DisableProjectCacheService,
EnableOpeningSourceGeneratedFilesInWorkspace,
EnableOpeningSourceGeneratedFilesInWorkspaceFeatureFlag);

[ImportingConstructor]
[Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
Expand Down

0 comments on commit 4be55f5

Please sign in to comment.