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;
25
using ICSharpCode.NRefactory.Semantics;
26
using ICSharpCode.NRefactory.TypeSystem;
27
using ICSharpCode.NRefactory.TypeSystem.Implementation;
29
namespace ICSharpCode.NRefactory.CSharp.TypeSystem
32
/// Type reference used within an attribute.
33
/// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists.
36
public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning
38
ITypeReference withoutSuffix, withSuffix;
40
public AttributeTypeReference(ITypeReference withoutSuffix, ITypeReference withSuffix)
42
if (withoutSuffix == null)
43
throw new ArgumentNullException("withoutSuffix");
44
if (withSuffix == null)
45
throw new ArgumentNullException("withSuffix");
46
this.withoutSuffix = withoutSuffix;
47
this.withSuffix = withSuffix;
50
public IType Resolve(ITypeResolveContext context)
52
IType t1 = withoutSuffix.Resolve(context);
53
IType t2 = withSuffix.Resolve(context);
54
return PreferAttributeTypeWithSuffix(t1, t2, context.Compilation) ? t2 : t1;
57
internal static bool PreferAttributeTypeWithSuffix(IType t1, IType t2, ICompilation compilation)
59
if (t2.Kind == TypeKind.Unknown) return false;
60
if (t1.Kind == TypeKind.Unknown) return true;
62
var attrTypeDef = compilation.FindType(KnownTypeCode.Attribute).GetDefinition();
63
if (attrTypeDef != null) {
64
bool t1IsAttribute = (t1.GetDefinition() != null && t1.GetDefinition().IsDerivedFrom(attrTypeDef));
65
bool t2IsAttribute = (t2.GetDefinition() != null && t2.GetDefinition().IsDerivedFrom(attrTypeDef));
66
if (t2IsAttribute && !t1IsAttribute)
68
// If both types exist and are attributes, C# considers that to be an ambiguity, but we are less strict.
73
public override string ToString()
75
return withoutSuffix.ToString() + "[Attribute]";
78
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
80
withoutSuffix = provider.Intern(withoutSuffix);
81
withSuffix = provider.Intern(withSuffix);
84
int ISupportsInterning.GetHashCodeForInterning()
87
return withoutSuffix.GetHashCode() + 715613 * withSuffix.GetHashCode();
91
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
93
AttributeTypeReference atr = other as AttributeTypeReference;
94
return atr != null && this.withoutSuffix == atr.withoutSuffix && this.withSuffix == atr.withSuffix;