protected override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.MustBeInvocableIfMember)) != 0)
            {
                return;
            }

            Debug.Assert(result.IsClear);

            var count = parameterMap.GetCountForKey(name);
            if (count == 1)
            {
                ParameterSymbol p;
                parameterMap.TryGetSingleValue(name, out p);
                result.MergeEqual(originalBinder.CheckViability(p, arity, options, null, diagnose, ref useSiteDiagnostics));
            }
            else if (count > 1)
            {
                var parameters = parameterMap[name];
                foreach (var sym in parameters)
                {
                    result.MergeEqual(originalBinder.CheckViability(sym, arity, options, null, diagnose, ref useSiteDiagnostics));
                }
            }
        }
Beispiel #2
0
 public BoundMethodGroup(
     CSharpSyntaxNode syntax,
     ImmutableArray<TypeSymbol> typeArgumentsOpt,
     BoundExpression receiverOpt,
     string name,
     ImmutableArray<MethodSymbol> methods,
     LookupResult lookupResult,
     BoundMethodGroupFlags flags,
     bool hasErrors = false)
     : this(syntax, typeArgumentsOpt, name, methods, lookupResult.SingleSymbolOrDefault, lookupResult.Error, flags, receiverOpt, lookupResult.Kind, hasErrors)
 {
 }
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);

            if ((options & LookupOptions.NamespaceAliasesOnly) != 0)
            {
                return;
            }

            foreach (var parameterSymbol in parameterMap[name])
            {
                result.MergeEqual(originalBinder.CheckViability(parameterSymbol, arity, options, null, diagnose, ref useSiteDiagnostics));
            }
        }
        protected override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            if ((options & (LookupOptions.NamespaceAliasesOnly | LookupOptions.MustBeInvocableIfMember)) != 0)
            {
                return;
            }

            Debug.Assert(result.IsClear);

            foreach (ParameterSymbol parameter in parameters)
            {
                if (parameter.Name == name)
                {
                    result.MergeEqual(originalBinder.CheckViability(parameter, arity, options, null, diagnose, ref useSiteDiagnostics));
                }
            }
        }
 internal override void LookupSymbolsInSingleBinder(
     LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
 {
     var hostObjectType = GetHostObjectType();
     if (hostObjectType.Kind == SymbolKind.ErrorType)
     {
         // The name '{0}' does not exist in the current context (are you missing a reference to assembly '{1}'?)
         result.SetFrom(new CSDiagnosticInfo(
             ErrorCode.ERR_NameNotInContextPossibleMissingReference,
             new object[] { name, ((MissingMetadataTypeSymbol)hostObjectType).ContainingAssembly.Identity },
             ImmutableArray<Symbol>.Empty,
             ImmutableArray<Location>.Empty
         ));
     }
     else
     {
         LookupMembersInternal(result, hostObjectType, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
     }
 }
Beispiel #6
0
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            if (!ShouldLookInUsings(options))
            {
                return;
            }

            LookupResult tmp = LookupResult.GetInstance();

            // usings:
            Imports.Empty.LookupSymbolInUsings(ConsolidatedUsings, originalBinder, tmp, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);

            // if we found a viable result in imported namespaces, use it instead of unviable symbols found in source:
            if (tmp.IsMultiViable)
            {
                result.MergeEqual(tmp);
            }

            tmp.Free();
        }
Beispiel #7
0
        /// <summary>
        /// Report appropriate diagnostics when lookup of a pattern member (i.e. GetEnumerator, Current, or MoveNext) fails.
        /// </summary>
        /// <param name="lookupResult">Failed lookup result.</param>
        /// <param name="patternType">Type in which member was looked up.</param>
        /// <param name="memberName">Name of looked up member.</param>
        /// <param name="warningsOnly">True if failures should result in warnings; false if they should result in errors.</param>
        /// <param name="diagnostics">Populated appropriately.</param>
        private void ReportPatternMemberLookupDiagnostics(LookupResult lookupResult, TypeSymbol patternType, string memberName, bool warningsOnly, DiagnosticBag diagnostics)
        {
            if (lookupResult.Symbols.Any())
            {
                if (warningsOnly)
                {
                    ReportEnumerableWarning(diagnostics, patternType, lookupResult.Symbols.First());
                }
                else
                {
                    lookupResult.Clear();

                    HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                    this.LookupMembersInType(
                        lookupResult,
                        patternType,
                        memberName,
                        arity: 0,
                        basesBeingResolved: null,
                        options: LookupOptions.Default,
                        originalBinder: this,
                        diagnose: true,
                        useSiteDiagnostics: ref useSiteDiagnostics);

                    diagnostics.Add(_syntax.Expression, useSiteDiagnostics);

                    if (lookupResult.Error != null)
                    {
                        diagnostics.Add(lookupResult.Error, _syntax.Expression.Location);
                    }
                }
            }
            else if (!warningsOnly)
            {
                diagnostics.Add(ErrorCode.ERR_NoSuchMember, _syntax.Expression.Location, patternType, memberName);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Perform a lookup for the specified method on the specified type.  Perform overload resolution
        /// on the lookup results.
        /// </summary>
        /// <param name="patternType">Type to search.</param>
        /// <param name="methodName">Method to search for.</param>
        /// <param name="lookupResult">Passed in for reusability.</param>
        /// <param name="warningsOnly">True if failures should result in warnings; false if they should result in errors.</param>
        /// <param name="diagnostics">Populated with binding diagnostics.</param>
        /// <returns>The desired method or null.</returns>
        private MethodSymbol FindForEachPatternMethod(TypeSymbol patternType, string methodName, LookupResult lookupResult, bool warningsOnly, DiagnosticBag diagnostics)
        {
            Debug.Assert(lookupResult.IsClear);

            // Not using LookupOptions.MustBeInvocableMember because we don't want the corresponding lookup error.
            // We filter out non-methods below.
            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            this.LookupMembersInType(
                lookupResult,
                patternType,
                methodName,
                arity: 0,
                basesBeingResolved: null,
                options: LookupOptions.Default,
                originalBinder: this,
                diagnose: false,
                useSiteDiagnostics: ref useSiteDiagnostics);

            diagnostics.Add(_syntax.Expression, useSiteDiagnostics);

            if (!lookupResult.IsMultiViable)
            {
                ReportPatternMemberLookupDiagnostics(lookupResult, patternType, methodName, warningsOnly, diagnostics);
                return null;
            }

            ArrayBuilder<MethodSymbol> candidateMethods = ArrayBuilder<MethodSymbol>.GetInstance();

            foreach (Symbol member in lookupResult.Symbols)
            {
                if (member.Kind != SymbolKind.Method)
                {
                    candidateMethods.Free();

                    if (warningsOnly)
                    {
                        ReportEnumerableWarning(diagnostics, patternType, member);
                    }
                    return null;
                }

                MethodSymbol method = (MethodSymbol)member;

                // SPEC VIOLATION: The spec says we should apply overload resolution, but Dev10 uses
                // some custom logic in ExpressionBinder.BindGrpToParams.  The biggest difference
                // we've found (so far) is that it only considers methods with zero parameters
                // (i.e. doesn't work with "params" or optional parameters).
                if (!method.Parameters.Any())
                {
                    candidateMethods.Add((MethodSymbol)member);
                }
            }

            MethodSymbol patternMethod = PerformForEachPatternOverloadResolution(patternType, candidateMethods, warningsOnly, diagnostics);

            candidateMethods.Free();

            return patternMethod;
        }
Beispiel #9
0
 /// <summary>
 /// Merge another result with this one, with the symbols combined if both
 /// this and other are viable. Otherwise the highest priority result wins (this if equal 
 /// priority and non-viable.)
 /// </summary>
 internal void MergeEqual(LookupResult other)
 {
     if (Kind > other.Kind)
     {
         return;
     }
     else if (other.Kind > Kind)
     {
         this.SetFrom(other);
     }
     else if (Kind != LookupResultKind.Viable)
     {
         // this makes the operator not symmetrical, but so far we do not care.
         // it is really a matter of which error gets reported.
         return;
     }
     else
     {
         // Merging two viable results together. We will always end up with at least two symbols.
         _symbolList.AddRange(other._symbolList);
     }
 }
Beispiel #10
0
 // Merge another result with this one, with the current result being prioritized
 // over the other if they are of equal "goodness". Mutates the current result.
 internal void MergePrioritized(LookupResult other)
 {
     if (other.Kind > Kind)
     {
         SetFrom(other);
     }
 }
Beispiel #11
0
 /// <summary>
 /// Set current result according to another.
 /// </summary>
 internal void SetFrom(LookupResult other)
 {
     _kind = other._kind;
     _symbolList.Clear();
     _symbolList.AddRange(other._symbolList);
     _error = other._error;
 }
Beispiel #12
0
        internal void LookupSymbolInUsings(
            ImmutableArray<NamespaceOrTypeAndUsingDirective> usings,
            Binder originalBinder,
            LookupResult result,
            string name,
            int arity,
            ConsList<Symbol> basesBeingResolved,
            LookupOptions options,
            bool diagnose,
            ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            bool callerIsSemanticModel = originalBinder.IsSemanticModelBinder;

            foreach (var typeOrNamespace in usings)
            {
                ImmutableArray<Symbol> candidates = Binder.GetCandidateMembers(typeOrNamespace.NamespaceOrType, name, options, originalBinder: originalBinder);
                foreach (Symbol symbol in candidates)
                {
                    switch (symbol.Kind)
                    {
                        // lookup via "using namespace" ignores namespaces inside
                        case SymbolKind.Namespace:
                            continue;

                        // lookup via "using static" ignores extension methods and non-static methods
                        case SymbolKind.Method:
                            if (!symbol.IsStatic || ((MethodSymbol)symbol).IsExtensionMethod)
                            {
                                continue;
                            }

                            break;

                        // types are considered static members for purposes of "using static" feature
                        // regardless of whether they are declared with "static" modifier or not
                        case SymbolKind.NamedType:
                            break;

                        // lookup via "using static" ignores non-static members
                        default:
                            if (!symbol.IsStatic)
                            {
                                continue;
                            }

                            break;
                    }

                    // Found a match in our list of normal using directives.  Mark the directive
                    // as being seen so that it won't be reported to the user as something that
                    // can be removed.
                    var res = originalBinder.CheckViability(symbol, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                    if (res.Kind == LookupResultKind.Viable)
                    {
                        MarkImportDirective(typeOrNamespace.UsingDirective, callerIsSemanticModel);
                    }

                    result.MergeEqual(res);
                }
            }
        }
Beispiel #13
0
        private Binder XSLookupSymbolsInternal(
            LookupResult result, string name, int arity, ConsList <Symbol> basesBeingResolved, LookupOptions options, bool diagnose, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);
            Debug.Assert(options.AreValid());

            // X# looks for functions first
            //if (Compilation.Options.HasRuntime)
            {
                // check for function calls method calls outside the current class
                bool check = (options.HasFlag(LookupOptions.MustNotBeInstance) && !options.HasFlag(LookupOptions.MustNotBeMethod));
                if (check)
                {
                    var funcOptions = options;
                    funcOptions |= LookupOptions.MustBeInvocableIfMember;
                    Binder scope = this;
                    while (scope != null)
                    {
                        if (scope is InContainerBinder && scope.ContainingType == null) // at the namespace level, so outside of all types
                        {
                            scope.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, funcOptions, this, diagnose, ref useSiteDiagnostics);
                            FilterResults(result, options);
                            if (!result.IsClear)
                            {
                                break;
                            }
                        }
                        scope = scope.Next;
                    }
                }
            }
            LookupResult functionResults = LookupResult.GetInstance();

            if (!result.IsClear)
            {
                foreach (var symbol in result.Symbols)
                {
                    if (symbol is MethodSymbol)
                    {
                        var ms = symbol as MethodSymbol;
                        if (ms.IsStatic && ms.ContainingType.Name.EndsWith("Functions", XSharpString.Comparison))
                        {
                            SingleLookupResult single = new SingleLookupResult(LookupResultKind.Viable, ms, null);
                            functionResults.MergeEqual(single);
                        }
                    }
                }
                result.Clear();
            }
            Binder binder = null;

            for (var scope = this; scope != null && !result.IsMultiViable; scope = scope.Next)
            {
                if (binder != null)
                {
                    var tmp = LookupResult.GetInstance();
                    scope.LookupSymbolsInSingleBinder(tmp, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics);
                    FilterResults(tmp, options);
                    result.MergeEqual(tmp);
                    tmp.Free();
                }
                else
                {
                    scope.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteDiagnostics);
                    FilterResults(result, options);
                    if (!result.IsClear)
                    {
                        binder = scope;
                    }
                }
            }
            if (!functionResults.IsClear)
            {
                // compare the function results with the overall results found
                // create a list of functions and methods
                // function first and then the methods
                LookupResult mergedResults = LookupResult.GetInstance();
                mergedResults.MergeEqual(functionResults);
                // now add the symbols from result that do not exist
                for (int j = 0; j < result.Symbols.Count; j++)
                {
                    var sym   = result.Symbols[j];
                    var found = false;
                    for (int i = 0; i < mergedResults.Symbols.Count; i++)
                    {
                        if (sym == mergedResults.Symbols[i])
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                    {
                        SingleLookupResult single = new SingleLookupResult(LookupResultKind.Viable, sym, null);
                        mergedResults.MergeEqual(single);
                    }
                }
                result.Clear();
                result.MergeEqual(mergedResults);
            }
            // C563 Make sure the error is generated for Inaccessible types.
            if (!result.IsClear && result.Kind == LookupResultKind.Inaccessible && result.Error != null)
            {
                // we only want to add this for internal fields (globals)
                if (result.Symbols[0].Kind == SymbolKind.Field)
                {
                    if (useSiteDiagnostics == null)
                    {
                        useSiteDiagnostics = new HashSet <DiagnosticInfo>();
                    }
                    useSiteDiagnostics.Add(result.Error);
                }
            }
            return(binder);
        }
Beispiel #14
0
        /// <summary>
        /// Called after it is determined that the expression being enumerated is of a type that
        /// has a GetEnumerator method.  Checks to see if the return type of the GetEnumerator
        /// method is suitable (i.e. has Current and MoveNext).
        /// </summary>
        /// <param name="builder">Must be non-null and contain a non-null GetEnumeratorMethod.</param>
        /// <param name="diagnostics">Will be populated with pattern diagnostics.</param>
        /// <returns>True if the return type has suitable members.</returns>
        /// <remarks>
        /// It seems that every failure path reports the same diagnostics, so that is left to the caller.
        /// </remarks>
        private bool SatisfiesForEachPattern(ref ForEachEnumeratorInfo.Builder builder, DiagnosticBag diagnostics)
        {
            Debug.Assert((object)builder.GetEnumeratorMethod != null);

            MethodSymbol getEnumeratorMethod = builder.GetEnumeratorMethod;
            TypeSymbol   enumeratorType      = getEnumeratorMethod.ReturnType;

            switch (enumeratorType.TypeKind)
            {
            case TypeKind.Class:
            case TypeKind.Struct:
            case TypeKind.Interface:
            case TypeKind.TypeParameter: // Not specifically mentioned in the spec, but consistent with Dev10.
            case TypeKind.Dynamic:       // Not specifically mentioned in the spec, but consistent with Dev10.
                break;

            case TypeKind.Submission:
                // submission class is synthesized and should never appear in a foreach:
                throw ExceptionUtilities.UnexpectedValue(enumeratorType.TypeKind);

            default:
                return(false);
            }

            // Use a try-finally since there are many return points
            LookupResult lookupResult = LookupResult.GetInstance();

            try
            {
                // If we searched for the accessor directly, we could reuse FindForEachPatternMethod and we
                // wouldn't have to mangle CurrentPropertyName.  However, Dev10 searches for the property and
                // then extracts the accessor, so we should do the same (in case of accessors with non-standard
                // names).
                HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                this.LookupMembersInType(
                    lookupResult,
                    enumeratorType,
                    CurrentPropertyName,
                    arity: 0,
                    basesBeingResolved: null,
                    options: LookupOptions.Default, // properties are not invocable - their accessors are
                    originalBinder: this,
                    diagnose: false,
                    useSiteDiagnostics: ref useSiteDiagnostics);

                diagnostics.Add(_syntax.Expression, useSiteDiagnostics);
                useSiteDiagnostics = null;

                if (!lookupResult.IsSingleViable)
                {
                    ReportPatternMemberLookupDiagnostics(lookupResult, enumeratorType, CurrentPropertyName, warningsOnly: false, diagnostics: diagnostics);
                    return(false);
                }

                // lookupResult.IsSingleViable above guaranteed there is exactly one symbol.
                Symbol lookupSymbol = lookupResult.SingleSymbolOrDefault;
                Debug.Assert((object)lookupSymbol != null);

                if (lookupSymbol.IsStatic || lookupSymbol.DeclaredAccessibility != Accessibility.Public || lookupSymbol.Kind != SymbolKind.Property)
                {
                    return(false);
                }

                // NOTE: accessor can be inherited from overridden property
                MethodSymbol currentPropertyGetterCandidate = ((PropertySymbol)lookupSymbol).GetOwnOrInheritedGetMethod();

                if ((object)currentPropertyGetterCandidate == null)
                {
                    return(false);
                }
                else
                {
                    bool isAccessible = this.IsAccessible(currentPropertyGetterCandidate, ref useSiteDiagnostics);
                    diagnostics.Add(_syntax.Expression, useSiteDiagnostics);

                    if (!isAccessible)
                    {
                        // NOTE: per Dev10 and the spec, the property has to be public, but the accessor just has to be accessible
                        return(false);
                    }
                }

                builder.CurrentPropertyGetter = currentPropertyGetterCandidate;

                lookupResult.Clear(); // Reuse the same LookupResult

                MethodSymbol moveNextMethodCandidate = FindForEachPatternMethod(enumeratorType, MoveNextMethodName, lookupResult, warningsOnly: false, diagnostics: diagnostics);

                // SPEC VIOLATION: Dev10 checks the return type of the original definition, rather than the return type of the actual method.

                if ((object)moveNextMethodCandidate == null ||
                    moveNextMethodCandidate.IsStatic || moveNextMethodCandidate.DeclaredAccessibility != Accessibility.Public ||
                    ((MethodSymbol)moveNextMethodCandidate.OriginalDefinition).ReturnType.SpecialType != SpecialType.System_Boolean)
                {
                    return(false);
                }

                builder.MoveNextMethod = moveNextMethodCandidate;

                return(true);
            }
            finally
            {
                lookupResult.Free();
            }
        }
Beispiel #15
0
        private BoundExpression BindWithExpression(
            WithExpressionSyntax syntax,
            BindingDiagnosticBag diagnostics
            )
        {
            var receiver     = BindRValueWithoutTargetType(syntax.Expression, diagnostics);
            var receiverType = receiver.Type;

            var  lookupResult = LookupResult.GetInstance();
            bool hasErrors    = false;

            if (receiverType is null || receiverType.IsVoidType())
            {
                diagnostics.Add(ErrorCode.ERR_InvalidWithReceiverType, syntax.Expression.Location);
                receiverType = CreateErrorType();
            }

            MethodSymbol?cloneMethod = null;

            if (!receiverType.IsErrorType())
            {
                CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(
                    diagnostics
                    );

                cloneMethod = SynthesizedRecordClone.FindValidCloneMethod(
                    receiverType is TypeParameterSymbol typeParameter
                      ? typeParameter.EffectiveBaseClass(ref useSiteInfo)
                      : receiverType,
                    ref useSiteInfo
                    );
                if (cloneMethod is null)
                {
                    hasErrors = true;
                    diagnostics.Add(
                        ErrorCode.ERR_NoSingleCloneMethod,
                        syntax.Expression.Location,
                        receiverType
                        );
                }
                else
                {
                    cloneMethod.AddUseSiteInfo(ref useSiteInfo);
                }

                diagnostics.Add(syntax.Expression, useSiteInfo);
            }

            var initializer = BindInitializerExpression(
                syntax.Initializer,
                receiverType,
                syntax.Expression,
                isForNewInstance: true,
                diagnostics
                );

            // N.B. Since we only don't parse nested initializers in syntax there should be no extra
            // errors we need to check for here.

            return(new BoundWithExpression(
                       syntax,
                       receiver,
                       cloneMethod,
                       initializer,
                       receiverType,
                       hasErrors: hasErrors
                       ));
        }
Beispiel #16
0
        internal static bool HandleXSharpImport(UsingDirectiveSyntax usingDirective, Binder usingsBinder,
                                                ArrayBuilder <NamespaceOrTypeAndUsingDirective> usings, PooledHashSet <NamespaceOrTypeSymbol> uniqueUsings,
                                                ConsList <Symbol> basesBeingResolved, CSharpCompilation compilation)
        {
            // The usingDirective name contains spaces when it is nested and the GlobalClassName not , so we must eliminate them here
            // nvk: usingDirective.Name.ToString() ONLY has spaces if it is nested. This is not supposed to be nested, as it is "Functions" even for the non-core dialects !!!
            if (usingDirective.Name.ToString().EndsWith(XSharpSpecialNames.FunctionsClass))
            {
                var                      result             = LookupResult.GetInstance();
                LookupOptions            options            = LookupOptions.AllNamedTypesOnArityZero;
                HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                usingsBinder.LookupSymbolsSimpleName(result, null, XSharpSpecialNames.FunctionsClass, 0, basesBeingResolved, options, false, useSiteDiagnostics: ref useSiteDiagnostics);
                foreach (var sym in result.Symbols)
                {
                    if (sym.Kind == SymbolKind.NamedType)
                    {
                        var ts = (NamedTypeSymbol)sym;
                        AddNs(usingDirective, ts, usings, uniqueUsings);
                    }
                }
                var opts = ((CSharpSyntaxTree)usingDirective.SyntaxTree).Options;
                if (opts.CommandLineArguments != null)
                {
                    string functionsClass = null;
                    if (compilation.Options.HasRuntime)
                    {
                        functionsClass = Syntax.InternalSyntax.XSharpTreeTransformationRT.VOGlobalClassName(opts);
                    }
                    else
                    {
                        functionsClass = Syntax.InternalSyntax.XSharpTreeTransformationCore.GlobalFunctionClassName(opts.TargetDLL);
                    }
                    if (!string.IsNullOrEmpty(functionsClass))
                    {
                        var declbinder  = usingsBinder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);
                        var diagnostics = DiagnosticBag.GetInstance();
                        var name        = Syntax.InternalSyntax.XSharpTreeTransformationCore.ExtGenerateQualifiedName(functionsClass);
                        var imported    = declbinder.BindNamespaceOrTypeSymbol(name, diagnostics, basesBeingResolved);
                        if (imported.Kind == SymbolKind.NamedType)
                        {
                            var importedType = (NamedTypeSymbol)imported;
                            AddNs(usingDirective, importedType, usings, uniqueUsings);
                        }
                    }
                }

                if (!compilation.ClassLibraryType().IsErrorType() &&
                    !compilation.ImplicitNamespaceType().IsErrorType())
                {
                    var      declbinder  = usingsBinder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);
                    var      diagnostics = DiagnosticBag.GetInstance();
                    string[] defNs;
                    if (compilation.Options.XSharpRuntime)
                    {
                        defNs = new string[] { OurNameSpaces.XSharp }
                    }
                    ;
                    else
                    {
                        defNs = new string[] { OurNameSpaces.Vulcan }
                    };

                    foreach (var n in defNs)
                    {
                        var name     = Syntax.InternalSyntax.XSharpTreeTransformationCore.ExtGenerateQualifiedName(n);
                        var imported = declbinder.BindNamespaceOrTypeSymbol(name, diagnostics, basesBeingResolved);
                        if (imported.Kind == SymbolKind.Namespace)
                        {
                            AddNs(usingDirective, imported, usings, uniqueUsings);
                        }
                        else if (imported.Kind == SymbolKind.NamedType)
                        {
                            var importedType = (NamedTypeSymbol)imported;
                            AddNs(usingDirective, importedType, usings, uniqueUsings);
                        }
                    }
                    var vcla   = compilation.ClassLibraryType();
                    var vins   = compilation.ImplicitNamespaceType();
                    var refMan = compilation.GetBoundReferenceManager();
                    foreach (var r in refMan.ReferencedAssemblies)
                    {
                        foreach (var attr in r.GetAttributes())
                        {
                            // Check for VulcanImplicitNameSpace attribute
                            if (attr.AttributeClass.ConstructedFrom == vins && compilation.Options.ImplicitNameSpace)
                            {
                                var args = attr.CommonConstructorArguments;
                                if (args != null && args.Length == 1)
                                {
                                    // only one argument, must be default namespace
                                    var defaultNamespace = args[0].Value.ToString();
                                    if (!string.IsNullOrEmpty(defaultNamespace))
                                    {
                                        var name     = Syntax.InternalSyntax.XSharpTreeTransformationCore.ExtGenerateQualifiedName(defaultNamespace);
                                        var imported = declbinder.BindNamespaceOrTypeSymbol(name, diagnostics, basesBeingResolved);
                                        if (imported.Kind == SymbolKind.Namespace)
                                        {
                                            AddNs(usingDirective, imported, usings, uniqueUsings);
                                        }
                                    }
                                }
                            }
                            // Check for VulcanClasslibrary  attribute
                            else if (attr.AttributeClass.ConstructedFrom == vcla)
                            {
                                var args = attr.CommonConstructorArguments;
                                if (args != null && args.Length == 2)
                                {
                                    // first element is the Functions class
                                    var globalClassName = args[0].Value.ToString();
                                    if (!string.IsNullOrEmpty(globalClassName))
                                    {
                                        var name     = Syntax.InternalSyntax.XSharpTreeTransformationCore.ExtGenerateQualifiedName(globalClassName);
                                        var imported = declbinder.BindNamespaceOrTypeSymbol(name, diagnostics, basesBeingResolved);
                                        if (imported.Kind == SymbolKind.NamedType)
                                        {
                                            var importedType = (NamedTypeSymbol)imported;
                                            AddNs(usingDirective, importedType, usings, uniqueUsings);
                                        }
                                    }
                                    // second element is the default namespace
                                    var defaultNamespace = args[1].Value.ToString();
                                    if (!string.IsNullOrEmpty(defaultNamespace) && compilation.Options.ImplicitNameSpace)
                                    {
                                        var name     = Syntax.InternalSyntax.XSharpTreeTransformationCore.ExtGenerateQualifiedName(defaultNamespace);
                                        var imported = declbinder.BindNamespaceOrTypeSymbol(name, diagnostics, basesBeingResolved);
                                        if (imported.Kind == SymbolKind.Namespace)
                                        {
                                            AddNs(usingDirective, imported, usings, uniqueUsings);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                return(true);
            }
            return(false);
        }
    }
Beispiel #17
0
        private ImmutableArray <Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol containerOpt, string memberName, int arity, bool hasParameterList, ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            // Since we may find symbols without going through the lookup API,
            // expose the symbols via an ArrayBuilder.
            ArrayBuilder <Symbol> builder;

            {
                LookupResult result = LookupResult.GetInstance();
                this.LookupSymbolsOrMembersInternal(
                    result,
                    containerOpt,
                    name: memberName,
                    arity: arity,
                    basesBeingResolved: null,
                    options: LookupOptions.AllMethodsOnArityZero,
                    diagnose: false,
                    useSiteDiagnostics: ref useSiteDiagnostics);

                // CONSIDER: Dev11 also checks for a constructor in the event of an ambiguous result.
                if (result.IsMultiViable)
                {
                    // Dev11 doesn't consider members from System.Object when the container is an interface.
                    // Lookup should already have dropped such members.
                    builder = ArrayBuilder <Symbol> .GetInstance();

                    builder.AddRange(result.Symbols);
                    result.Free();
                }
                else
                {
                    result.Free(); // Won't be using this.

                    // Dev11 has a complicated two-stage process for determining when a cref is really referring to a constructor.
                    // Under two sets of conditions, XmlDocCommentBinder::bindXMLReferenceName will decide that a name refers
                    // to a constructor and under one set of conditions, the calling method, XmlDocCommentBinder::bindXMLReference,
                    // will roll back that decision and return null.

                    // In XmlDocCommentBinder::bindXMLReferenceName:
                    //   1) If an unqualified, non-generic name didn't bind to anything and the name matches the name of the type
                    //      to which the doc comment is applied, then bind to a constructor.
                    //   2) If a qualified, non-generic name didn't bind to anything and the LHS of the qualified name is a type
                    //      with the same name, then bind to a constructor.

                    // Quoted from XmlDocCommentBinder::bindXMLReference:
                    //   Filtering out the case where specifying the name of a generic type without specifying
                    //   any arity returns a constructor. This case shouldn't return anything. Note that
                    //   returning the constructors was a fix for the wonky constructor behavior, but in order
                    //   to not introduce a regression and breaking change we return NULL in this case.
                    //   e.g.
                    //
                    //   /// <see cref="Foo"/>
                    //   class Foo<T> { }
                    //
                    //   This cref used not to bind to anything, because before it was looking for a type and
                    //   since there was no arity, it didn't find Foo<T>. Now however, it finds Foo<T>.ctor,
                    //   which is arguably correct, but would be a breaking change (albeit with minimal impact)
                    //   so we catch this case and chuck out the symbol found.

                    // In Roslyn, we're doing everything in one pass, rather than guessing and rolling back.

                    // As in the native compiler, we treat this as a fallback case - something that actually has the
                    // specified name is preferred.

                    NamedTypeSymbol constructorType = null;

                    if (arity == 0) // Member arity
                    {
                        NamedTypeSymbol containerType = containerOpt as NamedTypeSymbol;
                        if ((object)containerType != null)
                        {
                            // Case 1: If the name is qualified by a type with the same name, then we want a
                            // constructor (unless the type is generic, the cref is on/in the type (but not
                            // on/in a nested type), and there were no parens after the member name).

                            if (containerType.Name == memberName && (hasParameterList || containerType.Arity == 0 || this.ContainingType != containerType.OriginalDefinition))
                            {
                                constructorType = containerType;
                            }
                        }
                        else if ((object)containerOpt == null && hasParameterList)
                        {
                            // Case 2: If the name is not qualified by anything, but we're in the scope
                            // of a type with the same name (regardless of arity), then we want a constructor,
                            // as long as there were parens after the member name.

                            NamedTypeSymbol binderContainingType = this.ContainingType;
                            if ((object)binderContainingType != null && memberName == binderContainingType.Name)
                            {
                                constructorType = binderContainingType;
                            }
                        }
                    }

                    if ((object)constructorType != null)
                    {
                        ImmutableArray <MethodSymbol> instanceConstructors = constructorType.InstanceConstructors;
                        int numInstanceConstructors = instanceConstructors.Length;

                        if (numInstanceConstructors == 0)
                        {
                            return(ImmutableArray <Symbol> .Empty);
                        }

                        builder = ArrayBuilder <Symbol> .GetInstance(numInstanceConstructors);

                        builder.AddRange(instanceConstructors);
                    }
                    else
                    {
                        return(ImmutableArray <Symbol> .Empty);
                    }
                }
            }

            Debug.Assert(builder != null);

            // Since we resolve ambiguities by just picking the first symbol we encounter,
            // the order of the symbols matters for repeatability.
            if (builder.Count > 1)
            {
                builder.Sort(ConsistentSymbolOrder.Instance);
            }

            return(builder.ToImmutableAndFree());
        }
Beispiel #18
0
        internal void LookupSymbolInAliases(
            Binder originalBinder,
            LookupResult result,
            string name,
            int arity,
            ConsList <TypeSymbol> basesBeingResolved,
            LookupOptions options,
            bool diagnose,
            ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
            )
        {
            bool callerIsSemanticModel = originalBinder.IsSemanticModelBinder;

            AliasAndUsingDirective alias;

            if (this.UsingAliases.TryGetValue(name, out alias))
            {
                // Found a match in our list of normal aliases.  Mark the alias as being seen so that
                // it won't be reported to the user as something that can be removed.
                var res = originalBinder.CheckViability(
                    alias.Alias,
                    arity,
                    options,
                    null,
                    diagnose,
                    ref useSiteInfo,
                    basesBeingResolved
                    );
                if (res.Kind == LookupResultKind.Viable)
                {
                    MarkImportDirective(alias.UsingDirective, callerIsSemanticModel);
                }

                result.MergeEqual(res);
            }

            foreach (var a in this.ExternAliases)
            {
                if (a.Alias.Name == name)
                {
                    // Found a match in our list of extern aliases.  Mark the extern alias as being
                    // seen so that it won't be reported to the user as something that can be
                    // removed.
                    var res = originalBinder.CheckViability(
                        a.Alias,
                        arity,
                        options,
                        null,
                        diagnose,
                        ref useSiteInfo,
                        basesBeingResolved
                        );
                    if (res.Kind == LookupResultKind.Viable)
                    {
                        MarkImportDirective(a.ExternAliasDirective, callerIsSemanticModel);
                    }

                    result.MergeEqual(res);
                }
            }
        }
Beispiel #19
0
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result,
            string name,
            int arity,
            ConsList <TypeSymbol> basesBeingResolved,
            LookupOptions options,
            Binder originalBinder,
            bool diagnose,
            ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo
            )
        {
            Debug.Assert(result.IsClear);

            if (IsSubmissionClass)
            {
                this.LookupMembersInternal(
                    result,
                    _container,
                    name,
                    arity,
                    basesBeingResolved,
                    options,
                    originalBinder,
                    diagnose,
                    ref useSiteInfo
                    );
                return;
            }

            var imports = GetImports(basesBeingResolved);

            // first lookup members of the namespace
            if ((options & LookupOptions.NamespaceAliasesOnly) == 0 && _container != null)
            {
                this.LookupMembersInternal(
                    result,
                    _container,
                    name,
                    arity,
                    basesBeingResolved,
                    options,
                    originalBinder,
                    diagnose,
                    ref useSiteInfo
                    );

                if (result.IsMultiViable)
                {
                    // symbols cannot conflict with using alias names
                    if (
                        arity == 0 &&
                        imports.IsUsingAlias(name, originalBinder.IsSemanticModelBinder)
                        )
                    {
                        CSDiagnosticInfo diagInfo = new CSDiagnosticInfo(
                            ErrorCode.ERR_ConflictAliasAndMember,
                            name,
                            _container
                            );
                        var error = new ExtendedErrorTypeSymbol(
                            (NamespaceOrTypeSymbol)null,
                            name,
                            arity,
                            diagInfo,
                            unreported: true
                            );
                        result.SetFrom(LookupResult.Good(error)); // force lookup to be done w/ error symbol as result
                    }

                    return;
                }
            }

            // next try using aliases or symbols in imported namespaces
            imports.LookupSymbol(
                originalBinder,
                result,
                name,
                arity,
                basesBeingResolved,
                options,
                diagnose,
                ref useSiteInfo
                );
        }
        private void BindPCallAndDelegate(InvocationExpressionSyntax node, ArrayBuilder <BoundExpression> args,
                                          DiagnosticBag diagnostics, TypeSyntax type)
        {
            var    XNode  = node.XNode as XP.MethodCallContext;
            string method = XNode?.Expr.GetText();

            if (string.IsNullOrEmpty(method))
            {
                method = "PCALL";
            }
            if (!ValidatePCallArguments(node, args, diagnostics, method))
            {
                return;
            }
            var kind = args[0].Kind;

            if (kind != BoundKind.Local && kind != BoundKind.FieldAccess)
            {
                Error(diagnostics, ErrorCode.ERR_PCallFirstArgument, node, method, "typed function pointer");
                return;
            }
            string methodName = null;
            // Note that this does not get the syntax of the argument itself
            // but the syntax of the place where the symbol (Global, Field or Local) that the argument points to was defined
            SyntaxReference syntaxref = null;

            if (kind == BoundKind.FieldAccess)
            {
                var bfa = args[0] as BoundFieldAccess;  // Global or Field
                if (bfa != null && bfa.ExpressionSymbol.DeclaringSyntaxReferences.Length > 0)
                {
                    syntaxref = bfa.ExpressionSymbol.DeclaringSyntaxReferences[0] as SyntaxReference;
                }
            }
            else if (kind == BoundKind.Local)
            {
                var bl = args[0] as BoundLocal;         // Local
                if (bl != null && bl.LocalSymbol?.DeclaringSyntaxReferences.Length > 0)
                {
                    syntaxref = bl.LocalSymbol.DeclaringSyntaxReferences[0] as SyntaxReference;
                }
            }
            if (syntaxref != null)
            {
                CSharpSyntaxNode syntaxnode = syntaxref.GetSyntax() as CSharpSyntaxNode;
                var xNode = syntaxnode?.XNode;
                methodName = GetTypedPtrName(xNode);
            }

            if (methodName == null)
            {
                // first argument for pcall must be typed ptr
                Error(diagnostics, ErrorCode.ERR_PCallFirstArgument, node, method, "typed function pointer");
                return;
            }
            var lookupResult = LookupResult.GetInstance();
            HashSet <DiagnosticInfo> useSiteDiagnostics = null;
            LookupOptions            options            = LookupOptions.AllMethodsOnArityZero;

            options |= LookupOptions.MustNotBeInstance;
            this.LookupSymbolsWithFallback(lookupResult, methodName, arity: 0, useSiteDiagnostics: ref useSiteDiagnostics, options: options);
            SourceMethodSymbol methodSym = null;

            if (lookupResult.IsClear)
            {
                // Cannot locate types pointer for pcall
                Error(diagnostics, ErrorCode.ERR_PCallTypedPointerName, node, method, methodName);
                methodSym = null;
            }
            else if (lookupResult.IsMultiViable)
            {
                foreach (var symbol in lookupResult.Symbols)
                {
                    if (symbol.DeclaringCompilation == this.Compilation && symbol is SourceMethodSymbol)
                    {
                        methodSym = (SourceMethodSymbol)symbol;
                        break;
                    }
                }
            }
            else
            {
                methodSym = (SourceMethodSymbol)lookupResult.Symbols[0];
            }
            if (methodSym != null)
            {
                lookupResult.Clear();
                var ts = FindPCallDelegateType(type as IdentifierNameSyntax);
                if (ts != null && ts.IsDelegateType())
                {
                    SourceDelegateMethodSymbol delmeth = ts.DelegateInvokeMethod() as SourceDelegateMethodSymbol;
                    // clone the parameters from the methodSym
                    var builder = ArrayBuilder <ParameterSymbol> .GetInstance();

                    foreach (var par in methodSym.Parameters)
                    {
                        var parameter = new SourceSimpleParameterSymbol(
                            delmeth,
                            par.Type,
                            par.Ordinal,
                            par.RefKind,
                            par.Name,
                            par.Locations);
                        builder.Add(parameter);
                    }
                    delmeth.InitializeParameters(builder.ToImmutableAndFree());
                    delmeth.SetReturnType(methodSym.ReturnType);
                }
                else
                {
                    Error(diagnostics, ErrorCode.ERR_PCallResolveGeneratedDelegate, node, method, type.ToString());
                }
            }
            return;
        }
Beispiel #21
0
        internal void LookupSymbolInAliases(
            Binder originalBinder,
            LookupResult result,
            string name,
            int arity,
            ConsList<Symbol> basesBeingResolved,
            LookupOptions options,
            bool diagnose,
            ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            bool callerIsSemanticModel = originalBinder.IsSemanticModelBinder;

            AliasAndUsingDirective alias;
            if (this.UsingAliases != null && this.UsingAliases.TryGetValue(name, out alias))
            {
                // Found a match in our list of normal aliases.  Mark the alias as being seen so that
                // it won't be reported to the user as something that can be removed.
                var res = originalBinder.CheckViability(alias.Alias, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                if (res.Kind == LookupResultKind.Viable)
                {
                    MarkImportDirective(alias.UsingDirective, callerIsSemanticModel);
                }

                result.MergeEqual(res);
            }

            foreach (var a in this.ExternAliases)
            {
                if (a.Alias.Name == name)
                {
                    // Found a match in our list of extern aliases.  Mark the extern alias as being
                    // seen so that it won't be reported to the user as something that can be
                    // removed.
                    var res = originalBinder.CheckViability(a.Alias, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                    if (res.Kind == LookupResultKind.Viable)
                    {
                        MarkImportDirective(a.ExternAliasDirective, callerIsSemanticModel);
                    }

                    result.MergeEqual(res);
                }
            }
        }
Beispiel #22
0
        internal void LookupSymbolInUsings(
            ImmutableArray<NamespaceOrTypeAndUsingDirective> usings,
            Binder originalBinder,
            LookupResult result,
            string name,
            int arity,
            ConsList<Symbol> basesBeingResolved,
            LookupOptions options,
            bool diagnose,
            ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            bool callerIsSemanticModel = originalBinder.IsSemanticModelBinder;

            foreach (var typeOrNamespace in usings)
            {
                ImmutableArray<Symbol> candidates = Binder.GetCandidateMembers(typeOrNamespace.NamespaceOrType, name, options, originalBinder: originalBinder);
                foreach (Symbol symbol in candidates)
                {
                    // lookup via "using namespace" ignores namespaces inside
                    if (symbol.Kind != SymbolKind.Namespace)
                    {
                        // Found a match in our list of normal using directives.  Mark the directive
                        // as being seen so that it won't be reported to the user as something that
                        // can be removed.
                        var res = originalBinder.CheckViability(symbol, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                        if (res.Kind == LookupResultKind.Viable)
                        {
                            MarkImportDirective(typeOrNamespace.UsingDirective, callerIsSemanticModel);
                        }

                        result.MergeEqual(res);
                    }
                }
            }
        }
Beispiel #23
0
        internal static void LookupSymbolInUsings(
            ImmutableArray <NamespaceOrTypeAndUsingDirective> usings,
            Binder originalBinder,
            LookupResult result,
            string name,
            int arity,
            ConsList <Symbol> basesBeingResolved,
            LookupOptions options,
            bool diagnose,
            ref HashSet <DiagnosticInfo> useSiteDiagnostics)
        {
            if (originalBinder.Flags.Includes(BinderFlags.InScriptUsing))
            {
                return;
            }

            bool callerIsSemanticModel = originalBinder.IsSemanticModelBinder;

            foreach (var typeOrNamespace in usings)
            {
                ImmutableArray <Symbol> candidates = Binder.GetCandidateMembers(typeOrNamespace.NamespaceOrType, name, options, originalBinder: originalBinder);
                foreach (Symbol symbol in candidates)
                {
                    switch (symbol.Kind)
                    {
                    // lookup via "using namespace" ignores namespaces inside
                    case SymbolKind.Namespace:
                        continue;

                    // lookup via "using static" ignores extension methods and non-static methods
                    case SymbolKind.Method:
                        if (!symbol.IsStatic || ((MethodSymbol)symbol).IsExtensionMethod)
                        {
                            continue;
                        }

                        break;

                    // types are considered static members for purposes of "using static" feature
                    // regardless of whether they are declared with "static" modifier or not
                    case SymbolKind.NamedType:
                        break;

                    // lookup via "using static" ignores non-static members
                    default:
                        if (!symbol.IsStatic)
                        {
                            continue;
                        }

                        break;
                    }

                    // Found a match in our list of normal using directives.  Mark the directive
                    // as being seen so that it won't be reported to the user as something that
                    // can be removed.
                    var res = originalBinder.CheckViability(symbol, arity, options, null, diagnose, ref useSiteDiagnostics, basesBeingResolved);
                    if (res.Kind == LookupResultKind.Viable)
                    {
                        MarkImportDirective(originalBinder.Compilation, typeOrNamespace.UsingDirective, callerIsSemanticModel);
                    }

                    result.MergeEqual(res);
                }
            }
        }
 /// <summary>
 /// Set current result according to another.
 /// </summary>
 internal void SetFrom(LookupResult other)
 {
     this.kind = other.kind;
     this.symbolList.Clear();
     this.symbolList.AddRange(other.symbolList);
     this.error = other.error;
 }
Beispiel #25
0
        internal void LookupSymbol(
            Binder originalBinder,
            LookupResult result,
            string name,
            int arity,
            ConsList<Symbol> basesBeingResolved,
            LookupOptions options,
            bool diagnose,
            ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            LookupSymbolInAliases(originalBinder, result, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);

            if (!result.IsMultiViable && (options & LookupOptions.NamespaceAliasesOnly) == 0)
            {
                LookupSymbolInUsings(this.Usings, originalBinder, result, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);
            }
        }
        internal override void LookupSymbolsInSingleBinder(
            LookupResult result, string name, int arity, ConsList<Symbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
        {
            Debug.Assert(result.IsClear);

            if (_container.IsSubmissionClass)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);
                return;
            }

            var imports = GetImports(basesBeingResolved);

            // first lookup members of the namespace
            if ((options & LookupOptions.NamespaceAliasesOnly) == 0)
            {
                this.LookupMembersInternal(result, _container, name, arity, basesBeingResolved, options, originalBinder, diagnose, ref useSiteDiagnostics);

                if (result.IsMultiViable)
                {
                    // symbols cannot conflict with using alias names
                    if (arity == 0 && imports.IsUsingAlias(name, originalBinder.IsSemanticModelBinder))
                    {
                        CSDiagnosticInfo diagInfo = new CSDiagnosticInfo(ErrorCode.ERR_ConflictAliasAndMember, name, _container);
                        var error = new ExtendedErrorTypeSymbol((NamespaceOrTypeSymbol)null, name, arity, diagInfo, unreported: true);
                        result.SetFrom(LookupResult.Good(error)); // force lookup to be done w/ error symbol as result
                    }

                    return;
                }
            }

            // next try using aliases or symbols in imported namespaces
            imports.LookupSymbol(originalBinder, result, name, arity, basesBeingResolved, options, diagnose, ref useSiteDiagnostics);
        }
Beispiel #27
0
        /// <summary>
        /// Perform a lookup for the specified method on the specified type.  Perform overload resolution
        /// on the lookup results.
        /// </summary>
        /// <param name="patternType">Type to search.</param>
        /// <param name="methodName">Method to search for.</param>
        /// <param name="lookupResult">Passed in for reusability.</param>
        /// <param name="warningsOnly">True if failures should result in warnings; false if they should result in errors.</param>
        /// <param name="diagnostics">Populated with binding diagnostics.</param>
        /// <returns>The desired method or null.</returns>
        private MethodSymbol FindForEachPatternMethod(TypeSymbol patternType, string methodName, LookupResult lookupResult, bool warningsOnly, DiagnosticBag diagnostics)
        {
            Debug.Assert(lookupResult.IsClear);

            // Not using LookupOptions.MustBeInvocableMember because we don't want the corresponding lookup error.
            // We filter out non-methods below.
            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            this.LookupMembersInType(
                lookupResult,
                patternType,
                methodName,
                arity: 0,
                basesBeingResolved: null,
                options: LookupOptions.Default,
                originalBinder: this,
                diagnose: false,
                useSiteDiagnostics: ref useSiteDiagnostics);

            diagnostics.Add(_syntax.Expression, useSiteDiagnostics);

            if (!lookupResult.IsMultiViable)
            {
                ReportPatternMemberLookupDiagnostics(lookupResult, patternType, methodName, warningsOnly, diagnostics);
                return(null);
            }

            ArrayBuilder <MethodSymbol> candidateMethods = ArrayBuilder <MethodSymbol> .GetInstance();

            foreach (Symbol member in lookupResult.Symbols)
            {
                if (member.Kind != SymbolKind.Method)
                {
                    candidateMethods.Free();

                    if (warningsOnly)
                    {
                        ReportEnumerableWarning(diagnostics, patternType, member);
                    }
                    return(null);
                }

                MethodSymbol method = (MethodSymbol)member;

                // SPEC VIOLATION: The spec says we should apply overload resolution, but Dev10 uses
                // some custom logic in ExpressionBinder.BindGrpToParams.  The biggest difference
                // we've found (so far) is that it only considers methods with zero parameters
                // (i.e. doesn't work with "params" or optional parameters).
                if (!method.Parameters.Any())
                {
                    candidateMethods.Add((MethodSymbol)member);
                }
            }

            MethodSymbol patternMethod = PerformForEachPatternOverloadResolution(patternType, candidateMethods, warningsOnly, diagnostics);

            candidateMethods.Free();

            return(patternMethod);
        }