Beispiel #1
0
        internal EEMethodBinder(EEMethodSymbol method, MethodSymbol containingMethod, Binder next) : base(next)
        {
            // There are a lot of method symbols floating around and we're doing some subtle things with them.
            //   1) method is the EEMethodSymbol that we're going to synthesize and hand to the debugger to evaluate.
            //   2) containingMethod is the method that we are conceptually in, e.g. the method containing the
            //      lambda that is on top of the call stack.  Any type parameters will have been replaced with the
            //      corresponding type parameters from (1) and its containing type.
            //   3) method.SubstitutedSourceMethod is the method that we are actually in, e.g. a lambda method in
            //      a display class.  Any type parameters will have been replaced with the corresponding type parameters
            //      from (1).
            // So why do we need all these methods?
            //   1) gives us the parameters that we need to actually bind to (it's no good to bind to the symbols
            //      owned by (2) or (3)).  Also, it happens to contain (3), so we don't need to pass (3) explicitly.
            //   2) is where we want to pretend we're binding expressions, so we make it the containing symbol of
            //      this binder.
            //   3) is where we'll pretend to be for the purposes of looking up parameters by name.  However, any
            //      parameters we bind to from (3) will be replaced by the corresponding parameters from (1).

            _containingMethod = containingMethod;
            var substitutedSourceMethod = method.SubstitutedSourceMethod;

            _parameterOffset  = substitutedSourceMethod.IsStatic ? 0 : 1;
            _targetParameters = method.Parameters;
            _sourceBinder     = new InMethodBinder(substitutedSourceMethod, new BuckStopsHereBinder(next.Compilation));
        }
        internal EEMethodBinder(EEMethodSymbol method, MethodSymbol containingMethod, Binder next) : base(next)
        {
            // There are a lot of method symbols floating around and we're doing some subtle things with them.
            //   1) method is the EEMethodSymbol that we're going to synthesize and hand to the debugger to evaluate.
            //   2) containingMethod is the method that we are conceptually in, e.g. the method containing the
            //      lambda that is on top of the call stack.  Any type parameters will have been replaced with the
            //      corresponding type parameters from (1) and its containing type.
            //   3) method.SubstitutedSourceMethod is the method that we are actually in, e.g. a lambda method in
            //      a display class.  Any type parameters will have been replaced with the corresponding type parameters
            //      from (1).
            // So why do we need all these methods?
            //   1) gives us the parameters that we need to actually bind to (it's no good to bind to the symbols 
            //      owned by (2) or (3)).  Also, it happens to contain (3), so we don't need to pass (3) explicitly.
            //   2) is where we want to pretend we're binding expressions, so we make it the containing symbol of
            //      this binder.
            //   3) is where we'll pretend to be for the purposes of looking up parameters by name.  However, any
            //      parameters we bind to from (3) will be replaced by the corresponding parameters from (1).

            _containingMethod = containingMethod;
            var substitutedSourceMethod = method.SubstitutedSourceMethod;
            _parameterOffset = substitutedSourceMethod.IsStatic ? 0 : 1;
            _targetParameters = method.Parameters;
            _sourceBinder = new InMethodBinder(substitutedSourceMethod, new BuckStopsHereBinder(next.Compilation));
        }
Beispiel #3
0
        private static Binder ExtendBinderChain(
            CSharpSyntaxNode syntax,
            ImmutableArray<Alias> aliases,
            EEMethodSymbol method,
            Binder binder,
            bool hasDisplayClassThis,
            bool methodNotType)
        {
            var substitutedSourceMethod = GetSubstitutedSourceMethod(method.SubstitutedSourceMethod, hasDisplayClassThis);
            var substitutedSourceType = substitutedSourceMethod.ContainingType;

            var stack = ArrayBuilder<NamedTypeSymbol>.GetInstance();
            for (var type = substitutedSourceType; (object)type != null; type = type.ContainingType)
            {
                stack.Add(type);
            }

            while (stack.Count > 0)
            {
                substitutedSourceType = stack.Pop();

                binder = new InContainerBinder(substitutedSourceType, binder);
                if (substitutedSourceType.Arity > 0)
                {
                    binder = new WithTypeArgumentsBinder(substitutedSourceType.TypeArguments, binder);
                }
            }

            stack.Free();

            if (substitutedSourceMethod.Arity > 0)
            {
                binder = new WithTypeArgumentsBinder(substitutedSourceMethod.TypeArguments, binder);
            }

            if (methodNotType)
            {
                // Method locals and parameters shadow pseudo-variables.
                var typeNameDecoder = new EETypeNameDecoder(binder.Compilation, (PEModuleSymbol)substitutedSourceMethod.ContainingModule);
                binder = new PlaceholderLocalBinder(
                    syntax,
                    aliases,
                    method,
                    typeNameDecoder,
                    binder);
            }

            binder = new EEMethodBinder(method, substitutedSourceMethod, binder);

            if (methodNotType)
            {
                binder = new SimpleLocalScopeBinder(method.LocalsForBinding, binder);
            }

            return binder;
        }
Beispiel #4
0
        private static Binder ExtendBinderChain(
            CSharpSyntaxNode syntax,
            ImmutableArray<Alias> aliases,
            EEMethodSymbol method,
            Binder binder,
            bool hasDisplayClassThis,
            bool methodNotType,
            out ImmutableArray<LocalSymbol> declaredLocals)
        {
            var substitutedSourceMethod = GetSubstitutedSourceMethod(method.SubstitutedSourceMethod, hasDisplayClassThis);
            var substitutedSourceType = substitutedSourceMethod.ContainingType;

            var stack = ArrayBuilder<NamedTypeSymbol>.GetInstance();
            for (var type = substitutedSourceType; (object)type != null; type = type.ContainingType)
            {
                stack.Add(type);
            }

            while (stack.Count > 0)
            {
                substitutedSourceType = stack.Pop();

                binder = new InContainerBinder(substitutedSourceType, binder);
                if (substitutedSourceType.Arity > 0)
                {
                    binder = new WithTypeArgumentsBinder(substitutedSourceType.TypeArguments, binder);
                }
            }

            stack.Free();

            if (substitutedSourceMethod.Arity > 0)
            {
                binder = new WithTypeArgumentsBinder(substitutedSourceMethod.TypeArguments, binder);
            }

            // Method locals and parameters shadow pseudo-variables.
            // That is why we place PlaceholderLocalBinder and ExecutableCodeBinder before EEMethodBinder.
            if (methodNotType)
            {
                var typeNameDecoder = new EETypeNameDecoder(binder.Compilation, (PEModuleSymbol)substitutedSourceMethod.ContainingModule);
                binder = new PlaceholderLocalBinder(
                    syntax,
                    aliases,
                    method,
                    typeNameDecoder,
                    binder);
            }

            Binder originalRootBinder = null;
            SyntaxNode declaredLocalsScopeDesignator = null;
            var executableBinder = new ExecutableCodeBinder(syntax, substitutedSourceMethod, binder,
                                              (rootBinder, declaredLocalsScopeDesignatorOpt) =>
                                              {
                                                  originalRootBinder = rootBinder;
                                                  declaredLocalsScopeDesignator = declaredLocalsScopeDesignatorOpt;
                                                  binder = new EEMethodBinder(method, substitutedSourceMethod, rootBinder);

                                                  if (methodNotType)
                                                  {
                                                      binder = new SimpleLocalScopeBinder(method.LocalsForBinding, binder);
                                                  }

                                                  return binder;
                                              });

            // We just need to trigger the process of building the binder map
            // so that the lambda above was executed.
            executableBinder.GetBinder(syntax);

            Debug.Assert(originalRootBinder != null);
            Debug.Assert(executableBinder.Next != binder);

            if (declaredLocalsScopeDesignator != null)
            {
                declaredLocals = originalRootBinder.GetDeclaredLocalsForScope(declaredLocalsScopeDesignator);
            }
            else
            {
                declaredLocals = ImmutableArray<LocalSymbol>.Empty;
            }

            return binder;
        }