예제 #1
0
        public static BasePropertyDeclarationSyntax WithExplicitInterfaceSpecifier(this BasePropertyDeclarationSyntax node, ExplicitInterfaceSpecifierSyntax syntax)
        {
            switch (node.Kind())
            {
            case SyntaxKind.IndexerDeclaration:
                return(((IndexerDeclarationSyntax)node).WithExplicitInterfaceSpecifier(syntax));

            case SyntaxKind.PropertyDeclaration:
                return((((PropertyDeclarationSyntax)node)).WithExplicitInterfaceSpecifier(syntax));
            }
            throw new NotImplementedException("WithExplicitInterfaceSpecifier " + node.Kind().ToString());
        }
예제 #2
0
        public static BasePropertyDeclarationSyntax WithModifiers(this BasePropertyDeclarationSyntax node, SyntaxTokenList modifiers)
        {
            switch (node.Kind())
            {
            case SyntaxKind.IndexerDeclaration:
                return(((IndexerDeclarationSyntax)node).WithModifiers(modifiers));

            case SyntaxKind.PropertyDeclaration:
                return((((PropertyDeclarationSyntax)node)).WithModifiers(modifiers));
            }
            throw new NotImplementedException("WithModifiers " + node.Kind().ToString());
        }
예제 #3
0
        private static bool TryGetExpressionBody(
            BasePropertyDeclarationSyntax baseProperty,
            ParseOptions options,
            ExpressionBodyPreference preference,
            out ArrowExpressionClauseSyntax arrowExpression,
            out SyntaxToken semicolonToken
            )
        {
            var accessorList = baseProperty.AccessorList;

            if (preference != ExpressionBodyPreference.Never && accessorList.Accessors.Count == 1)
            {
                var accessor = accessorList.Accessors[0];
                if (accessor.IsKind(SyntaxKind.GetAccessorDeclaration))
                {
                    return(TryGetArrowExpressionBody(
                               baseProperty.Kind(),
                               accessor,
                               options,
                               preference,
                               out arrowExpression,
                               out semicolonToken
                               ));
                }
            }

            arrowExpression = null;
            semicolonToken  = default;
            return(false);
        }
        private static SourcePropertySymbol Create(
            SourceMemberContainerTypeSymbol containingType,
            Binder binder,
            BasePropertyDeclarationSyntax syntax,
            string name,
            Location location,
            BindingDiagnosticBag diagnostics)
        {
            GetAccessorDeclarations(
                syntax,
                diagnostics,
                out bool isAutoProperty,
                out bool hasAccessorList,
                out bool accessorsHaveImplementation,
                out bool isInitOnly,
                out var getSyntax,
                out var setSyntax);

            var             explicitInterfaceSpecifier        = GetExplicitInterfaceSpecifier(syntax);
            SyntaxTokenList modifiersTokenList                = GetModifierTokensSyntax(syntax);
            bool            isExplicitInterfaceImplementation = explicitInterfaceSpecifier is object;
            var             modifiers = MakeModifiers(
                containingType,
                modifiersTokenList,
                isExplicitInterfaceImplementation,
                isIndexer: syntax.Kind() == SyntaxKind.IndexerDeclaration,
                accessorsHaveImplementation: accessorsHaveImplementation,
                location,
                diagnostics,
                out _);

            bool isExpressionBodied = !hasAccessorList && GetArrowExpression(syntax) != null;

            binder = binder.WithUnsafeRegionIfNecessary(modifiersTokenList);
            TypeSymbol?explicitInterfaceType;
            string?    aliasQualifierOpt;
            string     memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, explicitInterfaceSpecifier, name, diagnostics, out explicitInterfaceType, out aliasQualifierOpt);

            return(new SourcePropertySymbol(
                       containingType,
                       syntax,
                       hasGetAccessor: getSyntax != null || isExpressionBodied,
                       hasSetAccessor: setSyntax != null,
                       isExplicitInterfaceImplementation,
                       explicitInterfaceType,
                       aliasQualifierOpt,
                       modifiers,
                       isAutoProperty: isAutoProperty,
                       isExpressionBodied: isExpressionBodied,
                       isInitOnly: isInitOnly,
                       memberName,
                       location,
                       diagnostics));
        }
예제 #5
0
        public static BasePropertyDeclarationSyntax WithAccessorList(this BasePropertyDeclarationSyntax node, AccessorListSyntax accessorList)
        {
            switch (node.Kind())
            {
            case SyntaxKind.IndexerDeclaration:
                return(((IndexerDeclarationSyntax)node).WithAccessorList(accessorList));

            case SyntaxKind.PropertyDeclaration:
                return((((PropertyDeclarationSyntax)node)).WithAccessorList(accessorList));
            }
            throw new NotImplementedException();
        }
        /// <summary>
        /// Available if <paramref name="node"/> is <see cref="PropertyDeclarationSyntax"/> or <see cref="IndexerDeclarationSyntax"/>.
        /// </summary>
        public static SyntaxToken TryGetSemicolonToken(this BasePropertyDeclarationSyntax node)
        {
            if (node != null)
            {
                switch (node.Kind())
                {
                case SyntaxKind.PropertyDeclaration: return(((PropertyDeclarationSyntax)node).EosToken);

                case SyntaxKind.IndexerDeclaration: return(((IndexerDeclarationSyntax)node).EosToken);
                }
            }

            return(default);
예제 #7
0
        private static SourcePropertySymbol Create(
            SourceMemberContainerTypeSymbol containingType,
            Binder bodyBinder,
            BasePropertyDeclarationSyntax syntax,
            string name,
            Location location,
            DiagnosticBag diagnostics)
        {
            GetAccessorDeclarations(
                syntax,
                diagnostics,
                out bool isAutoProperty,
                out bool hasAccessorList,
                out bool accessorsHaveImplementation,
                out bool isInitOnly,
                out var getSyntax,
                out var setSyntax);
            // This has the value that IsIndexer will ultimately have, once we've populated the fields of this object.
            bool isIndexer = syntax.Kind() == SyntaxKind.IndexerDeclaration;
            var  explicitInterfaceSpecifier = GetExplicitInterfaceSpecifier(syntax);
            var  modifiers = MakeModifiers(
                containingType,
                GetModifierTokensSyntax(syntax),
                isExplicitInterfaceImplementation: explicitInterfaceSpecifier is object,
                isIndexer: isIndexer,
                accessorsHaveImplementation: accessorsHaveImplementation,
                location,
                diagnostics,
                out _);

            return(new SourcePropertySymbol(
                       containingType,
                       bodyBinder,
                       syntax,
                       getSyntax: getSyntax,
                       setSyntax: setSyntax,
                       explicitInterfaceSpecifier,
                       modifiers,
                       isIndexer: isIndexer,
                       isAutoProperty: isAutoProperty,
                       hasAccessorList: hasAccessorList,
                       isInitOnly: isInitOnly,
                       name,
                       location,
                       diagnostics));
        }
예제 #8
0
        private static bool TryGetExpressionBody(
            BasePropertyDeclarationSyntax baseProperty, LanguageVersion languageVersion, ExpressionBodyPreference preference,
            [NotNullWhen(true)] out ArrowExpressionClauseSyntax?arrowExpression, out SyntaxToken semicolonToken)
        {
            var accessorList = baseProperty.AccessorList;

            if (preference != ExpressionBodyPreference.Never &&
                accessorList?.Accessors.Count == 1)
            {
                var accessor = accessorList.Accessors[0];
                if (accessor.IsKind(SyntaxKind.GetAccessorDeclaration))
                {
                    return(TryGetArrowExpressionBody(
                               baseProperty.Kind(), accessor, languageVersion, preference,
                               out arrowExpression, out semicolonToken));
                }
            }

            arrowExpression = null;
            semicolonToken  = default;
            return(false);
        }
예제 #9
0
        // CONSIDER: if the parameters were computed lazily, ParameterCount could be overridden to fall back on the syntax (as in SourceMemberMethodSymbol).

        private SourcePropertySymbol(
            SourceMemberContainerTypeSymbol containingType,
            Binder bodyBinder,
            BasePropertyDeclarationSyntax syntax,
            string name,
            Location location,
            DiagnosticBag diagnostics)
        {
            // This has the value that IsIndexer will ultimately have, once we've populated the fields of this object.
            bool isIndexer = syntax.Kind() == SyntaxKind.IndexerDeclaration;
            var interfaceSpecifier = GetExplicitInterfaceSpecifier(syntax);
            bool isExplicitInterfaceImplementation = (interfaceSpecifier != null);

            _location = location;
            _containingType = containingType;
            _syntaxRef = syntax.GetReference();

            SyntaxTokenList modifiers = syntax.Modifiers;
            bodyBinder = bodyBinder.WithUnsafeRegionIfNecessary(modifiers);
            bodyBinder = bodyBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, this);

            bool modifierErrors;
            _modifiers = MakeModifiers(modifiers, isExplicitInterfaceImplementation, isIndexer, location, diagnostics, out modifierErrors);
            this.CheckAccessibility(location, diagnostics);

            this.CheckModifiers(location, isIndexer, diagnostics);

            if (isIndexer && !isExplicitInterfaceImplementation)
            {
                // Evaluate the attributes immediately in case the IndexerNameAttribute has been applied.
                // NOTE: we want IsExplicitInterfaceImplementation, IsOverride, Locations, and the syntax reference
                // to be initialized before we pass this symbol to LoadCustomAttributes.

                // CONSIDER: none of the information from this early binding pass is cached.  Everything will
                // be re-bound when someone calls GetAttributes.  If this gets to be a problem, we could
                // always use the real attribute bag of this symbol and modify LoadAndValidateAttributes to
                // handle partially filled bags.
                CustomAttributesBag<CSharpAttributeData> temp = null;
                LoadAndValidateAttributes(OneOrMany.Create(this.CSharpSyntaxNode.AttributeLists), ref temp, earlyDecodingOnly: true);
                if (temp != null)
                {
                    Debug.Assert(temp.IsEarlyDecodedWellKnownAttributeDataComputed);
                    var propertyData = (PropertyEarlyWellKnownAttributeData)temp.EarlyDecodedWellKnownAttributeData;
                    if (propertyData != null)
                    {
                        _sourceName = propertyData.IndexerName;
                    }
                }
            }

            string aliasQualifierOpt;
            string memberName = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(bodyBinder, interfaceSpecifier, name, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt);
            _sourceName = _sourceName ?? memberName; //sourceName may have been set while loading attributes
            _name = isIndexer ? ExplicitInterfaceHelpers.GetMemberName(WellKnownMemberNames.Indexer, _explicitInterfaceType, aliasQualifierOpt) : _sourceName;
            _isExpressionBodied = false;

            bool hasAccessorList = syntax.AccessorList != null;
            var propertySyntax = syntax as PropertyDeclarationSyntax;
            var arrowExpression = propertySyntax != null
                ? propertySyntax.ExpressionBody
                : ((IndexerDeclarationSyntax)syntax).ExpressionBody;
            bool hasExpressionBody = arrowExpression != null;
            bool hasInitializer = !isIndexer && propertySyntax.Initializer != null;

            bool notRegularProperty = (!IsAbstract && !IsExtern && !isIndexer && hasAccessorList);
            AccessorDeclarationSyntax getSyntax = null;
            AccessorDeclarationSyntax setSyntax = null;
            if (hasAccessorList)
            {
                foreach (var accessor in syntax.AccessorList.Accessors)
                {
                    if (accessor.Kind() == SyntaxKind.GetAccessorDeclaration &&
                        (getSyntax == null || getSyntax.Keyword.Span.IsEmpty))
                    {
                        getSyntax = accessor;
                    }
                    else if (accessor.Kind() == SyntaxKind.SetAccessorDeclaration &&
                        (setSyntax == null || setSyntax.Keyword.Span.IsEmpty))
                    {
                        setSyntax = accessor;
                    }
                    else
                    {
                        continue;
                    }

                    if (accessor.Body != null)
                    {
                        notRegularProperty = false;
                    }
                }
            }
            else
            {
                notRegularProperty = false;
            }

            if (hasInitializer)
            {
                CheckInitializer(hasExpressionBody, notRegularProperty, location, diagnostics);
            }

            if (notRegularProperty || hasInitializer)
            {
                var hasGetSyntax = getSyntax != null;
                _isAutoProperty = notRegularProperty && hasGetSyntax;
                bool isReadOnly = hasGetSyntax && setSyntax == null;

                if (_isAutoProperty || hasInitializer)
                {
                    if (_isAutoProperty)
                    {
                        //issue a diagnostic if the compiler generated attribute ctor is not found.
                        Binder.ReportUseSiteDiagnosticForSynthesizedAttribute(bodyBinder.Compilation,
                        WellKnownMember.System_Runtime_CompilerServices_CompilerGeneratedAttribute__ctor, diagnostics, syntax: syntax);
                    }

                    string fieldName = GeneratedNames.MakeBackingFieldName(_sourceName);
                    _backingField = new SynthesizedBackingFieldSymbol(this,
                                                                          fieldName,
                                                                          isReadOnly,
                                                                          this.IsStatic,
                                                                          hasInitializer);
                }

                if (notRegularProperty)
                {
                    Binder.CheckFeatureAvailability(location, 
                                                    isReadOnly ? MessageID.IDS_FeatureReadonlyAutoImplementedProperties : 
                                                                 MessageID.IDS_FeatureAutoImplementedProperties, 
                                                    diagnostics);
                }
            }

            PropertySymbol explicitlyImplementedProperty = null;
            _typeCustomModifiers = ImmutableArray<CustomModifier>.Empty;

            // The runtime will not treat the accessors of this property as overrides or implementations
            // of those of another property unless both the signatures and the custom modifiers match.
            // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom
            // modifiers that are in the signatures of the overridden/implemented property accessors.
            // (From source, we know that there can only be one overridden/implemented property, so there
            // are no conflicts.)  This is unnecessary for implicit implementations because, if the custom
            // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations 
            // that delegate to the implicit implementations) with the correct custom modifiers
            // (see SourceNamedTypeSymbol.ImplementInterfaceMember).

            // Note: we're checking if the syntax indicates explicit implementation rather,
            // than if explicitInterfaceType is null because we don't want to look for an
            // overridden property if this is supposed to be an explicit implementation.
            if (isExplicitInterfaceImplementation || this.IsOverride)
            {
                // Type and parameters for overrides and explicit implementations cannot be bound
                // lazily since the property name depends on the metadata name of the base property,
                // and the property name is required to add the property to the containing type, and
                // the type and parameters are required to determine the override or implementation.
                _lazyType = this.ComputeType(bodyBinder, syntax, diagnostics);
                _lazyParameters = this.ComputeParameters(bodyBinder, syntax, diagnostics);

                bool isOverride = false;
                PropertySymbol overriddenOrImplementedProperty = null;

                if (!isExplicitInterfaceImplementation)
                {
                    // If this property is an override, we may need to copy custom modifiers from
                    // the overridden property (so that the runtime will recognize it as an override).
                    // We check for this case here, while we can still modify the parameters and
                    // return type without losing the appearance of immutability.
                    isOverride = true;
                    overriddenOrImplementedProperty = this.OverriddenProperty;
                }
                else
                {
                    string interfacePropertyName = isIndexer ? WellKnownMemberNames.Indexer : name;
                    explicitlyImplementedProperty = this.FindExplicitlyImplementedProperty(_explicitInterfaceType, interfacePropertyName, interfaceSpecifier, diagnostics);
                    overriddenOrImplementedProperty = explicitlyImplementedProperty;
                }

                if ((object)overriddenOrImplementedProperty != null)
                {
                    _typeCustomModifiers = overriddenOrImplementedProperty.TypeCustomModifiers;

                    TypeSymbol overriddenPropertyType = overriddenOrImplementedProperty.Type;

                    // We do an extra check before copying the type to handle the case where the overriding
                    // property (incorrectly) has a different type than the overridden property.  In such cases,
                    // we want to retain the original (incorrect) type to avoid hiding the type given in source.
                    if (_lazyType.Equals(overriddenPropertyType, ignoreCustomModifiersAndArraySizesAndLowerBounds: true, ignoreDynamic: false))
                    {
                        _lazyType = overriddenPropertyType;
                    }

                    _lazyParameters = CustomModifierUtils.CopyParameterCustomModifiers(overriddenOrImplementedProperty.Parameters, _lazyParameters, alsoCopyParamsModifier: isOverride);
                }
            }

            if (!hasAccessorList)
            {
                if (hasExpressionBody)
                {
                    _isExpressionBodied = true;
                    _getMethod = SourcePropertyAccessorSymbol.CreateAccessorSymbol(
                        containingType,
                        this,
                        _modifiers,
                        _sourceName,
                        arrowExpression,
                        explicitlyImplementedProperty,
                        aliasQualifierOpt,
                        diagnostics);
                }
                else
                {
                    _getMethod = null;
                }
                _setMethod = null;
            }
            else
            {
                _getMethod = CreateAccessorSymbol(getSyntax, explicitlyImplementedProperty, aliasQualifierOpt, notRegularProperty, diagnostics);
                _setMethod = CreateAccessorSymbol(setSyntax, explicitlyImplementedProperty, aliasQualifierOpt, notRegularProperty, diagnostics);

                if ((getSyntax == null) || (setSyntax == null))
                {
                    if ((getSyntax == null) && (setSyntax == null))
                    {
                        diagnostics.Add(ErrorCode.ERR_PropertyWithNoAccessors, location, this);
                    }
                    else if (notRegularProperty)
                    {
                        var accessor = _getMethod ?? _setMethod;
                        if (getSyntax == null)
                        {
                            diagnostics.Add(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, accessor.Locations[0], accessor);
                        }
                    }
                }

                // Check accessor accessibility is more restrictive than property accessibility.
                CheckAccessibilityMoreRestrictive(_getMethod, diagnostics);
                CheckAccessibilityMoreRestrictive(_setMethod, diagnostics);

                if (((object)_getMethod != null) && ((object)_setMethod != null))
                {
                    // Check accessibility is set on at most one accessor.
                    if ((_getMethod.LocalAccessibility != Accessibility.NotApplicable) &&
                        (_setMethod.LocalAccessibility != Accessibility.NotApplicable))
                    {
                        diagnostics.Add(ErrorCode.ERR_DuplicatePropertyAccessMods, location, this);
                    }
                    else if (this.IsAbstract)
                    {
                        // Check abstract property accessors are not private.
                        CheckAbstractPropertyAccessorNotPrivate(_getMethod, diagnostics);
                        CheckAbstractPropertyAccessorNotPrivate(_setMethod, diagnostics);
                    }
                }
                else
                {
                    if (!this.IsOverride)
                    {
                        var accessor = _getMethod ?? _setMethod;
                        if ((object)accessor != null)
                        {
                            // Check accessibility is not set on the one accessor.
                            if (accessor.LocalAccessibility != Accessibility.NotApplicable)
                            {
                                diagnostics.Add(ErrorCode.ERR_AccessModMissingAccessor, location, this);
                            }
                        }
                    }
                }
            }

            if ((object)explicitlyImplementedProperty != null)
            {
                CheckExplicitImplementationAccessor(this.GetMethod, explicitlyImplementedProperty.GetMethod, explicitlyImplementedProperty, diagnostics);
                CheckExplicitImplementationAccessor(this.SetMethod, explicitlyImplementedProperty.SetMethod, explicitlyImplementedProperty, diagnostics);
            }

            _explicitInterfaceImplementations =
                (object)explicitlyImplementedProperty == null ?
                    ImmutableArray<PropertySymbol>.Empty :
                    ImmutableArray.Create(explicitlyImplementedProperty);

            // get-only auto property should not override settable properties
            if (_isAutoProperty && (object)_setMethod == null && !this.IsReadOnly)
            {
                diagnostics.Add(ErrorCode.ERR_AutoPropertyMustOverrideSet, location, this);
            }
        }
예제 #10
0
 private static BaseParameterListSyntax GetParameterListSyntax(BasePropertyDeclarationSyntax syntax)
 {
     return (syntax.Kind() == SyntaxKind.IndexerDeclaration) ? ((IndexerDeclarationSyntax)syntax).ParameterList : null;
 }
예제 #11
0
 private static ExplicitInterfaceSpecifierSyntax GetExplicitInterfaceSpecifier(BasePropertyDeclarationSyntax syntax)
 {
     switch (syntax.Kind())
     {
         case SyntaxKind.PropertyDeclaration:
             return ((PropertyDeclarationSyntax)syntax).ExplicitInterfaceSpecifier;
         case SyntaxKind.IndexerDeclaration:
             return ((IndexerDeclarationSyntax)syntax).ExplicitInterfaceSpecifier;
         default:
             throw ExceptionUtilities.UnexpectedValue(syntax.Kind());
     }
 }