diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs
index a2e5fbc733e..e3789d3d547 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Field.cs
@@ -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
{
@@ -38,6 +39,16 @@ namespace Semmle.Extraction.CIL.Entities
public IId Id => ShortId + IdSuffix;
+ public void WriteId(TextWriter trapFile)
+ {
+ trapFile.WriteIId(Id);
+ }
+
+ public void WriteQuotedId(TextWriter trapFile)
+ {
+ WriteId(trapFile);
+ }
+
public Id IdSuffix => fieldSuffix;
static readonly StringId fieldSuffix = new StringId(";cil-field");
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs
index 3b840f10ba5..90311af8762 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Method.cs
@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
+using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs
index 0644d668fa1..375b2a5cbb8 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs
@@ -6,6 +6,8 @@ using System.Linq;
using System.Collections.Generic;
using System.Reflection;
using Semmle.Util;
+using System.IO;
+using System.Text;
namespace Semmle.Extraction.CIL.Entities
{
@@ -55,6 +57,22 @@ namespace Semmle.Extraction.CIL.Entities
public virtual IId Id { get { return ShortId + IdSuffix; } }
+ public void WriteId(System.IO.TextWriter trapFile)
+ {
+ // TODO: Specialise this
+ trapFile.WriteIId(Id);
+ }
+
+ ///
+ /// For debugging purposes.
+ ///
+ string DebugId => this.GetDebugLabel();
+
+ public void WriteQuotedId(TextWriter trapFile)
+ {
+ WriteId(trapFile);
+ }
+
public Id ShortId { get; set; }
public abstract Id IdSuffix { get; }
diff --git a/csharp/extractor/Semmle.Extraction.CIL/ExtractionProduct.cs b/csharp/extractor/Semmle.Extraction.CIL/ExtractionProduct.cs
index 8da16a22418..1f660e3ee83 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/ExtractionProduct.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/ExtractionProduct.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
namespace Semmle.Extraction.CIL
{
@@ -45,6 +46,16 @@ namespace Semmle.Extraction.CIL
public abstract IEnumerable Contents { get; }
public Label Label { get; set; }
+ public void WriteId(System.IO.TextWriter trapFile)
+ {
+ trapFile.Write('*');
+ }
+
+ public void WriteQuotedId(TextWriter trapFile)
+ {
+ WriteId(trapFile);
+ }
+
public Microsoft.CodeAnalysis.Location ReportingLocation => throw new NotImplementedException();
public virtual IId Id => FreshId.Instance;
@@ -79,6 +90,16 @@ namespace Semmle.Extraction.CIL
public abstract Id IdSuffix { get; }
public IId Id => ShortId + IdSuffix;
+ public void WriteId(System.IO.TextWriter trapFile)
+ {
+ trapFile.WriteIId(Id);
+ }
+
+ public void WriteQuotedId(TextWriter trapFile)
+ {
+ WriteId(trapFile);
+ }
+
public void Extract(Context cx2)
{
cx2.Populate(this);
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Factories.cs b/csharp/extractor/Semmle.Extraction.CIL/Factories.cs
index b8909f2b833..9448f789131 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Factories.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Factories.cs
@@ -23,7 +23,8 @@ namespace Semmle.Extraction.CIL
}
else
{
- cx.DefineLabel(e);
+ e.Label = cx.GetNewLabel();
+ cx.DefineLabel(e, cx.TrapWriter.Writer);
ids.Add(id, (e.Label, id));
cx.PopulateLater(() =>
{
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Id.cs b/csharp/extractor/Semmle.Extraction.CIL/Id.cs
index c8cbb04b3d5..616ca406dfd 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Id.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Id.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL
@@ -9,14 +10,14 @@ namespace Semmle.Extraction.CIL
///
public abstract class Id : IId
{
- public void AppendTo(ITrapBuilder tb)
+ public void AppendTo(System.IO.TextWriter tb)
{
- tb.Append("@\"");
+ tb.Write("@\"");
BuildParts(tb);
- tb.Append("\"");
+ tb.Write("\"");
}
- public abstract void BuildParts(ITrapBuilder tb);
+ public abstract void BuildParts(System.IO.TextWriter tb);
public static Id operator +(Id l1, Id l2) => Create(l1, l2);
@@ -76,7 +77,7 @@ namespace Semmle.Extraction.CIL
hash = unchecked(12 + 3 * (left.GetHashCode() + 51 * right.GetHashCode()));
}
- public override void BuildParts(ITrapBuilder tb)
+ public override void BuildParts(System.IO.TextWriter tb)
{
left.BuildParts(tb);
right.BuildParts(tb);
@@ -112,9 +113,9 @@ namespace Semmle.Extraction.CIL
value = s;
}
- public override void BuildParts(ITrapBuilder tb)
+ public override void BuildParts(System.IO.TextWriter tw)
{
- tb.Append(value);
+ tw.Write(value);
}
public override bool Equals(object obj)
@@ -138,9 +139,9 @@ namespace Semmle.Extraction.CIL
value = i;
}
- public override void BuildParts(ITrapBuilder tb)
+ public override void BuildParts(System.IO.TextWriter tw)
{
- tb.Append(value);
+ tw.Write(value);
}
public override bool Equals(object obj)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs
index 3fadd1c13cf..6b1d260644d 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs
@@ -375,6 +375,7 @@ namespace Semmle.Extraction.CSharp
Populators.CompilationUnit.Extract(cx, tree.GetRoot());
cx.PopulateAll();
cx.ExtractComments(cx.CommentGenerator);
+ cx.PopulateAll();
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs
index 1d171878209..25a188223e2 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentBlock.cs
@@ -1,5 +1,6 @@
using Semmle.Extraction.CommentProcessing;
using Semmle.Extraction.Entities;
+using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -21,13 +22,10 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
- public override IId Id
+ public override void WriteId(TextWriter tw)
{
- get
- {
- var loc = Context.Create(symbol.Location);
- return new Key(loc, ";commentblock");
- }
+ tw.WriteSubId(Context.Create(symbol.Location));
+ tw.Write(";commentblock");
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => symbol.Location;
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs
index b831c11724f..6476ef087e8 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs
@@ -2,6 +2,7 @@ using Semmle.Extraction.CommentProcessing;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Semmle.Extraction.Entities;
+using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -122,13 +123,10 @@ namespace Semmle.Extraction.CSharp.Entities
public override bool NeedsPopulation => true;
- public override IId Id
+ public override void WriteId(TextWriter tw)
{
- get
- {
- var loc = Context.Create(Location);
- return new Key(loc, ";commentline");
- }
+ tw.WriteSubId(Context.Create(Location));
+ tw.Write(";commentline");
}
static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw) => CommentLineFactory.Instance.CreateEntity(cx, loc, type, text, raw);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs
index 1a54120682a..c6802f0cd7a 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs
@@ -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
{
@@ -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() =>
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs
index 963e3fea989..7d3bc898df6 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Event.cs
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -9,19 +10,13 @@ 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()
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs
index 2d30a3ce468..b51eb92687f 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Field.cs
@@ -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
{
@@ -98,7 +99,13 @@ namespace Semmle.Extraction.CSharp.Entities
readonly Lazy 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;
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs
index eefaf6071f2..0a00a4051b7 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Indexer.cs
@@ -1,5 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Entities
@@ -73,20 +74,14 @@ namespace Semmle.Extraction.CSharp.Entities
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
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs
index e209b73f78d..5b6e50c05eb 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs
@@ -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);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs
index 00bf9d720a4..a5e1f45b707 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs
@@ -1,4 +1,5 @@
using System;
+using System.IO;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities;
@@ -18,7 +19,13 @@ 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 tw)
+ {
+ tw.WriteSubId(Parent);
+ tw.Write('_');
+ tw.Write(symbol.Name);
+ tw.Write(";localvar");
+ }
public override void Populate()
{
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs
index 218e6ef5ce8..2d37cba6b8a 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs
@@ -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
@@ -105,57 +106,62 @@ namespace Semmle.Extraction.CSharp.Entities
///
/// Factored out to share logic between `Method` and `UserOperator`.
///
- protected static void BuildMethodId(Method m, ITrapBuilder tb)
+ protected static void BuildMethodId(Method m, TextWriter tw)
{
- tb.Append(m.ContainingType);
+ tw.WriteSubId(m.ContainingType);
- AddExplicitInterfaceQualifierToId(m.Context, tb, m.symbol.ExplicitInterfaceImplementations);
+ AddExplicitInterfaceQualifierToId(m.Context, tw, m.symbol.ExplicitInterfaceImplementations);
- tb.Append(".").Append(m.symbol.Name);
+ tw.Write(".");
+ tw.Write(m.symbol.Name);
if (m.symbol.IsGenericMethod)
{
if (Equals(m.symbol, m.symbol.OriginalDefinition))
{
- tb.Append("`").Append(m.symbol.TypeParameters.Length);
+ tw.Write('`');
+ tw.Write(m.symbol.TypeParameters.Length);
}
else
{
- tb.Append("<");
+ tw.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(">");
+ tw.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); tw.Write((int)ta.Nullability); });
+ tw.Write('>');
}
}
- AddParametersToId(m.Context, tb, m.symbol);
+ AddParametersToId(m.Context, tw, m.symbol);
switch (m.symbol.MethodKind)
{
case MethodKind.PropertyGet:
- tb.Append(";getter");
+ tw.Write(";getter");
break;
case MethodKind.PropertySet:
- tb.Append(";setter");
+ tw.Write(";setter");
break;
case MethodKind.EventAdd:
- tb.Append(";adder");
+ tw.Write(";adder");
break;
case MethodKind.EventRaise:
- tb.Append(";raiser");
+ tw.Write(";raiser");
break;
case MethodKind.EventRemove:
- tb.Append(";remover");
+ tw.Write(";remover");
break;
default:
- tb.Append(";method");
+ tw.Write(";method");
break;
}
}
- public override IId Id => new Key(tb => BuildMethodId(this, tb));
+ public override void WriteId(TextWriter trapFile)
+ {
+ BuildMethodId(this, trapFile);
+ }
///
/// Adds an appropriate label ID to the trap builder
@@ -193,58 +199,54 @@ namespace Semmle.Extraction.CSharp.Entities
/// to make the reference to #3 in the label definition #4 for
/// T valid.
///
- protected static void AddSignatureTypeToId(Context cx, ITrapBuilder tb, IMethodSymbol method, ITypeSymbol type)
+ protected static void AddSignatureTypeToId(Context cx, TextWriter tb, IMethodSymbol method, ITypeSymbol type)
{
if (type.ContainsTypeParameters(cx, method))
type.BuildTypeId(cx, tb, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0));
else
- tb.Append(Type.Create(cx, type));
+ tb.WriteSubId(Type.Create(cx, type));
}
- protected static void AddParametersToId(Context cx, ITrapBuilder tb, IMethodSymbol method)
+ protected static void AddParametersToId(Context cx, TextWriter tb, IMethodSymbol method)
{
- tb.Append("(");
- tb.AppendList(",", AddParameterPartsToId(cx, tb, method));
- tb.Append(")");
- }
+ tb.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