Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public override void Populate(TextWriter trapFile)
}

public new static Accessor Create(Context cx, IMethodSymbol symbol) =>
AccessorFactory.Instance.CreateEntity(cx, symbol);
AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class AccessorFactory : ICachedEntityFactory<IMethodSymbol, Accessor>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ ConstructorDeclarationSyntax Syntax
{
case MethodKind.StaticConstructor:
case MethodKind.Constructor:
return ConstructorFactory.Instance.CreateEntity(cx, constructor);
return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor);
default:
throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Conversion : UserOperator
: base(cx, init) { }

public new static Conversion Create(Context cx, IMethodSymbol symbol) =>
ConversionFactory.Instance.CreateEntity(cx, symbol);
ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol);

public override Microsoft.CodeAnalysis.Location ReportingLocation
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public override void Populate(TextWriter trapFile)
}

public new static Destructor Create(Context cx, IMethodSymbol symbol) =>
DestructorFactory.Instance.CreateEntity(cx, symbol);
DestructorFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class DestructorFactory : ICachedEntityFactory<IMethodSymbol, Destructor>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public override void Populate(TextWriter trapFile)
TypeMention.Create(Context, syntaxType, this, type);
}

public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntity(cx, symbol);
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class EventFactory : ICachedEntityFactory<IEventSymbol, Event>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public override void Populate(TextWriter trapFile)
}

public new static EventAccessor Create(Context cx, IMethodSymbol symbol) =>
EventAccessorFactory.Instance.CreateEntity(cx, symbol);
EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class EventAccessorFactory : ICachedEntityFactory<IMethodSymbol, EventAccessor>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class Field : CachedSymbol<IFieldSymbol>, IExpressionParentEntity
type = new Lazy<AnnotatedType>(() => Entities.Type.Create(cx, symbol.GetAnnotatedType()));
}

public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntity(cx, field);
public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field);

// Do not populate backing fields.
// Populate Tuple fields.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public override void Populate(TextWriter trapFile)
TypeMention.Create(Context, syntax.Type, this, type);
}

public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop);
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop);

public override void WriteId(TextWriter trapFile)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public override void WriteQuotedId(TextWriter trapFile)
trapFile.Write('*');
}

public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field);
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntityFromSymbol(cx, field);

class LocalFunctionFactory : ICachedEntityFactory<IMethodSymbol, LocalFunction>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ symbol is ILocalSymbol l ?

public static LocalVariable Create(Context cx, ISymbol local)
{
return LocalVariableFactory.Instance.CreateEntity(cx, local);
return LocalVariableFactory.Instance.CreateEntityFromSymbol(cx, local);
}

void DefineConstantValue(TextWriter trapFile)
Expand Down
55 changes: 6 additions & 49 deletions csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ protected static void BuildMethodId(Method m, TextWriter trapFile)
// Type arguments with different nullability can result in
// a constructed method with different nullability of its parameters and return type,
// 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); trapFile.Write((int)ta.Nullability); });
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { ta.Symbol.BuildNestedTypeId(m.Context, tb0, m.symbol); trapFile.Write((int)ta.Nullability); });
trapFile.Write('>');
}
}
Expand Down Expand Up @@ -163,50 +163,6 @@ public override void WriteId(TextWriter trapFile)
BuildMethodId(this, trapFile);
}

/// <summary>
/// Adds an appropriate label ID to the trap builder <paramref name="trapFile"/>
/// for the type <paramref name="type"/> belonging to the signature of method
/// <paramref name="method"/>.
///
/// For methods without type parameters this will always add the key of the
/// corresponding type.
///
/// For methods with type parameters, this will add the key of the
/// corresponding type if the type does *not* contain one of the method
/// type parameters, otherwise it will add a textual representation of
/// the type. This distinction is required because type parameter IDs
/// refer to their declaring methods.
///
/// Example:
///
/// <code>
/// int Count&lt;T&gt;(IEnumerable<T> items)
/// </code>
///
/// The label definitions for <code>Count</code> (<code>#4</code>) and <code>T</code>
/// (<code>#5</code>) will look like:
///
/// <code>
/// #1=&lt;label for System.Int32&gt;
/// #2=&lt;label for type containing Count&gt;
/// #3=&lt;label for IEnumerable`1&gt;
/// #4=@"{#1} {#2}.Count`2(#3<T>);method"
/// #5=@"{#4}T;typeparameter"
/// </code>
///
/// Note how <code>int</code> is referenced in the label definition <code>#3</code> for
/// <code>Count</code>, while <code>T[]</code> is represented textually in order
/// to make the reference to <code>#3</code> in the label definition <code>#4</code> for
/// <code>T</code> valid.
/// </summary>
protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type)
{
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)
{
trapFile.Write('(');
Expand All @@ -215,13 +171,13 @@ protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethod
if (method.MethodKind == MethodKind.ReducedExtension)
{
trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType);
method.ReceiverType.BuildNestedTypeId(cx, trapFile, method);
}

foreach (var param in method.Parameters)
{
trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, param.Type);
param.Type.BuildNestedTypeId(cx, trapFile, method);
switch (param.RefKind)
{
case RefKind.Out:
Expand All @@ -244,9 +200,10 @@ protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethod

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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public override void Populate(TextWriter trapFile)
ExtractCompilerGenerated(trapFile);
}

public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method);
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method);

class OrdinaryMethodFactory : ICachedEntityFactory<IMethodSymbol, OrdinaryMethod>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public static Property Create(Context cx, IPropertySymbol prop)
{
bool isIndexer = prop.IsIndexer || prop.Parameters.Any();

return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop);
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop);
}

public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public override void WriteId(TextWriter trapFile)
trapFile.Write(";type");
}

public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntity(cx, symbol);
public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class ArrayTypeFactory : ICachedEntityFactory<IArrayTypeSymbol, ArrayType>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class DynamicType : Type<IDynamicTypeSymbol>
DynamicType(Context cx, IDynamicTypeSymbol init)
: base(cx, init) { }

public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntity(cx, type);
public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntityFromSymbol(cx, type);

public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class NamedType : Type<INamedTypeSymbol>
typeArgumentsLazy = new Lazy<Type[]>(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray());
}

public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntity(cx, type);
public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type);

public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error;

Expand All @@ -29,7 +29,8 @@ public override void Populate(TextWriter trapFile)
return;
}

trapFile.typeref_type((NamedTypeRef)TypeRef, this);
if (UsesTypeRef)
trapFile.typeref_type((NamedTypeRef)TypeRef, this);

if (symbol.IsGenericType)
{
Expand Down Expand Up @@ -108,7 +109,7 @@ public override IEnumerable<Extraction.Entities.Location> Locations

public override void WriteId(TextWriter trapFile)
{
symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub)));
symbol.BuildTypeId(Context, trapFile, true, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)));
trapFile.Write(";type");
}

Expand Down Expand Up @@ -148,7 +149,14 @@ class NamedTypeFactory : ICachedEntityFactory<INamedTypeSymbol, NamedType>
public NamedType Create(Context cx, INamedTypeSymbol init) => new NamedType(cx, init);
}

public override Type TypeRef => NamedTypeRef.Create(Context, symbol);
// Do not create typerefs of constructed generics as they are always in the current trap file, and there is a possibility
// that a generic could make the typedef ambiguous which leads to performance problems in QL.
// Create typerefs for constructed error types in case they are fully defined elsewhere.
// We cannot use `!this.NeedsPopulation` because this would not be stable as it would depend on
// the assembly that was being extracted at the time.
bool UsesTypeRef => symbol.TypeKind == TypeKind.Error || SymbolEqualityComparer.Default.Equals(symbol.OriginalDefinition, symbol);

public override Type TypeRef => UsesTypeRef ? (Type)NamedTypeRef.Create(Context, symbol) : this;
}

class NamedTypeRef : Type<INamedTypeSymbol>
Expand All @@ -174,7 +182,7 @@ class NamedTypeRefFactory : ICachedEntityFactory<INamedTypeSymbol, NamedTypeRef>

public override void WriteId(TextWriter trapFile)
{
trapFile.WriteSubId(referencedType);
referencedType.symbol.BuildNestedTypeId(Context, trapFile, referencedType.symbol);
trapFile.Write(";typeRef");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public override void Populate(TextWriter trapFile)

public Type PointedAtType { get; private set; }

public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntity(cx, symbol);
public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class PointerTypeFactory : ICachedEntityFactory<IPointerTypeSymbol, PointerType>
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary>
class TupleType : Type<INamedTypeSymbol>
{
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntity(cx, type);
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntityFromSymbol(cx, type);

class TupleTypeFactory : ICachedEntityFactory<INamedTypeSymbol, TupleType>
{
Expand All @@ -32,7 +32,7 @@ class TupleTypeFactory : ICachedEntityFactory<INamedTypeSymbol, TupleType>

public override void WriteId(TextWriter trapFile)
{
symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub)));
symbol.BuildTypeId(Context, trapFile, false, symbol, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)));
trapFile.Write(";tuple");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,14 @@ public virtual IEnumerable<Type> TypeMentions
}

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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public override void Populate(TextWriter trapFile)
}

static public TypeParameter Create(Context cx, ITypeParameterSymbol p) =>
TypeParameterFactory.Instance.CreateEntity(cx, p);
TypeParameterFactory.Instance.CreateEntityFromSymbol(cx, p);

/// <summary>
/// The variance of this type parameter.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public override Type ContainingType

public override void WriteId(TextWriter trapFile)
{
AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type.
symbol.ReturnType.BuildNestedTypeId(Context, trapFile, symbol); // Needed for op_explicit(), which differs only by return type.
trapFile.Write(' ');
BuildMethodId(this, trapFile);
}
Expand Down Expand Up @@ -190,7 +190,7 @@ public static string OperatorSymbol(Context cx, string methodName)
return result;
}

public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntity(cx, symbol);
public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntityFromSymbol(cx, symbol);

class UserOperatorFactory : ICachedEntityFactory<IMethodSymbol, UserOperator>
{
Expand Down
Loading