File: Symbols\Source\ThisParameterSymbol.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// 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;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal abstract class ThisParameterSymbolBase : ParameterSymbol
    {
        internal const string SymbolName = "this";
 
        public sealed override string Name => SymbolName;
 
        public sealed override bool IsDiscard => false;
 
        public sealed override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences
        {
            get { return ImmutableArray<SyntaxReference>.Empty; }
        }
 
        internal sealed override ConstantValue? ExplicitDefaultConstantValue
        {
            get { return null; }
        }
 
        internal sealed override bool IsMetadataOptional
        {
            get { return false; }
        }
 
        public sealed override bool IsParamsArray
        {
            get { return false; }
        }
 
        public sealed override bool IsParamsCollection
        {
            get { return false; }
        }
 
        internal sealed override bool IsIDispatchConstant
        {
            get { return false; }
        }
 
        internal sealed override bool IsIUnknownConstant
        {
            get { return false; }
        }
 
        internal sealed override bool IsCallerFilePath
        {
            get { return false; }
        }
 
        internal sealed override bool IsCallerLineNumber
        {
            get { return false; }
        }
 
        internal sealed override bool IsCallerMemberName
        {
            get { return false; }
        }
 
        internal sealed override int CallerArgumentExpressionParameterIndex
        {
            get { return -1; }
        }
 
        internal sealed override FlowAnalysisAnnotations FlowAnalysisAnnotations
        {
            get { return FlowAnalysisAnnotations.None; }
        }
 
        internal sealed override ImmutableHashSet<string> NotNullIfParameterNotNull
        {
            get { return ImmutableHashSet<string>.Empty; }
        }
 
        public sealed override int Ordinal
        {
            get { return -1; }
        }
 
        public sealed override ImmutableArray<CustomModifier> RefCustomModifiers
        {
            get { return ImmutableArray<CustomModifier>.Empty; }
        }
 
        public sealed override bool IsThis
        {
            get { return true; }
        }
 
        // "this" is never explicitly declared.
        public sealed override bool IsImplicitlyDeclared
        {
            get { return true; }
        }
 
        internal sealed override bool IsMetadataIn
        {
            get { return false; }
        }
 
        internal sealed override bool IsMetadataOut
        {
            get { return false; }
        }
 
        internal sealed override MarshalPseudoCustomAttributeData? MarshallingInformation
        {
            get { return null; }
        }
 
        internal sealed override ImmutableArray<int> InterpolatedStringHandlerArgumentIndexes => ImmutableArray<int>.Empty;
 
        internal sealed override bool HasInterpolatedStringHandlerArgumentError => false;
    }
 
    internal sealed class ThisParameterSymbol : ThisParameterSymbolBase
    {
        private readonly MethodSymbol? _containingMethod;
        private readonly TypeSymbol _containingType;
 
        internal ThisParameterSymbol(MethodSymbol forMethod) : this(forMethod, forMethod.ContainingType)
        {
        }
 
        internal ThisParameterSymbol(MethodSymbol? forMethod, TypeSymbol containingType)
        {
            Debug.Assert(containingType is not null);
            _containingMethod = forMethod;
            _containingType = containingType;
        }
 
        public override TypeWithAnnotations TypeWithAnnotations
            => TypeWithAnnotations.Create(_containingType, NullableAnnotation.NotAnnotated);
 
        public override RefKind RefKind
        {
            get
            {
                if (ContainingType?.TypeKind != TypeKind.Struct)
                {
                    return RefKind.None;
                }
 
                if (_containingMethod?.MethodKind == MethodKind.Constructor)
                {
                    return RefKind.Out;
                }
 
                if (_containingMethod?.IsEffectivelyReadOnly == true)
                {
                    return RefKind.In;
                }
 
                return RefKind.Ref;
            }
        }
 
        public override ImmutableArray<Location> Locations
        {
            get { return _containingMethod is not null ? _containingMethod.Locations : ImmutableArray<Location>.Empty; }
        }
 
        public override Symbol ContainingSymbol
        {
            get { return (Symbol?)_containingMethod ?? _containingType; }
        }
 
        internal override ScopedKind EffectiveScope
        {
            get
            {
                var scope = _containingType.IsStructType() ? ScopedKind.ScopedRef : ScopedKind.None;
                if (scope != ScopedKind.None &&
                    HasUnscopedRefAttribute &&
                    UseUpdatedEscapeRules)
                {
                    return ScopedKind.None;
                }
                return scope;
            }
        }
 
        internal override bool HasUnscopedRefAttribute
            => _containingMethod.HasUnscopedRefAttributeOnMethodOrProperty();
 
        internal sealed override bool UseUpdatedEscapeRules
            => _containingMethod?.UseUpdatedEscapeRules ?? _containingType.ContainingModule.UseUpdatedEscapeRules;
    }
}