예제 #1
0
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            bool isInterface   = this.ContainingType.IsInterface;
            var  defaultAccess = isInterface ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            var allowedModifiers = DeclarationModifiers.Partial | DeclarationModifiers.Unsafe;

            if (methodKind != MethodKind.ExplicitInterfaceImplementation)
            {
                allowedModifiers |= DeclarationModifiers.New;

                if (!isInterface)
                {
                    allowedModifiers |=
                        DeclarationModifiers.AccessibilityMask |
                        DeclarationModifiers.Sealed |
                        DeclarationModifiers.Abstract |
                        DeclarationModifiers.Static |
                        DeclarationModifiers.Virtual |
                        DeclarationModifiers.Override;
                }
            }

            if (!isInterface)
            {
                allowedModifiers |= DeclarationModifiers.Extern |
                                    DeclarationModifiers.Async;
            }

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(mods, diagnostics);

            mods = AddImpliedModifiers(mods, isInterface, methodKind);
            return(mods);
        }
예제 #2
0
 private static DeclarationModifiers AddImpliedModifiers(
     DeclarationModifiers mods,
     bool containingTypeIsInterface,
     MethodKind methodKind,
     bool hasBody
     )
 {
     // Let's overwrite modifiers for interface and explicit interface implementation methods with what they are supposed to be.
     // Proper errors must have been reported by now.
     if (containingTypeIsInterface)
     {
         mods = ModifierUtils.AdjustModifiersForAnInterfaceMember(
             mods,
             hasBody,
             methodKind == MethodKind.ExplicitInterfaceImplementation
             );
     }
     else if (methodKind == MethodKind.ExplicitInterfaceImplementation)
     {
         mods =
             (mods & ~DeclarationModifiers.AccessibilityMask) | DeclarationModifiers.Private;
     }
     return(mods);
 }
예제 #3
0
        private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, bool isExplicitInterfaceImplementation,
                                                   bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            // No default accessibility. If unset, accessibility
            // will be inherited from the property.
            const DeclarationModifiers defaultAccess = DeclarationModifiers.None;

            // Check that the set of modifiers is allowed
            var allowedModifiers = isExplicitInterfaceImplementation ? DeclarationModifiers.None : DeclarationModifiers.AccessibilityMask;
            var defaultInterfaceImplementationModifiers = DeclarationModifiers.None;

            if (this.ContainingType.IsInterface && !isExplicitInterfaceImplementation)
            {
                defaultInterfaceImplementationModifiers = DeclarationModifiers.AccessibilityMask;
            }

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
                                                                        defaultInterfaceImplementationModifiers,
                                                                        location, diagnostics);

            return(mods);
        }
        private DeclarationModifiers MakeModifiers(AccessorDeclarationSyntax syntax, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            // No default accessibility. If unset, accessibility
            // will be inherited from the property.
            const DeclarationModifiers defaultAccess = DeclarationModifiers.None;

            // Check that the set of modifiers is allowed
            const DeclarationModifiers allowedModifiers = DeclarationModifiers.AccessibilityMask;
            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            // For interface, check there are no accessibility modifiers.
            // (This check is handled outside of MakeAndCheckModifiers
            // since a distinct error message is reported for interfaces.)
            if (this.ContainingType.IsInterface)
            {
                if ((mods & DeclarationModifiers.AccessibilityMask) != 0)
                {
                    diagnostics.Add(ErrorCode.ERR_PropertyAccessModInInterface, location, this);
                    mods = (mods & ~DeclarationModifiers.AccessibilityMask);
                }
            }

            return(mods);
        }
예제 #5
0
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            var defaultAccess = (methodKind == MethodKind.StaticConstructor) ? DeclarationModifiers.None : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            const DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(mods, diagnostics);

            if (methodKind == MethodKind.StaticConstructor)
            {
                if ((mods & DeclarationModifiers.AccessibilityMask) != 0)
                {
                    diagnostics.Add(ErrorCode.ERR_StaticConstructorWithAccessModifiers, location, this);
                    mods           = mods & ~DeclarationModifiers.AccessibilityMask;
                    modifierErrors = true;
                }

                mods |= DeclarationModifiers.Private; // we mark static constructors private in the symbol table

                if (this.ContainingType.IsInterface)
                {
                    ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
                                                                                DeclarationModifiers.Extern,
                                                                                location, diagnostics);
                }
            }

            return(mods);
        }
예제 #6
0
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, bool explicitInterfaceImplementation,
                                                   bool isFieldLike, Location location,
                                                   DiagnosticBag diagnostics, out bool modifierErrors)
        {
            bool isInterface   = this.ContainingType.IsInterface;
            var  defaultAccess = isInterface && !explicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private;
            var  defaultInterfaceImplementationModifiers = DeclarationModifiers.None;

            // Check that the set of modifiers is allowed
            var allowedModifiers = DeclarationModifiers.Unsafe;

            if (!explicitInterfaceImplementation)
            {
                allowedModifiers |= DeclarationModifiers.New |
                                    DeclarationModifiers.Sealed |
                                    DeclarationModifiers.Abstract |
                                    DeclarationModifiers.Static |
                                    DeclarationModifiers.Virtual |
                                    DeclarationModifiers.AccessibilityMask;

                if (!isInterface)
                {
                    allowedModifiers |= DeclarationModifiers.Override;
                }
                else
                {
                    // This is needed to make sure we can detect 'public' modifier specified explicitly and
                    // check it against language version below.
                    defaultAccess = DeclarationModifiers.None;

                    allowedModifiers |= DeclarationModifiers.Extern;
                    defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
                                                               DeclarationModifiers.Abstract |
                                                               DeclarationModifiers.Static |
                                                               DeclarationModifiers.Virtual |
                                                               DeclarationModifiers.Extern |
                                                               DeclarationModifiers.AccessibilityMask;
                }
            }
            else if (isInterface)
            {
                Debug.Assert(explicitInterfaceImplementation);
                allowedModifiers |= DeclarationModifiers.Abstract;
            }

            if (this.ContainingType.IsStructType())
            {
                allowedModifiers |= DeclarationModifiers.ReadOnly;
            }

            if (!isInterface)
            {
                allowedModifiers |= DeclarationModifiers.Extern;
            }

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(mods, diagnostics);

            ModifierUtils.ReportDefaultInterfaceImplementationModifiers(!isFieldLike, mods,
                                                                        defaultInterfaceImplementationModifiers,
                                                                        location, diagnostics);

            // Let's overwrite modifiers for interface events with what they are supposed to be.
            // Proper errors must have been reported by now.
            if (isInterface)
            {
                mods = ModifierUtils.AdjustModifiersForAnInterfaceMember(mods, !isFieldLike, explicitInterfaceImplementation);
            }

            return(mods);
        }
예제 #7
0
        private SourcePropertyAccessorSymbol(
            NamedTypeSymbol containingType,
            string name,
            SourcePropertySymbol property,
            DeclarationModifiers propertyModifiers,
            ImmutableArray <MethodSymbol> explicitInterfaceImplementations,
            Location location,
            AccessorDeclarationSyntax syntax,
            MethodKind methodKind,
            bool isAutoPropertyAccessor,
            bool isExplicitInterfaceImplementation,
            DiagnosticBag diagnostics)
            : base(containingType,
                   syntax.GetReference(),
                   location)
        {
            _property = property;
            _explicitInterfaceImplementations = explicitInterfaceImplementations;
            _name = name;
            _isAutoPropertyAccessor = isAutoPropertyAccessor;
            Debug.Assert(!_property.IsExpressionBodied, "Cannot have accessors in expression bodied lightweight properties");
            var hasBody           = syntax.Body != null;
            var hasExpressionBody = syntax.ExpressionBody != null;

            _isExpressionBodied = !hasBody && hasExpressionBody;

            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(syntax, isExplicitInterfaceImplementation, hasBody || hasExpressionBody, location, diagnostics, out modifierErrors);

            // Include modifiers from the containing property.
            propertyModifiers &= ~DeclarationModifiers.AccessibilityMask;
            if ((declarationModifiers & DeclarationModifiers.Private) != 0)
            {
                // Private accessors cannot be virtual.
                propertyModifiers &= ~DeclarationModifiers.Virtual;
            }
            declarationModifiers |= propertyModifiers & ~DeclarationModifiers.Indexer;

            // ReturnsVoid property is overridden in this class so
            // returnsVoid argument to MakeFlags is ignored.
            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false,
                           isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any());

            CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody || hasExpressionBody, diagnostics);

            if (hasBody || hasExpressionBody)
            {
                CheckModifiersForBody(syntax, location, diagnostics);
            }

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (!modifierErrors)
            {
                this.CheckModifiers(location, hasBody || hasExpressionBody, isAutoPropertyAccessor, diagnostics);
            }

            if (this.IsOverride)
            {
                MethodSymbol overriddenMethod = this.OverriddenMethod;
                if ((object)overriddenMethod != null)
                {
                    // If this accessor is overriding a method from metadata, it is possible that
                    // the name of the overridden method doesn't follow the C# get_X/set_X pattern.
                    // We should copy the name so that the runtime will recognize this as an override.
                    _name = overriddenMethod.Name;
                }
            }

            CheckForBlockAndExpressionBody(
                syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
        }
예제 #8
0
        internal static DeclarationModifiers CheckModifiers(
            bool isForTypeDeclaration,
            bool isForInterfaceMember,
            DeclarationModifiers modifiers,
            DeclarationModifiers allowedModifiers,
            Location errorLocation,
            BindingDiagnosticBag diagnostics,
            SyntaxTokenList?modifierTokens,
            out bool modifierErrors)
        {
            Debug.Assert(!isForTypeDeclaration || !isForInterfaceMember);

            modifierErrors = false;
            DeclarationModifiers reportStaticNotVirtualForModifiers = DeclarationModifiers.None;

            if (isForTypeDeclaration)
            {
                Debug.Assert((allowedModifiers & (DeclarationModifiers.Override | DeclarationModifiers.Virtual)) == 0);
            }
            else if ((modifiers & allowedModifiers & DeclarationModifiers.Static) != 0)
            {
                if (isForInterfaceMember)
                {
                    reportStaticNotVirtualForModifiers = allowedModifiers & DeclarationModifiers.Override;
                }
                else
                {
                    reportStaticNotVirtualForModifiers = allowedModifiers & (DeclarationModifiers.Abstract | DeclarationModifiers.Override | DeclarationModifiers.Virtual);
                }

                allowedModifiers &= ~reportStaticNotVirtualForModifiers;
            }

            DeclarationModifiers errorModifiers = modifiers & ~allowedModifiers;
            DeclarationModifiers result         = modifiers & allowedModifiers;

            while (errorModifiers != DeclarationModifiers.None)
            {
                DeclarationModifiers oneError = errorModifiers & ~(errorModifiers - 1);
                Debug.Assert(oneError != DeclarationModifiers.None);
                errorModifiers = errorModifiers & ~oneError;

                switch (oneError)
                {
                case DeclarationModifiers.Partial:
                    // Provide a specialized error message in the case of partial.
                    ReportPartialError(errorLocation, diagnostics, modifierTokens);
                    break;

                case DeclarationModifiers.Abstract:
                case DeclarationModifiers.Override:
                case DeclarationModifiers.Virtual:
                    if ((reportStaticNotVirtualForModifiers & oneError) == 0)
                    {
                        goto default;
                    }

                    diagnostics.Add(ErrorCode.ERR_StaticNotVirtual, errorLocation, ModifierUtils.ConvertSingleModifierToSyntaxText(oneError));
                    break;

                default:
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, ConvertSingleModifierToSyntaxText(oneError));
                    break;
                }

                modifierErrors = true;
            }

            modifierErrors |= checkFeature(DeclarationModifiers.PrivateProtected, MessageID.IDS_FeaturePrivateProtected)
                              | checkFeature(DeclarationModifiers.Required, MessageID.IDS_FeatureRequiredMembers);

            if ((result & DeclarationModifiers.File) != 0)
            {
                modifierErrors |= !Binder.CheckFeatureAvailability(errorLocation.SourceTree, MessageID.IDS_FeatureFileTypes, diagnostics, errorLocation);
            }

            return(result);

            bool checkFeature(DeclarationModifiers modifier, MessageID featureID)
            => ((result & modifier) != 0) && !Binder.CheckFeatureAvailability(errorLocation.SourceTree, featureID, diagnostics, errorLocation);
        }
예제 #9
0
        internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingType, SyntaxToken firstIdentifier, SyntaxTokenList modifiers, bool isRefField, BindingDiagnosticBag diagnostics, out bool modifierErrors)
        {
            bool isInterface = containingType.IsInterface;
            DeclarationModifiers defaultAccess =
                isInterface ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Const |
                DeclarationModifiers.New |
                DeclarationModifiers.ReadOnly |
                DeclarationModifiers.Static |
                DeclarationModifiers.Volatile |
                DeclarationModifiers.Fixed |
                DeclarationModifiers.Unsafe |
                DeclarationModifiers.Abstract |
                DeclarationModifiers.Required; // Some of these are filtered out later, when illegal, for better error messages.

            var errorLocation           = new SourceLocation(firstIdentifier);
            DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                isOrdinaryMethod: false, isForInterfaceMember: isInterface,
                modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors);

            if ((result & DeclarationModifiers.Abstract) != 0)
            {
                diagnostics.Add(ErrorCode.ERR_AbstractField, errorLocation);
                result &= ~DeclarationModifiers.Abstract;
            }

            if ((result & DeclarationModifiers.Fixed) != 0)
            {
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Static, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.ReadOnly, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Const, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Required, diagnostics, errorLocation);

                result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile | DeclarationModifiers.Required);
                Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0);
            }

            if ((result & DeclarationModifiers.Const) != 0)
            {
                if ((result & DeclarationModifiers.Static) != 0)
                {
                    // The constant '{0}' cannot be marked static
                    diagnostics.Add(ErrorCode.ERR_StaticConstant, errorLocation, firstIdentifier.ValueText);
                }

                reportBadMemberFlagIfAny(result, DeclarationModifiers.ReadOnly, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Unsafe, diagnostics, errorLocation);

                if (reportBadMemberFlagIfAny(result, DeclarationModifiers.Required, diagnostics, errorLocation))
                {
                    result &= ~DeclarationModifiers.Required;
                }

                result |= DeclarationModifiers.Static; // "constants are considered static members"
            }
            else
            {
                if ((result & DeclarationModifiers.Static) != 0 && (result & DeclarationModifiers.Required) != 0)
                {
                    // The modifier 'required' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.RequiredKeyword));
                    result &= ~DeclarationModifiers.Required;
                }

                // NOTE: always cascading on a const, so suppress.
                // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol
                // to determine whether or not unsafe is allowed.  Since this symbol and the containing type are
                // in the same compilation, it won't make a difference.  We do, however, have to pass the error
                // location explicitly.
                containingType.CheckUnsafeModifier(result, errorLocation, diagnostics);
            }

            if (isRefField)
            {
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Static, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Const, diagnostics, errorLocation);
                reportBadMemberFlagIfAny(result, DeclarationModifiers.Volatile, diagnostics, errorLocation);
            }

            return(result);
예제 #10
0
        internal static DeclarationModifiers MakeModifiers(NamedTypeSymbol containingType, SyntaxToken firstIdentifier, SyntaxTokenList modifiers, DiagnosticBag diagnostics, out bool modifierErrors)
        {
            DeclarationModifiers defaultAccess =
                (containingType.IsInterface) ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Const |
                DeclarationModifiers.New |
                DeclarationModifiers.ReadOnly |
                DeclarationModifiers.Static |
                DeclarationModifiers.Volatile |
                DeclarationModifiers.Fixed |
                DeclarationModifiers.Unsafe |
                DeclarationModifiers.Abstract; // filtered out later

            var errorLocation           = new SourceLocation(firstIdentifier);
            DeclarationModifiers result = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiers, defaultAccess, allowedModifiers, errorLocation, diagnostics, out modifierErrors);

            if ((result & DeclarationModifiers.Abstract) != 0)
            {
                diagnostics.Add(ErrorCode.ERR_AbstractField, errorLocation);
                result &= ~DeclarationModifiers.Abstract;
            }

            if ((result & DeclarationModifiers.Fixed) != 0)
            {
                if ((result & DeclarationModifiers.Static) != 0)
                {
                    // The modifier 'static' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.StaticKeyword));
                }

                if ((result & DeclarationModifiers.ReadOnly) != 0)
                {
                    // The modifier 'readonly' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword));
                }

                if ((result & DeclarationModifiers.Const) != 0)
                {
                    // The modifier 'const' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ConstKeyword));
                }

                if ((result & DeclarationModifiers.Volatile) != 0)
                {
                    // The modifier 'volatile' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword));
                }

                result &= ~(DeclarationModifiers.Static | DeclarationModifiers.ReadOnly | DeclarationModifiers.Const | DeclarationModifiers.Volatile);
                Debug.Assert((result & ~(DeclarationModifiers.AccessibilityMask | DeclarationModifiers.Fixed | DeclarationModifiers.Unsafe | DeclarationModifiers.New)) == 0);
            }


            if ((result & DeclarationModifiers.Const) != 0)
            {
                if ((result & DeclarationModifiers.Static) != 0)
                {
                    // The constant '{0}' cannot be marked static
                    diagnostics.Add(ErrorCode.ERR_StaticConstant, errorLocation, firstIdentifier.ValueText);
                }

                if ((result & DeclarationModifiers.ReadOnly) != 0)
                {
                    // The modifier 'readonly' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.ReadOnlyKeyword));
                }

                if ((result & DeclarationModifiers.Volatile) != 0)
                {
                    // The modifier 'volatile' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.VolatileKeyword));
                }

                if ((result & DeclarationModifiers.Unsafe) != 0)
                {
                    // The modifier 'unsafe' is not valid for this item
                    diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, SyntaxFacts.GetText(SyntaxKind.UnsafeKeyword));
                }

                result |= DeclarationModifiers.Static; // "constants are considered static members"
            }
            else
            {
                // NOTE: always cascading on a const, so suppress.
                // NOTE: we're being a bit sneaky here - we're using the containingType rather than this symbol
                // to determine whether or not unsafe is allowed.  Since this symbol and the containing type are
                // in the same compilation, it won't make a difference.  We do, however, have to pass the error
                // location explicitly.
                containingType.CheckUnsafeModifier(result, errorLocation, diagnostics);
            }

            return(result);
        }
예제 #11
0
        protected SourceOrdinaryMethodSymbolBase(
            NamedTypeSymbol containingType,
            string name,
            Location location,
            CSharpSyntaxNode syntax,
            MethodKind methodKind,
            bool isIterator,
            bool isExtensionMethod,
            bool isPartial,
            bool hasBody,
            bool isNullableAnalysisEnabled,
            BindingDiagnosticBag diagnostics
            ) : base(containingType, syntax.GetReference(), location, isIterator: isIterator)
        {
            Debug.Assert(diagnostics.DiagnosticBag is object);

            _name = name;

            // The following two values are used to compute and store the initial value of the flags
            // However, these two components are placeholders; the correct value will be
            // computed lazily later and then the flags will be fixed up.
            const bool returnsVoid = false;

            DeclarationModifiers declarationModifiers;

            (declarationModifiers, HasExplicitAccessModifier) = this.MakeModifiers(
                methodKind,
                isPartial,
                hasBody,
                location,
                diagnostics
                );

            var isMetadataVirtualIgnoringModifiers =
                methodKind == MethodKind.ExplicitInterfaceImplementation; //explicit impls must be marked metadata virtual

            this.MakeFlags(
                methodKind,
                declarationModifiers,
                returnsVoid,
                isExtensionMethod: isExtensionMethod,
                isNullableAnalysisEnabled: isNullableAnalysisEnabled,
                isMetadataVirtualIgnoringModifiers: isMetadataVirtualIgnoringModifiers
                );

            _typeParameters = MakeTypeParameters(syntax, diagnostics);

            CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics);

            if (hasBody)
            {
                CheckModifiersForBody(location, diagnostics);
            }

            var info = ModifierUtils.CheckAccessibility(
                this.DeclarationModifiers,
                this,
                isExplicitInterfaceImplementation: methodKind
                == MethodKind.ExplicitInterfaceImplementation
                );

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }
        protected SourceUserDefinedOperatorSymbolBase(
            MethodKind methodKind,
            string name,
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            BaseMethodDeclarationSyntax syntax,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), location, isIterator: SyntaxFacts.HasYieldOperations(syntax.Body))
        {
            _name = name;
            _isExpressionBodied = syntax.Body == null && syntax.ExpressionBody != null;

            var defaultAccess    = DeclarationModifiers.Private;
            var allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            bool modifierErrors;
            var  declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                syntax.Modifiers, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(declarationModifiers, diagnostics);

            // We will bind the formal parameters and the return type lazily. For now,
            // assume that the return type is non-void; when we do the lazy initialization
            // of the parameters and return type we will update the flag if necessary.

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false);

            if (this.ContainingType.IsInterface &&
                (methodKind == MethodKind.Conversion || name == WellKnownMemberNames.EqualityOperatorName || name == WellKnownMemberNames.InequalityOperatorName))
            {
                // If we have a conversion or equality/inequality operator in an interface, we already have reported that fact as
                // an error. No need to cascade the error further.
                return;
            }

            if (this.ContainingType.IsStatic)
            {
                // Similarly if we're in a static class, though we have not reported it yet.

                // CS0715: '{0}': static classes cannot contain user-defined operators
                diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this);
                return;
            }

            // SPEC: An operator declaration must include both a public and a
            // SPEC: static modifier
            if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic)
            {
                // CS0558: User-defined operator '...' must be declared static and public
                diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this);
            }

            // SPEC: Because an external operator provides no actual implementation,
            // SPEC: its operator body consists of a semicolon. For expression-bodied
            // SPEC: operators, the body is an expression. For all other operators,
            // SPEC: the operator body consists of a block...
            bool hasBody = syntax.HasAnyBody();

            if (hasBody && IsExtern)
            {
                diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
            }
            else if (!hasBody && !IsExtern && !IsAbstract && !IsPartial)
            {
                // Do not report that the body is missing if the operator is marked as
                // partial or abstract; we will already have given an error for that so
                // there's no need to "cascade" the error.
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }

            // SPEC: It is an error for the same modifier to appear multiple times in an
            // SPEC: operator declaration.
            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation: false);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }
        private SourcePropertyAccessorSymbol(
            NamedTypeSymbol containingType,
            string name,
            SourcePropertySymbol property,
            DeclarationModifiers propertyModifiers,
            ImmutableArray <MethodSymbol> explicitInterfaceImplementations,
            Location location,
            AccessorDeclarationSyntax syntax,
            MethodKind methodKind,
            bool isAutoPropertyAccessor,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), syntax.Body.GetReferenceOrNull(), location)
        {
            this.property = property;
            this.explicitInterfaceImplementations = explicitInterfaceImplementations;
            this.name = name;
            this.isAutoPropertyAccessor = isAutoPropertyAccessor;

            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(syntax, location, diagnostics, out modifierErrors);

            // Include modifiers from the containing property.
            propertyModifiers &= ~DeclarationModifiers.AccessibilityMask;
            if ((declarationModifiers & DeclarationModifiers.Private) != 0)
            {
                // Private accessors cannot be virtual.
                propertyModifiers &= ~DeclarationModifiers.Virtual;
            }
            declarationModifiers |= propertyModifiers & ~DeclarationModifiers.Indexer;

            // ReturnsVoid property is overridden in this class so
            // returnsVoid argument to MakeFlags is ignored.
            this.flags = MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false,
                                   isMetadataVirtualIgnoringModifiers: explicitInterfaceImplementations.Any());

            var bodyOpt = syntax.Body;

            if (bodyOpt != null)
            {
                if (containingType.IsInterface)
                {
                    diagnostics.Add(ErrorCode.ERR_InterfaceMemberHasBody, location, this);
                }
                else if (IsExtern && !IsAbstract)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
                else if (IsAbstract && !IsExtern)
                {
                    diagnostics.Add(ErrorCode.ERR_AbstractHasBody, location, this);
                }
                // Do not report error for IsAbstract && IsExtern. Dev10 reports CS0180 only
                // in that case ("member cannot be both extern and abstract").
            }

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (!modifierErrors)
            {
                this.CheckModifiers(location, isAutoPropertyAccessor, diagnostics);
            }

            if (this.IsOverride)
            {
                MethodSymbol overriddenMethod = this.OverriddenMethod;
                if ((object)overriddenMethod != null)
                {
                    // If this accessor is overriding a method from metadata, it is possible that
                    // the name of the overridden method doesn't follow the C# get_X/set_X pattern.
                    // We should copy the name so that the runtime will recognize this as an override.
                    this.name = overriddenMethod.Name;
                }
            }
        }
예제 #14
0
        private DeclarationModifiers MakeModifiers(
            SyntaxTokenList modifiers,
            MethodKind methodKind,
            bool hasBody,
            Location location,
            BindingDiagnosticBag diagnostics,
            out bool modifierErrors
            )
        {
            var defaultAccess =
                (methodKind == MethodKind.StaticConstructor)
                    ? DeclarationModifiers.None
                    : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            const DeclarationModifiers allowedModifiers =
                DeclarationModifiers.AccessibilityMask
                | DeclarationModifiers.Static
                | DeclarationModifiers.Extern
                | DeclarationModifiers.Unsafe;

            var mods = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiers,
                defaultAccess,
                allowedModifiers,
                location,
                diagnostics,
                out modifierErrors
                );

            this.CheckUnsafeModifier(mods, diagnostics);

            if (methodKind == MethodKind.StaticConstructor)
            {
                // Don't report ERR_StaticConstructorWithAccessModifiers if the ctor symbol name doesn't match the containing type name.
                // This avoids extra unnecessary errors.
                // There will already be a diagnostic saying Method must have a return type.
                if (
                    (mods & DeclarationModifiers.AccessibilityMask) != 0 &&
                    ContainingType.Name
                    == ((ConstructorDeclarationSyntax)this.SyntaxNode).Identifier.ValueText
                    )
                {
                    diagnostics.Add(
                        ErrorCode.ERR_StaticConstructorWithAccessModifiers,
                        location,
                        this
                        );
                    mods           = mods & ~DeclarationModifiers.AccessibilityMask;
                    modifierErrors = true;
                }

                mods |= DeclarationModifiers.Private; // we mark static constructors private in the symbol table

                if (this.ContainingType.IsInterface)
                {
                    ModifierUtils.ReportDefaultInterfaceImplementationModifiers(
                        hasBody,
                        mods,
                        DeclarationModifiers.Extern,
                        location,
                        diagnostics
                        );
                }
            }

            return(mods);
        }
        private SourceOrdinaryMethodSymbol(
            NamedTypeSymbol containingType,
            TypeSymbol explicitInterfaceType,
            string name,
            Location location,
            MethodDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType,
                 syntax.GetReference(),
                 location)
        {
            _name = name;
            _explicitInterfaceType = explicitInterfaceType;

            SyntaxTokenList modifiers = syntax.Modifiers;

            // The following two values are used to compute and store the initial value of the flags
            // However, these two components are placeholders; the correct value will be
            // computed lazily later and then the flags will be fixed up.
            const bool returnsVoid = false;

            var  firstParam        = syntax.ParameterList.Parameters.FirstOrDefault();
            bool isExtensionMethod = firstParam != null &&
                                     !firstParam.IsArgList &&
                                     firstParam.Modifiers.Any(SyntaxKind.ThisKeyword);

            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors);

            var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers);

            if (syntax.Arity == 0)
            {
                _typeParameters = ImmutableArray <TypeParameterSymbol> .Empty;
                ReportErrorIfHasConstraints(syntax.ConstraintClauses, diagnostics);
            }
            else
            {
                _typeParameters = MakeTypeParameters(syntax, diagnostics);
            }

            bool hasBlockBody = syntax.Body != null;

            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;
            _hasAnyBody         = hasBlockBody || _isExpressionBodied;
            _refKind            = syntax.ReturnType.GetRefKind();

            if (_hasAnyBody)
            {
                CheckModifiersForBody(location, diagnostics);
            }

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            // When a generic method overrides a generic method declared in a base class, or is an
            // explicit interface member implementation of a method in a base interface, the method
            // shall not specify any type-parameter-constraints-clauses. In these cases, the type
            // parameters of the method inherit constraints from the method being overridden or
            // implemented
            if (syntax.ConstraintClauses.Count > 0)
            {
                if (syntax.ExplicitInterfaceSpecifier != null ||
                    syntax.Modifiers.Any(SyntaxKind.OverrideKeyword))
                {
                    diagnostics.Add(
                        ErrorCode.ERR_OverrideWithConstraints,
                        syntax.ConstraintClauses[0].WhereKeyword.GetLocation());
                }
            }

            CheckForBlockAndExpressionBody(
                syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
        }
        protected SourceUserDefinedOperatorSymbolBase(
            MethodKind methodKind,
            string name,
            // @MattWindsor91 (Concept-C# 2017)
            //
            // Default structs can contain these, so I've relaxed the class
            // requirement on 'containingType' to allow for this.
            //
            // A more robust approach to this would be to make a new symbol
            // for default user-defined operators and set this back to
            // SourceMemberContainerTypeSymbol.
            NamedTypeSymbol containingType,
            Location location,
            SyntaxReference syntaxReference,
            SyntaxReference bodySyntaxReference,
            SyntaxTokenList modifiersSyntax,
            DiagnosticBag diagnostics,
            bool isExpressionBodied) :
            base(containingType, syntaxReference, bodySyntaxReference, location)
        {
            _name = name;
            _isExpressionBodied = isExpressionBodied;

            var isConceptOperator = ContainingType.IsInstance || ContainingType.IsConcept || ContainingType.IsDefaultStruct;

            // @t-mawind (is this a good idea?)
            var defaultAccess    = isConceptOperator ? DeclarationModifiers.Public : DeclarationModifiers.Private;
            var allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            bool modifierErrors;
            var  declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiersSyntax, defaultAccess, allowedModifiers, location, diagnostics, out modifierErrors);

            this.CheckUnsafeModifier(declarationModifiers, diagnostics);

            if (ContainingType.IsConcept)
            {
                // @t-mawind Is there any easier way of doing this?
                declarationModifiers |= DeclarationModifiers.Abstract;
            }

            // We will bind the formal parameters and the return type lazily. For now,
            // assume that the return type is non-void; when we do the lazy initialization
            // of the parameters and return type we will update the flag if necessary.

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false);

            if (this.ContainingType.IsInterface && !this.ContainingType.IsConcept)
            {
                // If we have an operator in an interface, we already have reported that fact as
                // an error. No need to cascade the error further.
                return;
            }

            if (this.ContainingType.IsStatic)
            {
                // Similarly if we're in a static class, though we have not reported it yet.

                // CS0715: '{0}': static classes cannot contain user-defined operators
                diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this);
                return;
            }

            // @t-mawind
            //   Concept operators must be public and _non_-static.
            if (isConceptOperator)
            {
                if (DeclaredAccessibility != Accessibility.Public || IsStatic)
                {
                    // CS4038: User-defined concept operator '...' must be declared non-static and public.
                    diagnostics.Add(ErrorCode.ERR_ConceptOperatorsMustBeNonStatic, Locations[0], this);
                }
            }
            else
            {
                // SPEC: An operator declaration must include both a public and a
                // SPEC: static modifier
                if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic)
                {
                    // CS0558: User-defined operator '...' must be declared static and public
                    diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this);
                }
            }

            // SPEC: Because an external operator provides no actual implementation,
            // SPEC: its operator body consists of a semicolon. For expression-bodied
            // SPEC: operators, the body is an expression. For all other operators,
            // SPEC: the operator body consists of a block...
            if (bodySyntaxReference != null && IsExtern)
            {
                diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
            }
            else if (bodySyntaxReference == null && !IsExtern && !IsAbstract && !IsPartial)
            {
                // Do not report that the body is missing if the operator is marked as
                // partial or abstract; we will already have given an error for that so
                // there's no need to "cascade" the error.
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }

            // SPEC: It is an error for the same modifier to appear multiple times in an
            // SPEC: operator declaration.
            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }
예제 #17
0
        private (DeclarationModifiers mods, bool hasExplicitAccessMod) MakeModifiers(MethodKind methodKind, bool isPartial, bool hasBody, Location location, DiagnosticBag diagnostics)
        {
            bool isInterface = this.ContainingType.IsInterface;
            bool isExplicitInterfaceImplementation = methodKind == MethodKind.ExplicitInterfaceImplementation;
            var  defaultAccess = isInterface && isPartial && !isExplicitInterfaceImplementation ? DeclarationModifiers.Public : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
            var allowedModifiers = DeclarationModifiers.Partial | DeclarationModifiers.Unsafe;
            var defaultInterfaceImplementationModifiers = DeclarationModifiers.None;

            if (!isExplicitInterfaceImplementation)
            {
                allowedModifiers |= DeclarationModifiers.New |
                                    DeclarationModifiers.Sealed |
                                    DeclarationModifiers.Abstract |
                                    DeclarationModifiers.Static |
                                    DeclarationModifiers.Virtual |
                                    DeclarationModifiers.AccessibilityMask;

                if (!isInterface)
                {
                    allowedModifiers |= DeclarationModifiers.Override;
                }
                else
                {
                    // This is needed to make sure we can detect 'public' modifier specified explicitly and
                    // check it against language version below.
                    defaultAccess = DeclarationModifiers.None;

                    defaultInterfaceImplementationModifiers |= DeclarationModifiers.Sealed |
                                                               DeclarationModifiers.Abstract |
                                                               DeclarationModifiers.Static |
                                                               DeclarationModifiers.Virtual |
                                                               DeclarationModifiers.Extern |
                                                               DeclarationModifiers.Async |
                                                               DeclarationModifiers.Partial |
                                                               DeclarationModifiers.AccessibilityMask;
                }
            }
            else if (isInterface)
            {
                Debug.Assert(isExplicitInterfaceImplementation);
                allowedModifiers |= DeclarationModifiers.Abstract;
            }

            allowedModifiers |= DeclarationModifiers.Extern | DeclarationModifiers.Async;

            if (ContainingType.IsStructType())
            {
                allowedModifiers |= DeclarationModifiers.ReadOnly;
            }

            // In order to detect whether explicit accessibility mods were provided, we pass the default value
            // for 'defaultAccess' and manually add in the 'defaultAccess' flags after the call.
            bool hasExplicitAccessMod;
            DeclarationModifiers mods = MakeDeclarationModifiers(allowedModifiers, diagnostics);

            if ((mods & DeclarationModifiers.AccessibilityMask) == 0)
            {
                hasExplicitAccessMod = false;
                mods |= defaultAccess;
            }
            else
            {
                hasExplicitAccessMod = true;
            }

            this.CheckUnsafeModifier(mods, diagnostics);

            ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
                                                                        defaultInterfaceImplementationModifiers,
                                                                        location, diagnostics);

            mods = AddImpliedModifiers(mods, isInterface, methodKind, hasBody);
            return(mods, hasExplicitAccessMod);
        }
예제 #18
0
 protected void CheckAccessibility(BindingDiagnosticBag diagnostics)
 {
     ModifierUtils.CheckAccessibility(Modifiers, this, isExplicitInterfaceImplementation: false, diagnostics, ErrorLocation);
 }
예제 #19
0
        private SourceMemberMethodSymbol(
            NamedTypeSymbol containingType,
            TypeSymbol explicitInterfaceType,
            string name,
            Location location,
            MethodDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType,
                 syntax.GetReference(),
                 // Prefer a block body if both exist
                 syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(),
                 location)
        {
            _name = name;
            _explicitInterfaceType = explicitInterfaceType;

            SyntaxTokenList modifiers = syntax.Modifiers;

            // The following two values are used to compute and store the initial value of the flags
            // However, these two components are placeholders; the correct value will be
            // computed lazily later and then the flags will be fixed up.
            const bool returnsVoid = false;

            var  firstParam        = syntax.ParameterList.Parameters.FirstOrDefault();
            bool isExtensionMethod = firstParam != null &&
                                     !firstParam.IsArgList &&
                                     firstParam.Modifiers.Any(SyntaxKind.ThisKeyword);

            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors);

            var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers);

            // We, of course, have to deal with the possibility of the
            // type parameter list being null in MakeTypeParameters now.
            _typeParameters = (syntax.Arity == 0) ?
                              ImmutableArray <TypeParameterSymbol> .Empty :
                              MakeTypeParameters(syntax, diagnostics);

            bool hasBlockBody = syntax.Body != null;

            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;

            // @t-mawind
            //   If this method is on a concept and has a body, then we pretend
            //   it isn't there in various parts of this class, as it's meant for
            //   the default struct.
            //   First, we don't check modifiers for it here.
            if (!containingType.IsConcept && (hasBlockBody || _isExpressionBodied))
            {
                CheckModifiersForBody(location, diagnostics);
            }

            _refKind = syntax.RefKeyword.Kind().GetRefKind();

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }
예제 #20
0
        private SourceConstructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            ConstructorDeclarationSyntax syntax,
            MethodKind methodKind,
            bool isNullableAnalysisEnabled,
            BindingDiagnosticBag diagnostics
            ) : base(containingType, location, syntax, SyntaxFacts.HasYieldOperations(syntax))
        {
            bool hasBlockBody = syntax.Body != null;

            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;
            bool hasBody = hasBlockBody || _isExpressionBodied;

            _hasThisInitializer =
                syntax.Initializer?.Kind() == SyntaxKind.ThisConstructorInitializer;

            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(
                syntax.Modifiers,
                methodKind,
                hasBody,
                location,
                diagnostics,
                out modifierErrors
                );

            this.MakeFlags(
                methodKind,
                declarationModifiers,
                returnsVoid: true,
                isExtensionMethod: false,
                isNullableAnalysisEnabled: isNullableAnalysisEnabled
                );

            if (syntax.Identifier.ValueText != containingType.Name)
            {
                // This is probably a method declaration with the type missing.
                diagnostics.Add(ErrorCode.ERR_MemberNeedsType, location);
            }

            if (IsExtern)
            {
                if (methodKind == MethodKind.Constructor && syntax.Initializer != null)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasConstructorInitializer, location, this);
                }

                if (hasBody)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

            if (methodKind == MethodKind.StaticConstructor)
            {
                CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics);
            }

            var info = ModifierUtils.CheckAccessibility(
                this.DeclarationModifiers,
                this,
                isExplicitInterfaceImplementation: false
                );

            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (!modifierErrors)
            {
                this.CheckModifiers(methodKind, hasBody, location, diagnostics);
            }

            CheckForBlockAndExpressionBody(syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
        }
예제 #21
0
        private SourceMemberMethodSymbol(
            NamedTypeSymbol containingType,
            TypeSymbol explicitInterfaceType,
            string name,
            Location location,
            Binder bodyBinder,
            MethodDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType,
                 syntax.GetReference(),
                 // Prefer a block body if both exist
                 syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(),
                 location)
        {
            _name = name;
            _explicitInterfaceType = explicitInterfaceType;

            SyntaxTokenList modifiers = syntax.Modifiers;

            // The following two values are used to compute and store the initial value of the flags
            // However, these two components are placeholders; the correct value will be
            // computed lazily later and then the flags will be fixed up.
            const bool returnsVoid = false;

            var  firstParam        = syntax.ParameterList.Parameters.FirstOrDefault();
            bool isExtensionMethod = firstParam != null &&
                                     !firstParam.IsArgList &&
                                     firstParam.Modifiers.Any(SyntaxKind.ThisKeyword);

            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(modifiers, methodKind, location, diagnostics, out modifierErrors);

            var isMetadataVirtualIgnoringModifiers = (object)explicitInterfaceType != null; //explicit impls must be marked metadata virtual

            this.MakeFlags(methodKind, declarationModifiers, returnsVoid, isExtensionMethod, isMetadataVirtualIgnoringModifiers);

            // NOTE: by creating a WithMethodTypeParametersBinder, we are effectively duplicating the
            // functionality of the BinderFactory.  Unfortunately, we cannot use the BinderFactory
            // because it depends on having access to the member list of our containing type and
            // that list cannot be complete because we're not finished constructing this member.
            // TODO: at least keep this in sync with BinderFactory.VisitMethodDeclaration.
            bodyBinder = bodyBinder.WithUnsafeRegionIfNecessary(modifiers);

            Binder withTypeParamsBinder;

            if (syntax.Arity == 0)
            {
                withTypeParamsBinder = bodyBinder;
                _typeParameters      = ImmutableArray <TypeParameterSymbol> .Empty;
            }
            else
            {
                var parameterBinder = new WithMethodTypeParametersBinder(this, bodyBinder);
                withTypeParamsBinder = parameterBinder;
                _typeParameters      = MakeTypeParameters(syntax, diagnostics);
            }

            bool hasBlockBody = syntax.Body != null;

            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;

            if (hasBlockBody || _isExpressionBodied)
            {
                CheckModifiersForBody(location, diagnostics);
            }

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (this.IsPartial)
            {
                // Partial methods must be completed early because they are matched up
                // by signature while producing the enclosing type's member list. However,
                // that means any type parameter constraints will be bound before the method
                // is added to the containing type. To enable binding of constraints before the
                // .ctor completes we hold on to the current binder while the .ctor is executing.
                // If we change the handling of partial methods, so that partial methods are
                // completed lazily, the 'constraintClauseBinder' field should be removed.
                _constraintClauseBinder = withTypeParamsBinder;

                state.NotePartComplete(CompletionPart.StartMethodChecks);
                MethodChecks(syntax, withTypeParamsBinder, diagnostics);
                state.NotePartComplete(CompletionPart.FinishMethodChecks);
                _constraintClauseBinder = null;
            }
        }