private bool TryComputeRefactoring( CodeRefactoringContext context, SyntaxNode root, SyntaxNode declaration, OptionSet optionSet, UseExpressionBodyHelper helper) { var document = context.Document; var succeeded = false; if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: false)) { context.RegisterRefactoring(new MyCodeAction( helper.UseExpressionBodyTitle.ToString(), c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: true, cancellationToken: c)), declaration.Span); succeeded = true; } var(canOffer, _) = helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: false); if (canOffer) { context.RegisterRefactoring( new MyCodeAction( helper.UseBlockBodyTitle.ToString(), c => UpdateDocumentAsync( document, root, declaration, helper, useExpressionBody: false, cancellationToken: c)), declaration.Span); succeeded = true; } return(succeeded); }
private static SyntaxNode?TryGetDeclaration( UseExpressionBodyHelper helper, SourceText text, SyntaxNode node, int position ) { var declaration = GetDeclaration(node, helper); if (declaration == null) { return(null); } if (position < declaration.SpanStart) { // The user is allowed to be before the starting point of this node, as long as // they're only between the start of the node and the start of the same line the // node starts on. This prevents unnecessarily showing this feature in areas like // the comment of a method. if (!text.AreOnSameLine(position, declaration.SpanStart)) { return(null); } } return(declaration); }
private static async Task <Document> UpdateDocumentAsync( Document document, SyntaxNode root, SyntaxNode declaration, UseExpressionBodyHelper helper, bool useExpressionBody, CancellationToken cancellationToken ) { var semanticModel = await document .GetSemanticModelAsync(cancellationToken) .ConfigureAwait(false); var updatedDeclaration = helper.Update(semanticModel, declaration, useExpressionBody); var parent = declaration is AccessorDeclarationSyntax ? declaration.Parent : declaration; RoslynDebug.Assert(parent is object); var updatedParent = parent .ReplaceNode(declaration, updatedDeclaration) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(parent, updatedParent); return(document.WithSyntaxRoot(newRoot)); }
private Task <Document> UpdateDocumentAsync( Document document, SyntaxNode root, SyntaxNode declaration, OptionSet options, UseExpressionBodyHelper helper, bool useExpressionBody, CancellationToken cancellationToken) { var updatedDeclaration = helper.Update(declaration, options, useExpressionBody) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(declaration, updatedDeclaration); return(Task.FromResult(document.WithSyntaxRoot(newRoot))); }
private SyntaxNode GetDeclaration(SyntaxNode node, UseExpressionBodyHelper helper) { for (var current = node; current != null; current = current.Parent) { if (helper.SyntaxKinds.Contains(current.Kind())) { return(current); } } return(null); }
private Task <Document> UpdateDocumentAsync( Document document, SyntaxNode root, SyntaxNode declaration, OptionSet options, UseExpressionBodyHelper helper, bool useExpressionBody, CancellationToken cancellationToken) { var parseOptions = root.SyntaxTree.Options; var updatedDeclaration = helper.Update(declaration, options, parseOptions, useExpressionBody); var parent = declaration is AccessorDeclarationSyntax ? declaration.Parent : declaration; var updatedParent = parent.ReplaceNode(declaration, updatedDeclaration) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(parent, updatedParent); return(Task.FromResult(document.WithSyntaxRoot(newRoot))); }
private Diagnostic AnalyzeSyntax( OptionSet optionSet, SyntaxNode declaration, UseExpressionBodyHelper helper) { var preferExpressionBodiedOption = optionSet.GetOption(helper.Option); var severity = preferExpressionBodiedOption.Notification.Value; if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true)) { var location = severity == DiagnosticSeverity.Hidden ? declaration.GetLocation() : helper.GetDiagnosticLocation(declaration); var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); var properties = ImmutableDictionary <string, string> .Empty.Add(nameof(UseExpressionBody), ""); return(Diagnostic.Create( CreateDescriptorWithId(helper.DiagnosticId, helper.UseExpressionBodyTitle, helper.UseExpressionBodyTitle, severity, GetCustomTags(severity)), location, additionalLocations: additionalLocations, properties: properties)); } var(canOffer, fixesError) = helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true); if (canOffer) { // They have an expression body. Create a diagnostic to convert it to a block // if they don't want expression bodies for this member. var location = severity == DiagnosticSeverity.Hidden ? declaration.GetLocation() : helper.GetExpressionBody(declaration).GetLocation(); var properties = ImmutableDictionary <string, string> .Empty; if (fixesError) { properties = properties.Add(FixesError, ""); } var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); return(Diagnostic.Create( CreateDescriptorWithId(helper.DiagnosticId, helper.UseBlockBodyTitle, helper.UseBlockBodyTitle, severity, GetCustomTags(severity)), location, additionalLocations: additionalLocations, properties: properties)); } return(null); }
private static Diagnostic?AnalyzeSyntax( OptionSet optionSet, SyntaxNode declaration, UseExpressionBodyHelper helper) { var preferExpressionBodiedOption = optionSet.GetOption(helper.Option); var severity = preferExpressionBodiedOption.Notification.Severity; if (helper.CanOfferUseExpressionBody(optionSet, declaration, forAnalyzer: true)) { var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden ? declaration.GetLocation() : helper.GetDiagnosticLocation(declaration); var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); var properties = ImmutableDictionary <string, string?> .Empty.Add(nameof(UseExpressionBody), ""); return(DiagnosticHelper.Create( CreateDescriptorWithId(helper.DiagnosticId, helper.EnforceOnBuild, helper.UseExpressionBodyTitle, helper.UseExpressionBodyTitle), location, severity, additionalLocations: additionalLocations, properties: properties)); } if (helper.CanOfferUseBlockBody(optionSet, declaration, forAnalyzer: true, out var fixesError, out var expressionBody)) { // They have an expression body. Create a diagnostic to convert it to a block // if they don't want expression bodies for this member. var location = severity.WithDefaultSeverity(DiagnosticSeverity.Hidden) == ReportDiagnostic.Hidden ? declaration.GetLocation() : expressionBody.GetLocation(); var properties = ImmutableDictionary <string, string?> .Empty; if (fixesError) { properties = properties.Add(FixesError, ""); } var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); return(DiagnosticHelper.Create( CreateDescriptorWithId(helper.DiagnosticId, helper.EnforceOnBuild, helper.UseBlockBodyTitle, helper.UseBlockBodyTitle), location, severity, additionalLocations: additionalLocations, properties: properties)); } return(null); }