mirror of
https://github.com/github/codeql.git
synced 2026-02-23 10:23:41 +01:00
C#: Extract the implicit property backing field when referenced via the field keyword.
This commit is contained in:
@@ -160,6 +160,9 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
case SyntaxKind.ThisExpression:
|
||||
return This.CreateExplicit(info);
|
||||
|
||||
case SyntaxKind.FieldExpression:
|
||||
return PropertyFieldAccess.Create(info);
|
||||
|
||||
case SyntaxKind.AddressOfExpression:
|
||||
return Unary.Create(info.SetKind(ExprKind.ADDRESS_OF));
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
{
|
||||
internal class PropertyFieldAccess : Expression<FieldExpressionSyntax>
|
||||
{
|
||||
private PropertyFieldAccess(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.FIELD_ACCESS)) { }
|
||||
|
||||
public static Expression Create(ExpressionNodeInfo info) => new PropertyFieldAccess(info).TryPopulate();
|
||||
|
||||
protected override void PopulateExpression(TextWriter trapFile)
|
||||
{
|
||||
var symbolInfo = Context.GetSymbolInfo(Syntax);
|
||||
if (symbolInfo.Symbol is IFieldSymbol field)
|
||||
{
|
||||
var target = PropertyField.Create(Context, field);
|
||||
trapFile.expr_access(this, target);
|
||||
if (!field.IsStatic)
|
||||
{
|
||||
This.CreateImplicit(Context, field.ContainingType, Location, this, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class Field : CachedSymbol<IFieldSymbol>, IExpressionParentEntity
|
||||
{
|
||||
private Field(Context cx, IFieldSymbol init)
|
||||
protected Field(Context cx, IFieldSymbol init)
|
||||
: base(cx, init)
|
||||
{
|
||||
type = new Lazy<Type>(() => Entities.Type.Create(cx, Symbol.Type));
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Semmle.Extraction.CSharp.Util;
|
||||
using Semmle.Extraction.Kinds;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the autogenerated backing field `field` for a property.
|
||||
/// It is only created for properties that use the `field` keyword in their getter or setter, and
|
||||
/// is not created for auto-properties.
|
||||
/// </summary>
|
||||
internal class PropertyField : Field
|
||||
{
|
||||
protected PropertyField(Context cx, IFieldSymbol init)
|
||||
: base(cx, init)
|
||||
{
|
||||
}
|
||||
|
||||
public static new PropertyField Create(Context cx, IFieldSymbol field) => PropertyFieldFactory.Instance.CreateEntity(cx, (field, field.AssociatedSymbol), field);
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
PopulateNullability(trapFile, Symbol.GetAnnotatedType());
|
||||
|
||||
var unboundFieldKey = PropertyField.Create(Context, Symbol.OriginalDefinition);
|
||||
var name = Symbol.AssociatedSymbol is not null ? $"{Symbol.AssociatedSymbol.GetName()}.field" : Symbol.Name;
|
||||
trapFile.fields(this, VariableKind.None, name, ContainingType!, Type.TypeRef, unboundFieldKey);
|
||||
|
||||
if (Context.OnlyScaffold)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Context.ExtractLocation(Symbol))
|
||||
{
|
||||
WriteLocationsToTrap(trapFile.field_location, this, Locations);
|
||||
}
|
||||
}
|
||||
|
||||
private class PropertyFieldFactory : CachedEntityFactory<IFieldSymbol, PropertyField>
|
||||
{
|
||||
public static PropertyFieldFactory Instance { get; } = new PropertyFieldFactory();
|
||||
|
||||
public override PropertyField Create(Context cx, IFieldSymbol init) => new PropertyField(cx, init);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user