public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, _, cancellationToken) = context; var declaration = await context.TryGetRelevantNodeAsync <TLocalDeclaration>().ConfigureAwait(false); if (declaration == null) { return; } var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); var variables = syntaxFacts.GetVariablesOfLocalDeclarationStatement(declaration); if (variables.Count != 1) { return; } var service = document.GetRequiredLanguageService <IMoveDeclarationNearReferenceService>(); if (!await service.CanMoveDeclarationNearReferenceAsync(document, declaration, cancellationToken).ConfigureAwait(false)) { return; } context.RegisterRefactoring( CodeAction.CreateWithPriority( CodeActionPriority.Low, FeaturesResources.Move_declaration_near_reference, c => MoveDeclarationNearReferenceAsync(document, declaration, c), nameof(FeaturesResources.Move_declaration_near_reference)), declaration.Span); }
public override Task RegisterCodeFixesAsync(CodeFixContext context) { context.RegisterCodeFix( CodeAction.CreateWithPriority( CodeActionPriority.Low, CSharpAnalyzersResources.Use_pattern_matching, GetDocumentUpdater(context), nameof(CSharpAnalyzersResources.Use_pattern_matching)), context.Diagnostics); return(Task.CompletedTask); }
private async Task CheckItemsAsync( CodeFixContext context, SyntaxToken nameToken, bool isGeneric, CompletionList completionList, WordSimilarityChecker similarityChecker) { var document = context.Document; var cancellationToken = context.CancellationToken; var onlyConsiderGenerics = isGeneric; var results = new MultiDictionary <double, string>(); foreach (var item in completionList.ItemsList) { if (onlyConsiderGenerics && !IsGeneric(item)) { continue; } var candidateText = item.FilterText; if (!similarityChecker.AreSimilar(candidateText, out var matchCost)) { continue; } var insertionText = await GetInsertionTextAsync(document, item, cancellationToken : cancellationToken).ConfigureAwait(false); results.Add(matchCost, insertionText); } var nameText = nameToken.ValueText; var codeActions = results.OrderBy(kvp => kvp.Key) .SelectMany(kvp => kvp.Value.Order()) .Where(t => t != nameText) .Take(3) .Select(n => CreateCodeAction(nameToken, nameText, n, document)) .ToImmutableArrayOrEmpty <CodeAction>(); if (codeActions.Length > 1) { // Wrap the spell checking actions into a single top level suggestion // so as to not clutter the list. context.RegisterCodeFix( CodeAction.CreateWithPriority( CodeActionPriority.Low, string.Format(FeaturesResources.Fix_typo_0, nameText), codeActions, isInlinable: true), context.Diagnostics); } else { context.RegisterFixes(codeActions, context.Diagnostics); } }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var literalExpression = await context.TryGetRelevantNodeAsync <TStringExpressionSyntax>().ConfigureAwait(false); if (literalExpression == null || !IsAppropriateLiteralKind(literalExpression)) { return; } var(document, _, cancellationToken) = context; var charService = document.GetRequiredLanguageService <IVirtualCharLanguageService>(); using var _ = ArrayBuilder <SyntaxToken> .GetInstance(out var subStringTokens); // First, ensure that we understand all text parts of the interpolation. AddSubStringTokens(literalExpression, subStringTokens); foreach (var subToken in subStringTokens) { var chars = charService.TryConvertToVirtualChars(subToken); if (chars.IsDefault) { return; } } // Note: This is a generally useful feature on strings. But it's not likely to be something // people want to use a lot. Make low priority so it doesn't interfere with more // commonly useful refactorings. if (IsVerbatim(literalExpression)) { // always offer to convert from verbatim string to normal string. context.RegisterRefactoring(CodeAction.CreateWithPriority( CodeActionPriority.Low, CSharpFeaturesResources.Convert_to_regular_string, c => ConvertToRegularStringAsync(document, literalExpression, c), nameof(CSharpFeaturesResources.Convert_to_regular_string))); } else if (ContainsSimpleEscape(charService, subStringTokens)) { // Offer to convert to a verbatim string if the normal string contains simple // escapes that can be directly embedded in the verbatim string. context.RegisterRefactoring(CodeAction.CreateWithPriority( CodeActionPriority.Low, CSharpFeaturesResources.Convert_to_verbatim_string, c => ConvertToVerbatimStringAsync(document, literalExpression, c), nameof(CSharpFeaturesResources.Convert_to_verbatim_string))); } }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, span, cancellationToken) = context; if (!span.IsEmpty) { return; } if (!IsApplication(document.Project.CompilationOptions !)) { return; } var position = span.Start; var root = (CompilationUnitSyntax)await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (!root.IsTopLevelProgram()) { return; } var acceptableLocation = GetUseProgramMainDiagnosticLocation(root, isHidden: true); if (!acceptableLocation.SourceSpan.IntersectsWith(position)) { return; } var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var option = optionSet.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false); if (!CanOfferUseProgramMain(option, root, compilation, forAnalyzer: false)) { return; } context.RegisterRefactoring(CodeAction.CreateWithPriority( CodeActionPriority.Low, CSharpAnalyzersResources.Convert_to_Program_Main_style_program, c => ConvertToProgramMainAsync(document, c), nameof(CSharpAnalyzersResources.Convert_to_Program_Main_style_program))); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, _, cancellationToken) = context; var typeAndPriority = await GetRelevantTypeFromHeaderAsync(context).ConfigureAwait(false) ?? await GetRelevantTypeFromMethodAsync(context).ConfigureAwait(false); if (typeAndPriority == null) { return; } var(type, priority) = typeAndPriority.Value; var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var compilation = semanticModel.Compilation; var debuggerAttributeTypeSymbol = compilation.GetTypeByMetadataName("System.Diagnostics.DebuggerDisplayAttribute"); if (debuggerAttributeTypeSymbol is null) { return; } var typeSymbol = (INamedTypeSymbol)semanticModel.GetRequiredDeclaredSymbol(type, context.CancellationToken); if (typeSymbol.IsStatic || !IsClassOrStruct(typeSymbol)) { return; } if (HasDebuggerDisplayAttribute(typeSymbol, compilation)) { return; } context.RegisterRefactoring(CodeAction.CreateWithPriority( priority, FeaturesResources.Add_DebuggerDisplay_attribute, c => ApplyAsync(document, type, debuggerAttributeTypeSymbol, c), nameof(FeaturesResources.Add_DebuggerDisplay_attribute))); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, span, cancellationToken) = context; // can only suggest moving to top level statement on c# 9 or above. if (document.Project.ParseOptions !.LanguageVersion() < LanguageVersion.CSharp9 || !IsApplication(document.Project.CompilationOptions !)) { return; } var methodDeclaration = await context.TryGetRelevantNodeAsync <MethodDeclarationSyntax>().ConfigureAwait(false); if (methodDeclaration is null) { return; } var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); var option = options.GetOption(CSharpCodeStyleOptions.PreferTopLevelStatements); if (!CanOfferUseTopLevelStatements(option, forAnalyzer: false)) { return; } var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var compilation = semanticModel.Compilation; if (!IsProgramMainMethod(semanticModel, methodDeclaration, GetMainTypeName(compilation), cancellationToken, out var canConvert) || !canConvert) { return; } context.RegisterRefactoring(CodeAction.CreateWithPriority( CodeActionPriority.Low, CSharpAnalyzersResources.Convert_to_top_level_statements, c => ConvertToTopLevelStatementsAsync(document, methodDeclaration, context.Options, c), nameof(CSharpAnalyzersResources.Convert_to_top_level_statements))); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var(document, _, cancellationToken) = context; var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (root is null) { return; } var token = root.FindToken(context.Span.Start); if (!context.Span.IntersectsWith(token.Span)) { return; } var syntaxKinds = document.GetRequiredLanguageService <ISyntaxKindsService>(); if (token.RawKind != syntaxKinds.StringLiteralToken) { return; } var literalExpression = token.GetRequiredParent(); // Check the string literal for errors. This will ensure that we do not try to fixup an incomplete string. if (literalExpression.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error)) { return; } if (!token.Text.Contains('{') && !token.Text.Contains('}')) { return; } var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); if (!syntaxFacts.SupportsConstantInterpolatedStrings(document.Project.ParseOptions !)) { // If there is a const keyword, do not offer the refactoring (an interpolated string is not const) var declarator = literalExpression.FirstAncestorOrSelf <SyntaxNode>(syntaxFacts.IsVariableDeclarator); if (declarator != null) { var generator = SyntaxGenerator.GetGenerator(document); if (generator.GetModifiers(declarator).IsConst) { return; } } // Attributes also only allow constant values. var attribute = literalExpression.FirstAncestorOrSelf <SyntaxNode>(syntaxFacts.IsAttribute); if (attribute != null) { return; } } context.RegisterRefactoring( CodeAction.CreateWithPriority( CodeActionPriority.Low, FeaturesResources.Convert_to_interpolated_string, _ => UpdateDocumentAsync(document, root, token), nameof(FeaturesResources.Convert_to_interpolated_string)), literalExpression.Span); }