mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #1749 from calumgrant/cs/extractor-tidy
C#: Refactor extractor trap generation code
This commit is contained in:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() =>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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())
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user