Skip to content

Commit c94cdfa

Browse files
committed
C#: Update the extractor to include the kind of the extracted attributes. Furthermore, include method return attributes.
1 parent e86ac73 commit c94cdfa

File tree

3 files changed

+43
-12
lines changed

3 files changed

+43
-12
lines changed

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

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using System;
2+
using System.Collections.Generic;
13
using System.IO;
24
using System.Linq;
35
using Microsoft.CodeAnalysis;
@@ -6,18 +8,28 @@
68

79
namespace Semmle.Extraction.CSharp.Entities
810
{
11+
internal enum AttributeKind
12+
{
13+
Default = 0,
14+
Return = 1,
15+
Assembly = 2,
16+
Module = 3,
17+
}
18+
919
internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity
1020
{
1121
bool IExpressionParentEntity.IsTopLevelParent => true;
1222

1323
private readonly AttributeSyntax? attributeSyntax;
1424
private readonly IEntity entity;
25+
private readonly AttributeKind kind;
1526

16-
private Attribute(Context cx, AttributeData attributeData, IEntity entity)
27+
private Attribute(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind)
1728
: base(cx, attributeData)
1829
{
1930
this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax;
2031
this.entity = entity;
32+
this.kind = kind;
2133
}
2234

2335
public override void WriteId(EscapingTextWriter trapFile)
@@ -48,7 +60,7 @@ public sealed override void WriteQuotedId(EscapingTextWriter trapFile)
4860
public override void Populate(TextWriter trapFile)
4961
{
5062
var type = Type.Create(Context, Symbol.AttributeClass);
51-
trapFile.attributes(this, type.TypeRef, entity);
63+
trapFile.attributes(this, kind, type.TypeRef, entity);
5264
trapFile.attribute_location(this, Location);
5365

5466
if (attributeSyntax is not null)
@@ -125,26 +137,36 @@ private void ExtractArguments(TextWriter trapFile)
125137

126138
public override bool NeedsPopulation => true;
127139

140+
private static void ExtractAttributes<T>(Context cx, T symbol, Func<T, IEnumerable<AttributeData>> getAttributes, IEntity entity, AttributeKind kind) where T : ISymbol
141+
{
142+
foreach (var attribute in getAttributes(symbol))
143+
{
144+
Create(cx, attribute, entity, kind);
145+
}
146+
}
147+
128148
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
129149
{
130-
foreach (var attribute in symbol.GetAttributes())
150+
ExtractAttributes(cx, symbol, s => s.GetAttributes(), entity, AttributeKind.Default);
151+
if (symbol is IMethodSymbol method)
131152
{
132-
Create(cx, attribute, entity);
153+
ExtractAttributes(cx, method, s => s.GetReturnTypeAttributes(), entity, AttributeKind.Return);
133154
}
134155
}
135156

136-
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity)
157+
158+
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind)
137159
{
138-
var init = (attributeData, entity);
160+
var init = (attributeData, entity, kind);
139161
return AttributeFactory.Instance.CreateEntity(cx, attributeData, init);
140162
}
141163

142-
private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute>
164+
private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver, AttributeKind kind), Attribute>
143165
{
144166
public static readonly AttributeFactory Instance = new AttributeFactory();
145167

146-
public override Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver) init) =>
147-
new Attribute(cx, init.attributeData, init.receiver);
168+
public override Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver, AttributeKind kind) init) =>
169+
new Attribute(cx, init.attributeData, init.receiver, init.kind);
148170
}
149171
}
150172
}

csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,26 @@ private void ExtractTypeDeclaration(BaseTypeDeclarationSyntax node)
8080
Entities.Type.Create(Cx, Cx.GetModel(node).GetDeclaredSymbol(node)).ExtractRecursive(TrapFile, Parent);
8181
}
8282

83+
private static Entities.AttributeKind ExtractGlobalTarget(AttributeListSyntax node) =>
84+
node.Target?.Identifier.Kind() switch
85+
{
86+
SyntaxKind.AssemblyKeyword => Entities.AttributeKind.Assembly,
87+
SyntaxKind.ModuleKeyword => Entities.AttributeKind.Module,
88+
_ => throw new InternalError(node, "Unhandled global target")
89+
};
90+
8391
public override void VisitAttributeList(AttributeListSyntax node)
8492
{
8593
if (Cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
8694
return;
8795

8896
var outputAssembly = Assembly.CreateOutputAssembly(Cx);
97+
var kind = ExtractGlobalTarget(node);
8998
foreach (var attribute in node.Attributes)
9099
{
91100
if (attributeLookup.Value(attribute) is AttributeData attributeData)
92101
{
93-
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly);
102+
var ae = Entities.Attribute.Create(Cx, attributeData, outputAssembly, kind);
94103
Cx.BindComments(ae, attribute.GetLocation());
95104
}
96105
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ internal static void init_only_accessors(this TextWriter trapFile, Accessor acce
3232
internal static void array_element_type(this TextWriter trapFile, ArrayType array, int dimension, int rank, Type elementType) =>
3333
trapFile.WriteTuple("array_element_type", array, dimension, rank, elementType);
3434

35-
internal static void attributes(this TextWriter trapFile, Attribute attribute, Type attributeType, IEntity entity) =>
36-
trapFile.WriteTuple("attributes", attribute, attributeType, entity);
35+
internal static void attributes(this TextWriter trapFile, Attribute attribute, AttributeKind kind, Type attributeType, IEntity entity) =>
36+
trapFile.WriteTuple("attributes", attribute, (int)kind, attributeType, entity);
3737

3838
internal static void attribute_location(this TextWriter trapFile, Attribute attribute, Location location) =>
3939
trapFile.WriteTuple("attribute_location", attribute, location);

0 commit comments

Comments
 (0)