File: Symbols\EECompilationContextMethod.cs
Web Access
Project: ..\..\..\src\ExpressionEvaluator\CSharp\Source\ExpressionCompiler\Microsoft.CodeAnalysis.CSharp.ExpressionCompiler.csproj (Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.ExpressionCompiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
 
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
    /// <summary>
    /// The purpose of this symbol is to represent the method that we are actually in during evaluation,
    /// e.g. a lambda method in a display class. That method is actually a method from a PE module and we want
    /// to use it as a context for binding in order to make sure that the name lookup and other context dependent
    /// binding operations work properly. However, if we the use a symbol imported from the PE,
    /// symbols for locals, lambdas and local functions that will be directly or indirectly parented to it
    /// during binding won't be able to locate their <see cref="Symbol.DeclaringCompilation"/>, which will break
    /// assumptions made in different parts of the compilation pipeline. 
    /// Instead we create this symbol that represents exactly the same method, but pretends that 
    /// it is declared by EE compilation and allows to return that compilation as <see cref="Symbol.DeclaringCompilation"/>
    /// for all child symbols created during EE compilation process for evaluation.
    /// </summary>
    internal sealed class EECompilationContextMethod : WrappedMethodSymbol
    {
        private readonly MethodSymbol _underlyingMethod;
        private readonly CSharpCompilation _compilation;
 
        private readonly ImmutableArray<TypeParameterSymbol> _typeParameters;
        private readonly ImmutableArray<ParameterSymbol> _parameters;
 
        public EECompilationContextMethod(CSharpCompilation compilation, MethodSymbol underlyingMethod)
        {
            Debug.Assert(underlyingMethod.IsDefinition);
 
            _compilation = compilation;
 
            var typeMap = underlyingMethod.ContainingType.TypeSubstitution ?? TypeMap.Empty;
            typeMap.WithAlphaRename(underlyingMethod, this, out _typeParameters);
 
            _underlyingMethod = underlyingMethod.ConstructIfGeneric(TypeArgumentsWithAnnotations);
            _parameters = SynthesizedParameterSymbol.DeriveParameters(_underlyingMethod, this);
        }
 
        public override MethodSymbol UnderlyingMethod => _underlyingMethod;
 
        public override ImmutableArray<TypeParameterSymbol> TypeParameters
        {
            get { return _typeParameters; }
        }
 
        public override ImmutableArray<TypeWithAnnotations> TypeArgumentsWithAnnotations
        {
            get { return GetTypeParametersAsTypeArguments(); }
        }
 
        public override ImmutableArray<ParameterSymbol> Parameters
        {
            get { return _parameters; }
        }
 
        public override TypeWithAnnotations ReturnTypeWithAnnotations => _underlyingMethod.ReturnTypeWithAnnotations;
 
        public override ImmutableArray<MethodSymbol> ExplicitInterfaceImplementations => ImmutableArray<MethodSymbol>.Empty;
 
        public override ImmutableArray<CustomModifier> RefCustomModifiers => _underlyingMethod.RefCustomModifiers;
 
        public override Symbol? AssociatedSymbol => _underlyingMethod.AssociatedSymbol;
 
        public override Symbol ContainingSymbol => _underlyingMethod.ContainingSymbol;
 
        internal override int CalculateLocalSyntaxOffset(int localPosition, SyntaxTree localTree)
        {
            return _underlyingMethod.CalculateLocalSyntaxOffset(localPosition, localTree);
        }
 
        internal override UnmanagedCallersOnlyAttributeData? GetUnmanagedCallersOnlyAttributeData(bool forceComplete)
        {
            return _underlyingMethod.GetUnmanagedCallersOnlyAttributeData(forceComplete);
        }
 
        internal override bool IsNullableAnalysisEnabled()
        {
            return _underlyingMethod.IsNullableAnalysisEnabled();
        }
 
        internal override CSharpCompilation DeclaringCompilation => _compilation;
 
        internal override bool TryGetThisParameter(out ParameterSymbol? thisParameter)
        {
            ParameterSymbol underlyingThisParameter;
            if (!_underlyingMethod.TryGetThisParameter(out underlyingThisParameter))
            {
                thisParameter = null;
                return false;
            }
 
            thisParameter = (object)underlyingThisParameter != null
                ? new ThisParameterSymbol(this)
                : null;
            return true;
        }
    }
}