C#: Only extract Public and Protected members from reference assemblies.

This commit is contained in:
Michael Nebel
2024-11-26 13:13:08 +01:00
parent 647515bd84
commit f7874c37c4
5 changed files with 44 additions and 10 deletions

View File

@@ -642,5 +642,40 @@ namespace Semmle.Extraction.CSharp
/// </summary>
public static IEnumerable<AnnotatedTypeSymbol> GetAnnotatedTypeArguments(this INamedTypeSymbol symbol) =>
symbol.TypeArguments.Zip(symbol.TypeArgumentNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a));
/// <summary>
/// Returns true if the symbol is public, protected or protected internal.
/// </summary>
public static bool IsPublicOrProtected(this ISymbol symbol) =>
symbol.DeclaredAccessibility == Accessibility.Public
|| symbol.DeclaredAccessibility == Accessibility.Protected
|| symbol.DeclaredAccessibility == Accessibility.ProtectedOrInternal;
/// <summary>
/// Returns true if the given symbol should be extracted.
/// </summary>
public static bool ShouldExtractSymbol(this ISymbol symbol)
{
// Extract all source symbols and public/protected metadata symbols.
if (symbol.Locations.Any(x => !x.IsInMetadata) || symbol.IsPublicOrProtected())
{
return true;
}
if (symbol is IMethodSymbol method)
{
return method.ExplicitInterfaceImplementations.Any(m => m.ContainingType.DeclaredAccessibility == Accessibility.Public);
}
if (symbol is IPropertySymbol property)
{
return property.ExplicitInterfaceImplementations.Any(m => m.ContainingType.DeclaredAccessibility == Accessibility.Public);
}
return false;
}
/// <summary>
/// Returns the symbols that should be extracted.
/// </summary>
public static IEnumerable<T> ExtractionCandidates<T>(this IEnumerable<T> symbols) where T : ISymbol =>
symbols.Where(symbol => symbol.ShouldExtractSymbol());
}
}

View File

@@ -101,7 +101,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
if (Symbol.OverriddenMethod is not null)
if (Symbol.OverriddenMethod is not null && Symbol.OverriddenMethod.ShouldExtractSymbol())
{
trapFile.overrides(this, Method.Create(Context, Symbol.OverriddenMethod));
}

View File

@@ -225,7 +225,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
/// <summary>
/// Called to extract all members and nested types.
/// Called to extract members and nested types.
/// This is called on each member of a namespace,
/// in either source code or an assembly.
/// </summary>
@@ -236,7 +236,7 @@ namespace Semmle.Extraction.CSharp.Entities
Context.BindComments(this, l);
}
foreach (var member in Symbol.GetMembers())
foreach (var member in Symbol.GetMembers().ExtractionCandidates())
{
switch (member.Kind)
{
@@ -262,16 +262,16 @@ namespace Semmle.Extraction.CSharp.Entities
var members = new List<ISymbol>();
foreach (var member in Symbol.GetMembers())
foreach (var member in Symbol.GetMembers().ExtractionCandidates())
members.Add(member);
foreach (var member in Symbol.GetTypeMembers())
foreach (var member in Symbol.GetTypeMembers().ExtractionCandidates())
members.Add(member);
// Mono extractor puts all BASE interface members as members of the current interface.
if (Symbol.TypeKind == TypeKind.Interface)
{
foreach (var baseInterface in Symbol.Interfaces)
foreach (var baseInterface in Symbol.Interfaces.ExtractionCandidates())
{
foreach (var member in baseInterface.GetMembers())
members.Add(member);
@@ -285,10 +285,10 @@ namespace Semmle.Extraction.CSharp.Entities
Context.CreateEntity(member);
}
if (Symbol.BaseType is not null)
if (Symbol.BaseType is not null && Symbol.BaseType.ShouldExtractSymbol())
Create(Context, Symbol.BaseType).PopulateGenerics();
foreach (var i in Symbol.Interfaces)
foreach (var i in Symbol.Interfaces.ExtractionCandidates())
{
Create(Context, i).PopulateGenerics();
}

View File

@@ -269,7 +269,7 @@ namespace Semmle.Extraction.CSharp
AnalyseNamespace(cx, memberNamespace);
}
foreach (var memberType in ns.GetTypeMembers())
foreach (var memberType in ns.GetTypeMembers().ExtractionCandidates())
{
Entities.Type.Create(cx, memberType).ExtractRecursive();
}

View File

@@ -549,7 +549,6 @@ namespace Semmle.Extraction.CSharp
compilerArguments.CompilationOptions
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
.WithStrongNameProvider(new DesktopStrongNameProvider(compilerArguments.KeyFileSearchPaths))
.WithMetadataImportOptions(MetadataImportOptions.All)
);
},
(compilation, options) => analyser.EndInitialize(compilerArguments, options, compilation, cwd, args),