C#: Avoid qualifying explicit interface implementations.

This commit is contained in:
Calum Grant
2020-02-12 16:23:48 +00:00
committed by Tom Hvitved
parent 6649d72a2d
commit 4657ddcb7c
6 changed files with 43 additions and 20 deletions

View File

@@ -204,7 +204,7 @@ namespace Semmle.Extraction.CSharp.Entities
type.BuildTypeId(cx, trapFile, false, symbolBeingDefined, (cx0, tb0, type0, g) => AddSignatureTypeToId(cx, tb0, method, type0, g));
}
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method, ISymbol generic)
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method, ISymbol symbolBeingDefined)
{
trapFile.Write('(');
int index = 0;
@@ -212,13 +212,13 @@ namespace Semmle.Extraction.CSharp.Entities
if (method.MethodKind == MethodKind.ReducedExtension)
{
trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, generic);
AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, symbolBeingDefined);
}
foreach (var param in method.Parameters)
{
trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, param.Type, generic);
AddSignatureTypeToId(cx, trapFile, method, param.Type, symbolBeingDefined);
switch (param.RefKind)
{
case RefKind.Out:
@@ -241,9 +241,10 @@ namespace Semmle.Extraction.CSharp.Entities
public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations)
{
if (explicitInterfaceImplementations.Any())
foreach (var i in explicitInterfaceImplementations)
{
trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType)));
trapFile.Write(';');
i.ContainingType.BuildNestedTypeId(cx, trapFile, null);
}
}

View File

@@ -108,7 +108,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile)
{
symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, g) => tb0.WriteSubId(Create(cx0, sub)));
symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)));
trapFile.Write(";type");
}
@@ -174,11 +174,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile)
{
void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol, ISymbol symbolBeingDefined)
{
symbol.BuildTypeId(cx, trapFile, false, symbolBeingDefined, WriteType);
}
WriteType(Context, trapFile, referencedType.symbol, referencedType.symbol);
referencedType.symbol.BuildNestedTypeId(Context, trapFile, referencedType.symbol);
trapFile.Write(";typeRef");
}

View File

@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile)
{
symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, g) => tb0.WriteSubId(Create(cx0, sub)));
symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)));
trapFile.Write(";tuple");
}

View File

@@ -122,6 +122,24 @@ namespace Semmle.Extraction.CSharp
}
}
/// <summary>
/// Write the identifier for the symbol <paramref name="type"/> to the trapfile <paramref name="trapFile"/>.
/// If any nested types are found in the identifier, then they are written out explicitly, without
/// prefixing the assembly ID.
/// </summary>
/// <param name="type">The type to write.</param>
/// <param name="cx">The extraction context.</param>
/// <param name="trapFile">The trap file to write to.</param>
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
public static void BuildNestedTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, ISymbol symbolBeingDefined)
{
void WriteType(Context cx, TextWriter trapFile, ITypeSymbol symbol, ISymbol symbolBeingDefined)
{
symbol.BuildTypeId(cx, trapFile, false, symbolBeingDefined, WriteType);
}
WriteType(cx, trapFile, type, symbolBeingDefined);
}
/// <summary>
/// Constructs a unique string for this type symbol.
///
@@ -130,8 +148,10 @@ namespace Semmle.Extraction.CSharp
/// </summary>
/// <param name="cx">The extraction context.</param>
/// <param name="trapFile">The trap builder used to store the result.</param>
/// <param name="prefix">Whether to prefix the type ID with the assembly ID.</param>
/// <param name="symbolBeingDefined">The outer symbol being defined (to avoid recursive ids).</param>
/// <param name="subTermAction">The action to apply to syntactic sub terms of this type.</param>
public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, ISymbol SymbolBeingDefined, Action<Context, TextWriter, ITypeSymbol, ISymbol> subTermAction)
public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, bool prefix, ISymbol symbolBeingDefined, Action<Context, TextWriter, ITypeSymbol, ISymbol> subTermAction)
{
if (type.SpecialType != SpecialType.None && !(type is INamedTypeSymbol n && n.IsGenericType))
{
@@ -150,7 +170,7 @@ namespace Semmle.Extraction.CSharp
{
case TypeKind.Array:
var array = (IArrayTypeSymbol)type;
subTermAction(cx, trapFile, array.ElementType, SymbolBeingDefined);
subTermAction(cx, trapFile, array.ElementType, symbolBeingDefined);
array.BuildArraySuffix(trapFile);
return;
case TypeKind.Class:
@@ -160,16 +180,16 @@ namespace Semmle.Extraction.CSharp
case TypeKind.Delegate:
case TypeKind.Error:
var named = (INamedTypeSymbol)type;
named.BuildNamedTypeId(cx, trapFile, prefix, SymbolBeingDefined, subTermAction);
named.BuildNamedTypeId(cx, trapFile, prefix, symbolBeingDefined, subTermAction);
return;
case TypeKind.Pointer:
var ptr = (IPointerTypeSymbol)type;
subTermAction(cx, trapFile, ptr.PointedAtType, SymbolBeingDefined);
subTermAction(cx, trapFile, ptr.PointedAtType, symbolBeingDefined);
trapFile.Write('*');
return;
case TypeKind.TypeParameter:
var tp = (ITypeParameterSymbol)type;
if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, SymbolBeingDefined))
if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, symbolBeingDefined))
{
switch (tp.TypeParameterKind)
{
@@ -179,7 +199,7 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('_');
break;
case TypeParameterKind.Type:
subTermAction(cx, trapFile, tp.ContainingType, SymbolBeingDefined);
subTermAction(cx, trapFile, tp.ContainingType, symbolBeingDefined);
trapFile.Write('_');
break;
}

View File

@@ -1,3 +1,9 @@
| Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class |
| Program.cs:18:21:18:22 | c1 | Assembly2.dll:0:0:0:0 | Class |
| Program.cs:18:21:18:22 | c1 | Program.cs:10:7:10:11 | Class |
| Program.cs:19:21:19:22 | c2 | Assembly1.dll:0:0:0:0 | Class |
| Program.cs:19:21:19:22 | c2 | Assembly2.dll:0:0:0:0 | Class |
| Program.cs:19:21:19:22 | c2 | Program.cs:10:7:10:11 | Class |
| Program.cs:20:15:20:16 | c3 | Assembly1.dll:0:0:0:0 | Class |
| Program.cs:20:15:20:16 | c3 | Assembly2.dll:0:0:0:0 | Class |
| Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class |

View File

@@ -241,9 +241,9 @@ expressionTypes
| NullableRefTypes.cs:17:29:17:32 | null | null |
| NullableRefTypes.cs:18:31:18:34 | this access | MyClass! |
| NullableRefTypes.cs:19:33:19:36 | this access | MyClass! |
| NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass![]! |
| NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass?[]! |
| NullableRefTypes.cs:26:50:26:53 | null | null |
| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass![]! |
| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass?[]! |
| NullableRefTypes.cs:27:50:27:53 | null | null |
| NullableRefTypes.cs:30:21:30:24 | null | null |
| NullableRefTypes.cs:31:20:31:23 | this access | MyClass! |