SourceConstructorSymbol.cs 7.1 KB
Newer Older
J
Jonathon Marolf 已提交
1 2 3
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
P
Pilchie 已提交
4 5 6 7 8 9 10

using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
11
    internal sealed class SourceConstructorSymbol : SourceConstructorSymbolBase
P
Pilchie 已提交
12
    {
13
        private readonly bool _isExpressionBodied;
14

P
Pilchie 已提交
15 16 17 18 19 20 21 22 23 24
        public static SourceConstructorSymbol CreateConstructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            ConstructorDeclarationSyntax syntax,
            DiagnosticBag diagnostics)
        {
            var methodKind = syntax.Modifiers.Any(SyntaxKind.StaticKeyword) ? MethodKind.StaticConstructor : MethodKind.Constructor;
            return new SourceConstructorSymbol(containingType, syntax.Identifier.GetLocation(), syntax, methodKind, diagnostics);
        }

        private SourceConstructorSymbol(
25 26 27 28 29 30
             SourceMemberContainerTypeSymbol containingType,
             Location location,
             ConstructorDeclarationSyntax syntax,
             MethodKind methodKind,
             DiagnosticBag diagnostics) :
             base(containingType, location, syntax, methodKind, diagnostics)
P
Pilchie 已提交
31
        {
32 33 34 35
            bool hasBlockBody = syntax.Body != null;
            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;
            bool hasBody = hasBlockBody || _isExpressionBodied;

P
Pilchie 已提交
36
            bool modifierErrors;
37
            var declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, hasBody, location, diagnostics, out modifierErrors);
38
            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false);
P
Pilchie 已提交
39

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

46
            if (IsExtern)
P
Pilchie 已提交
47
            {
48 49 50 51 52
                if (methodKind == MethodKind.Constructor && syntax.Initializer != null)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasConstructorInitializer, location, this);
                }

53
                if (hasBody)
P
Pilchie 已提交
54 55 56 57 58
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

59 60 61 62 63
            if (methodKind == MethodKind.StaticConstructor)
            {
                CheckFeatureAvailabilityAndRuntimeSupport(syntax, location, hasBody, diagnostics);
            }

64
            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers, this, isExplicitInterfaceImplementation: false);
P
Pilchie 已提交
65 66 67 68 69 70 71
            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (!modifierErrors)
            {
72
                this.CheckModifiers(methodKind, hasBody, location, diagnostics);
P
Pilchie 已提交
73
            }
74 75 76

            CheckForBlockAndExpressionBody(
                syntax.Body, syntax.ExpressionBody, syntax, diagnostics);
P
Pilchie 已提交
77 78
        }

79 80 81 82 83 84
        internal ConstructorDeclarationSyntax GetSyntax()
        {
            Debug.Assert(syntaxReferenceOpt != null);
            return (ConstructorDeclarationSyntax)syntaxReferenceOpt.GetSyntax();
        }

85
        protected override ParameterListSyntax GetParameterList()
86
        {
87
            return GetSyntax().ParameterList;
88 89
        }

90
        protected override CSharpSyntaxNode GetInitializer()
P
Pilchie 已提交
91
        {
92
            return GetSyntax().Initializer;
P
Pilchie 已提交
93 94
        }

95
        private DeclarationModifiers MakeModifiers(SyntaxTokenList modifiers, MethodKind methodKind, bool hasBody, Location location, DiagnosticBag diagnostics, out bool modifierErrors)
P
Pilchie 已提交
96 97 98 99
        {
            var defaultAccess = (methodKind == MethodKind.StaticConstructor) ? DeclarationModifiers.None : DeclarationModifiers.Private;

            // Check that the set of modifiers is allowed
100
            const DeclarationModifiers allowedModifiers =
P
Pilchie 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
                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
120 121 122 123 124 125 126

                if (this.ContainingType.IsInterface)
                {
                    ModifierUtils.ReportDefaultInterfaceImplementationModifiers(hasBody, mods,
                                                                                DeclarationModifiers.Extern,
                                                                                location, diagnostics);
                }
P
Pilchie 已提交
127 128 129 130 131
            }

            return mods;
        }

132
        private void CheckModifiers(MethodKind methodKind, bool hasBody, Location location, DiagnosticBag diagnostics)
P
Pilchie 已提交
133
        {
134
            if (!hasBody && !IsExtern)
P
Pilchie 已提交
135 136 137
            {
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }
138 139 140 141
            else if (ContainingType.IsSealed && this.DeclaredAccessibility.HasProtected() && !this.IsOverride)
            {
                diagnostics.Add(AccessCheck.GetProtectedMemberInSealedTypeError(ContainingType), location, this);
            }
P
Pilchie 已提交
142 143 144 145 146 147 148 149 150 151 152
            else if (ContainingType.IsStatic && methodKind == MethodKind.Constructor)
            {
                diagnostics.Add(ErrorCode.ERR_ConstructorInStaticClass, location);
            }
        }

        internal override OneOrMany<SyntaxList<AttributeListSyntax>> GetAttributeDeclarations()
        {
            return OneOrMany.Create(((ConstructorDeclarationSyntax)this.SyntaxNode).AttributeLists);
        }

153 154
        internal override bool IsExpressionBodied
        {
155 156 157 158
            get
            {
                return _isExpressionBodied;
            }
159
        }
160

161
        protected override bool IsWithinExpressionOrBlockBody(int position, out int offset)
162
        {
163
            ConstructorDeclarationSyntax ctorSyntax = GetSyntax();
164
            if (ctorSyntax.Body?.Span.Contains(position) == true)
165
            {
166 167
                offset = position - ctorSyntax.Body.Span.Start;
                return true;
168
            }
169
            else if (ctorSyntax.ExpressionBody?.Span.Contains(position) == true)
170
            {
171 172
                offset = position - ctorSyntax.ExpressionBody.Span.Start;
                return true;
173
            }
174

175 176
            offset = -1;
            return false;
177
        }
P
Pilchie 已提交
178 179
    }
}