示例#1
0
        private SourcePropertyAccessorSymbol(
            NamedTypeSymbol containingType,
            string name,
            SourcePropertySymbol property,
            DeclarationModifiers propertyModifiers,
            ImmutableArray <MethodSymbol> explicitInterfaceImplementations,
            Location location,
            ArrowExpressionClauseSyntax syntax,
            bool isExplicitInterfaceImplementation,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), location)
        {
            _property = property;
            _explicitInterfaceImplementations = explicitInterfaceImplementations;
            _name = name;
            _isAutoPropertyAccessor = false;
            _isExpressionBodied     = true;

            // The modifiers for the accessor are the same as the modifiers for the property,
            // minus the indexer and readonly bit
            var declarationModifiers = GetAccessorModifiers(propertyModifiers);

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

            CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody: true, diagnostics: diagnostics);
            CheckModifiersForBody(syntax, location, diagnostics);

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

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

            this.CheckModifiers(location, hasBody: true, isAutoPropertyOrExpressionBodied: true, diagnostics: 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;
                }
            }
        }
示例#2
0
        private SourceConstructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            ConstructorDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), ImmutableArray.Create(location))
        {
            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, location, diagnostics, out modifierErrors);

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

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

            bool hasBlockBody = syntax.Body != null;

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

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

                if (hasBlockBody || _isExpressionBodied)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

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

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

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

            CheckForBlockAndExpressionBody(
                syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
        }
示例#3
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);
            }
        }
        private SourceConstructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            ConstructorDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), syntax.Body?.GetReference(), ImmutableArray.Create(location))
        {
            bool modifierErrors;
            var  declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, location, diagnostics, out modifierErrors);

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

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

                if (syntax.Body != null)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

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

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

            if (!modifierErrors)
            {
                this.CheckModifiers(methodKind, location, diagnostics);
            }
        }
示例#5
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);
        }
示例#6
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);
        }
        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);
            }
        }
示例#8
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;
            }
        }
        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;
                }
            }
        }
        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);
            }
        }
示例#12
0
 protected void CheckAccessibility(BindingDiagnosticBag diagnostics)
 {
     ModifierUtils.CheckAccessibility(Modifiers, this, isExplicitInterfaceImplementation: false, diagnostics, ErrorLocation);
 }
示例#13
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);
            }
        }