Merge branch 'main' of github.com:github/codeql into SharedDataflow_PostUpdateNodes

This commit is contained in:
Rasmus Lerchedahl Petersen
2020-08-28 13:01:14 +02:00
108 changed files with 2110 additions and 618 deletions

View File

@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL
/// </summary>
/// <typeparam name="SrcType">The type of the source.</typeparam>
/// <typeparam name="TargetType">The type of the generated object.</typeparam>
public class CachedFunction<SrcType, TargetType>
public class CachedFunction<SrcType, TargetType> where SrcType : notnull
{
readonly Func<SrcType, TargetType> generator;
readonly Dictionary<SrcType, TargetType> cache;

View File

@@ -14,13 +14,19 @@ namespace Semmle.Extraction.CIL
/// </summary>
partial class Context : IDisposable
{
public Extraction.Context cx;
readonly FileStream stream;
public readonly MetadataReader mdReader;
public readonly PEReader peReader;
public readonly string assemblyPath;
public Entities.Assembly assembly;
public PDB.IPdb pdb;
Entities.Assembly? assemblyNull;
public Extraction.Context cx { get; }
public MetadataReader mdReader { get; }
public PEReader peReader { get; }
public string assemblyPath { get; }
public Entities.Assembly assembly
{
get { return assemblyNull!; }
set { assemblyNull = value; }
}
public PDB.IPdb? pdb { get; }
public Context(Extraction.Context cx, string assemblyPath, bool extractPdbs)
{
@@ -105,7 +111,7 @@ namespace Semmle.Extraction.CIL
/// </summary>
/// <param name="handle">The handle of the method.</param>
/// <returns>The debugging information, or null if the information could not be located.</returns>
public PDB.IMethod GetMethodDebugInformation(MethodDefinitionHandle handle)
public PDB.IMethod? GetMethodDebugInformation(MethodDefinitionHandle handle)
{
return pdb == null ? null : pdb.GetMethod(handle.ToDebugInformationHandle());
}
@@ -125,7 +131,8 @@ namespace Semmle.Extraction.CIL
}
/// <summary>
/// The list of generic type parameters.
/// The list of generic type parameters, including type parameters of
/// containing types.
/// </summary>
public abstract IEnumerable<Entities.Type> TypeParameters { get; }

View File

@@ -47,9 +47,9 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(cx.assemblyPath.Replace("\\", "/"));
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return GetType() == obj.GetType() && Equals(file, ((Assembly)obj).file);
return GetType() == obj?.GetType() && Equals(file, ((Assembly)obj).file);
}
public override int GetHashCode() => 7 * file.GetHashCode();
@@ -63,7 +63,7 @@ namespace Semmle.Extraction.CIL.Entities
get
{
yield return file;
yield return Tuples.assemblies(this, file, FullName, assemblyName.Name, assemblyName.Version.ToString());
yield return Tuples.assemblies(this, file, FullName, assemblyName.Name ?? string.Empty, assemblyName.Version?.ToString() ?? string.Empty);
if (cx.pdb != null)
{
@@ -75,7 +75,7 @@ namespace Semmle.Extraction.CIL.Entities
foreach (var handle in cx.mdReader.TypeDefinitions)
{
IExtractionProduct product = null;
IExtractionProduct? product = null;
try
{
product = cx.Create(handle);
@@ -92,7 +92,7 @@ namespace Semmle.Extraction.CIL.Entities
foreach (var handle in cx.mdReader.MethodDefinitions)
{
IExtractionProduct product = null;
IExtractionProduct? product = null;
try
{
product = cx.Create(handle);

View File

@@ -27,7 +27,7 @@ namespace Semmle.Extraction.CIL.Entities
this.@object = @object;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is Attribute attribute && handle.Equals(attribute.handle);
}
@@ -58,13 +58,15 @@ namespace Semmle.Extraction.CIL.Entities
for (int index = 0; index < decoded.FixedArguments.Length; ++index)
{
object value = decoded.FixedArguments[index].Value;
yield return Tuples.cil_attribute_positional_argument(this, index, value == null ? "null" : value.ToString());
var stringValue = value?.ToString();
yield return Tuples.cil_attribute_positional_argument(this, index, stringValue ?? "null");
}
foreach (var p in decoded.NamedArguments)
{
object value = p.Value;
yield return Tuples.cil_attribute_named_argument(this, p.Name, value == null ? "null" : value.ToString());
var stringValue = value?.ToString();
yield return Tuples.cil_attribute_named_argument(this, p.Name, stringValue ?? "null");
}
}
}

View File

@@ -36,7 +36,7 @@ namespace Semmle.Extraction.CIL.Entities
public override string IdSuffix => ";cil-event";
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is Event e && handle.Equals(e.handle);
}

View File

@@ -30,7 +30,7 @@ namespace Semmle.Extraction.CIL.Entities
{
get
{
IInstruction try_start, try_end, handler_start;
IInstruction? try_start, try_end, handler_start;
if (!jump_table.TryGetValue(r.TryOffset, out try_start))
throw new InternalError("Failed to retrieve handler");
@@ -44,7 +44,7 @@ namespace Semmle.Extraction.CIL.Entities
if (r.FilterOffset != -1)
{
IInstruction filter_start;
IInstruction? filter_start;
if (!jump_table.TryGetValue(r.FilterOffset, out filter_start))
throw new InternalError("ExceptionRegion filter clause");

View File

@@ -91,7 +91,7 @@ namespace Semmle.Extraction.CIL.Entities
fd = cx.mdReader.GetFieldDefinition(handle);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is DefinitionField field && handle.Equals(field.handle);
}
@@ -153,7 +153,7 @@ namespace Semmle.Extraction.CIL.Entities
declType = (Type)cx.CreateGeneric(gc, mr.Parent);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is MemberReferenceField field && Handle.Equals(field.Handle);
}

View File

@@ -25,9 +25,9 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(Semmle.Extraction.Entities.File.PathAsDatabaseId(path));
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return GetType() == obj.GetType() && path == ((File)obj).path;
return GetType() == obj?.GetType() && path == ((File)obj).path;
}
public override int GetHashCode() => 11 * path.GetHashCode();
@@ -36,7 +36,11 @@ namespace Semmle.Extraction.CIL.Entities
{
get
{
var parent = cx.CreateFolder(System.IO.Path.GetDirectoryName(path));
var directoryName = System.IO.Path.GetDirectoryName(path);
if (directoryName is null)
throw new InternalError($"Directory name for path '{path}' is null.");
var parent = cx.CreateFolder(directoryName);
yield return parent;
yield return Tuples.containerparent(parent, this);
yield return Tuples.files(this, path, System.IO.Path.GetFileNameWithoutExtension(path), System.IO.Path.GetExtension(path).Substring(1));

View File

@@ -41,7 +41,7 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is Folder folder && path == folder.path;
}

View File

@@ -365,6 +365,11 @@ namespace Semmle.Extraction.CIL.Entities
{
int offset = Offset;
if (Method.Implementation is null)
{
yield break;
}
yield return Tuples.cil_instruction(this, (int)OpCode, Index, Method.Implementation);
switch (PayloadType)
@@ -414,11 +419,17 @@ namespace Semmle.Extraction.CIL.Entities
break;
case Payload.Arg8:
case Payload.Arg16:
yield return Tuples.cil_access(this, Method.Parameters[(int)UnsignedPayloadValue]);
if (Method.Parameters is object)
{
yield return Tuples.cil_access(this, Method.Parameters[(int)UnsignedPayloadValue]);
}
break;
case Payload.Local8:
case Payload.Local16:
yield return Tuples.cil_access(this, Method.LocalVariables[(int)UnsignedPayloadValue]);
if (Method.LocalVariables is object)
{
yield return Tuples.cil_access(this, Method.LocalVariables[(int)UnsignedPayloadValue]);
}
break;
case Payload.None:
case Payload.Target8:
@@ -439,7 +450,7 @@ namespace Semmle.Extraction.CIL.Entities
public IEnumerable<IExtractionProduct> JumpContents(Dictionary<int, IInstruction> jump_table)
{
int target;
IInstruction inst;
IInstruction? inst;
switch (PayloadType)
{

View File

@@ -23,25 +23,29 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary>
abstract class Method : TypeContainer, IMethod
{
protected MethodTypeParameter[]? genericParams;
protected GenericContext gc;
protected MethodSignature<ITypeSignature> signature;
protected Method(GenericContext gc) : base(gc.cx)
{
this.gc = gc;
}
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(declaringType.TypeParameters);
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
public override IEnumerable<Type> MethodParameters =>
genericParams == null ? gc.MethodParameters : gc.MethodParameters.Concat(genericParams);
public int GenericParameterCount => signature.GenericParameterCount;
public virtual Method SourceDeclaration => this;
public virtual Method? SourceDeclaration => this;
public abstract Type DeclaringType { get; }
public abstract string Name { get; }
public virtual IList<LocalVariable> LocalVariables => throw new NotImplementedException();
public IList<Parameter> Parameters { get; private set; }
public virtual IList<LocalVariable>? LocalVariables => throw new NotImplementedException();
public IList<Parameter>? Parameters { get; protected set; }
public override void WriteId(TextWriter trapFile) => WriteMethodId(trapFile, DeclaringType, NameLabel);
@@ -70,19 +74,8 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(')');
}
protected MethodTypeParameter[] genericParams;
protected Type declaringType;
protected GenericContext gc;
protected MethodSignature<ITypeSignature> signature;
protected string name;
public override string IdSuffix => ";cil-method";
protected void PopulateParameters(IEnumerable<Type> parameterTypes)
{
Parameters = MakeParameters(parameterTypes).ToArray();
}
protected IEnumerable<IExtractionProduct> PopulateFlags
{
get
@@ -94,7 +87,7 @@ namespace Semmle.Extraction.CIL.Entities
public abstract bool IsStatic { get; }
private IEnumerable<Parameter> MakeParameters(IEnumerable<Type> parameterTypes)
protected IEnumerable<Parameter> MakeParameters(IEnumerable<Type> parameterTypes)
{
int i = 0;
@@ -145,13 +138,15 @@ namespace Semmle.Extraction.CIL.Entities
{
readonly Handle handle;
readonly MethodDefinition md;
readonly PDB.IMethod methodDebugInformation;
readonly PDB.IMethod? methodDebugInformation;
readonly Type declaringType;
LocalVariable[] locals;
readonly string name;
LocalVariable[]? locals;
public MethodImplementation Implementation { get; private set; }
public MethodImplementation? Implementation { get; private set; }
public override IList<LocalVariable> LocalVariables => locals;
public override IList<LocalVariable>? LocalVariables => locals;
public DefinitionMethod(GenericContext gc, MethodDefinitionHandle handle) : base(gc)
{
@@ -167,7 +162,7 @@ namespace Semmle.Extraction.CIL.Entities
methodDebugInformation = cx.GetMethodDebugInformation(handle);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is DefinitionMethod method && handle.Equals(method.handle);
}
@@ -206,7 +201,7 @@ namespace Semmle.Extraction.CIL.Entities
var typeSignature = md.DecodeSignature(cx.TypeSignatureDecoder, this);
PopulateParameters(typeSignature.ParameterTypes);
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
foreach (var c in Parameters)
yield return c;
@@ -315,8 +310,8 @@ namespace Semmle.Extraction.CIL.Entities
// The sequence point gives the location of each instruction.
// The location of an instruction is given by the sequence point *after* the
// instruction.
IEnumerator<PDB.SequencePoint> nextSequencePoint = null;
PdbSourceLocation instructionLocation = null;
IEnumerator<PDB.SequencePoint>? nextSequencePoint = null;
PdbSourceLocation? instructionLocation = null;
if (methodDebugInformation != null)
{
@@ -401,9 +396,9 @@ namespace Semmle.Extraction.CIL.Entities
{
readonly MemberReferenceHandle handle;
readonly MemberReference mr;
readonly Type declType;
readonly Type declaringType;
readonly GenericContext parent;
readonly Method sourceDeclaration;
readonly Method? sourceDeclaration;
public MemberReferenceMethod(GenericContext gc, MemberReferenceHandle handle) : base(gc)
{
@@ -416,22 +411,24 @@ namespace Semmle.Extraction.CIL.Entities
parent = (GenericContext)cx.CreateGeneric(gc, mr.Parent);
var parentMethod = parent as Method;
nameLabel = cx.GetString(mr.Name);
declType = parentMethod == null ? parent as Type : parentMethod.DeclaringType;
var declType = parentMethod is null ? parent as Type : parentMethod.DeclaringType;
if (declType is null)
throw new InternalError("Parent context of method is not a type");
var typeSourceDeclaration = declType.SourceDeclaration;
sourceDeclaration = typeSourceDeclaration == declType ? (Method)this : typeSourceDeclaration.LookupMethod(mr.Name, mr.Signature);
declaringType = declType;
nameLabel = cx.GetString(mr.Name);
var typeSourceDeclaration = declaringType.SourceDeclaration;
sourceDeclaration = typeSourceDeclaration == declaringType ? (Method)this : typeSourceDeclaration.LookupMethod(mr.Name, mr.Signature);
}
private readonly string nameLabel;
public override string NameLabel => nameLabel;
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is MemberReferenceMethod method && handle.Equals(method.handle);
}
@@ -441,11 +438,11 @@ namespace Semmle.Extraction.CIL.Entities
return handle.GetHashCode();
}
public override Method SourceDeclaration => sourceDeclaration;
public override Method? SourceDeclaration => sourceDeclaration;
public override bool IsStatic => !signature.Header.IsInstance;
public override Type DeclaringType => declType;
public override Type DeclaringType => declaringType;
public override string Name => cx.ShortName(mr.Name);
@@ -464,7 +461,7 @@ namespace Semmle.Extraction.CIL.Entities
var typeSignature = mr.DecodeMethodSignature(cx.TypeSignatureDecoder, this);
PopulateParameters(typeSignature.ParameterTypes);
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
foreach (var p in Parameters) yield return p;
foreach (var f in PopulateFlags) yield return f;
@@ -486,6 +483,7 @@ namespace Semmle.Extraction.CIL.Entities
readonly MethodSpecification ms;
readonly Method unboundMethod;
readonly ImmutableArray<Type> typeParams;
readonly Type declaringType;
public MethodSpecificationMethod(GenericContext gc, MethodSpecificationHandle handle) : base(gc)
{
@@ -511,7 +509,7 @@ namespace Semmle.Extraction.CIL.Entities
public override string NameLabel => throw new NotImplementedException();
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is MethodSpecificationMethod method && handle.Equals(method.handle) && typeParams.SequenceEqual(method.typeParams);
}
@@ -547,7 +545,7 @@ namespace Semmle.Extraction.CIL.Entities
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
}
PopulateParameters(constructedTypeSignature.ParameterTypes);
Parameters = MakeParameters(constructedTypeSignature.ParameterTypes).ToArray();
foreach (var p in Parameters)
yield return p;

View File

@@ -17,10 +17,10 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary>
public sealed class Namespace : TypeContainer, INamespace
{
public Namespace ParentNamespace;
public Namespace? ParentNamespace;
public readonly string Name;
public bool IsGlobalNamespace => ParentNamespace == null;
public bool IsGlobalNamespace => ParentNamespace is null;
public override string IdSuffix => ";namespace";
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(Name);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is Namespace ns && Name == ns.Name)
{
@@ -63,7 +63,7 @@ namespace Semmle.Extraction.CIL.Entities
return i == -1 ? fqn : fqn.Substring(i + 1);
}
static Namespace createParentNamespace(Context cx, string fqn)
static Namespace? createParentNamespace(Context cx, string fqn)
{
if (fqn == "") return null;
var i = fqn.LastIndexOf('.');
@@ -74,7 +74,7 @@ namespace Semmle.Extraction.CIL.Entities
{
}
public Namespace(Context cx, string name, Namespace parent) : base(cx)
public Namespace(Context cx, string name, Namespace? parent) : base(cx)
{
Name = name;
ParentNamespace = parent;
@@ -85,7 +85,7 @@ namespace Semmle.Extraction.CIL.Entities
get
{
yield return Tuples.namespaces(this, Name);
if (!IsGlobalNamespace)
if (ParentNamespace is object)
yield return Tuples.parent_namespace(this, ParentNamespace);
}
}

View File

@@ -33,7 +33,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(index);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is Parameter param && method.Equals(param.method) && index == param.index;
}

View File

@@ -48,7 +48,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(")");
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is Property property && Equals(handle, property.handle);
}

View File

@@ -32,7 +32,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(location.EndColumn);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is PdbSourceLocation l && location.Equals(l.location);
}

View File

@@ -8,6 +8,7 @@ using System.Reflection;
using Semmle.Util;
using System.IO;
using System.Text;
using System.Diagnostics.CodeAnalysis;
namespace Semmle.Extraction.CIL.Entities
{
@@ -103,7 +104,7 @@ namespace Semmle.Extraction.CIL.Entities
/// shortcut to comparing the signature bytes since handles are unique.
/// </param>
/// <returns>The method, or 'null' if not found or not supported.</returns>
internal virtual Method LookupMethod(StringHandle methodName, BlobHandle signature)
internal virtual Method? LookupMethod(StringHandle methodName, BlobHandle signature)
{
return null;
}
@@ -160,7 +161,7 @@ namespace Semmle.Extraction.CIL.Entities
get;
}
public virtual TypeContainer Parent => (TypeContainer)ContainingType ?? Namespace;
public virtual TypeContainer Parent => (TypeContainer?)ContainingType ?? Namespace!;
public override IEnumerable<IExtractionProduct> Contents
{
@@ -177,9 +178,9 @@ namespace Semmle.Extraction.CIL.Entities
public abstract string Name { get; }
public abstract Namespace Namespace { get; }
public abstract Namespace? Namespace { get; }
public abstract Type ContainingType { get; }
public abstract Type? ContainingType { get; }
public abstract Type Construct(IEnumerable<Type> typeArguments);
@@ -233,7 +234,7 @@ namespace Semmle.Extraction.CIL.Entities
/// </summary>
/// <param name="t">The resulting primitive type, or null.</param>
/// <returns>True if this type is a primitive type.</returns>
public bool TryGetPrimitiveType(out PrimitiveType t)
public bool TryGetPrimitiveType([NotNullWhen(true)] out PrimitiveType? t)
{
if (TryGetPrimitiveTypeCode(out var code))
{
@@ -249,7 +250,7 @@ namespace Semmle.Extraction.CIL.Entities
private bool TryGetPrimitiveTypeCode(out PrimitiveTypeCode code)
{
if (ContainingType == null && Namespace.Name == cx.SystemNamespace.Name)
if (ContainingType == null && Namespace?.Name == cx.SystemNamespace.Name)
{
switch (Name)
{
@@ -341,7 +342,7 @@ namespace Semmle.Extraction.CIL.Entities
typeParams = new Lazy<IEnumerable<TypeTypeParameter>>(MakeTypeParameters);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is TypeDefinitionType t && handle.Equals(t.handle);
}
@@ -390,9 +391,9 @@ namespace Semmle.Extraction.CIL.Entities
public override Namespace Namespace => cx.Create(td.NamespaceDefinition);
readonly Type declType;
readonly Type? declType;
public override Type ContainingType => declType;
public override Type? ContainingType => declType;
public override int ThisTypeParameters
{
@@ -562,18 +563,14 @@ namespace Semmle.Extraction.CIL.Entities
readonly TypeReference tr;
readonly Lazy<TypeTypeParameter[]> typeParams;
public TypeReferenceType(Context cx, TypeReferenceHandle handle) : this(cx, handle, cx.mdReader.GetTypeReference(handle))
{
typeParams = new Lazy<TypeTypeParameter[]>(MakeTypeParameters);
}
public TypeReferenceType(Context cx, TypeReferenceHandle handle, TypeReference tr) : base(cx)
public TypeReferenceType(Context cx, TypeReferenceHandle handle) : base(cx)
{
this.typeParams = new Lazy<TypeTypeParameter[]>(MakeTypeParameters);
this.handle = handle;
this.tr = tr;
this.tr = cx.mdReader.GetTypeReference(handle);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is TypeReferenceType t && handle.Equals(t.handle);
}
@@ -637,7 +634,7 @@ namespace Semmle.Extraction.CIL.Entities
}
}
public override Type ContainingType
public override Type? ContainingType
{
get
{
@@ -654,7 +651,7 @@ namespace Semmle.Extraction.CIL.Entities
switch (tr.ResolutionScope.Kind)
{
case HandleKind.TypeReference:
ContainingType.WriteAssemblyPrefix(trapFile);
ContainingType!.WriteAssemblyPrefix(trapFile);
break;
case HandleKind.AssemblyReference:
var assemblyDef = cx.mdReader.GetAssemblyReference((AssemblyReferenceHandle)tr.ResolutionScope);
@@ -684,7 +681,7 @@ namespace Semmle.Extraction.CIL.Entities
var ct = ContainingType;
if (ct != null)
{
ContainingType.GetId(trapFile, inContext);
ct.GetId(trapFile, inContext);
}
else
{
@@ -719,9 +716,11 @@ namespace Semmle.Extraction.CIL.Entities
public sealed class ConstructedType : Type
{
readonly Type unboundGenericType;
readonly Type[] thisTypeArguments;
public override IEnumerable<Type> ThisTypeArguments => thisTypeArguments;
// Either null or notEmpty
readonly Type[]? thisTypeArguments;
public override IEnumerable<Type> ThisTypeArguments => thisTypeArguments.EnumerateNull();
public override IEnumerable<Type> ThisGenericArguments => thisTypeArguments.EnumerateNull();
@@ -751,7 +750,6 @@ namespace Semmle.Extraction.CIL.Entities
unboundGenericType = unboundType;
var thisParams = unboundType.ThisTypeParameters;
var parentParams = suppliedArgs - thisParams;
if (typeArguments.Count() == thisParams)
{
@@ -760,16 +758,19 @@ namespace Semmle.Extraction.CIL.Entities
}
else if (thisParams == 0)
{
containingType = unboundType.ContainingType.Construct(typeArguments);
// all type arguments belong to containing type
containingType = unboundType.ContainingType!.Construct(typeArguments);
}
else
{
containingType = unboundType.ContainingType.Construct(typeArguments.Take(parentParams));
// some type arguments belong to containing type
var parentParams = suppliedArgs - thisParams;
containingType = unboundType.ContainingType!.Construct(typeArguments.Take(parentParams));
thisTypeArguments = typeArguments.Skip(parentParams).ToArray();
}
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
if (obj is ConstructedType t && Equals(unboundGenericType, t.unboundGenericType) && Equals(containingType, t.containingType))
{
@@ -788,12 +789,12 @@ namespace Semmle.Extraction.CIL.Entities
return h;
}
readonly Type containingType;
public override Type ContainingType => containingType;
readonly Type? containingType;
public override Type? ContainingType => containingType;
public override string Name => unboundGenericType.Name;
public override Namespace Namespace => unboundGenericType.Namespace;
public override Namespace Namespace => unboundGenericType.Namespace!;
public override int ThisTypeParameters => thisTypeArguments == null ? 0 : thisTypeArguments.Length;
@@ -851,7 +852,7 @@ namespace Semmle.Extraction.CIL.Entities
typeCode = tc;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is PrimitiveType pt && typeCode == pt.typeCode;
}
@@ -871,7 +872,7 @@ namespace Semmle.Extraction.CIL.Entities
public override Namespace Namespace => cx.SystemNamespace;
public override Type ContainingType => null;
public override Type? ContainingType => null;
public override int ThisTypeParameters => 0;
@@ -894,19 +895,17 @@ namespace Semmle.Extraction.CIL.Entities
readonly Type elementType;
readonly int rank;
public ArrayType(Context cx, Type element, ArrayShape shape) : base(cx)
public ArrayType(Context cx, Type elementType, int rank) : base(cx)
{
rank = shape.Rank;
elementType = element;
this.rank = rank;
this.elementType = elementType;
}
public ArrayType(Context cx, Type element) : base(cx)
public ArrayType(Context cx, Type elementType) : this(cx, elementType, 1)
{
rank = 1;
elementType = element;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is ArrayType array && elementType.Equals(array.elementType) && rank == array.rank;
}
@@ -929,7 +928,7 @@ namespace Semmle.Extraction.CIL.Entities
public override Namespace Namespace => cx.SystemNamespace;
public override Type ContainingType => null;
public override Type? ContainingType => null;
public override int ThisTypeParameters => elementType.ThisTypeParameters;
@@ -972,9 +971,9 @@ namespace Semmle.Extraction.CIL.Entities
this.gc = gc;
}
public override Namespace Namespace => null;
public override Namespace? Namespace => null;
public override Type ContainingType => null;
public override Type? ContainingType => null;
public override int ThisTypeParameters => 0;
@@ -1034,7 +1033,7 @@ namespace Semmle.Extraction.CIL.Entities
this.index = index;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is MethodTypeParameter tp && method.Equals(tp.method) && index == tp.index;
}
@@ -1072,7 +1071,7 @@ namespace Semmle.Extraction.CIL.Entities
type = t;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is TypeTypeParameter tp && type.Equals(tp.type) && index == tp.index;
}
@@ -1089,7 +1088,7 @@ namespace Semmle.Extraction.CIL.Entities
trapFile.Write(index);
}
public override TypeContainer Parent => type ?? gc as TypeContainer;
public override TypeContainer Parent => type;
public override string Name => "!" + index;
public override IEnumerable<Type> TypeParameters => Enumerable.Empty<Type>();
@@ -1119,7 +1118,7 @@ namespace Semmle.Extraction.CIL.Entities
this.pointee = pointee;
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
return obj is PointerType pt && pointee.Equals(pt.pointee);
}
@@ -1138,9 +1137,9 @@ namespace Semmle.Extraction.CIL.Entities
public override string Name => pointee.Name + "*";
public override Namespace Namespace => pointee.Namespace;
public override Namespace? Namespace => pointee.Namespace;
public override Type ContainingType => pointee.ContainingType;
public override Type? ContainingType => pointee.ContainingType;
public override TypeContainer Parent => pointee.Parent;
@@ -1180,7 +1179,7 @@ namespace Semmle.Extraction.CIL.Entities
public override Namespace Namespace => cx.GlobalNamespace;
public override Type ContainingType => null;
public override Type? ContainingType => null;
public override int ThisTypeParameters => 0;
@@ -1202,8 +1201,15 @@ namespace Semmle.Extraction.CIL.Entities
{
struct Array : ITypeSignature
{
public ITypeSignature elementType;
public ArrayShape shape;
private readonly ITypeSignature elementType;
private readonly ArrayShape shape;
public Array(ITypeSignature elementType, ArrayShape shape) : this()
{
this.elementType = elementType;
this.shape = shape;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
elementType.WriteId(trapFile, gc);
@@ -1216,7 +1222,12 @@ namespace Semmle.Extraction.CIL.Entities
struct ByRef : ITypeSignature
{
public ITypeSignature elementType;
private readonly ITypeSignature elementType;
public ByRef(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1227,7 +1238,12 @@ namespace Semmle.Extraction.CIL.Entities
struct FnPtr : ITypeSignature
{
public MethodSignature<ITypeSignature> signature;
private readonly MethodSignature<ITypeSignature> signature;
public FnPtr(MethodSignature<ITypeSignature> signature)
{
this.signature = signature;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1236,18 +1252,25 @@ namespace Semmle.Extraction.CIL.Entities
}
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetArrayType(ITypeSignature elementType, ArrayShape shape) =>
new Array { elementType = elementType, shape = shape };
new Array(elementType, shape);
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetByReferenceType(ITypeSignature elementType) =>
new ByRef { elementType = elementType };
new ByRef(elementType);
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetFunctionPointerType(MethodSignature<ITypeSignature> signature) =>
new FnPtr { signature = signature };
new FnPtr(signature);
class Instantiation : ITypeSignature
{
public ITypeSignature genericType;
public ImmutableArray<ITypeSignature> typeArguments;
private readonly ITypeSignature genericType;
private readonly ImmutableArray<ITypeSignature> typeArguments;
public Instantiation(ITypeSignature genericType, ImmutableArray<ITypeSignature> typeArguments)
{
this.genericType = genericType;
this.typeArguments = typeArguments;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1264,12 +1287,18 @@ namespace Semmle.Extraction.CIL.Entities
}
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetGenericInstantiation(ITypeSignature genericType, ImmutableArray<ITypeSignature> typeArguments) =>
new Instantiation { genericType = genericType, typeArguments = typeArguments };
new Instantiation(genericType, typeArguments);
class GenericMethodParameter : ITypeSignature
{
public object innerGc;
public int index;
private readonly object innerGc;
private readonly int index;
public GenericMethodParameter(object innerGc, int index)
{
this.innerGc = innerGc;
this.index = index;
}
public void WriteId(TextWriter trapFile, GenericContext outerGc)
{
@@ -1284,7 +1313,12 @@ namespace Semmle.Extraction.CIL.Entities
class GenericTypeParameter : ITypeSignature
{
public int index;
private readonly int index;
public GenericTypeParameter(int index)
{
this.index = index;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1294,16 +1328,23 @@ namespace Semmle.Extraction.CIL.Entities
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetGenericMethodParameter(object genericContext, int index) =>
new GenericMethodParameter { innerGc = genericContext, index = index };
new GenericMethodParameter(genericContext, index);
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetGenericTypeParameter(object genericContext, int index) =>
new GenericTypeParameter { index = index };
new GenericTypeParameter(index);
class Modified : ITypeSignature
{
public ITypeSignature modifier;
public ITypeSignature unmodifiedType;
public bool isRequired;
private readonly ITypeSignature modifier;
private readonly ITypeSignature unmodifiedType;
private readonly bool isRequired;
public Modified(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired)
{
this.modifier = modifier;
this.unmodifiedType = unmodifiedType;
this.isRequired = isRequired;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1313,12 +1354,17 @@ namespace Semmle.Extraction.CIL.Entities
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetModifiedType(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired)
{
return new Modified { modifier = modifier, unmodifiedType = unmodifiedType, isRequired = isRequired };
return new Modified(modifier, unmodifiedType, isRequired);
}
class Pinned : ITypeSignature
{
public ITypeSignature elementType;
private readonly ITypeSignature elementType;
public Pinned(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1329,12 +1375,17 @@ namespace Semmle.Extraction.CIL.Entities
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetPinnedType(ITypeSignature elementType)
{
return new Pinned { elementType = elementType };
return new Pinned(elementType);
}
class PointerType : ITypeSignature
{
public ITypeSignature elementType;
private readonly ITypeSignature elementType;
public PointerType(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1345,12 +1396,17 @@ namespace Semmle.Extraction.CIL.Entities
ITypeSignature IConstructedTypeProvider<ITypeSignature>.GetPointerType(ITypeSignature elementType)
{
return new PointerType { elementType = elementType };
return new PointerType(elementType);
}
class Primitive : ITypeSignature
{
public PrimitiveTypeCode typeCode;
private readonly PrimitiveTypeCode typeCode;
public Primitive(PrimitiveTypeCode typeCode)
{
this.typeCode = typeCode;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
@@ -1360,12 +1416,18 @@ namespace Semmle.Extraction.CIL.Entities
ITypeSignature ISimpleTypeProvider<ITypeSignature>.GetPrimitiveType(PrimitiveTypeCode typeCode)
{
return new Primitive { typeCode = typeCode };
return new Primitive(typeCode);
}
class SzArrayType : ITypeSignature
{
public ITypeSignature elementType;
private readonly ITypeSignature elementType;
public SzArrayType(ITypeSignature elementType)
{
this.elementType = elementType;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
elementType.WriteId(trapFile, gc);
@@ -1375,41 +1437,53 @@ namespace Semmle.Extraction.CIL.Entities
ITypeSignature ISZArrayTypeProvider<ITypeSignature>.GetSZArrayType(ITypeSignature elementType)
{
return new SzArrayType { elementType = elementType };
return new SzArrayType(elementType);
}
class TypeDefinition : ITypeSignature
{
public TypeDefinitionHandle handle;
public byte rawTypeKind;
Type type;
private readonly TypeDefinitionHandle handle;
private readonly byte rawTypeKind;
public TypeDefinition(TypeDefinitionHandle handle, byte rawTypeKind)
{
this.handle = handle;
this.rawTypeKind = rawTypeKind;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
type = (Type)gc.cx.Create(handle);
var type = (Type)gc.cx.Create(handle);
type.WriteId(trapFile);
}
}
ITypeSignature ISimpleTypeProvider<ITypeSignature>.GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
return new TypeDefinition { handle = handle, rawTypeKind = rawTypeKind };
return new TypeDefinition(handle, rawTypeKind);
}
class TypeReference : ITypeSignature
{
public TypeReferenceHandle handle;
public byte rawTypeKind; // struct/class (not used)
Type type;
private readonly TypeReferenceHandle handle;
private readonly byte rawTypeKind; // struct/class (not used)
public TypeReference(TypeReferenceHandle handle, byte rawTypeKind)
{
this.handle = handle;
this.rawTypeKind = rawTypeKind;
}
public void WriteId(TextWriter trapFile, GenericContext gc)
{
type = (Type)gc.cx.Create(handle);
var type = (Type)gc.cx.Create(handle);
type.WriteId(trapFile);
}
}
ITypeSignature ISimpleTypeProvider<ITypeSignature>.GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
return new TypeReference { handle = handle, rawTypeKind = rawTypeKind };
return new TypeReference(handle, rawTypeKind);
}
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetTypeFromSpecification(MetadataReader reader, object genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
@@ -1433,7 +1507,7 @@ namespace Semmle.Extraction.CIL.Entities
}
Type IConstructedTypeProvider<Type>.GetArrayType(Type elementType, ArrayShape shape) =>
cx.Populate(new ArrayType(cx, elementType, shape));
cx.Populate(new ArrayType(cx, elementType, shape.Rank));
Type IConstructedTypeProvider<Type>.GetByReferenceType(Type elementType) =>
elementType; // ??

View File

@@ -41,7 +41,7 @@ namespace Semmle.Extraction.CIL
e.WriteId(writer);
var id = writer.ToString();
if (debugLabels.TryGetValue(id, out IExtractedEntity previousEntity))
if (debugLabels.TryGetValue(id, out IExtractedEntity? previousEntity))
{
cx.Extractor.Message(new Message("Duplicate trap ID", id, null, severity: Util.Logging.Severity.Warning));
}

View File

@@ -25,7 +25,7 @@ namespace Semmle.Extraction.PDB
public string Path { get; private set; }
public string Contents => File.Exists(Path) ? File.ReadAllText(Path, System.Text.Encoding.Default) : null;
public string? Contents => File.Exists(Path) ? File.ReadAllText(Path, System.Text.Encoding.Default) : null;
}
// Turns out to be very important to keep the MetadataReaderProvider live
@@ -41,7 +41,7 @@ namespace Semmle.Extraction.PDB
public IEnumerable<ISourceFile> SourceFiles => reader.Documents.Select(handle => new SourceFile(reader, handle));
public IMethod GetMethod(MethodDebugInformationHandle handle)
public IMethod? GetMethod(MethodDebugInformationHandle handle)
{
var debugInfo = reader.GetMethodDebugInformation(handle);
@@ -51,10 +51,10 @@ namespace Semmle.Extraction.PDB
Where(p => p.Location.File.Path != null).
ToArray();
return sequencePoints.Any() ? new Method() { SequencePoints = sequencePoints } : null;
return sequencePoints.Any() ? new Method(sequencePoints) : null;
}
public static MetadataPdbReader CreateFromAssembly(string assemblyPath, PEReader peReader)
public static MetadataPdbReader? CreateFromAssembly(string assemblyPath, PEReader peReader)
{
foreach (var provider in peReader.
ReadDebugDirectory().

View File

@@ -23,7 +23,7 @@ namespace Semmle.Extraction.PDB
public Document(ISymUnmanagedDocument doc)
{
document = doc;
contents = new Lazy<string>(() =>
contents = new Lazy<string?>(() =>
{
bool isEmbedded;
if (document.HasEmbeddedSource(out isEmbedded) == 0 && isEmbedded)
@@ -38,7 +38,7 @@ namespace Semmle.Extraction.PDB
});
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
var otherDoc = obj as Document;
return otherDoc != null && Path.Equals(otherDoc.Path);
@@ -50,14 +50,14 @@ namespace Semmle.Extraction.PDB
public override string ToString() => Path;
readonly Lazy<string> contents;
readonly Lazy<string?> contents;
public string Contents => contents.Value;
public string? Contents => contents.Value;
}
public IEnumerable<ISourceFile> SourceFiles => reader.GetDocuments().Select(d => new Document(d));
public IMethod GetMethod(MethodDebugInformationHandle h)
public IMethod? GetMethod(MethodDebugInformationHandle h)
{
int methodToken = MetadataTokens.GetToken(h.ToDefinitionHandle());
var method = reader.GetMethod(methodToken);
@@ -72,7 +72,7 @@ namespace Semmle.Extraction.PDB
Select(sp => new SequencePoint(sp.Offset, new Location(new Document(sp.Document), sp.StartLine, sp.StartColumn, sp.EndLine, sp.EndColumn))).
ToArray();
return s.Any() ? new Method { SequencePoints = s } : null;
return s.Any() ? new Method(s) : null;
}
return null;
}
@@ -87,7 +87,7 @@ namespace Semmle.Extraction.PDB
readonly ISymUnmanagedReader5 reader;
readonly FileStream pdbStream;
public static NativePdbReader CreateFromAssembly(string assemblyPath, PEReader peReader)
public static NativePdbReader? CreateFromAssembly(string assemblyPath, PEReader peReader)
{
// The Native PDB reader uses an unmanaged Windows DLL
// so only works on Windows.
@@ -123,7 +123,7 @@ namespace Semmle.Extraction.PDB
{
}
public object GetMetadataImport() => null;
public object? GetMetadataImport() => null;
public unsafe bool TryGetStandaloneSignature(int standaloneSignatureToken, out byte* signature, out int length) =>
throw new NotImplementedException();

View File

@@ -55,7 +55,7 @@ namespace Semmle.Extraction.PDB
return string.Format("({0},{1})-({2},{3})", StartLine, StartColumn, EndLine, EndColumn);
}
public override bool Equals(object obj)
public override bool Equals(object? obj)
{
var otherLocation = obj as Location;
@@ -91,7 +91,12 @@ namespace Semmle.Extraction.PDB
class Method : IMethod
{
public IEnumerable<SequencePoint> SequencePoints { get; set; }
public IEnumerable<SequencePoint> SequencePoints { get; }
public Method(IEnumerable<SequencePoint> sequencePoints)
{
SequencePoints = sequencePoints;
}
public Location Location => SequencePoints.First().Location;
}
@@ -111,7 +116,7 @@ namespace Semmle.Extraction.PDB
/// null if the contents are unavailable.
/// E.g. if the PDB file exists but the corresponding source files are missing.
/// </summary>
string Contents { get; }
string? Contents { get; }
}
/// <summary>
@@ -131,7 +136,7 @@ namespace Semmle.Extraction.PDB
/// </summary>
/// <param name="methodHandle">The handle to query.</param>
/// <returns>The method information, or null if the method does not have debug information.</returns>
IMethod GetMethod(MethodDebugInformationHandle methodHandle);
IMethod? GetMethod(MethodDebugInformationHandle methodHandle);
}
class PdbReader
@@ -140,11 +145,11 @@ namespace Semmle.Extraction.PDB
/// Returns the PDB information associated with an assembly.
/// </summary>
/// <param name="assemblyPath">The path to the assembly.</param>
/// <param name="peReader">The PE reader for the assembky.</param>
/// <param name="peReader">The PE reader for the assembly.</param>
/// <returns>A PdbReader, or null if no PDB information is available.</returns>
public static IPdb Create(string assemblyPath, PEReader peReader)
public static IPdb? Create(string assemblyPath, PEReader peReader)
{
return (IPdb)MetadataPdbReader.CreateFromAssembly(assemblyPath, peReader) ??
return (IPdb?)MetadataPdbReader.CreateFromAssembly(assemblyPath, peReader) ??
NativePdbReader.CreateFromAssembly(assemblyPath, peReader);
}
}

View File

@@ -7,6 +7,7 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

View File

@@ -1,4 +1,5 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.IO;
@@ -21,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
protected override void PopulateExpression(TextWriter trapFile)
{
var child = 0;
var explicitlySized = false;
if (TypeSyntax is null)
@@ -29,38 +30,21 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
cx.ModelError(Syntax, "Array has unexpected type syntax");
}
foreach (var rank in TypeSyntax.RankSpecifiers.SelectMany(rs => rs.Sizes))
var firstLevelSizes = TypeSyntax.RankSpecifiers.First()?.Sizes ?? SyntaxFactory.SeparatedList<ExpressionSyntax>();
if (firstLevelSizes.OfType<ExpressionSyntax>().Any(s => s is OmittedArraySizeExpressionSyntax))
{
if (rank is OmittedArraySizeExpressionSyntax)
{
// Create an expression which simulates the explicit size of the array
if (!(Initializer is null))
{
// An implicitly-sized array must have an initializer.
// Guard it just in case.
var size = Initializer.Expressions.Count;
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
Location,
ExprKind.INT_LITERAL,
this,
child,
true,
size.ToString());
new Expression(info);
}
}
else
{
Create(cx, rank, this, child);
explicitlySized = true;
}
child++;
SetArraySizes(Initializer, firstLevelSizes.Count);
}
else
{
for (var sizeIndex = 0; sizeIndex < firstLevelSizes.Count; sizeIndex++)
{
Create(cx, firstLevelSizes[sizeIndex], this, sizeIndex);
}
explicitlySized = true;
}
if (!(Initializer is null))
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, -1));
@@ -69,6 +53,31 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (explicitlySized)
trapFile.explicitly_sized_array_creation(this);
}
private void SetArraySizes(InitializerExpressionSyntax initializer, int rank)
{
for (var level = 0; level < rank; level++)
{
if (initializer is null)
{
return;
}
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
Location,
ExprKind.INT_LITERAL,
this,
level,
true,
initializer.Expressions.Count.ToString());
new Expression(info);
initializer = initializer.Expressions.FirstOrDefault() as InitializerExpressionSyntax;
}
}
}
class NormalArrayCreation : ExplicitArrayCreation<ArrayCreationExpressionSyntax>

View File

@@ -64,7 +64,7 @@ namespace Semmle.Util
/// Enumerates a possibly null enumerable.
/// If the enumerable is null, the list is empty.
/// </summary>
public static IEnumerable<T> EnumerateNull<T>(this IEnumerable<T> items)
public static IEnumerable<T> EnumerateNull<T>(this IEnumerable<T>? items)
{
if (items == null) yield break;
foreach (var item in items) yield return item;

View File

@@ -6,18 +6,32 @@
import csharp
//#################### PREDICATES ####################
Stmt firstStmt(ForeachStmt fes) {
private Stmt firstStmt(ForeachStmt fes) {
if fes.getBody() instanceof BlockStmt
then result = fes.getBody().(BlockStmt).getStmt(0)
else result = fes.getBody()
}
private int numStmts(ForeachStmt fes) {
if fes.getBody() instanceof BlockStmt
then result = count(fes.getBody().(BlockStmt).getAStmt())
else result = 1
}
/** Holds if the type's qualified name is "System.Linq.Enumerable" */
predicate isEnumerableType(ValueOrRefType t) { t.hasQualifiedName("System.Linq.Enumerable") }
/** Holds if the type's qualified name starts with "System.Collections.Generic.IEnumerable" */
predicate isIEnumerableType(ValueOrRefType t) {
t.getQualifiedName().matches("System.Collections.Generic.IEnumerable%")
}
/**
* Holds if `foreach` statement `fes` could be converted to a `.All()` call.
* That is, the `ForeachStmt` contains a single `if` with a condition that
* accesses the loop variable and with a body that assigns `false` to a variable
* and `break`s out of the `foreach`.
*/
predicate missedAllOpportunity(ForeachStmt fes) {
exists(IfStmt is |
// The loop contains an if statement with no else case, and nothing else.
@@ -36,6 +50,12 @@ predicate missedAllOpportunity(ForeachStmt fes) {
)
}
/**
* Holds if `foreach` statement `fes` could be converted to a `.Cast()` call.
* That is, the loop variable is accessed only in the first statement of the
* block, and the access is a cast. The first statement needs to be a
* `LocalVariableDeclStmt`.
*/
predicate missedCastOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
s = firstStmt(fes) and
forex(VariableAccess va | va = fes.getVariable().getAnAccess() |
@@ -47,6 +67,12 @@ predicate missedCastOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
)
}
/**
* Holds if `foreach` statement `fes` could be converted to an `.OfType()` call.
* That is, the loop variable is accessed only in the first statement of the
* block, and the access is a cast with the `as` operator. The first statement
* needs to be a `LocalVariableDeclStmt`.
*/
predicate missedOfTypeOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
s = firstStmt(fes) and
forex(VariableAccess va | va = fes.getVariable().getAnAccess() |
@@ -58,6 +84,12 @@ predicate missedOfTypeOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
)
}
/**
* Holds if `foreach` statement `fes` could be converted to a `.Select()` call.
* That is, the loop variable is accessed only in the first statement of the
* block, and the access is not a cast. The first statement needs to be a
* `LocalVariableDeclStmt`.
*/
predicate missedSelectOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
s = firstStmt(fes) and
forex(VariableAccess va | va = fes.getVariable().getAnAccess() |
@@ -66,6 +98,12 @@ predicate missedSelectOpportunity(ForeachStmt fes, LocalVariableDeclStmt s) {
not s.getAVariableDeclExpr().getInitializer() instanceof Cast
}
/**
* Holds if `foreach` statement `fes` could be converted to a `.Where()` call.
* That is, first statement of the loop is an `if`, which accesses the loop
* variable, and the body of the `if` is either a `continue` or there's nothing
* else in the loop than the `if`.
*/
predicate missedWhereOpportunity(ForeachStmt fes, IfStmt is) {
// The very first thing the foreach loop does is test its iteration variable.
is = firstStmt(fes) and
@@ -82,12 +120,6 @@ predicate missedWhereOpportunity(ForeachStmt fes, IfStmt is) {
)
}
int numStmts(ForeachStmt fes) {
if fes.getBody() instanceof BlockStmt
then result = count(fes.getBody().(BlockStmt).getAStmt())
else result = 1
}
//#################### CLASSES ####################
/** A LINQ Any(...) call. */
class AnyCall extends MethodCall {

View File

@@ -66,9 +66,9 @@ class SimilarBlock extends Copy, @similarity {
}
}
Method sourceMethod() { method_location(result, _) and numlines(result, _, _, _) }
private Method sourceMethod() { method_location(result, _) and numlines(result, _, _, _) }
int numberOfSourceMethods(Class c) {
private int numberOfSourceMethods(Class c) {
result = count(Method m | m = sourceMethod() and m.getDeclaringType() = c)
}
@@ -97,6 +97,7 @@ private predicate duplicateStatement(Method m1, Method m2, Stmt s1, Stmt s2) {
)
}
/** Holds if `duplicate` number of statements are duplicated in the methods. */
predicate duplicateStatements(Method m1, Method m2, int duplicate, int total) {
duplicate = strictcount(Stmt s | duplicateStatement(m1, m2, s, _)) and
total = strictcount(statementInMethod(m1))
@@ -109,7 +110,7 @@ predicate duplicateMethod(Method m, Method other) {
exists(int total | duplicateStatements(m, other, total, total))
}
predicate similarLines(File f, int line) {
private predicate similarLines(File f, int line) {
exists(SimilarBlock b | b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()])
}
@@ -148,7 +149,7 @@ private predicate similarLinesCovered(File f, int coveredLines, File otherFile)
)
}
predicate duplicateLines(File f, int line) {
private predicate duplicateLines(File f, int line) {
exists(DuplicateBlock b |
b.sourceFile() = f and line in [b.sourceStartLine() .. b.sourceEndLine()]
)
@@ -189,6 +190,7 @@ private predicate duplicateLinesCovered(File f, int coveredLines, File otherFile
)
}
/** Holds if the two files are not duplicated but have more than 80% similar lines. */
predicate similarFiles(File f, File other, int percent) {
exists(int covered, int total |
similarLinesCovered(f, covered, other) and
@@ -199,6 +201,7 @@ predicate similarFiles(File f, File other, int percent) {
not duplicateFiles(f, other, _)
}
/** Holds if the two files have more than 70% duplicated lines. */
predicate duplicateFiles(File f, File other, int percent) {
exists(int covered, int total |
duplicateLinesCovered(f, covered, other) and
@@ -209,7 +212,7 @@ predicate duplicateFiles(File f, File other, int percent) {
}
pragma[noopt]
predicate duplicateAnonymousClass(AnonymousClass c, AnonymousClass other) {
private predicate duplicateAnonymousClass(AnonymousClass c, AnonymousClass other) {
exists(int numDup |
numDup =
strictcount(Method m1 |
@@ -248,6 +251,7 @@ private predicate mostlyDuplicateClassBase(Class c, Class other, int numDup, int
not other instanceof AnonymousClass
}
/** Holds if the methods in the two classes are more than 80% duplicated. */
predicate mostlyDuplicateClass(Class c, Class other, string message) {
exists(int numDup, int total |
mostlyDuplicateClassBase(c, other, numDup, total) and
@@ -272,19 +276,28 @@ predicate mostlyDuplicateClass(Class c, Class other, string message) {
)
}
/** Holds if the two files are similar or duplicated. */
predicate fileLevelDuplication(File f, File other) {
similarFiles(f, other, _) or duplicateFiles(f, other, _)
}
/**
* Holds if the two classes are duplicated anonymous classes or more than 80% of
* their methods are duplicated.
*/
predicate classLevelDuplication(Class c, Class other) {
duplicateAnonymousClass(c, other) or mostlyDuplicateClass(c, other, _)
}
Element whitelistedDuplicateElement() {
private Element whitelistedDuplicateElement() {
result instanceof UsingNamespaceDirective or
result instanceof UsingStaticDirective
}
/**
* Holds if the `line` in the `file` contains an element, such as a `using`
* directive, that is not considered for code duplication.
*/
predicate whitelistedLineForDuplication(File file, int line) {
exists(Location loc | loc = whitelistedDuplicateElement().getLocation() |
line = loc.getStartLine() and file = loc.getFile()

View File

@@ -31,6 +31,7 @@ class ReadRefAccess extends ReadAccess, ReadRef { }
/** An instruction that writes a variable. */
class WriteAccess extends VariableAccess, @cil_write_access {
/** Gets the expression whose value is used in this variable write. */
Expr getExpr() { none() }
}

View File

@@ -437,6 +437,9 @@ class Operator extends Callable, Member, Attributable, @operator {
override string getName() { operators(this, _, result, _, _, _) }
/**
* Gets the metadata name of the operator, such as `op_implicit` or `op_RightShift`.
*/
string getFunctionName() { none() }
override ValueOrRefType getDeclaringType() { operators(this, _, _, result, _, _) }

View File

@@ -514,6 +514,11 @@ predicate convNullableType(ValueOrRefType fromType, NullableType toType) {
)
}
/**
* Holds if `fromType` is `NullType`, and `toType` is a type that can represent
* the `null` value, such as a reference type, `Nullable<T>` or a type parameter
* with contraints that restrict it to a reference type.
*/
// This is a deliberate, small Cartesian product, so we have manually lifted it to force the
// evaluator to evaluate it in its entirety, rather than trying to optimize it in context.
pragma[noinline]

View File

@@ -26,6 +26,7 @@ class RuntimeMethod extends RuntimeCallable {
this instanceof CIL::Method
}
/** Holds if the method is `static`. */
predicate isStatic() { this.(Method).isStatic() or this.(CIL::Method).isStatic() }
}

View File

@@ -1011,6 +1011,7 @@ class RangeExpr extends Expr, @range_expr {
/** An index expression, for example `^1` meaning "1 from the end". */
class IndexExpr extends Expr, @index_expr {
/** Gets the sub expression of this index expression. */
Expr getExpr() { result.getParent() = this }
override string toString() { result = "^..." }

View File

@@ -8,7 +8,12 @@ private import semmle.code.csharp.frameworks.system.collections.Generic
private import semmle.code.csharp.frameworks.Sql
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
/**
* Definitions relating to the `System.ComponentModel.DataAnnotations`
* namespace.
*/
module DataAnnotations {
/** Class for `NotMappedAttribute`. */
class NotMappedAttribute extends Attribute {
NotMappedAttribute() {
this
@@ -18,6 +23,10 @@ module DataAnnotations {
}
}
/**
* Definitions relating to the `Microsoft.EntityFrameworkCore` or
* `System.Data.Entity` namespaces.
*/
module EntityFramework {
/** An EF6 or EFCore namespace. */
class EFNamespace extends Namespace {
@@ -43,12 +52,14 @@ module EntityFramework {
class DbContext extends EFClass {
DbContext() { this.getName() = "DbContext" }
/** Gets a `Find` or `FindAsync` method in the `DbContext`. */
Method getAFindMethod() {
result = this.getAMethod("Find")
or
result = this.getAMethod("FindAsync")
}
/** Gets an `Update` method in the `DbContext`. */
Method getAnUpdateMethod() { result = this.getAMethod("Update") }
}
@@ -119,6 +130,7 @@ module EntityFramework {
preservesValue = false
}
/** Gets a conversion operator from `string` to `RawSqlString`. */
ConversionOperator getAConversionTo() {
result = this.getAMember() and
result.getTargetType() instanceof RawSqlStringStruct and

View File

@@ -135,8 +135,10 @@ module JsonNET {
class JsonSerializerClass extends JsonClass, LibraryTypeDataFlow {
JsonSerializerClass() { this.hasName("JsonSerializer") }
/** Gets the method for `JsonSerializer.Serialize`. */
Method getSerializeMethod() { result = this.getAMethod("Serialize") }
/** Gets the method for `JsonSerializer.Deserialize`. */
Method getDeserializeMethod() { result = this.getAMethod("Deserialize") }
override predicate callableFlow(

View File

@@ -1,8 +1,13 @@
/**
* Classes for modelling NHibernate.
*/
import csharp
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.frameworks.system.Collections
private import semmle.code.csharp.frameworks.Sql
/** Definitions relating to the `NHibernate` package. */
module NHibernate {
/** A class that is mapped to the database. */
abstract class MappedClass extends Class { }

View File

@@ -5,6 +5,7 @@
private import csharp as csharp
private import semmle.code.csharp.frameworks.System as System
/** Definitions relating to the `System.Linq` namespace. */
module SystemLinq {
/** The `System.Linq` namespace. */
class Namespace extends csharp::Namespace {

View File

@@ -5,6 +5,7 @@
private import csharp as csharp
private import semmle.code.csharp.frameworks.system.Data as Data
/** Definitions relating to the `System.Data.Common` namespace. */
module SystemDataCommon {
/** The `System.Data.Common` namespace. */
class Namespace extends csharp::Namespace {

View File

@@ -5,6 +5,7 @@
private import csharp as csharp
private import semmle.code.csharp.frameworks.system.Data as Data
/** Definitions relating to the `System.Data.Entity` namespace. */
module SystemDataEntity {
/** The `System.Data.Entity` namespace. */
class Namespace extends csharp::Namespace {
@@ -78,6 +79,7 @@ module SystemDataEntity {
}
}
/** Definitions relating to the `System.Data.Entity.Infrastructure` namespace. */
module SystemDataEntityInfrastructure {
/** The `System.Data.Entity.Infrastructure` namespace. */
class Namespace extends csharp::Namespace {

View File

@@ -5,6 +5,7 @@
private import csharp as csharp
private import semmle.code.csharp.frameworks.system.Linq
/** Definitions relating to the `System.Linq.Expressions` namespace. */
module SystemLinqExpressions {
/** The `System.Linq.Expressions` namespace. */
class Namespace extends csharp::Namespace {

View File

@@ -1,3 +1,7 @@
/**
* Provides classes related to the namespace `System.Text.RegularExpressions`.
*/
import default
import semmle.code.csharp.frameworks.system.Text

View File

@@ -3,6 +3,7 @@
import csharp as csharp
private import semmle.code.csharp.frameworks.system.Xml as xml
/** Definitions relating to the `System.Xml.XPath` namespace. */
module SystemXmlXPath {
/** The `System.Xml.XPath` namespace. */
class Namespace extends csharp::Namespace {

View File

@@ -222,6 +222,10 @@ predicate shareFieldOrProperty(ValueOrRefType t, Method m1, Method m2) {
)
}
/**
* Holds if the declaring type of method `m` is `t` and `m` accesses declaration
* `d`, which is either a field or a property.
*/
predicate methodUsesFieldOrProperty(ValueOrRefType t, Method m, Declaration d) {
m.getDeclaringType() = t and
(

View File

@@ -8,6 +8,7 @@ import csharp
/** An unsafe deserializer. */
abstract class UnsafeDeserializer extends Callable { }
/** An unsafe deserializer method in the `System.*` namespace. */
class SystemDeserializer extends UnsafeDeserializer {
SystemDeserializer() {
this
@@ -48,12 +49,17 @@ class SystemDeserializer extends UnsafeDeserializer {
}
}
/** An unsafe deserializer method in the `Microsoft.*` namespace. */
class MicrosoftDeserializer extends UnsafeDeserializer {
MicrosoftDeserializer() {
this.hasQualifiedName("Microsoft.Web.Design.Remote.ProxyObject", "DecodeValue")
}
}
/**
* An unsafe deserializer method that calls any unsafe deserializer on any of
* the parameters.
*/
class WrapperDeserializer extends UnsafeDeserializer {
WrapperDeserializer() {
exists(Call call |

View File

@@ -1,5 +1,14 @@
/**
* Provides classes to identify any .Net serializable type such as types
* attributed with `SerializableAttribute` and types implementing the
* `ISerializable` interface.
*/
import csharp
/**
* A constructor with `SerializationInfo` and `StreamingContext` parameters.
*/
class SerializationConstructor extends Constructor {
SerializationConstructor() {
this.getNumberOfParameters() = 2 and
@@ -91,16 +100,3 @@ class CustomBinarySerializableType extends BinarySerializableType {
result.(SerializationConstructor).getDeclaringType() = this
}
}
class DangerousCallable extends Callable {
DangerousCallable() {
//files
this.(Method).getQualifiedName().matches("System.IO.File.Write%") or
this.(Method).getQualifiedName().matches("System.IO.File.%Copy%") or
this.(Method).getQualifiedName().matches("System.IO.File.%Move%") or
this.(Method).getQualifiedName().matches("System.IO.File.%Append%") or
this.(Method).getQualifiedName().matches("System.IO.%.%Delete%") or
//assembly
this.(Method).getQualifiedName().matches("System.Reflection.Assembly.%Load%")
}
}

View File

@@ -1,3 +1,8 @@
/**
* Provides `Callable` classes, which are things that can be called
* such as methods and constructors.
*/
import Declaration
import Variable
import Expr

View File

@@ -1,3 +1,5 @@
/** Provides classes for .Net variables, such as fields and parameters. */
import Declaration
import Callable

View File

@@ -1 +1 @@
| expressions.cs:443:33:443:66 | delegate(...) { ... } |
| expressions.cs:455:33:455:66 | delegate(...) { ... } |

View File

@@ -1 +1 @@
| expressions.cs:443:33:443:66 | delegate(...) { ... } | expressions.cs:443:47:443:47 | x |
| expressions.cs:455:33:455:66 | delegate(...) { ... } | expressions.cs:455:47:455:47 | x |

View File

@@ -1 +1 @@
| expressions.cs:443:33:443:66 | delegate(...) { ... } |
| expressions.cs:455:33:455:66 | delegate(...) { ... } |

View File

@@ -1 +1 @@
| expressions.cs:445:28:445:53 | delegate(...) { ... } | expressions.cs:445:28:445:53 | delegate(...) { ... } |
| expressions.cs:457:28:457:53 | delegate(...) { ... } | expressions.cs:457:28:457:53 | delegate(...) { ... } |

View File

@@ -1 +1 @@
| expressions.cs:445:28:445:53 | delegate(...) { ... } | expressions.cs:445:46:445:46 | access to local variable j |
| expressions.cs:457:28:457:53 | delegate(...) { ... } | expressions.cs:457:46:457:46 | access to local variable j |

View File

@@ -1,3 +1,27 @@
| expressions.cs:168:27:168:44 | array creation of type Object[] | expressions.cs:168:27:168:44 | 1 | true |
| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 2 | true |
| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true |
| expressions.cs:409:23:409:65 | array creation of type Int32[,] | expressions.cs:409:23:409:65 | 3 | true |
| expressions.cs:437:24:437:66 | array creation of type Int32[,] | expressions.cs:437:24:437:66 | 2 | true |
| expressions.cs:437:24:437:66 | array creation of type Int32[,] | expressions.cs:437:24:437:66 | 3 | true |
| expressions.cs:438:17:438:93 | array creation of type Int32[,,] | expressions.cs:438:17:438:93 | 2 | true |
| expressions.cs:438:17:438:93 | array creation of type Int32[,,] | expressions.cs:438:17:438:93 | 2 | true |
| expressions.cs:438:17:438:93 | array creation of type Int32[,,] | expressions.cs:438:17:438:93 | 3 | true |
| expressions.cs:439:17:443:13 | array creation of type Int32[,][,] | expressions.cs:439:17:443:13 | 2 | true |
| expressions.cs:439:17:443:13 | array creation of type Int32[,][,] | expressions.cs:439:17:443:13 | 3 | true |
| expressions.cs:441:19:441:45 | array creation of type Int32[,] | expressions.cs:441:19:441:45 | 2 | true |
| expressions.cs:441:19:441:45 | array creation of type Int32[,] | expressions.cs:441:19:441:45 | 2 | true |
| expressions.cs:441:48:441:82 | array creation of type Int32[,] | expressions.cs:441:48:441:82 | 2 | true |
| expressions.cs:441:48:441:82 | array creation of type Int32[,] | expressions.cs:441:48:441:82 | 3 | true |
| expressions.cs:441:85:441:122 | array creation of type Int32[,] | expressions.cs:441:85:441:122 | 2 | true |
| expressions.cs:441:85:441:122 | array creation of type Int32[,] | expressions.cs:441:85:441:122 | 3 | true |
| expressions.cs:442:19:442:45 | array creation of type Int32[,] | expressions.cs:442:19:442:45 | 2 | true |
| expressions.cs:442:19:442:45 | array creation of type Int32[,] | expressions.cs:442:19:442:45 | 2 | true |
| expressions.cs:442:48:442:82 | array creation of type Int32[,] | expressions.cs:442:48:442:82 | 2 | true |
| expressions.cs:442:48:442:82 | array creation of type Int32[,] | expressions.cs:442:48:442:82 | 3 | true |
| expressions.cs:442:85:442:122 | array creation of type Int32[,] | expressions.cs:442:85:442:122 | 2 | true |
| expressions.cs:442:85:442:122 | array creation of type Int32[,] | expressions.cs:442:85:442:122 | 3 | true |
| expressions.cs:444:17:444:123 | array creation of type Int32[,][] | expressions.cs:444:17:444:123 | 2 | true |
| expressions.cs:444:32:444:54 | array creation of type Int32[,] | expressions.cs:444:32:444:54 | 1 | true |
| expressions.cs:444:32:444:54 | array creation of type Int32[,] | expressions.cs:444:32:444:54 | 2 | true |
| expressions.cs:444:57:444:121 | array creation of type Int32[,] | expressions.cs:444:57:444:121 | 3 | true |
| expressions.cs:444:57:444:121 | array creation of type Int32[,] | expressions.cs:444:57:444:121 | 4 | true |

View File

@@ -1 +1 @@
| expressions.cs:437:36:437:53 | (...) => ... |
| expressions.cs:449:36:449:53 | (...) => ... |

View File

@@ -1 +1 @@
| expressions.cs:438:38:438:59 | (...) => ... |
| expressions.cs:450:38:450:59 | (...) => ... |

View File

@@ -1 +1 @@
| expressions.cs:439:33:439:48 | (...) => ... |
| expressions.cs:451:33:451:48 | (...) => ... |

View File

@@ -1 +1 @@
| expressions.cs:440:36:440:64 | (...) => ... |
| expressions.cs:452:36:452:64 | (...) => ... |

View File

@@ -1 +1 @@
| expressions.cs:441:20:441:34 | (...) => ... |
| expressions.cs:453:20:453:34 | (...) => ... |

View File

@@ -1 +1 @@
| expressions.cs:442:23:442:47 | (...) => ... |
| expressions.cs:454:23:454:47 | (...) => ... |

View File

@@ -1,4 +1,4 @@
| expressions.cs:458:20:458:27 | addition | expressions.cs:460:26:460:26 | access to parameter a | expressions.cs:473:40:473:40 | + |
| expressions.cs:458:20:458:27 | addition | expressions.cs:460:30:460:30 | access to parameter b | expressions.cs:473:40:473:40 | + |
| expressions.cs:458:20:458:27 | addition | expressions.cs:461:13:461:18 | access to local variable result | expressions.cs:473:40:473:40 | + |
| expressions.cs:458:20:458:27 | addition | expressions.cs:461:23:461:23 | access to parameter c | expressions.cs:473:40:473:40 | + |
| expressions.cs:470:20:470:27 | addition | expressions.cs:472:26:472:26 | access to parameter a | expressions.cs:485:40:485:40 | + |
| expressions.cs:470:20:470:27 | addition | expressions.cs:472:30:472:30 | access to parameter b | expressions.cs:485:40:485:40 | + |
| expressions.cs:470:20:470:27 | addition | expressions.cs:473:13:473:18 | access to local variable result | expressions.cs:485:40:485:40 | + |
| expressions.cs:470:20:470:27 | addition | expressions.cs:473:23:473:23 | access to parameter c | expressions.cs:485:40:485:40 | + |

View File

@@ -1,2 +1,2 @@
| expressions.cs:452:21:452:35 | delegateCombine | expressions.cs:450:11:450:23 | OperatorCalls | expressions.cs:455:13:455:27 | access to local variable PropertyChanged | expressions.cs:479:30:479:39 | MyDelegate |
| expressions.cs:452:21:452:35 | delegateCombine | expressions.cs:450:11:450:23 | OperatorCalls | expressions.cs:455:32:455:34 | access to parameter fun | expressions.cs:479:30:479:39 | MyDelegate |
| expressions.cs:464:21:464:35 | delegateCombine | expressions.cs:462:11:462:23 | OperatorCalls | expressions.cs:467:13:467:27 | access to local variable PropertyChanged | expressions.cs:491:30:491:39 | MyDelegate |
| expressions.cs:464:21:464:35 | delegateCombine | expressions.cs:462:11:462:23 | OperatorCalls | expressions.cs:467:32:467:34 | access to parameter fun | expressions.cs:491:30:491:39 | MyDelegate |

View File

@@ -1491,333 +1491,467 @@ expressions.cs:
# 432| 0: [Parameter] x
# 432| 1: [Parameter] y
# 433| 7: [DelegateType] Unit
# 435| 8: [Method] MainAnonymousFunctions
# 435| 8: [Method] MultiDimensionalArrayCreations
# 436| 4: [BlockStmt] {...}
# 437| 0: [LocalVariableDeclStmt] ... ...;
# 437| 0: [LocalVariableDeclAndInitExpr] Func<Int16,Byte> f1 = ...
# 437| 0: [LambdaExpr] (...) => ...
# 437| 0: [CastExpr] (...) ...
# 437| 0: [AddExpr] ... + ...
# 437| 0: [CastExpr] (...) ...
# 437| 0: [ParameterAccess] access to parameter x
# 437| 1: [IntLiteral] 1
# 437| 1: [TypeAccess] access to type Byte
# 437| 0: [LocalVariableDeclAndInitExpr] Object o = ...
# 437| 0: [ArrayCreation] array creation of type Int32[,]
# 437| -1: [ArrayInitializer] { ..., ... }
# 437| 0: [ArrayInitializer] { ..., ... }
# 437| 0: [IntLiteral] 1
# 437| 1: [IntLiteral] 2
# 437| 1: [ArrayInitializer] { ..., ... }
# 437| 0: [IntLiteral] 3
# 437| 1: [IntLiteral] 4
# 437| 2: [ArrayInitializer] { ..., ... }
# 437| 0: [IntLiteral] 5
# 437| 1: [IntLiteral] 6
# 437| 1: [LocalVariableAccess] access to local variable o
# 438| 1: [ExprStmt] ...;
# 438| 0: [AssignExpr] ... = ...
# 438| 0: [ArrayCreation] array creation of type Int32[,,]
# 438| -1: [ArrayInitializer] { ..., ... }
# 438| 0: [ArrayInitializer] { ..., ... }
# 438| 0: [ArrayInitializer] { ..., ... }
# 438| 0: [IntLiteral] 1
# 438| 1: [IntLiteral] 2
# 438| 2: [IntLiteral] 3
# 438| 1: [ArrayInitializer] { ..., ... }
# 438| 0: [IntLiteral] 4
# 438| 1: [IntLiteral] 5
# 438| 2: [IntLiteral] 6
# 438| 1: [ArrayInitializer] { ..., ... }
# 438| 0: [ArrayInitializer] { ..., ... }
# 438| 0: [IntLiteral] 7
# 438| 1: [IntLiteral] 8
# 438| 2: [IntLiteral] 9
# 438| 1: [ArrayInitializer] { ..., ... }
# 438| 0: [IntLiteral] 10
# 438| 1: [IntLiteral] 11
# 438| 2: [IntLiteral] 12
# 438| 1: [LocalVariableAccess] access to local variable o
# 439| 2: [ExprStmt] ...;
# 439| 0: [AssignExpr] ... = ...
# 439| 0: [ArrayCreation] array creation of type Int32[,][,]
# 440| -1: [ArrayInitializer] { ..., ... }
# 441| 0: [ArrayInitializer] { ..., ... }
# 441| 0: [ArrayCreation] array creation of type Int32[,]
# 441| -1: [ArrayInitializer] { ..., ... }
# 441| 0: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 1
# 441| 1: [IntLiteral] 3
# 441| 1: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 5
# 441| 1: [IntLiteral] 7
# 441| 1: [ArrayCreation] array creation of type Int32[,]
# 441| -1: [ArrayInitializer] { ..., ... }
# 441| 0: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 0
# 441| 1: [IntLiteral] 2
# 441| 1: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 4
# 441| 1: [IntLiteral] 6
# 441| 2: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 8
# 441| 1: [IntLiteral] 10
# 441| 2: [ArrayCreation] array creation of type Int32[,]
# 441| -1: [ArrayInitializer] { ..., ... }
# 441| 0: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 11
# 441| 1: [IntLiteral] 22
# 441| 1: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 99
# 441| 1: [IntLiteral] 88
# 441| 2: [ArrayInitializer] { ..., ... }
# 441| 0: [IntLiteral] 0
# 441| 1: [IntLiteral] 9
# 442| 1: [ArrayInitializer] { ..., ... }
# 442| 0: [ArrayCreation] array creation of type Int32[,]
# 442| -1: [ArrayInitializer] { ..., ... }
# 442| 0: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 1
# 442| 1: [IntLiteral] 3
# 442| 1: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 5
# 442| 1: [IntLiteral] 7
# 442| 1: [ArrayCreation] array creation of type Int32[,]
# 442| -1: [ArrayInitializer] { ..., ... }
# 442| 0: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 0
# 442| 1: [IntLiteral] 2
# 442| 1: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 4
# 442| 1: [IntLiteral] 6
# 442| 2: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 8
# 442| 1: [IntLiteral] 10
# 442| 2: [ArrayCreation] array creation of type Int32[,]
# 442| -1: [ArrayInitializer] { ..., ... }
# 442| 0: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 11
# 442| 1: [IntLiteral] 22
# 442| 1: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 99
# 442| 1: [IntLiteral] 88
# 442| 2: [ArrayInitializer] { ..., ... }
# 442| 0: [IntLiteral] 0
# 442| 1: [IntLiteral] 9
# 439| 1: [LocalVariableAccess] access to local variable o
# 444| 3: [ExprStmt] ...;
# 444| 0: [AssignExpr] ... = ...
# 444| 0: [ArrayCreation] array creation of type Int32[,][]
# 444| -1: [ArrayInitializer] { ..., ... }
# 444| 0: [ArrayCreation] array creation of type Int32[,]
# 444| -1: [ArrayInitializer] { ..., ... }
# 444| 0: [ArrayInitializer] { ..., ... }
# 444| 0: [IntLiteral] 1
# 444| 1: [IntLiteral] 2
# 444| 1: [ArrayCreation] array creation of type Int32[,]
# 444| -1: [ArrayInitializer] { ..., ... }
# 444| 0: [ArrayInitializer] { ..., ... }
# 444| 0: [IntLiteral] 1
# 444| 1: [IntLiteral] 2
# 444| 2: [IntLiteral] 3
# 444| 1: [ArrayInitializer] { ..., ... }
# 444| 0: [IntLiteral] 1
# 444| 1: [IntLiteral] 2
# 444| 2: [IntLiteral] 3
# 444| 2: [ArrayInitializer] { ..., ... }
# 444| 0: [IntLiteral] 1
# 444| 1: [IntLiteral] 2
# 444| 2: [IntLiteral] 3
# 444| 3: [ArrayInitializer] { ..., ... }
# 444| 0: [IntLiteral] 1
# 444| 1: [IntLiteral] 2
# 444| 2: [IntLiteral] 3
# 444| 1: [LocalVariableAccess] access to local variable o
# 447| 9: [Method] MainAnonymousFunctions
# 448| 4: [BlockStmt] {...}
# 449| 0: [LocalVariableDeclStmt] ... ...;
# 449| 0: [LocalVariableDeclAndInitExpr] Func<Int16,Byte> f1 = ...
# 449| 0: [LambdaExpr] (...) => ...
# 449| 0: [CastExpr] (...) ...
# 449| 0: [AddExpr] ... + ...
# 449| 0: [CastExpr] (...) ...
# 449| 0: [ParameterAccess] access to parameter x
# 449| 1: [IntLiteral] 1
# 449| 1: [TypeAccess] access to type Byte
#-----| 2: (Parameters)
# 437| 0: [Parameter] x
# 437| 1: [LocalVariableAccess] access to local variable f1
# 438| 1: [LocalVariableDeclStmt] ... ...;
# 438| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Double> f2 = ...
# 438| 0: [LambdaExpr] (...) => ...
# 438| 0: [BlockStmt] {...}
# 438| 0: [ReturnStmt] return ...;
# 438| 0: [CastExpr] (...) ...
# 438| 0: [AddExpr] ... + ...
# 438| 0: [ParameterAccess] access to parameter x
# 438| 1: [IntLiteral] 1
# 449| 0: [Parameter] x
# 449| 1: [LocalVariableAccess] access to local variable f1
# 450| 1: [LocalVariableDeclStmt] ... ...;
# 450| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Double> f2 = ...
# 450| 0: [LambdaExpr] (...) => ...
# 450| 0: [BlockStmt] {...}
# 450| 0: [ReturnStmt] return ...;
# 450| 0: [CastExpr] (...) ...
# 450| 0: [AddExpr] ... + ...
# 450| 0: [ParameterAccess] access to parameter x
# 450| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 438| 0: [Parameter] x
# 438| 1: [LocalVariableAccess] access to local variable f2
# 439| 2: [LocalVariableDeclStmt] ... ...;
# 439| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f3 = ...
# 439| 0: [LambdaExpr] (...) => ...
# 439| 0: [AddExpr] ... + ...
# 439| 0: [ParameterAccess] access to parameter x
# 439| 1: [IntLiteral] 1
# 450| 0: [Parameter] x
# 450| 1: [LocalVariableAccess] access to local variable f2
# 451| 2: [LocalVariableDeclStmt] ... ...;
# 451| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f3 = ...
# 451| 0: [LambdaExpr] (...) => ...
# 451| 0: [AddExpr] ... + ...
# 451| 0: [ParameterAccess] access to parameter x
# 451| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 439| 0: [Parameter] x
# 439| 1: [LocalVariableAccess] access to local variable f3
# 440| 3: [LocalVariableDeclStmt] ... ...;
# 440| 0: [LocalVariableDeclAndInitExpr] Func<Int32,String> f4 = ...
# 440| 0: [LambdaExpr] (...) => ...
# 440| 0: [BlockStmt] {...}
# 440| 0: [ReturnStmt] return ...;
# 440| 0: [AddExpr] ... + ...
# 440| 0: [CastExpr] (...) ...
# 440| 0: [ParameterAccess] access to parameter x
# 440| 1: [StringLiteral] ""
# 451| 0: [Parameter] x
# 451| 1: [LocalVariableAccess] access to local variable f3
# 452| 3: [LocalVariableDeclStmt] ... ...;
# 452| 0: [LocalVariableDeclAndInitExpr] Func<Int32,String> f4 = ...
# 452| 0: [LambdaExpr] (...) => ...
# 452| 0: [BlockStmt] {...}
# 452| 0: [ReturnStmt] return ...;
# 452| 0: [AddExpr] ... + ...
# 452| 0: [CastExpr] (...) ...
# 452| 0: [ParameterAccess] access to parameter x
# 452| 1: [StringLiteral] ""
#-----| 2: (Parameters)
# 440| 0: [Parameter] x
# 440| 1: [LocalVariableAccess] access to local variable f4
# 441| 4: [LocalVariableDeclStmt] ... ...;
# 441| 0: [LocalVariableDeclAndInitExpr] S f5 = ...
# 441| 0: [LambdaExpr] (...) => ...
# 441| 0: [MulExpr] ... * ...
# 441| 0: [ParameterAccess] access to parameter x
# 441| 1: [ParameterAccess] access to parameter y
# 452| 0: [Parameter] x
# 452| 1: [LocalVariableAccess] access to local variable f4
# 453| 4: [LocalVariableDeclStmt] ... ...;
# 453| 0: [LocalVariableDeclAndInitExpr] S f5 = ...
# 453| 0: [LambdaExpr] (...) => ...
# 453| 0: [MulExpr] ... * ...
# 453| 0: [ParameterAccess] access to parameter x
# 453| 1: [ParameterAccess] access to parameter y
#-----| 2: (Parameters)
# 441| 0: [Parameter] x
# 441| 1: [Parameter] y
# 441| 1: [LocalVariableAccess] access to local variable f5
# 442| 5: [LocalVariableDeclStmt] ... ...;
# 442| 0: [LocalVariableDeclAndInitExpr] Unit f6 = ...
# 442| 0: [LambdaExpr] (...) => ...
# 442| 0: [MethodCall] call to method WriteLine
# 442| -1: [TypeAccess] access to type Console
# 442| 1: [LocalVariableAccess] access to local variable f6
# 443| 6: [LocalVariableDeclStmt] ... ...;
# 443| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f7 = ...
# 443| 0: [AnonymousMethodExpr] delegate(...) { ... }
# 443| 0: [BlockStmt] {...}
# 443| 0: [ReturnStmt] return ...;
# 443| 0: [AddExpr] ... + ...
# 443| 0: [ParameterAccess] access to parameter x
# 443| 1: [IntLiteral] 1
# 453| 0: [Parameter] x
# 453| 1: [Parameter] y
# 453| 1: [LocalVariableAccess] access to local variable f5
# 454| 5: [LocalVariableDeclStmt] ... ...;
# 454| 0: [LocalVariableDeclAndInitExpr] Unit f6 = ...
# 454| 0: [LambdaExpr] (...) => ...
# 454| 0: [MethodCall] call to method WriteLine
# 454| -1: [TypeAccess] access to type Console
# 454| 1: [LocalVariableAccess] access to local variable f6
# 455| 6: [LocalVariableDeclStmt] ... ...;
# 455| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f7 = ...
# 455| 0: [AnonymousMethodExpr] delegate(...) { ... }
# 455| 0: [BlockStmt] {...}
# 455| 0: [ReturnStmt] return ...;
# 455| 0: [AddExpr] ... + ...
# 455| 0: [ParameterAccess] access to parameter x
# 455| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 443| 0: [Parameter] x
# 443| 1: [LocalVariableAccess] access to local variable f7
# 444| 7: [LocalVariableDeclStmt] ... ...;
# 444| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
# 444| 0: [IntLiteral] 0
# 444| 1: [LocalVariableAccess] access to local variable j
# 445| 8: [LocalVariableDeclStmt] ... ...;
# 445| 0: [LocalVariableDeclAndInitExpr] Func<Int32> f8 = ...
# 445| 0: [AnonymousMethodExpr] delegate(...) { ... }
# 445| 0: [BlockStmt] {...}
# 445| 0: [ReturnStmt] return ...;
# 445| 0: [AddExpr] ... + ...
# 445| 0: [LocalVariableAccess] access to local variable j
# 445| 1: [IntLiteral] 1
# 445| 1: [LocalVariableAccess] access to local variable f8
# 450| 18: [Class] OperatorCalls
# 452| 5: [Method] delegateCombine
# 455| 0: [Parameter] x
# 455| 1: [LocalVariableAccess] access to local variable f7
# 456| 7: [LocalVariableDeclStmt] ... ...;
# 456| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
# 456| 0: [IntLiteral] 0
# 456| 1: [LocalVariableAccess] access to local variable j
# 457| 8: [LocalVariableDeclStmt] ... ...;
# 457| 0: [LocalVariableDeclAndInitExpr] Func<Int32> f8 = ...
# 457| 0: [AnonymousMethodExpr] delegate(...) { ... }
# 457| 0: [BlockStmt] {...}
# 457| 0: [ReturnStmt] return ...;
# 457| 0: [AddExpr] ... + ...
# 457| 0: [LocalVariableAccess] access to local variable j
# 457| 1: [IntLiteral] 1
# 457| 1: [LocalVariableAccess] access to local variable f8
# 462| 18: [Class] OperatorCalls
# 464| 5: [Method] delegateCombine
#-----| 2: (Parameters)
# 452| 0: [Parameter] fun
# 453| 4: [BlockStmt] {...}
# 454| 0: [LocalVariableDeclStmt] ... ...;
# 454| 0: [LocalVariableDeclAndInitExpr] MyDelegate PropertyChanged = ...
# 454| 0: [NullLiteral] null
# 454| 1: [LocalVariableAccess] access to local variable PropertyChanged
# 455| 1: [ExprStmt] ...;
# 455| 0: [AssignAddExpr] ... += ...
# 455| 0: [ParameterAccess] access to parameter fun
# 455| 1: [LocalVariableAccess] access to local variable PropertyChanged
# 458| 6: [Method] addition
# 464| 0: [Parameter] fun
# 465| 4: [BlockStmt] {...}
# 466| 0: [LocalVariableDeclStmt] ... ...;
# 466| 0: [LocalVariableDeclAndInitExpr] MyDelegate PropertyChanged = ...
# 466| 0: [NullLiteral] null
# 466| 1: [LocalVariableAccess] access to local variable PropertyChanged
# 467| 1: [ExprStmt] ...;
# 467| 0: [AssignAddExpr] ... += ...
# 467| 0: [ParameterAccess] access to parameter fun
# 467| 1: [LocalVariableAccess] access to local variable PropertyChanged
# 470| 6: [Method] addition
#-----| 2: (Parameters)
# 458| 0: [Parameter] a
# 458| 1: [Parameter] b
# 458| 2: [Parameter] c
# 459| 4: [BlockStmt] {...}
# 460| 0: [LocalVariableDeclStmt] ... ...;
# 460| 0: [LocalVariableDeclAndInitExpr] Num result = ...
# 460| 0: [OperatorCall] call to operator +
# 460| 0: [ParameterAccess] access to parameter a
# 460| 1: [ParameterAccess] access to parameter b
# 460| 1: [LocalVariableAccess] access to local variable result
# 461| 1: [ExprStmt] ...;
# 461| 0: [AssignAddExpr] ... += ...
# 461| 0: [ParameterAccess] access to parameter c
# 461| 1: [LocalVariableAccess] access to local variable result
# 462| 2: [ReturnStmt] return ...;
# 462| 0: [LocalVariableAccess] access to local variable result
# 464| 7: [Class] Num
# 466| 4: [Field] value
# 468| 5: [InstanceConstructor] Num
# 470| 0: [Parameter] a
# 470| 1: [Parameter] b
# 470| 2: [Parameter] c
# 471| 4: [BlockStmt] {...}
# 472| 0: [LocalVariableDeclStmt] ... ...;
# 472| 0: [LocalVariableDeclAndInitExpr] Num result = ...
# 472| 0: [OperatorCall] call to operator +
# 472| 0: [ParameterAccess] access to parameter a
# 472| 1: [ParameterAccess] access to parameter b
# 472| 1: [LocalVariableAccess] access to local variable result
# 473| 1: [ExprStmt] ...;
# 473| 0: [AssignAddExpr] ... += ...
# 473| 0: [ParameterAccess] access to parameter c
# 473| 1: [LocalVariableAccess] access to local variable result
# 474| 2: [ReturnStmt] return ...;
# 474| 0: [LocalVariableAccess] access to local variable result
# 476| 7: [Class] Num
# 478| 4: [Field] value
# 480| 5: [InstanceConstructor] Num
#-----| 2: (Parameters)
# 468| 0: [Parameter] value
# 469| 4: [BlockStmt] {...}
# 470| 0: [ExprStmt] ...;
# 470| 0: [AssignExpr] ... = ...
# 470| 0: [ParameterAccess] access to parameter value
# 470| 1: [FieldAccess] access to field value
# 470| -1: [ThisAccess] this access
# 473| 6: [AddOperator] +
# 480| 0: [Parameter] value
# 481| 4: [BlockStmt] {...}
# 482| 0: [ExprStmt] ...;
# 482| 0: [AssignExpr] ... = ...
# 482| 0: [ParameterAccess] access to parameter value
# 482| 1: [FieldAccess] access to field value
# 482| -1: [ThisAccess] this access
# 485| 6: [AddOperator] +
#-----| 2: (Parameters)
# 473| 0: [Parameter] c1
# 473| 1: [Parameter] c2
# 474| 4: [BlockStmt] {...}
# 475| 0: [ReturnStmt] return ...;
# 475| 0: [ObjectCreation] object creation of type Num
# 475| 0: [AddExpr] ... + ...
# 475| 0: [FieldAccess] access to field value
# 475| -1: [ParameterAccess] access to parameter c1
# 475| 1: [FieldAccess] access to field value
# 475| -1: [ParameterAccess] access to parameter c2
# 479| 8: [DelegateType] MyDelegate
# 485| 0: [Parameter] c1
# 485| 1: [Parameter] c2
# 486| 4: [BlockStmt] {...}
# 487| 0: [ReturnStmt] return ...;
# 487| 0: [ObjectCreation] object creation of type Num
# 487| 0: [AddExpr] ... + ...
# 487| 0: [FieldAccess] access to field value
# 487| -1: [ParameterAccess] access to parameter c1
# 487| 1: [FieldAccess] access to field value
# 487| -1: [ParameterAccess] access to parameter c2
# 491| 8: [DelegateType] MyDelegate
#-----| 2: (Parameters)
# 479| 0: [Parameter] e
# 482| 19: [Class] ExpressionDepth
# 484| 5: [Field] d
# 484| 1: [AssignExpr] ... = ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [AddExpr] ... + ...
# 484| 0: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 484| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 485| 1: [IntLiteral] 1
# 484| 1: [MemberConstantAccess] access to constant d
# 488| 20: [Class] TupleExprs
# 490| 5: [Method] Test
# 491| 4: [BlockStmt] {...}
# 492| 0: [LocalVariableDeclStmt] ... ...;
# 492| 0: [LocalVariableDeclAndInitExpr] (Int32,String) a = ...
# 492| 0: [DefaultValueExpr] default(...)
# 492| 0: [TypeAccess] access to type (Int32,String)
# 492| 1: [LocalVariableAccess] access to local variable a
# 493| 1: [LocalVariableDeclStmt] ... ...;
# 493| 0: [LocalVariableDeclAndInitExpr] (Boolean,Int32[],Object) b = ...
# 493| 0: [DefaultValueExpr] default(...)
# 493| 0: [TypeAccess] access to type (Boolean,Int32[],Object)
# 493| 1: [LocalVariableAccess] access to local variable b
# 494| 2: [LocalVariableDeclStmt] ... ...;
# 494| 0: [LocalVariableDeclAndInitExpr] Type x = ...
# 494| 0: [TypeofExpr] typeof(...)
# 494| 0: [TypeAccess] access to type (Int32,String)
# 494| 1: [LocalVariableAccess] access to local variable x
# 495| 3: [LocalVariableDeclStmt] ... ...;
# 495| 0: [LocalVariableDeclAndInitExpr] Type y = ...
# 495| 0: [TypeofExpr] typeof(...)
# 495| 0: [TypeAccess] access to type (Boolean,Int32[],dynamic)
# 495| 1: [LocalVariableAccess] access to local variable y
# 491| 0: [Parameter] e
# 494| 19: [Class] ExpressionDepth
# 496| 5: [Field] d
# 496| 1: [AssignExpr] ... = ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [AddExpr] ... + ...
# 496| 0: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 496| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 497| 1: [IntLiteral] 1
# 496| 1: [MemberConstantAccess] access to constant d
# 500| 20: [Class] TupleExprs
# 502| 5: [Method] Test
# 503| 4: [BlockStmt] {...}
# 504| 0: [LocalVariableDeclStmt] ... ...;
# 504| 0: [LocalVariableDeclAndInitExpr] (Int32,String) a = ...
# 504| 0: [DefaultValueExpr] default(...)
# 504| 0: [TypeAccess] access to type (Int32,String)
# 504| 1: [LocalVariableAccess] access to local variable a
# 505| 1: [LocalVariableDeclStmt] ... ...;
# 505| 0: [LocalVariableDeclAndInitExpr] (Boolean,Int32[],Object) b = ...
# 505| 0: [DefaultValueExpr] default(...)
# 505| 0: [TypeAccess] access to type (Boolean,Int32[],Object)
# 505| 1: [LocalVariableAccess] access to local variable b
# 506| 2: [LocalVariableDeclStmt] ... ...;
# 506| 0: [LocalVariableDeclAndInitExpr] Type x = ...
# 506| 0: [TypeofExpr] typeof(...)
# 506| 0: [TypeAccess] access to type (Int32,String)
# 506| 1: [LocalVariableAccess] access to local variable x
# 507| 3: [LocalVariableDeclStmt] ... ...;
# 507| 0: [LocalVariableDeclAndInitExpr] Type y = ...
# 507| 0: [TypeofExpr] typeof(...)
# 507| 0: [TypeAccess] access to type (Boolean,Int32[],dynamic)
# 507| 1: [LocalVariableAccess] access to local variable y

View File

@@ -65,7 +65,7 @@
| expressions.cs:377:43:377:46 | access to field name | expressions.cs:377:43:377:46 | this access |
| expressions.cs:377:57:377:60 | access to field name | expressions.cs:377:57:377:60 | this access |
| expressions.cs:378:57:378:68 | access to field phoneNumbers | expressions.cs:378:57:378:68 | this access |
| expressions.cs:442:29:442:47 | call to method WriteLine | expressions.cs:442:29:442:35 | access to type Console |
| expressions.cs:470:17:470:26 | access to field value | expressions.cs:470:17:470:20 | this access |
| expressions.cs:475:32:475:39 | access to field value | expressions.cs:475:32:475:33 | access to parameter c1 |
| expressions.cs:475:43:475:50 | access to field value | expressions.cs:475:43:475:44 | access to parameter c2 |
| expressions.cs:454:29:454:47 | call to method WriteLine | expressions.cs:454:29:454:35 | access to type Console |
| expressions.cs:482:17:482:26 | access to field value | expressions.cs:482:17:482:20 | this access |
| expressions.cs:487:32:487:39 | access to field value | expressions.cs:487:32:487:33 | access to parameter c1 |
| expressions.cs:487:43:487:50 | access to field value | expressions.cs:487:43:487:44 | access to parameter c2 |

View File

@@ -50,7 +50,7 @@
| expressions.cs:334:30:334:30 | (...) ... | expressions.cs:334:30:334:30 | 8 |
| expressions.cs:414:31:414:31 | (...) ... | expressions.cs:414:31:414:31 | 1 |
| expressions.cs:414:39:414:39 | (...) ... | expressions.cs:414:39:414:39 | 2 |
| expressions.cs:437:41:437:53 | (...) ... | expressions.cs:437:48:437:52 | ... + ... |
| expressions.cs:437:48:437:48 | (...) ... | expressions.cs:437:48:437:48 | access to parameter x |
| expressions.cs:438:52:438:56 | (...) ... | expressions.cs:438:52:438:56 | ... + ... |
| expressions.cs:440:56:440:56 | (...) ... | expressions.cs:440:56:440:56 | access to parameter x |
| expressions.cs:449:41:449:53 | (...) ... | expressions.cs:449:48:449:52 | ... + ... |
| expressions.cs:449:48:449:48 | (...) ... | expressions.cs:449:48:449:48 | access to parameter x |
| expressions.cs:450:52:450:56 | (...) ... | expressions.cs:450:52:450:56 | ... + ... |
| expressions.cs:452:56:452:56 | (...) ... | expressions.cs:452:56:452:56 | access to parameter x |

View File

@@ -1,4 +1,4 @@
| expressions.cs:492:29:492:41 | access to type (Int32,String) | expressions.cs:492:29:492:41 | (Int32,String) |
| expressions.cs:493:29:493:49 | access to type (Boolean,Int32[],Object) | expressions.cs:493:29:493:49 | (Boolean,Int32[],Object) |
| expressions.cs:494:28:494:40 | access to type (Int32,String) | expressions.cs:492:29:492:41 | (Int32,String) |
| expressions.cs:495:28:495:49 | access to type (Boolean,Int32[],dynamic) | expressions.cs:495:28:495:49 | (Boolean,Int32[],dynamic) |
| expressions.cs:504:29:504:41 | access to type (Int32,String) | expressions.cs:504:29:504:41 | (Int32,String) |
| expressions.cs:505:29:505:49 | access to type (Boolean,Int32[],Object) | expressions.cs:505:29:505:49 | (Boolean,Int32[],Object) |
| expressions.cs:506:28:506:40 | access to type (Int32,String) | expressions.cs:504:29:504:41 | (Int32,String) |
| expressions.cs:507:28:507:49 | access to type (Boolean,Int32[],dynamic) | expressions.cs:507:28:507:49 | (Boolean,Int32[],dynamic) |

View File

@@ -432,6 +432,18 @@ namespace Expressions
delegate int S(int x, int y);
delegate void Unit();
void MultiDimensionalArrayCreations()
{
object o = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 } };
o = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } }, { { 7, 8, 9 }, { 10, 11, 12 } } };
o = new int[,][,]
{
{ new int[,] { {1,3}, {5,7} }, new int[,] { {0,2}, {4,6}, {8,10} }, new int[,] { {11,22}, {99,88}, {0,9} } },
{ new int[,] { {1,3}, {5,7} }, new int[,] { {0,2}, {4,6}, {8,10} }, new int[,] { {11,22}, {99,88}, {0,9} } }
};
o = new int[][,] { new int[,] { { 1, 2 } }, new int[,] { { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 }, { 1, 2, 3 } } };
}
void MainAnonymousFunctions()
{
Func<Int16, Byte> f1 = x => (byte)(x + 1); // Implicitly typed, expression body