C#: Populate expression type nullability and nullable flow state.

This commit is contained in:
Calum Grant
2019-11-26 14:23:50 +00:00
committed by Calum Grant
parent 0327b83958
commit 6c9ebaba0b
12 changed files with 242 additions and 30 deletions

View File

@@ -58,7 +58,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
var initInfo = new ExpressionInfo(Context,
new AnnotatedType(initializerType, Kinds.TypeAnnotation.NotAnnotated),
new AnnotatedType(initializerType, NullableAnnotation.None),
Context.Create(initializer.ThisOrBaseKeyword.GetLocation()),
Kinds.ExprKind.CONSTRUCTOR_INIT,
this,

View File

@@ -46,6 +46,18 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.expr_parent(this, Info.Child, Info.Parent);
trapFile.expr_location(this, Location);
var annotatedType = Type.Symbol;
if (!annotatedType.HasObliviousNullability())
{
var n = NullabilityEntity.Create(cx, Nullability.Create(annotatedType));
trapFile.type_nullability(this, n);
}
if(Info.FlowState != NullableFlowState.None)
{
trapFile.expr_flowstate(this, (int)Info.FlowState);
}
if (Info.IsCompilerGenerated)
trapFile.expr_compiler_generated(this);
@@ -344,6 +356,8 @@ namespace Semmle.Extraction.CSharp.Entities
/// is null.
/// </summary>
string ExprValue { get; }
NullableFlowState FlowState { get; }
}
/// <summary>
@@ -371,6 +385,9 @@ namespace Semmle.Extraction.CSharp.Entities
ExprValue = value;
IsCompilerGenerated = isCompilerGenerated;
}
// Synthetic expressions don't have a flow state.
public NullableFlowState FlowState => NullableFlowState.None;
}
/// <summary>
@@ -533,5 +550,7 @@ namespace Semmle.Extraction.CSharp.Entities
return cachedSymbolInfo;
}
}
public NullableFlowState FlowState => TypeInfo.Nullability.FlowState;
}
}

View File

@@ -43,7 +43,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), Kinds.TypeAnnotation.NotAnnotated),
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
Location,
ExprKind.INT_LITERAL,
this,

View File

@@ -1,4 +1,4 @@
using Semmle.Extraction.Entities;
using Microsoft.CodeAnalysis;
using Semmle.Extraction.Kinds;
namespace Semmle.Extraction.CSharp.Entities.Expressions
@@ -7,8 +7,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
This(IExpressionInfo info) : base(info) { }
public static This CreateImplicit(Context cx, Type @class, Location loc, IExpressionParentEntity parent, int child) =>
new This(new ExpressionInfo(cx, new AnnotatedType(@class, Kinds.TypeAnnotation.NotAnnotated), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null));
public static This CreateImplicit(Context cx, Type @class, Extraction.Entities.Location loc, IExpressionParentEntity parent, int child) =>
new This(new ExpressionInfo(cx, new AnnotatedType(@class, NullableAnnotation.None), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null));
public static This CreateExplicit(ExpressionNodeInfo info) => new This(info.SetKind(ExprKind.THIS_ACCESS));
}

View File

@@ -75,7 +75,7 @@ namespace Semmle.Extraction.CSharp.Entities
Context.PopulateLater(() =>
{
var loc = Context.Create(initializer.GetLocation());
var annotatedType = new AnnotatedType(type, TypeAnnotation.None);
var annotatedType = new AnnotatedType(type, NullableAnnotation.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));

View File

@@ -27,7 +27,7 @@ namespace Semmle.Extraction.CSharp.Entities
return obj != null && obj.GetType() == typeof(NullType);
}
public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateEntity(cx, null), Kinds.TypeAnnotation.None);
public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateEntity(cx, null), NullableAnnotation.None);
class NullTypeFactory : ICachedEntityFactory<ITypeSymbol, NullType>
{

View File

@@ -1,8 +1,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -14,14 +12,23 @@ namespace Semmle.Extraction.CSharp.Entities
/// </summary>
public struct AnnotatedType
{
public AnnotatedType(Type t, Kinds.TypeAnnotation a)
public AnnotatedType(Type t, NullableAnnotation n)
{
Type = t;
Annotation = a;
annotation = n;
}
/// <summary>
/// The underlying type.
/// </summary>
public Type Type;
public Kinds.TypeAnnotation Annotation;
private NullableAnnotation annotation;
/// <summary>
/// Gets the annotated type symbol of this annotated type.
/// </summary>
public AnnotatedTypeSymbol Symbol => new AnnotatedTypeSymbol(Type.symbol, annotation);
}
public abstract class Type : CachedSymbol<ITypeSymbol>
@@ -274,7 +281,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
public static AnnotatedType Create(Context cx, AnnotatedTypeSymbol type) =>
new AnnotatedType(Create(cx, type.Symbol), type.Nullability.GetTypeAnnotation());
new AnnotatedType(Create(cx, type.Symbol), type.Nullability);
public virtual int Dimension => 0;

View File

@@ -201,16 +201,6 @@ namespace Semmle.Extraction.CSharp
trapFile.WriteTuple("explicitly_sized_array_creation", array);
}
internal static void expr_compiler_generated(this TextWriter trapFile, Expression expr)
{
trapFile.WriteTuple("expr_compiler_generated", expr);
}
internal static void expr_location(this TextWriter trapFile, Expression exprKey, Location location)
{
trapFile.WriteTuple("expr_location", exprKey, location);
}
internal static void expr_access(this TextWriter trapFile, Expression expr, IEntity access)
{
trapFile.WriteTuple("expr_access", expr, access);
@@ -231,19 +221,34 @@ namespace Semmle.Extraction.CSharp
trapFile.WriteTuple("expr_call", expr, target);
}
internal static void expr_parent(this TextWriter trapFile, Expression exprKey, int child, IExpressionParentEntity parent)
internal static void expr_compiler_generated(this TextWriter trapFile, Expression expr)
{
trapFile.WriteTuple("expr_parent", exprKey, child, parent);
trapFile.WriteTuple("expr_compiler_generated", expr);
}
internal static void expr_parent_top_level(this TextWriter trapFile, Expression exprKey, int child, IExpressionParentEntity parent)
internal static void expr_flowstate(this TextWriter trapFile, Expression expr, int flowState)
{
trapFile.WriteTuple("expr_parent_top_level", exprKey, child, parent);
trapFile.WriteTuple("expr_flowstate", expr, flowState);
}
internal static void expr_value(this TextWriter trapFile, Expression exprKey, string value)
internal static void expr_location(this TextWriter trapFile, Expression expr, Location location)
{
trapFile.WriteTuple("expr_value", exprKey, value);
trapFile.WriteTuple("expr_location", expr, location);
}
internal static void expr_parent(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent)
{
trapFile.WriteTuple("expr_parent", expr, child, parent);
}
internal static void expr_parent_top_level(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent)
{
trapFile.WriteTuple("expr_parent_top_level", expr, child, parent);
}
internal static void expr_value(this TextWriter trapFile, Expression expr, string value)
{
trapFile.WriteTuple("expr_value", expr, value);
}
internal static void expressions(this TextWriter trapFile, Expression expr, ExprKind kind, Type exprType)