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

Beginning of work on "Used Assembly References" feature. #39807

Merged

Conversation

AlekseyTs
Copy link
Contributor

This is a beginning of work on #37768.

Detect used assembly references from:

  • explicit references to types in source;
  • explicit references to namespaces in source;
  • explicit references to fields in source;
  • explicit method invocations in source;

Usings flagged by the compiler as unused shouldn’t contribute to the set of used references.

Detect used assembly references from:
- explicit references to types in source;
- explicit references to namespaces in source;
- explicit references to fields in source;
- explicit method invocations in source;

Usings flagged by the compiler as unused shouldn’t contribute to the set of used references.
@AlekseyTs AlekseyTs requested a review from a team as a code owner November 13, 2019 23:50
@AlekseyTs
Copy link
Contributor Author

@gafter, @dotnet/roslyn-compiler Please review.

/// For example, if a type declared in a referenced assembly is referenced in source code
/// within this compilation, the reference is considered to be used. Etc.
/// The returned set is a subset of references returned by <see cref="References"/> API.
/// If compilation contains errors, it is valid to consider all assembly references as used for the purpose
Copy link
Member

@333fred 333fred Nov 14, 2019

Choose a reason for hiding this comment

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

If compilation [](start = 12, length = 14)

Nit: If the compilation #Resolved

=========================

The *Used Assembly References* feature provides a ```GetUsedAssemblyReferences``` API on a ```Compilation``` to obtain a set
of metadata assembly references that are considered as used by the compilation. For example, if a type declared in a
Copy link
Member

@gafter gafter Nov 15, 2019

Choose a reason for hiding this comment

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

as [](start = 52, length = 2)

"as" should be "to be". Also in the line below. #Closed

@@ -1397,6 +1397,16 @@ IAssemblySymbol computeContainingAssembly(ISymbol s)

internal abstract void GetDiagnostics(CompilationStage stage, bool includeEarlierStages, DiagnosticBag diagnostics, CancellationToken cancellationToken = default);

/// <summary>
/// Unique metadata assembly references that are considered as used by this compilation.
Copy link
Member

@gafter gafter Nov 15, 2019

Choose a reason for hiding this comment

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

as [](start = 68, length = 2)

"to be" instead of "as" here and four lines below. #Closed

{
NamedTypeSymbol container = symbol.ContainingType;

if (container is null)
Copy link
Member

@gafter gafter Nov 15, 2019

Choose a reason for hiding this comment

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

if [](start = 24, length = 2)

Can you please explain why this whole if statement isn't just Compilation.AddAssembliesUsedByTypeReference((TypeSymbol)symbol);? #Closed

Copy link
Contributor Author

@AlekseyTs AlekseyTs Nov 15, 2019

Choose a reason for hiding this comment

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

Can you please explain why this whole if statement isn't just Compilation.AddAssembliesUsedByTypeReference((TypeSymbol)symbol);?

I guess it could be. We would unnecessary visit type arguments for the type, but it is probably not a big deal. I will simplify.


In reply to: 346973383 [](ancestors = 346973383)

if (imported is NamespaceSymbol ns)
{
Debug.Assert(!ns.IsGlobalNamespace);
compilation.AddAssembliesUsedByNamespaceReference(ns);
Copy link
Member

@gafter gafter Nov 15, 2019

Choose a reason for hiding this comment

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

compilation [](start = 24, length = 11)

Is this line tested? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this line tested?

Yes.


In reply to: 346974882 [](ancestors = 346974882)


try
{
var visitor = new UsedAssembliesRecorder(compilation);
Copy link
Member

@gafter gafter Nov 15, 2019

Choose a reason for hiding this comment

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

new UsedAssembliesRecorder(compilation) [](start = 30, length = 39)

It feels like it would be valuable to cache one UsedAssembliesRecorder per compilation (e.g. in the compilation). #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It feels like it would be valuable to cache one UsedAssembliesRecorder per compilation (e.g. in the compilation).

The base class has state which cannot be shared while walking nodes in parallel.


In reply to: 346980102 [](ancestors = 346980102)

// PROTOTYPE(UsedAssemblyReferences): This error might not be cached, but its presence might affect cached full set of used assemblies.
// We would report all assemblies as used, even though no one will ever see this error and under
// different environment state the pass could succeed causing us to return different set of used assemblies
// with now apparent reason for the difference from the consumer's point of view.
Copy link
Contributor Author

@AlekseyTs AlekseyTs Nov 15, 2019

Choose a reason for hiding this comment

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

now [](start = 59, length = 3)

Typo #Closed

/// For example, if a type declared in a referenced assembly is referenced in source code
/// within this compilation, the reference is considered to be used. Etc.
/// The returned set is a subset of references returned by <see cref="References"/> API.
/// If compilation contains errors, it is valid to consider all assembly references as used for the purpose
Copy link
Member

@gafter gafter Nov 15, 2019

Choose a reason for hiding this comment

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

If [](start = 12, length = 2)

I would suggest replacing these two sentences with "The result is undefined if the compilation contains errors." #Closed

@gafter
Copy link
Member

gafter commented Nov 15, 2019

Completed review of Iteration 1. #Closed

@AlekseyTs
Copy link
Contributor Author

@dotnet/roslyn-compiler Please review.

{
if (!underlyingDependency.IsLinked && usedAssemblies.Contains(underlyingDependency))
{
AssemblySymbol dependency;
Copy link
Member

@333fred 333fred Nov 18, 2019

Choose a reason for hiding this comment

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

NIt: could use inline declaration #WontFix

return false;
}

_lazyUsedAssemblyReferences ??= new ConcurrentSet<AssemblySymbol>();
Copy link
Member

@333fred 333fred Nov 18, 2019

Choose a reason for hiding this comment

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

_lazyUsedAssemblyReferences [](start = 12, length = 27)

Given that we're locking on this later, I don't think ??= provides the correct threading guarantee here. We probably need to use Interlocked.CompareExchange. #Closed


namespace Microsoft.CodeAnalysis.CSharp
{
internal sealed class UsedAssembliesRecorder : BoundTreeWalkerWithStackGuard
Copy link
Member

@333fred 333fred Nov 18, 2019

Choose a reason for hiding this comment

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

What about:

  • typeof
  • default
  • events
  • exception variable declarations #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What about:

I believe PR description clearly says what is in scope for this PR. BTW, typeof and "exception variable declarations" do not need special handling because the types are referred to explicitly in syntax and will be intercepted by Binder.ResultSymbol.


In reply to: 347628028 [](ancestors = 347628028)

class C2
{
/// <summary>
/// <see cref=""C1{C0}.E1.F1""/>
Copy link
Member

@333fred 333fred Nov 18, 2019

Choose a reason for hiding this comment

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

C0 [](start = 23, length = 2)

I'm not understanding why this wouldn't count as a reference to comp0 when parsing documentation? #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not understanding why this wouldn't count as a reference to comp0 when parsing documentation?

Because it is treated as a definition of a type parameter, that could be referred to later. You don't see cref parsing working this way?


In reply to: 347630679 [](ancestors = 347630679)

@@ -1922,6 +1922,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property

Friend Overrides Function GetUsedAssemblyReferences(Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of MetadataReference)
Throw New System.NotImplementedException()
Copy link
Member

@333fred 333fred Nov 18, 2019

Choose a reason for hiding this comment

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

Is this planned on being implemented for VB? #Closed

Copy link
Contributor Author

@AlekseyTs AlekseyTs Nov 18, 2019

Choose a reason for hiding this comment

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

Is this planned on being implemented for VB?

Yes, I'll add a prototype comment.


In reply to: 347633548 [](ancestors = 347633548)

@333fred
Copy link
Member

333fred commented Nov 18, 2019

Done review pass (commit 3) #Resolved

Copy link
Member

@333fred 333fred left a comment

Choose a reason for hiding this comment

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

LGTM (commit 4)

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

:shipit:

@AlekseyTs AlekseyTs merged commit c5bc1e0 into dotnet:features/UsedAssemblyReferences Nov 19, 2019
@AlekseyTs
Copy link
Contributor Author

@ivanbasov FYI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants