private static Diagnostic?AnalyzeSyntax( SemanticModel semanticModel, CodeStyleOption2 <ExpressionBodyPreference> option, LambdaExpressionSyntax declaration, CancellationToken cancellationToken) { if (UseExpressionBodyForLambdaHelpers.CanOfferUseExpressionBody(option.Value, declaration, declaration.GetLanguageVersion())) { var location = GetDiagnosticLocation(declaration); var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); var properties = ImmutableDictionary <string, string?> .Empty; return(DiagnosticHelper.Create( s_useExpressionBodyForLambda, location, option.Notification.Severity, additionalLocations, properties)); } if (UseExpressionBodyForLambdaHelpers.CanOfferUseBlockBody(semanticModel, option.Value, declaration, cancellationToken)) { // 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 = GetDiagnosticLocation(declaration); var properties = ImmutableDictionary <string, string?> .Empty; var additionalLocations = ImmutableArray.Create(declaration.GetLocation()); return(DiagnosticHelper.Create( s_useBlockBodyForLambda, location, option.Notification.Severity, additionalLocations, properties)); } return(null); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; var cancellationToken = context.CancellationToken; var optionProvider = await document.GetAnalyzerOptionsProviderAsync(cancellationToken).ConfigureAwait(false); var optionValue = UseExpressionBodyForLambdaHelpers.GetCodeStyleOption(optionProvider); var severity = UseExpressionBodyForLambdaHelpers.GetOptionSeverity(optionValue); switch (severity) { case ReportDiagnostic.Suppress: case ReportDiagnostic.Hidden: // if the severity is Hidden that's equivalent to 'refactoring only', so we want // to try to compute the refactoring here. // // If the severity is 'suppress', that means the user doesn't want the actual // analyzer to run here. However, we can still check to see if we could offer // the feature here as a refactoring. await ComputeRefactoringsAsync(context, optionValue.Value, analyzerActive : false).ConfigureAwait(false); return; case ReportDiagnostic.Error: case ReportDiagnostic.Warn: case ReportDiagnostic.Info: // User has this option set at a level where we want it checked by the // DiagnosticAnalyser and not the CodeRefactoringProvider. However, we still // want to check if we want to offer the *reverse* refactoring here in this // single location. // // For example, say this is the "use expression body" feature. If the user says // they always prefer expression-bodies (with warning level), then we want the // analyzer to always be checking for that. However, we still want to offer the // refactoring to flip their code to use a block body here, just in case that // was something they wanted to do as a one off (i.e. before adding new // statements. // // TODO(cyrusn): Should we only do this for warn/info? Argument could be made // that we shouldn't even offer to refactor in the reverse direction if it will // just cause an error. That said, maybe this is just an intermediary step, and // we shouldn't really be blocking the user from making it. await ComputeRefactoringsAsync(context, optionValue.Value, analyzerActive : true).ConfigureAwait(false); return; } }
private static void AnalyzeIfEnabled(SyntaxNodeAnalysisContext context) { var analyzerOptions = context.Options; var syntaxTree = context.SemanticModel.SyntaxTree; var optionValue = UseExpressionBodyForLambdaHelpers.GetCodeStyleOption(analyzerOptions.GetAnalyzerOptions(syntaxTree)); var severity = UseExpressionBodyForLambdaHelpers.GetOptionSeverity(optionValue); switch (severity) { case ReportDiagnostic.Error: case ReportDiagnostic.Warn: case ReportDiagnostic.Info: break; default: // don't analyze if it's any other value. return; } AnalyzeSyntax(context, optionValue); }
private static async Task <ImmutableArray <CodeAction> > ComputeRefactoringsAsync( Document document, TextSpan span, ExpressionBodyPreference option, CancellationToken cancellationToken) { var lambdaNode = await document.TryGetRelevantNodeAsync <LambdaExpressionSyntax>(span, cancellationToken).ConfigureAwait(false); if (lambdaNode == null) { return(ImmutableArray <CodeAction> .Empty); } var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); using var resultDisposer = ArrayBuilder <CodeAction> .GetInstance(out var result); if (UseExpressionBodyForLambdaHelpers.CanOfferUseExpressionBody(option, lambdaNode, root.GetLanguageVersion())) { var title = UseExpressionBodyForLambdaHelpers.UseExpressionBodyTitle.ToString(); result.Add(CodeAction.Create( title, c => UpdateDocumentAsync( document, root, lambdaNode, c), title)); } var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (UseExpressionBodyForLambdaHelpers.CanOfferUseBlockBody(semanticModel, option, lambdaNode, cancellationToken)) { var title = UseExpressionBodyForLambdaHelpers.UseBlockBodyTitle.ToString(); result.Add(CodeAction.Create( title, c => UpdateDocumentAsync( document, root, lambdaNode, c), title)); } return(result.ToImmutable()); }