1
ļ»æ// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
21
using System.Collections.ObjectModel;
22
using System.Diagnostics;
24
using ICSharpCode.NRefactory.CSharp.Resolver;
25
using ICSharpCode.NRefactory.Semantics;
26
using ICSharpCode.NRefactory.TypeSystem;
27
using ICSharpCode.NRefactory.TypeSystem.Implementation;
28
using ICSharpCode.NRefactory.Utils;
30
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
33
public sealed class CSharpAttribute : IUnresolvedAttribute
35
ITypeReference attributeType;
37
IList<IConstantValue> positionalArguments;
38
IList<KeyValuePair<string, IConstantValue>> namedCtorArguments;
39
IList<KeyValuePair<string, IConstantValue>> namedArguments;
41
public CSharpAttribute(ITypeReference attributeType, DomRegion region,
42
IList<IConstantValue> positionalArguments,
43
IList<KeyValuePair<string, IConstantValue>> namedCtorArguments,
44
IList<KeyValuePair<string, IConstantValue>> namedArguments)
46
if (attributeType == null)
47
throw new ArgumentNullException("attributeType");
48
this.attributeType = attributeType;
50
this.positionalArguments = positionalArguments ?? EmptyList<IConstantValue>.Instance;
51
this.namedCtorArguments = namedCtorArguments ?? EmptyList<KeyValuePair<string, IConstantValue>>.Instance;
52
this.namedArguments = namedArguments ?? EmptyList<KeyValuePair<string, IConstantValue>>.Instance;
54
public DomRegion Region {
55
get { return region; }
58
public ITypeReference AttributeType {
59
get { return attributeType; }
62
public IAttribute CreateResolvedAttribute(ITypeResolveContext context)
64
return new CSharpResolvedAttribute((CSharpTypeResolveContext)context, this);
67
sealed class CSharpResolvedAttribute : IAttribute
69
readonly CSharpTypeResolveContext context;
70
readonly CSharpAttribute unresolved;
71
readonly IType attributeType;
73
IList<KeyValuePair<IMember, ResolveResult>> namedArguments;
75
public CSharpResolvedAttribute(CSharpTypeResolveContext context, CSharpAttribute unresolved)
77
this.context = context;
78
this.unresolved = unresolved;
79
// Pretty much any access to the attribute checks the type first, so
80
// we don't need to use lazy-loading for that.
81
this.attributeType = unresolved.AttributeType.Resolve(context);
84
DomRegion IAttribute.Region {
85
get { return unresolved.Region; }
88
IType IAttribute.AttributeType {
89
get { return attributeType; }
92
ResolveResult ctorInvocation;
94
InvocationResolveResult GetCtorInvocation()
96
ResolveResult rr = LazyInit.VolatileRead(ref this.ctorInvocation);
98
return rr as InvocationResolveResult;
100
CSharpResolver resolver = new CSharpResolver(context);
101
int totalArgumentCount = unresolved.positionalArguments.Count + unresolved.namedCtorArguments.Count;
102
ResolveResult[] arguments = new ResolveResult[totalArgumentCount];
103
string[] argumentNames = new string[totalArgumentCount];
105
while (i < unresolved.positionalArguments.Count) {
106
IConstantValue cv = unresolved.positionalArguments[i];
107
arguments[i] = cv.Resolve(context);
110
foreach (var pair in unresolved.namedCtorArguments) {
111
argumentNames[i] = pair.Key;
112
arguments[i] = pair.Value.Resolve(context);
115
rr = resolver.ResolveObjectCreation(attributeType, arguments, argumentNames);
116
return LazyInit.GetOrSet(ref this.ctorInvocation, rr) as InvocationResolveResult;
120
IMethod IAttribute.Constructor {
122
var invocation = GetCtorInvocation();
123
if (invocation != null)
124
return invocation.Member as IMethod;
130
IList<ResolveResult> positionalArguments;
132
IList<ResolveResult> IAttribute.PositionalArguments {
134
var result = LazyInit.VolatileRead(ref this.positionalArguments);
135
if (result != null) {
138
var invocation = GetCtorInvocation();
139
if (invocation != null)
140
result = invocation.GetArgumentsForCall();
142
result = EmptyList<ResolveResult>.Instance;
143
return LazyInit.GetOrSet(ref this.positionalArguments, result);
148
IList<KeyValuePair<IMember, ResolveResult>> IAttribute.NamedArguments {
150
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
151
if (namedArgs != null) {
154
namedArgs = new List<KeyValuePair<IMember, ResolveResult>>();
155
foreach (var pair in unresolved.namedArguments) {
156
IMember member = attributeType.GetMembers(m => (m.EntityType == EntityType.Field || m.EntityType == EntityType.Property) && m.Name == pair.Key).FirstOrDefault();
157
if (member != null) {
158
ResolveResult val = pair.Value.Resolve(context);
159
namedArgs.Add(new KeyValuePair<IMember, ResolveResult>(member, val));
162
return LazyInit.GetOrSet(ref this.namedArguments, namedArgs);
170
public IMethod ResolveConstructor(ITypeResolveContext context)
172
CSharpResolver r = new CSharpResolver(context);
173
IType type = attributeType.Resolve(context);
174
int totalArgumentCount = 0;
175
if (positionalArguments != null)
176
totalArgumentCount += positionalArguments.Count;
177
if (namedCtorArguments != null)
178
totalArgumentCount += namedCtorArguments.Count;
179
ResolveResult[] arguments = new ResolveResult[totalArgumentCount];
180
string[] argumentNames = new string[totalArgumentCount];
182
if (positionalArguments != null) {
183
while (i < positionalArguments.Count) {
184
IConstantValue cv = positionalArguments[i];
185
arguments[i] = cv.Resolve(context);
189
if (namedCtorArguments != null) {
190
foreach (var pair in namedCtorArguments) {
191
argumentNames[i] = pair.Key;
192
arguments[i] = pair.Value.Resolve(context);
196
MemberResolveResult mrr = r.ResolveObjectCreation(type, arguments, argumentNames) as MemberResolveResult;
197
return mrr != null ? mrr.Member as IMethod : null;
200
public IList<ResolveResult> GetPositionalArguments(ITypeResolveContext context)
202
List<ResolveResult> result = new List<ResolveResult>();
203
if (positionalArguments != null) {
204
foreach (var arg in positionalArguments) {
205
result.Add(Resolve(arg, context));
208
if (namedCtorArguments == null || namedCtorArguments.Count == 0) {
209
// no namedCtorArguments: just return the positionalArguments
210
return result.AsReadOnly();
212
// we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments
213
IMethod method = ResolveConstructor(context);
214
if (method != null) {
215
for (int i = result.Count; i < method.Parameters.Count; i++) {
216
IParameter p = method.Parameters[i];
218
foreach (var pair in namedCtorArguments) {
219
if (pair.Key == p.Name) {
220
result.Add(Resolve(pair.Value, context));
225
// add the parameter's default value:
226
if (p.DefaultValue != null) {
227
result.Add(Resolve(p.DefaultValue, context));
229
IType type = p.Type.Resolve(context);
230
result.Add(new ConstantResolveResult(type, CSharpResolver.GetDefaultValue(type)));
235
return result.AsReadOnly();
238
ResolveResult Resolve(IConstantValue constantValue, ITypeResolveContext context)
240
if (constantValue != null)
241
return constantValue.Resolve(context);
243
return new ErrorResolveResult(SpecialType.UnknownType);
246
public IList<KeyValuePair<string, ResolveResult>> GetNamedArguments(ITypeResolveContext context)
248
if (namedArguments != null) {
249
return namedArguments.Select(p => new KeyValuePair<string, ResolveResult>(p.Key, p.Value.Resolve(context)))
250
.ToList().AsReadOnly();
252
return EmptyList<KeyValuePair<string, ResolveResult>>.Instance;
b'\\ No newline at end of file'