EndSession() public méthode

public EndSession ( ) : void
Résultat void
Exemple #1
0
        /// <summary>
        ///   Find the Applicable Function Members (7.4.2.1)
        ///
        ///   me: Method Group expression with the members to select.
        ///       it might contain constructors or methods (or anything
        ///       that maps to a method).
        ///
        ///   Arguments: ArrayList containing resolved Argument objects.
        ///
        ///   loc: The location if we want an error to be reported, or a Null
        ///        location for "probing" purposes.
        ///
        ///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
        ///            that is the best match of me on Arguments.
        ///
        /// </summary>
        public virtual MethodGroupExpr OverloadResolve(ResolveContext ec, ref Arguments Arguments,
            bool may_fail, Location loc)
        {
            var candidates = new List<MethodSpec> (2);
            List<MethodSpec> params_candidates = null;

            int arg_count = Arguments != null ? Arguments.Count : 0;
            Dictionary<MethodSpec, Arguments> candidates_expanded = null;
            Arguments candidate_args = Arguments;

            if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
                if (!may_fail)
                    ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
                return null;
            }

            //
            // Enable message recording, it's used mainly by lambda expressions
            //
            var msg_recorder = new SessionReportPrinter ();
            var prev_recorder = ec.Report.SetPrinter (msg_recorder);

            do {
                //
                // Methods in a base class are not candidates if any method in a derived
                // class is applicable
                //
                int best_candidate_rate = int.MaxValue;

                foreach (var member in Methods) {
                    var m = member as MethodSpec;
                    if (m == null) {
                        // TODO: It's wrong when non-member is before applicable method
                        // TODO: Should report only when at least 1 from the batch is applicable
                        if (candidates.Count != 0) {
                            ec.Report.SymbolRelatedToPreviousError (candidates [0]);
                            ec.Report.SymbolRelatedToPreviousError (member);
                            ec.Report.Warning (467, 2, loc, "Ambiguity between method `{0}' and non-method `{1}'. Using method `{0}'",
                                candidates[0].GetSignatureForError (), member.GetSignatureForError ());
                        }
                        continue;
                    }

                    //
                    // Check if candidate is applicable (section 14.4.2.1)
                    //
                    bool params_expanded_form = false;
                    int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref m, ref params_expanded_form);

                    if (candidate_rate < best_candidate_rate) {
                        best_candidate_rate = candidate_rate;
                        best_candidate = m;
                    }

                    if (params_expanded_form) {
                        if (params_candidates == null)
                            params_candidates = new List<MethodSpec> (2);
                        params_candidates.Add (m);
                    }

                    if (candidate_args != Arguments) {
                        if (candidates_expanded == null)
                            candidates_expanded = new Dictionary<MethodSpec, Arguments> (2);

                        candidates_expanded.Add (m, candidate_args);
                        candidate_args = Arguments;
                    }

                    if (candidate_rate != 0 || has_inaccessible_candidates_only) {
                        if (msg_recorder != null)
                            msg_recorder.EndSession ();
                        continue;
                    }

                    msg_recorder = null;
                    candidates.Add (m);
                }
            } while (candidates.Count == 0 && GetBaseTypeMethods (ec));

            ec.Report.SetPrinter (prev_recorder);
            if (msg_recorder != null && !msg_recorder.IsEmpty) {
                if (!may_fail)
                    msg_recorder.Merge (prev_recorder);

                return null;
            }

            int candidate_top = candidates.Count;
            if (candidate_top == 0) {
                //
                // When we found a top level method which does not match and it's
                // not an extension method. We start extension methods lookup from here
                //
                if (InstanceExpression != null) {
                    var first = Methods.First ();
                    var arity = type_arguments == null ? -1 : type_arguments.Count;
                    ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, first.Name, arity, loc);
                    if (ex_method_lookup != null) {
                        ex_method_lookup.ExtensionExpression = InstanceExpression;
                        ex_method_lookup.SetTypeArguments (ec, type_arguments);
                        return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
                    }
                }

                if (may_fail)
                    return null;

                //
                // Okay so we have failed to find exact match so we
                // return error info about the closest match
                //
                if (best_candidate != null) {
                    if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
                        return null;

                    bool params_expanded = params_candidates != null && params_candidates.Contains (best_candidate);
                    if (NoExactMatch (ec, ref Arguments, params_expanded))
                        return null;
                }

                //
                // We failed to find any method with correct argument count
                //
                if (Methods.First ().Kind == MemberKind.Constructor) {
                    ec.Report.SymbolRelatedToPreviousError (queried_type);
                    ec.Report.Error (1729, loc,
                        "The type `{0}' does not contain a constructor that takes `{1}' arguments",
                        TypeManager.CSharpName (queried_type), arg_count.ToString ());
                } else {
                    Error_ArgumentCountWrong (ec, arg_count);
                }

                return null;
            }

            if (arg_count != 0 && Arguments.HasDynamic) {
                best_candidate = null;
                return this;
            }

            //
            // Now we actually find the best method
            //
            best_candidate = candidates [0];
            bool method_params = params_candidates != null && params_candidates.Contains (best_candidate);

            for (int ix = 1; ix < candidate_top; ix++) {
                var candidate = candidates [ix];

                if (candidate == best_candidate)
                    continue;

                bool cand_params = params_candidates != null && params_candidates.Contains (candidate);

                if (candidates_expanded != null && candidates_expanded.ContainsKey (candidate)) {
                    candidate_args = candidates_expanded[candidate];
                    arg_count = candidate_args.Count;
                }

                if (BetterFunction (ec, candidate_args, arg_count,
                    candidate, cand_params,
                    best_candidate, method_params)) {
                    best_candidate = candidate;
                    method_params = cand_params;
                }

                if (candidate_args != Arguments) {
                    candidate_args = Arguments;
                    arg_count = candidate_args != null ? candidate_args.Count : 0;
                }
            }

            if (candidates_expanded != null && candidates_expanded.ContainsKey (best_candidate)) {
                candidate_args = candidates_expanded[best_candidate];
                arg_count = candidate_args.Count;
            }

            //
            // Now check that there are no ambiguities i.e the selected method
            // should be better than all the others
            //
            MethodSpec ambiguous = null;
            for (int ix = 1; ix < candidate_top; ix++) {
                var candidate = candidates [ix];

                if (candidate == best_candidate)
                    continue;

                bool cand_params = params_candidates != null && params_candidates.Contains (candidate);
                if (!BetterFunction (ec, candidate_args, arg_count,
                    best_candidate, method_params,
                    candidate, cand_params))
                {
                    if (!may_fail)
                        ec.Report.SymbolRelatedToPreviousError (candidate);
                    ambiguous = candidate;
                }
            }

            if (ambiguous != null) {
                Error_AmbiguousCall (ec, ambiguous);
                return this;
            }

            //
            // And now check if the arguments are all
            // compatible, perform conversions if
            // necessary etc. and return if everything is
            // all right
            //
            if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
                method_params, may_fail, loc))
                return null;

            if (best_candidate == null)
                return null;

            if (best_candidate.IsGeneric) {
                ConstraintChecker.CheckAll (best_candidate.GetGenericMethodDefinition (), best_candidate.TypeArguments,
                    best_candidate.Constraints, loc, ec.Report);
            }

            //
            // Check ObsoleteAttribute on the best method
            //
            ObsoleteAttribute oa = best_candidate.GetAttributeObsolete ();
            if (oa != null && !ec.IsObsolete)
                AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);

            best_candidate.MemberDefinition.SetIsUsed ();

            Arguments = candidate_args;
            return this;
        }
Exemple #2
0
		/// <summary>
		///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
		/// </summary>
		void ResolveAttributeType ()
		{
			SessionReportPrinter resolve_printer = new SessionReportPrinter ();
			ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);

			bool t1_is_attr = false;
			bool t2_is_attr = false;
			TypeSpec t1, t2;
			ATypeNameExpression expanded = null;

			try {
				t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);

				if (nameEscaped) {
					t2 = null;
				} else {
					expanded = (ATypeNameExpression) expression.Clone (null);
					expanded.Name += "Attribute";

					t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
				}

				resolve_printer.EndSession ();
			} finally {
				context.Compiler.Report.SetPrinter (prev_recorder);
			}

			if (t1_is_attr && t2_is_attr) {
				Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
					GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
				resolve_error = true;
				return;
			}

			if (t1_is_attr) {
				Type = t1;
				return;
			}

			if (t2_is_attr) {
				Type = t2;
				return;
			}

			resolve_printer.Merge (prev_recorder);
			resolve_error = true;
		}
		/// <summary>
		///   Find the Applicable Function Members (7.4.2.1)
		///
		///   me: Method Group expression with the members to select.
		///       it might contain constructors or methods (or anything
		///       that maps to a method).
		///
		///   Arguments: ArrayList containing resolved Argument objects.
		///
		///   loc: The location if we want an error to be reported, or a Null
		///        location for "probing" purposes.
		///
		///   Returns: The MethodBase (either a ConstructorInfo or a MethodInfo)
		///            that is the best match of me on Arguments.
		///
		/// </summary>
		public virtual MethodGroupExpr OverloadResolve (ResolveContext ec, ref Arguments Arguments,
			bool may_fail, Location loc)
		{
			bool method_params = false;
			Type applicable_type = null;
			ArrayList candidates = new ArrayList (2);
			ArrayList candidate_overrides = null;

			//
			// Used to keep a map between the candidate
			// and whether it is being considered in its
			// normal or expanded form
			//
			// false is normal form, true is expanded form
			//
			Hashtable candidate_to_form = null;
			Hashtable candidates_expanded = null;
			Arguments candidate_args = Arguments;

			int arg_count = Arguments != null ? Arguments.Count : 0;

			if (RootContext.Version == LanguageVersion.ISO_1 && Name == "Invoke" && TypeManager.IsDelegateType (DeclaringType)) {
				if (!may_fail)
					ec.Report.Error (1533, loc, "Invoke cannot be called directly on a delegate");
				return null;
			}

			int nmethods = Methods.Length;

			if (!IsBase) {
				//
				// Methods marked 'override' don't take part in 'applicable_type'
				// computation, nor in the actual overload resolution.
				// However, they still need to be emitted instead of a base virtual method.
				// So, we salt them away into the 'candidate_overrides' array.
				//
				// In case of reflected methods, we replace each overriding method with
				// its corresponding base virtual method.  This is to improve compatibility
				// with non-C# libraries which change the visibility of overrides (#75636)
				//
				int j = 0;
				for (int i = 0; i < Methods.Length; ++i) {
					MethodBase m = Methods [i];
					if (TypeManager.IsOverride (m)) {
						if (candidate_overrides == null)
							candidate_overrides = new ArrayList ();
						candidate_overrides.Add (m);
						m = TypeManager.TryGetBaseDefinition (m);
					}
					if (m != null)
						Methods [j++] = m;
				}
				nmethods = j;
			}

			//
			// Enable message recording, it's used mainly by lambda expressions
			//
			SessionReportPrinter msg_recorder = new SessionReportPrinter ();
			ReportPrinter prev_recorder = ec.Report.SetPrinter (msg_recorder);

			//
			// First we construct the set of applicable methods
			//
			bool is_sorted = true;
			int best_candidate_rate = int.MaxValue;
			for (int i = 0; i < nmethods; i++) {
				Type decl_type = Methods [i].DeclaringType;

				//
				// If we have already found an applicable method
				// we eliminate all base types (Section 14.5.5.1)
				//
				if (applicable_type != null && IsAncestralType (decl_type, applicable_type))
					continue;

				//
				// Check if candidate is applicable (section 14.4.2.1)
				//
				bool params_expanded_form = false;
				int candidate_rate = IsApplicable (ec, ref candidate_args, arg_count, ref Methods [i], ref params_expanded_form);

				if (candidate_rate < best_candidate_rate) {
					best_candidate_rate = candidate_rate;
					best_candidate = Methods [i];
				}
				
				if (params_expanded_form) {
					if (candidate_to_form == null)
						candidate_to_form = new PtrHashtable ();
					MethodBase candidate = Methods [i];
					candidate_to_form [candidate] = candidate;
				}
				
				if (candidate_args != Arguments) {
					if (candidates_expanded == null)
						candidates_expanded = new Hashtable (2);

					candidates_expanded.Add (Methods [i], candidate_args);
					candidate_args = Arguments;
				}

				if (candidate_rate != 0 || has_inaccessible_candidates_only) {
					if (msg_recorder != null)
						msg_recorder.EndSession ();
					continue;
				}

				msg_recorder = null;
				candidates.Add (Methods [i]);

				if (applicable_type == null)
					applicable_type = decl_type;
				else if (applicable_type != decl_type) {
					is_sorted = false;
					if (IsAncestralType (applicable_type, decl_type))
						applicable_type = decl_type;
				}
			}

			ec.Report.SetPrinter (prev_recorder);
			if (msg_recorder != null && !msg_recorder.IsEmpty) {
				if (!may_fail)
					msg_recorder.Merge (prev_recorder);

				return null;
			}
			
			int candidate_top = candidates.Count;

			if (applicable_type == null) {
				//
				// When we found a top level method which does not match and it's 
				// not an extension method. We start extension methods lookup from here
				//
				if (InstanceExpression != null) {
					ExtensionMethodGroupExpr ex_method_lookup = ec.LookupExtensionMethod (type, Name, loc);
					if (ex_method_lookup != null) {
						ex_method_lookup.ExtensionExpression = InstanceExpression;
						ex_method_lookup.SetTypeArguments (ec, type_arguments);
						return ex_method_lookup.OverloadResolve (ec, ref Arguments, may_fail, loc);
					}
				}
				
				if (may_fail)
					return null;

				//
				// Okay so we have failed to find exact match so we
				// return error info about the closest match
				//
				if (best_candidate != null) {
					if (CustomErrorHandler != null && !has_inaccessible_candidates_only && CustomErrorHandler.NoExactMatch (ec, best_candidate))
						return null;

					AParametersCollection pd = TypeManager.GetParameterData (best_candidate);
					bool cand_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);
					if (arg_count == pd.Count || pd.HasParams) {
						if (TypeManager.IsGenericMethodDefinition (best_candidate)) {
							if (type_arguments == null) {
								ec.Report.Error (411, loc,
									"The type arguments for method `{0}' cannot be inferred from " +
									"the usage. Try specifying the type arguments explicitly",
									TypeManager.CSharpSignature (best_candidate));
								return null;
							}

							Type[] g_args = TypeManager.GetGenericArguments (best_candidate);
							if (type_arguments.Count != g_args.Length) {
								ec.Report.SymbolRelatedToPreviousError (best_candidate);
								ec.Report.Error (305, loc, "Using the generic method `{0}' requires `{1}' type argument(s)",
									TypeManager.CSharpSignature (best_candidate),
									g_args.Length.ToString ());
								return null;
							}
						} else {
							if (type_arguments != null && !TypeManager.IsGenericMethod (best_candidate)) {
								Namespace.Error_TypeArgumentsCannotBeUsed (best_candidate, loc);
								return null;
							}
						}

						if (has_inaccessible_candidates_only) {
							if (InstanceExpression != null && type != ec.CurrentType && TypeManager.IsNestedFamilyAccessible (ec.CurrentType, best_candidate.DeclaringType)) {
								// Although a derived class can access protected members of
								// its base class it cannot do so through an instance of the
								// base class (CS1540).  If the qualifier_type is a base of the
								// ec.CurrentType and the lookup succeeds with the latter one,
								// then we are in this situation.
								Error_CannotAccessProtected (ec, loc, best_candidate, queried_type, ec.CurrentType);
							} else {
								ec.Report.SymbolRelatedToPreviousError (best_candidate);
								ErrorIsInaccesible (loc, GetSignatureForError (), ec.Report);
							}
						}

						if (!VerifyArgumentsCompat (ec, ref Arguments, arg_count, best_candidate, cand_params, may_fail, loc))
							return null;

						if (has_inaccessible_candidates_only)
							return null;

						throw new InternalErrorException ("VerifyArgumentsCompat didn't find any problem with rejected candidate " + best_candidate);
					}
				}

				//
				// We failed to find any method with correct argument count
				//
				if (Name == ConstructorInfo.ConstructorName) {
					ec.Report.SymbolRelatedToPreviousError (queried_type);
					ec.Report.Error (1729, loc,
						"The type `{0}' does not contain a constructor that takes `{1}' arguments",
						TypeManager.CSharpName (queried_type), arg_count);
				} else {
					Error_ArgumentCountWrong (ec, arg_count);
				}
                                
				return null;
			}

			if (!is_sorted) {
				//
				// At this point, applicable_type is _one_ of the most derived types
				// in the set of types containing the methods in this MethodGroup.
				// Filter the candidates so that they only contain methods from the
				// most derived types.
				//

				int finalized = 0; // Number of finalized candidates

				do {
					// Invariant: applicable_type is a most derived type
					
					// We'll try to complete Section 14.5.5.1 for 'applicable_type' by 
					// eliminating all it's base types.  At the same time, we'll also move
					// every unrelated type to the end of the array, and pick the next
					// 'applicable_type'.

					Type next_applicable_type = null;
					int j = finalized; // where to put the next finalized candidate
					int k = finalized; // where to put the next undiscarded candidate
					for (int i = finalized; i < candidate_top; ++i) {
						MethodBase candidate = (MethodBase) candidates [i];
						Type decl_type = candidate.DeclaringType;

						if (decl_type == applicable_type) {
							candidates [k++] = candidates [j];
							candidates [j++] = candidates [i];
							continue;
						}

						if (IsAncestralType (decl_type, applicable_type))
							continue;

						if (next_applicable_type != null &&
							IsAncestralType (decl_type, next_applicable_type))
							continue;

						candidates [k++] = candidates [i];

						if (next_applicable_type == null ||
							IsAncestralType (next_applicable_type, decl_type))
							next_applicable_type = decl_type;
					}

					applicable_type = next_applicable_type;
					finalized = j;
					candidate_top = k;
				} while (applicable_type != null);
			}

			//
			// Now we actually find the best method
			//

			best_candidate = (MethodBase) candidates [0];
			method_params = candidate_to_form != null && candidate_to_form.Contains (best_candidate);

			//
			// TODO: Broken inverse order of candidates logic does not work with optional
			// parameters used for method overrides and I am not going to fix it for SRE
			//
			if (candidates_expanded != null && candidates_expanded.Contains (best_candidate)) {
				candidate_args = (Arguments) candidates_expanded [best_candidate];
				arg_count = candidate_args.Count;
			}

			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);

				if (BetterFunction (ec, candidate_args, arg_count, 
					candidate, cand_params,
					best_candidate, method_params)) {
					best_candidate = candidate;
					method_params = cand_params;
				}
			}
			//
			// Now check that there are no ambiguities i.e the selected method
			// should be better than all the others
			//
			MethodBase ambiguous = null;
			for (int ix = 1; ix < candidate_top; ix++) {
				MethodBase candidate = (MethodBase) candidates [ix];

				if (candidate == best_candidate)
					continue;

				bool cand_params = candidate_to_form != null && candidate_to_form.Contains (candidate);
				if (!BetterFunction (ec, candidate_args, arg_count,
					best_candidate, method_params,
					candidate, cand_params)) 
				{
					if (!may_fail)
						ec.Report.SymbolRelatedToPreviousError (candidate);
					ambiguous = candidate;
				}
			}

			if (ambiguous != null) {
				Error_AmbiguousCall (ec, ambiguous);
				return this;
			}

			//
			// If the method is a virtual function, pick an override closer to the LHS type.
			//
			if (!IsBase && best_candidate.IsVirtual) {
				if (TypeManager.IsOverride (best_candidate))
					throw new InternalErrorException (
						"Should not happen.  An 'override' method took part in overload resolution: " + best_candidate);

				if (candidate_overrides != null) {
					Type[] gen_args = null;
					bool gen_override = false;
					if (TypeManager.IsGenericMethod (best_candidate))
						gen_args = TypeManager.GetGenericArguments (best_candidate);

					foreach (MethodBase candidate in candidate_overrides) {
						if (TypeManager.IsGenericMethod (candidate)) {
							if (gen_args == null)
								continue;

							if (gen_args.Length != TypeManager.GetGenericArguments (candidate).Length)
								continue;
						} else {
							if (gen_args != null)
								continue;
						}
						
						if (IsOverride (candidate, best_candidate)) {
							gen_override = true;
							best_candidate = candidate;
						}
					}

					if (gen_override && gen_args != null) {
#if GMCS_SOURCE
						best_candidate = ((MethodInfo) best_candidate).MakeGenericMethod (gen_args);
#endif						
					}
				}
			}

			//
			// And now check if the arguments are all
			// compatible, perform conversions if
			// necessary etc. and return if everything is
			// all right
			//
			if (!VerifyArgumentsCompat (ec, ref candidate_args, arg_count, best_candidate,
				method_params, may_fail, loc))
				return null;

			if (best_candidate == null)
				return null;

			MethodBase the_method = TypeManager.DropGenericMethodArguments (best_candidate);
			if (TypeManager.IsGenericMethodDefinition (the_method) &&
			    !ConstraintChecker.CheckConstraints (ec, the_method, best_candidate, loc))
				return null;

			//
			// Check ObsoleteAttribute on the best method
			//
			ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (the_method);
			if (oa != null && !ec.IsObsolete)
				AttributeTester.Report_ObsoleteMessage (oa, GetSignatureForError (), loc, ec.Report);

			IMethodData data = TypeManager.GetMethod (the_method);
			if (data != null)
				data.SetMemberIsUsed ();

			Arguments = candidate_args;
			return this;
		}