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

Skip to content

Commit d6515e7

Browse files
hvitvedtamasvajk
authored andcommitted
C#: Changes to extraction of attributes in assemblies
- Only cache on `AttributeData` and not the parent entity. - Move `CreateGeneratedExpressionFromArgument` to `Expression.cs`. - Restructure the various `CreateGenerated` methods so child entities are created inside them (and therefore no need to expose child index logic). - Add locations to generated expressions. - Avoid linear lookup in `CompilationUnit.cs`. - Consolidate tests.
1 parent b8d6070 commit d6515e7

15 files changed

Lines changed: 181 additions & 200 deletions

File tree

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

Lines changed: 16 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,20 @@
22
using System.Linq;
33
using Microsoft.CodeAnalysis;
44
using Microsoft.CodeAnalysis.CSharp.Syntax;
5-
using Semmle.Extraction.CSharp.Entities.Expressions;
65
using Semmle.Extraction.Entities;
76

87
namespace Semmle.Extraction.CSharp.Entities
98
{
10-
internal class Attribute : CachedEntity<(AttributeData, IEntity)>, IExpressionParentEntity
9+
internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity
1110
{
1211
bool IExpressionParentEntity.IsTopLevelParent => true;
1312

14-
private readonly AttributeData attributeData;
1513
private readonly AttributeSyntax attributeSyntax;
1614
private readonly IEntity entity;
1715

1816
private Attribute(Context cx, AttributeData attributeData, IEntity entity)
19-
: base(cx, (attributeData, entity))
17+
: base(cx, attributeData)
2018
{
21-
this.attributeData = attributeData;
2219
this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax;
2320
this.entity = entity;
2421
}
@@ -27,7 +24,7 @@ public override void WriteId(TextWriter trapFile)
2724
{
2825
if (ReportingLocation?.IsInSource == true)
2926
{
30-
trapFile.WriteSubId(Context.Create(ReportingLocation));
27+
trapFile.WriteSubId(Location);
3128
trapFile.Write(";attribute");
3229
}
3330
else
@@ -50,13 +47,12 @@ public override void WriteQuotedId(TextWriter trapFile)
5047

5148
public override void Populate(TextWriter trapFile)
5249
{
53-
var type = Type.Create(Context, attributeData.AttributeClass);
50+
var type = Type.Create(Context, symbol.AttributeClass);
5451
trapFile.attributes(this, type.TypeRef, entity);
52+
trapFile.attribute_location(this, Location);
5553

5654
if (attributeSyntax is object)
5755
{
58-
trapFile.attribute_location(this, Context.Create(attributeSyntax.Name.GetLocation()));
59-
6056
if (Context.Extractor.OutputPath != null)
6157
{
6258
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context));
@@ -71,18 +67,16 @@ public override void Populate(TextWriter trapFile)
7167
private void ExtractArguments(TextWriter trapFile)
7268
{
7369
var childIndex = 0;
74-
foreach (var constructorArgument in attributeData.ConstructorArguments)
70+
foreach (var constructorArgument in symbol.ConstructorArguments)
7571
{
7672
CreateExpressionFromArgument(
7773
constructorArgument,
7874
attributeSyntax?.ArgumentList.Arguments[childIndex].Expression,
7975
this,
80-
childIndex);
81-
82-
childIndex++;
76+
childIndex++);
8377
}
8478

85-
foreach (var namedArgument in attributeData.NamedArguments)
79+
foreach (var namedArgument in symbol.NamedArguments)
8680
{
8781
var expr = CreateExpressionFromArgument(
8882
namedArgument.Value,
@@ -100,71 +94,19 @@ private void ExtractArguments(TextWriter trapFile)
10094
private Expression CreateExpressionFromArgument(TypedConstant constant, ExpressionSyntax syntax, IExpressionParentEntity parent,
10195
int childIndex)
10296
{
103-
if (syntax is object)
104-
{
105-
return Expression.Create(Context, syntax, parent, childIndex);
106-
}
107-
108-
return CreateGeneratedExpressionFromArgument(constant, parent, childIndex);
109-
}
110-
111-
private Expression CreateGeneratedExpressionFromArgument(TypedConstant constant, IExpressionParentEntity parent,
112-
int childIndex)
113-
{
114-
if (constant.IsNull)
115-
{
116-
return Literal.CreateGeneratedNullLiteral(Context, parent, childIndex);
117-
}
118-
119-
switch (constant.Kind)
120-
{
121-
case TypedConstantKind.Primitive:
122-
return Literal.CreateGenerated(Context, parent, childIndex, constant.Type, constant.Value);
123-
case TypedConstantKind.Enum:
124-
// Enum value is generated in the following format: (Enum)value
125-
126-
var cast = Cast.CreateGenerated(Context, parent, childIndex, constant.Type, constant.Value);
127-
Literal.CreateGenerated(Context, cast, Cast.ExpressionIndex, ((INamedTypeSymbol)constant.Type).EnumUnderlyingType, constant.Value);
128-
TypeAccess.CreateGenerated(Context, cast, Cast.TypeAccessIndex, constant.Type);
129-
130-
return cast;
131-
case TypedConstantKind.Type:
132-
var type = ((ITypeSymbol)constant.Value).OriginalDefinition;
133-
var t = TypeOf.CreateGenerated(Context, parent, childIndex, type);
134-
TypeAccess.CreateGenerated(Context, t, TypeOf.TypeAccessIndex, type);
135-
return t;
136-
case TypedConstantKind.Array:
137-
{
138-
// Single dimensional arrays are in the following format:
139-
// * new Type[N] { item1, item2, ..., itemN }
140-
// * new Type[0]
141-
//
142-
// itemI is generated recursively.
143-
144-
var arrayCreation = NormalArrayCreation.CreateGenerated(Context, parent, childIndex, constant.Type, constant.Values.Length);
145-
146-
if (constant.Values.Length > 0)
147-
{
148-
var arrayInit = ArrayInitializer.CreateGenerated(Context, arrayCreation);
149-
150-
constant.Values
151-
.Select((constantItem, itemIndex) => CreateGeneratedExpressionFromArgument(constantItem, arrayInit, itemIndex))
152-
.Where(e => e is object)
153-
.ToList();
154-
}
155-
156-
return arrayCreation;
157-
}
158-
default:
159-
Context.ExtractionError("Couldn't extract constant in attribute", entity.ToString(), Context.Create(entity.ReportingLocation));
160-
return null;
161-
}
97+
return syntax is null
98+
? Expression.CreateGenerated(Context, constant, parent, childIndex, Location)
99+
: Expression.Create(Context, syntax, parent, childIndex);
162100
}
163101

164102
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
165103

166104
public override Microsoft.CodeAnalysis.Location ReportingLocation => attributeSyntax?.Name.GetLocation();
167105

106+
private Semmle.Extraction.Entities.Location location;
107+
private Semmle.Extraction.Entities.Location Location =>
108+
location ?? (location = Semmle.Extraction.Entities.Location.Create(Context, attributeSyntax is null ? entity.ReportingLocation : attributeSyntax.Name.GetLocation()));
109+
168110
public override bool NeedsPopulation => true;
169111

170112
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
@@ -178,7 +120,7 @@ public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
178120
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity)
179121
{
180122
var init = (attributeData, entity);
181-
return AttributeFactory.Instance.CreateEntity(cx, init, init);
123+
return AttributeFactory.Instance.CreateEntity(cx, attributeData, init);
182124
}
183125

184126
private class AttributeFactory : ICachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute>

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

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using Semmle.Extraction.CSharp.Entities.Expressions;
45
using Semmle.Extraction.CSharp.Populators;
56
using Semmle.Extraction.Entities;
67
using Semmle.Extraction.Kinds;
8+
using System;
79
using System.IO;
810
using System.Linq;
911

@@ -125,6 +127,42 @@ public static void CreateDeferred(Context cx, ExpressionSyntax node, IExpression
125127
private static bool ContainsPattern(SyntaxNode node) =>
126128
node is PatternSyntax || node is VariableDesignationSyntax || node.ChildNodes().Any(ContainsPattern);
127129

130+
/// <summary>
131+
/// Creates a generated expression from a typed constant..
132+
/// </summary>
133+
public static Expression CreateGenerated(Context cx, TypedConstant constant, IExpressionParentEntity parent,
134+
int childIndex, Semmle.Extraction.Entities.Location location)
135+
{
136+
if (constant.IsNull)
137+
{
138+
return Literal.CreateGeneratedNullLiteral(cx, parent, childIndex, location);
139+
}
140+
141+
switch (constant.Kind)
142+
{
143+
case TypedConstantKind.Primitive:
144+
return Literal.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Value, location);
145+
case TypedConstantKind.Enum:
146+
// Enum value is generated in the following format: (Enum)value
147+
Action<Expression, int> createChild = (parent, index) => Literal.CreateGenerated(cx, parent, index, ((INamedTypeSymbol)constant.Type).EnumUnderlyingType, constant.Value, location);
148+
var cast = Cast.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Value, createChild, location);
149+
return cast;
150+
case TypedConstantKind.Type:
151+
var type = ((ITypeSymbol)constant.Value).OriginalDefinition;
152+
return TypeOf.CreateGenerated(cx, parent, childIndex, type, location);
153+
case TypedConstantKind.Array:
154+
// Single dimensional arrays are in the following format:
155+
// * new Type[N] { item1, item2, ..., itemN }
156+
// * new Type[0]
157+
//
158+
// itemI is generated recursively.
159+
return NormalArrayCreation.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Values, location);
160+
default:
161+
cx.ExtractionError("Couldn't extract constant in attribute", constant.ToString(), location);
162+
return null;
163+
}
164+
}
165+
128166
/// <summary>
129167
/// Adapt the operator kind depending on whether it's a dynamic call or a user-operator call.
130168
/// </summary>

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
44
using Semmle.Extraction.Kinds;
5+
using System.Collections.Generic;
56
using System.IO;
67
using System.Linq;
78

@@ -10,6 +11,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
1011
internal abstract class ArrayCreation<TSyntaxNode> : Expression<TSyntaxNode>
1112
where TSyntaxNode : ExpressionSyntax
1213
{
14+
protected const int InitializerIndex = -1;
15+
1316
protected ArrayCreation(ExpressionNodeInfo info) : base(info) { }
1417
}
1518

@@ -48,7 +51,7 @@ protected override void PopulateExpression(TextWriter trapFile)
4851

4952
if (!(Initializer is null))
5053
{
51-
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, NormalArrayCreation.InitializerIndex));
54+
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, InitializerIndex));
5255
}
5356

5457
if (explicitlySized)
@@ -75,8 +78,6 @@ private void SetArraySizes(InitializerExpressionSyntax initializer, int rank)
7578

7679
internal class NormalArrayCreation : ExplicitArrayCreation<ArrayCreationExpressionSyntax>
7780
{
78-
public const int InitializerIndex = -1;
79-
8081
private NormalArrayCreation(ExpressionNodeInfo info) : base(info) { }
8182

8283
protected override ArrayTypeSyntax TypeSyntax => Syntax.Type;
@@ -85,12 +86,12 @@ private NormalArrayCreation(ExpressionNodeInfo info) : base(info) { }
8586

8687
public static Expression Create(ExpressionNodeInfo info) => new NormalArrayCreation(info).TryPopulate();
8788

88-
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, int length)
89+
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, IEnumerable<TypedConstant> items, Semmle.Extraction.Entities.Location location)
8990
{
9091
var info = new ExpressionInfo(
9192
cx,
9293
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
93-
Extraction.Entities.GeneratedLocation.Create(cx),
94+
location,
9495
ExprKind.ARRAY_CREATION,
9596
parent,
9697
childIndex,
@@ -99,7 +100,19 @@ public static Expression CreateGenerated(Context cx, IExpressionParentEntity par
99100

100101
var arrayCreation = new Expression(info);
101102

102-
Literal.CreateGenerated(cx, arrayCreation, 0, cx.Compilation.GetSpecialType(SpecialType.System_Int32), length);
103+
var length = items.Count();
104+
105+
Literal.CreateGenerated(cx, arrayCreation, 0, cx.Compilation.GetSpecialType(SpecialType.System_Int32), length, location);
106+
107+
if (length > 0)
108+
{
109+
var arrayInit = ArrayInitializer.CreateGenerated(cx, arrayCreation, InitializerIndex, location);
110+
var child = 0;
111+
foreach (var item in items)
112+
{
113+
Expression.CreateGenerated(cx, item, arrayInit, child++, location);
114+
}
115+
}
103116

104117
return arrayCreation;
105118
}
@@ -130,7 +143,7 @@ private ImplicitStackAllocArrayCreation(ExpressionNodeInfo info) : base(info.Set
130143

131144
protected override void PopulateExpression(TextWriter trapFile)
132145
{
133-
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, NormalArrayCreation.InitializerIndex));
146+
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, InitializerIndex));
134147
trapFile.implicitly_typed_array_creation(this);
135148
trapFile.stackalloc_array_creation(this);
136149
}
@@ -146,7 +159,7 @@ protected override void PopulateExpression(TextWriter trapFile)
146159
{
147160
if (Syntax.Initializer != null)
148161
{
149-
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, NormalArrayCreation.InitializerIndex));
162+
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, InitializerIndex));
150163
}
151164

152165
trapFile.implicitly_typed_array_creation(this);

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

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
using Microsoft.CodeAnalysis.CSharp.Syntax;
22
using Semmle.Extraction.Kinds;
3+
using System;
34
using System.IO;
45

56
namespace Semmle.Extraction.CSharp.Entities.Expressions
67
{
78
internal class Cast : Expression<CastExpressionSyntax>
89
{
9-
public const int ExpressionIndex = 0;
10-
public const int TypeAccessIndex = 1;
10+
private const int ExpressionIndex = 0;
11+
private const int TypeAccessIndex = 1;
1112

1213
private Cast(ExpressionNodeInfo info) : base(info.SetKind(UnaryOperatorKind(info.Context, ExprKind.CAST, info.Node))) { }
1314

@@ -31,19 +32,25 @@ protected override void PopulateExpression(TextWriter trapFile)
3132

3233
public override Microsoft.CodeAnalysis.Location ReportingLocation => Syntax.GetLocation();
3334

34-
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, object value)
35+
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, object value, Action<Expression, int> createChild, Extraction.Entities.Location location)
3536
{
3637
var info = new ExpressionInfo(
3738
cx,
3839
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
39-
Extraction.Entities.GeneratedLocation.Create(cx),
40+
location,
4041
ExprKind.CAST,
4142
parent,
4243
childIndex,
4344
true,
4445
ValueAsString(value));
4546

46-
return new Expression(info);
47+
var ret = new Expression(info);
48+
49+
createChild(ret, ExpressionIndex);
50+
51+
TypeAccess.CreateGenerated(cx, ret, TypeAccessIndex, type, location);
52+
53+
return ret;
4754
}
4855
}
4956
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ protected override void PopulateExpression(TextWriter trapFile)
3636
}
3737
}
3838

39-
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent)
39+
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int index, Extraction.Entities.Location location)
4040
{
4141
var info = new ExpressionInfo(
4242
cx,
4343
NullType.Create(cx),
44-
GeneratedLocation.Create(cx),
44+
location,
4545
ExprKind.ARRAY_INIT,
4646
parent,
47-
NormalArrayCreation.InitializerIndex,
47+
index,
4848
true,
4949
null);
5050

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,12 @@ private static ExprKind GetExprKind(ITypeSymbol type, ExpressionSyntax expr, Con
7878
}
7979

8080
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object value,
81-
Extraction.Entities.Location location = null)
81+
Extraction.Entities.Location location)
8282
{
8383
var info = new ExpressionInfo(
8484
cx,
8585
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
86-
location ?? Extraction.Entities.GeneratedLocation.Create(cx),
86+
location,
8787
GetExprKind(type, null, cx),
8888
parent,
8989
childIndex,
@@ -93,12 +93,12 @@ public static Expression CreateGenerated(Context cx, IExpressionParentEntity par
9393
return new Expression(info);
9494
}
9595

96-
public static Expression CreateGeneratedNullLiteral(Context cx, IExpressionParentEntity parent, int childIndex)
96+
public static Expression CreateGeneratedNullLiteral(Context cx, IExpressionParentEntity parent, int childIndex, Extraction.Entities.Location location)
9797
{
9898
var info = new ExpressionInfo(
9999
cx,
100100
NullType.Create(cx),
101-
Extraction.Entities.GeneratedLocation.Create(cx),
101+
location,
102102
ExprKind.NULL_LITERAL,
103103
parent,
104104
childIndex,

0 commit comments

Comments
 (0)