Example #1
0
        public static AccessorDeclarationSyntax AccessorDeclaration(AccessorDeclarationKind kind = default(AccessorDeclarationKind), BlockSyntax body = null)
        {
            var result = new AccessorDeclarationSyntax();

            result.Kind = kind;
            result.Body = body;

            return result;
        }
Example #2
0
        public static AccessorDeclarationSyntax AccessorDeclaration(AccessorDeclarationKind kind = default(AccessorDeclarationKind), IEnumerable<AttributeListSyntax> attributeLists = null, Modifiers modifiers = default(Modifiers), BlockSyntax body = null)
        {
            var result = new AccessorDeclarationSyntax();

            result.Kind = kind;
            if (attributeLists != null)
                result.AttributeLists.AddRange(attributeLists);
            result.Modifiers = modifiers;
            result.Body = body;

            return result;
        }
Example #3
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 some modifiers from the containing property, but not the accessibility modifiers.
            declarationModifiers |= GetAccessorModifiers(propertyModifiers) & ~DeclarationModifiers.AccessibilityMask;
            if ((declarationModifiers & DeclarationModifiers.Private) != 0)
            {
                // Private accessors cannot be virtual.
                declarationModifiers &= ~DeclarationModifiers.Virtual;
            }

            // 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: hasBody || hasExpressionBody || isAutoPropertyAccessor, 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);
        }
        private static (SyntaxNode newRoot, PropertyDeclarationSyntax newNode) AddCallToOnPropertyChanged(SyntaxNode root, AccessorDeclarationSyntax node)
        {
            InvocationExpressionSyntax invoc = SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("OnPropertyChanged"));
            ExpressionStatementSyntax  expr  = SyntaxFactory.ExpressionStatement(invoc, SyntaxFactory.Token(SyntaxKind.SemicolonToken));

            var annotation = new SyntaxAnnotation("new_call_node", "");
            var newNode    = node.AddBodyStatements(expr).WithAdditionalAnnotations(annotation);
            var newRoot    = root.ReplaceNode(node, newNode);

            newNode = newRoot.GetAnnotatedNodes(annotation).First() as AccessorDeclarationSyntax;
            return(newRoot, newNode.Parent.Parent as PropertyDeclarationSyntax);
        }
Example #5
0
 public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
 {
 }
        private static void AnalyzeSummaryElement(SyntaxNodeAnalysisContext context, XmlNodeSyntax syntax, Location diagnosticLocation, PropertyDeclarationSyntax propertyDeclaration, string startingTextGets, string startingTextSets, string startingTextGetsOrSets, string startingTextReturns)
        {
            var diagnosticProperties = ImmutableDictionary.CreateBuilder <string, string>();
            ArrowExpressionClauseSyntax expressionBody = propertyDeclaration.ExpressionBody;
            AccessorDeclarationSyntax   getter         = null;
            AccessorDeclarationSyntax   setter         = null;

            if (propertyDeclaration.AccessorList != null)
            {
                foreach (var accessor in propertyDeclaration.AccessorList.Accessors)
                {
                    switch (accessor.Keyword.Kind())
                    {
                    case SyntaxKind.GetKeyword:
                        getter = accessor;
                        break;

                    case SyntaxKind.SetKeyword:
                        setter = accessor;
                        break;
                    }
                }
            }

            if (!(syntax is XmlElementSyntax summaryElement))
            {
                // This is reported by SA1604 or SA1606.
                return;
            }

            // Add a no code fix tag when the summary element is empty.
            // This will only impact SA1623, because SA1624 cannot trigger with an empty summary.
            if (summaryElement.Content.Count == 0)
            {
                diagnosticProperties.Add(NoCodeFixKey, string.Empty);
            }

            var    textElement = XmlCommentHelper.TryGetFirstTextElementWithContent(summaryElement);
            string text        = textElement is null ? string.Empty : XmlCommentHelper.GetText(textElement, normalizeWhitespace: true).TrimStart();

            bool prefixIsGetsOrSets = text.StartsWith(startingTextGetsOrSets, StringComparison.OrdinalIgnoreCase);
            bool prefixIsGets       = !prefixIsGetsOrSets && text.StartsWith(startingTextGets, StringComparison.OrdinalIgnoreCase);
            bool prefixIsSets       = text.StartsWith(startingTextSets, StringComparison.OrdinalIgnoreCase);

            bool getterVisible, setterVisible;

            if (getter != null && setter != null)
            {
                if (!getter.Modifiers.Any() && !setter.Modifiers.Any())
                {
                    // The getter and setter have the same declared accessibility
                    getterVisible = true;
                    setterVisible = true;
                }
                else if (getter.Modifiers.Any(SyntaxKind.PrivateKeyword))
                {
                    getterVisible = false;
                    setterVisible = true;
                }
                else if (setter.Modifiers.Any(SyntaxKind.PrivateKeyword))
                {
                    getterVisible = true;
                    setterVisible = false;
                }
                else
                {
                    var  propertyAccessibility = propertyDeclaration.GetEffectiveAccessibility(context.SemanticModel, context.CancellationToken);
                    bool propertyOnlyInternal  = propertyAccessibility == Accessibility.Internal ||
                                                 propertyAccessibility == Accessibility.ProtectedAndInternal ||
                                                 propertyAccessibility == Accessibility.Private;
                    if (propertyOnlyInternal)
                    {
                        // Property only internal and no accessor is explicitly private
                        getterVisible = true;
                        setterVisible = true;
                    }
                    else
                    {
                        var getterAccessibility = getter.GetEffectiveAccessibility(context.SemanticModel, context.CancellationToken);
                        var setterAccessibility = setter.GetEffectiveAccessibility(context.SemanticModel, context.CancellationToken);

                        switch (getterAccessibility)
                        {
                        case Accessibility.Public:
                        case Accessibility.ProtectedOrInternal:
                        case Accessibility.Protected:
                            getterVisible = true;
                            break;

                        case Accessibility.Internal:
                        case Accessibility.ProtectedAndInternal:
                        case Accessibility.Private:
                        default:
                            // The property is externally accessible, so the setter must be more accessible.
                            getterVisible = false;
                            break;
                        }

                        switch (setterAccessibility)
                        {
                        case Accessibility.Public:
                        case Accessibility.ProtectedOrInternal:
                        case Accessibility.Protected:
                            setterVisible = true;
                            break;

                        case Accessibility.Internal:
                        case Accessibility.ProtectedAndInternal:
                        case Accessibility.Private:
                        default:
                            // The property is externally accessible, so the getter must be more accessible.
                            setterVisible = false;
                            break;
                        }
                    }
                }
            }
            else
            {
                if (getter != null || expressionBody != null)
                {
                    getterVisible = true;
                    setterVisible = false;
                }
                else
                {
                    getterVisible = false;
                    setterVisible = setter != null;
                }
            }

            if (getterVisible)
            {
                if (setterVisible)
                {
                    // Both getter and setter are visible.
                    if (!prefixIsGetsOrSets)
                    {
                        ReportSA1623(context, diagnosticLocation, diagnosticProperties, text, expectedStartingText: startingTextGetsOrSets, unexpectedStartingText1: startingTextGets, unexpectedStartingText2: startingTextSets, unexpectedStartingText3: startingTextReturns);
                    }
                }
                else if (setter != null)
                {
                    // Both getter and setter exist, but only getter is visible.
                    if (!prefixIsGets)
                    {
                        if (prefixIsGetsOrSets)
                        {
                            ReportSA1624(context, diagnosticLocation, diagnosticProperties, accessor: "get", expectedStartingText: startingTextGets, startingTextToRemove: startingTextGetsOrSets);
                        }
                        else
                        {
                            ReportSA1623(context, diagnosticLocation, diagnosticProperties, text, expectedStartingText: startingTextGets, unexpectedStartingText1: startingTextSets, unexpectedStartingText2: startingTextReturns);
                        }
                    }
                }
                else
                {
                    // Getter exists and is visible. Setter does not exist.
                    if (!prefixIsGets)
                    {
                        ReportSA1623(context, diagnosticLocation, diagnosticProperties, text, expectedStartingText: startingTextGets, unexpectedStartingText1: startingTextSets, unexpectedStartingText2: startingTextGetsOrSets, unexpectedStartingText3: startingTextReturns);
                    }
                }
            }
            else if (setterVisible)
            {
                if (getter != null)
                {
                    // Both getter and setter exist, but only setter is visible.
                    if (!prefixIsSets)
                    {
                        if (prefixIsGetsOrSets)
                        {
                            ReportSA1624(context, diagnosticLocation, diagnosticProperties, accessor: "set", expectedStartingText: startingTextSets, startingTextToRemove: startingTextGetsOrSets);
                        }
                        else
                        {
                            ReportSA1623(context, diagnosticLocation, diagnosticProperties, text, expectedStartingText: startingTextSets, unexpectedStartingText1: startingTextGets, unexpectedStartingText2: startingTextReturns);
                        }
                    }
                }
                else
                {
                    // Setter exists and is visible. Getter does not exist.
                    if (!prefixIsSets)
                    {
                        ReportSA1623(context, diagnosticLocation, diagnosticProperties, text, expectedStartingText: startingTextSets, unexpectedStartingText1: startingTextGetsOrSets, unexpectedStartingText2: startingTextGets, unexpectedStartingText3: startingTextReturns);
                    }
                }
            }
        }
        public void TestGetSpeculativeSemanticModelForPropertyAccessorBody()
        {
            var compilation = CreateStandardCompilation(@"
class R
{
    private int _p;
}

class C : R 
{
    
    private int M
    {
        set
        {
            int y = 1000;
        }
    }
}
");

            var blockStatement = (BlockSyntax)SyntaxFactory.ParseStatement(@"
{ 
   int z = 0; 

   _p = 123L;
}
");

            var tree  = compilation.SyntaxTrees[0];
            var root  = tree.GetCompilationUnitRoot();
            var model = compilation.GetSemanticModel(tree, ignoreAccessibility: true);

            AccessorDeclarationSyntax accessorDecl = root.DescendantNodes().OfType <AccessorDeclarationSyntax>().Single();

            var speculatedMethod = accessorDecl.ReplaceNode(accessorDecl.Body, blockStatement);

            SemanticModel speculativeModel;
            var           success =
                model.TryGetSpeculativeSemanticModelForMethodBody(
                    accessorDecl.Body.Statements[0].SpanStart, speculatedMethod, out speculativeModel);

            Assert.True(success);
            Assert.NotNull(speculativeModel);

            var p =
                speculativeModel.SyntaxTree.GetRoot()
                .DescendantNodes()
                .OfType <IdentifierNameSyntax>()
                .Single(s => s.Identifier.ValueText == "_p");

            var symbolSpeculation =
                speculativeModel.GetSpeculativeSymbolInfo(p.FullSpan.Start, p, SpeculativeBindingOption.BindAsExpression);

            Assert.Equal("_p", symbolSpeculation.Symbol.Name);

            var typeSpeculation =
                speculativeModel.GetSpeculativeTypeInfo(p.FullSpan.Start, p, SpeculativeBindingOption.BindAsExpression);

            Assert.Equal("Int32", typeSpeculation.Type.Name);
        }
        protected IEnumerable <CodeAction> GetActions(Document document, SyntaxNode root, AccessorDeclarationSyntax node)
        {
            var propertyOrIndexerDeclaration = node.Ancestors().Where(n => n.GetType().Equals(typeof(PropertyDeclarationSyntax)) || n.GetType().Equals(typeof(IndexerDeclarationSyntax))).FirstOrDefault();

            var nullableType = propertyOrIndexerDeclaration.ChildNodes().OfType <NullableTypeSyntax>().FirstOrDefault();

            var objectType = propertyOrIndexerDeclaration.ChildNodes().OfType <IdentifierNameSyntax>().FirstOrDefault();

            return(GetActions(document, root, node, nullableType, objectType));
        }
        private static SyntaxNode ReformatAccessorAsMultipleLines(IndentationSettings indentationSettings, AccessorDeclarationSyntax accessor)
        {
            var accessorList          = (AccessorListSyntax)accessor.Parent;
            var indentationSteps      = IndentationHelper.GetIndentationSteps(indentationSettings, accessorList.OpenBraceToken) + 1;
            var indentation           = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps);
            var indentationStatements = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps + 1);

            var newAccessor = accessor
                              .WithModifiers(ReformatModifiersAsMultipleLines(accessor.Modifiers, indentation))
                              .WithKeyword(ReformatKeywordAsMultipleLines(accessor.Keyword, indentation, accessor.Modifiers.Count == 0))
                              .WithBody(ReformatBodyAsMultipleLines(accessor.Body, indentation, indentationStatements));

            return(newAccessor);
        }
Example #10
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.GetSyntaxRootAsync().ConfigureAwait(false);

            if (!TryFindToken(root, context.Span.Start, out SyntaxToken token))
            {
                return;
            }

            SyntaxKind kind = token.Kind();

            foreach (Diagnostic diagnostic in context.Diagnostics)
            {
                switch (diagnostic.Id)
                {
                case CompilerDiagnosticIdentifiers.OperatorCannotBeAppliedToOperand:
                {
                    if (kind == SyntaxKind.QuestionToken &&
                        token.Parent is ConditionalAccessExpressionSyntax conditionalAccess)
                    {
                        SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(conditionalAccess.Expression, context.CancellationToken);

                        if (typeSymbol?.IsErrorType() == false &&
                            !typeSymbol.IsNullableType())
                        {
                            if (typeSymbol.IsValueType)
                            {
                                if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveConditionalAccess))
                                {
                                    CodeAction codeAction = CodeAction.Create(
                                        "Remove '?' operator",
                                        cancellationToken =>
                                        {
                                            var textChange = new TextChange(token.Span, "");
                                            return(context.Document.WithTextChangeAsync(textChange, cancellationToken));
                                        },
                                        GetEquivalenceKey(diagnostic));

                                    context.RegisterCodeFix(codeAction, diagnostic);
                                }
                            }
                            else if (typeSymbol.IsReferenceType)
                            {
                                if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddArgumentList) &&
                                    conditionalAccess.WhenNotNull is MemberBindingExpressionSyntax memberBindingExpression)
                                {
                                    ConditionalAccessExpressionSyntax newNode = conditionalAccess.WithWhenNotNull(
                                        InvocationExpression(
                                            memberBindingExpression.WithoutTrailingTrivia(),
                                            ArgumentList().WithTrailingTrivia(memberBindingExpression.GetTrailingTrivia())));

                                    CodeAction codeAction = CodeAction.Create(
                                        "Add argument list",
                                        cancellationToken => context.Document.ReplaceNodeAsync(conditionalAccess, newNode, cancellationToken),
                                        GetEquivalenceKey(diagnostic));

                                    context.RegisterCodeFix(codeAction, diagnostic);
                                }
                            }
                        }
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.PartialModifierCanOnlyAppearImmediatelyBeforeClassStructInterfaceOrVoid:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.OrderModifiers))
                    {
                        break;
                    }

                    ModifiersCodeFixRegistrator.MoveModifier(context, diagnostic, token.Parent, token);
                    break;
                }

                case CompilerDiagnosticIdentifiers.ValueCannotBeUsedAsDefaultParameter:
                {
                    if (!(token.Parent is ParameterSyntax parameter))
                    {
                        break;
                    }

                    ExpressionSyntax value = parameter.Default?.Value;

                    if (value == null)
                    {
                        break;
                    }

                    if (value.IsKind(SyntaxKind.NullLiteralExpression))
                    {
                        if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReplaceNullLiteralExpressionWithDefaultValue))
                        {
                            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                            CodeFixRegistrator.ReplaceNullWithDefaultValue(context, diagnostic, value, semanticModel);
                        }
                    }
                    else if (!value.IsKind(SyntaxKind.DefaultExpression, SyntaxKind.DefaultLiteralExpression))
                    {
                        if (Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeParameterType))
                        {
                            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(value, context.CancellationToken);

                            if (!typeSymbol.IsKind(SymbolKind.ErrorType))
                            {
                                CodeFixRegistrator.ChangeType(context, diagnostic, parameter.Type, typeSymbol, semanticModel);
                            }
                        }
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.ObjectOfTypeConvertibleToTypeIsRequired:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ReturnDefaultValue))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.ReturnKeyword)
                    {
                        break;
                    }

                    if (!token.IsParentKind(SyntaxKind.ReturnStatement))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ISymbol symbol = semanticModel.GetEnclosingSymbol(token.SpanStart, context.CancellationToken);

                    if (symbol == null)
                    {
                        break;
                    }

                    SymbolKind symbolKind = symbol.Kind;

                    ITypeSymbol typeSymbol = null;

                    if (symbolKind == SymbolKind.Method)
                    {
                        var methodSymbol = (IMethodSymbol)symbol;

                        typeSymbol = methodSymbol.ReturnType;

                        if (methodSymbol.IsAsync &&
                            (typeSymbol is INamedTypeSymbol namedTypeSymbol))
                        {
                            ImmutableArray <ITypeSymbol> typeArguments = namedTypeSymbol.TypeArguments;

                            if (typeArguments.Any())
                            {
                                typeSymbol = typeArguments[0];
                            }
                        }
                    }
                    else if (symbolKind == SymbolKind.Property)
                    {
                        typeSymbol = ((IPropertySymbol)symbol).Type;
                    }
                    else
                    {
                        Debug.Fail(symbolKind.ToString());
                    }

                    if (typeSymbol == null)
                    {
                        break;
                    }

                    if (typeSymbol.Kind == SymbolKind.ErrorType)
                    {
                        break;
                    }

                    if (!typeSymbol.SupportsExplicitDeclaration())
                    {
                        break;
                    }

                    var returnStatement = (ReturnStatementSyntax)token.Parent;

                    CodeAction codeAction = CodeAction.Create(
                        "Return default value",
                        cancellationToken =>
                        {
                            ExpressionSyntax expression = typeSymbol.GetDefaultValueSyntax(context.Document.GetDefaultSyntaxOptions());

                            if (expression.IsKind(SyntaxKind.DefaultExpression) &&
                                context.Document.SupportsLanguageFeature(CSharpLanguageFeature.DefaultLiteral))
                            {
                                expression = CSharpFactory.DefaultLiteralExpression().WithTriviaFrom(expression);
                            }

                            ReturnStatementSyntax newNode = returnStatement.WithExpression(expression);

                            return(context.Document.ReplaceNodeAsync(returnStatement, newNode, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.TypeExpected:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddMissingType))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.CloseParenToken)
                    {
                        break;
                    }

                    if (!(token.Parent is DefaultExpressionSyntax defaultExpression))
                    {
                        break;
                    }

                    if (!(defaultExpression.Type is IdentifierNameSyntax identifierName))
                    {
                        break;
                    }

                    if (!identifierName.IsMissing)
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    TypeInfo typeInfo = semanticModel.GetTypeInfo(defaultExpression, context.CancellationToken);

                    ITypeSymbol convertedType = typeInfo.ConvertedType;

                    if (convertedType?.SupportsExplicitDeclaration() != true)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        $"Add type '{SymbolDisplay.ToMinimalDisplayString(convertedType, semanticModel, defaultExpression.SpanStart, SymbolDisplayFormats.DisplayName)}'",
                        ct =>
                        {
                            TypeSyntax newType = convertedType.ToTypeSyntax()
                                                 .WithTriviaFrom(identifierName)
                                                 .WithFormatterAndSimplifierAnnotation();

                            return(context.Document.ReplaceNodeAsync(identifierName, newType, ct));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }

                case CompilerDiagnosticIdentifiers.SemicolonAfterMethodOrAccessorBlockIsNotValid:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.RemoveSemicolon))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.SemicolonToken)
                    {
                        break;
                    }

                    switch (token.Parent)
                    {
                    case MethodDeclarationSyntax methodDeclaration:
                    {
                        BlockSyntax body = methodDeclaration.Body;

                        if (body == null)
                        {
                            break;
                        }

                        CodeAction codeAction = CodeAction.Create(
                            "Remove semicolon",
                            cancellationToken =>
                                {
                                    SyntaxTriviaList trivia = body
                                                              .GetTrailingTrivia()
                                                              .EmptyIfWhitespace()
                                                              .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                              .AddRange(token.TrailingTrivia);

                                    MethodDeclarationSyntax newNode = methodDeclaration
                                                                      .WithBody(body.WithTrailingTrivia(trivia))
                                                                      .WithSemicolonToken(default(SyntaxToken));

                                    return(context.Document.ReplaceNodeAsync(methodDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                        break;
                    }

                    case PropertyDeclarationSyntax propertyDeclaration:
                    {
                        AccessorListSyntax accessorList = propertyDeclaration.AccessorList;

                        if (accessorList == null)
                        {
                            break;
                        }

                        CodeAction codeAction = CodeAction.Create(
                            "Remove semicolon",
                            cancellationToken =>
                                {
                                    SyntaxTriviaList trivia = accessorList
                                                              .GetTrailingTrivia()
                                                              .EmptyIfWhitespace()
                                                              .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                              .AddRange(token.TrailingTrivia);

                                    PropertyDeclarationSyntax newNode = propertyDeclaration
                                                                        .WithAccessorList(accessorList.WithTrailingTrivia(trivia))
                                                                        .WithSemicolonToken(default(SyntaxToken));

                                    return(context.Document.ReplaceNodeAsync(propertyDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                        break;
                    }

                    case AccessorDeclarationSyntax accessorDeclaration:
                    {
                        BlockSyntax body = accessorDeclaration.Body;

                        if (body == null)
                        {
                            break;
                        }

                        CodeAction codeAction = CodeAction.Create(
                            "Remove semicolon",
                            cancellationToken =>
                                {
                                    SyntaxTriviaList trivia = body
                                                              .GetTrailingTrivia()
                                                              .EmptyIfWhitespace()
                                                              .AddRange(token.LeadingTrivia.EmptyIfWhitespace())
                                                              .AddRange(token.TrailingTrivia);

                                    AccessorDeclarationSyntax newNode = accessorDeclaration
                                                                        .WithBody(body.WithTrailingTrivia(trivia))
                                                                        .WithSemicolonToken(default(SyntaxToken));

                                    return(context.Document.ReplaceNodeAsync(accessorDeclaration, newNode, cancellationToken));
                                },
                            GetEquivalenceKey(diagnostic));

                        context.RegisterCodeFix(codeAction, diagnostic);
                        break;
                    }
                    }

                    break;
                }

                case CompilerDiagnosticIdentifiers.CannotConvertType:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.ChangeForEachType))
                    {
                        break;
                    }

                    if (token.Kind() != SyntaxKind.ForEachKeyword)
                    {
                        break;
                    }

                    if (!(token.Parent is ForEachStatementSyntax forEachStatement))
                    {
                        break;
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    ForEachStatementInfo info = semanticModel.GetForEachStatementInfo(forEachStatement);

                    ITypeSymbol typeSymbol = info.ElementType;

                    if (typeSymbol.SupportsExplicitDeclaration())
                    {
                        CodeFixRegistrator.ChangeType(context, diagnostic, forEachStatement.Type, typeSymbol, semanticModel, CodeFixIdentifiers.ChangeForEachType);
                    }

                    CodeFixRegistrator.ChangeTypeToVar(context, diagnostic, forEachStatement.Type, CodeFixIdentifiers.ChangeTypeToVar);
                    break;
                }

                case CompilerDiagnosticIdentifiers.OptionalParametersMustAppearAfterAllRequiredParameters:
                {
                    if (!Settings.IsEnabled(diagnostic.Id, CodeFixIdentifiers.AddDefaultValueToParameter))
                    {
                        break;
                    }

                    if (!(token.Parent is BaseParameterListSyntax parameterList))
                    {
                        break;
                    }

                    SeparatedSyntaxList <ParameterSyntax> parameters = parameterList.Parameters;

                    ParameterSyntax parameter = null;

                    for (int i = 0; i < parameters.Count; i++)
                    {
                        ParameterSyntax p = parameters[i];

                        if (p.FullSpan.End <= token.SpanStart)
                        {
                            parameter = p;
                        }
                        else
                        {
                            break;
                        }
                    }

                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                    ITypeSymbol typeSymbol = parameterSymbol.Type;

                    if (typeSymbol.Kind == SymbolKind.ErrorType)
                    {
                        break;
                    }

                    CodeAction codeAction = CodeAction.Create(
                        "Add default value",
                        cancellationToken =>
                        {
                            ExpressionSyntax defaultValue = typeSymbol.GetDefaultValueSyntax(context.Document.GetDefaultSyntaxOptions());

                            ParameterSyntax newParameter = parameter
                                                           .WithDefault(EqualsValueClause(defaultValue).WithTrailingTrivia(parameter.GetTrailingTrivia()))
                                                           .WithoutTrailingTrivia()
                                                           .WithFormatterAnnotation();

                            return(context.Document.ReplaceNodeAsync(parameter, newParameter, cancellationToken));
                        },
                        GetEquivalenceKey(diagnostic));

                    context.RegisterCodeFix(codeAction, diagnostic);
                    break;
                }
                }
            }
        }
Example #11
0
 public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
 {
     VisitBlock(node.Body);
 }
        private static bool IsMultiline(AccessorDeclarationSyntax accessorDeclaration)
        {
            var lineSpan = accessorDeclaration.GetLineSpan();

            return(lineSpan.StartLinePosition.Line != lineSpan.EndLinePosition.Line);
        }
        private static void AnalyzeAccessorDeclarationBlock(
            SyntaxNodeAnalysisContext context,
            AccessorDeclarationSyntax accessor,
            BlockSyntax body)
        {
            if (body.ContainsDirectives)
                return;

            if (accessor.AttributeLists.Any())
                return;

            BodyStyle style = context.GetBodyStyle();

            if (style.IsDefault)
                return;

            bool isGetter = accessor.IsKind(SyntaxKind.GetAccessorDeclaration);

            BlockExpressionAnalysis analysis = BlockExpressionAnalysis.Create(body, allowExpressionStatement: !isGetter);

            ExpressionSyntax expression = analysis.Expression;

            if (expression == null)
                return;

            if (!style.UseExpression)
                return;

            if (style.UseBlockWhenExpressionIsMultiLine == true
                && expression.IsMultiLine())
            {
                return;
            }

            if (isGetter
                && accessor.Parent is AccessorListSyntax accessorList
                && accessorList.Accessors.Count == 1)
            {
                if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(accessorList.OpenBraceToken))
                    return;

                if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(accessor.Keyword))
                    return;

                if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(body.OpenBraceToken))
                    return;

                if (style.UseBlockWhenDeclarationIsMultiLine == true)
                {
                    switch (accessorList.Parent.Kind())
                    {
                        case SyntaxKind.PropertyDeclaration:
                            {
                                if (accessor.SyntaxTree.IsMultiLineSpan(((PropertyDeclarationSyntax)accessorList.Parent).HeaderSpan()))
                                    return;

                                break;
                            }
                        case SyntaxKind.IndexerDeclaration:
                            {
                                if (accessor.SyntaxTree.IsMultiLineSpan(((IndexerDeclarationSyntax)accessorList.Parent).HeaderSpan()))
                                    return;

                                break;
                            }
                        default:
                            {
                                SyntaxDebug.Fail(accessorList.Parent);
                                break;
                            }
                    }

                    return;
                }

                ReportDiagnostic(context, accessorList);
                return;
            }

            if (!accessor.Keyword.TrailingTrivia.IsEmptyOrWhitespace())
                return;

            if (!SyntaxTriviaAnalysis.IsExteriorTriviaEmptyOrWhitespace(body.OpenBraceToken))
                return;

            if (!accessor.Keyword.LeadingTrivia.IsEmptyOrWhitespace())
                return;

            ReportDiagnostic(context, body);
        }
        internal static bool TryGetAccessorDeclaration(this BasePropertyDeclarationSyntax property, SyntaxKind kind, out AccessorDeclarationSyntax result)
        {
            result = null;
            var accessors = property?.AccessorList?.Accessors;

            if (accessors == null)
            {
                return(false);
            }

            foreach (var accessor in accessors.Value)
            {
                if (accessor.IsKind(kind))
                {
                    result = accessor;
                    return(true);
                }
            }

            return(false);
        }
 internal static bool TryGetSetAccessorDeclaration(this BasePropertyDeclarationSyntax property, out AccessorDeclarationSyntax result)
 {
     return(TryGetAccessorDeclaration(property, SyntaxKind.SetAccessorDeclaration, out result));
 }
        public static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context)
        {
            var property = (PropertyDeclarationSyntax)context.Node;

            if (property.ContainsDiagnostics)
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            IFieldSymbol fieldSymbol = null;

            AccessorDeclarationSyntax getter = null;
            AccessorDeclarationSyntax setter = null;

            ArrowExpressionClauseSyntax expressionBody = property.ExpressionBody;

            if (expressionBody != null)
            {
                IdentifierNameSyntax identifierName = GetIdentifierNameFromExpression(expressionBody.Expression);

                if (identifierName != null)
                {
                    fieldSymbol = GetBackingFieldSymbol(identifierName, semanticModel, cancellationToken);
                }
            }
            else
            {
                getter = property.Getter();

                if (getter != null)
                {
                    setter = property.Setter();

                    if (setter != null)
                    {
                        fieldSymbol = GetBackingFieldSymbol(getter, setter, semanticModel, cancellationToken);
                    }
                    else
                    {
                        IdentifierNameSyntax identifierName = GetIdentifierNameFromGetter(getter);

                        if (identifierName != null)
                        {
                            fieldSymbol = GetBackingFieldSymbol(identifierName, semanticModel, cancellationToken);
                        }
                    }
                }
            }

            if (fieldSymbol == null)
            {
                return;
            }

            var variableDeclarator = (VariableDeclaratorSyntax)fieldSymbol.GetSyntax(cancellationToken);

            if (variableDeclarator.SyntaxTree != property.SyntaxTree)
            {
                return;
            }

            if (!CheckPreprocessorDirectives(property))
            {
                return;
            }

            if (!CheckPreprocessorDirectives(variableDeclarator))
            {
                return;
            }

            IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(property, cancellationToken);

            if (propertySymbol?.IsStatic != fieldSymbol.IsStatic)
            {
                return;
            }

            if (!propertySymbol.ExplicitInterfaceImplementations.IsDefaultOrEmpty)
            {
                return;
            }

            if (!propertySymbol.Type.Equals(fieldSymbol.Type))
            {
                return;
            }

            if (propertySymbol.ContainingType?.Equals(fieldSymbol.ContainingType) != true)
            {
                return;
            }

            if (setter == null &&
                propertySymbol.IsOverride &&
                propertySymbol.OverriddenProperty?.SetMethod != null)
            {
                return;
            }

            cancellationToken.ThrowIfCancellationRequested();

            foreach (AttributeData attributeData in fieldSymbol.GetAttributes())
            {
                if (attributeData.AttributeClass.HasMetadataName(MetadataNames.System_NonSerializedAttribute))
                {
                    return;
                }
            }

            if (HasStructLayoutAttributeWithExplicitKind(propertySymbol.ContainingType))
            {
                return;
            }

            if (!IsFixableBackingField(property, propertySymbol, fieldSymbol, context.Compilation, semanticModel, cancellationToken))
            {
                return;
            }

            context.ReportDiagnostic(DiagnosticDescriptors.UseAutoProperty, property.Identifier);

            if (property.ExpressionBody != null)
            {
                context.ReportNode(DiagnosticDescriptors.UseAutoPropertyFadeOut, property.ExpressionBody);
            }
            else
            {
                if (getter != null)
                {
                    FadeOut(getter);
                }

                if (setter != null)
                {
                    FadeOut(setter);
                }
            }

            void FadeOut(AccessorDeclarationSyntax accessor)
            {
                BlockSyntax body = accessor.Body;

                if (body != null)
                {
                    switch (body.Statements.First())
                    {
                    case ReturnStatementSyntax returnStatement:
                    {
                        context.ReportToken(DiagnosticDescriptors.UseAutoPropertyFadeOut, returnStatement.ReturnKeyword);
                        context.ReportNode(DiagnosticDescriptors.UseAutoPropertyFadeOut, returnStatement.Expression);
                        break;
                    }

                    case ExpressionStatementSyntax expressionStatement:
                    {
                        context.ReportNode(DiagnosticDescriptors.UseAutoPropertyFadeOut, expressionStatement.Expression);
                        break;
                    }
                    }

                    context.ReportBraces(DiagnosticDescriptors.UseAutoPropertyFadeOut, body);
                }
                else
                {
                    context.ReportNode(DiagnosticDescriptors.UseAutoPropertyFadeOut, accessor.ExpressionBody);
                }
            }
        }
Example #17
0
 private static IdentifierNameSyntax?GetIdentifierUsedInGetter(AccessorDeclarationSyntax getter)
 {
     if (getter.Body is { Statements : { Count : 1 } } && getter.Body.Statements[0] is ReturnStatementSyntax returnStatement)
Example #18
0
 private static bool OnlyThrows(AccessorDeclarationSyntax accessor) =>
 (accessor.Body?.Statements.Count == 1 &&
  accessor.Body.Statements[0] is ThrowStatementSyntax) ||
 ThrowExpressionSyntaxWrapper.IsInstance(accessor.ExpressionBody()?.Expression);
        protected IEnumerable <CodeAction> GetActions(Document document, SyntaxNode root, MethodDeclarationSyntax methodNode, AccessorDeclarationSyntax getterNode)
        {
            if (methodNode != null)
            {
                return(GetActions(document, root, methodNode));
            }

            if (getterNode != null)
            {
                return(GetActions(document, root, getterNode));
            }

            return(Enumerable.Empty <CodeAction>());
        }
 public static BlockExpressionAnalysis Create(AccessorDeclarationSyntax accessor)
 {
     return(Create(accessor.Body));
 }
 public static string AccessorDeclaration(AccessorDeclarationSyntax node)
 {
     //TODO: implement this
     return(SyntaxNode(node.Body));
 }
 public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
 {
     AddLocation(node.Keyword);
     base.VisitAccessorDeclaration(node);
 }
Example #23
0
 private static bool IsAutoAccessor(AccessorDeclarationSyntax accessor)
 {
     return(accessor.Body == null && accessor.ExpressionBody == null);
 }
 internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
 {
     return(GetSpeculativeSemanticModelForMethodBody(parentModel, position, accessor.Body, out speculativeModel));
 }
Example #25
0
 public override void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
 {
     Visit(node.Body);
     Visit(node.ExpressionBody);
 }
Example #26
0
 internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
 {
     throw ExceptionUtilities.Unreachable;
 }
 private static ExpressionSyntax GetExpressionOrThrowExpression(AccessorDeclarationSyntax accessor)
 {
     return(GetExpression(accessor.Body));
 }
        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;

            // 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;
                }
            }
        }
Example #29
0
 internal override bool TryGetSpeculativeSemanticModelForMethodBodyCore(SyntaxTreeSemanticModel parentModel, int position, AccessorDeclarationSyntax accessor, out SemanticModel speculativeModel)
 {
     speculativeModel = null;
     return(false);
 }
        private void HandleProperty(SyntaxNodeAnalysisContext context)
        {
            var propertyDeclaration = (PropertyDeclarationSyntax)context.Node;

            if (propertyDeclaration.ExpressionBody != null)
            {
                return;
            }

            foreach (var declaration in propertyDeclaration.DescendantNodesAndTokensAndSelf())
            {
                foreach (var trivia in declaration.GetLeadingTrivia())
                {
                    if (!trivia.IsWhitespaceTrivia())
                    {
                        return;
                    }
                }

                foreach (var trivia in declaration.GetTrailingTrivia())
                {
                    if (!trivia.IsWhitespaceTrivia())
                    {
                        return;
                    }
                }
            }

            foreach (var accessor in propertyDeclaration.AccessorList.Accessors)
            {
                if (accessor.Keyword.IsKind(SyntaxKind.SetKeyword))
                {
                    return;
                }
            }

            AccessorDeclarationSyntax getter = null;

            foreach (var accessor in propertyDeclaration.AccessorList.Accessors)
            {
                if (accessor.Keyword.IsKind(SyntaxKind.GetKeyword))
                {
                    getter = accessor;
                    break;
                }
            }
            if (getter == null)
            {
                return;
            }

            foreach (var list in getter.AttributeLists)
            {
                if (list.Attributes.Any())
                {
                    return;
                }
            }

            if (getter.Body?.Statements.Count != 1)
            {
                return;
            }

            if (!Nodes.Contains(getter.Body.Statements[0].Kind()))
            {
                return;
            }

            var statement = getter.Body.Statements.First();

            context.ReportDiagnostic(Diagnostic.Create(Rule, statement.GetLocation(), "Property", propertyDeclaration.Identifier));
        }
Example #31
0
 private static IEnumerable <SyntaxKind> GetModifierKinds(AccessorDeclarationSyntax accessor)
 {
     return(accessor.Modifiers.Select(m => m.Kind()));
 }
        private static SyntaxNode ReformatAccessorAsSingleLine(IndentationSettings indentationSettings, AccessorDeclarationSyntax accessor)
        {
            var newAccessor = accessor
                              .WithModifiers(ReformatModifiersAsSingleLine(accessor.Modifiers))
                              .WithKeyword(ReformatKeywordAsSingleLine(accessor.Keyword))
                              .WithBody(ReformatBodyAsSingleLine(accessor.Body));

            var accessorList = (AccessorListSyntax)accessor.Parent;

            var indentationSteps = IndentationHelper.GetIndentationSteps(indentationSettings, accessorList.OpenBraceToken);
            var indentation      = IndentationHelper.GenerateWhitespaceTrivia(indentationSettings, indentationSteps + 1);

            newAccessor = newAccessor.WithLeadingTrivia(newAccessor.GetLeadingTrivia().Insert(0, indentation));
            return(newAccessor);
        }
 public virtual void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
 {
     DefaultVisit(node);
 }
Example #34
0
        public void VisitAccessorDeclaration(AccessorDeclarationSyntax node)
        {
            if (node == null)
                throw new ArgumentNullException("node");

            node.Validate();

            WriteLeadingTrivia(node);

            var accessorList = node.Parent as AccessorListSyntax;

            bool isSimple =
                _writer.Configuration.LineBreaksAndWrapping.Other.PlaceAbstractAutoPropertyIndexerEventDeclarationOnSingleLine &&
                accessorList != null &&
                accessorList.Accessors.All(p =>
                    (!HasExtras(p) || _writer.Configuration.LineBreaksAndWrapping.Other.PlaceSingleLineAccessorAttributeOnSameLine) &&
                    p.Body == null
                );

            if (!isSimple)
            {
                isSimple =
                    _writer.Configuration.LineBreaksAndWrapping.Other.PlaceSimplePropertyIndexerEventDeclarationOnSingleLine &&
                    accessorList != null &&
                    accessorList.Accessors.All(p =>
                        (!HasExtras(p) || _writer.Configuration.LineBreaksAndWrapping.Other.PlaceSingleLineAccessorAttributeOnSameLine) &&
                        IsSimpleBody(p.Body)
                    );
            }

            if (!isSimple)
                _writer.WriteIndent();

            bool isBodySimple =
                node.Body == null ||
                IsSimpleBody(node.Body);

            WriteAttributes(
                node,
                _writer.Configuration.LineBreaksAndWrapping.Other.PlaceMethodAttributeOnSameLine ||
                (
                    isBodySimple
                    ? _writer.Configuration.LineBreaksAndWrapping.Other.PlaceSingleLineAccessorAttributeOnSameLine
                    : _writer.Configuration.LineBreaksAndWrapping.Other.PlaceMultiLineAccessorAttributeOnSameLine
                )
            );

            if (node.Modifiers != Modifiers.None)
            {
                _writer.WriteModifiers(node.Modifiers);
                _writer.WriteSpace();
            }

            switch (node.Kind)
            {
                case AccessorDeclarationKind.Add: _writer.WriteKeyword(PrinterKeyword.Add); break;
                case AccessorDeclarationKind.Get: _writer.WriteKeyword(PrinterKeyword.Get); break;
                case AccessorDeclarationKind.Remove: _writer.WriteKeyword(PrinterKeyword.Remove); break;
                case AccessorDeclarationKind.Set: _writer.WriteKeyword(PrinterKeyword.Set); break;
                default: throw new InvalidOperationException("Invalid enum value");
            }

            if (node.Body != null)
            {
                if (
                    isSimple || (
                        _writer.Configuration.LineBreaksAndWrapping.Other.PlaceSimpleAccessorOnSingleLine &&
                        isBodySimple
                    )
                )
                {
                    _writer.PushSingleLineBody(true);

                    node.Body.Accept(this);

                    if (!isSimple)
                        _writer.WriteLine();

                    _writer.PopSingleLineBody();
                }
                else
                {
                    node.Body.Accept(this);
                }
            }
            else
            {
                _writer.WriteSyntax(Syntax.Semicolon);

                if (!isSimple)
                    _writer.WriteLine();
            }

            WriteTrailingTrivia(node);
        }