using System; using Microsoft.CodeAnalysis; using Semmle.Extraction.Entities; namespace Semmle.Extraction.CSharp.Entities { class LocalVariable : CachedSymbol { LocalVariable(Context cx, ISymbol init, Expression parent, bool isVar, Extraction.Entities.Location declLocation) : base(cx, init) { Parent = parent; IsVar = isVar; DeclLocation = declLocation; } readonly Expression Parent; readonly bool IsVar; readonly Extraction.Entities.Location DeclLocation; public override IId Id => new Key(Parent, "_", symbol.Name, ";localvar"); public override void Populate() { Context.Emit(Tuples.localvars( this, IsRef ? 3 : IsConst ? 2 : 1, symbol.Name, IsVar ? 1 : 0, Type.TypeRef, Parent)); Context.Emit(Tuples.localvar_location(this, DeclLocation)); DefineConstantValue(); } public static LocalVariable Create(Context cx, ISymbol local, Expression parent, bool isVar, Extraction.Entities.Location declLocation) { return LocalVariableFactory.Instance.CreateEntity(cx, local, parent, isVar, declLocation); } /// /// Gets the local variable entity for which must /// already have been created. /// public static LocalVariable GetAlreadyCreated(Context cx, ISymbol local) => LocalVariableFactory.Instance.CreateEntity(cx, local, null, false, null); bool IsConst { get { var local = symbol as ILocalSymbol; return local != null && local.IsConst; } } bool IsRef { get { var local = symbol as ILocalSymbol; return local != null && local.IsRef; } } Type Type { get { var local = symbol as ILocalSymbol; return local == null ? Parent.Type : Type.Create(Context, local.Type); } } void DefineConstantValue() { var local = symbol as ILocalSymbol; if (local != null && local.HasConstantValue) { Context.Emit(Tuples.constant_value(this, Expression.ValueAsString(local.ConstantValue))); } } class LocalVariableFactory : ICachedEntityFactory<(ISymbol, Expression, bool, Extraction.Entities.Location), LocalVariable> { public static readonly LocalVariableFactory Instance = new LocalVariableFactory(); public LocalVariable Create(Context cx, (ISymbol, Expression, bool, Extraction.Entities.Location) init) => new LocalVariable(cx, init.Item1, init.Item2, init.Item3, init.Item4); } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NeedsLabel; } }