ICSharpCode.NRefactory.MonoCSharp.Method.DefineTypeParameters C# (CSharp) Method

DefineTypeParameters() protected method

protected DefineTypeParameters ( ) : void
return void
		protected virtual void DefineTypeParameters ()
		{
			var tparams = CurrentTypeParameters;

			TypeParameterSpec[] base_tparams = null;
			TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes;
			TypeSpec[] base_targs = TypeSpec.EmptyTypes;
			if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
				MethodSpec base_override = base_method ?? MethodData.implementing;

				if (base_override != null) {
					base_tparams = base_override.GenericDefinition.TypeParameters;

					if (base_override.DeclaringType.IsGeneric) {
						base_decl_tparams = base_override.DeclaringType.MemberDefinition.TypeParameters;

						if (base_method != null) {
							var base_type_parent = CurrentType;
							while (base_type_parent.BaseType != base_override.DeclaringType) {
								base_type_parent = base_type_parent.BaseType;
							}

							base_targs = base_type_parent.BaseType.TypeArguments;
						} else {
							foreach (var iface in Parent.CurrentType.Interfaces) {
								if (iface == base_override.DeclaringType) {
									base_targs = iface.TypeArguments;
									break;
								}
							}
						}
					}

					if (base_override.IsGeneric) {
						ObsoleteAttribute oa;
						foreach (var base_tp in base_tparams) {
							oa = base_tp.BaseType.GetAttributeObsolete ();
							if (oa != null) {
								AttributeTester.Report_ObsoleteMessage (oa, base_tp.BaseType.GetSignatureForError (), Location, Report);
							}

							if (base_tp.InterfacesDefined != null) {
								foreach (var iface in base_tp.InterfacesDefined) {
									oa = iface.GetAttributeObsolete ();
									if (oa != null) {
										AttributeTester.Report_ObsoleteMessage (oa, iface.GetSignatureForError (), Location, Report);
									}
								}
							}
						}

						if (base_decl_tparams.Length != 0) {
							base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray ();
							base_targs = base_targs.Concat (tparams.Types).ToArray ();
						} else {
							base_decl_tparams = base_tparams;
							base_targs = tparams.Types;
						}
					}
				}
			}

			for (int i = 0; i < tparams.Count; ++i) {
				var tp = tparams [i];

				if (base_tparams == null) {
					tp.ResolveConstraints (this);
					continue;
				}

				//
				// Copy base constraints for override/explicit methods
				//
				var base_tparam = base_tparams [i];
				var local_tparam = tp.Type;
				local_tparam.SpecialConstraint = base_tparam.SpecialConstraint;

				var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs);
				base_tparam.InflateConstraints (inflator, local_tparam);

				//
				// Check all type argument constraints for possible collision or unification
				// introduced by inflating inherited constraints in this context
				//
				// Conflict example:
				//
				// class A<T> { virtual void Foo<U> () where U : class, T {} }
				// class B : A<int> { override void Foo<U> {} }
				//
				var local_tparam_targs = local_tparam.TypeArguments;
				if (local_tparam_targs != null) {
					for (int ii = 0; ii < local_tparam_targs.Length; ++ii) {
						var ta = local_tparam_targs [ii];
						if (!ta.IsClass && !ta.IsStruct)
							continue;

						TypeSpec[] unique_tparams = null;
						for (int iii = ii + 1; iii < local_tparam_targs.Length; ++iii) {
							//
							// Remove any identical or unified constraint types
							//
							var tparam_checked = local_tparam_targs [iii];
							if (TypeSpecComparer.IsEqual (ta, tparam_checked) || TypeSpec.IsBaseClass (ta, tparam_checked, false)) {
								unique_tparams = new TypeSpec[local_tparam_targs.Length - 1];
								Array.Copy (local_tparam_targs, 0, unique_tparams, 0, iii);
								Array.Copy (local_tparam_targs, iii + 1, unique_tparams, iii, local_tparam_targs.Length - iii - 1);
							} else if (!TypeSpec.IsBaseClass (tparam_checked, ta, false)) {
								Constraints.Error_ConflictingConstraints (this, local_tparam, ta, tparam_checked, Location);
							}
						}

						if (unique_tparams != null) {
							local_tparam_targs = unique_tparams;
							local_tparam.TypeArguments = local_tparam_targs;
							continue;
						}

						Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location);
					}
				}
			}

			if (base_tparams == null && MethodData != null && MethodData.implementing != null) {
				CheckImplementingMethodConstraints (Parent, spec, MethodData.implementing);
			}
		}