using System.IO; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.Kinds; namespace Semmle.Extraction.CSharp.Entities.Expressions { internal abstract class BaseObjectCreation : Expression where TExpressionSyntax : BaseObjectCreationExpressionSyntax { protected BaseObjectCreation(ExpressionNodeInfo info) : base(info.SetKind(GetKind(info.Context, (BaseObjectCreationExpressionSyntax)info.Node))) { } protected override void PopulateExpression(TextWriter trapFile) { if (Syntax.ArgumentList is not null) { PopulateArguments(trapFile, Syntax.ArgumentList, 0); } var target = Context.GetModel(Syntax).GetSymbolInfo(Syntax); if (target.Symbol is IMethodSymbol method) { trapFile.expr_call(this, Method.Create(Context, method)); } if (IsDynamicObjectCreation(Context, Syntax)) { if (Context.GetModel(Syntax).GetTypeInfo(Syntax).Type is INamedTypeSymbol type && !string.IsNullOrEmpty(type.Name)) { trapFile.dynamic_member_name(this, type.Name); } else { Context.ModelError(Syntax, "Unable to get name for dynamic object creation."); } } if (Syntax.Initializer is not null) { var kind = Syntax.Initializer.Kind(); switch (kind) { case SyntaxKind.CollectionInitializerExpression: CollectionInitializer.Create(new ExpressionNodeInfo(Context, Syntax.Initializer, this, -1).SetType(Type)); break; case SyntaxKind.ObjectInitializerExpression: ObjectInitializer.Create(new ExpressionNodeInfo(Context, Syntax.Initializer, this, -1).SetType(Type)); break; default: Context.ModelError(Syntax.Initializer, $"Unhandled initializer in object creation of kind {kind}"); break; } } } private static ExprKind GetKind(Context cx, BaseObjectCreationExpressionSyntax node) { var type = cx.GetModel(node).GetTypeInfo(node).Type; return Entities.Type.IsDelegate(type as INamedTypeSymbol) ? ExprKind.EXPLICIT_DELEGATE_CREATION : ExprKind.OBJECT_CREATION; } private static bool IsDynamicObjectCreation(Context cx, BaseObjectCreationExpressionSyntax node) { return node.ArgumentList is not null && node.ArgumentList.Arguments.Any(arg => IsDynamic(cx, arg.Expression)); } } }