Files
codeql/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalVariable.cs
2019-08-30 10:11:00 +01:00

110 lines
3.5 KiB
C#

using System;
using System.IO;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Entities;
namespace Semmle.Extraction.CSharp.Entities
{
class LocalVariable : CachedSymbol<ISymbol>
{
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 void WriteId(TextWriter tw)
{
tw.WriteSubId(Parent);
tw.Write('_');
tw.Write(symbol.Name);
tw.Write(";localvar");
}
public override void Populate(TextWriter trapFile)
{
if (symbol is ILocalSymbol local)
{
ExtractNullability(trapFile, local.NullableAnnotation);
if (local.IsRef)
trapFile.Emit(Tuples.type_annotation(this, Kinds.TypeAnnotation.Ref));
}
trapFile.Emit(Tuples.localvars(
this,
IsRef ? 3 : IsConst ? 2 : 1,
symbol.Name,
IsVar ? 1 : 0,
Type.Type.TypeRef,
Parent));
trapFile.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);
}
/// <summary>
/// Gets the local variable entity for <paramref name="local"/> which must
/// already have been created.
/// </summary>
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;
}
}
AnnotatedType Type
{
get
{
var local = symbol as ILocalSymbol;
return local == null ? Parent.Type : Entities.Type.Create(Context, local.GetAnnotatedType());
}
}
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;
}
}