File: Symbols\Source\SourceUserDefinedConversionSymbol.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.
 
#nullable disable
 
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
    internal sealed class SourceUserDefinedConversionSymbol : SourceUserDefinedOperatorSymbolBase
    {
        public static SourceUserDefinedConversionSymbol CreateUserDefinedConversionSymbol(
            SourceMemberContainerTypeSymbol containingType,
            Binder bodyBinder,
            ConversionOperatorDeclarationSyntax syntax,
            bool isNullableAnalysisEnabled,
            BindingDiagnosticBag diagnostics)
        {
            // Dev11 includes the explicit/implicit keyword, but we don't have a good way to include
            // Narrowing/Widening in VB and we want the languages to be consistent.
            var location = syntax.Type.Location;
            string name = OperatorFacts.OperatorNameFromDeclaration(syntax);
 
            if (name == WellKnownMemberNames.CheckedExplicitConversionName)
            {
                MessageID.IDS_FeatureCheckedUserDefinedOperators.CheckFeatureAvailability(diagnostics, syntax.CheckedKeyword);
            }
            else if (syntax.CheckedKeyword.IsKind(SyntaxKind.CheckedKeyword))
            {
                diagnostics.Add(ErrorCode.ERR_ImplicitConversionOperatorCantBeChecked, syntax.CheckedKeyword.GetLocation());
            }
 
            var interfaceSpecifier = syntax.ExplicitInterfaceSpecifier;
 
            TypeSymbol explicitInterfaceType;
            name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, name, diagnostics, out explicitInterfaceType, aliasQualifierOpt: out _);
 
            var methodKind = interfaceSpecifier == null
                ? MethodKind.Conversion
                : MethodKind.ExplicitInterfaceImplementation;
 
            return new SourceUserDefinedConversionSymbol(
                methodKind, containingType, explicitInterfaceType, name, location, syntax, isNullableAnalysisEnabled, diagnostics);
        }
 
        // NOTE: no need to call WithUnsafeRegionIfNecessary, since the signature
        // is bound lazily using binders from a BinderFactory (which will already include an
        // UnsafeBinder, if necessary).
        private SourceUserDefinedConversionSymbol(
            MethodKind methodKind,
            SourceMemberContainerTypeSymbol containingType,
            TypeSymbol explicitInterfaceType,
            string name,
            Location location,
            ConversionOperatorDeclarationSyntax syntax,
            bool isNullableAnalysisEnabled,
            BindingDiagnosticBag diagnostics) :
            base(
                methodKind,
                explicitInterfaceType,
                name,
                containingType,
                location,
                syntax,
                MakeDeclarationModifiers(methodKind, containingType.IsInterface, syntax, location, diagnostics),
                hasAnyBody: syntax.HasAnyBody(),
                isExpressionBodied: syntax.IsExpressionBodied(),
                isIterator: SyntaxFacts.HasYieldOperations(syntax.Body),
                isNullableAnalysisEnabled: isNullableAnalysisEnabled,
                diagnostics)
        {
            CheckForBlockAndExpressionBody(
                syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
 
            if (syntax.ParameterList.Parameters.Count != 1)
            {
                diagnostics.Add(ErrorCode.ERR_OvlUnaryOperatorExpected, syntax.ParameterList.GetLocation());
            }
 
            if (IsStatic && (IsAbstract || IsVirtual))
            {
                CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody: syntax.Body != null || syntax.ExpressionBody != null, diagnostics: diagnostics);
            }
 
            if (syntax.ExplicitInterfaceSpecifier != null)
                MessageID.IDS_FeatureStaticAbstractMembersInInterfaces.CheckFeatureAvailability(diagnostics, syntax.ExplicitInterfaceSpecifier);
        }
 
        internal ConversionOperatorDeclarationSyntax GetSyntax()
        {
            Debug.Assert(syntaxReferenceOpt != null);
            return (ConversionOperatorDeclarationSyntax)syntaxReferenceOpt.GetSyntax();
        }
 
        internal override ExecutableCodeBinder TryGetBodyBinder(BinderFactory binderFactoryOpt = null, bool ignoreAccessibility = false)
        {
            return TryGetBodyBinderFromSyntax(binderFactoryOpt, ignoreAccessibility);
        }
 
        protected override int GetParameterCountFromSyntax()
        {
            return GetSyntax().ParameterList.ParameterCount;
        }
 
        protected override Location ReturnTypeLocation
        {
            get
            {
                return GetSyntax().Type.Location;
            }
        }
 
        internal override bool GenerateDebugInfo
        {
            get { return true; }
        }
 
        internal sealed override OneOrMany<SyntaxList<AttributeListSyntax>> GetAttributeDeclarations()
        {
            return OneOrMany.Create(this.GetSyntax().AttributeLists);
        }
 
        protected override (TypeWithAnnotations ReturnType, ImmutableArray<ParameterSymbol> Parameters) MakeParametersAndBindReturnType(BindingDiagnosticBag diagnostics)
        {
            ConversionOperatorDeclarationSyntax declarationSyntax = GetSyntax();
            return MakeParametersAndBindReturnType(declarationSyntax, declarationSyntax.Type, diagnostics);
        }
    }
}