Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6c9ebab

Browse files
committed
C#: Populate expression type nullability and nullable flow state.
1 parent 0327b83 commit 6c9ebab

12 files changed

Lines changed: 242 additions & 30 deletions

File tree

csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ protected override void ExtractInitializers(TextWriter trapFile)
5858
}
5959

6060
var initInfo = new ExpressionInfo(Context,
61-
new AnnotatedType(initializerType, Kinds.TypeAnnotation.NotAnnotated),
61+
new AnnotatedType(initializerType, NullableAnnotation.None),
6262
Context.Create(initializer.ThisOrBaseKeyword.GetLocation()),
6363
Kinds.ExprKind.CONSTRUCTOR_INIT,
6464
this,

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ protected sealed override void Populate(TextWriter trapFile)
4646
trapFile.expr_parent(this, Info.Child, Info.Parent);
4747
trapFile.expr_location(this, Location);
4848

49+
var annotatedType = Type.Symbol;
50+
if (!annotatedType.HasObliviousNullability())
51+
{
52+
var n = NullabilityEntity.Create(cx, Nullability.Create(annotatedType));
53+
trapFile.type_nullability(this, n);
54+
}
55+
56+
if(Info.FlowState != NullableFlowState.None)
57+
{
58+
trapFile.expr_flowstate(this, (int)Info.FlowState);
59+
}
60+
4961
if (Info.IsCompilerGenerated)
5062
trapFile.expr_compiler_generated(this);
5163

@@ -344,6 +356,8 @@ interface IExpressionInfo
344356
/// is null.
345357
/// </summary>
346358
string ExprValue { get; }
359+
360+
NullableFlowState FlowState { get; }
347361
}
348362

349363
/// <summary>
@@ -371,6 +385,9 @@ public ExpressionInfo(Context cx, AnnotatedType type, Extraction.Entities.Locati
371385
ExprValue = value;
372386
IsCompilerGenerated = isCompilerGenerated;
373387
}
388+
389+
// Synthetic expressions don't have a flow state.
390+
public NullableFlowState FlowState => NullableFlowState.None;
374391
}
375392

376393
/// <summary>
@@ -533,5 +550,7 @@ public SymbolInfo SymbolInfo
533550
return cachedSymbolInfo;
534551
}
535552
}
553+
554+
public NullableFlowState FlowState => TypeInfo.Nullability.FlowState;
536555
}
537556
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ArrayCreation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ protected override void PopulateExpression(TextWriter trapFile)
4343

4444
var info = new ExpressionInfo(
4545
cx,
46-
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), Kinds.TypeAnnotation.NotAnnotated),
46+
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
4747
Location,
4848
ExprKind.INT_LITERAL,
4949
this,

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/This.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Semmle.Extraction.Entities;
1+
using Microsoft.CodeAnalysis;
22
using Semmle.Extraction.Kinds;
33

44
namespace Semmle.Extraction.CSharp.Entities.Expressions
@@ -7,8 +7,8 @@ class This : Expression
77
{
88
This(IExpressionInfo info) : base(info) { }
99

10-
public static This CreateImplicit(Context cx, Type @class, Location loc, IExpressionParentEntity parent, int child) =>
11-
new This(new ExpressionInfo(cx, new AnnotatedType(@class, Kinds.TypeAnnotation.NotAnnotated), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null));
10+
public static This CreateImplicit(Context cx, Type @class, Extraction.Entities.Location loc, IExpressionParentEntity parent, int child) =>
11+
new This(new ExpressionInfo(cx, new AnnotatedType(@class, NullableAnnotation.None), loc, Kinds.ExprKind.THIS_ACCESS, parent, child, true, null));
1212

1313
public static This CreateExplicit(ExpressionNodeInfo info) => new This(info.SetKind(ExprKind.THIS_ACCESS));
1414
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public override void Populate(TextWriter trapFile)
7575
Context.PopulateLater(() =>
7676
{
7777
var loc = Context.Create(initializer.GetLocation());
78-
var annotatedType = new AnnotatedType(type, TypeAnnotation.None);
78+
var annotatedType = new AnnotatedType(type, NullableAnnotation.None);
7979
var simpleAssignExpr = new Expression(new ExpressionInfo(Context, annotatedType, loc, ExprKind.SIMPLE_ASSIGN, this, child++, false, null));
8080
Expression.CreateFromNode(new ExpressionNodeInfo(Context, initializer.Value, simpleAssignExpr, 0));
8181
var access = new Expression(new ExpressionInfo(Context, annotatedType, Location, ExprKind.PROPERTY_ACCESS, simpleAssignExpr, 1, false, null));

csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NullType.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public override bool Equals(object obj)
2727
return obj != null && obj.GetType() == typeof(NullType);
2828
}
2929

30-
public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateEntity(cx, null), Kinds.TypeAnnotation.None);
30+
public static AnnotatedType Create(Context cx) => new AnnotatedType(NullTypeFactory.Instance.CreateEntity(cx, null), NullableAnnotation.None);
3131

3232
class NullTypeFactory : ICachedEntityFactory<ITypeSymbol, NullType>
3333
{

csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CSharp.Syntax;
3-
using Semmle.Extraction.CSharp.Populators;
43
using Semmle.Util;
5-
using System;
64
using System.Collections.Generic;
75
using System.IO;
86
using System.Linq;
@@ -14,14 +12,23 @@ namespace Semmle.Extraction.CSharp.Entities
1412
/// </summary>
1513
public struct AnnotatedType
1614
{
17-
public AnnotatedType(Type t, Kinds.TypeAnnotation a)
15+
public AnnotatedType(Type t, NullableAnnotation n)
1816
{
1917
Type = t;
20-
Annotation = a;
18+
annotation = n;
2119
}
2220

21+
/// <summary>
22+
/// The underlying type.
23+
/// </summary>
2324
public Type Type;
24-
public Kinds.TypeAnnotation Annotation;
25+
26+
private NullableAnnotation annotation;
27+
28+
/// <summary>
29+
/// Gets the annotated type symbol of this annotated type.
30+
/// </summary>
31+
public AnnotatedTypeSymbol Symbol => new AnnotatedTypeSymbol(Type.symbol, annotation);
2532
}
2633

2734
public abstract class Type : CachedSymbol<ITypeSymbol>
@@ -274,7 +281,7 @@ public static Type Create(Context cx, ITypeSymbol type)
274281
}
275282

276283
public static AnnotatedType Create(Context cx, AnnotatedTypeSymbol type) =>
277-
new AnnotatedType(Create(cx, type.Symbol), type.Nullability.GetTypeAnnotation());
284+
new AnnotatedType(Create(cx, type.Symbol), type.Nullability);
278285

279286
public virtual int Dimension => 0;
280287

csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -201,16 +201,6 @@ internal static void explicitly_sized_array_creation(this TextWriter trapFile, E
201201
trapFile.WriteTuple("explicitly_sized_array_creation", array);
202202
}
203203

204-
internal static void expr_compiler_generated(this TextWriter trapFile, Expression expr)
205-
{
206-
trapFile.WriteTuple("expr_compiler_generated", expr);
207-
}
208-
209-
internal static void expr_location(this TextWriter trapFile, Expression exprKey, Location location)
210-
{
211-
trapFile.WriteTuple("expr_location", exprKey, location);
212-
}
213-
214204
internal static void expr_access(this TextWriter trapFile, Expression expr, IEntity access)
215205
{
216206
trapFile.WriteTuple("expr_access", expr, access);
@@ -231,19 +221,34 @@ internal static void expr_call(this TextWriter trapFile, Expression expr, Method
231221
trapFile.WriteTuple("expr_call", expr, target);
232222
}
233223

234-
internal static void expr_parent(this TextWriter trapFile, Expression exprKey, int child, IExpressionParentEntity parent)
224+
internal static void expr_compiler_generated(this TextWriter trapFile, Expression expr)
225+
{
226+
trapFile.WriteTuple("expr_compiler_generated", expr);
227+
}
228+
229+
internal static void expr_flowstate(this TextWriter trapFile, Expression expr, int flowState)
230+
{
231+
trapFile.WriteTuple("expr_flowstate", expr, flowState);
232+
}
233+
234+
internal static void expr_location(this TextWriter trapFile, Expression expr, Location location)
235+
{
236+
trapFile.WriteTuple("expr_location", expr, location);
237+
}
238+
239+
internal static void expr_parent(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent)
235240
{
236-
trapFile.WriteTuple("expr_parent", exprKey, child, parent);
241+
trapFile.WriteTuple("expr_parent", expr, child, parent);
237242
}
238243

239-
internal static void expr_parent_top_level(this TextWriter trapFile, Expression exprKey, int child, IExpressionParentEntity parent)
244+
internal static void expr_parent_top_level(this TextWriter trapFile, Expression expr, int child, IExpressionParentEntity parent)
240245
{
241-
trapFile.WriteTuple("expr_parent_top_level", exprKey, child, parent);
246+
trapFile.WriteTuple("expr_parent_top_level", expr, child, parent);
242247
}
243248

244-
internal static void expr_value(this TextWriter trapFile, Expression exprKey, string value)
249+
internal static void expr_value(this TextWriter trapFile, Expression expr, string value)
245250
{
246-
trapFile.WriteTuple("expr_value", exprKey, value);
251+
trapFile.WriteTuple("expr_value", expr, value);
247252
}
248253

249254
internal static void expressions(this TextWriter trapFile, Expression expr, ExprKind kind, Type exprType)

csharp/ql/src/semmle/code/csharp/exprs/Expr.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr {
8787
string getExplicitArgumentName() { expr_argument_name(this, result) }
8888

8989
override Element getParent() { result = ControlFlowElement.super.getParent() }
90+
91+
/** Holds if the nullable flow state of this expression is not null. */
92+
predicate hasNotNullFlowState() { expr_flowstate(this, 1) }
93+
94+
/** Holds if the nullable flow state of this expression may be null. */
95+
predicate hasMaybeNullFlowState() { expr_flowstate(this, 2) }
9096
}
9197

9298
/**

csharp/ql/src/semmlecode.csharp.dbscheme

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,15 @@ case @nullability.kind of
483483
#keyset[parent, index]
484484
nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
485485

486-
type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref)
486+
type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
487+
488+
/**
489+
* Thw nullable flow state of an expression, as determined by Roslyn.
490+
* 0 = none (default, not populated)
491+
* 1 = not null
492+
* 2 = maybe null
493+
*/
494+
expr_flowstate(unique int id: @expr ref, int state: int ref);
487495

488496
/** GENERICS **/
489497

0 commit comments

Comments
 (0)