mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Merge pull request #4821 from tamasvajk/feature/csharp9-cil-init-prop
C#: Extract init only accessors from CIL
This commit is contained in:
@@ -76,9 +76,10 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
var typeSignature = md.DecodeSignature(Cx.TypeSignatureDecoder, this);
|
||||
|
||||
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
|
||||
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
|
||||
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||
|
||||
foreach (var c in Parameters)
|
||||
foreach (var c in parameters)
|
||||
yield return c;
|
||||
|
||||
foreach (var c in PopulateFlags)
|
||||
@@ -95,7 +96,12 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
}
|
||||
|
||||
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
|
||||
yield return Tuples.cil_method(this, Name, declaringType, typeSignature.ReturnType);
|
||||
|
||||
foreach (var m in GetMethodExtractionProducts(Name, declaringType, typeSignature.ReturnType))
|
||||
{
|
||||
yield return m;
|
||||
}
|
||||
|
||||
yield return Tuples.cil_method_source_declaration(this, this);
|
||||
yield return Tuples.cil_method_location(this, Cx.Assembly);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// An entity representing a field.
|
||||
/// </summary>
|
||||
internal abstract class Field : GenericContext, IMember
|
||||
internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver
|
||||
{
|
||||
protected Field(Context cx) : base(cx)
|
||||
{
|
||||
@@ -45,7 +45,13 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return Tuples.cil_field(this, DeclaringType, Name, Type);
|
||||
var t = Type;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_field(this, DeclaringType, Name, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,12 +76,16 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
var typeSignature = mr.DecodeMethodSignature(Cx.TypeSignatureDecoder, this);
|
||||
|
||||
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
|
||||
foreach (var p in Parameters) yield return p;
|
||||
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
|
||||
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||
foreach (var p in parameters) yield return p;
|
||||
|
||||
foreach (var f in PopulateFlags) yield return f;
|
||||
|
||||
yield return Tuples.cil_method(this, Name, DeclaringType, typeSignature.ReturnType);
|
||||
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType))
|
||||
{
|
||||
yield return m;
|
||||
}
|
||||
|
||||
if (SourceDeclaration != null)
|
||||
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
||||
|
||||
@@ -3,14 +3,13 @@ using System.Reflection.Metadata;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// A method entity.
|
||||
/// </summary>
|
||||
internal abstract class Method : TypeContainer, IMember
|
||||
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
|
||||
{
|
||||
protected MethodTypeParameter[]? genericParams;
|
||||
protected GenericContext gc;
|
||||
@@ -21,6 +20,8 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.gc = gc;
|
||||
}
|
||||
|
||||
public ITypeSignature ReturnType => signature.ReturnType;
|
||||
|
||||
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
|
||||
|
||||
public override IEnumerable<Type> MethodParameters =>
|
||||
@@ -76,7 +77,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public abstract bool IsStatic { get; }
|
||||
|
||||
protected IEnumerable<Parameter> MakeParameters(IEnumerable<Type> parameterTypes)
|
||||
protected IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes)
|
||||
{
|
||||
var i = 0;
|
||||
|
||||
@@ -86,7 +87,26 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
}
|
||||
|
||||
foreach (var p in parameterTypes)
|
||||
yield return Cx.Populate(new Parameter(Cx, this, i++, p));
|
||||
{
|
||||
var t = p;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Cx.Populate(new Parameter(Cx, this, i++, t));
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<IExtractionProduct> GetMethodExtractionProducts(string name, Type declaringType, Type returnType)
|
||||
{
|
||||
var t = returnType;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_method(this, name, declaringType, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +77,19 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
|
||||
}
|
||||
|
||||
Parameters = MakeParameters(constructedTypeSignature.ParameterTypes).ToArray();
|
||||
foreach (var p in Parameters)
|
||||
var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray();
|
||||
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||
foreach (var p in parameters)
|
||||
yield return p;
|
||||
|
||||
foreach (var f in PopulateFlags)
|
||||
yield return f;
|
||||
|
||||
yield return Tuples.cil_method(this, Name, DeclaringType, constructedTypeSignature.ReturnType);
|
||||
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, constructedTypeSignature.ReturnType))
|
||||
{
|
||||
yield return m;
|
||||
}
|
||||
|
||||
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
||||
|
||||
if (typeParams.Length != unboundMethod.GenericParameterCount)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Modified types are not written directly to trap files. Instead, the modifiers are stored
|
||||
/// on the modifiable entity (field type, property/method/function pointer parameter or return types).
|
||||
/// </summary>
|
||||
internal sealed class ModifiedType : Type
|
||||
{
|
||||
public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired) : base(cx)
|
||||
{
|
||||
Unmodified = unmodified;
|
||||
Modifier = modifier;
|
||||
IsRequired = isRequired;
|
||||
}
|
||||
|
||||
public Type Unmodified { get; }
|
||||
public Type Modifier { get; }
|
||||
public bool IsRequired { get; }
|
||||
|
||||
public override CilTypeKind Kind => throw new NotImplementedException();
|
||||
|
||||
public override Namespace? ContainingNamespace => throw new NotImplementedException();
|
||||
|
||||
public override Type? ContainingType => throw new NotImplementedException();
|
||||
|
||||
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
|
||||
|
||||
public override int ThisTypeParameterCount => throw new NotImplementedException();
|
||||
|
||||
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
|
||||
|
||||
public override string Name => $"{Unmodified.Name} {(IsRequired ? "modreq" : "modopt")}({Modifier.Name})";
|
||||
|
||||
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
|
||||
|
||||
public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// A property.
|
||||
/// </summary>
|
||||
internal sealed class Property : LabelledEntity
|
||||
internal sealed class Property : LabelledEntity, ICustomModifierReceiver
|
||||
{
|
||||
private readonly Handle handle;
|
||||
private readonly Type type;
|
||||
@@ -54,7 +54,15 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
|
||||
var sig = pd.DecodeSignature(Cx.TypeSignatureDecoder, type);
|
||||
|
||||
yield return Tuples.cil_property(this, type, Cx.ShortName(pd.Name), sig.ReturnType);
|
||||
var name = Cx.ShortName(pd.Name);
|
||||
|
||||
var t = sig.ReturnType;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_property(this, type, name, t);
|
||||
|
||||
var accessors = pd.GetAccessors();
|
||||
if (!accessors.Getter.IsNil)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Reflection.Metadata;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
@@ -138,21 +139,28 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
private class Modified : ITypeSignature
|
||||
{
|
||||
private readonly ITypeSignature unmodifiedType;
|
||||
private readonly ITypeSignature modifier;
|
||||
private readonly bool isRequired;
|
||||
|
||||
public Modified(ITypeSignature unmodifiedType)
|
||||
public Modified(ITypeSignature unmodifiedType, ITypeSignature modifier, bool isRequired)
|
||||
{
|
||||
this.unmodifiedType = unmodifiedType;
|
||||
this.modifier = modifier;
|
||||
this.isRequired = isRequired;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
{
|
||||
unmodifiedType.WriteId(trapFile, gc);
|
||||
trapFile.Write(isRequired ? " modreq(" : " modopt(");
|
||||
modifier.WriteId(trapFile, gc);
|
||||
trapFile.Write(")");
|
||||
}
|
||||
}
|
||||
|
||||
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetModifiedType(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired)
|
||||
{
|
||||
return new Modified(unmodifiedType);
|
||||
return new Modified(unmodifiedType, modifier, isRequired);
|
||||
}
|
||||
|
||||
private class Pinned : ITypeSignature
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
genericContext.GetGenericTypeParameter(index);
|
||||
|
||||
Type ISignatureTypeProvider<Type, GenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) =>
|
||||
unmodifiedType; // !! Not implemented properly
|
||||
new ModifiedType(cx, unmodifiedType, modifier, isRequired);
|
||||
|
||||
Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) =>
|
||||
cx.Populate(new PointerType(cx, elementType));
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
internal interface ICustomModifierReceiver
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -188,6 +188,9 @@ namespace Semmle.Extraction.CIL
|
||||
internal static Tuple cil_virtual(Method method) =>
|
||||
new Tuple("cil_virtual", method);
|
||||
|
||||
internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) =>
|
||||
new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0);
|
||||
|
||||
internal static Tuple containerparent(Folder parent, IFileOrFolder child) =>
|
||||
new Tuple("containerparent", parent, child);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user