Skip to content

Commit 5075de5

Browse files
committed
C#: Add class for making synthetic parameter entities.
1 parent 60bb9a9 commit 5075de5

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
using System.IO;
2+
using System.Linq;
3+
using Microsoft.CodeAnalysis;
4+
using Microsoft.CodeAnalysis.CSharp.Syntax;
5+
6+
namespace Semmle.Extraction.CSharp.Entities
7+
{
8+
/// <summary>
9+
/// Synthetic parameter for extension methods declared using the extension syntax.
10+
/// That is, we add a synthetic parameter s to IsValid in the following example:
11+
/// extension(string s) {
12+
/// public bool IsValid() { ... }
13+
/// }
14+
///
15+
/// Note, that we use the characteristics of the parameter of the extension type
16+
/// to populate the database.
17+
/// </summary>
18+
internal class SyntheticExtensionParameter : FreshEntity, IParameter
19+
{
20+
private Method ExtensionMethod { get; }
21+
private IParameterSymbol ExtensionParameter { get; }
22+
private SyntheticExtensionParameter Original { get; }
23+
24+
private SyntheticExtensionParameter(Context cx, Method method, IParameterSymbol parameter, SyntheticExtensionParameter? original) : base(cx)
25+
{
26+
ExtensionMethod = method;
27+
ExtensionParameter = parameter;
28+
Original = original ?? this;
29+
}
30+
31+
private static int Ordinal => 0;
32+
33+
private Parameter.Kind ParamKind
34+
{
35+
get
36+
{
37+
switch (ExtensionParameter.RefKind)
38+
{
39+
case RefKind.Ref:
40+
return Parameter.Kind.Ref;
41+
case RefKind.In:
42+
return Parameter.Kind.In;
43+
case RefKind.RefReadOnlyParameter:
44+
return Parameter.Kind.RefReadOnly;
45+
default:
46+
return Parameter.Kind.None;
47+
}
48+
}
49+
}
50+
51+
private string Name => ExtensionParameter.Name;
52+
53+
private bool IsSourceDeclaration => ExtensionMethod.Symbol.IsSourceDeclaration();
54+
55+
private void PopulateAttributes()
56+
{
57+
// Only extract attributes for source declarations
58+
if (ReferenceEquals(ExtensionParameter, ExtensionParameter.OriginalDefinition))
59+
Attribute.ExtractAttributes(Context, ExtensionParameter, this);
60+
}
61+
62+
/// <summary>
63+
/// Bind comments to this symbol.
64+
/// Comments are only bound to source declarations.
65+
/// </summary>
66+
private void BindComments()
67+
{
68+
if (IsSourceDeclaration && ExtensionParameter.FromSource())
69+
Context.BindComments(this, ExtensionParameter.Locations.BestOrDefault());
70+
}
71+
72+
protected override void Populate(TextWriter trapFile)
73+
{
74+
PopulateAttributes();
75+
PopulateNullability(trapFile, ExtensionParameter.GetAnnotatedType());
76+
PopulateRefKind(trapFile, ExtensionParameter.RefKind);
77+
78+
var type = Type.Create(Context, ExtensionParameter.Type);
79+
trapFile.@params(this, Name, type.TypeRef, Ordinal, ParamKind, ExtensionMethod, Original);
80+
81+
if (Context.OnlyScaffold)
82+
{
83+
return;
84+
}
85+
86+
if (Context.ExtractLocation(ExtensionParameter))
87+
{
88+
var locations = Context.GetLocations(ExtensionParameter);
89+
WriteLocationsToTrap(trapFile.param_location, this, locations);
90+
}
91+
92+
BindComments();
93+
94+
if (IsSourceDeclaration)
95+
{
96+
foreach (var syntax in ExtensionParameter.DeclaringSyntaxReferences
97+
.Select(d => d.GetSyntax())
98+
.OfType<ParameterSyntax>()
99+
.Where(s => s.Type is not null))
100+
{
101+
TypeMention.Create(Context, syntax.Type!, this, type);
102+
}
103+
}
104+
}
105+
106+
public static SyntheticExtensionParameter Create(Context cx, Method method, IParameterSymbol parameter, SyntheticExtensionParameter? original)
107+
{
108+
var p = new SyntheticExtensionParameter(cx, method, parameter, original);
109+
p.TryPopulate();
110+
return p;
111+
}
112+
}
113+
114+
}

0 commit comments

Comments
 (0)