|
| 1 | +using System; |
| 2 | +using System.Collections.Generic; |
1 | 3 | using System.IO; |
2 | 4 | using System.Linq; |
3 | 5 | using Microsoft.CodeAnalysis; |
|
6 | 8 |
|
7 | 9 | namespace Semmle.Extraction.CSharp.Entities |
8 | 10 | { |
| 11 | + internal enum AttributeKind |
| 12 | + { |
| 13 | + Default = 0, |
| 14 | + Return = 1, |
| 15 | + Assembly = 2, |
| 16 | + Module = 3, |
| 17 | + } |
| 18 | + |
9 | 19 | internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity |
10 | 20 | { |
11 | 21 | bool IExpressionParentEntity.IsTopLevelParent => true; |
12 | 22 |
|
13 | 23 | private readonly AttributeSyntax? attributeSyntax; |
14 | 24 | private readonly IEntity entity; |
| 25 | + private readonly AttributeKind kind; |
15 | 26 |
|
16 | | - private Attribute(Context cx, AttributeData attributeData, IEntity entity) |
| 27 | + private Attribute(Context cx, AttributeData attributeData, IEntity entity, AttributeKind kind) |
17 | 28 | : base(cx, attributeData) |
18 | 29 | { |
19 | 30 | this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax; |
20 | 31 | this.entity = entity; |
| 32 | + this.kind = kind; |
21 | 33 | } |
22 | 34 |
|
23 | 35 | public override void WriteId(EscapingTextWriter trapFile) |
@@ -48,7 +60,7 @@ public sealed override void WriteQuotedId(EscapingTextWriter trapFile) |
48 | 60 | public override void Populate(TextWriter trapFile) |
49 | 61 | { |
50 | 62 | var type = Type.Create(Context, Symbol.AttributeClass); |
51 | | - trapFile.attributes(this, type.TypeRef, entity); |
| 63 | + trapFile.attributes(this, kind, type.TypeRef, entity); |
52 | 64 | trapFile.attribute_location(this, Location); |
53 | 65 |
|
54 | 66 | if (attributeSyntax is not null) |
@@ -125,26 +137,36 @@ private void ExtractArguments(TextWriter trapFile) |
125 | 137 |
|
126 | 138 | public override bool NeedsPopulation => true; |
127 | 139 |
|
| 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 | + |
128 | 148 | public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity) |
129 | 149 | { |
130 | | - foreach (var attribute in symbol.GetAttributes()) |
| 150 | + ExtractAttributes(cx, symbol, s => s.GetAttributes(), entity, AttributeKind.Default); |
| 151 | + if (symbol is IMethodSymbol method) |
131 | 152 | { |
132 | | - Create(cx, attribute, entity); |
| 153 | + ExtractAttributes(cx, method, s => s.GetReturnTypeAttributes(), entity, AttributeKind.Return); |
133 | 154 | } |
134 | 155 | } |
135 | 156 |
|
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) |
137 | 159 | { |
138 | | - var init = (attributeData, entity); |
| 160 | + var init = (attributeData, entity, kind); |
139 | 161 | return AttributeFactory.Instance.CreateEntity(cx, attributeData, init); |
140 | 162 | } |
141 | 163 |
|
142 | | - private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute> |
| 164 | + private class AttributeFactory : CachedEntityFactory<(AttributeData attributeData, IEntity receiver, AttributeKind kind), Attribute> |
143 | 165 | { |
144 | 166 | public static readonly AttributeFactory Instance = new AttributeFactory(); |
145 | 167 |
|
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); |
148 | 170 | } |
149 | 171 | } |
150 | 172 | } |
0 commit comments