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 Solution.WithProjectInfo API #74289

Merged
merged 3 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ public void EndSession()
_sessionId = default;
}

// access to internal API:
public static Solution WithProjectInfo(Solution solution, ProjectInfo info)
=> solution.WithProjectInfo(info);

internal TestAccessor GetTestAccessor()
=> new(this);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -991,7 +991,7 @@ static string GetStyledText(TaggedText taggedText, bool isInCodeBlock)
return null;
}

var spanMappingService = document.Services.GetService<ISpanMappingService>();
var spanMappingService = document.DocumentServiceProvider.GetService<ISpanMappingService>();
CyrusNajmabadi marked this conversation as resolved.
Show resolved Hide resolved
if (spanMappingService == null)
{
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private async Task<ImmutableArray<ReferenceLocationDescriptor>> FixUpDescriptors
continue;
}

var spanMapper = document.Services.GetService<ISpanMappingService>();
var spanMapper = document.DocumentServiceProvider.GetService<ISpanMappingService>();
if (spanMapper == null)
{
// for normal document, just add one as they are
Expand All @@ -173,7 +173,7 @@ private async Task<ImmutableArray<ReferenceLocationDescriptor>> FixUpDescriptors
continue;
}

var excerpter = document.Services.GetService<IDocumentExcerptService>();
var excerpter = document.DocumentServiceProvider.GetService<IDocumentExcerptService>();
if (excerpter == null)
{
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ protected async Task AddDocumentSpanEntriesAsync(
var document = documentSpan.Document;
var sourceSpan = documentSpan.SourceSpan;

var excerptService = document.Services.GetService<IDocumentExcerptService>();
var excerptService = document.DocumentServiceProvider.GetService<IDocumentExcerptService>();

// Fetching options is expensive enough to try to avoid it if we can. So only fetch this if absolutely necessary.
ClassificationOptions? options = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ await documentNavigationService.TryNavigateToSpanAsync(

public static async Task<MappedSpanResult?> TryMapAndGetFirstAsync(DocumentSpan documentSpan, SourceText sourceText, CancellationToken cancellationToken)
{
var service = documentSpan.Document.Services.GetService<ISpanMappingService>();
var service = documentSpan.Document.DocumentServiceProvider.GetService<ISpanMappingService>();
if (service == null)
{
return new MappedSpanResult(documentSpan.Document.FilePath, sourceText.Lines.GetLinePositionSpan(documentSpan.SourceSpan), documentSpan.SourceSpan);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ private DisposableToolTip CreateDisposableToolTip(Document document, TextSpan so
var controlService = document.Project.Solution.Services.GetRequiredService<IContentControlService>();
var sourceText = document.GetTextSynchronously(CancellationToken.None);

var excerptService = document.Services.GetService<IDocumentExcerptService>();
var excerptService = document.DocumentServiceProvider.GetService<IDocumentExcerptService>();
if (excerptService != null)
{
var classificationOptions = Presenter._globalOptions.GetClassificationOptions(document.Project.Language);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ internal override void ApplyMappedFileChanges(SolutionChanges solutionChanges)

bool ShouldApplyChangesToMappedDocuments(CodeAnalysis.Document document, [NotNullWhen(true)] out ISpanMappingService? spanMappingService)
{
spanMappingService = document.Services.GetService<ISpanMappingService>();
spanMappingService = document.DocumentServiceProvider.GetService<ISpanMappingService>();
// Only consider files that are mapped and that we are unable to apply changes to.
// TODO - refactor how this is determined - https://github.com/dotnet/roslyn/issues/47908
return spanMappingService != null && document?.CanApplyChange() == false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ static VsTextSpan GetVsTextSpan(SourceText text, int position, int virtualSpace)
}

// Before attempting to open the document, check if the location maps to a different file that should be opened instead.
var spanMappingService = document.Services.GetService<ISpanMappingService>();
var spanMappingService = document.DocumentServiceProvider.GetService<ISpanMappingService>();
if (spanMappingService != null)
{
var mappedSpan = await GetMappedSpanAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public static DiagnosticData Create(Diagnostic diagnostic, TextDocument document
var additionalLocations = GetAdditionalLocations(document, diagnostic);
var additionalProperties = GetAdditionalProperties(document, diagnostic);

var documentPropertiesService = document.Services.GetService<DocumentPropertiesService>();
var documentPropertiesService = document.DocumentServiceProvider.GetService<DocumentPropertiesService>();
var diagnosticsLspClientName = documentPropertiesService?.DiagnosticsLspClientName;

if (diagnosticsLspClientName != null)
Expand Down
2 changes: 1 addition & 1 deletion src/Workspaces/Core/Portable/Rename/Renamer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public static async Task<RenameDocumentActionSet> RenameDocumentAsync(
if (document == null)
throw new ArgumentNullException(nameof(document));

if (document.Services.GetService<ISpanMappingService>() != null)
if (document.DocumentServiceProvider.GetService<ISpanMappingService>() != null)
{
// Don't advertise that we can file rename generated documents that map to a different file.
return new RenameDocumentActionSet([], document.Id, document.Name, [.. document.Folders], options);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public AdditionalDocumentState(
SolutionServices solutionServices,
DocumentInfo documentInfo,
LoadTextOptions loadTextOptions)
: this(solutionServices, documentInfo.DocumentServiceProvider, documentInfo.Attributes, CreateTextAndVersionSource(solutionServices, documentInfo, loadTextOptions), loadTextOptions)
: this(solutionServices, documentInfo.DocumentServiceProvider, documentInfo.Attributes, CreateTextAndVersionSource(solutionServices, documentInfo.TextLoader, documentInfo.FilePath, loadTextOptions), loadTextOptions)
{
}

Expand All @@ -39,6 +39,14 @@ protected override TextDocumentState UpdateAttributes(DocumentInfo.DocumentAttri
TextAndVersionSource,
LoadTextOptions);

protected override TextDocumentState UpdateDocumentServiceProvider(IDocumentServiceProvider? newProvider)
tmat marked this conversation as resolved.
Show resolved Hide resolved
=> new AdditionalDocumentState(
SolutionServices,
newProvider,
Attributes,
TextAndVersionSource,
LoadTextOptions);

public new AdditionalDocumentState UpdateText(TextLoader loader, PreservationMode mode)
=> (AdditionalDocumentState)base.UpdateText(loader, mode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public AnalyzerConfigDocumentState(
SolutionServices solutionServices,
DocumentInfo documentInfo,
LoadTextOptions loadTextOptions)
: this(solutionServices, documentInfo.DocumentServiceProvider, documentInfo.Attributes, CreateTextAndVersionSource(solutionServices, documentInfo, loadTextOptions), loadTextOptions)
: this(solutionServices, documentInfo.DocumentServiceProvider, documentInfo.Attributes, CreateTextAndVersionSource(solutionServices, documentInfo.TextLoader, documentInfo.FilePath, loadTextOptions), loadTextOptions)
{
}

Expand All @@ -47,6 +47,16 @@ protected override TextDocumentState UpdateAttributes(DocumentInfo.DocumentAttri
// Reuse parsed config unless the path changed:
Attributes.FilePath == newAttributes.FilePath ? _lazyAnalyzerConfig : null);

protected override TextDocumentState UpdateDocumentServiceProvider(IDocumentServiceProvider? newProvider)
=> new AnalyzerConfigDocumentState(
SolutionServices,
DocumentServiceProvider,
Attributes,
TextAndVersionSource,
LoadTextOptions,
// Reuse parsed config:
_lazyAnalyzerConfig);

public new AnalyzerConfigDocumentState UpdateText(TextLoader loader, PreservationMode mode)
=> (AnalyzerConfigDocumentState)base.UpdateText(loader, mode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static DocumentState Create(
ParseOptions? options,
LoadTextOptions loadTextOptions)
{
var textSource = CreateTextAndVersionSource(languageServices.SolutionServices, info, loadTextOptions);
var textSource = CreateTextAndVersionSource(languageServices.SolutionServices, info.TextLoader, info.FilePath, loadTextOptions);

// If this is document that doesn't support syntax, then don't even bother holding
// onto any tree source. It will never be used to get a tree, and can only hurt us
Expand Down Expand Up @@ -430,6 +430,16 @@ protected override TextDocumentState UpdateAttributes(DocumentInfo.DocumentAttri
newTreeSource);
}

protected override TextDocumentState UpdateDocumentServiceProvider(IDocumentServiceProvider? newProvider)
=> new DocumentState(
LanguageServices,
newProvider,
Attributes,
TextAndVersionSource,
LoadTextOptions,
ParseOptions,
TreeSource);

public new DocumentState WithAttributes(DocumentInfo.DocumentAttributes newAttributes)
=> (DocumentState)base.WithAttributes(newAttributes);

Expand Down
45 changes: 26 additions & 19 deletions src/Workspaces/Core/Portable/Workspace/Solution/Project.cs
Original file line number Diff line number Diff line change
Expand Up @@ -573,106 +573,113 @@ internal Task<Checksum> GetDependentChecksumAsync(CancellationToken cancellation
/// Creates a new instance of this project updated to have the new assembly name.
/// </summary>
public Project WithAssemblyName(string assemblyName)
=> this.Solution.WithProjectAssemblyName(this.Id, assemblyName).GetProject(this.Id)!;
=> this.Solution.WithProjectAssemblyName(this.Id, assemblyName).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to have the new default namespace.
/// </summary>
public Project WithDefaultNamespace(string defaultNamespace)
=> this.Solution.WithProjectDefaultNamespace(this.Id, defaultNamespace).GetProject(this.Id)!;
=> this.Solution.WithProjectDefaultNamespace(this.Id, defaultNamespace).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to have the specified compilation options.
/// </summary>
public Project WithCompilationOptions(CompilationOptions options)
=> this.Solution.WithProjectCompilationOptions(this.Id, options).GetProject(this.Id)!;
=> this.Solution.WithProjectCompilationOptions(this.Id, options).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to have the specified parse options.
/// </summary>
public Project WithParseOptions(ParseOptions options)
=> this.Solution.WithProjectParseOptions(this.Id, options).GetProject(this.Id)!;
=> this.Solution.WithProjectParseOptions(this.Id, options).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to include the specified project reference
/// in addition to already existing ones.
/// </summary>
public Project AddProjectReference(ProjectReference projectReference)
=> this.Solution.AddProjectReference(this.Id, projectReference).GetProject(this.Id)!;
=> this.Solution.AddProjectReference(this.Id, projectReference).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to include the specified project references
/// in addition to already existing ones.
/// </summary>
public Project AddProjectReferences(IEnumerable<ProjectReference> projectReferences)
=> this.Solution.AddProjectReferences(this.Id, projectReferences).GetProject(this.Id)!;
=> this.Solution.AddProjectReferences(this.Id, projectReferences).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to no longer include the specified project reference.
/// </summary>
public Project RemoveProjectReference(ProjectReference projectReference)
=> this.Solution.RemoveProjectReference(this.Id, projectReference).GetProject(this.Id)!;
=> this.Solution.RemoveProjectReference(this.Id, projectReference).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to replace existing project references
/// with the specified ones.
/// </summary>
public Project WithProjectReferences(IEnumerable<ProjectReference> projectReferences)
=> this.Solution.WithProjectReferences(this.Id, projectReferences).GetProject(this.Id)!;
=> this.Solution.WithProjectReferences(this.Id, projectReferences).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to include the specified metadata reference
/// in addition to already existing ones.
/// </summary>
public Project AddMetadataReference(MetadataReference metadataReference)
=> this.Solution.AddMetadataReference(this.Id, metadataReference).GetProject(this.Id)!;
=> this.Solution.AddMetadataReference(this.Id, metadataReference).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to include the specified metadata references
/// in addition to already existing ones.
/// </summary>
public Project AddMetadataReferences(IEnumerable<MetadataReference> metadataReferences)
=> this.Solution.AddMetadataReferences(this.Id, metadataReferences).GetProject(this.Id)!;
=> this.Solution.AddMetadataReferences(this.Id, metadataReferences).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to no longer include the specified metadata reference.
/// </summary>
public Project RemoveMetadataReference(MetadataReference metadataReference)
=> this.Solution.RemoveMetadataReference(this.Id, metadataReference).GetProject(this.Id)!;
=> this.Solution.RemoveMetadataReference(this.Id, metadataReference).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to replace existing metadata reference
/// with the specified ones.
/// </summary>
public Project WithMetadataReferences(IEnumerable<MetadataReference> metadataReferences)
=> this.Solution.WithProjectMetadataReferences(this.Id, metadataReferences).GetProject(this.Id)!;
=> this.Solution.WithProjectMetadataReferences(this.Id, metadataReferences).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to include the specified analyzer reference
/// in addition to already existing ones.
/// </summary>
public Project AddAnalyzerReference(AnalyzerReference analyzerReference)
=> this.Solution.AddAnalyzerReference(this.Id, analyzerReference).GetProject(this.Id)!;
=> this.Solution.AddAnalyzerReference(this.Id, analyzerReference).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to include the specified analyzer references
/// in addition to already existing ones.
/// </summary>
public Project AddAnalyzerReferences(IEnumerable<AnalyzerReference> analyzerReferences)
=> this.Solution.AddAnalyzerReferences(this.Id, analyzerReferences).GetProject(this.Id)!;
=> this.Solution.AddAnalyzerReferences(this.Id, analyzerReferences).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to no longer include the specified analyzer reference.
/// </summary>
public Project RemoveAnalyzerReference(AnalyzerReference analyzerReference)
=> this.Solution.RemoveAnalyzerReference(this.Id, analyzerReference).GetProject(this.Id)!;
=> this.Solution.RemoveAnalyzerReference(this.Id, analyzerReference).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to replace existing analyzer references
/// with the specified ones.
/// </summary>
public Project WithAnalyzerReferences(IEnumerable<AnalyzerReference> analyzerReferencs)
=> this.Solution.WithProjectAnalyzerReferences(this.Id, analyzerReferencs).GetProject(this.Id)!;
=> this.Solution.WithProjectAnalyzerReferences(this.Id, analyzerReferencs).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to replace existing analyzer references
/// with the specified ones.
/// </summary>
internal Project WithAttributes(ProjectInfo.ProjectAttributes attributes)
=> Solution.WithProjectAttributes(attributes).GetRequiredProject(Id);

/// <summary>
/// Creates a new document in a new instance of this project.
Expand Down Expand Up @@ -738,7 +745,7 @@ public Project RemoveDocument(DocumentId documentId)
{
// NOTE: the method isn't checking if documentId belongs to the project. This probably should be done, but may be a compat change.
// https://github.com/dotnet/roslyn/issues/41211 tracks this investigation.
return this.Solution.RemoveDocument(documentId).GetProject(this.Id)!;
return this.Solution.RemoveDocument(documentId).GetRequiredProject(Id);
}

/// <summary>
Expand All @@ -757,7 +764,7 @@ public Project RemoveDocuments(ImmutableArray<DocumentId> documentIds)
public Project RemoveAdditionalDocument(DocumentId documentId)
// NOTE: the method isn't checking if documentId belongs to the project. This probably should be done, but may be a compat change.
// https://github.com/dotnet/roslyn/issues/41211 tracks this investigation.
=> this.Solution.RemoveAdditionalDocument(documentId).GetProject(this.Id)!;
=> this.Solution.RemoveAdditionalDocument(documentId).GetRequiredProject(Id);

/// <summary>
/// Creates a new instance of this project updated to no longer include the specified additional documents.
Expand All @@ -775,7 +782,7 @@ public Project RemoveAdditionalDocuments(ImmutableArray<DocumentId> documentIds)
public Project RemoveAnalyzerConfigDocument(DocumentId documentId)
// NOTE: the method isn't checking if documentId belongs to the project. This probably should be done, but may be a compat change.
// https://github.com/dotnet/roslyn/issues/41211 tracks this investigation.
=> this.Solution.RemoveAnalyzerConfigDocument(documentId).GetProject(this.Id)!;
=> this.Solution.RemoveAnalyzerConfigDocument(documentId).GetRequiredProject(Id);

/// <summary>
/// Creates a new solution instance that no longer includes the specified <see cref="AnalyzerConfigDocument"/>s.
Expand Down
Loading
Loading