using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using System.IO; using System.Linq; namespace Semmle.Extraction.CSharp.Entities { class LocalFunction : Method { LocalFunction(Context cx, IMethodSymbol init) : base(cx, init) { } public override void WriteId(TextWriter trapFile) { trapFile.WriteSubId(ContainingType); trapFile.Write("."); trapFile.WriteSubId(Location); if (symbol.IsGenericMethod && !IsSourceDeclaration) { trapFile.Write('<'); trapFile.BuildList(",", symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(Context, tb0, symbol, ta)); trapFile.Write('>'); } trapFile.Write(";localfunction"); } public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field); class LocalFunctionFactory : ICachedEntityFactory { public static readonly LocalFunctionFactory Instance = new LocalFunctionFactory(); public LocalFunction Create(Context cx, IMethodSymbol init) => new LocalFunction(cx, init); } public override void Populate(TextWriter trapFile) { PopulateMethod(trapFile); // There is a "bug" in Roslyn whereby the IMethodSymbol associated with the local function symbol // is always static, so we need to go to the syntax reference of the local function to see whether // the "static" modifier is present. if (symbol.DeclaringSyntaxReferences.SingleOrDefault().GetSyntax() is LocalFunctionStatementSyntax fn) { foreach (var modifier in fn.Modifiers) { Modifier.HasModifier(Context, trapFile, this, modifier.Text); } } var originalDefinition = IsSourceDeclaration ? this : Create(Context, symbol.OriginalDefinition); var returnType = Type.Create(Context, symbol.ReturnType); trapFile.local_functions(this, symbol.Name, returnType, originalDefinition); ExtractRefReturn(trapFile); } } }