Merge pull request #1749 from calumgrant/cs/extractor-tidy

C#: Refactor extractor trap generation code
This commit is contained in:
Tom Hvitved
2019-08-30 15:44:35 +02:00
committed by GitHub
155 changed files with 3268 additions and 2381 deletions

View File

@@ -184,6 +184,7 @@ namespace Semmle.Extraction.CIL.Driver
public bool NoCache { get; private set; }
public int Threads { get; private set; }
public bool PDB { get; private set; }
public TrapWriter.CompressionMode TrapCompression { get; private set; }
void AddFileOrDirectory(string path)
{
@@ -220,6 +221,7 @@ namespace Semmle.Extraction.CIL.Driver
options.Verbosity = Verbosity.Info;
options.Threads = System.Environment.ProcessorCount;
options.PDB = true;
options.TrapCompression = TrapWriter.CompressionMode.Gzip;
foreach (var arg in args)
{

View File

@@ -21,13 +21,13 @@ namespace Semmle.Extraction.CIL.Driver
Console.WriteLine(" path A directory/dll/exe to analyze");
}
static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs)
static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression)
{
string trapFile;
bool extracted;
var sw = new Stopwatch();
sw.Start();
Entities.Assembly.ExtractCIL(layout, assemblyPath, logger, nocache, extractPdbs, out trapFile, out extracted);
Entities.Assembly.ExtractCIL(layout, assemblyPath, logger, nocache, extractPdbs, trapCompression, out trapFile, out extracted);
sw.Stop();
logger.Log(Severity.Info, " {0} ({1})", assemblyPath, sw.Elapsed);
}
@@ -46,7 +46,7 @@ namespace Semmle.Extraction.CIL.Driver
var actions = options.
AssembliesToExtract.Select(asm => asm.filename).
Select<string, Action>(filename => () => ExtractAssembly(layout, filename, logger, options.NoCache, options.PDB)).
Select<string, Action>(filename => () => ExtractAssembly(layout, filename, logger, options.NoCache, options.PDB, options.TrapCompression)).
ToArray();
foreach (var missingRef in options.MissingReferences)

View File

@@ -31,9 +31,9 @@ namespace Semmle.Extraction.CIL
mdReader = peReader.GetMetadataReader();
TypeSignatureDecoder = new Entities.TypeSignatureDecoder(this);
globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, GetId(""), null)));
globalNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "", null)));
systemNamespace = new Lazy<Entities.Namespace>(() => Populate(new Entities.Namespace(this, "System")));
genericHandleFactory = new CachedFunction<GenericContext, Handle, ILabelledEntity>(CreateGenericHandle);
genericHandleFactory = new CachedFunction<GenericContext, Handle, IExtractedEntity>(CreateGenericHandle);
namespaceFactory = new CachedFunction<StringHandle, Entities.Namespace>(n => CreateNamespace(mdReader.GetString(n)));
namespaceDefinitionFactory = new CachedFunction<NamespaceDefinitionHandle, Entities.Namespace>(CreateNamespace);
sourceFiles = new CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile>(path => new Entities.PdbSourceFile(this, path));
@@ -42,9 +42,6 @@ namespace Semmle.Extraction.CIL
defaultGenericContext = new EmptyContext(this);
var def = mdReader.GetAssemblyDefinition();
AssemblyPrefix = GetId(def.Name) + "_" + def.Version.ToString() + "::";
if (extractPdbs)
{
pdb = PDB.PdbReader.Create(assemblyPath, peReader);
@@ -75,7 +72,14 @@ namespace Semmle.Extraction.CIL
}
}
public readonly Id AssemblyPrefix;
public void WriteAssemblyPrefix(TextWriter trapFile)
{
var def = mdReader.GetAssemblyDefinition();
trapFile.Write(GetString(def.Name));
trapFile.Write('_');
trapFile.Write(def.Version.ToString());
trapFile.Write("::");
}
public readonly Entities.TypeSignatureDecoder TypeSignatureDecoder;

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using Semmle.Util.Logging;
using System;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
@@ -20,8 +21,6 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary>
public class Assembly : LabelledEntity, IAssembly
{
public override Id IdSuffix => suffix;
readonly File file;
readonly AssemblyName assemblyName;
@@ -38,12 +37,24 @@ namespace Semmle.Extraction.CIL.Entities
if (!def.PublicKey.IsNil)
assemblyName.SetPublicKey(cx.mdReader.GetBlobBytes(def.PublicKey));
ShortId = cx.GetId(FullName) + "#file:///" + cx.assemblyPath.Replace("\\", "/");
file = new File(cx, cx.assemblyPath);
}
static readonly Id suffix = new StringId(";assembly");
public override void WriteId(TextWriter trapFile)
{
trapFile.Write(FullName);
trapFile.Write("#file:///");
trapFile.Write(cx.assemblyPath.Replace("\\", "/"));
}
public override bool Equals(object obj)
{
return GetType() == obj.GetType() && Equals(file, ((Assembly)obj).file);
}
public override int GetHashCode() => 7 * file.GetHashCode();
public override string IdSuffix => ";assembly";
string FullName => assemblyName.GetPublicKey() is null ? assemblyName.FullName + ", PublicKeyToken=null" : assemblyName.FullName;
@@ -117,7 +128,7 @@ namespace Semmle.Extraction.CIL.Entities
/// <param name="extractPdbs">Whether to extract PDBs.</param>
/// <param name="trapFile">The path of the trap file.</param>
/// <param name="extracted">Whether the file was extracted (false=cached).</param>
public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, out string trapFile, out bool extracted)
public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression, out string trapFile, out bool extracted)
{
trapFile = "";
extracted = false;
@@ -125,7 +136,7 @@ namespace Semmle.Extraction.CIL.Entities
{
var extractor = new Extractor(false, assemblyPath, logger);
var project = layout.LookupProjectOrDefault(assemblyPath);
using (var trapWriter = project.CreateTrapWriter(logger, assemblyPath + ".cil", true))
using (var trapWriter = project.CreateTrapWriter(logger, assemblyPath + ".cil", true, trapCompression))
{
trapFile = trapWriter.TrapFile;
if (nocache || !System.IO.File.Exists(trapFile))

View File

@@ -14,8 +14,9 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// Entity representing a CIL attribute.
/// </summary>
class Attribute : UnlabelledEntity, IAttribute
sealed class Attribute : UnlabelledEntity, IAttribute
{
readonly CustomAttributeHandle handle;
readonly CustomAttribute attrib;
readonly IEntity @object;
@@ -25,6 +26,13 @@ namespace Semmle.Extraction.CIL.Entities
this.@object = @object;
}
public override bool Equals(object obj)
{
return obj is Attribute attribute && handle.Equals(attribute.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
@@ -78,7 +86,7 @@ namespace Semmle.Extraction.CIL.Entities
readonly Context cx;
public CustomAttributeDecoder(Context cx) { this.cx = cx; }
public Type GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Populate(new PrimitiveType(cx, typeCode));
public Type GetPrimitiveType(PrimitiveTypeCode typeCode) => cx.Create(typeCode);
public Type GetSystemType() => throw new NotImplementedException();

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
@@ -6,26 +7,42 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// An event.
/// </summary>
interface IEvent : ILabelledEntity
interface IEvent : IExtractedEntity
{
}
/// <summary>
/// An event entity.
/// </summary>
class Event : LabelledEntity, IEvent
sealed class Event : LabelledEntity, IEvent
{
readonly EventDefinitionHandle handle;
readonly Type parent;
readonly EventDefinition ed;
static readonly Id suffix = CIL.Id.Create(";cil-event");
public Event(Context cx, Type parent, EventDefinitionHandle handle) : base(cx)
{
this.handle = handle;
this.parent = parent;
ed = cx.mdReader.GetEventDefinition(handle);
ShortId = parent.ShortId + cx.Dot + cx.ShortName(ed.Name) + suffix;
}
public override void WriteId(TextWriter trapFile)
{
parent.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(cx.ShortName(ed.Name));
}
public override string IdSuffix => ";cil-event";
public override bool Equals(object obj)
{
return obj is Event e && handle.Equals(e.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
@@ -61,7 +78,5 @@ namespace Semmle.Extraction.CIL.Entities
yield return c;
}
}
public override Id IdSuffix => suffix;
}
}

View File

@@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis;
using System.Reflection.Metadata;
using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
@@ -12,7 +13,7 @@ namespace Semmle.Extraction.CIL.Entities
/// An entity represting a member.
/// Used to type tuples correctly.
/// </summary>
interface IMember : ILabelledEntity
interface IMember : IExtractedEntity
{
}
@@ -36,18 +37,24 @@ namespace Semmle.Extraction.CIL.Entities
public Label Label { get; set; }
public IId Id => ShortId + IdSuffix;
public Id IdSuffix => fieldSuffix;
static readonly StringId fieldSuffix = new StringId(";cil-field");
public Id ShortId
public void WriteId(TextWriter trapFile)
{
get; set;
trapFile.WriteSubId(DeclaringType);
trapFile.Write('.');
trapFile.Write(Name);
}
public abstract Id Name { get; }
public void WriteQuotedId(TextWriter trapFile)
{
trapFile.Write("@\"");
WriteId(trapFile);
trapFile.Write(IdSuffix);
trapFile.Write('\"');
}
public string IdSuffix => ";cil-field";
public abstract string Name { get; }
public abstract Type DeclaringType { get; }
@@ -59,7 +66,7 @@ namespace Semmle.Extraction.CIL.Entities
{
get
{
yield return Tuples.cil_field(this, DeclaringType, Name.Value, Type);
yield return Tuples.cil_field(this, DeclaringType, Name, Type);
}
}
@@ -82,9 +89,15 @@ namespace Semmle.Extraction.CIL.Entities
this.handle = handle;
this.gc = gc;
fd = cx.mdReader.GetFieldDefinition(handle);
ShortId = DeclaringType.ShortId + cx.Dot + Name;
}
public override bool Equals(object obj)
{
return obj is DefinitionField field && handle.Equals(field.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
@@ -114,7 +127,7 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override Id Name => cx.GetId(fd.Name);
public override string Name => cx.GetString(fd.Name);
public override Type DeclaringType => (Type)cx.Create(fd.GetDeclaringType());
@@ -127,19 +140,30 @@ namespace Semmle.Extraction.CIL.Entities
sealed class MemberReferenceField : Field
{
readonly MemberReferenceHandle Handle;
readonly MemberReference mr;
readonly GenericContext gc;
readonly Type declType;
public MemberReferenceField(GenericContext gc, MemberReferenceHandle handle) : base(gc.cx)
{
Handle = handle;
this.gc = gc;
mr = cx.mdReader.GetMemberReference(handle);
declType = (Type)cx.CreateGeneric(gc, mr.Parent);
ShortId = declType.ShortId + cx.Dot + Name;
}
public override Id Name => cx.GetId(mr.Name);
public override bool Equals(object obj)
{
return obj is MemberReferenceField field && Handle.Equals(field.Handle);
}
public override int GetHashCode()
{
return Handle.GetHashCode();
}
public override string Name => cx.GetString(mr.Name);
public override Type DeclaringType => declType;

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
@@ -17,9 +18,20 @@ namespace Semmle.Extraction.CIL.Entities
public File(Context cx, string path) : base(cx)
{
this.path = Semmle.Extraction.Entities.File.PathAsDatabaseString(path);
ShortId = new StringId(Semmle.Extraction.Entities.File.PathAsDatabaseId(path));
}
public override void WriteId(TextWriter trapFile)
{
trapFile.Write(Semmle.Extraction.Entities.File.PathAsDatabaseId(path));
}
public override bool Equals(object obj)
{
return GetType() == obj.GetType() && path == ((File)obj).path;
}
public override int GetHashCode() => 11 * path.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
@@ -31,9 +43,7 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override Id IdSuffix => suffix;
static readonly Id suffix = new StringId(";sourcefile");
public override string IdSuffix => ";sourcefile";
}
public class PdbSourceFile : File

View File

@@ -7,17 +7,21 @@ namespace Semmle.Extraction.CIL.Entities
{
}
public class Folder : LabelledEntity, IFolder
public sealed class Folder : LabelledEntity, IFolder
{
readonly string path;
public Folder(Context cx, string path) : base(cx)
{
this.path = path;
ShortId = new StringId(Semmle.Extraction.Entities.File.PathAsDatabaseId(path));
}
static readonly Id suffix = new StringId(";folder");
public override void WriteId(TextWriter trapFile)
{
trapFile.Write(Semmle.Extraction.Entities.File.PathAsDatabaseId(path));
}
public override string IdSuffix => ";folder";
public override IEnumerable<IExtractionProduct> Contents
{
@@ -37,6 +41,11 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override Id IdSuffix => suffix;
public override bool Equals(object obj)
{
return obj is Folder folder && path == folder.path;
}
public override int GetHashCode() => path.GetHashCode();
}
}

View File

@@ -1,8 +1,9 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
interface ILocal : ILabelledEntity
interface ILocal : IExtractedEntity
{
}
@@ -17,12 +18,16 @@ namespace Semmle.Extraction.CIL.Entities
method = m;
index = i;
type = t;
ShortId = CIL.Id.Create(method.Label) + underscore + index;
}
static readonly Id underscore = CIL.Id.Create("_");
static readonly Id suffix = CIL.Id.Create(";cil-local");
public override Id IdSuffix => suffix;
public override void WriteId(TextWriter trapFile)
{
trapFile.WriteSubId(method);
trapFile.Write('_');
trapFile.Write(index);
}
public override string IdSuffix => ";cil-local";
public override IEnumerable<IExtractionProduct> Contents
{

View File

@@ -6,6 +6,8 @@ using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.IO;
using Semmle.Util;
namespace Semmle.Extraction.CIL.Entities
{
@@ -41,34 +43,40 @@ namespace Semmle.Extraction.CIL.Entities
public virtual IList<LocalVariable> LocalVariables => throw new NotImplementedException();
public IList<Parameter> Parameters { get; private set; }
static readonly Id tick = CIL.Id.Create("`");
static readonly Id space = CIL.Id.Create(" ");
static readonly Id dot = CIL.Id.Create(".");
static readonly Id open = CIL.Id.Create("(");
static readonly Id close = CIL.Id.Create(")");
public override void WriteId(TextWriter trapFile) => WriteMethodId(trapFile, DeclaringType, NameLabel);
internal protected Id MakeMethodId(Type parent, Id methodName)
public abstract string NameLabel { get; }
internal protected void WriteMethodId(TextWriter trapFile, Type parent, string methodName)
{
var id = signature.ReturnType.MakeId(this) + space + parent.ShortId + dot + methodName;
signature.ReturnType.WriteId(trapFile, this);
trapFile.Write(' ');
parent.WriteId(trapFile);
trapFile.Write('.');
trapFile.Write(methodName);
if (signature.GenericParameterCount > 0)
{
id += tick + signature.GenericParameterCount;
trapFile.Write('`');
trapFile.Write(signature.GenericParameterCount);
}
id += open + CIL.Id.CommaSeparatedList(signature.ParameterTypes.Select(p => p.MakeId(this))) + close;
return id;
trapFile.Write('(');
int index = 0;
foreach (var param in signature.ParameterTypes)
{
trapFile.WriteSeparator(",", ref index);
param.WriteId(trapFile, this);
}
trapFile.Write(')');
}
protected MethodTypeParameter[] genericParams;
protected Type declaringType;
protected GenericContext gc;
protected MethodSignature<ITypeSignature> signature;
protected Id name;
protected string name;
static readonly StringId methodSuffix = new StringId(";cil-method");
public override Id IdSuffix => methodSuffix;
public override string IdSuffix => ";cil-method";
protected void PopulateParameters(IEnumerable<Type> parameterTypes)
{
@@ -133,7 +141,7 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// A definition method - a method defined in the current assembly.
/// </summary>
class DefinitionMethod : Method, IMember
sealed class DefinitionMethod : Method, IMember
{
readonly Handle handle;
readonly MethodDefinition md;
@@ -150,22 +158,30 @@ namespace Semmle.Extraction.CIL.Entities
md = cx.mdReader.GetMethodDefinition(handle);
this.gc = gc;
this.handle = handle;
name = cx.GetId(md.Name);
name = cx.GetString(md.Name);
declaringType = (Type)cx.CreateGeneric(this, md.GetDeclaringType());
signature = md.DecodeSignature(new SignatureDecoder(), this);
ShortId = MakeMethodId(declaringType, name);
methodDebugInformation = cx.GetMethodDebugInformation(handle);
}
public override bool Equals(object obj)
{
return obj is DefinitionMethod method && handle.Equals(method.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override bool IsStatic => !signature.Header.IsInstance;
public override Type DeclaringType => declaringType;
public override string Name => cx.ShortName(md.Name);
public override string NameLabel => name;
/// <summary>
/// Holds if this method has bytecode.
/// </summary>
@@ -381,8 +397,9 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// This is a late-bound reference to a method.
/// </summary>
class MemberReferenceMethod : Method
sealed class MemberReferenceMethod : Method
{
readonly MemberReferenceHandle handle;
readonly MemberReference mr;
readonly Type declType;
readonly GenericContext parent;
@@ -390,6 +407,7 @@ namespace Semmle.Extraction.CIL.Entities
public MemberReferenceMethod(GenericContext gc, MemberReferenceHandle handle) : base(gc)
{
this.handle = handle;
this.gc = gc;
mr = cx.mdReader.GetMemberReference(handle);
@@ -398,19 +416,31 @@ namespace Semmle.Extraction.CIL.Entities
parent = (GenericContext)cx.CreateGeneric(gc, mr.Parent);
var parentMethod = parent as Method;
var nameLabel = cx.GetId(mr.Name);
nameLabel = cx.GetString(mr.Name);
declType = parentMethod == null ? parent as Type : parentMethod.DeclaringType;
if (declType is null)
throw new InternalError("Parent context of method is not a type");
ShortId = MakeMethodId(declType, nameLabel);
var typeSourceDeclaration = declType.SourceDeclaration;
sourceDeclaration = typeSourceDeclaration == declType ? (Method)this : typeSourceDeclaration.LookupMethod(mr.Name, mr.Signature);
}
private readonly string nameLabel;
public override string NameLabel => nameLabel;
public override bool Equals(object obj)
{
return obj is MemberReferenceMethod method && handle.Equals(method.handle);
}
public override int GetHashCode()
{
return handle.GetHashCode();
}
public override Method SourceDeclaration => sourceDeclaration;
public override bool IsStatic => !signature.Header.IsInstance;
@@ -450,26 +480,43 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// A constructed method.
/// </summary>
class MethodSpecificationMethod : Method
sealed class MethodSpecificationMethod : Method
{
readonly MethodSpecificationHandle handle;
readonly MethodSpecification ms;
readonly Method unboundMethod;
readonly ImmutableArray<Type> typeParams;
public MethodSpecificationMethod(GenericContext gc, MethodSpecificationHandle handle) : base(gc)
{
this.handle = handle;
ms = cx.mdReader.GetMethodSpecification(handle);
typeParams = ms.DecodeSignature(cx.TypeSignatureDecoder, gc);
unboundMethod = (Method)cx.CreateGeneric(gc, ms.Method);
declaringType = unboundMethod.DeclaringType;
ShortId = unboundMethod.ShortId + openAngle + CIL.Id.CommaSeparatedList(typeParams.Select(p => p.ShortId)) + closeAngle;
}
static readonly Id openAngle = CIL.Id.Create("<");
static readonly Id closeAngle = CIL.Id.Create(">");
public override void WriteId(TextWriter trapFile)
{
unboundMethod.WriteId(trapFile);
trapFile.Write('<');
int index = 0;
foreach(var param in typeParams)
{
trapFile.WriteSeparator(",", ref index);
trapFile.WriteSubId(param);
}
trapFile.Write('>');
}
public override string NameLabel => throw new NotImplementedException();
public override bool Equals(object obj)
{
return obj is MethodSpecificationMethod method && handle.Equals(method.handle) && typeParams.SequenceEqual(method.typeParams);
}
public override int GetHashCode() => handle.GetHashCode() * 11 + typeParams.SequenceHash();
public override Method SourceDeclaration => unboundMethod;

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CIL.Entities
@@ -14,28 +15,43 @@ namespace Semmle.Extraction.CIL.Entities
/// <summary>
/// A namespace.
/// </summary>
public class Namespace : TypeContainer, INamespace
public sealed class Namespace : TypeContainer, INamespace
{
public Namespace ParentNamespace;
public readonly StringId Name;
public readonly string Name;
public bool IsGlobalNamespace => ParentNamespace == null;
static readonly Id suffix = CIL.Id.Create(";namespace");
public override string IdSuffix => ";namespace";
public Id CreateId
public override void WriteId(TextWriter trapFile)
{
get
if (ParentNamespace != null && !ParentNamespace.IsGlobalNamespace)
{
if (ParentNamespace != null && !ParentNamespace.IsGlobalNamespace)
{
return ParentNamespace.ShortId + cx.Dot + Name;
}
return Name;
ParentNamespace.WriteId(trapFile);
trapFile.Write('.');
}
trapFile.Write(Name);
}
public override Id IdSuffix => suffix;
public override bool Equals(object obj)
{
if (obj is Namespace ns && Name == ns.Name)
{
if (ParentNamespace is null)
return ns.ParentNamespace is null;
if (!(ns.ParentNamespace is null))
return ParentNamespace.Equals(ns.ParentNamespace);
}
return false;
}
public override int GetHashCode()
{
int h = ParentNamespace is null ? 19 : ParentNamespace.GetHashCode();
return 13 * h + Name.GetHashCode();
}
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
@@ -54,22 +70,21 @@ namespace Semmle.Extraction.CIL.Entities
return i == -1 ? cx.GlobalNamespace : cx.Populate(new Namespace(cx, fqn.Substring(0, i)));
}
public Namespace(Context cx, string fqn) : this(cx, cx.GetId(parseNamespaceName(fqn)), createParentNamespace(cx, fqn))
public Namespace(Context cx, string fqn) : this(cx, parseNamespaceName(fqn), createParentNamespace(cx, fqn))
{
}
public Namespace(Context cx, StringId name, Namespace parent) : base(cx)
public Namespace(Context cx, string name, Namespace parent) : base(cx)
{
Name = name;
ParentNamespace = parent;
ShortId = CreateId;
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
yield return Tuples.namespaces(this, Name.Value);
yield return Tuples.namespaces(this, Name);
if (!IsGlobalNamespace)
yield return Tuples.parent_namespace(this, ParentNamespace);
}

View File

@@ -1,18 +1,19 @@
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A parameter entity.
/// </summary>
interface IParameter : ILabelledEntity
interface IParameter : IExtractedEntity
{
}
/// <summary>
/// A parameter entity.
/// </summary>
class Parameter : LabelledEntity, IParameter
sealed class Parameter : LabelledEntity, IParameter
{
readonly Method method;
readonly int index;
@@ -23,14 +24,26 @@ namespace Semmle.Extraction.CIL.Entities
method = m;
index = i;
type = t;
ShortId = openCurly + method.Label.Value + closeCurly + index;
}
static readonly Id parameterSuffix = CIL.Id.Create(";cil-parameter");
static readonly Id openCurly = CIL.Id.Create("{#");
static readonly Id closeCurly = CIL.Id.Create("}_");
public override void WriteId(TextWriter trapFile)
{
trapFile.WriteSubId(method);
trapFile.Write('_');
trapFile.Write(index);
}
public override Id IdSuffix => parameterSuffix;
public override bool Equals(object obj)
{
return obj is Parameter param && method.Equals(param.method) && index == param.index;
}
public override int GetHashCode()
{
return 23 * method.GetHashCode() + index;
}
public override string IdSuffix => ";cil-parameter";
public override IEnumerable<IExtractionProduct> Contents
{

View File

@@ -2,38 +2,59 @@
using System.Reflection.Metadata;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// A property.
/// </summary>
interface IProperty : ILabelledEntity
interface IProperty : IExtractedEntity
{
}
/// <summary>
/// A property.
/// </summary>
class Property : LabelledEntity, IProperty
sealed class Property : LabelledEntity, IProperty
{
readonly Handle handle;
readonly Type type;
readonly PropertyDefinition pd;
static readonly Id suffix = CIL.Id.Create(";cil-property");
public override string IdSuffix => ";cil-property";
readonly GenericContext gc;
public Property(GenericContext gc, Type type, PropertyDefinitionHandle handle) : base(gc.cx)
{
this.gc = gc;
this.handle = handle;
pd = cx.mdReader.GetPropertyDefinition(handle);
this.type = type;
var id = type.ShortId + gc.cx.Dot + cx.ShortName(pd.Name);
var signature = pd.DecodeSignature(new SignatureDecoder(), gc);
id += "(" + CIL.Id.CommaSeparatedList(signature.ParameterTypes.Select(p => p.MakeId(gc))) + ")";
ShortId = id;
}
public override void WriteId(TextWriter trapFile)
{
trapFile.WriteSubId(type);
trapFile.Write('.');
trapFile.Write(cx.GetString(pd.Name));
trapFile.Write("(");
int index=0;
var signature = pd.DecodeSignature(new SignatureDecoder(), gc);
foreach (var param in signature.ParameterTypes)
{
trapFile.WriteSeparator(",", ref index);
param.WriteId(trapFile, gc);
}
trapFile.Write(")");
}
public override bool Equals(object obj)
{
return obj is Property property && Equals(handle, property.handle);
}
public override int GetHashCode() => handle.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
get
@@ -62,7 +83,5 @@ namespace Semmle.Extraction.CIL.Entities
yield return c;
}
}
public override Id IdSuffix => suffix;
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.IO;
using Semmle.Extraction.PDB;
namespace Semmle.Extraction.CIL.Entities
@@ -16,12 +17,27 @@ namespace Semmle.Extraction.CIL.Entities
{
this.location = location;
file = cx.CreateSourceFile(location.File);
ShortId = file.ShortId + separator + new IntId(location.StartLine) + separator + new IntId(location.StartColumn) + separator + new IntId(location.EndLine) + separator + new IntId(location.EndColumn);
}
static readonly Id suffix = new StringId(";sourcelocation");
static readonly Id separator = new StringId(",");
public override void WriteId(TextWriter trapFile)
{
file.WriteId(trapFile);
trapFile.Write(',');
trapFile.Write(location.StartLine);
trapFile.Write(',');
trapFile.Write(location.StartColumn);
trapFile.Write(',');
trapFile.Write(location.EndLine);
trapFile.Write(',');
trapFile.Write(location.EndColumn);
}
public override bool Equals(object obj)
{
return obj is PdbSourceLocation l && location.Equals(l.location);
}
public override int GetHashCode() => location.GetHashCode();
public override IEnumerable<IExtractionProduct> Contents
{
@@ -32,6 +48,6 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override Id IdSuffix => suffix;
public override string IdSuffix => ";sourcelocation";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL
{
@@ -11,7 +12,7 @@ namespace Semmle.Extraction.CIL
/// The extraction algorithm proceeds as follows:
/// - Construct entity
/// - Call Extract()
/// - ILabelledEntity check if already extracted
/// - IExtractedEntity check if already extracted
/// - Enumerate Contents to produce more extraction products
/// - Extract these until there is nothing left to extract
/// </remarks>
@@ -45,9 +46,17 @@ namespace Semmle.Extraction.CIL
public abstract IEnumerable<IExtractionProduct> Contents { get; }
public Label Label { get; set; }
public Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public void WriteId(System.IO.TextWriter trapFile)
{
trapFile.Write('*');
}
public virtual IId Id => FreshId.Instance;
public void WriteQuotedId(TextWriter trapFile)
{
WriteId(trapFile);
}
public Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public virtual void Extract(Context cx2)
{
@@ -69,15 +78,23 @@ namespace Semmle.Extraction.CIL
/// An entity that needs to be populated during extraction.
/// This assigns a key and optionally extracts its contents.
/// </summary>
public abstract class LabelledEntity : ILabelledEntity
public abstract class LabelledEntity : IExtractedEntity
{
public abstract IEnumerable<IExtractionProduct> Contents { get; }
public Label Label { get; set; }
public Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public Id ShortId { get; set; }
public abstract Id IdSuffix { get; }
public IId Id => ShortId + IdSuffix;
public abstract void WriteId(System.IO.TextWriter trapFile);
public abstract string IdSuffix { get; }
public void WriteQuotedId(TextWriter trapFile)
{
trapFile.Write("@\"");
WriteId(trapFile);
trapFile.Write(IdSuffix);
trapFile.Write('\"');
}
public void Extract(Context cx2)
{
@@ -91,20 +108,18 @@ namespace Semmle.Extraction.CIL
this.cx = cx;
}
public override string ToString() => Id.ToString();
public override string ToString()
{
using (var writer = new StringWriter())
{
WriteQuotedId(writer);
return writer.ToString();
}
}
TrapStackBehaviour IEntity.TrapStackBehaviour => TrapStackBehaviour.NoLabel;
}
/// <summary>
/// An entity with a defined ID.
/// </summary>
public interface ILabelledEntity : IExtractedEntity
{
Id ShortId { get; set; }
Id IdSuffix { get; }
}
/// <summary>
/// A tuple that is an extraction product.
/// </summary>

View File

@@ -1,5 +1,7 @@
using System;
using Semmle.Extraction.CIL.Entities;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL
@@ -9,37 +11,78 @@ namespace Semmle.Extraction.CIL
/// </summary>
public partial class Context
{
readonly Dictionary<Id, (Label, Id)> ids = new Dictionary<Id, (Label, Id)>();
readonly Dictionary<object, Label> ids = new Dictionary<object, Label>();
public T Populate<T>(T e) where T : ILabelledEntity
public T Populate<T>(T e) where T : IExtractedEntity
{
Id id = e.ShortId;
if (e.Label.Valid)
{
return e; // Already populated
}
if (ids.TryGetValue(id, out var existing))
if (ids.TryGetValue(e, out var existing))
{
// It exists already
e.Label = existing.Item1;
e.ShortId = existing.Item2; // Reuse ID for efficiency
e.Label = existing;
}
else
{
cx.DefineLabel(e);
ids.Add(id, (e.Label, id));
e.Label = cx.GetNewLabel();
cx.DefineLabel(e, cx.TrapWriter.Writer);
ids.Add(e, e.Label);
cx.PopulateLater(() =>
{
foreach (var c in e.Contents)
c.Extract(this);
});
#if DEBUG_LABELS
using (var writer = new StringWriter())
{
e.WriteId(writer);
var id = writer.ToString();
if (debugLabels.TryGetValue(id, out IExtractedEntity previousEntity))
{
cx.Extractor.Message(new Message("Duplicate trap ID", id, null, severity: Util.Logging.Severity.Warning));
}
else
{
debugLabels.Add(id, e);
}
}
#endif
}
return e;
}
#if DEBUG_LABELS
private readonly Dictionary<string, IExtractedEntity> debugLabels = new Dictionary<string, IExtractedEntity>();
#endif
public IExtractedEntity Create(Handle h)
{
var entity = CreateGeneric(defaultGenericContext, h);
return entity;
}
// Lazily cache primitive types.
private readonly PrimitiveType[] primitiveTypes = new PrimitiveType[(int)PrimitiveTypeCode.Object + 1];
public PrimitiveType Create(PrimitiveTypeCode code)
{
PrimitiveType e = primitiveTypes[(int)code];
if (e is null)
{
e = new PrimitiveType(this, code);
e.Label = cx.GetNewLabel();
cx.DefineLabel(e, cx.TrapWriter.Writer);
primitiveTypes[(int)code] = e;
}
return e;
}
/// <summary>
/// Creates an entity from a Handle in a GenericContext.
/// The type of the returned entity depends on the type of the handle.
@@ -52,35 +95,38 @@ namespace Semmle.Extraction.CIL
/// <param name="h">The handle of the entity.</param>
/// <param name="genericContext">The generic context.</param>
/// <returns></returns>
public ILabelledEntity CreateGeneric(GenericContext genericContext, Handle h) => genericHandleFactory[genericContext, h];
public IExtractedEntity CreateGeneric(GenericContext genericContext, Handle h) => genericHandleFactory[genericContext, h];
readonly GenericContext defaultGenericContext;
ILabelledEntity CreateGenericHandle(GenericContext gc, Handle handle)
IExtractedEntity CreateGenericHandle(GenericContext gc, Handle handle)
{
ILabelledEntity entity;
IExtractedEntity entity;
switch (handle.Kind)
{
case HandleKind.MethodDefinition:
entity = new Entities.DefinitionMethod(gc, (MethodDefinitionHandle)handle);
entity = new DefinitionMethod(gc, (MethodDefinitionHandle)handle);
break;
case HandleKind.MemberReference:
entity = Create(gc, (MemberReferenceHandle)handle);
break;
case HandleKind.MethodSpecification:
entity = new Entities.MethodSpecificationMethod(gc, (MethodSpecificationHandle)handle);
entity = new MethodSpecificationMethod(gc, (MethodSpecificationHandle)handle);
break;
case HandleKind.FieldDefinition:
entity = new Entities.DefinitionField(gc, (FieldDefinitionHandle)handle);
entity = new DefinitionField(gc, (FieldDefinitionHandle)handle);
break;
case HandleKind.TypeReference:
entity = new Entities.TypeReferenceType(this, (TypeReferenceHandle)handle);
var tr = new TypeReferenceType(this, (TypeReferenceHandle)handle);
if (tr.TryGetPrimitiveType(out var pt))
// Map special names like `System.Int32` to `int`
return pt;
entity = tr;
break;
case HandleKind.TypeSpecification:
entity = new Entities.TypeSpecificationType(gc, (TypeSpecificationHandle)handle);
break;
return Entities.Type.DecodeType(gc, (TypeSpecificationHandle)handle);
case HandleKind.TypeDefinition:
entity = new Entities.TypeDefinitionType(this, (TypeDefinitionHandle)handle);
entity = new TypeDefinitionType(this, (TypeDefinitionHandle)handle);
break;
default:
throw new InternalError("Unhandled handle kind " + handle.Kind);
@@ -90,131 +136,98 @@ namespace Semmle.Extraction.CIL
return entity;
}
ILabelledEntity Create(GenericContext gc, MemberReferenceHandle handle)
IExtractedEntity Create(GenericContext gc, MemberReferenceHandle handle)
{
var mr = mdReader.GetMemberReference(handle);
switch (mr.GetKind())
{
case MemberReferenceKind.Method:
return new Entities.MemberReferenceMethod(gc, handle);
return new MemberReferenceMethod(gc, handle);
case MemberReferenceKind.Field:
return new Entities.MemberReferenceField(gc, handle);
return new MemberReferenceField(gc, handle);
default:
throw new InternalError("Unhandled member reference handle");
}
}
#region Strings
readonly Dictionary<StringHandle, StringId> stringHandleIds = new Dictionary<StringHandle, StringId>();
readonly Dictionary<string, StringId> stringIds = new Dictionary<string, StringId>();
/// <summary>
/// Return an ID containing the given string.
/// Gets the string for a string handle.
/// </summary>
/// <param name="h">The string handle.</param>
/// <returns>An ID.</returns>
public StringId GetId(StringHandle h)
{
StringId result;
if (!stringHandleIds.TryGetValue(h, out result))
{
result = new StringId(mdReader.GetString(h));
stringHandleIds.Add(h, result);
}
return result;
}
public readonly StringId Dot = new StringId(".");
/// <summary>
/// Gets an ID containing the given string.
/// Caches existing IDs for more compact storage.
/// </summary>
/// <param name="str">The string.</param>
/// <returns>An ID containing the string.</returns>
public StringId GetId(string str)
{
StringId result;
if (!stringIds.TryGetValue(str, out result))
{
result = new StringId(str);
stringIds.Add(str, result);
}
return result;
}
#endregion
/// <returns>The string.</returns>
public string GetString(StringHandle h) => mdReader.GetString(h);
#region Namespaces
readonly CachedFunction<StringHandle, Entities.Namespace> namespaceFactory;
readonly CachedFunction<StringHandle, Namespace> namespaceFactory;
public Entities.Namespace CreateNamespace(StringHandle fqn) => namespaceFactory[fqn];
public Namespace CreateNamespace(StringHandle fqn) => namespaceFactory[fqn];
readonly Lazy<Entities.Namespace> globalNamespace, systemNamespace;
readonly Lazy<Namespace> globalNamespace, systemNamespace;
/// <summary>
/// The entity representing the global namespace.
/// </summary>
public Entities.Namespace GlobalNamespace => globalNamespace.Value;
public Namespace GlobalNamespace => globalNamespace.Value;
/// <summary>
/// The entity representing the System namespace.
/// </summary>
public Entities.Namespace SystemNamespace => systemNamespace.Value;
public Namespace SystemNamespace => systemNamespace.Value;
/// <summary>
/// Creates a namespace from a fully-qualified name.
/// </summary>
/// <param name="fqn">The fully-qualified namespace name.</param>
/// <returns>The namespace entity.</returns>
Entities.Namespace CreateNamespace(string fqn) => Populate(new Entities.Namespace(this, fqn));
Namespace CreateNamespace(string fqn) => Populate(new Namespace(this, fqn));
readonly CachedFunction<NamespaceDefinitionHandle, Entities.Namespace> namespaceDefinitionFactory;
readonly CachedFunction<NamespaceDefinitionHandle, Namespace> namespaceDefinitionFactory;
/// <summary>
/// Creates a namespace from a namespace handle.
/// </summary>
/// <param name="handle">The handle of the namespace.</param>
/// <returns>The namespace entity.</returns>
public Entities.Namespace Create(NamespaceDefinitionHandle handle) => namespaceDefinitionFactory[handle];
public Namespace Create(NamespaceDefinitionHandle handle) => namespaceDefinitionFactory[handle];
Entities.Namespace CreateNamespace(NamespaceDefinitionHandle handle)
Namespace CreateNamespace(NamespaceDefinitionHandle handle)
{
if (handle.IsNil) return GlobalNamespace;
NamespaceDefinition nd = mdReader.GetNamespaceDefinition(handle);
return Populate(new Entities.Namespace(this, GetId(nd.Name), Create(nd.Parent)));
return Populate(new Namespace(this, GetString(nd.Name), Create(nd.Parent)));
}
#endregion
#region Locations
readonly CachedFunction<PDB.ISourceFile, Entities.PdbSourceFile> sourceFiles;
readonly CachedFunction<string, Entities.Folder> folders;
readonly CachedFunction<PDB.Location, Entities.PdbSourceLocation> sourceLocations;
readonly CachedFunction<PDB.ISourceFile, PdbSourceFile> sourceFiles;
readonly CachedFunction<string, Folder> folders;
readonly CachedFunction<PDB.Location, PdbSourceLocation> sourceLocations;
/// <summary>
/// Creates a source file entity from a PDB source file.
/// </summary>
/// <param name="file">The PDB source file.</param>
/// <returns>A source file entity.</returns>
public Entities.PdbSourceFile CreateSourceFile(PDB.ISourceFile file) => sourceFiles[file];
public PdbSourceFile CreateSourceFile(PDB.ISourceFile file) => sourceFiles[file];
/// <summary>
/// Creates a folder entitiy with the given path.
/// </summary>
/// <param name="path">The path of the folder.</param>
/// <returns>A folder entity.</returns>
public Entities.Folder CreateFolder(string path) => folders[path];
public Folder CreateFolder(string path) => folders[path];
/// <summary>
/// Creates a source location.
/// </summary>
/// <param name="loc">The source location from PDB.</param>
/// <returns>A source location entity.</returns>
public Entities.PdbSourceLocation CreateSourceLocation(PDB.Location loc) => sourceLocations[loc];
public PdbSourceLocation CreateSourceLocation(PDB.Location loc) => sourceLocations[loc];
#endregion
readonly CachedFunction<GenericContext, Handle, ILabelledEntity> genericHandleFactory;
readonly CachedFunction<GenericContext, Handle, IExtractedEntity> genericHandleFactory;
/// <summary>
/// Gets the short name of a member, without the preceding interface qualifier.

View File

@@ -1,202 +1,31 @@
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL
{
/// <summary>
/// An ID fragment which is designed to be shared, reused
/// and composed using the + operator.
/// </summary>
public abstract class Id : IId
{
public void AppendTo(ITrapBuilder tb)
{
tb.Append("@\"");
BuildParts(tb);
tb.Append("\"");
}
public abstract void BuildParts(ITrapBuilder tb);
public static Id operator +(Id l1, Id l2) => Create(l1, l2);
public static Id operator +(Id l1, string l2) => Create(l1, Create(l2));
public static Id operator +(Id l1, int l2) => Create(l1, Create(l2));
public static Id operator +(string l1, Id l2) => Create(Create(l1), l2);
public static Id operator +(int l1, Id l2) => Create(Create(l1), l2);
public static Id Create(string s) => s == null ? null : new StringId(s);
public static Id Create(int i) => new IntId(i);
static readonly Id openCurly = Create("{#");
static readonly Id closeCurly = Create("}");
public static Id Create(Label l) => openCurly + l.Value + closeCurly;
static readonly Id comma = Id.Create(",");
public static Id CommaSeparatedList(IEnumerable<Id> items)
{
Id result = null;
bool first = true;
foreach (var i in items)
{
if (first) first = false; else result += comma;
result += i;
}
return result;
}
public static Id Create(Id l1, Id l2)
{
return l1 == null ? l2 : l2 == null ? l1 : new ConsId(l1, l2);
}
public abstract string Value { get; }
public override string ToString() => Value;
}
/// <summary>
/// An ID concatenating two other IDs.
/// </summary>
public sealed class ConsId : Id
{
readonly Id left, right;
readonly int hash;
public ConsId(Id l1, Id l2)
{
left = l1;
right = l2;
hash = unchecked(12 + 3 * (left.GetHashCode() + 51 * right.GetHashCode()));
}
public override void BuildParts(ITrapBuilder tb)
{
left.BuildParts(tb);
right.BuildParts(tb);
}
public override bool Equals(object other)
{
return other is ConsId && Equals((ConsId)other);
}
public bool Equals(ConsId other)
{
return this == other ||
(hash == other.hash && left.Equals(other.left) && right.Equals(other.right));
}
public override int GetHashCode() => hash;
public override string Value => left.Value + right.Value;
}
/// <summary>
/// A leaf ID storing a string.
/// </summary>
public sealed class StringId : Id
{
readonly string value;
public override string Value => value;
public StringId(string s)
{
value = s;
}
public override void BuildParts(ITrapBuilder tb)
{
tb.Append(value);
}
public override bool Equals(object obj)
{
return obj is StringId && ((StringId)obj).value == value;
}
public override int GetHashCode() => Value.GetHashCode() * 31 + 9;
}
/// <summary>
/// A leaf ID storing an integer.
/// </summary>
public sealed class IntId : Id
{
readonly int value;
public override string Value => value.ToString();
public IntId(int i)
{
value = i;
}
public override void BuildParts(ITrapBuilder tb)
{
tb.Append(value);
}
public override bool Equals(object obj)
{
return obj is IntId && ((IntId)obj).value == value;
}
public override int GetHashCode() => unchecked(12 + value * 17);
}
/// <summary>
/// Some predefined IDs.
/// </summary>
public static class IdUtils
{
public static StringId boolId = new StringId("Boolean");
public static StringId byteId = new StringId("Byte");
public static StringId charId = new StringId("Char");
public static StringId doubleId = new StringId("Double");
public static StringId shortId = new StringId("Int16");
public static StringId intId = new StringId("Int32");
public static StringId longId = new StringId("Int64");
public static StringId intptrId = new StringId("IntPtr");
public static StringId objectId = new StringId("Object");
public static StringId sbyteId = new StringId("SByte");
public static StringId floatId = new StringId("Single");
public static StringId stringId = new StringId("String");
public static StringId ushortId = new StringId("UInt16");
public static StringId uintId = new StringId("UInt32");
public static StringId ulongId = new StringId("UInt64");
public static StringId uintptrId = new StringId("UIntPtr");
public static StringId voidId = new StringId("Void");
public static StringId typedReferenceId = new StringId("TypedReference");
public static StringId Id(this PrimitiveTypeCode typeCode)
public static string Id(this PrimitiveTypeCode typeCode)
{
switch (typeCode)
{
case PrimitiveTypeCode.Boolean: return boolId;
case PrimitiveTypeCode.Byte: return byteId;
case PrimitiveTypeCode.Char: return charId;
case PrimitiveTypeCode.Double: return doubleId;
case PrimitiveTypeCode.Int16: return shortId;
case PrimitiveTypeCode.Int32: return intId;
case PrimitiveTypeCode.Int64: return longId;
case PrimitiveTypeCode.IntPtr: return intptrId;
case PrimitiveTypeCode.Object: return objectId;
case PrimitiveTypeCode.SByte: return sbyteId;
case PrimitiveTypeCode.Single: return floatId;
case PrimitiveTypeCode.String: return stringId;
case PrimitiveTypeCode.UInt16: return ushortId;
case PrimitiveTypeCode.UInt32: return uintId;
case PrimitiveTypeCode.UInt64: return ulongId;
case PrimitiveTypeCode.UIntPtr: return uintptrId;
case PrimitiveTypeCode.Void: return voidId;
case PrimitiveTypeCode.TypedReference: return typedReferenceId;
case PrimitiveTypeCode.Boolean: return "Boolean";
case PrimitiveTypeCode.Byte: return "Byte";
case PrimitiveTypeCode.Char: return "Char";
case PrimitiveTypeCode.Double: return "Double";
case PrimitiveTypeCode.Int16: return "Int16";
case PrimitiveTypeCode.Int32: return "Int32";
case PrimitiveTypeCode.Int64: return "Int64";
case PrimitiveTypeCode.IntPtr: return "IntPtr";
case PrimitiveTypeCode.Object: return "Object";
case PrimitiveTypeCode.SByte: return "SByte";
case PrimitiveTypeCode.Single: return "Single";
case PrimitiveTypeCode.String: return "String";
case PrimitiveTypeCode.UInt16: return "UInt16";
case PrimitiveTypeCode.UInt32: return "UInt32";
case PrimitiveTypeCode.UInt64: return "UInt64";
case PrimitiveTypeCode.UIntPtr: return "UIntPtr";
case PrimitiveTypeCode.Void: return "Void";
case PrimitiveTypeCode.TypedReference: return "TypedReference";
default: throw new InternalError($"Unhandled type code {typeCode}");
}
}

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
@@ -8,6 +8,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>DEBUG;DEBUG_LABELS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>

View File

@@ -228,7 +228,7 @@ namespace Semmle.Extraction.CSharp
var assemblyPath = extractor.OutputPath;
var assembly = compilation.Assembly;
var projectLayout = layout.LookupProjectOrDefault(assemblyPath);
var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true);
var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true, options.TrapCompression);
compilationTrapFile = trapWriter; // Dispose later
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new AssemblyScope(assembly, assemblyPath, true));
@@ -257,7 +257,7 @@ namespace Semmle.Extraction.CSharp
var assemblyPath = r.FilePath;
var projectLayout = layout.LookupProjectOrDefault(assemblyPath);
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true))
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, assemblyPath, true, options.TrapCompression))
{
var skipExtraction = FileIsCached(assemblyPath, trapWriter.TrapFile);
@@ -311,7 +311,7 @@ namespace Semmle.Extraction.CSharp
stopwatch.Start();
string trapFile;
bool extracted;
CIL.Entities.Assembly.ExtractCIL(layout, r.FilePath, Logger, !options.Cache, options.PDB, out trapFile, out extracted);
CIL.Entities.Assembly.ExtractCIL(layout, r.FilePath, Logger, !options.Cache, options.PDB, options.TrapCompression, out trapFile, out extracted);
stopwatch.Stop();
ReportProgress(r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate);
}
@@ -359,13 +359,13 @@ namespace Semmle.Extraction.CSharp
var projectLayout = layout.LookupProjectOrNull(sourcePath);
bool excluded = projectLayout == null;
string trapPath = excluded ? "" : projectLayout.GetTrapPath(Logger, sourcePath);
string trapPath = excluded ? "" : projectLayout.GetTrapPath(Logger, sourcePath, options.TrapCompression);
bool upToDate = false;
if (!excluded)
{
// compilation.Clone() is used to allow symbols to be garbage collected.
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, sourcePath, false))
using (var trapWriter = projectLayout.CreateTrapWriter(Logger, sourcePath, false, options.TrapCompression))
{
upToDate = options.Fast && FileIsUpToDate(sourcePath, trapWriter.TrapFile);
@@ -375,6 +375,7 @@ namespace Semmle.Extraction.CSharp
Populators.CompilationUnit.Extract(cx, tree.GetRoot());
cx.PopulateAll();
cx.ExtractComments(cx.CommentGenerator);
cx.PopulateAll();
}
}
}

View File

@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -30,11 +31,11 @@ namespace Semmle.Extraction.CSharp.Entities
public new Accessor OriginalDefinition => Create(Context, symbol.OriginalDefinition);
public override void Populate()
public override void Populate(TextWriter trapFile)
{
PopulateMethod();
ExtractModifiers();
ContainingType.ExtractGenerics();
PopulateMethod(trapFile);
PopulateModifiers(trapFile);
ContainingType.PopulateGenerics();
var prop = PropertySymbol;
if (prop == null)
@@ -62,16 +63,16 @@ namespace Semmle.Extraction.CSharp.Entities
return;
}
Context.Emit(Tuples.accessors(this, kind, symbol.Name, parent, unboundAccessor));
trapFile.accessors(this, kind, symbol.Name, parent, unboundAccessor);
foreach (var l in Locations)
Context.Emit(Tuples.accessor_location(this, l));
trapFile.accessor_location(this, l);
Overrides();
Overrides(trapFile);
if (symbol.FromSource() && Block == null)
{
Context.Emit(Tuples.compiler_generated(this));
trapFile.compiler_generated(this);
}
}

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -11,17 +12,27 @@ namespace Semmle.Extraction.CSharp.Entities
{
bool IExpressionParentEntity.IsTopLevelParent => true;
private readonly AttributeData AttributeData;
private readonly IEntity Entity;
public Attribute(Context cx, AttributeData attribute, IEntity entity)
: base(cx)
{
if (attribute.ApplicationSyntaxReference != null)
AttributeData = attribute;
Entity = entity;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
{
if (AttributeData.ApplicationSyntaxReference != null)
{
// !! Extract attributes from assemblies.
// This is harder because the "expression" entities presume the
// existence of a syntax tree. This is not the case for compiled
// attributes.
var syntax = attribute.ApplicationSyntaxReference.GetSyntax() as AttributeSyntax;
ExtractAttribute(syntax, attribute.AttributeClass, entity);
var syntax = AttributeData.ApplicationSyntaxReference.GetSyntax() as AttributeSyntax;
ExtractAttribute(cx.TrapWriter.Writer, syntax, AttributeData.AttributeClass, Entity);
}
}
@@ -29,18 +40,18 @@ namespace Semmle.Extraction.CSharp.Entities
: base(cx)
{
var info = cx.GetSymbolInfo(attribute);
ExtractAttribute(attribute, info.Symbol.ContainingType, entity);
ExtractAttribute(cx.TrapWriter.Writer, attribute, info.Symbol.ContainingType, entity);
}
void ExtractAttribute(AttributeSyntax syntax, ITypeSymbol attributeClass, IEntity entity)
void ExtractAttribute(System.IO.TextWriter trapFile, AttributeSyntax syntax, ITypeSymbol attributeClass, IEntity entity)
{
var type = Type.Create(cx, attributeClass);
cx.Emit(Tuples.attributes(this, type.TypeRef, entity));
trapFile.attributes(this, type.TypeRef, entity);
cx.Emit(Tuples.attribute_location(this, cx.Create(syntax.Name.GetLocation())));
trapFile.attribute_location(this, cx.Create(syntax.Name.GetLocation()));
if (cx.Extractor.OutputPath != null)
cx.Emit(Tuples.attribute_location(this, Assembly.CreateOutputAssembly(cx)));
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(cx));
TypeMention.Create(cx, syntax.Name, this, type);
@@ -54,7 +65,7 @@ namespace Semmle.Extraction.CSharp.Entities
var expr = Expression.Create(cx, arg.Expression, this, child++);
if (!(arg.NameEquals is null))
{
cx.Emit(Tuples.expr_argument_name(expr, arg.NameEquals.Name.Identifier.Text));
trapFile.expr_argument_name(expr, arg.NameEquals.Name.Identifier.Text);
}
}
});

View File

@@ -1,5 +1,6 @@
using Semmle.Extraction.CommentProcessing;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -8,33 +9,30 @@ namespace Semmle.Extraction.CSharp.Entities
CommentBlock(Context cx, ICommentBlock init)
: base(cx, init) { }
public override void Populate()
public override void Populate(TextWriter trapFile)
{
Context.Emit(Tuples.commentblock(this));
trapFile.commentblock(this);
int child = 0;
Context.Emit(Tuples.commentblock_location(this, Context.Create(symbol.Location)));
trapFile.commentblock_location(this, Context.Create(symbol.Location));
foreach (var l in symbol.CommentLines)
{
Context.Emit(Tuples.commentblock_child(this, (CommentLine)l, child++));
trapFile.commentblock_child(this, (CommentLine)l, child++);
}
}
public override bool NeedsPopulation => true;
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
var loc = Context.Create(symbol.Location);
return new Key(loc, ";commentblock");
}
trapFile.WriteSubId(Context.Create(symbol.Location));
trapFile.Write(";commentblock");
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => symbol.Location;
public void BindTo(Label entity, Binding binding)
public void BindTo(Label entity, CommentBinding binding)
{
Context.Emit(Tuples.commentblock_binding(this, entity, binding));
Context.TrapWriter.Writer.commentblock_binding(this, entity, binding);
}
public static CommentBlock Create(Context cx, ICommentBlock block) => CommentBlockFactory.Instance.CreateEntity(cx, block);

View File

@@ -2,13 +2,13 @@ using Semmle.Extraction.CommentProcessing;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
using System;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
class CommentLine : CachedEntity<(Microsoft.CodeAnalysis.Location, string)>, ICommentLine
{
CommentLine(Context cx, Microsoft.CodeAnalysis.Location loc, CommentType type, string text, string raw)
CommentLine(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw)
: base(cx, (loc, text))
{
Type = type;
@@ -16,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
public Microsoft.CodeAnalysis.Location Location => symbol.Item1;
public CommentType Type { get; private set; }
public CommentLineType Type { get; private set; }
public string Text { get { return symbol.Item2; } }
public string RawText { get; private set; }
@@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities
var span = Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(currentLocation, currentLocation + fullLine.Length);
var location = Microsoft.CodeAnalysis.Location.Create(trivia.SyntaxTree, span);
var commentType = CommentType.XmlDoc;
var commentType = CommentLineType.XmlDoc;
cx.CommentGenerator.AddComment(Create(cx, location, commentType, trimmedLine, fullLine));
}
else
@@ -67,10 +67,10 @@ namespace Semmle.Extraction.CSharp.Entities
case SyntaxKind.SingleLineCommentTrivia:
{
string contents = trivia.ToString().Substring(2);
var commentType = CommentType.Singleline;
var commentType = CommentLineType.Singleline;
if (contents.Length > 0 && contents[0] == '/')
{
commentType = CommentType.XmlDoc;
commentType = CommentLineType.XmlDoc;
contents = contents.Substring(1); // An XML comment.
}
cx.CommentGenerator.AddComment(Create(cx, trivia.GetLocation(), commentType, contents.Trim(), trivia.ToFullString()));
@@ -98,7 +98,7 @@ namespace Semmle.Extraction.CSharp.Entities
var span = Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(currentLocation, currentLocation + fullLine.Length);
var location = Microsoft.CodeAnalysis.Location.Create(trivia.SyntaxTree, span);
var commentType = line == 0 ? CommentType.Multiline : CommentType.MultilineContinuation;
var commentType = line == 0 ? CommentLineType.Multiline : CommentLineType.MultilineContinuation;
cx.CommentGenerator.AddComment(Create(cx, location, commentType, trimmedLine, fullLine));
currentLocation = nextLineLocation;
}
@@ -112,33 +112,30 @@ namespace Semmle.Extraction.CSharp.Entities
Extraction.Entities.Location location;
public override void Populate()
public override void Populate(TextWriter trapFile)
{
location = Context.Create(Location);
Context.Emit(Tuples.commentline(this, Type == CommentType.MultilineContinuation ? CommentType.Multiline : Type, Text, RawText));
Context.Emit(Tuples.commentline_location(this, location));
trapFile.commentline(this, Type == CommentLineType.MultilineContinuation ? CommentLineType.Multiline : Type, Text, RawText);
trapFile.commentline_location(this, location);
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => location.symbol;
public override bool NeedsPopulation => true;
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
var loc = Context.Create(Location);
return new Key(loc, ";commentline");
}
trapFile.WriteSubId(Context.Create(Location));
trapFile.Write(";commentline");
}
static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentType type, string text, string raw) => CommentLineFactory.Instance.CreateEntity(cx, loc, type, text, raw);
static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw) => CommentLineFactory.Instance.CreateEntity(cx, loc, type, text, raw);
class CommentLineFactory : ICachedEntityFactory<(Microsoft.CodeAnalysis.Location, CommentType, string, string), CommentLine>
class CommentLineFactory : ICachedEntityFactory<(Microsoft.CodeAnalysis.Location, CommentLineType, string, string), CommentLine>
{
public static readonly CommentLineFactory Instance = new CommentLineFactory();
public CommentLine Create(Context cx, (Microsoft.CodeAnalysis.Location, CommentType, string, string) init) =>
public CommentLine Create(Context cx, (Microsoft.CodeAnalysis.Location, CommentLineType, string, string) init) =>
new CommentLine(cx, init.Item1, init.Item2, init.Item3, init.Item4);
}

View File

@@ -1,57 +1,67 @@
using Microsoft.CodeAnalysis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
namespace Semmle.Extraction.CSharp.Entities
{
class Compilation : FreshEntity
{
private readonly string cwd;
private readonly string[] args;
public Compilation(Context cx, string cwd, string[] args) : base(cx)
{
this.cwd = cwd;
this.args = args;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
{
Extraction.Entities.Assembly.CreateOutputAssembly(cx);
cx.Emit(Tuples.compilations(this, Extraction.Entities.File.PathAsDatabaseString(cwd)));
trapFile.compilations(this, Extraction.Entities.File.PathAsDatabaseString(cwd));
// Arguments
int index = 0;
foreach(var arg in args)
{
cx.Emit(Tuples.compilation_args(this, index++, arg));
trapFile.compilation_args(this, index++, arg);
}
// Files
index = 0;
foreach(var file in cx.Compilation.SyntaxTrees.Select(tree => Extraction.Entities.File.Create(cx, tree.FilePath)))
{
cx.Emit(Tuples.compilation_compiling_files(this, index++, file));
trapFile.compilation_compiling_files(this, index++, file);
}
// References
index = 0;
foreach(var file in cx.Compilation.References.OfType<PortableExecutableReference>().Select(r => Extraction.Entities.File.Create(cx, r.FilePath)))
{
cx.Emit(Tuples.compilation_referencing_files(this, index++, file));
trapFile.compilation_referencing_files(this, index++, file);
}
// Diagnostics
index = 0;
foreach(var diag in cx.Compilation.GetDiagnostics().Select(d => new Diagnostic(cx, d)))
{
cx.Emit(Tuples.diagnostic_for(diag, this, 0, index++));
trapFile.diagnostic_for(diag, this, 0, index++);
}
}
public void PopulatePerformance(PerformanceMetrics p)
{
var trapFile = cx.TrapWriter.Writer;
int index = 0;
foreach(float metric in p.Metrics)
{
cx.Emit(Tuples.compilation_time(this, -1, index++, metric));
trapFile.compilation_time(this, -1, index++, metric);
}
cx.Emit(Tuples.compilation_finished(this, (float)p.Total.Cpu.TotalSeconds, (float)p.Total.Elapsed.TotalSeconds));
trapFile.compilation_finished(this, (float)p.Total.Cpu.TotalSeconds, (float)p.Total.Elapsed.TotalSeconds);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
@@ -61,10 +71,18 @@ namespace Semmle.Extraction.CSharp.Entities
{
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
readonly Microsoft.CodeAnalysis.Diagnostic diagnostic;
public Diagnostic(Context cx, Microsoft.CodeAnalysis.Diagnostic diag) : base(cx)
{
cx.Emit(Tuples.diagnostics(this, (int)diag.Severity, diag.Id, diag.Descriptor.Title.ToString(),
diag.GetMessage(), Extraction.Entities.Location.Create(cx, diag.Location)));
diagnostic = diag;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
{
trapFile.diagnostics(this, (int)diagnostic.Severity, diagnostic.Id, diagnostic.Descriptor.Title.ToString(),
diagnostic.GetMessage(), Extraction.Entities.Location.Create(cx, diagnostic.Location));
}
}

View File

@@ -5,6 +5,7 @@ using Semmle.Util;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -13,24 +14,24 @@ namespace Semmle.Extraction.CSharp.Entities
Constructor(Context cx, IMethodSymbol init)
: base(cx, init) { }
public override void Populate()
public override void Populate(TextWriter trapFile)
{
PopulateMethod();
ExtractModifiers();
ContainingType.ExtractGenerics();
PopulateMethod(trapFile);
PopulateModifiers(trapFile);
ContainingType.PopulateGenerics();
Context.Emit(Tuples.constructors(this, symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition));
Context.Emit(Tuples.constructor_location(this, Location));
trapFile.constructors(this, symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition);
trapFile.constructor_location(this, Location);
if (symbol.IsImplicitlyDeclared)
{
var lineCounts = new LineCounts() { Total = 2, Code = 1, Comment = 0 };
Context.Emit(Tuples.numlines(this, lineCounts));
trapFile.numlines(this, lineCounts);
}
ExtractCompilerGenerated();
ExtractCompilerGenerated(trapFile);
}
protected override void ExtractInitializers()
protected override void ExtractInitializers(TextWriter trapFile)
{
// Do not extract initializers for constructed types.
if (!IsSourceDeclaration) return;
@@ -75,7 +76,7 @@ namespace Semmle.Extraction.CSharp.Entities
return;
}
Context.Emit(Tuples.expr_call(init, target));
trapFile.expr_call(init, target);
int child = 0;
foreach (var arg in initializer.ArgumentList.Arguments)
@@ -109,18 +110,12 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
return new Key(tb =>
{
if (symbol.IsStatic) tb.Append("static");
tb.Append(ContainingType);
AddParametersToId(Context, tb, symbol);
tb.Append(";constructor");
});
}
if (symbol.IsStatic) trapFile.Write("static");
trapFile.WriteSubId(ContainingType);
AddParametersToId(Context, trapFile, symbol);
trapFile.Write(";constructor");
}
ConstructorDeclarationSyntax GetSyntax() =>

View File

@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -7,14 +8,14 @@ namespace Semmle.Extraction.CSharp.Entities
Destructor(Context cx, IMethodSymbol init)
: base(cx, init) { }
public override void Populate()
public override void Populate(TextWriter trapFile)
{
PopulateMethod();
ExtractModifiers();
ContainingType.ExtractGenerics();
PopulateMethod(trapFile);
PopulateModifiers(trapFile);
ContainingType.PopulateGenerics();
Context.Emit(Tuples.destructors(this, string.Format("~{0}", symbol.ContainingType.Name), ContainingType, OriginalDefinition(Context, this, symbol)));
Context.Emit(Tuples.destructor_location(this, Location));
trapFile.destructors(this, string.Format("~{0}", symbol.ContainingType.Name), ContainingType, OriginalDefinition(Context, this, symbol));
trapFile.destructor_location(this, Location);
}
static new Destructor OriginalDefinition(Context cx, Destructor original, IMethodSymbol symbol)

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -9,27 +10,21 @@ namespace Semmle.Extraction.CSharp.Entities
Event(Context cx, IEventSymbol init)
: base(cx, init) { }
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
return new Key(tb =>
{
tb.Append(ContainingType);
tb.Append(".");
Method.AddExplicitInterfaceQualifierToId(Context, tb, symbol.ExplicitInterfaceImplementations);
tb.Append(symbol.Name);
tb.Append(";event");
});
}
trapFile.WriteSubId(ContainingType);
trapFile.Write('.');
Method.AddExplicitInterfaceQualifierToId(Context, trapFile, symbol.ExplicitInterfaceImplementations);
trapFile.Write(symbol.Name);
trapFile.Write(";event");
}
public override void Populate()
public override void Populate(TextWriter trapFile)
{
ExtractNullability(symbol.NullableAnnotation);
PopulateNullability(trapFile, symbol.NullableAnnotation);
var type = Type.Create(Context, symbol.Type);
Context.Emit(Tuples.events(this, symbol.GetName(), ContainingType, type.TypeRef, Create(Context, symbol.OriginalDefinition)));
trapFile.events(this, symbol.GetName(), ContainingType, type.TypeRef, Create(Context, symbol.OriginalDefinition));
var adder = symbol.AddMethod;
var remover = symbol.RemoveMethod;
@@ -40,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities
if (!(remover is null))
Method.Create(Context, remover);
ExtractModifiers();
PopulateModifiers(trapFile);
BindComments();
var declSyntaxReferences = IsSourceDeclaration
@@ -49,14 +44,14 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var explicitInterface in symbol.ExplicitInterfaceImplementations.Select(impl => Type.Create(Context, impl.ContainingType)))
{
Context.Emit(Tuples.explicitly_implements(this, explicitInterface.TypeRef));
trapFile.explicitly_implements(this, explicitInterface.TypeRef);
foreach (var syntax in declSyntaxReferences.OfType<EventDeclarationSyntax>())
TypeMention.Create(Context, syntax.ExplicitInterfaceSpecifier.Name, this, explicitInterface);
}
foreach (var l in Locations)
Context.Emit(Tuples.event_location(this, l));
trapFile.event_location(this, l);
foreach (var syntaxType in declSyntaxReferences.OfType<VariableDeclaratorSyntax>().
Select(d => d.Parent).

View File

@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -12,10 +13,10 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary>
IEventSymbol EventSymbol => symbol.AssociatedSymbol as IEventSymbol;
public override void Populate()
public override void Populate(TextWriter trapFile)
{
PopulateMethod();
ContainingType.ExtractGenerics();
PopulateMethod(trapFile);
ContainingType.PopulateGenerics();
var @event = EventSymbol;
if (@event == null)
@@ -43,12 +44,12 @@ namespace Semmle.Extraction.CSharp.Entities
return;
}
Context.Emit(Tuples.event_accessors(this, kind, symbol.Name, parent, unboundAccessor));
trapFile.event_accessors(this, kind, symbol.Name, parent, unboundAccessor);
foreach (var l in Locations)
Context.Emit(Tuples.event_accessor_location(this, l));
trapFile.event_accessor_location(this, l);
Overrides();
Overrides(trapFile);
}
public new static EventAccessor Create(Context cx, IMethodSymbol symbol) =>

View File

@@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -18,6 +19,7 @@ namespace Semmle.Extraction.CSharp.Entities
class Expression : FreshEntity, IExpressionParentEntity
{
private readonly IExpressionInfo Info;
public readonly AnnotatedType Type;
public readonly Extraction.Entities.Location Location;
public readonly ExprKind Kind;
@@ -25,27 +27,32 @@ namespace Semmle.Extraction.CSharp.Entities
internal Expression(IExpressionInfo info)
: base(info.Context)
{
Info = info;
Location = info.Location;
Kind = info.Kind;
Type = info.Type;
if (Type.Type is null)
Type = NullType.Create(cx);
cx.Emit(Tuples.expressions(this, Kind, Type.Type.TypeRef));
if (info.Parent.IsTopLevelParent)
cx.Emit(Tuples.expr_parent_top_level(this, info.Child, info.Parent));
TryPopulate();
}
protected sealed override void Populate(TextWriter trapFile)
{
trapFile.expressions(this, Kind, Type.Type.TypeRef);
if (Info.Parent.IsTopLevelParent)
trapFile.expr_parent_top_level(this, Info.Child, Info.Parent);
else
cx.Emit(Tuples.expr_parent(this, info.Child, info.Parent));
cx.Emit(Tuples.expr_location(this, Location));
trapFile.expr_parent(this, Info.Child, Info.Parent);
trapFile.expr_location(this, Location);
if (info.IsCompilerGenerated)
cx.Emit(Tuples.expr_compiler_generated(this));
if (Info.IsCompilerGenerated)
trapFile.expr_compiler_generated(this);
if (info.ExprValue is string value)
cx.Emit(Tuples.expr_value(this, value));
if (Info.ExprValue is string value)
trapFile.expr_value(this, value);
Type.Type.ExtractGenerics();
Type.Type.PopulateGenerics();
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => Location.symbol;
@@ -117,21 +124,20 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary>
/// <param name="cx">Context</param>
/// <param name="node">The expression.</param>
public void OperatorCall(ExpressionSyntax node)
public void OperatorCall(TextWriter trapFile, ExpressionSyntax node)
{
var @operator = cx.GetSymbolInfo(node);
if (@operator.Symbol is IMethodSymbol method)
{
var callType = GetCallType(cx, node);
if (callType == CallType.Dynamic)
{
UserOperator.OperatorSymbol(method.Name, out string operatorName);
cx.Emit(Tuples.dynamic_member_name(this, operatorName));
trapFile.dynamic_member_name(this, operatorName);
return;
}
cx.Emit(Tuples.expr_call(this, Method.Create(cx, method)));
trapFile.expr_call(this, Method.Create(cx, method));
}
}
@@ -203,18 +209,18 @@ namespace Semmle.Extraction.CSharp.Entities
throw new InternalError(node, "Unable to locate a ConditionalAccessExpression");
}
public void MakeConditional()
public void MakeConditional(TextWriter trapFile)
{
cx.Emit(Tuples.conditional_access(this));
trapFile.conditional_access(this);
}
public void PopulateArguments(BaseArgumentListSyntax args, int child)
public void PopulateArguments(TextWriter trapFile, BaseArgumentListSyntax args, int child)
{
foreach (var arg in args.Arguments)
PopulateArgument(arg, child++);
PopulateArgument(trapFile, arg, child++);
}
private void PopulateArgument(ArgumentSyntax arg, int child)
private void PopulateArgument(TextWriter trapFile, ArgumentSyntax arg, int child)
{
var expr = Create(cx, arg.Expression, this, child);
int mode;
@@ -235,11 +241,11 @@ namespace Semmle.Extraction.CSharp.Entities
default:
throw new InternalError(arg, "Unknown argument type");
}
cx.Emit(Tuples.expr_argument(expr, mode));
trapFile.expr_argument(expr, mode);
if (arg.NameColon != null)
{
cx.Emit(Tuples.expr_argument_name(expr, arg.NameColon.Name.Identifier.Text));
trapFile.expr_argument_name(expr, arg.NameColon.Name.Identifier.Text);
}
}
@@ -285,11 +291,11 @@ namespace Semmle.Extraction.CSharp.Entities
/// <see cref="Expression.Create(Context, ExpressionSyntax, IEntity, int, ITypeSymbol)"/> will
/// still be valid.
/// </summary>
protected abstract void Populate();
protected abstract void PopulateExpression(TextWriter trapFile);
protected Expression TryPopulate()
protected new Expression TryPopulate()
{
cx.Try(Syntax, null, Populate);
cx.Try(Syntax, null, ()=>PopulateExpression(cx.TrapWriter.Writer));
return this;
}
}
@@ -384,7 +390,7 @@ namespace Semmle.Extraction.CSharp.Entities
Parent = parent;
Child = child;
TypeInfo = typeInfo;
Conversion = cx.Model(node).GetConversion(node);
Conversion = cx.GetModel(node).GetConversion(node);
}
public Context Context { get; }
@@ -443,7 +449,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public SemanticModel Model => Context.Model(Node);
public SemanticModel Model => Context.GetModel(Node);
public string ExprValue
{

View File

@@ -45,7 +45,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Access(ExpressionNodeInfo info, ISymbol symbol, bool implicitThis, IEntity target)
: base(info.SetKind(AccessKind(info.Context, symbol)))
{
cx.Emit(Tuples.expr_access(this, target));
cx.TrapWriter.Writer.expr_access(this, target);
if (implicitThis && !symbol.IsStatic)
{

View File

@@ -1,6 +1,7 @@
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -8,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
ArgList(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.UNKNOWN)) { }
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
throw new NotImplementedException();
}

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities.Expressions
@@ -18,7 +19,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public abstract InitializerExpressionSyntax Initializer { get; }
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var child = 0;
var explicitlySized = false;
@@ -66,7 +67,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
if (explicitlySized)
cx.Emit(Tuples.explicitly_sized_array_creation(this));
trapFile.explicitly_sized_array_creation(this);
}
}
@@ -98,14 +99,14 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new ImplicitArrayCreation(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
if (Syntax.Initializer != null)
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1));
}
cx.Emit(Tuples.implicitly_typed_array_creation(this));
trapFile.implicitly_typed_array_creation(this);
}
}
}

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -20,7 +21,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return ret;
}
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var operatorKind = OperatorKind;
if (operatorKind.HasValue)
@@ -31,7 +32,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var opexpr = new Expression(new ExpressionInfo(cx, Type, Location, operatorKind.Value, simpleAssignExpr, 0, false, null));
Create(cx, Syntax.Left, opexpr, 0);
Create(cx, Syntax.Right, opexpr, 1);
opexpr.OperatorCall(Syntax);
opexpr.OperatorCall(trapFile, Syntax);
}
else
{
@@ -40,7 +41,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (Kind == ExprKind.ADD_EVENT || Kind == ExprKind.REMOVE_EVENT)
{
OperatorCall(Syntax);
OperatorCall(trapFile, Syntax);
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Await(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -13,9 +14,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Binary(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
OperatorCall(Syntax);
OperatorCall(trapFile, Syntax);
CreateDeferred(cx, Syntax.Left, this, 0);
CreateDeferred(cx, Syntax.Right, this, 1);
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Cast(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
@@ -19,7 +20,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
else
{
// Type conversion
OperatorCall(Syntax);
OperatorCall(trapFile, Syntax);
TypeMention.Create(cx, Syntax.Type, this, Type);
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Checked(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Conditional(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Condition, this, 0);
Create(cx, Syntax.WhenTrue, this, 1);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Default(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
TypeAccess.Create(cx, Syntax.Type, this, 0);
}

View File

@@ -4,6 +4,7 @@ using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -19,7 +20,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
readonly ExpressionSyntax Qualifier;
readonly BracketedArgumentListSyntax ArgumentList;
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
if (Kind == ExprKind.POINTER_INDIRECTION)
{
@@ -27,7 +28,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var add = new Expression(new ExpressionInfo(cx, qualifierInfo.Type, Location, ExprKind.ADD, this, 0, false, null));
qualifierInfo.SetParent(add, 0);
CreateFromNode(qualifierInfo);
PopulateArguments(ArgumentList, 1);
PopulateArguments(trapFile, ArgumentList, 1);
}
else
{
@@ -43,7 +44,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var indexer = symbolInfo.Symbol as IPropertySymbol;
if (indexer != null)
{
cx.Emit(Tuples.expr_access(this, Indexer.Create(cx, indexer)));
trapFile.expr_access(this, Indexer.Create(cx, indexer));
}
}
}
@@ -86,10 +87,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new BindingElementAccess(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
base.Populate();
MakeConditional();
base.PopulateExpression(trapFile);
MakeConditional(trapFile);
}
}
}

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -27,7 +28,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var target = Method.Create(cx, method);
if (target != null)
cx.Emit(Tuples.expr_call(this, target));
cx.TrapWriter.Writer.expr_call(this, target);
else
cx.ModelError(info.Node, "Failed to resolve target for operator invocation");
}

View File

@@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -18,7 +19,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new ArrayInitializer(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var child = 0;
foreach (var e in Syntax.Expressions)
@@ -44,10 +45,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new ImplicitArrayInitializer(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax, this, -1));
cx.Emit(Tuples.implicitly_typed_array_creation(this));
trapFile.implicitly_typed_array_creation(this);
}
}
@@ -58,7 +59,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new ObjectInitializer(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var child = 0;
@@ -98,19 +99,19 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new CollectionInitializer(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var child = 0;
foreach (var i in Syntax.Expressions)
{
var collectionInfo = cx.Model(Syntax).GetCollectionInitializerSymbolInfo(i);
var collectionInfo = cx.GetModel(Syntax).GetCollectionInitializerSymbolInfo(i);
var addMethod = Method.Create(cx, collectionInfo.Symbol as IMethodSymbol);
var voidType = Entities.Type.Create(cx, new AnnotatedTypeSymbol(cx.Compilation.GetSpecialType(SpecialType.System_Void), NullableAnnotation.NotApplicable));
var invocation = new Expression(new ExpressionInfo(cx, voidType, cx.Create(i.GetLocation()), ExprKind.METHOD_INVOCATION, this, child++, false, null));
if (addMethod != null)
cx.Emit(Tuples.expr_call(invocation, addMethod));
trapFile.expr_call(invocation, addMethod);
else
cx.ModelError(Syntax, "Unable to find an Add() method for collection initializer");

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -12,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new InterpolatedString(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var child = 0;
foreach (var c in Syntax.Contents)

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -18,11 +19,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Invocation(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
if (IsNameof(Syntax))
{
PopulateArguments(Syntax.ArgumentList, 0);
PopulateArguments(trapFile, Syntax.ArgumentList, 0);
return;
}
@@ -44,7 +45,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
// Conditionally qualified method call; `x?.M()`
memberName = memberBinding.Name.Identifier.Text;
Create(cx, FindConditionalQualifier(memberBinding), this, child++);
MakeConditional();
MakeConditional(trapFile);
break;
case SimpleNameSyntax simpleName when (Kind == ExprKind.METHOD_INVOCATION):
// Unqualified method call; `M()`
@@ -52,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (target != null && !target.IsStatic)
{
// Implicit `this` qualifier; add explicitly
var callingMethod = cx.Model(Syntax).GetEnclosingSymbol(Location.symbol.SourceSpan.Start) as IMethodSymbol;
var callingMethod = cx.GetModel(Syntax).GetEnclosingSymbol(Location.symbol.SourceSpan.Start) as IMethodSymbol;
if (callingMethod == null)
cx.ModelError(Syntax, "Couldn't determine implicit this type");
@@ -75,12 +76,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (isDynamicCall)
{
if (memberName != null)
cx.Emit(Tuples.dynamic_member_name(this, memberName));
trapFile.dynamic_member_name(this, memberName);
else
cx.ModelError(Syntax, "Unable to get name for dynamic call.");
}
PopulateArguments(Syntax.ArgumentList, child);
PopulateArguments(trapFile, Syntax.ArgumentList, child);
if (target == null)
{
@@ -90,7 +91,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
var targetKey = Method.Create(cx, target);
cx.Emit(Tuples.expr_call(this, targetKey));
trapFile.expr_call(this, targetKey);
}
static bool IsDynamicCall(ExpressionNodeInfo info)

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Kinds;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -20,7 +21,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
if (declPattern.Designation is VariableDesignationSyntax designation)
{
if (cx.Model(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
if (cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
{
var type = Type.Create(cx, symbol.GetAnnotatedType());
return VariableDeclaration.Create(cx, symbol, type, declPattern.Type, cx.Create(syntax.GetLocation()), cx.Create(designation.GetLocation()), false, parent, child);
@@ -43,7 +44,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case ParenthesizedVariableDesignationSyntax parDesignation:
return VariableDeclaration.CreateParenthesized(cx, varPattern, parDesignation, parent, child);
case SingleVariableDesignationSyntax varDesignation:
if (cx.Model(syntax).GetDeclaredSymbol(varDesignation) is ILocalSymbol symbol)
if (cx.GetModel(syntax).GetDeclaredSymbol(varDesignation) is ILocalSymbol symbol)
{
var type = Type.Create(cx, symbol.GetAnnotatedType());
@@ -72,10 +73,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
base(new ExpressionInfo(cx, Entities.NullType.Create(cx), cx.Create(pp.GetLocation()), ExprKind.PROPERTY_PATTERN, parent, child, false, null))
{
child = 0;
var trapFile = cx.TrapWriter.Writer;
foreach (var sub in pp.Subpatterns)
{
var p = cx.CreatePattern(sub.Pattern, this, child++);
cx.Emit(Tuples.exprorstmt_name(p, sub.NameColon.Name.ToString()));
trapFile.exprorstmt_name(p, sub.NameColon.Name.ToString());
}
}
}
@@ -111,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Expressions.TypeAccess.Create(cx, t, this, 1);
// Extract the local variable declaration
if (syntax.Designation is VariableDesignationSyntax designation && cx.Model(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
if (syntax.Designation is VariableDesignationSyntax designation && cx.GetModel(syntax).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
{
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
@@ -139,7 +141,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
private void PopulatePattern(PatternSyntax pattern, TypeSyntax optionalType, SyntaxToken varKeyword, VariableDesignationSyntax designation)
{
var isVar = optionalType is null;
if (!(designation is null) && cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
if (!(designation is null) && cx.GetModel(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
{
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 1);
@@ -148,7 +150,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Expressions.TypeAccess.Create(cx, optionalType, this, 1);
}
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
switch (Syntax.Pattern)

View File

@@ -5,6 +5,7 @@ using Microsoft.CodeAnalysis;
using System.Collections.Generic;
using Semmle.Util;
using System.Linq;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -12,11 +13,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
bool IStatementParentEntity.IsTopLevelParent => false;
protected override void Populate() { }
protected override void PopulateExpression(TextWriter trapFile) { }
void VisitParameter(ParameterSyntax p)
{
var symbol = cx.Model(p).GetDeclaredSymbol(p);
var symbol = cx.GetModel(p).GetDeclaredSymbol(p);
Parameter.Create(cx, symbol, this);
}

View File

@@ -3,6 +3,7 @@ using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.CSharp.Populators;
using Microsoft.CodeAnalysis.CSharp;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -12,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Literal(info).TryPopulate();
protected override void Populate() { }
protected override void PopulateExpression(TextWriter trapFile) { }
static ExprKind GetKind(ExpressionNodeInfo info)
{

View File

@@ -1,5 +1,6 @@
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new MakeRef(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -8,8 +8,11 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
class MemberAccess : Expression
{
readonly IEntity Target;
private MemberAccess(ExpressionNodeInfo info, ExpressionSyntax qualifier, ISymbol target) : base(info)
{
var trapFile = info.Context.TrapWriter.Writer;
Qualifier = Create(cx, qualifier, this, -1);
if (target == null)
@@ -19,7 +22,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
else
{
cx.Emit(Tuples.expr_access(this, cx.CreateEntity(target)));
Target = cx.CreateEntity(target);
trapFile.expr_access(this, Target);
}
}
@@ -31,7 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info, MemberBindingExpressionSyntax node)
{
var expr = Create(info, FindConditionalQualifier(node), node.Name);
expr.MakeConditional();
expr.MakeConditional(info.Context.TrapWriter.Writer);
return expr;
}
@@ -43,7 +47,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (IsDynamic(info.Context, expression))
{
var expr = new MemberAccess(info.SetKind(ExprKind.DYNAMIC_MEMBER_ACCESS), expression, null);
info.Context.Emit(Tuples.dynamic_member_name(expr, name.Identifier.Text));
info.Context.TrapWriter.Writer.dynamic_member_name(expr, name.Identifier.Text);
return expr;
}

View File

@@ -4,6 +4,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities.Expressions
@@ -24,7 +25,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
static ExprKind GetKind(Context cx, ObjectCreationExpressionSyntax node)
{
var si = cx.Model(node).GetSymbolInfo(node.Type);
var si = cx.GetModel(node).GetSymbolInfo(node.Type);
return Entities.Type.IsDelegate(si.Symbol as INamedTypeSymbol) ? ExprKind.EXPLICIT_DELEGATE_CREATION : ExprKind.OBJECT_CREATION;
}
@@ -33,26 +34,26 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new ExplicitObjectCreation(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
if (Syntax.ArgumentList != null)
{
PopulateArguments(Syntax.ArgumentList, 0);
PopulateArguments(trapFile, Syntax.ArgumentList, 0);
}
var target = cx.Model(Syntax).GetSymbolInfo(Syntax);
var target = cx.GetModel(Syntax).GetSymbolInfo(Syntax);
var method = (IMethodSymbol)target.Symbol;
if (method != null)
{
cx.Emit(Tuples.expr_call(this, Method.Create(cx, method)));
trapFile.expr_call(this, Method.Create(cx, method));
}
if (IsDynamicObjectCreation(cx, Syntax))
{
var name = GetDynamicName(Syntax.Type);
if (name.HasValue)
cx.Emit(Tuples.dynamic_member_name(this, name.Value.Text));
trapFile.dynamic_member_name(this, name.Value.Text);
else
cx.ModelError(Syntax, "Unable to get name for dynamic object creation.");
}
@@ -101,14 +102,14 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) =>
new ImplicitObjectCreation(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
var target = cx.GetSymbolInfo(Syntax);
var method = (IMethodSymbol)target.Symbol;
if (method != null)
{
cx.Emit(Tuples.expr_call(this, Method.Create(cx, method)));
trapFile.expr_call(this, Method.Create(cx, method));
}
var child = 0;
@@ -119,7 +120,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
foreach (var init in Syntax.Initializers)
{
// Create an "assignment"
var property = cx.Model(init).GetDeclaredSymbol(init);
var property = cx.GetModel(init).GetDeclaredSymbol(init);
var propEntity = Property.Create(cx, property);
var type = Entities.Type.Create(cx, property.GetAnnotatedType());
var loc = cx.Create(init.GetLocation());
@@ -129,7 +130,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Property.Create(cx, property);
var access = new Expression(new ExpressionInfo(cx, type, loc, ExprKind.PROPERTY_ACCESS, assignment, 1, false, null));
cx.Emit(Tuples.expr_access(access, propEntity));
trapFile.expr_access(access, propEntity);
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new PointerMemberAccess(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -17,15 +18,15 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info, ExpressionSyntax operand) => new PostfixUnary(info, info.Kind, operand).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Operand, this, 0);
OperatorCall(Syntax);
OperatorCall(trapFile, Syntax);
if ((OperatorKind == ExprKind.POST_INCR || OperatorKind == ExprKind.POST_DECR) &&
Kind == ExprKind.OPERATOR_INVOCATION)
{
cx.Emit(Tuples.mutator_invocation_mode(this, 2));
trapFile.mutator_invocation_mode(this, 2);
}
}
}

View File

@@ -28,7 +28,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
ExprKind.METHOD_INVOCATION, parent, child, false, null))
{
if (method != null)
cx.Emit(Tuples.expr_call(this, Method.Create(cx, method)));
cx.TrapWriter.Writer.expr_call(this, Method.Create(cx, method));
}
}
@@ -99,7 +99,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Expression.Create(cx, Expr, decl, 0);
var access = new Expression(new ExpressionInfo(cx, type, nameLoc, ExprKind.LOCAL_VARIABLE_ACCESS, decl, 1, false, null));
cx.Emit(Tuples.expr_access(access, LocalVariable.GetAlreadyCreated(cx, variableSymbol)));
cx.TrapWriter.Writer.expr_access(access, LocalVariable.GetAlreadyCreated(cx, variableSymbol));
return decl;
}
@@ -197,14 +197,14 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
/// <returns>A "syntax tree" of the query.</returns>
static Clause ConstructQueryExpression(Context cx, QueryExpressionSyntax node)
{
var info = cx.Model(node).GetQueryClauseInfo(node.FromClause);
var info = cx.GetModel(node).GetQueryClauseInfo(node.FromClause);
var method = info.OperationInfo.Symbol as IMethodSymbol;
Clause clauseExpr = new RangeClause(method, node.FromClause, cx.Model(node).GetDeclaredSymbol(node.FromClause), node.FromClause.Identifier).AddArgument(node.FromClause.Expression);
Clause clauseExpr = new RangeClause(method, node.FromClause, cx.GetModel(node).GetDeclaredSymbol(node.FromClause), node.FromClause.Identifier).AddArgument(node.FromClause.Expression);
foreach (var qc in node.Body.Clauses)
{
info = cx.Model(node).GetQueryClauseInfo(qc);
info = cx.GetModel(node).GetQueryClauseInfo(qc);
method = info.OperationInfo.Symbol as IMethodSymbol;
@@ -214,7 +214,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var orderByClause = (OrderByClauseSyntax)qc;
foreach (var ordering in orderByClause.Orderings)
{
method = cx.Model(node).GetSymbolInfo(ordering).Symbol as IMethodSymbol;
method = cx.GetModel(node).GetSymbolInfo(ordering).Symbol as IMethodSymbol;
clauseExpr = clauseExpr.WithCallClause(method, orderByClause).AddArgument(ordering.Expression);
@@ -229,25 +229,25 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case SyntaxKind.FromClause:
var fromClause = (FromClauseSyntax)qc;
clauseExpr = clauseExpr.
WithLetClause(method, fromClause, cx.Model(node).GetDeclaredSymbol(fromClause), fromClause.Identifier).
WithLetClause(method, fromClause, cx.GetModel(node).GetDeclaredSymbol(fromClause), fromClause.Identifier).
AddArgument(fromClause.Expression);
break;
case SyntaxKind.LetClause:
var letClause = (LetClauseSyntax)qc;
clauseExpr = clauseExpr.WithLetClause(method, letClause, cx.Model(node).GetDeclaredSymbol(letClause), letClause.Identifier).
clauseExpr = clauseExpr.WithLetClause(method, letClause, cx.GetModel(node).GetDeclaredSymbol(letClause), letClause.Identifier).
AddArgument(letClause.Expression);
break;
case SyntaxKind.JoinClause:
var joinClause = (JoinClauseSyntax)qc;
clauseExpr = clauseExpr.WithLetClause(method, joinClause, cx.Model(node).GetDeclaredSymbol(joinClause), joinClause.Identifier).
clauseExpr = clauseExpr.WithLetClause(method, joinClause, cx.GetModel(node).GetDeclaredSymbol(joinClause), joinClause.Identifier).
AddArgument(joinClause.InExpression).
AddArgument(joinClause.LeftExpression).
AddArgument(joinClause.RightExpression);
if (joinClause.Into != null)
{
var into = cx.Model(node).GetDeclaredSymbol(joinClause.Into);
var into = cx.GetModel(node).GetDeclaredSymbol(joinClause.Into);
((LetClause)clauseExpr).WithInto(into);
}
@@ -257,7 +257,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
}
method = cx.Model(node).GetSymbolInfo(node.Body.SelectOrGroup).Symbol as IMethodSymbol;
method = cx.GetModel(node).GetSymbolInfo(node.Body.SelectOrGroup).Symbol as IMethodSymbol;
clauseExpr = new CallClause(clauseExpr, method, node.Body.SelectOrGroup);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
}
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
if (!(Syntax.LeftOperand is null))
Expression.Create(cx, Syntax.LeftOperand, this, 0);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Ref(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -1,5 +1,6 @@
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new RefType(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -1,5 +1,6 @@
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new RefValue(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
Create(cx, Syntax.Type, this, 1); // A type-access

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new SizeOf(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
TypeAccess.Create(cx, Syntax.Type, this, 0);
}

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -14,7 +15,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public Expression SwitchedExpr { get; private set; }
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
SwitchedExpr = Expression.Create(cx, Syntax.GoverningExpression, this, -1);
int child = 0;

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Throw(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities.Expressions
@@ -12,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
}
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
int child = 0;
foreach (var argument in Syntax.Arguments.Select(a => a.Expression))

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -8,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
TypeAccess(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.TYPE_ACCESS)) { }
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
switch (Syntax.Kind())
{

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new TypeOf(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
TypeAccess.Create(cx, Syntax.Type, this, 0);
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -20,15 +21,15 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return ret;
}
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Operand, this, 0);
OperatorCall(Syntax);
OperatorCall(trapFile, Syntax);
if ((OperatorKind == ExprKind.PRE_INCR || OperatorKind == ExprKind.PRE_DECR) &&
Kind == ExprKind.OPERATOR_INVOCATION)
{
cx.Emit(Tuples.mutator_invocation_mode(this, 1));
trapFile.mutator_invocation_mode(this, 1);
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
@@ -9,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Unchecked(info).TryPopulate();
protected override void Populate()
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
}

View File

@@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
bool isVar = node.Type.IsVar;
var variableSymbol = cx.Model(designation).GetDeclaredSymbol(designation) as ILocalSymbol;
var variableSymbol = cx.GetModel(designation).GetDeclaredSymbol(designation) as ILocalSymbol;
if (variableSymbol == null)
{
cx.ModelError(node, "Failed to determine local variable");
@@ -76,7 +76,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
CreateParenthesized(cx, varPattern, paren, tuple, child0++);
break;
case SingleVariableDesignationSyntax single:
if (cx.Model(variable).GetDeclaredSymbol(single) is ILocalSymbol local)
if (cx.GetModel(variable).GetDeclaredSymbol(single) is ILocalSymbol local)
{
var decl = Create(cx, variable, Entities.Type.Create(cx, local.GetAnnotatedType()), true, tuple, child0++);
var id = single.Identifier;
@@ -126,13 +126,13 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static VariableDeclaration Create(Context cx, CatchDeclarationSyntax d, bool isVar, IExpressionParentEntity parent, int child)
{
var symbol = cx.Model(d).GetDeclaredSymbol(d);
var symbol = cx.GetModel(d).GetDeclaredSymbol(d);
var type = Entities.Type.Create(cx, symbol.GetAnnotatedType());
var ret = Create(cx, d, type, isVar, parent, child);
cx.Try(d, null, () =>
{
var id = d.Identifier;
var declSymbol = cx.Model(d).GetDeclaredSymbol(d);
var declSymbol = cx.GetModel(d).GetDeclaredSymbol(d);
var location = cx.Create(id.GetLocation());
LocalVariable.Create(cx, declSymbol, ret, isVar, location);
TypeMention.Create(cx, d.Type, ret, type);
@@ -146,7 +146,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
cx.Try(d, null, () =>
{
var id = d.Identifier;
var declSymbol = cx.Model(d).GetDeclaredSymbol(d);
var declSymbol = cx.GetModel(d).GetDeclaredSymbol(d);
var location = cx.Create(id.GetLocation());
var localVar = LocalVariable.Create(cx, declSymbol, ret, isVar, location);
@@ -156,7 +156,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
// Create an access
var access = new Expression(new ExpressionInfo(cx, type, location, ExprKind.LOCAL_VARIABLE_ACCESS, ret, 1, false, null));
cx.Emit(Tuples.expr_access(access, localVar));
cx.TrapWriter.Writer.expr_access(access, localVar);
}
var decl = d.Parent as VariableDeclarationSyntax;

View File

@@ -6,6 +6,7 @@ using System;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using Semmle.Extraction.CSharp.Entities.Expressions;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -24,33 +25,33 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation =>
(base.NeedsPopulation && !symbol.IsImplicitlyDeclared) || symbol.ContainingType.IsTupleType;
public override void Populate()
public override void Populate(TextWriter trapFile)
{
ExtractMetadataHandle();
ExtractAttributes();
ContainingType.ExtractGenerics();
ExtractNullability(symbol.NullableAnnotation);
PopulateMetadataHandle(trapFile);
PopulateAttributes();
ContainingType.PopulateGenerics();
PopulateNullability(trapFile, symbol.NullableAnnotation);
Field unboundFieldKey = Field.Create(Context, symbol.OriginalDefinition);
Context.Emit(Tuples.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.Type.TypeRef, unboundFieldKey));
trapFile.fields(this, (symbol.IsConst ? 2 : 1), symbol.Name, ContainingType, Type.Type.TypeRef, unboundFieldKey);
ExtractModifiers();
PopulateModifiers(trapFile);
if (symbol.IsVolatile)
Modifier.HasModifier(Context, this, "volatile");
Modifier.HasModifier(Context, trapFile, this, "volatile");
if (symbol.IsConst)
{
Modifier.HasModifier(Context, this, "const");
Modifier.HasModifier(Context, trapFile, this, "const");
if (symbol.HasConstantValue)
{
Context.Emit(Tuples.constant_value(this, Expression.ValueAsString(symbol.ConstantValue)));
trapFile.constant_value(this, Expression.ValueAsString(symbol.ConstantValue));
}
}
foreach (var l in Locations)
Context.Emit(Tuples.field_location(this, l));
trapFile.field_location(this, l);
if (!IsSourceDeclaration || !symbol.FromSource())
return;
@@ -70,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, Type, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null));
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Initializer.Value, simpleAssignExpr, 0));
var access = new Expression(new ExpressionInfo(Context, Type, Location, ExprKind.FIELD_ACCESS, simpleAssignExpr, 1, false, null));
Context.Emit(Tuples.expr_access(access, this));
trapFile.expr_access(access, this);
if (!symbol.IsStatic)
{
This.CreateImplicit(Context, Entities.Type.Create(Context, symbol.ContainingType), Location, access, -1);
@@ -85,7 +86,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
// Mark fields that have explicit initializers.
var expr = new Expression(new ExpressionInfo(Context, Type, Context.Create(initializer.EqualsValue.Value.FixedLocation()), Kinds.ExprKind.FIELD_ACCESS, this, child++, false, null));
Context.Emit(Tuples.expr_access(expr, this));
trapFile.expr_access(expr, this);
}
if (IsSourceDeclaration)
@@ -98,7 +99,13 @@ namespace Semmle.Extraction.CSharp.Entities
readonly Lazy<AnnotatedType> type;
public AnnotatedType Type => type.Value;
public override IId Id => new Key(ContainingType, ".", symbol.Name, ";field");
public override void WriteId(TextWriter trapFile)
{
trapFile.WriteSubId(ContainingType);
trapFile.Write('.');
trapFile.Write(symbol.Name);
trapFile.Write(";field");
}
bool IExpressionParentEntity.IsTopLevelParent => true;

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -11,14 +12,14 @@ namespace Semmle.Extraction.CSharp.Entities
Indexer OriginalDefinition => IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition);
public override void Populate()
public override void Populate(TextWriter trapFile)
{
ExtractNullability(symbol.NullableAnnotation);
PopulateNullability(trapFile, symbol.NullableAnnotation);
var type = Type.Create(Context, symbol.Type);
Context.Emit(Tuples.indexers(this, symbol.GetName(useMetadataName: true), ContainingType, type.TypeRef, OriginalDefinition));
trapFile.indexers(this, symbol.GetName(useMetadataName: true), ContainingType, type.TypeRef, OriginalDefinition);
foreach (var l in Locations)
Context.Emit(Tuples.indexer_location(this, l));
trapFile.indexer_location(this, l);
var getter = symbol.GetMethod;
var setter = symbol.SetMethod;
@@ -49,7 +50,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
ExtractModifiers();
PopulateModifiers(trapFile);
BindComments();
var declSyntaxReferences = IsSourceDeclaration
@@ -59,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var explicitInterface in symbol.ExplicitInterfaceImplementations.Select(impl => Type.Create(Context, impl.ContainingType)))
{
Context.Emit(Tuples.explicitly_implements(this, explicitInterface.TypeRef));
trapFile.explicitly_implements(this, explicitInterface.TypeRef);
foreach (var syntax in declSyntaxReferences)
TypeMention.Create(Context, syntax.ExplicitInterfaceSpecifier.Name, this, explicitInterface);
@@ -70,23 +71,16 @@ namespace Semmle.Extraction.CSharp.Entities
TypeMention.Create(Context, syntax.Type, this, type);
}
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop);
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
return new Key(tb =>
{
tb.Append(ContainingType);
tb.Append(".");
tb.Append(symbol.MetadataName);
tb.Append("(");
tb.BuildList(",", symbol.Parameters, (p, tb0) => tb0.Append(Type.Create(Context, p.Type)));
tb.Append(");indexer");
});
}
trapFile.WriteSubId(ContainingType);
trapFile.Write('.');
trapFile.Write(symbol.MetadataName);
trapFile.Write('(');
trapFile.BuildList(",", symbol.Parameters, (p, tb0) => tb0.WriteSubId(Type.Create(Context, p.Type)));
trapFile.Write(");indexer");
}
public override Microsoft.CodeAnalysis.Location FullLocation

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -10,23 +11,16 @@ namespace Semmle.Extraction.CSharp.Entities
{
}
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
trapFile.WriteSubId(Location);
if (symbol.IsGenericMethod && !IsSourceDeclaration)
{
return new Key(tb =>
{
tb.Append(Location);
if (symbol.IsGenericMethod && !IsSourceDeclaration)
{
tb.Append("<");
tb.BuildList(",", symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(Context, tb0, symbol, ta));
tb.Append(">");
}
tb.Append(";localfunction");
});
trapFile.Write('<');
trapFile.BuildList(",", symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(Context, tb0, symbol, ta));
trapFile.Write('>');
}
trapFile.Write(";localfunction");
}
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field);
@@ -38,9 +32,9 @@ namespace Semmle.Extraction.CSharp.Entities
public LocalFunction Create(Context cx, IMethodSymbol init) => new LocalFunction(cx, init);
}
public override void Populate()
public override void Populate(TextWriter trapFile)
{
PopulateMethod();
PopulateMethod(trapFile);
// There is a "bug" in Roslyn whereby the IMethodSymbol associated with the local function symbol
// is always static, so we need to go to the syntax reference of the local function to see whether
@@ -49,14 +43,14 @@ namespace Semmle.Extraction.CSharp.Entities
{
foreach(var modifier in fn.Modifiers)
{
Modifier.HasModifier(Context, this, modifier.Text);
Modifier.HasModifier(Context, trapFile, this, modifier.Text);
}
}
var originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition);
var returnType = Type.Create(Context, symbol.ReturnType);
Context.Emit(Tuples.local_functions(this, symbol.Name, returnType, originalDefinition));
ExtractRefReturn();
trapFile.local_functions(this, symbol.Name, returnType, originalDefinition);
ExtractRefReturn(trapFile);
}
}
}

View File

@@ -1,4 +1,5 @@
using System;
using System.IO;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities;
@@ -18,28 +19,34 @@ namespace Semmle.Extraction.CSharp.Entities
readonly bool IsVar;
readonly Extraction.Entities.Location DeclLocation;
public override IId Id => new Key(Parent, "_", symbol.Name, ";localvar");
public override void WriteId(TextWriter trapFile)
{
trapFile.WriteSubId(Parent);
trapFile.Write('_');
trapFile.Write(symbol.Name);
trapFile.Write(";localvar");
}
public override void Populate()
public override void Populate(TextWriter trapFile)
{
if (symbol is ILocalSymbol local)
{
ExtractNullability(local.NullableAnnotation);
PopulateNullability(trapFile, local.NullableAnnotation);
if (local.IsRef)
Context.Emit(Tuples.type_annotation(this, Kinds.TypeAnnotation.Ref));
trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref);
}
Context.Emit(Tuples.localvars(
trapFile.localvars(
this,
IsRef ? 3 : IsConst ? 2 : 1,
symbol.Name,
IsVar ? 1 : 0,
Type.Type.TypeRef,
Parent));
Parent);
Context.Emit(Tuples.localvar_location(this, DeclLocation));
trapFile.localvar_location(this, DeclLocation);
DefineConstantValue();
DefineConstantValue(trapFile);
}
public static LocalVariable Create(Context cx, ISymbol local, Expression parent, bool isVar, Extraction.Entities.Location declLocation)
@@ -80,12 +87,12 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
void DefineConstantValue()
void DefineConstantValue(TextWriter trapFile)
{
var local = symbol as ILocalSymbol;
if (local != null && local.HasConstantValue)
{
Context.Emit(Tuples.constant_value(this, Expression.ValueAsString(local.ConstantValue)));
trapFile.constant_value(this, Expression.ValueAsString(local.ConstantValue));
}
}

View File

@@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -11,7 +12,7 @@ namespace Semmle.Extraction.CSharp.Entities
public Method(Context cx, IMethodSymbol init)
: base(cx, init) { }
protected void ExtractParameters()
protected void PopulateParameters(TextWriter trapFile)
{
var originalMethod = OriginalDefinition;
IEnumerable<IParameterSymbol> parameters = symbol.Parameters;
@@ -55,13 +56,13 @@ namespace Semmle.Extraction.CSharp.Entities
/// <summary>
/// Extracts constructor initializers.
/// </summary>
protected virtual void ExtractInitializers()
protected virtual void ExtractInitializers(TextWriter trapFile)
{
// Normal methods don't have initializers,
// so there's nothing to extract.
}
void ExtractMethodBody()
void PopulateMethodBody(TextWriter trapFile)
{
if (!IsSourceDeclaration)
return;
@@ -73,23 +74,23 @@ namespace Semmle.Extraction.CSharp.Entities
Context.PopulateLater(
() =>
{
ExtractInitializers();
ExtractInitializers(trapFile);
if (block != null)
Statements.Block.Create(Context, block, this, 0);
else
Expression.Create(Context, expr, this, 0);
Context.NumberOfLines(symbol, this);
Context.NumberOfLines(trapFile, symbol, this);
});
}
public void Overrides()
public void Overrides(TextWriter trapFile)
{
foreach (var explicitInterface in symbol.ExplicitInterfaceImplementations.
Where(sym => sym.MethodKind == MethodKind.Ordinary).
Select(impl => Type.Create(Context, impl.ContainingType)))
{
Context.Emit(Tuples.explicitly_implements(this, explicitInterface.TypeRef));
trapFile.explicitly_implements(this, explicitInterface.TypeRef);
if (IsSourceDeclaration)
foreach (var syntax in symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()).OfType<MethodDeclarationSyntax>())
@@ -98,67 +99,72 @@ namespace Semmle.Extraction.CSharp.Entities
if (symbol.OverriddenMethod != null)
{
Context.Emit(Tuples.overrides(this, Method.Create(Context, symbol.OverriddenMethod)));
trapFile.overrides(this, Method.Create(Context, symbol.OverriddenMethod));
}
}
/// <summary>
/// Factored out to share logic between `Method` and `UserOperator`.
/// </summary>
protected static void BuildMethodId(Method m, ITrapBuilder tb)
protected static void BuildMethodId(Method m, TextWriter trapFile)
{
tb.Append(m.ContainingType);
trapFile.WriteSubId(m.ContainingType);
AddExplicitInterfaceQualifierToId(m.Context, tb, m.symbol.ExplicitInterfaceImplementations);
AddExplicitInterfaceQualifierToId(m.Context, trapFile, m.symbol.ExplicitInterfaceImplementations);
tb.Append(".").Append(m.symbol.Name);
trapFile.Write(".");
trapFile.Write(m.symbol.Name);
if (m.symbol.IsGenericMethod)
{
if (Equals(m.symbol, m.symbol.OriginalDefinition))
{
tb.Append("`").Append(m.symbol.TypeParameters.Length);
trapFile.Write('`');
trapFile.Write(m.symbol.TypeParameters.Length);
}
else
{
tb.Append("<");
trapFile.Write('<');
// Encode the nullability of the type arguments in the label.
// 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.
tb.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); tb.Append((int)ta.Nullability); });
tb.Append(">");
trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); });
trapFile.Write('>');
}
}
AddParametersToId(m.Context, tb, m.symbol);
AddParametersToId(m.Context, trapFile, m.symbol);
switch (m.symbol.MethodKind)
{
case MethodKind.PropertyGet:
tb.Append(";getter");
trapFile.Write(";getter");
break;
case MethodKind.PropertySet:
tb.Append(";setter");
trapFile.Write(";setter");
break;
case MethodKind.EventAdd:
tb.Append(";adder");
trapFile.Write(";adder");
break;
case MethodKind.EventRaise:
tb.Append(";raiser");
trapFile.Write(";raiser");
break;
case MethodKind.EventRemove:
tb.Append(";remover");
trapFile.Write(";remover");
break;
default:
tb.Append(";method");
trapFile.Write(";method");
break;
}
}
public override IId Id => new Key(tb => BuildMethodId(this, tb));
public override void WriteId(TextWriter trapFile)
{
BuildMethodId(this, trapFile);
}
/// <summary>
/// Adds an appropriate label ID to the trap builder <paramref name="tb"/>
/// 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"/>.
///
@@ -193,58 +199,54 @@ namespace Semmle.Extraction.CSharp.Entities
/// 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, ITrapBuilder tb, IMethodSymbol method, ITypeSymbol type)
protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type)
{
if (type.ContainsTypeParameters(cx, method))
type.BuildTypeId(cx, tb, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
else
tb.Append(Type.Create(cx, type));
trapFile.WriteSubId(Type.Create(cx, type));
}
protected static void AddParametersToId(Context cx, ITrapBuilder tb, IMethodSymbol method)
protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method)
{
tb.Append("(");
tb.AppendList(",", AddParameterPartsToId(cx, tb, method));
tb.Append(")");
}
trapFile.Write('(');
int index = 0;
// This is a slight abuse of ITrapBuilder.AppendList().
// yield return "" is used to insert a list separator
// at the desired location.
static IEnumerable<object> AddParameterPartsToId(Context cx, ITrapBuilder tb, IMethodSymbol method)
{
if (method.MethodKind == MethodKind.ReducedExtension)
{
AddSignatureTypeToId(cx, tb, method, method.ReceiverType);
yield return ""; // The next yield return outputs a ","
trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType);
}
foreach (var param in method.Parameters)
{
yield return ""; // Maybe print ","
AddSignatureTypeToId(cx, tb, method, param.Type);
trapFile.WriteSeparator(",", ref index);
AddSignatureTypeToId(cx, trapFile, method, param.Type);
switch (param.RefKind)
{
case RefKind.Out:
yield return " out";
trapFile.Write(" out");
break;
case RefKind.Ref:
yield return " ref";
trapFile.Write(" ref");
break;
}
}
if (method.IsVararg)
{
yield return "__arglist";
trapFile.WriteSeparator(",", ref index);
trapFile.Write("__arglist");
}
trapFile.Write(')');
}
public static void AddExplicitInterfaceQualifierToId(Context cx, ITrapBuilder tb, IEnumerable<ISymbol> explicitInterfaceImplementations)
public static void AddExplicitInterfaceQualifierToId(Context cx, System.IO.TextWriter trapFile, IEnumerable<ISymbol> explicitInterfaceImplementations)
{
if (explicitInterfaceImplementations.Any())
{
tb.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType)));
trapFile.AppendList(",", explicitInterfaceImplementations.Select(impl => cx.CreateEntity(impl.ContainingType)));
}
}
@@ -328,7 +330,7 @@ namespace Semmle.Extraction.CSharp.Entities
bool IStatementParentEntity.IsTopLevelParent => true;
protected void ExtractGenerics()
protected void PopulateGenerics(TextWriter trapFile)
{
var isFullyConstructed = IsBoundGeneric;
@@ -338,47 +340,47 @@ namespace Semmle.Extraction.CSharp.Entities
if (isFullyConstructed)
{
Context.Emit(Tuples.is_constructed(this));
Context.Emit(Tuples.constructed_generic(this, Method.Create(Context, ConstructedFromSymbol)));
trapFile.is_constructed(this);
trapFile.constructed_generic(this, Method.Create(Context, ConstructedFromSymbol));
foreach (var tp in symbol.GetAnnotatedTypeArguments())
{
Context.Emit(Tuples.type_arguments(Type.Create(Context, tp.Symbol), child, this));
trapFile.type_arguments(Type.Create(Context, tp.Symbol), child, this);
var ta = tp.Nullability.GetTypeAnnotation();
if (ta != Kinds.TypeAnnotation.None)
Context.Emit(Tuples.type_argument_annotation(this, child, ta));
trapFile.type_argument_annotation(this, child, ta);
child++;
}
}
else
{
Context.Emit(Tuples.is_generic(this));
trapFile.is_generic(this);
foreach (var typeParam in symbol.TypeParameters.Select(tp => TypeParameter.Create(Context, tp)))
{
Context.Emit(Tuples.type_parameters(typeParam, child, this));
trapFile.type_parameters(typeParam, child, this);
child++;
}
}
}
}
protected void ExtractRefReturn()
protected void ExtractRefReturn(TextWriter trapFile)
{
if (symbol.ReturnsByRef)
Context.Emit(Tuples.type_annotation(this, Kinds.TypeAnnotation.Ref));
trapFile.type_annotation(this, Kinds.TypeAnnotation.Ref);
if (symbol.ReturnsByRefReadonly)
Context.Emit(Tuples.type_annotation(this, Kinds.TypeAnnotation.ReadonlyRef));
trapFile.type_annotation(this, Kinds.TypeAnnotation.ReadonlyRef);
}
protected void PopulateMethod()
protected void PopulateMethod(TextWriter trapFile)
{
// Common population code for all callables
BindComments();
ExtractAttributes();
ExtractParameters();
ExtractMethodBody();
ExtractGenerics();
ExtractMetadataHandle();
ExtractNullability(symbol.ReturnNullableAnnotation);
PopulateAttributes();
PopulateParameters(trapFile);
PopulateMethodBody(trapFile);
PopulateGenerics(trapFile);
PopulateMetadataHandle(trapFile);
PopulateNullability(trapFile, symbol.ReturnNullableAnnotation);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.PushesLabel;

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using System;
using System.IO;
using System.Reflection;
namespace Semmle.Extraction.CSharp.Entities
@@ -32,13 +33,17 @@ namespace Semmle.Extraction.CSharp.Entities
public override Microsoft.CodeAnalysis.Location ReportingLocation => null;
public override IId Id => new Key(symbol.name, ";modifier");
public override void WriteId(TextWriter trapFile)
{
trapFile.Write(symbol.name);
trapFile.Write(";modifier");
}
public override bool NeedsPopulation => true;
public override void Populate()
public override void Populate(TextWriter trapFile)
{
Context.Emit(new Tuple("modifiers", Label, symbol.name));
trapFile.modifiers(Label, symbol.name);
}
public static string AccessbilityModifier(Accessibility access)
@@ -58,7 +63,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public static void HasAccessibility(Context cx, IEntity type, Accessibility access)
public static void HasAccessibility(Context cx, TextWriter trapFile, IEntity type, Accessibility access)
{
switch (access)
{
@@ -66,70 +71,70 @@ namespace Semmle.Extraction.CSharp.Entities
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.Internal:
HasModifier(cx, type, Modifier.AccessbilityModifier(access));
HasModifier(cx, trapFile, type, Modifier.AccessbilityModifier(access));
break;
case Accessibility.NotApplicable:
break;
case Accessibility.ProtectedOrInternal:
HasModifier(cx, type, "protected");
HasModifier(cx, type, "internal");
HasModifier(cx, trapFile, type, "protected");
HasModifier(cx, trapFile, type, "internal");
break;
case Accessibility.ProtectedAndInternal:
HasModifier(cx, type, "protected");
HasModifier(cx, type, "private");
HasModifier(cx, trapFile, type, "protected");
HasModifier(cx, trapFile, type, "private");
break;
default:
throw new InternalError($"Unhandled Microsoft.CodeAnalysis.Accessibility value: {access}");
}
}
public static void HasModifier(Context cx, IEntity target, string modifier)
public static void HasModifier(Context cx, TextWriter trapFile, IEntity target, string modifier)
{
cx.Emit(Tuples.has_modifiers(target, Modifier.Create(cx, modifier)));
trapFile.has_modifiers(target, Modifier.Create(cx, modifier));
}
public static void ExtractModifiers(Context cx, IEntity key, ISymbol symbol)
public static void ExtractModifiers(Context cx, TextWriter trapFile, IEntity key, ISymbol symbol)
{
bool interfaceDefinition = symbol.ContainingType != null
&& symbol.ContainingType.Kind == SymbolKind.NamedType
&& symbol.ContainingType.TypeKind == TypeKind.Interface;
Modifier.HasAccessibility(cx, key, symbol.DeclaredAccessibility);
HasAccessibility(cx, trapFile, key, symbol.DeclaredAccessibility);
if (symbol.Kind == SymbolKind.ErrorType)
cx.Emit(Tuples.has_modifiers(key, Modifier.Create(cx, Accessibility.Public)));
trapFile.has_modifiers(key, Modifier.Create(cx, Accessibility.Public));
if (symbol.IsAbstract && (symbol.Kind != SymbolKind.NamedType || ((INamedTypeSymbol)symbol).TypeKind != TypeKind.Interface) && !interfaceDefinition)
Modifier.HasModifier(cx, key, "abstract");
HasModifier(cx, trapFile, key, "abstract");
if (symbol.IsSealed)
HasModifier(cx, key, "sealed");
HasModifier(cx, trapFile, key, "sealed");
bool fromSource = symbol.DeclaringSyntaxReferences.Length > 0;
if (symbol.IsStatic && !(symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsConst && !fromSource))
HasModifier(cx, key, "static");
HasModifier(cx, trapFile, key, "static");
if (symbol.IsVirtual)
HasModifier(cx, key, "virtual");
HasModifier(cx, trapFile, key, "virtual");
// For some reason, method in interfaces are "virtual", not "abstract"
if (symbol.IsAbstract && interfaceDefinition)
HasModifier(cx, key, "virtual");
HasModifier(cx, trapFile, key, "virtual");
if (symbol.Kind == SymbolKind.Field && ((IFieldSymbol)symbol).IsReadOnly)
HasModifier(cx, key, "readonly");
HasModifier(cx, trapFile, key, "readonly");
if (symbol.IsOverride)
HasModifier(cx, key, "override");
HasModifier(cx, trapFile, key, "override");
if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).IsAsync)
HasModifier(cx, key, "async");
HasModifier(cx, trapFile, key, "async");
if (symbol.IsExtern)
HasModifier(cx, key, "extern");
HasModifier(cx, trapFile, key, "extern");
foreach (var modifier in symbol.GetSourceLevelModifiers())
HasModifier(cx, key, modifier);
HasModifier(cx, trapFile, key, modifier);
if (symbol.Kind == SymbolKind.NamedType)
{
@@ -140,9 +145,9 @@ namespace Semmle.Extraction.CSharp.Entities
if (nt.TypeKind == TypeKind.Struct)
{
if (nt.IsReadOnly)
HasModifier(cx, key, "readonly");
HasModifier(cx, trapFile, key, "readonly");
if (nt.IsRefLikeType)
HasModifier(cx, key, "ref");
HasModifier(cx, trapFile, key, "ref");
}
}
}

View File

@@ -1,3 +1,4 @@
using System.IO;
using Microsoft.CodeAnalysis;
namespace Semmle.Extraction.CSharp.Entities
@@ -9,26 +10,28 @@ namespace Semmle.Extraction.CSharp.Entities
public override Microsoft.CodeAnalysis.Location ReportingLocation => null;
public override void Populate()
public override void Populate(TextWriter trapFile)
{
Context.Emit(Tuples.namespaces(this, symbol.Name));
trapFile.namespaces(this, symbol.Name);
if (symbol.ContainingNamespace != null)
{
Namespace parent = Create(Context, symbol.ContainingNamespace);
Context.Emit(Tuples.parent_namespace(this, parent));
trapFile.parent_namespace(this, parent);
}
}
public override bool NeedsPopulation => true;
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
if (!symbol.IsGlobalNamespace)
{
return symbol.IsGlobalNamespace ? new Key(";namespace") :
new Key(Create(Context, symbol.ContainingNamespace), ".", symbol.Name, ";namespace");
trapFile.WriteSubId(Create(Context, symbol.ContainingNamespace));
trapFile.Write('.');
trapFile.Write(symbol.Name);
}
trapFile.Write(";namespace");
}
public static Namespace Create(Context cx, INamespaceSymbol ns) => NamespaceFactory.Instance.CreateEntity2(cx, ns);

View File

@@ -3,29 +3,40 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
{
class NamespaceDeclaration : FreshEntity
{
private readonly NamespaceDeclaration Parent;
private readonly NamespaceDeclarationSyntax Node;
public NamespaceDeclaration(Context cx, NamespaceDeclarationSyntax node, NamespaceDeclaration parent)
: base(cx)
{
var ns = Namespace.Create(cx, (INamespaceSymbol)cx.Model(node).GetSymbolInfo(node.Name).Symbol);
cx.Emit(Tuples.namespace_declarations(this, ns));
cx.Emit(Tuples.namespace_declaration_location(this, cx.Create(node.Name.GetLocation())));
Node = node;
Parent = parent;
TryPopulate();
}
var visitor = new Populators.TypeOrNamespaceVisitor(cx, this);
protected override void Populate(TextWriter trapFile)
{
var ns = Namespace.Create(cx, (INamespaceSymbol)cx.GetModel(Node).GetSymbolInfo(Node.Name).Symbol);
trapFile.namespace_declarations(this, ns);
trapFile.namespace_declaration_location(this, cx.Create(Node.Name.GetLocation()));
foreach (var member in node.Members.Cast<CSharpSyntaxNode>().Concat(node.Usings))
var visitor = new Populators.TypeOrNamespaceVisitor(cx, trapFile, this);
foreach (var member in Node.Members.Cast<CSharpSyntaxNode>().Concat(Node.Usings))
{
member.Accept(visitor);
}
if (parent != null)
if (Parent != null)
{
cx.Emit(Tuples.parent_namespace_declaration(this, parent));
trapFile.parent_namespace_declaration(this, Parent);
}
}

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -23,14 +24,14 @@ namespace Semmle.Extraction.CSharp.Entities
public override Microsoft.CodeAnalysis.Location ReportingLocation => symbol.GetSymbolLocation();
public override void Populate()
public override void Populate(TextWriter trapFile)
{
PopulateMethod();
ExtractModifiers();
ContainingType.ExtractGenerics();
PopulateMethod(trapFile);
PopulateModifiers(trapFile);
ContainingType.PopulateGenerics();
var returnType = Type.Create(Context, symbol.ReturnType);
Context.Emit(Tuples.methods(this, Name, ContainingType, returnType.TypeRef, OriginalDefinition));
trapFile.methods(this, Name, ContainingType, returnType.TypeRef, OriginalDefinition);
if (IsSourceDeclaration)
foreach (var declaration in symbol.DeclaringSyntaxReferences.Select(s => s.GetSyntax()).OfType<MethodDeclarationSyntax>())
@@ -40,12 +41,12 @@ namespace Semmle.Extraction.CSharp.Entities
}
foreach (var l in Locations)
Context.Emit(Tuples.method_location(this, l));
trapFile.method_location(this, l);
ExtractGenerics();
Overrides();
ExtractRefReturn();
ExtractCompilerGenerated();
PopulateGenerics(trapFile);
Overrides(trapFile);
ExtractRefReturn(trapFile);
ExtractCompilerGenerated(trapFile);
}
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method);

View File

@@ -4,6 +4,7 @@ using Semmle.Extraction.CSharp.Populators;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -75,16 +76,14 @@ namespace Semmle.Extraction.CSharp.Entities
public static Parameter GetAlreadyCreated(Context cx, IParameterSymbol param) =>
ParameterFactory.Instance.CreateEntity(cx, param, null, null);
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
// This is due to a bug in Roslyn when ValueTuple.cs is extracted.
// The parameter symbols don't match up properly so we don't have a parent.
if (Parent == null)
Parent = Method.Create(Context, symbol.ContainingSymbol as IMethodSymbol);
return new Key(Parent, "_", Ordinal, ";parameter");
}
if (Parent == null)
Parent = Method.Create(Context, symbol.ContainingSymbol as IMethodSymbol);
trapFile.WriteSubId(Parent);
trapFile.Write('_');
trapFile.Write(Ordinal);
trapFile.Write(";parameter");
}
public override bool NeedsPopulation => true;
@@ -101,20 +100,20 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
public override void Populate()
public override void Populate(TextWriter trapFile)
{
ExtractAttributes();
ExtractNullability(symbol.NullableAnnotation);
ExtractRefKind(symbol.RefKind);
PopulateAttributes();
PopulateNullability(trapFile, symbol.NullableAnnotation);
PopulateRefKind(trapFile, symbol.RefKind);
if (symbol.Name != Original.symbol.Name)
Context.ModelError(symbol, "Inconsistent parameter declaration");
var type = Type.Create(Context, symbol.Type);
Context.Emit(Tuples.@params(this, Name, type.TypeRef, Ordinal, ParamKind, Parent, Original));
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, Parent, Original);
foreach (var l in symbol.Locations)
Context.Emit(Tuples.param_location(this, Context.Create(l)));
trapFile.param_location(this, Context.Create(l));
if (!IsSourceDeclaration || !symbol.FromSource())
return;
@@ -184,16 +183,19 @@ namespace Semmle.Extraction.CSharp.Entities
VarargsType(Context cx)
: base(cx, null) { }
public override void Populate()
public override void Populate(TextWriter trapFile)
{
Context.Emit(Tuples.types(this, Kinds.TypeKind.ARGLIST, "__arglist"));
Context.Emit(Tuples.parent_namespace(this, Namespace.Create(Context, Context.Compilation.GlobalNamespace)));
Modifier.HasModifier(Context, this, "public");
trapFile.types(this, Kinds.TypeKind.ARGLIST, "__arglist");
trapFile.parent_namespace(this, Namespace.Create(Context, Context.Compilation.GlobalNamespace));
Modifier.HasModifier(Context, trapFile, this, "public");
}
public override bool NeedsPopulation => true;
public sealed override IId Id => new Key("__arglist;type");
public override void WriteId(TextWriter trapFile)
{
trapFile.Write("__arglist;type");
}
public override int GetHashCode()
{
@@ -220,12 +222,12 @@ namespace Semmle.Extraction.CSharp.Entities
VarargsParam(Context cx, Method methodKey)
: base(cx, null, methodKey, null) { }
public override void Populate()
public override void Populate(TextWriter trapFile)
{
var typeKey = VarargsType.Create(Context);
// !! Maybe originaldefinition is wrong
Context.Emit(Tuples.@params(this, "", typeKey, Ordinal, Kind.None, Parent, this));
Context.Emit(Tuples.param_location(this, GeneratedLocation.Create(Context)));
trapFile.@params(this, "", typeKey, Ordinal, Kind.None, Parent, this);
trapFile.param_location(this, GeneratedLocation.Create(Context));
}
protected override int Ordinal => ((Method)Parent).OriginalDefinition.symbol.Parameters.Length;
@@ -260,11 +262,11 @@ namespace Semmle.Extraction.CSharp.Entities
ConstructedType = method.symbol.ReceiverType;
}
public override void Populate()
public override void Populate(TextWriter trapFile)
{
var typeKey = Type.Create(Context, ConstructedType);
Context.Emit(Tuples.@params(this, Original.symbol.Name, typeKey.TypeRef, 0, Kind.This, Parent, Original));
Context.Emit(Tuples.param_location(this, Original.Location));
trapFile.@params(this, Original.symbol.Name, typeKey.TypeRef, 0, Kind.This, Parent, Original);
trapFile.param_location(this, Original.Location);
}
public override int GetHashCode() => symbol.GetHashCode() + 31 * ConstructedType.GetHashCode();

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -12,32 +13,26 @@ namespace Semmle.Extraction.CSharp.Entities
protected Property(Context cx, IPropertySymbol init)
: base(cx, init) { }
public override IId Id
public override void WriteId(TextWriter trapFile)
{
get
{
return new Key(tb =>
{
tb.Append(ContainingType);
tb.Append(".");
Method.AddExplicitInterfaceQualifierToId(Context, tb, symbol.ExplicitInterfaceImplementations);
tb.Append(symbol.Name);
tb.Append(";property");
});
}
trapFile.WriteSubId(ContainingType);
trapFile.Write('.');
Method.AddExplicitInterfaceQualifierToId(Context, trapFile, symbol.ExplicitInterfaceImplementations);
trapFile.Write(symbol.Name);
trapFile.Write(";property");
}
public override void Populate()
public override void Populate(TextWriter trapFile)
{
ExtractMetadataHandle();
ExtractAttributes();
ExtractModifiers();
PopulateMetadataHandle(trapFile);
PopulateAttributes();
PopulateModifiers(trapFile);
BindComments();
ExtractNullability(symbol.NullableAnnotation);
ExtractRefKind(symbol.RefKind);
PopulateNullability(trapFile, symbol.NullableAnnotation);
PopulateRefKind(trapFile, symbol.RefKind);
var type = Type.Create(Context, symbol.Type);
Context.Emit(Tuples.properties(this, symbol.GetName(), ContainingType, type.TypeRef, Create(Context, symbol.OriginalDefinition)));
trapFile.properties(this, symbol.GetName(), ContainingType, type.TypeRef, Create(Context, symbol.OriginalDefinition));
var getter = symbol.GetMethod;
var setter = symbol.SetMethod;
@@ -55,14 +50,14 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var explicitInterface in symbol.ExplicitInterfaceImplementations.Select(impl => Type.Create(Context, impl.ContainingType)))
{
Context.Emit(Tuples.explicitly_implements(this, explicitInterface.TypeRef));
trapFile.explicitly_implements(this, explicitInterface.TypeRef);
foreach (var syntax in declSyntaxReferences)
TypeMention.Create(Context, syntax.ExplicitInterfaceSpecifier.Name, this, explicitInterface);
}
foreach (var l in Locations)
Context.Emit(Tuples.property_location(this, l));
trapFile.property_location(this, l);
if (IsSourceDeclaration && symbol.FromSource())
{
@@ -84,7 +79,7 @@ namespace Semmle.Extraction.CSharp.Entities
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null));
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0));
var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, false, null));
Context.Emit(Tuples.expr_access(access, this));
trapFile.expr_access(access, this);
if (!symbol.IsStatic)
{
This.CreateImplicit(Context, Type.Create(Context, symbol.ContainingType), Location, access, -1);

View File

@@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -40,6 +41,10 @@ namespace Semmle.Extraction.CSharp.Entities
abstract class Statement<TSyntax> : Statement where TSyntax : CSharpSyntaxNode
{
protected readonly TSyntax Stmt;
private readonly int Child;
private readonly Kinds.StmtKind Kind;
private readonly IStatementParentEntity Parent;
private readonly Location Location;
protected override CSharpSyntaxNode GetStatementSyntax() => Stmt;
@@ -47,33 +52,29 @@ namespace Semmle.Extraction.CSharp.Entities
: base(cx)
{
Stmt = stmt;
Parent = parent;
Child = child;
Location = location;
Kind = kind;
cx.BindComments(this, location.symbol);
cx.Emit(Tuples.statements(this, kind));
if (parent.IsTopLevelParent)
cx.Emit(Tuples.stmt_parent_top_level(this, child, parent));
else
cx.Emit(Tuples.stmt_parent(this, child, parent));
cx.Emit(Tuples.stmt_location(this, location));
}
protected sealed override void Populate(TextWriter trapFile)
{
trapFile.statements(this, Kind);
if (Parent.IsTopLevelParent)
trapFile.stmt_parent_top_level(this, Child, Parent);
else
trapFile.stmt_parent(this, Child, Parent);
trapFile.stmt_location(this, Location);
PopulateStatement(trapFile);
}
protected abstract void PopulateStatement(TextWriter trapFile);
protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child)
: this(cx, stmt, kind, parent, child, cx.Create(stmt.FixedLocation())) { }
/// <summary>
/// Populates statement-type specific relations in the trap file. The general relations
/// <code>statements</code> and <code>stmt_location</code> are populated by the constructor
/// (should not fail), so even if statement-type specific population fails (e.g., in
/// standalone extraction), the statement created via
/// <see cref="Statement.Create(Context, StatementSyntax, Statement, int)"/> will still
/// be valid.
/// </summary>
protected abstract void Populate();
protected void TryPopulate()
{
cx.Try(Stmt, null, Populate);
}
public override string ToString() => Label.ToString();
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities.Statements
@@ -16,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
var child = 0;
foreach (var childStmt in Stmt.Statements.Select(c => Statement.Create(cx, c, this, child)))

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,6 +16,6 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate() { }
protected override void PopulateStatement(TextWriter trapFile) { }
}
}

View File

@@ -3,6 +3,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -32,11 +33,11 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
CaseLabel(Context cx, CaseSwitchLabelSyntax node, Switch parent, int child)
: base(cx, node, parent, child) { }
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
var value = Stmt.Value;
Expression.Create(cx, value, this, 0);
Switch.LabelForValue(cx.Model(Stmt).GetConstantValue(value).Value);
Switch.LabelForValue(cx.GetModel(Stmt).GetConstantValue(value).Value);
}
public static CaseLabel Create(Context cx, CaseSwitchLabelSyntax node, Switch parent, int child)
@@ -52,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
CaseDefault(Context cx, DefaultSwitchLabelSyntax node, Switch parent, int child)
: base(cx, node, parent, child) { }
protected override void Populate() { }
protected override void PopulateStatement(TextWriter trapFile) { }
public static CaseDefault Create(Context cx, DefaultSwitchLabelSyntax node, Switch parent, int child)
{
@@ -73,7 +74,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
switch (designation)
{
case SingleVariableDesignationSyntax _:
if (cx.Model(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
if (cx.GetModel(pattern).GetDeclaredSymbol(designation) is ILocalSymbol symbol)
{
var type = Type.Create(cx, symbol.GetAnnotatedType());
Expressions.VariableDeclaration.Create(cx, symbol, type, optionalType, cx.Create(pattern.GetLocation()), cx.Create(designation.GetLocation()), isVar, this, 0);
@@ -95,7 +96,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
}
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
switch (Stmt.Pattern)
{

View File

@@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -12,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
Catch(Context cx, CatchClauseSyntax node, Try parent, int child)
: base(cx, node, StmtKind.CATCH, parent, child, cx.Create(node.GetLocation())) { }
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
bool isSpecificCatchClause = Stmt.Declaration != null;
bool hasVariableDeclaration = isSpecificCatchClause && Stmt.Declaration.Identifier.RawKind != 0;
@@ -20,16 +21,16 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
if (hasVariableDeclaration) // A catch clause of the form 'catch(Ex ex) { ... }'
{
var decl = Expressions.VariableDeclaration.Create(cx, Stmt.Declaration, false, this, 0);
cx.Emit(Tuples.catch_type(this, decl.Type.Type.TypeRef, true));
trapFile.catch_type(this, decl.Type.Type.TypeRef, true);
}
else if (isSpecificCatchClause) // A catch clause of the form 'catch(Ex) { ... }'
{
cx.Emit(Tuples.catch_type(this, Type.Create(cx, cx.GetType(Stmt.Declaration.Type)).Type.TypeRef, true));
trapFile.catch_type(this, Type.Create(cx, cx.GetType(Stmt.Declaration.Type)).Type.TypeRef, true);
}
else // A catch clause of the form 'catch { ... }'
{
var exception = Type.Create(cx, cx.Compilation.GetTypeByMetadataName(SystemExceptionName));
cx.Emit(Tuples.catch_type(this, exception, false));
trapFile.catch_type(this, exception, false);
}
if (Stmt.Filter != null)

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax; // lgtm[cs/similar-file]
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
Statement.Create(cx, Stmt.Block, this, 0);
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate() { }
protected override void PopulateStatement(TextWriter trapFile) { }
}
}

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -16,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
Create(cx, Stmt.Statement, this, 1);
Expression.Create(cx, Stmt.Condition, this, 0);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,6 +16,6 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate() { }
protected override void PopulateStatement(TextWriter trapFile) { }
}
}

View File

@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -14,7 +15,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
if (Stmt.Expression != null)
Expression.Create(cx, Stmt.Expression, this, 0);

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -16,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
VariableDeclarations.Populate(cx, Stmt.Declaration, this, -1, childIncrement: -1);
Create(cx, Stmt.Statement, this, 0);

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -16,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
int child = -1;

View File

@@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -17,11 +18,11 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter _)
{
Expression.Create(cx, Stmt.Expression, this, 1);
var typeSymbol = cx.Model(Stmt).GetDeclaredSymbol(Stmt);
var typeSymbol = cx.GetModel(Stmt).GetDeclaredSymbol(Stmt);
var type = Type.Create(cx, typeSymbol.GetAnnotatedType());
var location = cx.Create(Stmt.Identifier.GetLocation());
@@ -44,7 +45,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
Expression.Create(cx, Stmt.Variable, this, 0);
Expression.Create(cx, Stmt.Expression, this, 1);

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -30,17 +31,17 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
switch (GetKind(Stmt))
{
case StmtKind.GOTO:
var target = ((IdentifierNameSyntax)Stmt.Expression).Identifier.Text;
cx.Emit(Tuples.exprorstmt_name(this, target));
trapFile.exprorstmt_name(this, target);
break;
case StmtKind.GOTO_CASE:
Expr = Expression.Create(cx, Stmt.Expression, this, 0);
ConstantValue = Switch.LabelForValue(cx.Model(Stmt).GetConstantValue(Stmt.Expression).Value);
ConstantValue = Switch.LabelForValue(cx.GetModel(Stmt).GetConstantValue(Stmt.Expression).Value);
break;
case StmtKind.GOTO_DEFAULT:
ConstantValue = Switch.DefaultLabel;

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
Expression.Create(cx, Stmt.Condition, this, 0);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -22,9 +23,9 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
cx.Emit(Tuples.exprorstmt_name(this, Stmt.Identifier.ToString()));
trapFile.exprorstmt_name(this, Stmt.Identifier.ToString());
// For compatilibty with the Mono extractor, make insert the labelled statement into the same block
// as this one. The parent MUST be a block statement.

View File

@@ -1,6 +1,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -27,7 +28,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
VariableDeclarations.Populate(cx, Stmt.Declaration, this, 0);
cx.BindComments(this, Stmt.GetLocation());

View File

@@ -3,6 +3,7 @@ using Semmle.Extraction.Kinds;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -29,7 +30,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
// the right thing but it doesn't exist.
// So instead, we have to do the lookup via GetEnclosingSymbol.
var m = cx.Model(Stmt);
var m = cx.GetModel(Stmt);
var body = Stmt.Body == null ? Stmt.ExpressionBody : (CSharpSyntaxNode)Stmt.Body;
return m.GetEnclosingSymbol(body.GetLocation().SourceSpan.Start) as IMethodSymbol;
}
@@ -40,9 +41,9 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
/// </summary>
Entities.LocalFunction Function => Entities.LocalFunction.Create(cx, Symbol);
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
cx.Emit(Tuples.local_function_stmts(this, Function));
trapFile.local_function_stmts(this, Function);
}
}
}

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
Expression.Create(cx, Stmt.Expression, this, 0);
Statement.Create(cx, Stmt.Statement, this, 1);

View File

@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis.CSharp.Syntax; // lgtm[cs/similar-file]
using Semmle.Extraction.Kinds;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Statements
{
@@ -15,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
return ret;
}
protected override void Populate()
protected override void PopulateStatement(TextWriter trapFile)
{
if (Stmt.Expression != null)
Expression.Create(cx, Stmt.Expression, this, 0);

Some files were not shown because too many files have changed in this diff Show More