~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory/TypeSystem/TypeParameterSubstitution.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
ļ»æ// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
 
2
// 
 
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:
 
8
// 
 
9
// The above copyright notice and this permission notice shall be included in all copies or
 
10
// substantial portions of the Software.
 
11
// 
 
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.
 
18
 
 
19
using System;
 
20
using System.Collections.Generic;
 
21
using System.Text;
 
22
 
 
23
namespace ICSharpCode.NRefactory.TypeSystem
 
24
{
 
25
        /// <summary>
 
26
        /// Substitutes class and method type parameters.
 
27
        /// </summary>
 
28
        public class TypeParameterSubstitution : TypeVisitor
 
29
        {
 
30
                /// <summary>
 
31
                /// The identity function.
 
32
                /// </summary>
 
33
                public static readonly TypeParameterSubstitution Identity = new TypeParameterSubstitution(null, null);
 
34
                
 
35
                readonly IList<IType> classTypeArguments;
 
36
                readonly IList<IType> methodTypeArguments;
 
37
                
 
38
                /// <summary>
 
39
                /// Creates a new type parameter substitution.
 
40
                /// </summary>
 
41
                /// <param name="classTypeArguments">
 
42
                /// The type arguments to substitute for class type parameters.
 
43
                /// Pass <c>null</c> to keep class type parameters unmodified.
 
44
                /// </param>
 
45
                /// <param name="methodTypeArguments">
 
46
                /// The type arguments to substitute for method type parameters.
 
47
                /// Pass <c>null</c> to keep method type parameters unmodified.
 
48
                /// </param>
 
49
                public TypeParameterSubstitution(IList<IType> classTypeArguments, IList<IType> methodTypeArguments)
 
50
                {
 
51
                        this.classTypeArguments = classTypeArguments;
 
52
                        this.methodTypeArguments = methodTypeArguments;
 
53
                }
 
54
                
 
55
                /// <summary>
 
56
                /// Gets the list of class type arguments.
 
57
                /// Returns <c>null</c> if this substitution keeps class type parameters unmodified.
 
58
                /// </summary>
 
59
                public IList<IType> ClassTypeArguments {
 
60
                        get { return classTypeArguments; }
 
61
                }
 
62
                
 
63
                /// <summary>
 
64
                /// Gets the list of method type arguments.
 
65
                /// Returns <c>null</c> if this substitution keeps method type parameters unmodified.
 
66
                /// </summary>
 
67
                public IList<IType> MethodTypeArguments {
 
68
                        get { return methodTypeArguments; }
 
69
                }
 
70
                
 
71
                #region Compose
 
72
                /// <summary>
 
73
                /// Computes a single TypeParameterSubstitution so that for all types <c>t</c>:
 
74
                /// <c>t.AcceptVisitor(Compose(g, f)) equals t.AcceptVisitor(f).AcceptVisitor(g)</c>
 
75
                /// </summary>
 
76
                /// <remarks>If you consider type parameter substitution to be a function, this is function composition.</remarks>
 
77
                public static TypeParameterSubstitution Compose(TypeParameterSubstitution g, TypeParameterSubstitution f)
 
78
                {
 
79
                        if (g == null)
 
80
                                return f;
 
81
                        if (f == null || (f.classTypeArguments == null && f.methodTypeArguments == null))
 
82
                                return g;
 
83
                        // The composition is a copy of 'f', with 'g' applied on the array elements.
 
84
                        // If 'f' has a null list (keeps type parameters unmodified), we have to treat it as
 
85
                        // the identity function, and thus use the list from 'g'.
 
86
                        var classTypeArguments = f.classTypeArguments != null ? GetComposedTypeArguments(f.classTypeArguments, g) : g.classTypeArguments;
 
87
                        var methodTypeArguments = f.methodTypeArguments != null ? GetComposedTypeArguments(f.methodTypeArguments, g) : g.methodTypeArguments;
 
88
                        return new TypeParameterSubstitution(classTypeArguments, methodTypeArguments);
 
89
                }
 
90
                
 
91
                static IList<IType> GetComposedTypeArguments(IList<IType> input, TypeParameterSubstitution substitution)
 
92
                {
 
93
                        IType[] result = new IType[input.Count];
 
94
                        for (int i = 0; i < result.Length; i++) {
 
95
                                result[i] = input[i].AcceptVisitor(substitution);
 
96
                        }
 
97
                        return result;
 
98
                }
 
99
                #endregion
 
100
                
 
101
                #region Equals and GetHashCode implementation
 
102
                public override bool Equals(object obj)
 
103
                {
 
104
                        TypeParameterSubstitution other = obj as TypeParameterSubstitution;
 
105
                        if (other == null)
 
106
                                return false;
 
107
                        return TypeListEquals(classTypeArguments, other.classTypeArguments)
 
108
                                && TypeListEquals(methodTypeArguments, other.methodTypeArguments);
 
109
                }
 
110
                
 
111
                public override int GetHashCode()
 
112
                {
 
113
                        unchecked {
 
114
                                return 1124131 * TypeListHashCode(classTypeArguments) + 1821779 * TypeListHashCode(methodTypeArguments);
 
115
                        }
 
116
                }
 
117
                
 
118
                static bool TypeListEquals(IList<IType> a, IList<IType> b)
 
119
                {
 
120
                        if (a == b)
 
121
                                return true;
 
122
                        if (a == null || b == null)
 
123
                                return false;
 
124
                        if (a.Count != b.Count)
 
125
                                return false;
 
126
                        for (int i = 0; i < a.Count; i++) {
 
127
                                if (!a[i].Equals(b[i]))
 
128
                                        return false;
 
129
                        }
 
130
                        return true;
 
131
                }
 
132
                
 
133
                static int TypeListHashCode(IList<IType> obj)
 
134
                {
 
135
                        if (obj == null)
 
136
                                return 0;
 
137
                        unchecked {
 
138
                                int hashCode = 1;
 
139
                                foreach (var element in obj) {
 
140
                                        hashCode *= 27;
 
141
                                        hashCode += element.GetHashCode();
 
142
                                }
 
143
                                return hashCode;
 
144
                        }
 
145
                }
 
146
                #endregion
 
147
                
 
148
                public override IType VisitTypeParameter(ITypeParameter type)
 
149
                {
 
150
                        int index = type.Index;
 
151
                        if (classTypeArguments != null && type.OwnerType == EntityType.TypeDefinition) {
 
152
                                if (index >= 0 && index < classTypeArguments.Count)
 
153
                                        return classTypeArguments[index];
 
154
                                else
 
155
                                        return SpecialType.UnknownType;
 
156
                        } else if (methodTypeArguments != null && type.OwnerType == EntityType.Method) {
 
157
                                if (index >= 0 && index < methodTypeArguments.Count)
 
158
                                        return methodTypeArguments[index];
 
159
                                else
 
160
                                        return SpecialType.UnknownType;
 
161
                        } else {
 
162
                                return base.VisitTypeParameter(type);
 
163
                        }
 
164
                }
 
165
                
 
166
                public override string ToString()
 
167
                {
 
168
                        StringBuilder b = new StringBuilder();
 
169
                        b.Append('[');
 
170
                        bool first = true;
 
171
                        if (classTypeArguments != null) {
 
172
                                for (int i = 0; i < classTypeArguments.Count; i++) {
 
173
                                        if (first) first = false; else b.Append(", ");
 
174
                                        b.Append('`');
 
175
                                        b.Append(i);
 
176
                                        b.Append(" -> ");
 
177
                                        b.Append(classTypeArguments[i].ReflectionName);
 
178
                                }
 
179
                        }
 
180
                        if (methodTypeArguments != null) {
 
181
                                for (int i = 0; i < methodTypeArguments.Count; i++) {
 
182
                                        if (first) first = false; else b.Append(", ");
 
183
                                        b.Append("``");
 
184
                                        b.Append(i);
 
185
                                        b.Append(" -> ");
 
186
                                        b.Append(methodTypeArguments[i].ReflectionName);
 
187
                                }
 
188
                        }
 
189
                        b.Append(']');
 
190
                        return b.ToString();
 
191
                }
 
192
        }
 
193
}