Revert "C#: Improve db consistency by removing assembly id"

This commit is contained in:
Tom Hvitved
2020-04-22 16:32:13 +02:00
committed by GitHub
parent 1ecfa2eb55
commit 8c0c283811
26 changed files with 53 additions and 132 deletions

View File

@@ -77,7 +77,7 @@ namespace Semmle.Extraction.CSharp.Entities
} }
public new static Accessor Create(Context cx, IMethodSymbol symbol) => public new static Accessor Create(Context cx, IMethodSymbol symbol) =>
AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol); AccessorFactory.Instance.CreateEntity(cx, symbol);
class AccessorFactory : ICachedEntityFactory<IMethodSymbol, Accessor> class AccessorFactory : ICachedEntityFactory<IMethodSymbol, Accessor>
{ {

View File

@@ -104,7 +104,7 @@ namespace Semmle.Extraction.CSharp.Entities
{ {
case MethodKind.StaticConstructor: case MethodKind.StaticConstructor:
case MethodKind.Constructor: case MethodKind.Constructor:
return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor); return ConstructorFactory.Instance.CreateEntity(cx, constructor);
default: default:
throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor"); throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor");
} }

View File

@@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities
: base(cx, init) { } : base(cx, init) { }
public new static Conversion Create(Context cx, IMethodSymbol symbol) => public new static Conversion Create(Context cx, IMethodSymbol symbol) =>
ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol); ConversionFactory.Instance.CreateEntity(cx, symbol);
public override Microsoft.CodeAnalysis.Location ReportingLocation public override Microsoft.CodeAnalysis.Location ReportingLocation
{ {

View File

@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
} }
public new static Destructor Create(Context cx, IMethodSymbol symbol) => public new static Destructor Create(Context cx, IMethodSymbol symbol) =>
DestructorFactory.Instance.CreateEntityFromSymbol(cx, symbol); DestructorFactory.Instance.CreateEntity(cx, symbol);
class DestructorFactory : ICachedEntityFactory<IMethodSymbol, Destructor> class DestructorFactory : ICachedEntityFactory<IMethodSymbol, Destructor>
{ {

View File

@@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities
TypeMention.Create(Context, syntaxType, this, type); TypeMention.Create(Context, syntaxType, this, type);
} }
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol); public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntity(cx, symbol);
class EventFactory : ICachedEntityFactory<IEventSymbol, Event> class EventFactory : ICachedEntityFactory<IEventSymbol, Event>
{ {

View File

@@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities
} }
public new static EventAccessor Create(Context cx, IMethodSymbol symbol) => public new static EventAccessor Create(Context cx, IMethodSymbol symbol) =>
EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol); EventAccessorFactory.Instance.CreateEntity(cx, symbol);
class EventAccessorFactory : ICachedEntityFactory<IMethodSymbol, EventAccessor> class EventAccessorFactory : ICachedEntityFactory<IMethodSymbol, EventAccessor>
{ {

View File

@@ -18,7 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities
type = new Lazy<AnnotatedType>(() => Entities.Type.Create(cx, symbol.GetAnnotatedType())); type = new Lazy<AnnotatedType>(() => Entities.Type.Create(cx, symbol.GetAnnotatedType()));
} }
public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field); public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntity(cx, field);
// Do not populate backing fields. // Do not populate backing fields.
// Populate Tuple fields. // Populate Tuple fields.

View File

@@ -71,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities
TypeMention.Create(Context, syntax.Type, this, type); TypeMention.Create(Context, syntax.Type, this, type);
} }
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop); public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop);
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {

View File

@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.Write('*'); trapFile.Write('*');
} }
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntityFromSymbol(cx, field); public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field);
class LocalFunctionFactory : ICachedEntityFactory<IMethodSymbol, LocalFunction> class LocalFunctionFactory : ICachedEntityFactory<IMethodSymbol, LocalFunction>
{ {

View File

@@ -43,7 +43,7 @@ namespace Semmle.Extraction.CSharp.Entities
public static LocalVariable Create(Context cx, ISymbol local) public static LocalVariable Create(Context cx, ISymbol local)
{ {
return LocalVariableFactory.Instance.CreateEntityFromSymbol(cx, local); return LocalVariableFactory.Instance.CreateEntity(cx, local);
} }
void DefineConstantValue(TextWriter trapFile) void DefineConstantValue(TextWriter trapFile)

View File

@@ -129,7 +129,7 @@ namespace Semmle.Extraction.CSharp.Entities
// Type arguments with different nullability can result in // Type arguments with different nullability can result in
// a constructed method with different nullability of its parameters and return type, // a constructed method with different nullability of its parameters and return type,
// so we need to create a distinct database entity for it. // so we need to create a distinct database entity for it.
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, m.symbol); trapFile.Write((int)ta.Nullability); }); trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); });
trapFile.Write('>'); trapFile.Write('>');
} }
} }
@@ -199,9 +199,12 @@ namespace Semmle.Extraction.CSharp.Entities
/// to make the reference to <code>#3</code> in the label definition <code>#4</code> for /// to make the reference to <code>#3</code> in the label definition <code>#4</code> for
/// <code>T</code> valid. /// <code>T</code> valid.
/// </summary> /// </summary>
protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, ISymbol symbolBeingDefined) protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type)
{ {
type.BuildTypeId(cx, trapFile, false, symbolBeingDefined, (cx0, tb0, type0, g) => AddSignatureTypeToId(cx, tb0, method, type0, g)); if (type.ContainsTypeParameters(cx, method))
type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
else
trapFile.WriteSubId(Type.Create(cx, type));
} }
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method)
@@ -212,13 +215,13 @@ namespace Semmle.Extraction.CSharp.Entities
if (method.MethodKind == MethodKind.ReducedExtension) if (method.MethodKind == MethodKind.ReducedExtension)
{ {
trapFile.WriteSeparator(",", ref index); trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, method); AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType);
} }
foreach (var param in method.Parameters) foreach (var param in method.Parameters)
{ {
trapFile.WriteSeparator(",", ref index); trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, param.Type, method); AddSignatureTypeToId(cx, trapFile, method, param.Type);
switch (param.RefKind) switch (param.RefKind)
{ {
case RefKind.Out: case RefKind.Out:
@@ -241,10 +244,9 @@ namespace Semmle.Extraction.CSharp.Entities
public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations) public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations)
{ {
foreach (var i in explicitInterfaceImplementations) if (explicitInterfaceImplementations.Any())
{ {
trapFile.Write(';'); trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType)));
i.ContainingType.BuildNestedTypeId(cx, trapFile, null);
} }
} }

View File

@@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp.Entities
ExtractCompilerGenerated(trapFile); ExtractCompilerGenerated(trapFile);
} }
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method); public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method);
class OrdinaryMethodFactory : ICachedEntityFactory<IMethodSymbol, OrdinaryMethod> class OrdinaryMethodFactory : ICachedEntityFactory<IMethodSymbol, OrdinaryMethod>
{ {

View File

@@ -113,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities
{ {
bool isIndexer = prop.IsIndexer || prop.Parameters.Any(); bool isIndexer = prop.IsIndexer || prop.Parameters.Any();
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop); return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop);
} }
public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p) public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p)

View File

@@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.Write(";type"); trapFile.Write(";type");
} }
public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntity(cx, symbol);
class ArrayTypeFactory : ICachedEntityFactory<IArrayTypeSymbol, ArrayType> class ArrayTypeFactory : ICachedEntityFactory<IArrayTypeSymbol, ArrayType>
{ {

View File

@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities
DynamicType(Context cx, IDynamicTypeSymbol init) DynamicType(Context cx, IDynamicTypeSymbol init)
: base(cx, init) { } : base(cx, init) { }
public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntity(cx, type);
public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault(); public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault();

View File

@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities
typeArgumentsLazy = new Lazy<Type[]>(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray()); typeArgumentsLazy = new Lazy<Type[]>(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray());
} }
public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntity(cx, type);
public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error; public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error;
@@ -111,7 +111,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub))); symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub)));
trapFile.Write(";type"); trapFile.Write(";type");
} }
@@ -177,7 +177,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
referencedType.symbol.BuildNestedTypeId(Context, trapFile, referencedType.symbol); trapFile.WriteSubId(referencedType);
trapFile.Write(";typeRef"); trapFile.Write(";typeRef");
} }

View File

@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities
public Type PointedAtType { get; private set; } public Type PointedAtType { get; private set; }
public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol); public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntity(cx, symbol);
class PointerTypeFactory : ICachedEntityFactory<IPointerTypeSymbol, PointerType> class PointerTypeFactory : ICachedEntityFactory<IPointerTypeSymbol, PointerType>
{ {

View File

@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary> /// </summary>
class TupleType : Type<INamedTypeSymbol> class TupleType : Type<INamedTypeSymbol>
{ {
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntityFromSymbol(cx, type); public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntity(cx, type);
class TupleTypeFactory : ICachedEntityFactory<INamedTypeSymbol, TupleType> class TupleTypeFactory : ICachedEntityFactory<INamedTypeSymbol, TupleType>
{ {
@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub))); symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub)));
trapFile.Write(";tuple"); trapFile.Write(";tuple");
} }

View File

@@ -324,14 +324,6 @@ namespace Semmle.Extraction.CSharp.Entities
} }
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
public override bool Equals(object obj)
{
var other = obj as Type;
return other?.GetType() == GetType() && SymbolEqualityComparer.IncludeNullability.Equals(other.symbol, symbol);
}
public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(symbol);
} }
abstract class Type<T> : Type where T : ITypeSymbol abstract class Type<T> : Type where T : ITypeSymbol

View File

@@ -88,7 +88,7 @@ namespace Semmle.Extraction.CSharp.Entities
} }
static public TypeParameter Create(Context cx, ITypeParameterSymbol p) => static public TypeParameter Create(Context cx, ITypeParameterSymbol p) =>
TypeParameterFactory.Instance.CreateEntityFromSymbol(cx, p); TypeParameterFactory.Instance.CreateEntity(cx, p);
/// <summary> /// <summary>
/// The variance of this type parameter. /// The variance of this type parameter.

View File

@@ -51,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities
public override void WriteId(TextWriter trapFile) public override void WriteId(TextWriter trapFile)
{ {
AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, symbol); // Needed for op_explicit(), which differs only by return type. AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type.
trapFile.Write(' '); trapFile.Write(' ');
BuildMethodId(this, trapFile); BuildMethodId(this, trapFile);
} }
@@ -190,7 +190,7 @@ namespace Semmle.Extraction.CSharp.Entities
return result; return result;
} }
public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntityFromSymbol(cx, symbol); public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntity(cx, symbol);
class UserOperatorFactory : ICachedEntityFactory<IMethodSymbol, UserOperator> class UserOperatorFactory : ICachedEntityFactory<IMethodSymbol, UserOperator>
{ {

View File

@@ -122,24 +122,6 @@ 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> /// <summary>
/// Constructs a unique string for this type symbol. /// Constructs a unique string for this type symbol.
/// ///
@@ -148,12 +130,10 @@ namespace Semmle.Extraction.CSharp
/// </summary> /// </summary>
/// <param name="cx">The extraction context.</param> /// <param name="cx">The extraction context.</param>
/// <param name="trapFile">The trap builder used to store the result.</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> /// <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, Action<Context, TextWriter, ITypeSymbol> subTermAction)
{ {
if (type.SpecialType != SpecialType.None && !(type is INamedTypeSymbol n && n.IsGenericType)) if (type.SpecialType != SpecialType.None)
{ {
/* /*
* Use the keyword ("int" etc) for the built-in types. * Use the keyword ("int" etc) for the built-in types.
@@ -170,7 +150,7 @@ namespace Semmle.Extraction.CSharp
{ {
case TypeKind.Array: case TypeKind.Array:
var array = (IArrayTypeSymbol)type; var array = (IArrayTypeSymbol)type;
subTermAction(cx, trapFile, array.ElementType, symbolBeingDefined); subTermAction(cx, trapFile, array.ElementType);
array.BuildArraySuffix(trapFile); array.BuildArraySuffix(trapFile);
return; return;
case TypeKind.Class: case TypeKind.Class:
@@ -180,30 +160,15 @@ namespace Semmle.Extraction.CSharp
case TypeKind.Delegate: case TypeKind.Delegate:
case TypeKind.Error: case TypeKind.Error:
var named = (INamedTypeSymbol)type; var named = (INamedTypeSymbol)type;
named.BuildNamedTypeId(cx, trapFile, prefix, symbolBeingDefined, subTermAction); named.BuildNamedTypeId(cx, trapFile, subTermAction);
return; return;
case TypeKind.Pointer: case TypeKind.Pointer:
var ptr = (IPointerTypeSymbol)type; var ptr = (IPointerTypeSymbol)type;
subTermAction(cx, trapFile, ptr.PointedAtType, symbolBeingDefined); subTermAction(cx, trapFile, ptr.PointedAtType);
trapFile.Write('*'); trapFile.Write('*');
return; return;
case TypeKind.TypeParameter: case TypeKind.TypeParameter:
var tp = (ITypeParameterSymbol)type; var tp = (ITypeParameterSymbol)type;
if (!SymbolEqualityComparer.Default.Equals(tp.ContainingSymbol, symbolBeingDefined))
{
switch (tp.TypeParameterKind)
{
case TypeParameterKind.Method:
var method = Method.Create(cx, (IMethodSymbol)tp.ContainingSymbol);
trapFile.WriteSubId(method);
trapFile.Write('_');
break;
case TypeParameterKind.Type:
subTermAction(cx, trapFile, tp.ContainingType, symbolBeingDefined);
trapFile.Write('_');
break;
}
}
trapFile.Write(tp.Name); trapFile.Write(tp.Name);
return; return;
case TypeKind.Dynamic: case TypeKind.Dynamic:
@@ -246,8 +211,9 @@ namespace Semmle.Extraction.CSharp
trapFile.Write("::"); trapFile.Write("::");
} }
static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, bool prefixAssembly, ISymbol symbolBeingDefined, Action<Context, TextWriter, ITypeSymbol, ISymbol> subTermAction) static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction)
{ {
bool prefixAssembly = true;
if (named.ContainingAssembly is null) prefixAssembly = false; if (named.ContainingAssembly is null) prefixAssembly = false;
if (named.IsTupleType) if (named.IsTupleType)
@@ -258,7 +224,7 @@ namespace Semmle.Extraction.CSharp
{ {
trapFile.Write(f.Name); trapFile.Write(f.Name);
trapFile.Write(":"); trapFile.Write(":");
subTermAction(cx, tb0, f.Type, symbolBeingDefined); subTermAction(cx, tb0, f.Type);
} }
); );
trapFile.Write(")"); trapFile.Write(")");
@@ -267,7 +233,7 @@ namespace Semmle.Extraction.CSharp
if (named.ContainingType != null) if (named.ContainingType != null)
{ {
subTermAction(cx, trapFile, named.ContainingType, symbolBeingDefined); subTermAction(cx, trapFile, named.ContainingType);
trapFile.Write('.'); trapFile.Write('.');
} }
else if (named.ContainingNamespace != null) else if (named.ContainingNamespace != null)
@@ -289,14 +255,14 @@ namespace Semmle.Extraction.CSharp
} }
else else
{ {
subTermAction(cx, trapFile, named.ConstructedFrom, symbolBeingDefined); subTermAction(cx, trapFile, named.ConstructedFrom);
trapFile.Write('<'); trapFile.Write('<');
// Encode the nullability of the type arguments in the label. // Encode the nullability of the type arguments in the label.
// Type arguments with different nullability can result in // Type arguments with different nullability can result in
// a constructed type with different nullability of its members and methods, // a constructed type with different nullability of its members and methods,
// so we need to create a distinct database entity for it. // so we need to create a distinct database entity for it.
trapFile.BuildList(",", named.GetAnnotatedTypeArguments(), trapFile.BuildList(",", named.GetAnnotatedTypeArguments(),
(ta, tb0) => subTermAction(cx, tb0, ta.Symbol, symbolBeingDefined) (ta, tb0) => subTermAction(cx, tb0, ta.Symbol)
); );
trapFile.Write('>'); trapFile.Write('>');
} }
@@ -308,16 +274,16 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('.'); trapFile.Write('.');
} }
static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol, ISymbol> subTermAction, bool includeParamName) static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action<Context, TextWriter, ITypeSymbol> subTermAction, bool includeParamName)
{ {
var buildParam = includeParamName var buildParam = includeParamName
? (prop, tb0) => ? (prop, tb0) =>
{ {
tb0.Write(prop.Name); tb0.Write(prop.Name);
tb0.Write(' '); tb0.Write(' ');
subTermAction(cx, tb0, prop.Type, null); subTermAction(cx, tb0, prop.Type);
} }
: (Action<IPropertySymbol, TextWriter>)((prop, tb0) => subTermAction(cx, tb0, prop.Type, null)); : (Action<IPropertySymbol, TextWriter>)((prop, tb0) => subTermAction(cx, tb0, prop.Type));
int memberCount = type.GetMembers().OfType<IPropertySymbol>().Count(); int memberCount = type.GetMembers().OfType<IPropertySymbol>().Count();
int hackTypeNumber = memberCount == 1 ? 1 : 0; int hackTypeNumber = memberCount == 1 ? 1 : 0;
trapFile.Write("<>__AnonType"); trapFile.Write("<>__AnonType");
@@ -389,7 +355,7 @@ namespace Semmle.Extraction.CSharp
if (namedType.IsAnonymousType) if (namedType.IsAnonymousType)
{ {
namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub, _) => sub.BuildDisplayName(cx0, tb0), false); namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false);
} }
trapFile.Write(namedType.Name); trapFile.Write(namedType.Name);

View File

@@ -51,20 +51,7 @@ namespace Semmle.Extraction
/// <returns>The new/existing entity.</returns> /// <returns>The new/existing entity.</returns>
public Entity CreateEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity public Entity CreateEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity
{ {
return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, objectEntityCache); return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init);
}
/// <summary>
/// Creates a new entity using the factory.
/// </summary>
/// <param name="factory">The entity factory.</param>
/// <param name="init">The initializer for the entity.</param>
/// <returns>The new/existing entity.</returns>
public Entity CreateEntityFromSymbol<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init)
where Entity : ICachedEntity
where Type: ISymbol
{
return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, symbolEntityCache);
} }
// A recursion guard against writing to the trap file whilst writing an id to the trap file. // A recursion guard against writing to the trap file whilst writing an id to the trap file.
@@ -149,13 +136,8 @@ namespace Semmle.Extraction
public Label GetNewLabel() => new Label(GetNewId()); public Label GetNewLabel() => new Label(GetNewId());
private Entity CreateNonNullEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity private Entity CreateNonNullEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity
=> CreateNonNullEntity(factory, init, objectEntityCache);
private Entity CreateNonNullEntity<Type, Src, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init, IDictionary<Src, ICachedEntity> dictionary)
where Entity : ICachedEntity
where Type : Src
{ {
if (dictionary.TryGetValue(init, out var cached)) if (objectEntityCache.TryGetValue(init, out var cached))
return (Entity)cached; return (Entity)cached;
using (StackGuard) using (StackGuard)
@@ -164,7 +146,7 @@ namespace Semmle.Extraction
var entity = factory.Create(this, init); var entity = factory.Create(this, init);
entity.Label = label; entity.Label = label;
dictionary[init] = entity; objectEntityCache[init] = entity;
DefineLabel(entity, TrapWriter.Writer, Extractor); DefineLabel(entity, TrapWriter.Writer, Extractor);
if (entity.NeedsPopulation) if (entity.NeedsPopulation)
@@ -218,9 +200,7 @@ namespace Semmle.Extraction
#if DEBUG_LABELS #if DEBUG_LABELS
readonly Dictionary<string, ICachedEntity> idLabelCache = new Dictionary<string, ICachedEntity>(); readonly Dictionary<string, ICachedEntity> idLabelCache = new Dictionary<string, ICachedEntity>();
#endif #endif
readonly Dictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>();
readonly IDictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>();
readonly IDictionary<ISymbol, ICachedEntity> symbolEntityCache = new Dictionary<ISymbol, ICachedEntity>(10000, SymbolEqualityComparer.IncludeNullability);
readonly Dictionary<ICachedEntity, Label> entityLabelCache = new Dictionary<ICachedEntity, Label>(); readonly Dictionary<ICachedEntity, Label> entityLabelCache = new Dictionary<ICachedEntity, Label>();
readonly HashSet<Label> extractedGenerics = new HashSet<Label>(); readonly HashSet<Label> extractedGenerics = new HashSet<Label>();

View File

@@ -130,19 +130,6 @@ namespace Semmle.Extraction
public static Entity CreateEntity<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init) public static Entity CreateEntity<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
where Entity : ICachedEntity => cx.CreateEntity(factory, init); where Entity : ICachedEntity => cx.CreateEntity(factory, init);
/// <summary>
/// Creates and populates a new entity, or returns the existing one from the cache.
/// </summary>
/// <typeparam name="Type">The symbol type used to construct the entity.</typeparam>
/// <typeparam name="Entity">The type of the entity to create.</typeparam>
/// <param name="cx">The extractor context.</param>
/// <param name="factory">The factory used to construct the entity.</param>
/// <param name="init">The initializer for the entity, which may not be null.</param>
/// <returns>The entity.</returns>
public static Entity CreateEntityFromSymbol<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
where Entity : ICachedEntity
where Type : ISymbol => cx.CreateEntityFromSymbol(factory, init);
/// <summary> /// <summary>
/// Creates and populates a new entity, but uses a different cache. /// Creates and populates a new entity, but uses a different cache.
/// </summary> /// </summary>

View File

@@ -1,9 +1,3 @@
| Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class | | 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 | 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 | | Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class |

View File

@@ -243,7 +243,7 @@ expressionTypes
| NullableRefTypes.cs:19:33:19:36 | 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: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:27:50:27:53 | null | null |
| NullableRefTypes.cs:30:21:30:24 | null | null | | NullableRefTypes.cs:30:21:30:24 | null | null |
| NullableRefTypes.cs:31:20:31:23 | this access | MyClass! | | NullableRefTypes.cs:31:20:31:23 | this access | MyClass! |