using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.CSharp.Entities.Expressions; using Semmle.Extraction.Entities; using Semmle.Extraction.Kinds; using System.IO; using System.Linq; namespace Semmle.Extraction.CSharp.Entities { class Property : CachedSymbol, IExpressionParentEntity { protected Property(Context cx, IPropertySymbol init) : base(cx, init) { } public override void WriteId(TextWriter trapFile) { trapFile.WriteSubId(ContainingType); trapFile.Write('.'); Method.AddExplicitInterfaceQualifierToId(Context, trapFile, symbol.ExplicitInterfaceImplementations); trapFile.Write(symbol.Name); trapFile.Write(";property"); } public override void Populate(TextWriter trapFile) { PopulateMetadataHandle(trapFile); PopulateAttributes(); PopulateModifiers(trapFile); BindComments(); PopulateNullability(trapFile, symbol.GetAnnotatedType()); PopulateRefKind(trapFile, symbol.RefKind); var type = Type.Create(Context, symbol.Type); trapFile.properties(this, symbol.GetName(), ContainingType, type.TypeRef, Create(Context, symbol.OriginalDefinition)); var getter = symbol.GetMethod; var setter = symbol.SetMethod; if (!(getter is null)) Method.Create(Context, getter); if (!(setter is null)) Method.Create(Context, setter); var declSyntaxReferences = IsSourceDeclaration ? symbol.DeclaringSyntaxReferences. Select(d => d.GetSyntax()).OfType().ToArray() : Enumerable.Empty(); 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); } foreach (var l in Locations) trapFile.property_location(this, l); if (IsSourceDeclaration && symbol.FromSource()) { var expressionBody = ExpressionBody; if (expressionBody != null) { Context.PopulateLater(() => Expression.Create(Context, expressionBody, this, 0)); } int child = 1; foreach (var initializer in declSyntaxReferences. Select(n => n.Initializer). Where(i => i != null)) { Context.PopulateLater(() => { var loc = Context.Create(initializer.GetLocation()); var annotatedType = new AnnotatedType(type, TypeAnnotation.None); var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null)); Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0)); var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, false, null)); trapFile.expr_access(access, this); if (!symbol.IsStatic) { This.CreateImplicit(Context, Type.Create(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(). Select(s => s.GetLocation()). Concat(symbol.Locations). First(); } } bool IExpressionParentEntity.IsTopLevelParent => true; public static Property Create(Context cx, IPropertySymbol prop) { bool isIndexer = prop.IsIndexer || prop.Parameters.Any(); return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop); } public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p) { } class PropertyFactory : ICachedEntityFactory { public static readonly PropertyFactory Instance = new PropertyFactory(); public Property Create(Context cx, IPropertySymbol init) => new Property(cx, init); } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.PushesLabel; } }