mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
148 lines
5.8 KiB
C#
148 lines
5.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Semmle.Extraction.CSharp.Entities.Expressions;
|
|
using Semmle.Extraction.Kinds;
|
|
using Semmle.Extraction.CSharp.Util;
|
|
|
|
namespace Semmle.Extraction.CSharp.Entities
|
|
{
|
|
internal class Property : CachedSymbol<IPropertySymbol>, IExpressionParentEntity
|
|
{
|
|
protected Property(Context cx, IPropertySymbol init)
|
|
: base(cx, init)
|
|
{
|
|
type = new Lazy<Type>(() => Type.Create(base.Context, Symbol.Type));
|
|
}
|
|
|
|
private readonly Lazy<Type> type;
|
|
|
|
private Type Type => type.Value;
|
|
|
|
protected override IPropertySymbol BodyDeclaringSymbol => Symbol.PartialImplementationPart ?? Symbol;
|
|
|
|
public override Microsoft.CodeAnalysis.Location? ReportingLocation => BodyDeclaringSymbol.Locations.BestOrDefault();
|
|
|
|
public override void WriteId(EscapingTextWriter trapFile)
|
|
{
|
|
trapFile.WriteSubId(Type);
|
|
trapFile.Write(" ");
|
|
trapFile.WriteSubId(ContainingType!);
|
|
trapFile.Write('.');
|
|
Method.AddExplicitInterfaceQualifierToId(Context, trapFile, Symbol.ExplicitInterfaceImplementations);
|
|
trapFile.Write(Symbol.Name);
|
|
trapFile.Write(";property");
|
|
}
|
|
|
|
public override void Populate(TextWriter trapFile)
|
|
{
|
|
PopulateAttributes();
|
|
PopulateModifiers(trapFile);
|
|
PopulateNullability(trapFile, Symbol.GetAnnotatedType());
|
|
PopulateRefKind(trapFile, Symbol.RefKind);
|
|
|
|
var type = Type;
|
|
trapFile.properties(this, Symbol.GetName(), ContainingType!, type.TypeRef, Create(Context, Symbol.OriginalDefinition));
|
|
|
|
var getter = BodyDeclaringSymbol.GetMethod;
|
|
var setter = BodyDeclaringSymbol.SetMethod;
|
|
|
|
if (getter is not null)
|
|
Method.Create(Context, getter);
|
|
|
|
if (setter is not null)
|
|
Method.Create(Context, setter);
|
|
|
|
var declSyntaxReferences = IsSourceDeclaration ?
|
|
Symbol.DeclaringSyntaxReferences.
|
|
Select(d => d.GetSyntax()).OfType<PropertyDeclarationSyntax>().ToArray()
|
|
: Enumerable.Empty<PropertyDeclarationSyntax>();
|
|
|
|
foreach (var explicitInterface in Symbol.ExplicitInterfaceImplementations.Select(impl => Type.Create(Context, impl.ContainingType)))
|
|
{
|
|
trapFile.explicitly_implements(this, explicitInterface.TypeRef);
|
|
|
|
foreach (var syntax in declSyntaxReferences)
|
|
TypeMention.Create(Context, syntax.ExplicitInterfaceSpecifier!.Name, this, explicitInterface);
|
|
}
|
|
|
|
if (Context.OnlyScaffold)
|
|
{
|
|
return;
|
|
}
|
|
|
|
BindComments();
|
|
|
|
if (Context.ExtractLocation(Symbol))
|
|
{
|
|
WriteLocationsToTrap(trapFile.property_location, this, Locations);
|
|
}
|
|
|
|
if (IsSourceDeclaration && Symbol.FromSource())
|
|
{
|
|
var expressionBody = ExpressionBody;
|
|
if (expressionBody is not null)
|
|
{
|
|
Context.PopulateLater(() => Expression.Create(Context, expressionBody, this, 0));
|
|
}
|
|
|
|
var child = 1;
|
|
foreach (var initializer in declSyntaxReferences
|
|
.Select(n => n.Initializer)
|
|
.Where(i => i is not null))
|
|
{
|
|
Context.PopulateLater(() =>
|
|
{
|
|
var loc = Context.CreateLocation(initializer!.GetLocation());
|
|
var annotatedType = AnnotatedTypeSymbol.CreateNotAnnotated(Symbol.Type);
|
|
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, isCompilerGenerated: true, null));
|
|
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0));
|
|
var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, isCompilerGenerated: true, null));
|
|
trapFile.expr_access(access, this);
|
|
if (!Symbol.IsStatic)
|
|
{
|
|
This.CreateImplicit(Context, Symbol.ContainingType, Location, access, -1);
|
|
}
|
|
});
|
|
}
|
|
|
|
foreach (var syntax in declSyntaxReferences)
|
|
TypeMention.Create(Context, syntax.Type, this, type);
|
|
}
|
|
}
|
|
|
|
public override Microsoft.CodeAnalysis.Location FullLocation
|
|
{
|
|
get
|
|
{
|
|
return Symbol.DeclaringSyntaxReferences
|
|
.Select(r => r.GetSyntax())
|
|
.OfType<PropertyDeclarationSyntax>()
|
|
.Select(s => s.GetLocation())
|
|
.Concat(Symbol.Locations)
|
|
.Best();
|
|
}
|
|
}
|
|
|
|
bool IExpressionParentEntity.IsTopLevelParent => true;
|
|
|
|
public static Property Create(Context cx, IPropertySymbol prop)
|
|
{
|
|
var isIndexer = prop.IsIndexer || prop.Parameters.Any();
|
|
|
|
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
|
}
|
|
|
|
private class PropertyFactory : CachedEntityFactory<IPropertySymbol, Property>
|
|
{
|
|
public static PropertyFactory Instance { get; } = new PropertyFactory();
|
|
|
|
public override Property Create(Context cx, IPropertySymbol init) => new Property(cx, init);
|
|
}
|
|
|
|
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.PushesLabel;
|
|
}
|
|
}
|