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

Simplify and unify assembly loader provider #74895

Merged
merged 16 commits into from
Aug 26, 2024

Conversation

CyrusNajmabadi
Copy link
Member

@CyrusNajmabadi CyrusNajmabadi commented Aug 25, 2024

I've been touching this layer a lot in the reloadable-SG space, and this strange hierarchy has been bothering me majorly. This cleans things up a ton here.

@CyrusNajmabadi CyrusNajmabadi requested a review from a team as a code owner August 25, 2024 03:26
@dotnet-issue-labeler dotnet-issue-labeler bot added Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead labels Aug 25, 2024
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class VSAnalyzerAssemblyLoaderProvider(
[ImportMany] IEnumerable<IAnalyzerAssemblyResolver> externalResolvers)
: AbstractAnalyzerAssemblyLoaderProvider(externalResolvers.ToImmutableArray());
Copy link
Member Author

Choose a reason for hiding this comment

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

we don't need this type. It was just exporting for the 'host' layer using the default behavior. But we don't need this since we already have a 'default' exported impl of IAnalyzerAssemblyLoaderProvider

/// Abstract implementation of an anlyzer assembly loader that can be used by VS/VSCode to provide a
/// <see cref="IAnalyzerAssemblyLoader"/> with an appropriate path.
/// </summary>
internal abstract class AbstractAnalyzerAssemblyLoaderProvider : IAnalyzerAssemblyLoaderProvider
Copy link
Member Author

Choose a reason for hiding this comment

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

this code moved to be next to IAnalyzerAssemblyLoaderProvider

[ExportWorkspaceServiceFactory(typeof(IAnalyzerAssemblyLoaderProvider)), Shared]
[method: ImportingConstructor]
[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class DefaultAnalyzerAssemblyLoaderServiceFactory(
Copy link
Member Author

Choose a reason for hiding this comment

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

this code moved to be next to IAnalyzerAssemblyLoaderProvider. That's a standard pattern we have for workspace services. We have hte interface, and the default impl next to it.

[method: Obsolete(MefConstruction.ImportingConstructorMessage, error: true)]
internal sealed class DefaultAnalyzerAssemblyLoaderService(
[ImportMany] IEnumerable<IAnalyzerAssemblyResolver> externalResolvers)
: AbstractAnalyzerAssemblyLoaderProvider(externalResolvers.ToImmutableArray());
Copy link
Member Author

Choose a reason for hiding this comment

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

Note: this default impl is what everything (except VSCode) uses. It is slightly different from the original logic in that it now just subclasses AbstractAnalyzerAssemblyLoaderProvider to pick up the logic from that.

new(AbstractAnalyzerAssemblyLoaderProvider.GetDefaultShadowCopyPath(), externalResolvers.ToImmutableArray());

public IAnalyzerAssemblyLoaderInternal GetShadowCopyLoader()
=> _shadowCopyLoader;
Copy link
Member Author

Choose a reason for hiding this comment

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

we don't need a special REmoteWorkspace impl. The default impl does this work already properly.

@CyrusNajmabadi
Copy link
Member Author

@ToddGrun @dibarbet ptal

=> new DefaultAnalyzerAssemblyLoaderProvider(this, workspaceServices.Workspace.Kind ?? "Default", _externalResolvers);

protected virtual IAnalyzerAssemblyLoaderInternal WrapLoader(IAnalyzerAssemblyLoaderInternal loader)
=> loader;
Copy link
Member Author

Choose a reason for hiding this comment

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

no-op behavior. The VSCode version overrides this to customize behavior.


public static string GetDefaultShadowCopyPath()
=> Path.Combine(Path.GetTempPath(), "Roslyn", "AnalyzerAssemblyLoader");
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little confused by this comment. _workspaceKind is still factoring into the path passed into WrapLoader, no?

=> _shadowCopyLoader.Value;

private IAnalyzerAssemblyLoaderInternal CreateShadowCopyLoader()
=> _factory.WrapLoader(DefaultAnalyzerAssemblyLoader.CreateNonLockingLoader(
Copy link
Contributor

Choose a reason for hiding this comment

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

WrapLoader

calling into a WrapLoader method feels a bit out of place here. Not horrible, just feels like it's leaking the needs of one of the derived classes down to this level.

Also, personal preference, but this is a bit of a run-on sentence. Worth more semicolons.

Copy link
Member Author

Choose a reason for hiding this comment

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

I mean, it's an abstract impl. It's sharing the logic we need for our two subclasses. That doesn't bother me.

@CyrusNajmabadi
Copy link
Member Author

I'm a little confused by this comment.

yup. i got my branches mixed and hadn't pushed everythign properly. Good to go again @ToddGrun


private IAnalyzerAssemblyLoaderInternal CreateShadowCopyLoader()
=> this.WrapLoader(DefaultAnalyzerAssemblyLoader.CreateNonLockingLoader(
Path.Combine(Path.GetTempPath(), nameof(Roslyn), "AnalyzerAssemblyLoader"),
Copy link
Member

Choose a reason for hiding this comment

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

It looks like we're now always using the same path now for VS/OOP - which I think is fine? I assume in VS we only make shadow copies in the remote workspace now? So devenv won't shadow copy analyzers and conflict with the remote workspace any more?

Copy link
Member Author

Choose a reason for hiding this comment

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

correct. every shadow copy loader already puts their work in a unique guid-named subdirectory of the base directory passed in. So there's no conflicts ever across instances (within the same process, or other process, etc.). THey are always independent.

Copy link
Contributor

@ToddGrun ToddGrun 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 1ea679d into dotnet:main Aug 26, 2024
25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Aug 26, 2024
@CyrusNajmabadi CyrusNajmabadi deleted the loaderProvider branch August 26, 2024 20:45
@dibarbet dibarbet modified the milestones: Next, 17.12 P2 Aug 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-IDE untriaged Issues and PRs which have not yet been triaged by a lead VSCode
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants