1
ļ»æ// Copyright (c) 2010-2013 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 ICSharpCode.NRefactory.Semantics;
22
using ICSharpCode.NRefactory.Utils;
24
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
27
/// Default implementation of <see cref="IUnresolvedAttribute"/>.
30
public sealed class DefaultUnresolvedAttribute : AbstractFreezable, IUnresolvedAttribute, IFreezable, ISupportsInterning
32
ITypeReference attributeType;
34
IList<ITypeReference> constructorParameterTypes;
35
IList<IConstantValue> positionalArguments;
36
IList<KeyValuePair<IMemberReference, IConstantValue>> namedArguments;
38
public DefaultUnresolvedAttribute(ITypeReference attributeType)
40
if (attributeType == null)
41
throw new ArgumentNullException("attributeType");
42
this.attributeType = attributeType;
45
public DefaultUnresolvedAttribute(ITypeReference attributeType, IEnumerable<ITypeReference> constructorParameterTypes)
47
if (attributeType == null)
48
throw new ArgumentNullException("attributeType");
49
this.attributeType = attributeType;
50
this.ConstructorParameterTypes.AddRange(constructorParameterTypes);
53
protected override void FreezeInternal()
55
base.FreezeInternal();
56
constructorParameterTypes = FreezableHelper.FreezeList(constructorParameterTypes);
57
positionalArguments = FreezableHelper.FreezeListAndElements(positionalArguments);
58
namedArguments = FreezableHelper.FreezeList(namedArguments);
59
foreach (var pair in namedArguments) {
60
FreezableHelper.Freeze(pair.Key);
61
FreezableHelper.Freeze(pair.Value);
65
public ITypeReference AttributeType {
66
get { return attributeType; }
69
public DomRegion Region {
70
get { return region; }
72
FreezableHelper.ThrowIfFrozen(this);
77
public IList<ITypeReference> ConstructorParameterTypes {
79
if (constructorParameterTypes == null)
80
constructorParameterTypes = new List<ITypeReference>();
81
return constructorParameterTypes;
85
public IList<IConstantValue> PositionalArguments {
87
if (positionalArguments == null)
88
positionalArguments = new List<IConstantValue>();
89
return positionalArguments;
93
public IList<KeyValuePair<IMemberReference, IConstantValue>> NamedArguments {
95
if (namedArguments == null)
96
namedArguments = new List<KeyValuePair<IMemberReference, IConstantValue>>();
97
return namedArguments;
101
public void AddNamedFieldArgument(string fieldName, IConstantValue value)
103
this.NamedArguments.Add(new KeyValuePair<IMemberReference, IConstantValue>(
104
new DefaultMemberReference(EntityType.Field, attributeType, fieldName),
109
public void AddNamedPropertyArgument(string propertyName, IConstantValue value)
111
this.NamedArguments.Add(new KeyValuePair<IMemberReference, IConstantValue>(
112
new DefaultMemberReference(EntityType.Property, attributeType, propertyName),
117
public IAttribute CreateResolvedAttribute(ITypeResolveContext context)
119
return new DefaultResolvedAttribute(this, context);
122
int ISupportsInterning.GetHashCodeForInterning()
124
int hash = attributeType.GetHashCode() ^ constructorParameterTypes.GetHashCode();
126
if (constructorParameterTypes != null) {
127
foreach (var type in constructorParameterTypes) {
129
hash += type.GetHashCode();
132
if (positionalArguments != null) {
133
foreach (var arg in positionalArguments) {
135
hash += arg.GetHashCode();
138
if (namedArguments != null) {
139
foreach (var pair in namedArguments) {
141
hash += pair.Key.GetHashCode() + pair.Value.GetHashCode() * 73;
148
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
150
DefaultUnresolvedAttribute o = other as DefaultUnresolvedAttribute;
151
return o != null && attributeType == o.attributeType
152
&& ListEquals(constructorParameterTypes, o.constructorParameterTypes)
153
&& ListEquals(positionalArguments, o.positionalArguments)
154
&& ListEquals(namedArguments ?? EmptyList<KeyValuePair<IMemberReference, IConstantValue>>.Instance,
155
o.namedArguments ?? EmptyList<KeyValuePair<IMemberReference, IConstantValue>>.Instance);
158
static bool ListEquals<T>(IList<T> list1, IList<T> list2) where T : class
161
list1 = EmptyList<T>.Instance;
163
list2 = EmptyList<T>.Instance;
166
if (list1.Count != list2.Count)
168
for (int i = 0; i < list1.Count; i++) {
169
if (list1[i] != list2[i])
175
static bool ListEquals(IList<KeyValuePair<IMemberReference, IConstantValue>> list1, IList<KeyValuePair<IMemberReference, IConstantValue>> list2)
179
if (list1.Count != list2.Count)
181
for (int i = 0; i < list1.Count; i++) {
184
if (!(a.Key == b.Key && a.Value == b.Value))
190
sealed class DefaultResolvedAttribute : IAttribute, ICompilationProvider
192
readonly DefaultUnresolvedAttribute unresolved;
193
readonly ITypeResolveContext context;
194
readonly IType attributeType;
195
readonly IList<ResolveResult> positionalArguments;
197
// cannot use ProjectedList because KeyValuePair is value type
198
IList<KeyValuePair<IMember, ResolveResult>> namedArguments;
201
volatile bool constructorResolved;
203
public DefaultResolvedAttribute(DefaultUnresolvedAttribute unresolved, ITypeResolveContext context)
205
this.unresolved = unresolved;
206
this.context = context;
208
this.attributeType = unresolved.AttributeType.Resolve(context);
209
this.positionalArguments = unresolved.PositionalArguments.Resolve(context);
212
public IType AttributeType {
213
get { return attributeType; }
216
public DomRegion Region {
217
get { return unresolved.Region; }
220
public IMethod Constructor {
222
if (!constructorResolved) {
223
constructor = ResolveConstructor();
224
constructorResolved = true;
230
IMethod ResolveConstructor()
232
var parameterTypes = unresolved.ConstructorParameterTypes.Resolve(context);
233
foreach (var ctor in attributeType.GetConstructors(m => m.Parameters.Count == parameterTypes.Count)) {
235
for (int i = 0; i < parameterTypes.Count; i++) {
236
if (!ctor.Parameters[i].Type.Equals(parameterTypes[i])) {
247
public IList<ResolveResult> PositionalArguments {
248
get { return positionalArguments; }
251
public IList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
253
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
254
if (namedArgs != null) {
257
namedArgs = new List<KeyValuePair<IMember, ResolveResult>>();
258
foreach (var pair in unresolved.NamedArguments) {
259
IMember member = pair.Key.Resolve(context);
260
if (member != null) {
261
ResolveResult val = pair.Value.Resolve(context);
262
namedArgs.Add(new KeyValuePair<IMember, ResolveResult>(member, val));
265
return LazyInit.GetOrSet(ref this.namedArguments, namedArgs);
270
public ICompilation Compilation {
271
get { return context.Compilation; }
274
public override string ToString()
276
if (positionalArguments.Count == 0)
277
return "[" + attributeType.ToString() + "]";
279
return "[" + attributeType.ToString() + "(...)]";