1 //
2 // MethodReference.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@gmail.com)
6 //
7 // Copyright (c) 2008 - 2011 Jb Evain
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 
29 using System;
30 using System.Text;
31 
32 using Mono.Collections.Generic;
33 
34 namespace Mono.Cecil {
35 
36 	public class MethodReference : MemberReference, IMethodSignature, IGenericParameterProvider, IGenericContext {
37 
38 		internal ParameterDefinitionCollection parameters;
39 		MethodReturnType return_type;
40 
41 		bool has_this;
42 		bool explicit_this;
43 		MethodCallingConvention calling_convention;
44 		internal Collection<GenericParameter> generic_parameters;
45 
46 		public virtual bool HasThis {
47 			get { return has_this; }
48 			set { has_this = value; }
49 		}
50 
51 		public virtual bool ExplicitThis {
52 			get { return explicit_this; }
53 			set { explicit_this = value; }
54 		}
55 
56 		public virtual MethodCallingConvention CallingConvention {
57 			get { return calling_convention; }
58 			set { calling_convention = value; }
59 		}
60 
61 		public virtual bool HasParameters {
62 			get { return !parameters.IsNullOrEmpty (); }
63 		}
64 
65 		public virtual Collection<ParameterDefinition> Parameters {
66 			get {
67 				if (parameters == null)
68 					parameters = new ParameterDefinitionCollection (this);
69 
70 				return parameters;
71 			}
72 		}
73 
74 		IGenericParameterProvider IGenericContext.Type {
75 			get {
76 				var declaring_type = this.DeclaringType;
77 				var instance = declaring_type as GenericInstanceType;
78 				if (instance != null)
79 					return instance.ElementType;
80 
81 				return declaring_type;
82 			}
83 		}
84 
85 		IGenericParameterProvider IGenericContext.Method {
86 			get { return this; }
87 		}
88 
89 		GenericParameterType IGenericParameterProvider.GenericParameterType {
90 			get { return GenericParameterType.Method; }
91 		}
92 
93 		public virtual bool HasGenericParameters {
94 			get { return !generic_parameters.IsNullOrEmpty (); }
95 		}
96 
97 		public virtual Collection<GenericParameter> GenericParameters {
98 			get {
99 				if (generic_parameters != null)
100 					return generic_parameters;
101 
102 				return generic_parameters = new GenericParameterCollection (this);
103 			}
104 		}
105 
106 		public TypeReference ReturnType {
107 			get {
108 				var return_type = MethodReturnType;
109 				return return_type != null ? return_type.ReturnType : null;
110 			}
111 			set {
112 				var return_type = MethodReturnType;
113 				if (return_type != null)
114 					return_type.ReturnType = value;
115 			}
116 		}
117 
118 		public virtual MethodReturnType MethodReturnType {
119 			get { return return_type; }
120 			set { return_type = value; }
121 		}
122 
123 		public override string FullName {
124 			get {
125 				var builder = new StringBuilder ();
126 				builder.Append (ReturnType.FullName)
127 					.Append (" ")
128 					.Append (MemberFullName ());
129 				this.MethodSignatureFullName (builder);
130 				return builder.ToString ();
131 			}
132 		}
133 
134 		public virtual bool IsGenericInstance {
135 			get { return false; }
136 		}
137 
138 		internal override bool ContainsGenericParameter {
139 			get {
140 				if (this.ReturnType.ContainsGenericParameter || base.ContainsGenericParameter)
141 					return true;
142 
143 				var parameters = this.Parameters;
144 
145 				for (int i = 0; i < parameters.Count; i++)
146 					if (parameters [i].ParameterType.ContainsGenericParameter)
147 						return true;
148 
149 				return false;
150 			}
151 		}
152 
MethodReference()153 		internal MethodReference ()
154 		{
155 			this.return_type = new MethodReturnType (this);
156 			this.token = new MetadataToken (TokenType.MemberRef);
157 		}
158 
MethodReference(string name, TypeReference returnType)159 		public MethodReference (string name, TypeReference returnType)
160 			: base (name)
161 		{
162 			if (returnType == null)
163 				throw new ArgumentNullException ("returnType");
164 
165 			this.return_type = new MethodReturnType (this);
166 			this.return_type.ReturnType = returnType;
167 			this.token = new MetadataToken (TokenType.MemberRef);
168 		}
169 
MethodReference(string name, TypeReference returnType, TypeReference declaringType)170 		public MethodReference (string name, TypeReference returnType, TypeReference declaringType)
171 			: this (name, returnType)
172 		{
173 			if (declaringType == null)
174 				throw new ArgumentNullException ("declaringType");
175 
176 			this.DeclaringType = declaringType;
177 		}
178 
GetElementMethod()179 		public virtual MethodReference GetElementMethod ()
180 		{
181 			return this;
182 		}
183 
Resolve()184 		public virtual MethodDefinition Resolve ()
185 		{
186 			var module = this.Module;
187 			if (module == null)
188 				throw new NotSupportedException ();
189 
190 			return module.Resolve (this);
191 		}
192 	}
193 
194 	static partial class Mixin {
195 
IsVarArg(this IMethodSignature self)196 		public static bool IsVarArg (this IMethodSignature self)
197 		{
198 			return (self.CallingConvention & MethodCallingConvention.VarArg) != 0;
199 		}
200 
GetSentinelPosition(this IMethodSignature self)201 		public static int GetSentinelPosition (this IMethodSignature self)
202 		{
203 			if (!self.HasParameters)
204 				return -1;
205 
206 			var parameters = self.Parameters;
207 			for (int i = 0; i < parameters.Count; i++)
208 				if (parameters [i].ParameterType.IsSentinel)
209 					return i;
210 
211 			return -1;
212 		}
213 	}
214 }
215