Skip to content

Make SolutionServices (and related) APIs public#63241

Merged
CyrusNajmabadi merged 10 commits intodotnet:mainfrom
CyrusNajmabadi:solutionServices
Aug 7, 2022
Merged

Make SolutionServices (and related) APIs public#63241
CyrusNajmabadi merged 10 commits intodotnet:mainfrom
CyrusNajmabadi:solutionServices

Conversation

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor

@CyrusNajmabadi CyrusNajmabadi commented Aug 5, 2022

Closes #62914.

Approved by Public API committee.

I have commented interesting lines to help explain the API shape changes that were approved and came along with things becoming public.

@CyrusNajmabadi CyrusNajmabadi requested review from a team, 333fred and JoeRobich as code owners August 5, 2022 19:58
@ghost ghost added the Area-IDE label Aug 5, 2022
identifier = currentRoot.GetCurrentNode(identifier);

var editor = document.GetSyntaxEditor(currentRoot);
var editor = new SyntaxEditor(currentRoot, document.Project.Solution.Services);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted this code to the original pattern now that we have this public API.

{
var parsedDocument = ParsedDocument.CreateSynchronously(document, cancellationToken);
var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, parsedDocument.ProjectServices, explicitFormat: true);
var options = textBuffer.GetSyntaxFormattingOptions(_editorOptionsService, parsedDocument.LanguageServices, explicitFormat: true);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProjectServices was renamed to LanugageServices on behalf of the API committee. This was preferred as the type exposes ILanguageServices. I originally didn't name it that way as we we had HostLanguageServices and i was naming the type HostXXX. However, the API group decided to drop Host. So now we have:

HostWorkspaceServices (existing, mutable) and its immutable counterpart: SolutionServices
HostLanguageServices (existing, mutable) and its immutable counterpart: LanguageServices


var (formattingChanges, finalCurlyBraceEnd) = FormatTrackingSpan(
context.Document,
context.Document.LanguageServices.ProjectServices,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unnecessarily redundant with the ParsedDocument being passed in. removed this parameter.

/// Creates a new <see cref="SyntaxEditor"/> instance.
/// </summary>
internal SyntaxEditor(SyntaxNode root, HostSolutionServices services)
public SyntaxEditor(SyntaxNode root, SolutionServices services)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New public API.

Microsoft.CodeAnalysis.Host.SolutionServices.IsSupported(string languageName) -> bool
Microsoft.CodeAnalysis.Host.SolutionServices.SupportedLanguages.get -> System.Collections.Generic.IEnumerable<string>
Microsoft.CodeAnalysis.Project.Services.get -> Microsoft.CodeAnalysis.Host.LanguageServices
Microsoft.CodeAnalysis.Solution.Services.get -> Microsoft.CodeAnalysis.Host.SolutionServices
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is worth reviewing to make sure it aligns with the shape people expect.

/// Immutable snapshot of the host services. Preferable to use instead of this <see
/// cref="HostLanguageServices"/> when possible.
/// </summary>
public LanguageServices LanguageServices { get; }
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New public API.

/// <summary>
/// Per language services provided by the host environment.
/// </summary>
public sealed class LanguageServices
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New public API. ANd all public members in this are the new public api shape. It's worth expanding this file to see/understand them.

internal LanguageServices(HostLanguageServices services)
{
_services = services;
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: GetRequiredService below could become an extension method. But that has the downside that the caller must know to include a using for Microsoft.CodeAnalysis.Host to see that extension. so it's just convenient to have thse be instance methods instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instance methods are definitely better. Extension methods are not discoverable.

/// <summary>
/// Per solution services provided by the host environment.
/// </summary>
public sealed class SolutionServices
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new public API. it's worth expanding this file to see the entire shape exposed.

/// Immutable snapshot of language services from the host environment associated with this project's language.
/// Use this over <see cref="LanguageServices"/> when possible.
/// </summary>
public Host.LanguageServices Services => LanguageServices.LanguageServices;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new public API.

/// Per solution services provided by the host environment. Use this instead of <see
/// cref="Workspace.Services"/> when possible.
/// </summary>
public SolutionServices Services => _state.Services.SolutionServices;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new public API.

}
#endif

public static SyntaxEditor GetSyntaxEditor(this Document document, SyntaxNode root)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed this extension which just existed so we could customize CODE_STYLE behavior prior to these types becoming public.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@dotnet/roslyn-ide please review.

@tmat
Copy link
Copy Markdown
Member

tmat commented Aug 5, 2022

Many places using Host.LanguageServices qualification. Can these be cleaned up?

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

Many places using Host.LanguageServices qualification. Can these be cleaned up?

Yes. but i would strongly advise in a separate PR. Here's the issue, right now this PR adds the public type LanguageServices. However, we also have an internal namespace Microsoft.CodeAnalysis.LanguageServices. This is where types like ISyntaxFactsService are in. This makes a conflict between the type and namespace.

I can resolve the conflict by renaming the existing non-exported namespace to something like LanguageService (no trailing s). Then, LanguageServices can refer directly to this new type. However, that rename of that namespace touches 700+ files (due to all the places that namespace is imported). I would prefer to do this in an immediately following PR just make this manageable.

I will link to that PR immediately though.

@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@tmat The followup PR is: #63249

@CyrusNajmabadi CyrusNajmabadi requested a review from tmat August 6, 2022 04:56
@CyrusNajmabadi
Copy link
Copy Markdown
Contributor Author

@tmat PTAL. Thanks :)

/// of such feature to either not be invoked on a UI thread or be entirely synchronous.
/// </remarks>
internal readonly record struct ParsedDocument(DocumentId Id, SourceText Text, SyntaxNode Root, HostLanguageServices LanguageServices)
internal readonly record struct ParsedDocument(DocumentId Id, SourceText Text, SyntaxNode Root, HostLanguageServices HostLanguageServices)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HostLanguageServices

For follow up: I'd expect this to be just LanguageServices. Is Workspace being accessed from these services?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup agreed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have noted this for follow-up

Copy link
Copy Markdown
Member

@tmat tmat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@CyrusNajmabadi CyrusNajmabadi merged commit 1c3cdb0 into dotnet:main Aug 7, 2022
@CyrusNajmabadi CyrusNajmabadi deleted the solutionServices branch August 7, 2022 20:25
@ghost ghost added this to the Next milestone Aug 7, 2022
@dibarbet dibarbet modified the milestones: Next, 17.4 P2 Sep 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose snapshot of IWorkspaceServices off of Solution, instead of just off of Workspace.

4 participants