Skip to content

Commit 801f696

Browse files
authored
Merge pull request github#18159 from michaelnebel/csharp/publicprotected
C#: Only extract public and protected members from metadata.
2 parents 4bf7bbb + 395bdd0 commit 801f696

File tree

10 files changed

+47
-61
lines changed

10 files changed

+47
-61
lines changed

csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,5 +642,40 @@ public static AnnotatedTypeSymbol GetType(this Context cx, Microsoft.CodeAnalysi
642642
/// </summary>
643643
public static IEnumerable<AnnotatedTypeSymbol> GetAnnotatedTypeArguments(this INamedTypeSymbol symbol) =>
644644
symbol.TypeArguments.Zip(symbol.TypeArgumentNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a));
645+
646+
/// <summary>
647+
/// Returns true if the symbol is public, protected or protected internal.
648+
/// </summary>
649+
public static bool IsPublicOrProtected(this ISymbol symbol) =>
650+
symbol.DeclaredAccessibility == Accessibility.Public
651+
|| symbol.DeclaredAccessibility == Accessibility.Protected
652+
|| symbol.DeclaredAccessibility == Accessibility.ProtectedOrInternal;
653+
654+
/// <summary>
655+
/// Returns true if the given symbol should be extracted.
656+
/// </summary>
657+
public static bool ShouldExtractSymbol(this ISymbol symbol)
658+
{
659+
// Extract all source symbols and public/protected metadata symbols.
660+
if (symbol.Locations.Any(x => !x.IsInMetadata) || symbol.IsPublicOrProtected())
661+
{
662+
return true;
663+
}
664+
if (symbol is IMethodSymbol method)
665+
{
666+
return method.ExplicitInterfaceImplementations.Any(m => m.ContainingType.ShouldExtractSymbol());
667+
}
668+
if (symbol is IPropertySymbol property)
669+
{
670+
return property.ExplicitInterfaceImplementations.Any(m => m.ContainingType.ShouldExtractSymbol());
671+
}
672+
return false;
673+
}
674+
675+
/// <summary>
676+
/// Returns the symbols that should be extracted.
677+
/// </summary>
678+
public static IEnumerable<T> ExtractionCandidates<T>(this IEnumerable<T> symbols) where T : ISymbol =>
679+
symbols.Where(symbol => symbol.ShouldExtractSymbol());
645680
}
646681
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public void Overrides(TextWriter trapFile)
101101
}
102102
}
103103

104-
if (Symbol.OverriddenMethod is not null)
104+
if (Symbol.OverriddenMethod is not null && Symbol.OverriddenMethod.ShouldExtractSymbol())
105105
{
106106
trapFile.overrides(this, Method.Create(Context, Symbol.OverriddenMethod));
107107
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ private void ExtractParametersForDelegateLikeType(TextWriter trapFile, IMethodSy
225225
}
226226

227227
/// <summary>
228-
/// Called to extract all members and nested types.
228+
/// Called to extract members and nested types.
229229
/// This is called on each member of a namespace,
230230
/// in either source code or an assembly.
231231
/// </summary>
@@ -236,7 +236,7 @@ public void ExtractRecursive()
236236
Context.BindComments(this, l);
237237
}
238238

239-
foreach (var member in Symbol.GetMembers())
239+
foreach (var member in Symbol.GetMembers().ExtractionCandidates())
240240
{
241241
switch (member.Kind)
242242
{
@@ -262,16 +262,16 @@ public void PopulateGenerics()
262262

263263
var members = new List<ISymbol>();
264264

265-
foreach (var member in Symbol.GetMembers())
265+
foreach (var member in Symbol.GetMembers().ExtractionCandidates())
266266
members.Add(member);
267-
foreach (var member in Symbol.GetTypeMembers())
267+
foreach (var member in Symbol.GetTypeMembers().ExtractionCandidates())
268268
members.Add(member);
269269

270270
// Mono extractor puts all BASE interface members as members of the current interface.
271271

272272
if (Symbol.TypeKind == TypeKind.Interface)
273273
{
274-
foreach (var baseInterface in Symbol.Interfaces)
274+
foreach (var baseInterface in Symbol.Interfaces.ExtractionCandidates())
275275
{
276276
foreach (var member in baseInterface.GetMembers())
277277
members.Add(member);
@@ -288,7 +288,7 @@ public void PopulateGenerics()
288288
if (Symbol.BaseType is not null)
289289
Create(Context, Symbol.BaseType).PopulateGenerics();
290290

291-
foreach (var i in Symbol.Interfaces)
291+
foreach (var i in Symbol.Interfaces.ExtractionCandidates())
292292
{
293293
Create(Context, i).PopulateGenerics();
294294
}

csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ private static void AnalyseNamespace(Context cx, INamespaceSymbol ns)
269269
AnalyseNamespace(cx, memberNamespace);
270270
}
271271

272-
foreach (var memberType in ns.GetTypeMembers())
272+
foreach (var memberType in ns.GetTypeMembers().ExtractionCandidates())
273273
{
274274
Entities.Type.Create(cx, memberType).ExtractRecursive();
275275
}

csharp/extractor/Semmle.Extraction.CSharp/Extractor/Extractor.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,6 @@ private static ExitCode AnalyseTracing(
549549
compilerArguments.CompilationOptions
550550
.WithAssemblyIdentityComparer(DesktopAssemblyIdentityComparer.Default)
551551
.WithStrongNameProvider(new DesktopStrongNameProvider(compilerArguments.KeyFileSearchPaths))
552-
.WithMetadataImportOptions(MetadataImportOptions.All)
553552
);
554553
},
555554
(compilation, options) => analyser.EndInitialize(compilerArguments, options, compilation, cwd, args),
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Only extract *public* and *protected* members from reference assemblies. This yields an approximate average speed-up of around 10% for extraction and query execution. Custom MaD rows using `Field`-based summaries may need to be changed to `SyntheticField`-based flows if they reference private fields.

csharp/ql/test/library-tests/conversion/operator/Operator.expected

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,13 @@
2121
| Int32 | Decimal |
2222
| Int32 | Index |
2323
| Int32 | Int128 |
24-
| Int32 | MetadataToken |
2524
| Int32 | NFloat |
2625
| Int64 | Decimal |
2726
| Int64 | Int128 |
2827
| Int64 | NFloat |
2928
| IntPtr | Int128 |
3029
| IntPtr | NFloat |
3130
| Memory`1 | ReadOnlyMemory<T> |
32-
| MetadataToken | Int32 |
3331
| NFloat | Double |
3432
| SByte | Decimal |
3533
| SByte | Half |
@@ -59,4 +57,3 @@
5957
| UIntPtr | Int128 |
6058
| UIntPtr | NFloat |
6159
| UIntPtr | UInt128 |
62-
| UnixFileMode | Nullable<UnixFileMode> |

csharp/ql/test/library-tests/conversion/reftype/RefType.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,6 @@
183183
| IReadOnlyList<T4> | dynamic |
184184
| Int16[] | Object |
185185
| Int16[] | dynamic |
186-
| Int32[,] | Object |
187-
| Int32[,] | dynamic |
188186
| Int32[] | Object |
189187
| Int32[] | dynamic |
190188
| Int64[] | Object |
@@ -223,8 +221,6 @@
223221
| T5 | C1 |
224222
| T5 | Object |
225223
| T5 | dynamic |
226-
| UInt16[][] | Object |
227-
| UInt16[][] | dynamic |
228224
| UInt32[] | Object |
229225
| UInt32[] | dynamic |
230226
| UInt64[] | Object |
@@ -283,7 +279,6 @@
283279
| null | IReadOnlyList<T3> |
284280
| null | IReadOnlyList<T4> |
285281
| null | Int16[] |
286-
| null | Int32[,] |
287282
| null | Int32[] |
288283
| null | Int64[] |
289284
| null | Object |
@@ -294,7 +289,6 @@
294289
| null | T4 |
295290
| null | T4[] |
296291
| null | T5 |
297-
| null | UInt16[][] |
298292
| null | UInt32[] |
299293
| null | UInt64[] |
300294
| null | dynamic |

csharp/ql/test/library-tests/csharp9/FunctionPointer.expected

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,33 @@
11
type
22
| file://:0:0:0:0 | delegate* default<A,B> | B | DefaultCallingConvention |
33
| file://:0:0:0:0 | delegate* default<B,A> | A | DefaultCallingConvention |
4-
| file://:0:0:0:0 | delegate* default<Byte ref,Void> | Void | DefaultCallingConvention |
54
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | ref int | DefaultCallingConvention |
65
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | readonly int | DefaultCallingConvention |
76
| file://:0:0:0:0 | delegate* default<Int32*,Void*> | Void* | DefaultCallingConvention |
87
| file://:0:0:0:0 | delegate* default<Int32> | int | DefaultCallingConvention |
9-
| file://:0:0:0:0 | delegate* default<IntPtr,Byte ref,PortableTailCallFrame*,Void> | Void | DefaultCallingConvention |
10-
| file://:0:0:0:0 | delegate* default<Object,Void> | Void | DefaultCallingConvention |
118
| file://:0:0:0:0 | delegate* default<T,Int32> | int | DefaultCallingConvention |
129
| file://:0:0:0:0 | delegate* default<Void*,Int32*> | int* | DefaultCallingConvention |
13-
| file://:0:0:0:0 | delegate* default<Void*,Object> | object | DefaultCallingConvention |
1410
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | Void | StdCallCallingConvention |
15-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | Void | UnmanagedCallingConvention |
16-
| file://:0:0:0:0 | delegate* unmanaged<Char*,IntPtr,Void> | Void | UnmanagedCallingConvention |
17-
| file://:0:0:0:0 | delegate* unmanaged<Int32,PosixSignal,Int32> | int | UnmanagedCallingConvention |
1811
| file://:0:0:0:0 | delegate* unmanaged<IntPtr,Int32> | int | UnmanagedCallingConvention |
1912
| file://:0:0:0:0 | delegate* unmanaged<IntPtr,Void> | Void | UnmanagedCallingConvention |
20-
| file://:0:0:0:0 | delegate* unmanaged<NoGCRegionCallbackFinalizerWorkItem*,Void> | Void | UnmanagedCallingConvention |
21-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Byte*,Void> | Void | UnmanagedCallingConvention |
22-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Void*,Void*,GCConfigurationType,Int64,Void> | Void | UnmanagedCallingConvention |
2313
| file://:0:0:0:0 | delegate* unmanaged<Void> | Void | UnmanagedCallingConvention |
2414
unmanagedCallingConvention
2515
parameter
2616
| file://:0:0:0:0 | delegate* default<A,B> | 0 | file://:0:0:0:0 | | A |
2717
| file://:0:0:0:0 | delegate* default<B,A> | 0 | file://:0:0:0:0 | | B |
28-
| file://:0:0:0:0 | delegate* default<Byte ref,Void> | 0 | file://:0:0:0:0 | | ref byte! |
2918
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 0 | file://:0:0:0:0 | | ref int! |
3019
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 1 | file://:0:0:0:0 | `1 | out object? |
3120
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 in,Int32 ref> | 2 | file://:0:0:0:0 | `2 | readonly int! |
3221
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 0 | file://:0:0:0:0 | | ref int! |
3322
| file://:0:0:0:0 | delegate* default<Int32 ref,Object out,Int32 ref readonly> | 1 | file://:0:0:0:0 | `1 | out object? |
3423
| file://:0:0:0:0 | delegate* default<Int32*,Void*> | 0 | file://:0:0:0:0 | | int*! |
35-
| file://:0:0:0:0 | delegate* default<IntPtr,Byte ref,PortableTailCallFrame*,Void> | 0 | file://:0:0:0:0 | | IntPtr! |
36-
| file://:0:0:0:0 | delegate* default<IntPtr,Byte ref,PortableTailCallFrame*,Void> | 1 | file://:0:0:0:0 | `1 | ref byte! |
37-
| file://:0:0:0:0 | delegate* default<IntPtr,Byte ref,PortableTailCallFrame*,Void> | 2 | file://:0:0:0:0 | `2 | PortableTailCallFrame*! |
38-
| file://:0:0:0:0 | delegate* default<Object,Void> | 0 | file://:0:0:0:0 | | object |
3924
| file://:0:0:0:0 | delegate* default<T,Int32> | 0 | file://:0:0:0:0 | | T |
4025
| file://:0:0:0:0 | delegate* default<Void*,Int32*> | 0 | file://:0:0:0:0 | | Void*! |
41-
| file://:0:0:0:0 | delegate* default<Void*,Object> | 0 | file://:0:0:0:0 | | Void*! |
4226
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 0 | file://:0:0:0:0 | | ref int! |
4327
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 1 | file://:0:0:0:0 | `1 | out object? |
4428
| file://:0:0:0:0 | delegate* stdcall<Int32 ref,Object out,T,Void> | 2 | file://:0:0:0:0 | `2 | T |
45-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 0 | file://:0:0:0:0 | | byte*! |
46-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 1 | file://:0:0:0:0 | `1 | int! |
47-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 2 | file://:0:0:0:0 | `2 | byte! |
48-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 3 | file://:0:0:0:0 | `3 | long! |
49-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 4 | file://:0:0:0:0 | `4 | long! |
50-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 5 | file://:0:0:0:0 | `5 | EVENT_FILTER_DESCRIPTOR*! |
51-
| file://:0:0:0:0 | delegate* unmanaged<Byte*,Int32,Byte,Int64,Int64,EVENT_FILTER_DESCRIPTOR*,Void*,Void> | 6 | file://:0:0:0:0 | `6 | Void*! |
52-
| file://:0:0:0:0 | delegate* unmanaged<Char*,IntPtr,Void> | 0 | file://:0:0:0:0 | | char*! |
53-
| file://:0:0:0:0 | delegate* unmanaged<Char*,IntPtr,Void> | 1 | file://:0:0:0:0 | `1 | IntPtr! |
54-
| file://:0:0:0:0 | delegate* unmanaged<Int32,PosixSignal,Int32> | 0 | file://:0:0:0:0 | | int! |
55-
| file://:0:0:0:0 | delegate* unmanaged<Int32,PosixSignal,Int32> | 1 | file://:0:0:0:0 | `1 | PosixSignal! |
5629
| file://:0:0:0:0 | delegate* unmanaged<IntPtr,Int32> | 0 | file://:0:0:0:0 | | IntPtr! |
5730
| file://:0:0:0:0 | delegate* unmanaged<IntPtr,Void> | 0 | file://:0:0:0:0 | | IntPtr! |
58-
| file://:0:0:0:0 | delegate* unmanaged<NoGCRegionCallbackFinalizerWorkItem*,Void> | 0 | file://:0:0:0:0 | | NoGCRegionCallbackFinalizerWorkItem*! |
59-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Byte*,Void> | 0 | file://:0:0:0:0 | | Void*! |
60-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Byte*,Void> | 1 | file://:0:0:0:0 | `1 | byte*! |
61-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Void*,Void*,GCConfigurationType,Int64,Void> | 0 | file://:0:0:0:0 | | Void*! |
62-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Void*,Void*,GCConfigurationType,Int64,Void> | 1 | file://:0:0:0:0 | `1 | Void*! |
63-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Void*,Void*,GCConfigurationType,Int64,Void> | 2 | file://:0:0:0:0 | `2 | Void*! |
64-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Void*,Void*,GCConfigurationType,Int64,Void> | 3 | file://:0:0:0:0 | `3 | GCConfigurationType! |
65-
| file://:0:0:0:0 | delegate* unmanaged<Void*,Void*,Void*,GCConfigurationType,Int64,Void> | 4 | file://:0:0:0:0 | `4 | long! |
6631
invocation
6732
| FunctionPointer.cs:17:21:17:43 | function pointer call |
6833
| FunctionPointer.cs:23:13:23:44 | function pointer call |

0 commit comments

Comments
 (0)