Skip to content

Commit 25095f9

Browse files
authored
Merge pull request #4962 from hvitved/csharp/nullability-extraction
C#: Improved extraction of type nullability
2 parents b620e02 + 9a9a577 commit 25095f9

38 files changed

+147
-176
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,24 @@ protected override void ExtractInitializers(TextWriter trapFile)
4242
if (initializer == null)
4343
return;
4444

45-
Type initializerType;
45+
ITypeSymbol initializerType;
4646
var symbolInfo = Context.GetSymbolInfo(initializer);
4747

4848
switch (initializer.Kind())
4949
{
5050
case SyntaxKind.BaseConstructorInitializer:
51-
initializerType = Type.Create(Context, symbol.ContainingType.BaseType);
51+
initializerType = symbol.ContainingType.BaseType;
5252
break;
5353
case SyntaxKind.ThisConstructorInitializer:
54-
initializerType = ContainingType;
54+
initializerType = symbol.ContainingType;
5555
break;
5656
default:
5757
Context.ModelError(initializer, "Unknown initializer");
5858
return;
5959
}
6060

6161
var initInfo = new ExpressionInfo(Context,
62-
new AnnotatedType(initializerType, NullableAnnotation.None),
62+
AnnotatedTypeSymbol.CreateNotAnnotated(initializerType),
6363
Context.Create(initializer.ThisOrBaseKeyword.GetLocation()),
6464
Kinds.ExprKind.CONSTRUCTOR_INIT,
6565
this,

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

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public interface IExpressionParentEntity : IEntity
2222
internal class Expression : FreshEntity, IExpressionParentEntity
2323
{
2424
private readonly IExpressionInfo info;
25-
public AnnotatedType Type { get; }
25+
public AnnotatedTypeSymbol? Type { get; }
2626
public Extraction.Entities.Location Location { get; }
2727
public ExprKind Kind { get; }
2828

@@ -33,25 +33,23 @@ internal Expression(IExpressionInfo info)
3333
Location = info.Location;
3434
Kind = info.Kind;
3535
Type = info.Type;
36-
if (Type.Type is null)
37-
Type = NullType.Create(cx);
3836

3937
TryPopulate();
4038
}
4139

4240
protected sealed override void Populate(TextWriter trapFile)
4341
{
44-
trapFile.expressions(this, Kind, Type.Type.TypeRef);
42+
var type = Type.HasValue ? Entities.Type.Create(cx, Type.Value) : NullType.Create(cx);
43+
trapFile.expressions(this, Kind, type.TypeRef);
4544
if (info.Parent.IsTopLevelParent)
4645
trapFile.expr_parent_top_level(this, info.Child, info.Parent);
4746
else
4847
trapFile.expr_parent(this, info.Child, info.Parent);
4948
trapFile.expr_location(this, Location);
5049

51-
var annotatedType = Type.Symbol;
52-
if (!annotatedType.HasObliviousNullability())
50+
if (Type.HasValue && !Type.Value.HasObliviousNullability())
5351
{
54-
var n = NullabilityEntity.Create(cx, Nullability.Create(annotatedType));
52+
var n = NullabilityEntity.Create(cx, Nullability.Create(Type.Value));
5553
trapFile.type_nullability(this, n);
5654
}
5755

@@ -66,7 +64,7 @@ protected sealed override void Populate(TextWriter trapFile)
6664
if (info.ExprValue is string value)
6765
trapFile.expr_value(this, value);
6866

69-
Type.Type.PopulateGenerics();
67+
type.PopulateGenerics();
7068
}
7169

7270
public override Microsoft.CodeAnalysis.Location ReportingLocation => Location.symbol;
@@ -367,7 +365,7 @@ internal interface IExpressionInfo
367365
/// <summary>
368366
/// The type of the expression.
369367
/// </summary>
370-
AnnotatedType Type { get; }
368+
AnnotatedTypeSymbol? Type { get; }
371369

372370
/// <summary>
373371
/// The location of the expression.
@@ -411,15 +409,15 @@ internal interface IExpressionInfo
411409
internal class ExpressionInfo : IExpressionInfo
412410
{
413411
public Context Context { get; }
414-
public AnnotatedType Type { get; }
412+
public AnnotatedTypeSymbol? Type { get; }
415413
public Extraction.Entities.Location Location { get; }
416414
public ExprKind Kind { get; }
417415
public IExpressionParentEntity Parent { get; }
418416
public int Child { get; }
419417
public bool IsCompilerGenerated { get; }
420418
public string ExprValue { get; }
421419

422-
public ExpressionInfo(Context cx, AnnotatedType type, Extraction.Entities.Location location, ExprKind kind,
420+
public ExpressionInfo(Context cx, AnnotatedTypeSymbol? type, Extraction.Entities.Location location, ExprKind kind,
423421
IExpressionParentEntity parent, int child, bool isCompilerGenerated, string value)
424422
{
425423
Context = cx;
@@ -466,10 +464,15 @@ public ExpressionNodeInfo(Context cx, ExpressionSyntax node, IExpressionParentEn
466464
public AnnotatedTypeSymbol ResolvedType => new AnnotatedTypeSymbol(TypeInfo.Type.DisambiguateType(), TypeInfo.Nullability.Annotation);
467465
public AnnotatedTypeSymbol ConvertedType => new AnnotatedTypeSymbol(TypeInfo.ConvertedType.DisambiguateType(), TypeInfo.ConvertedNullability.Annotation);
468466

469-
public AnnotatedTypeSymbol ExpressionType
467+
private AnnotatedTypeSymbol? cachedType;
468+
private bool cachedTypeSet;
469+
public AnnotatedTypeSymbol? Type
470470
{
471471
get
472472
{
473+
if (cachedTypeSet)
474+
return cachedType;
475+
473476
var type = ResolvedType;
474477

475478
if (type.Symbol == null)
@@ -491,6 +494,9 @@ public AnnotatedTypeSymbol ExpressionType
491494
Context.ModelError(Node, "Failed to determine type");
492495
}
493496

497+
cachedType = type;
498+
cachedTypeSet = true;
499+
494500
return type;
495501
}
496502
}
@@ -522,22 +528,6 @@ public string ExprValue
522528
}
523529
}
524530

525-
private AnnotatedType cachedType;
526-
527-
public AnnotatedType Type
528-
{
529-
get
530-
{
531-
if (cachedType.Type == null)
532-
cachedType = Entities.Type.Create(Context, ExpressionType);
533-
return cachedType;
534-
}
535-
set
536-
{
537-
cachedType = value;
538-
}
539-
}
540-
541531
private Extraction.Entities.Location cachedLocation;
542532

543533
public Extraction.Entities.Location Location
@@ -572,9 +562,10 @@ public ExpressionNodeInfo SetKind(ExprKind kind)
572562
return this;
573563
}
574564

575-
public ExpressionNodeInfo SetType(AnnotatedType type)
565+
public ExpressionNodeInfo SetType(AnnotatedTypeSymbol? type)
576566
{
577-
Type = type;
567+
cachedType = type;
568+
cachedTypeSet = true;
578569
return this;
579570
}
580571

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private Access(ExpressionNodeInfo info, ISymbol symbol, bool implicitThis, IEnti
5252

5353
if (implicitThis && !symbol.IsStatic)
5454
{
55-
This.CreateImplicit(cx, Entities.Type.Create(cx, symbol.ContainingType), Location, this, -1);
55+
This.CreateImplicit(cx, symbol.ContainingType, Location, this, -1);
5656
}
5757
}
5858

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public static Expression CreateGenerated(Context cx, IExpressionParentEntity par
9090
{
9191
var info = new ExpressionInfo(
9292
cx,
93-
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
93+
AnnotatedTypeSymbol.CreateNotAnnotated(type),
9494
location,
9595
ExprKind.ARRAY_CREATION,
9696
parent,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static Expression CreateGenerated(Context cx, IExpressionParentEntity par
3636
{
3737
var info = new ExpressionInfo(
3838
cx,
39-
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
39+
AnnotatedTypeSymbol.CreateNotAnnotated(type),
4040
location,
4141
ExprKind.CAST,
4242
parent,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public Discard(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.DISCARD))
1212
}
1313

1414
private Discard(Context cx, CSharpSyntaxNode syntax, IExpressionParentEntity parent, int child) :
15-
base(new ExpressionInfo(cx, Entities.Type.Create(cx, cx.GetType(syntax)), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null))
15+
base(new ExpressionInfo(cx, cx.GetType(syntax), cx.Create(syntax.GetLocation()), ExprKind.DISCARD, parent, child, false, null))
1616
{
1717
}
1818

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ public Expression Expr
1212
}
1313

1414
public ImplicitCast(ExpressionNodeInfo info)
15-
: base(new ExpressionInfo(info.Context, Entities.Type.Create(info.Context, info.ConvertedType), info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue))
15+
: base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.CAST, info.Parent, info.Child, true, info.ExprValue))
1616
{
1717
Expr = Factory.Create(new ExpressionNodeInfo(cx, info.Node, this, 0));
1818
}
1919

2020
public ImplicitCast(ExpressionNodeInfo info, IMethodSymbol method)
21-
: base(new ExpressionInfo(info.Context, Entities.Type.Create(info.Context, info.ConvertedType), info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue))
21+
: base(new ExpressionInfo(info.Context, info.ConvertedType, info.Location, ExprKind.OPERATOR_INVOCATION, info.Parent, info.Child, true, info.ExprValue))
2222
{
2323
Expr = Factory.Create(info.SetParent(this, 0));
2424

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ protected Initializer(ExpressionNodeInfo info) : base(info) { }
1414

1515
internal class ArrayInitializer : Expression<InitializerExpressionSyntax>
1616
{
17-
private ArrayInitializer(ExpressionNodeInfo info) : base(info.SetType(NullType.Create(info.Context)).SetKind(ExprKind.ARRAY_INIT)) { }
17+
private ArrayInitializer(ExpressionNodeInfo info) : base(info.SetType(null).SetKind(ExprKind.ARRAY_INIT)) { }
1818

1919
public static Expression Create(ExpressionNodeInfo info) => new ArrayInitializer(info).TryPopulate();
2020

@@ -40,7 +40,7 @@ public static Expression CreateGenerated(Context cx, IExpressionParentEntity par
4040
{
4141
var info = new ExpressionInfo(
4242
cx,
43-
NullType.Create(cx),
43+
null,
4444
location,
4545
ExprKind.ARRAY_INIT,
4646
parent,
@@ -135,7 +135,7 @@ protected override void PopulateExpression(TextWriter trapFile)
135135
{
136136
var collectionInfo = cx.GetModel(Syntax).GetCollectionInitializerSymbolInfo(i);
137137
var addMethod = Method.Create(cx, collectionInfo.Symbol as IMethodSymbol);
138-
var voidType = Entities.Type.Create(cx, new AnnotatedTypeSymbol(cx.Compilation.GetSpecialType(SpecialType.System_Void), NullableAnnotation.None));
138+
var voidType = AnnotatedTypeSymbol.CreateNotAnnotated(cx.Compilation.GetSpecialType(SpecialType.System_Void));
139139

140140
var invocation = new Expression(new ExpressionInfo(cx, voidType, cx.Create(i.GetLocation()), ExprKind.METHOD_INVOCATION, this, child++, false, null));
141141

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ protected override void PopulateExpression(TextWriter trapFile)
5555
// Implicit `this` qualifier; add explicitly
5656

5757
if (cx.GetModel(Syntax).GetEnclosingSymbol(Location.symbol.SourceSpan.Start) is IMethodSymbol callingMethod)
58-
This.CreateImplicit(cx, Entities.Type.Create(cx, callingMethod.ContainingType), Location, this, child++);
58+
This.CreateImplicit(cx, callingMethod.ContainingType, Location, this, child++);
5959
else
6060
cx.ModelError(Syntax, "Couldn't determine implicit this type");
6161
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ private static ExprKind GetKind(ExpressionNodeInfo info)
2121
case SyntaxKind.DefaultLiteralExpression:
2222
return ExprKind.DEFAULT;
2323
case SyntaxKind.NullLiteralExpression:
24-
info.Type = Entities.NullType.Create(info.Context); // Don't use converted type.
24+
info.SetType(null); // Don't use converted type.
2525
return ExprKind.NULL_LITERAL;
2626
}
2727

28-
var type = info.Type.Type.symbol;
28+
var type = info.Type?.Symbol;
2929
return GetExprKind(type, info.Node, info.Context);
3030
}
3131

@@ -82,7 +82,7 @@ public static Expression CreateGenerated(Context cx, IExpressionParentEntity par
8282
{
8383
var info = new ExpressionInfo(
8484
cx,
85-
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
85+
AnnotatedTypeSymbol.CreateNotAnnotated(type),
8686
location,
8787
GetExprKind(type, null, cx),
8888
parent,
@@ -97,7 +97,7 @@ public static Expression CreateGeneratedNullLiteral(Context cx, IExpressionParen
9797
{
9898
var info = new ExpressionInfo(
9999
cx,
100-
NullType.Create(cx),
100+
null,
101101
location,
102102
ExprKind.NULL_LITERAL,
103103
parent,

0 commit comments

Comments
 (0)