WithLambdaParametersBinder.cs 6.8 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2 3 4

using System;
using System.Collections.Generic;
5
using System.Collections.Immutable;
P
Pilchie 已提交
6 7 8 9 10 11 12 13 14 15 16
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp
{
    internal class WithLambdaParametersBinder : LocalScopeBinder
    {
        protected readonly LambdaSymbol lambdaSymbol;
        protected readonly MultiDictionary<string, ParameterSymbol> parameterMap;
17
        private SmallDictionary<string, ParameterSymbol> _definitionMap;
P
Pilchie 已提交
18 19

        public WithLambdaParametersBinder(LambdaSymbol lambdaSymbol, Binder enclosing)
20
            : base(enclosing)
P
Pilchie 已提交
21 22 23
        {
            this.lambdaSymbol = lambdaSymbol;
            this.parameterMap = new MultiDictionary<string, ParameterSymbol>();
24 25 26

            var parameters = lambdaSymbol.Parameters;
            if (!parameters.IsDefaultOrEmpty)
P
Pilchie 已提交
27
            {
28 29 30 31 32 33 34 35 36 37
                RecordDefinitions(parameters);
                foreach (var parameter in lambdaSymbol.Parameters)
                {
                    this.parameterMap.Add(parameter.Name, parameter);
                }
            }
        }

        private void RecordDefinitions(ImmutableArray<ParameterSymbol> definitions)
        {
38
            var declarationMap = _definitionMap ?? (_definitionMap = new SmallDictionary<string, ParameterSymbol>());
39 40 41 42 43 44
            foreach (var s in definitions)
            {
                if (!declarationMap.ContainsKey(s.Name))
                {
                    declarationMap.Add(s.Name, s);
                }
P
Pilchie 已提交
45 46 47
            }
        }

48
        protected override TypeSymbol GetCurrentReturnType(out RefKind refKind)
P
Pilchie 已提交
49
        {
50
            refKind = lambdaSymbol.RefKind;
51
            return lambdaSymbol.ReturnType;
P
Pilchie 已提交
52 53 54 55 56 57 58 59 60 61
        }

        internal override Symbol ContainingMemberOrLambda
        {
            get
            {
                return this.lambdaSymbol;
            }
        }

62 63
        internal override bool IsNestedFunctionBinder => true;

P
Pilchie 已提交
64 65 66 67 68 69 70 71 72 73
        internal override bool IsDirectlyInIterator
        {
            get
            {
                return false;
            }
        }

        // NOTE: Specifically not overriding IsIndirectlyInIterator.

74
        internal override TypeWithAnnotations GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
P
Pilchie 已提交
75
        {
P
pgavlin 已提交
76 77 78 79
            if (node != null)
            {
                diagnostics.Add(ErrorCode.ERR_YieldInAnonMeth, node.YieldKeyword.GetLocation());
            }
80
            return TypeWithAnnotations.Create(CreateErrorType());
P
Pilchie 已提交
81 82
        }

83
        internal override void LookupSymbolsInSingleBinder(
84
            LookupResult result, string name, int arity, ConsList<TypeSymbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref HashSet<DiagnosticInfo> useSiteDiagnostics)
P
Pilchie 已提交
85 86 87
        {
            Debug.Assert(result.IsClear);

P
pgavlin 已提交
88
            if ((options & LookupOptions.NamespaceAliasesOnly) != 0)
P
Pilchie 已提交
89
            {
P
pgavlin 已提交
90
                return;
P
Pilchie 已提交
91
            }
P
pgavlin 已提交
92 93

            foreach (var parameterSymbol in parameterMap[name])
P
Pilchie 已提交
94
            {
P
pgavlin 已提交
95
                result.MergeEqual(originalBinder.CheckViability(parameterSymbol, arity, options, null, diagnose, ref useSiteDiagnostics));
P
Pilchie 已提交
96 97 98 99 100 101 102 103 104
            }
        }

        protected override void AddLookupSymbolsInfoInSingleBinder(LookupSymbolsInfo result, LookupOptions options, Binder originalBinder)
        {
            if (options.CanConsiderMembers())
            {
                foreach (var parameter in lambdaSymbol.Parameters)
                {
105
                    if (originalBinder.CanAddLookupSymbolInfo(parameter, options, result, null))
P
Pilchie 已提交
106 107 108 109 110 111
                    {
                        result.AddSymbol(parameter, parameter.Name, 0);
                    }
                }
            }
        }
112

C
Charles Stoner 已提交
113
        private static bool ReportConflictWithParameter(ParameterSymbol parameter, Symbol newSymbol, string name, Location newLocation, DiagnosticBag diagnostics)
114
        {
C
Charles Stoner 已提交
115 116
            var oldLocation = parameter.Locations[0];
            if (oldLocation == newLocation)
117 118 119 120 121 122 123 124
            {
                // a query variable and its corresponding lambda parameter, for example
                return false;
            }

            // Quirk of the way we represent lambda parameters.                
            SymbolKind newSymbolKind = (object)newSymbol == null ? SymbolKind.Parameter : newSymbol.Kind;

C
Charles Stoner 已提交
125
            switch (newSymbolKind)
P
pgavlin 已提交
126
            {
C
Charles Stoner 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
                case SymbolKind.ErrorType:
                    return true;

                case SymbolKind.Parameter:
                case SymbolKind.Local:
                    // Error: A local or parameter named '{0}' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
                    diagnostics.Add(ErrorCode.ERR_LocalIllegallyOverrides, newLocation, name);
                    return true;

                case SymbolKind.Method:
                    // Local function declaration name conflicts are not reported, for backwards compatibility.
                    return false;

                case SymbolKind.TypeParameter:
                    // Type parameter declaration name conflicts are not reported, for backwards compatibility.
                    return false;

                case SymbolKind.RangeVariable:
                    // The range variable '{0}' conflicts with a previous declaration of '{0}'
                    diagnostics.Add(ErrorCode.ERR_QueryRangeVariableOverrides, newLocation, name);
                    return true;
148 149 150
            }

            Debug.Assert(false, "what else could be defined in a lambda?");
151
            diagnostics.Add(ErrorCode.ERR_InternalError, newLocation);
152 153 154 155 156 157
            return false;
        }

        internal override bool EnsureSingleDefinition(Symbol symbol, string name, Location location, DiagnosticBag diagnostics)
        {
            ParameterSymbol existingDeclaration;
158
            var map = _definitionMap;
159 160 161 162 163 164 165
            if (map != null && map.TryGetValue(name, out existingDeclaration))
            {
                return ReportConflictWithParameter(existingDeclaration, symbol, name, location, diagnostics);
            }

            return false;
        }
166

C
CyrusNajmabadi 已提交
167
        internal override ImmutableArray<LocalSymbol> GetDeclaredLocalsForScope(SyntaxNode scopeDesignator)
168 169 170 171 172 173 174 175
        {
            throw ExceptionUtilities.Unreachable;
        }

        internal override ImmutableArray<LocalFunctionSymbol> GetDeclaredLocalFunctionsForScope(CSharpSyntaxNode scopeDesignator)
        {
            throw ExceptionUtilities.Unreachable;
        }
V
vsadov 已提交
176 177

        internal override uint LocalScopeDepth => Binder.TopLevelScope;
P
Pilchie 已提交
178
    }
P
pgavlin 已提交
179
}