public static void ComputeRefactoring( RefactoringContext context, EnumDeclarationSyntax enumDeclaration, SeparatedSyntaxListSelection <EnumMemberDeclarationSyntax> selectedMembers, SemanticModel semanticModel) { if (!enumDeclaration.AttributeLists.Any()) { return; } INamedTypeSymbol enumSymbol = semanticModel.GetDeclaredSymbol(enumDeclaration, context.CancellationToken); if (enumSymbol?.HasAttribute(MetadataNames.System_FlagsAttribute) != true) { return; } IEnumerable <(IFieldSymbol symbol, ulong value)> symbolsValues = selectedMembers .Select(f => semanticModel.GetDeclaredSymbol(f, context.CancellationToken)) .Where(f => f.HasConstantValue) .Select(f => (symbol: f, value: SymbolUtility.GetEnumValueAsUInt64(f.ConstantValue, enumSymbol))) .Where(f => !FlagsUtility <ulong> .Instance.IsComposite(f.value)); ImmutableArray <ulong> constantValues = symbolsValues.Select(f => f.value).ToImmutableArray(); if (constantValues.Length <= 1) { return; } Optional <ulong> optionalValue = FlagsUtility <ulong> .Instance.Combine(constantValues); if (!optionalValue.HasValue) { return; } if (IsValueDefined(optionalValue)) { return; } string name = NameGenerator.Default.EnsureUniqueEnumMemberName( string.Concat(symbolsValues.Select(f => f.symbol.Name)), enumSymbol); context.RegisterRefactoring( $"Generate member '{name}'", ct => RefactorAsync(context.Document, enumDeclaration, selectedMembers, enumSymbol, name, semanticModel, ct), RefactoringDescriptors.GenerateCombinedEnumMember); bool IsValueDefined(object value) { foreach (ISymbol member in enumSymbol.GetMembers()) { if (member.Kind == SymbolKind.Field) { var fieldSymbol = (IFieldSymbol)member; if (fieldSymbol.HasConstantValue && object.Equals(fieldSymbol.ConstantValue, value)) { return(true); } } } return(false); } }
public static void ComputeRefactorings( RefactoringContext context, InitializerExpressionSyntax initializer, SemanticModel semanticModel) { Debug.Assert(initializer.IsKind(SyntaxKind.ObjectInitializerExpression, SyntaxKind.WithInitializerExpression), initializer.Kind().ToString()); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(initializer.Parent, context.CancellationToken); if (typeSymbol?.IsErrorType() != false) { return; } if (typeSymbol.IsAnonymousType) { return; } int position = initializer.OpenBraceToken.Span.End; ImmutableArray <ISymbol> symbols = semanticModel.LookupSymbols(position, typeSymbol); if (!symbols.Any()) { return; } SeparatedSyntaxList <ExpressionSyntax> expressions = initializer.Expressions; if (expressions.Any()) { var initializedPropertyNames = new HashSet <string>(); foreach (ExpressionSyntax expression in expressions) { Debug.Assert(expression.IsKind(SyntaxKind.SimpleAssignmentExpression), expression.Kind().ToString()); if (expression.IsKind(SyntaxKind.SimpleAssignmentExpression)) { SimpleAssignmentExpressionInfo assignmentInfo = SyntaxInfo.SimpleAssignmentExpressionInfo((AssignmentExpressionSyntax)expression); if (assignmentInfo.Success) { ExpressionSyntax left = assignmentInfo.Left; Debug.Assert(left.IsKind(SyntaxKind.IdentifierName), left.Kind().ToString()); if (left is IdentifierNameSyntax identifierName) { initializedPropertyNames.Add(identifierName.Identifier.ValueText); } } } } Dictionary <string, IPropertySymbol> namesToProperties = null; foreach (ISymbol symbol in symbols) { if (initializedPropertyNames.Contains(symbol.Name)) { continue; } IPropertySymbol propertySymbol = GetInitializableProperty(symbol, position, semanticModel); if (propertySymbol == null) { continue; } if (namesToProperties != null) { if (namesToProperties.ContainsKey(propertySymbol.Name)) { continue; } } else { namesToProperties = new Dictionary <string, IPropertySymbol>(); } namesToProperties.Add(propertySymbol.Name, propertySymbol); } if (namesToProperties != null) { Document document = context.Document; context.RegisterRefactoring( "Initialize all properties", ct => { IEnumerable <IPropertySymbol> propertySymbols = namesToProperties.Select(f => f.Value); return(RefactorAsync(document, initializer, propertySymbols, initializeToDefault: false, ct)); }, RefactoringDescriptors.AddAllPropertiesToInitializer); } } else if (HasAccessiblePropertySetter()) { Document document = context.Document; context.RegisterRefactoring( "Initialize all properties", ct => { IEnumerable <IPropertySymbol> propertySymbols = GetInitializableProperties(initializer, symbols, semanticModel); return(RefactorAsync(document, initializer, propertySymbols, initializeToDefault: false, ct)); }, RefactoringDescriptors.AddAllPropertiesToInitializer); } bool HasAccessiblePropertySetter() { foreach (ISymbol symbol in symbols) { if (GetInitializableProperty(symbol, position, semanticModel) != null) { return(true); } } return(false); } }
public static void ComputeRefactoring(RefactoringContext context, WhileStatementSyntax whileStatement) { context.RegisterRefactoring( Title, cancellationToken => RefactorAsync(context.Document, null, null, whileStatement, cancellationToken)); }
private static async Task ComputeRefactoringAsync(RefactoringContext context, ExpressionSyntax expression) { if (expression == null) { return; } if (!expression.IsKind(SyntaxKind.IdentifierName, SyntaxKind.SimpleMemberAccessExpression)) { return; } if (!context.Span.IsContainedInSpanOrBetweenSpans(expression)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var methodSymbol = semanticModel.GetSymbol(expression, context.CancellationToken) as IMethodSymbol; if (methodSymbol == null) { return; } if (methodSymbol.IsImplicitlyDeclared) { return; } if (methodSymbol.PartialDefinitionPart != null) { return; } Debug.Assert(methodSymbol.DeclaringSyntaxReferences.Any()); SyntaxReference syntaxReference = methodSymbol.DeclaringSyntaxReferences.FirstOrDefault(); if (syntaxReference == null) { return; } SyntaxNode node = await syntaxReference.GetSyntaxAsync(context.CancellationToken).ConfigureAwait(false); switch (node) { case MethodDeclarationSyntax methodDeclaration: { if (methodDeclaration.ContainsYield()) { break; } context.RegisterRefactoring( Title, cancellationToken => RefactorAsync( context.Document, expression, methodDeclaration.Modifiers, methodDeclaration.ParameterList, methodDeclaration.BodyOrExpressionBody(), cancellationToken)); break; } case LocalFunctionStatementSyntax localFunction: { if (localFunction.ContainsYield()) { break; } context.RegisterRefactoring( Title, cancellationToken => RefactorAsync( context.Document, expression, localFunction.Modifiers, localFunction.ParameterList, localFunction.BodyOrExpressionBody(), cancellationToken)); break; } default: { Debug.Fail(node.Kind().ToString()); break; } } }
public static async Task ComputeRefactoringAsync(RefactoringContext context, LocalDeclarationStatementSyntax localDeclaration) { VariableDeclarationSyntax declaration = localDeclaration.Declaration; TypeSyntax type = declaration?.Type; if (type?.IsVar != false) { return; } VariableDeclaratorSyntax declarator = declaration.Variables.FirstOrDefault(); if (declarator == null) { return; } if (context.Span.Start < type.SpanStart) { return; } SyntaxTriviaList triviaList = type.GetTrailingTrivia(); if (!triviaList.Any()) { return; } SyntaxTrivia trivia = triviaList .SkipWhile(f => f.IsWhitespaceTrivia()) .FirstOrDefault(); if (!trivia.IsEndOfLineTrivia()) { return; } if (context.Span.End > trivia.SpanStart) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken); string name = NameGenerator.Default.CreateUniqueLocalName( typeSymbol, semanticModel, declarator.SpanStart, cancellationToken: context.CancellationToken); if (name == null) { return; } context.RegisterRefactoring( $"Add identifier '{name}'", c => RefactorAsync(context.Document, type, name, c)); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, InvocationExpressionSyntax invocation) { SimpleMemberInvocationExpressionInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationExpressionInfo(invocation); if (!invocationInfo.Success) { return; } switch (invocationInfo.NameText) { case "First": { if (invocationInfo.Arguments.Any()) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (!UseElementAccessAnalysis.IsFixableFirst(invocationInfo, semanticModel, context.CancellationToken)) { break; } context.RegisterRefactoring( "Use [] instead of calling 'First'", cancellationToken => UseElementAccessInsteadOfEnumerableMethodRefactoring.UseElementAccessInsteadOfFirstAsync(context.Document, invocation, cancellationToken), RefactoringIdentifiers.UseElementAccessInsteadOfEnumerableMethod); break; } case "Last": { if (invocationInfo.Arguments.Any()) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (!UseElementAccessAnalysis.IsFixableLast(invocationInfo, semanticModel, context.CancellationToken)) { break; } string propertyName = CSharpUtility.GetCountOrLengthPropertyName(invocationInfo.Expression, semanticModel, context.CancellationToken); if (propertyName == null) { break; } context.RegisterRefactoring( "Use [] instead of calling 'Last'", cancellationToken => UseElementAccessInsteadOfEnumerableMethodRefactoring.UseElementAccessInsteadOfLastAsync(context.Document, invocation, propertyName, cancellationToken), RefactoringIdentifiers.UseElementAccessInsteadOfEnumerableMethod); break; } case "ElementAt": { if (invocationInfo.Arguments.SingleOrDefault(shouldThrow: false)?.Expression?.IsMissing != false) { break; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (!UseElementAccessAnalysis.IsFixableElementAt(invocationInfo, semanticModel, context.CancellationToken)) { break; } context.RegisterRefactoring( "Use [] instead of calling 'ElementAt'", cancellationToken => UseElementAccessInsteadOfEnumerableMethodRefactoring.UseElementAccessInsteadOfElementAtAsync(context.Document, invocation, cancellationToken), RefactoringIdentifiers.UseElementAccessInsteadOfEnumerableMethod); break; } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, StatementContainerSelection selectedStatements) { if (selectedStatements.Count > 1) { StatementSyntax firstStatement = selectedStatements.First(); SemanticModel semanticModel = null; ISymbol symbol = null; ObjectCreationExpressionSyntax objectCreation = null; SyntaxKind kind = firstStatement.Kind(); if (kind == SyntaxKind.LocalDeclarationStatement) { var localDeclaration = (LocalDeclarationStatementSyntax)firstStatement; VariableDeclaratorSyntax variable = localDeclaration .Declaration? .Variables .SingleOrDefault(throwException: false); objectCreation = variable?.Initializer?.Value as ObjectCreationExpressionSyntax; if (objectCreation != null) { semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); symbol = semanticModel.GetDeclaredSymbol(variable, context.CancellationToken); } } else if (kind == SyntaxKind.ExpressionStatement) { var expressionStatement = (ExpressionStatementSyntax)firstStatement; var assignment = expressionStatement.Expression as AssignmentExpressionSyntax; if (assignment != null) { objectCreation = assignment.Right as ObjectCreationExpressionSyntax; if (objectCreation != null) { semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); symbol = semanticModel.GetSymbol(assignment.Left, context.CancellationToken); } } } if (objectCreation != null && symbol?.IsErrorType() == false && selectedStatements .Skip(1) .All(f => IsValidAssignmentStatement(f, symbol, semanticModel, context.CancellationToken))) { context.RegisterRefactoring( "Collapse to initializer", cancellationToken => { return(RefactorAsync( context.Document, objectCreation, selectedStatements, cancellationToken)); }); } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, SyntaxNode node) { if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.WrapInRegion, RefactoringIdentifiers.WrapInIfDirective, RefactoringIdentifiers.RemoveEmptyLines)) { SyntaxNode root = context.Root; TextSpan span = context.Span; if (!IsFullLineSpan(node, span)) { return; } Document document = context.Document; SourceText sourceText = await document.GetTextAsync(context.CancellationToken).ConfigureAwait(false); if (!TextLineCollectionSelection.TryCreate(sourceText.Lines, span, out TextLineCollectionSelection selectedLines)) { return; } if (!IsInMultiLineDocumentationComment(root, span.Start) && !IsInMultiLineDocumentationComment(root, span.End)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.WrapInRegion)) { context.RegisterRefactoring( "Wrap in region", ct => WrapInRegionRefactoring.Instance.RefactorAsync(document, selectedLines, ct), RefactoringIdentifiers.WrapInRegion); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.WrapInIfDirective)) { context.RegisterRefactoring( "Wrap in #if", ct => WrapInIfDirectiveRefactoring.Instance.RefactorAsync(document, selectedLines, ct), RefactoringIdentifiers.WrapInIfDirective); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveEmptyLines)) { bool containsEmptyLine = false; foreach (TextLine line in selectedLines) { context.ThrowIfCancellationRequested(); if (line.IsEmptyOrWhiteSpace() && root.FindTrivia(line.End, findInsideTrivia: true).IsEndOfLineTrivia()) { containsEmptyLine = true; break; } } if (containsEmptyLine) { context.RegisterRefactoring( "Remove empty lines", ct => { ct.ThrowIfCancellationRequested(); IEnumerable <TextChange> textChanges = selectedLines .Where(line => line.IsEmptyOrWhiteSpace() && root.FindTrivia(line.End, findInsideTrivia: true).IsEndOfLineTrivia()) .Select(line => new TextChange(line.SpanIncludingLineBreak, "")); return(document.WithTextChangesAsync(textChanges, ct)); }, RefactoringIdentifiers.RemoveEmptyLines); } } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, LiteralExpressionSyntax literalExpression) { StringLiteralExpressionInfo info = SyntaxInfo.StringLiteralExpressionInfo(literalExpression); Debug.Assert(info.Success); if (!info.Success) { return; } if (context.IsRefactoringEnabled(RefactoringIdentifiers.InsertStringInterpolation) && context.SupportsCSharp6 && context.Span.End < literalExpression.Span.End && !CSharpUtility.IsPartOfExpressionThatMustBeConstant(literalExpression)) { int startIndex = GetStartIndex(info, context.Span); if (startIndex != -1) { context.RegisterRefactoring( "Insert interpolation", cancellationToken => { return(ReplaceWithInterpolatedStringAsync( context.Document, literalExpression, startIndex, context.Span.Length, addNameOf: false, cancellationToken: cancellationToken)); }, RefactoringIdentifiers.InsertStringInterpolation); if (!context.Span.IsEmpty) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); string name = StringLiteralParser.Parse(literalExpression.Token.Text, startIndex, context.Span.Length, info.IsVerbatim, isInterpolatedText: false); foreach (ISymbol symbol in semanticModel.LookupSymbols(literalExpression.SpanStart)) { if (string.Equals(name, symbol.MetadataName, StringComparison.Ordinal)) { context.RegisterRefactoring( "Insert interpolation with nameof", cancellationToken => { return(ReplaceWithInterpolatedStringAsync( context.Document, literalExpression, startIndex, context.Span.Length, addNameOf: true, cancellationToken: cancellationToken)); }, EquivalenceKey.Join(RefactoringIdentifiers.InsertStringInterpolation, "WithNameOf")); break; } } } } } if (context.Span.IsBetweenSpans(literalExpression)) { if (info.IsVerbatim) { if (info.ContainsEscapeSequence) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiteral)) { context.RegisterRefactoring( "Replace verbatim string literal with regular string literal", ct => ReplaceWithRegularStringLiteralAsync(context.Document, literalExpression, ct), RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiteral); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiterals) && info.ContainsLinefeed) { context.RegisterRefactoring( "Replace verbatim string literal with regular string literals", ct => ReplaceWithRegularStringLiteralsAsync(context.Document, literalExpression, ct), RefactoringIdentifiers.ReplaceVerbatimStringLiteralWithRegularStringLiterals); } } } else if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceRegularStringLiteralWithVerbatimStringLiteral) && info.ContainsEscapeSequence) { context.RegisterRefactoring( "Replace regular string literal with verbatim string literal", ct => ReplaceWithVerbatimStringLiteralAsync(context.Document, literalExpression, ct), RefactoringIdentifiers.ReplaceRegularStringLiteralWithVerbatimStringLiteral); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseStringEmptyInsteadOfEmptyStringLiteral) && CanReplaceWithStringEmpty(literalExpression)) { context.RegisterRefactoring( "Replace \"\" with 'string.Empty'", ct => ReplaceWithStringEmptyAsync(context.Document, literalExpression, ct), RefactoringIdentifiers.UseStringEmptyInsteadOfEmptyStringLiteral); } }
public static async Task ComputeRefactoringAsync(RefactoringContext context, EventFieldDeclarationSyntax eventFieldDeclaration) { if (eventFieldDeclaration.IsParentKind(SyntaxKind.InterfaceDeclaration)) { return; } VariableDeclarationSyntax variableDeclaration = eventFieldDeclaration.Declaration; if (variableDeclaration == null) { return; } SemanticModel semanticModel = null; foreach (VariableDeclaratorSyntax variableDeclarator in variableDeclaration.Variables) { if (!context.Span.IsContainedInSpanOrBetweenSpans(variableDeclarator.Identifier)) { continue; } semanticModel ??= await context.GetSemanticModelAsync().ConfigureAwait(false); var eventSymbol = semanticModel.GetDeclaredSymbol(variableDeclarator, context.CancellationToken) as IEventSymbol; if (eventSymbol?.IsStatic != false) { continue; } INamedTypeSymbol containingType = eventSymbol.ContainingType; if (containingType == null) { return; } if (!(eventSymbol.Type is INamedTypeSymbol eventHandlerType)) { continue; } ITypeSymbol eventArgsSymbol = GetEventArgsSymbol(eventHandlerType, semanticModel); if (eventArgsSymbol == null) { continue; } string methodName = "On" + eventSymbol.Name; if (containingType.ContainsMember <IMethodSymbol>( $"On{eventSymbol.Name}", methodSymbol => SymbolEqualityComparer.Default.Equals(eventArgsSymbol, methodSymbol.Parameters.SingleOrDefault(shouldThrow: false)?.Type))) { continue; } methodName = NameGenerator.Default.EnsureUniqueName(methodName, containingType.GetMembers()); context.RegisterRefactoring( $"Generate '{methodName}' method", cancellationToken => { return(RefactorAsync( context.Document, eventFieldDeclaration, eventSymbol, eventArgsSymbol, context.SupportsCSharp6, cancellationToken)); }, RefactoringIdentifiers.GenerateEventInvokingMethod); } }
public static void ComputeRefactoring(RefactoringContext context, MemberDeclarationSyntax member) { MemberDeclarationListInfo info = SyntaxInfo.MemberDeclarationListInfo(member.Parent); if (!info.Success) { return; } SyntaxList <MemberDeclarationSyntax> members = info.Members; if (members.Count <= 1) { return; } int index = IndexOfMemberToSwap(member, members, context.Span); if (index == -1) { return; } SyntaxTree tree = member.SyntaxTree; FileLinePositionSpan fileLinePositionSpan = tree.GetLineSpan(context.Span, context.CancellationToken); int startLine = fileLinePositionSpan.StartLine(); int endLine = fileLinePositionSpan.EndLine(); if (startLine <= tree.GetEndLine(members[index].TrimmedSpan(), context.CancellationToken)) { return; } if (endLine >= tree.GetStartLine(members[index + 1].TrimmedSpan(), context.CancellationToken)) { return; } if (context.IsRefactoringEnabled(RefactoringDescriptors.RemoveMemberDeclarations)) { context.RegisterRefactoring( "Remove members above", ct => ReplaceMembersAsync(context.Document, info, members.Skip(index + 1), ct), RefactoringDescriptors.RemoveMemberDeclarations, "Above"); context.RegisterRefactoring( "Remove members below", ct => ReplaceMembersAsync(context.Document, info, members.Take(index + 1), ct), RefactoringDescriptors.RemoveMemberDeclarations, "Below"); } if (context.IsRefactoringEnabled(RefactoringDescriptors.SwapMemberDeclarations)) { context.RegisterRefactoring( "Swap members", ct => SwapMembersAsync(context.Document, info, index, ct), RefactoringDescriptors.SwapMemberDeclarations); } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, SyntaxToken modifier) { SyntaxNode node = modifier.Parent; if (node.IsKind(SyntaxKind.DestructorDeclaration)) { return; } ModifierListInfo modifiersInfo = SyntaxInfo.ModifierListInfo(node); if (node.IsKind( SyntaxKind.ClassDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.StructDeclaration)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var symbol = (INamedTypeSymbol)semanticModel.GetDeclaredSymbol(node, context.CancellationToken); ImmutableArray <SyntaxReference> syntaxReferences = symbol.DeclaringSyntaxReferences; if (syntaxReferences.Length > 1) { ImmutableArray <MemberDeclarationSyntax> memberDeclarations = ImmutableArray.CreateRange( syntaxReferences, f => (MemberDeclarationSyntax)f.GetSyntax(context.CancellationToken)); foreach (Accessibility accessibility in AvailableAccessibilities) { if (accessibility != modifiersInfo.ExplicitAccessibility && SyntaxAccessibility.IsValidAccessibility(node, accessibility)) { context.RegisterRefactoring( GetTitle(accessibility), cancellationToken => RefactorAsync(context.Solution, memberDeclarations, accessibility, cancellationToken), EquivalenceKey.Join(RefactoringIdentifiers.ChangeAccessibility, accessibility.ToString())); } } return; } } foreach (Accessibility accessibility in AvailableAccessibilities) { if (accessibility == modifiersInfo.ExplicitAccessibility) { continue; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); ISymbol symbol = GetBaseSymbolOrDefault(semanticModel, context.CancellationToken); if (symbol != null) { if (SyntaxAccessibility.IsValidAccessibility(node, accessibility, ignoreOverride: true)) { context.RegisterRefactoring( GetTitle(accessibility), cancellationToken => RefactorAsync(context.Solution, symbol, accessibility, cancellationToken), EquivalenceKey.Join(RefactoringIdentifiers.ChangeAccessibility, accessibility.ToString())); } } else if (SyntaxAccessibility.IsValidAccessibility(node, accessibility)) { context.RegisterRefactoring( GetTitle(accessibility), cancellationToken => RefactorAsync(context.Document, node, accessibility, cancellationToken), EquivalenceKey.Join(RefactoringIdentifiers.ChangeAccessibility, accessibility.ToString())); } } ISymbol GetBaseSymbolOrDefault(SemanticModel semanticModel, CancellationToken cancellationToken) { if (modifiersInfo.GetKinds().Any(ModifierKinds.AbstractVirtualOverride)) { return(ChangeAccessibilityRefactoring.GetBaseSymbolOrDefault(node, semanticModel, cancellationToken)); } return(null); } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, BinaryExpressionSyntax binaryExpression) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateOperator)) { SyntaxToken operatorToken = binaryExpression.OperatorToken; if (operatorToken.Span.Contains(context.Span) && NegateOperatorRefactoring.CanBeNegated(operatorToken)) { context.RegisterRefactoring( "Negate operator", cancellationToken => NegateOperatorRefactoring.RefactorAsync(context.Document, operatorToken, cancellationToken)); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddBooleanComparison) && binaryExpression.IsKind(SyntaxKind.LogicalAndExpression, SyntaxKind.LogicalOrExpression) && binaryExpression.Left?.IsMissing == false && binaryExpression.Right?.IsMissing == false && context.SupportsSemanticModel) { if (binaryExpression.Left.Span.Contains(context.Span)) { await AddBooleanComparisonRefactoring.ComputeRefactoringAsync(context, binaryExpression.Left).ConfigureAwait(false); } else if (binaryExpression.Right.Span.Contains(context.Span)) { await AddBooleanComparisonRefactoring.ComputeRefactoringAsync(context, binaryExpression.Right).ConfigureAwait(false); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.FormatBinaryExpression)) { FormatBinaryExpressionRefactoring.ComputeRefactorings(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.NegateBinaryExpression)) { NegateBinaryExpressionRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandCoalesceExpression) && binaryExpression.OperatorToken.Span.Contains(context.Span) && ExpandCoalesceExpressionRefactoring.CanRefactor(binaryExpression)) { context.RegisterRefactoring( "Expand ??", cancellationToken => { return(ExpandCoalesceExpressionRefactoring.RefactorAsync( context.Document, binaryExpression, cancellationToken)); }); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.MergeStringLiterals, RefactoringIdentifiers.MergeStringLiteralsIntoMultilineStringLiteral) && MergeStringLiteralsRefactoring.CanRefactor(context, binaryExpression)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.MergeStringLiterals)) { context.RegisterRefactoring( "Merge string literals", cancellationToken => MergeStringLiteralsRefactoring.RefactorAsync(context.Document, binaryExpression, cancellationToken: cancellationToken)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MergeStringLiteralsIntoMultilineStringLiteral) && binaryExpression .DescendantTrivia(binaryExpression.Span) .Any(f => f.IsKind(SyntaxKind.EndOfLineTrivia))) { context.RegisterRefactoring( "Merge string literals into multiline string literal", cancellationToken => MergeStringLiteralsRefactoring.RefactorAsync(context.Document, binaryExpression, multiline: true, cancellationToken: cancellationToken)); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SwapExpressionsInBinaryExpression) && SwapExpressionsRefactoring.CanRefactor(binaryExpression) && context.Span.IsBetweenSpans(binaryExpression)) { context.RegisterRefactoring( "Swap expressions", cancellationToken => { return(SwapExpressionsRefactoring.RefactorAsync( context.Document, binaryExpression, cancellationToken)); }); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceAsWithCast)) { ReplaceAsWithCastRefactoring.ComputeRefactoring(context, binaryExpression); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceEqualsExpressionWithStringEquals) && context.Span.IsContainedInSpanOrBetweenSpans(binaryExpression.OperatorToken)) { await ReplaceEqualsExpressionWithStringEqualsRefactoring.ComputeRefactoringAsync(context, binaryExpression).ConfigureAwait(false); } }
private static async Task RenameFieldAccordingToPropertyNameAsync( RefactoringContext context, IdentifierNameSyntax identifierName) { if (IsQualified(identifierName) && !IsQualifiedWithThis(identifierName)) { return; } PropertyDeclarationSyntax propertyDeclaration = identifierName.FirstAncestor <PropertyDeclarationSyntax>(); if (propertyDeclaration == null) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); var fieldSymbol = semanticModel.GetSymbol(identifierName, context.CancellationToken) as IFieldSymbol; if (fieldSymbol?.DeclaredAccessibility != Accessibility.Private) { return; } IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken); if (propertySymbol == null) { return; } if (fieldSymbol.IsStatic != propertySymbol.IsStatic) { return; } if (!SymbolEqualityComparer.Default.Equals(fieldSymbol.ContainingType, propertySymbol.ContainingType)) { return; } string newName = StringUtility.ToCamelCase(propertySymbol.Name, context.Settings.PrefixFieldIdentifierWithUnderscore); if (string.Equals(fieldSymbol.Name, newName, StringComparison.Ordinal)) { return; } if (!await MemberNameGenerator.IsUniqueMemberNameAsync( newName, fieldSymbol, context.Solution, cancellationToken: context.CancellationToken).ConfigureAwait(false)) { return; } context.RegisterRefactoring( $"Rename '{fieldSymbol.Name}' to '{newName}'", cancellationToken => Renamer.RenameSymbolAsync(context.Solution, fieldSymbol, newName, default(OptionSet), cancellationToken), RefactoringIdentifiers.RenameBackingFieldAccordingToPropertyName); }
public static void ComputeRefactorings(RefactoringContext context, SyntaxNode node) { if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.RemoveAllComments, RefactoringIdentifiers.RemoveAllCommentsExceptDocumentationComments, RefactoringIdentifiers.RemoveAllDocumentationComments)) { bool fComment = false; bool fDocComment = false; foreach (SyntaxTrivia trivia in node.DescendantTrivia(context.Span, descendIntoTrivia: true)) { if (fComment && fDocComment) { break; } if (context.Span.Contains(trivia.Span)) { switch (trivia.Kind()) { case SyntaxKind.SingleLineCommentTrivia: case SyntaxKind.MultiLineCommentTrivia: { fComment = true; break; } case SyntaxKind.SingleLineDocumentationCommentTrivia: case SyntaxKind.MultiLineDocumentationCommentTrivia: { fDocComment = true; break; } } } } if (fComment && context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveAllComments)) { context.RegisterRefactoring( "Remove comments", c => RemoveCommentAsync(context.Document, CommentRemoveOptions.All, context.Span, c)); } if (fComment && fDocComment && context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveAllCommentsExceptDocumentationComments)) { context.RegisterRefactoring( "Remove comments (except documentation comments)", c => RemoveCommentAsync(context.Document, CommentRemoveOptions.AllExceptDocumentation, context.Span, c)); } if (fDocComment && context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveAllDocumentationComments)) { context.RegisterRefactoring( "Remove documentation comments", c => RemoveCommentAsync(context.Document, CommentRemoveOptions.Documentation, context.Span, c)); } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, SwitchSectionSyntax switchSection) { if (SelectedStatementsRefactoring.IsAnyRefactoringEnabled(context) && StatementListSelection.TryCreate(switchSection, context.Span, out StatementListSelection selectedStatements)) { await SelectedStatementsRefactoring.ComputeRefactoringAsync(context, selectedStatements).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SortCaseLabels) && SyntaxListSelection <SwitchLabelSyntax> .TryCreate(switchSection.Labels, context.Span, out SyntaxListSelection <SwitchLabelSyntax> selectedLabels) && selectedLabels.Count > 1) { SortCaseLabelsRefactoring.ComputeRefactoring(context, selectedLabels); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SplitSwitchLabels)) { SplitSwitchLabelsRefactoring.ComputeRefactoring(context, switchSection); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.AddBracesToSwitchSection, RefactoringIdentifiers.AddBracesToSwitchSections, RefactoringIdentifiers.RemoveBracesFromSwitchSection, RefactoringIdentifiers.RemoveBracesFromSwitchSections) && context.Span.IsEmpty && IsContainedInCaseOrDefaultKeyword(context.Span)) { var switchStatement = (SwitchStatementSyntax)switchSection.Parent; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; BracesAnalysis analysis = BracesAnalysis.AnalyzeBraces(switchSection); if (analysis.AddBraces) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddBracesToSwitchSection)) { context.RegisterRefactoring( AddBracesToSwitchSectionRefactoring.Title, cancellationToken => AddBracesToSwitchSectionRefactoring.RefactorAsync(context.Document, switchSection, cancellationToken), RefactoringIdentifiers.AddBracesToSwitchSection); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddBracesToSwitchSections) && sections.Any(f => f != switchSection && AddBracesToSwitchSectionAnalysis.CanAddBraces(f))) { context.RegisterRefactoring( AddBracesToSwitchSectionsRefactoring.Title, cancellationToken => AddBracesToSwitchSectionsRefactoring.RefactorAsync(context.Document, switchStatement, null, cancellationToken), RefactoringIdentifiers.AddBracesToSwitchSections); } } else if (analysis.RemoveBraces) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveBracesFromSwitchSection)) { context.RegisterRefactoring( RemoveBracesFromSwitchSectionRefactoring.Title, cancellationToken => RemoveBracesFromSwitchSectionRefactoring.RefactorAsync(context.Document, switchSection, cancellationToken), RefactoringIdentifiers.RemoveBracesFromSwitchSection); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveBracesFromSwitchSections) && sections.Any(f => f != switchSection && RemoveBracesFromSwitchSectionRefactoring.CanRemoveBraces(f))) { context.RegisterRefactoring( RemoveBracesFromSwitchSectionsRefactoring.Title, cancellationToken => RemoveBracesFromSwitchSectionsRefactoring.RefactorAsync(context.Document, switchStatement, null, cancellationToken), RefactoringIdentifiers.RemoveBracesFromSwitchSections); } } } bool IsContainedInCaseOrDefaultKeyword(TextSpan span) { foreach (SwitchLabelSyntax label in switchSection.Labels) { if (label.Keyword.Span.Contains(span)) { return(true); } } return(false); } }
private static void RegisterRefactoring(RefactoringContext context, StringConcatenationExpressionInfo concatenationInfo, StatementSyntax statement) { context.RegisterRefactoring( "Use StringBuilder instead of concatenation", cancellationToken => RefactorAsync(context.Document, concatenationInfo, statement, cancellationToken)); }
public static void RegisterRefactoring(RefactoringContext context, ExpressionSyntax expression) { context.RegisterRefactoring( (expression.IsKind(SyntaxKind.LogicalNotExpression)) ? "Add ' == false'" : "Add ' == true'", cancellationToken => RefactorAsync(context.Document, expression, cancellationToken)); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, SwitchSectionSyntax switchSection) { if (SelectedStatementsRefactoring.IsAnyRefactoringEnabled(context) && StatementListSelection.TryCreate(switchSection, context.Span, out StatementListSelection selectedStatements)) { await SelectedStatementsRefactoring.ComputeRefactoringAsync(context, selectedStatements).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.SplitSwitchLabels)) { SplitSwitchLabelsRefactoring.ComputeRefactoring(context, switchSection); } if (context.Span.IsEmpty && context.IsAnyRefactoringEnabled( RefactoringIdentifiers.AddBracesToSwitchSection, RefactoringIdentifiers.AddBracesToSwitchSections, RefactoringIdentifiers.RemoveBracesFromSwitchSection, RefactoringIdentifiers.RemoveBracesFromSwitchSections)) { var switchStatement = (SwitchStatementSyntax)switchSection.Parent; SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; BracesAnalysis analysis = BracesAnalysis.AnalyzeBraces(switchSection); if (analysis.AddBraces) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddBracesToSwitchSection)) { context.RegisterRefactoring( AddBracesToSwitchSectionRefactoring.Title, cancellationToken => AddBracesToSwitchSectionRefactoring.RefactorAsync(context.Document, switchSection, cancellationToken)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddBracesToSwitchSections) && sections.Any(f => f != switchSection && AddBracesToSwitchSectionAnalysis.CanAddBraces(f))) { context.RegisterRefactoring( AddBracesToSwitchSectionsRefactoring.Title, cancellationToken => AddBracesToSwitchSectionsRefactoring.RefactorAsync(context.Document, switchStatement, null, cancellationToken)); } } else if (analysis.RemoveBraces) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveBracesFromSwitchSection)) { context.RegisterRefactoring( RemoveBracesFromSwitchSectionRefactoring.Title, cancellationToken => RemoveBracesFromSwitchSectionRefactoring.RefactorAsync(context.Document, switchSection, cancellationToken)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveBracesFromSwitchSections) && sections.Any(f => f != switchSection && RemoveBracesFromSwitchSectionRefactoring.CanRemoveBraces(f))) { context.RegisterRefactoring( RemoveBracesFromSwitchSectionsRefactoring.Title, cancellationToken => RemoveBracesFromSwitchSectionsRefactoring.RefactorAsync(context.Document, switchStatement, null, cancellationToken)); } } } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, PropertyDeclarationSyntax propertyDeclaration) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplacePropertyWithMethod) && propertyDeclaration.HeaderSpan().Contains(context.Span)) { ReplacePropertyWithMethodRefactoring.ComputeRefactoring(context, propertyDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemovePropertyInitializer) && RemovePropertyInitializerRefactoring.CanRefactor(context, propertyDeclaration)) { context.RegisterRefactoring( "Remove property initializer", cancellationToken => RemovePropertyInitializerRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken), RefactoringIdentifiers.RemovePropertyInitializer); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.ExpandProperty, RefactoringIdentifiers.ExpandPropertyAndAddBackingField) && propertyDeclaration.Span.Contains(context.Span) && ExpandPropertyRefactoring.CanRefactor(propertyDeclaration)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandProperty)) { context.RegisterRefactoring( "Expand property", cancellationToken => ExpandPropertyRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken), RefactoringIdentifiers.ExpandProperty); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandPropertyAndAddBackingField)) { context.RegisterRefactoring( "Expand property and add backing field", cancellationToken => ExpandPropertyAndAddBackingFieldRefactoring.RefactorAsync(context.Document, propertyDeclaration, context.Settings.PrefixFieldIdentifierWithUnderscore, cancellationToken), RefactoringIdentifiers.ExpandPropertyAndAddBackingField); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseExpressionBodiedMember) && context.SupportsCSharp6) { AccessorListSyntax accessorList = propertyDeclaration.AccessorList; if (accessorList != null && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(accessorList)) { AccessorDeclarationSyntax accessor = propertyDeclaration .AccessorList? .Accessors .SingleOrDefault(shouldThrow: false); if (accessor?.AttributeLists.Any() == false && accessor.IsKind(SyntaxKind.GetAccessorDeclaration) && accessor.Body != null && (UseExpressionBodiedMemberAnalysis.GetReturnExpression(accessor.Body) != null)) { context.RegisterRefactoring( UseExpressionBodiedMemberRefactoring.Title, ct => UseExpressionBodiedMemberRefactoring.RefactorAsync(context.Document, propertyDeclaration, ct), RefactoringIdentifiers.UseExpressionBodiedMember); } } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.NotifyPropertyChanged) && await NotifyPropertyChangedRefactoring.CanRefactorAsync(context, propertyDeclaration).ConfigureAwait(false)) { context.RegisterRefactoring( "Notify property changed", cancellationToken => { return(NotifyPropertyChangedRefactoring.RefactorAsync( context.Document, propertyDeclaration, context.SupportsCSharp6, cancellationToken)); }, RefactoringIdentifiers.NotifyPropertyChanged); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberAbstract) && propertyDeclaration.HeaderSpan().Contains(context.Span)) { MakePropertyAbstractRefactoring.ComputeRefactoring(context, propertyDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberVirtual) && propertyDeclaration.HeaderSpan().Contains(context.Span)) { MakePropertyVirtualRefactoring.ComputeRefactoring(context, propertyDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.CopyDocumentationCommentFromBaseMember) && propertyDeclaration.HeaderSpan().Contains(context.Span)) { await CopyDocumentationCommentFromBaseMemberRefactoring.ComputeRefactoringAsync(context, propertyDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenamePropertyAccordingToTypeName)) { await RenamePropertyAccodingToTypeName(context, propertyDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddMemberToInterface) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(propertyDeclaration.Identifier)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); AddMemberToInterfaceRefactoring.ComputeRefactoring(context, propertyDeclaration, semanticModel); } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, PropertyDeclarationSyntax propertyDeclaration) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplacePropertyWithMethod) && propertyDeclaration.HeaderSpan().Contains(context.Span)) { ReplacePropertyWithMethodRefactoring.ComputeRefactoring(context, propertyDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemovePropertyInitializer) && RemovePropertyInitializerRefactoring.CanRefactor(context, propertyDeclaration)) { context.RegisterRefactoring( "Remove property initializer", cancellationToken => RemovePropertyInitializerRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken), RefactoringIdentifiers.RemovePropertyInitializer); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.ExpandProperty, RefactoringIdentifiers.ExpandPropertyAndAddBackingField) && propertyDeclaration.Span.Contains(context.Span) && ExpandPropertyRefactoring.CanRefactor(propertyDeclaration)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandProperty)) { context.RegisterRefactoring( "Expand property", cancellationToken => ExpandPropertyRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken), RefactoringIdentifiers.ExpandProperty); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandPropertyAndAddBackingField)) { context.RegisterRefactoring( "Expand property and add backing field", cancellationToken => ExpandPropertyAndAddBackingFieldRefactoring.RefactorAsync(context.Document, propertyDeclaration, context.Settings.PrefixFieldIdentifierWithUnderscore, cancellationToken), RefactoringIdentifiers.ExpandPropertyAndAddBackingField); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseExpressionBodiedMember) && context.SupportsCSharp6 && UseExpressionBodiedMemberRefactoring.CanRefactor(propertyDeclaration, context.Span)) { context.RegisterRefactoring( UseExpressionBodiedMemberRefactoring.Title, ct => UseExpressionBodiedMemberRefactoring.RefactorAsync(context.Document, propertyDeclaration, ct), RefactoringIdentifiers.UseExpressionBodiedMember); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.NotifyWhenPropertyChange)) { await NotifyWhenPropertyChangeRefactoring.ComputeRefactoringAsync(context, propertyDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberAbstract) && propertyDeclaration.HeaderSpan().Contains(context.Span)) { MakePropertyAbstractRefactoring.ComputeRefactoring(context, propertyDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberVirtual) && context.Span.IsEmptyAndContainedInSpan(propertyDeclaration.Identifier)) { MakePropertyVirtualRefactoring.ComputeRefactoring(context, propertyDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.CopyDocumentationCommentFromBaseMember) && propertyDeclaration.HeaderSpan().Contains(context.Span) && !propertyDeclaration.HasDocumentationComment()) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); CopyDocumentationCommentFromBaseMemberRefactoring.ComputeRefactoring(context, propertyDeclaration, semanticModel); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenamePropertyAccordingToTypeName)) { await RenamePropertyAccodingToTypeName(context, propertyDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddMemberToInterface) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(propertyDeclaration.Identifier)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); AddMemberToInterfaceRefactoring.ComputeRefactoring(context, propertyDeclaration, semanticModel); } }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, MethodDeclarationSyntax methodDeclaration) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ChangeMethodReturnTypeToVoid) && methodDeclaration.Span.Contains(context.Span)) { await ChangeMethodReturnTypeToVoidRefactoring.ComputeRefactoringAsync(context, methodDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddTypeParameter)) { AddTypeParameterRefactoring.ComputeRefactoring(context, methodDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplaceMethodWithProperty) && methodDeclaration.HeaderSpan().Contains(context.Span) && ReplaceMethodWithPropertyRefactoring.CanRefactor(methodDeclaration)) { context.RegisterRefactoring( $"Replace '{methodDeclaration.Identifier.ValueText}' with property", cancellationToken => ReplaceMethodWithPropertyRefactoring.RefactorAsync(context.Document, methodDeclaration, cancellationToken)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseExpressionBodiedMember) && methodDeclaration.Body?.Span.Contains(context.Span) == true && context.SupportsCSharp6 && UseExpressionBodiedMemberAnalysis.IsFixable(methodDeclaration)) { context.RegisterRefactoring( "Use expression-bodied member", cancellationToken => UseExpressionBodiedMemberRefactoring.RefactorAsync(context.Document, methodDeclaration, cancellationToken)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberAbstract) && methodDeclaration.HeaderSpan().Contains(context.Span)) { MakeMethodAbstractRefactoring.ComputeRefactoring(context, methodDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberVirtual) && methodDeclaration.HeaderSpan().Contains(context.Span)) { MakeMethodVirtualRefactoring.ComputeRefactoring(context, methodDeclaration); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.CopyDocumentationCommentFromBaseMember) && methodDeclaration.HeaderSpan().Contains(context.Span)) { await CopyDocumentationCommentFromBaseMemberRefactoring.ComputeRefactoringAsync(context, methodDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenameMethodAccordingToTypeName)) { await RenameMethodAccoringToTypeNameAsync(context, methodDeclaration).ConfigureAwait(false); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddMemberToInterface) && context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(methodDeclaration.Identifier)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); AddMemberToInterfaceRefactoring.ComputeRefactoring(context, methodDeclaration, semanticModel); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseListInsteadOfYield) && methodDeclaration.Identifier.Span.Contains(context.Span)) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); UseListInsteadOfYieldRefactoring.ComputeRefactoring(context, methodDeclaration, semanticModel); } }
public static void ComputeRefactoring(RefactoringContext context, MemberDeclarationSelection selectedMembers) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ChangeAccessibility)) { AccessibilityFlags accessibilityFlags = ChangeAccessibilityRefactoring.GetAllowedAccessibilityFlags(selectedMembers, allowOverride: true); if (accessibilityFlags != AccessibilityFlags.None) { bool canHaveMultipleDeclarations = CanHaveMultipleDeclarations(); TryRegisterRefactoring(accessibilityFlags, Accessibility.Public, canHaveMultipleDeclarations); TryRegisterRefactoring(accessibilityFlags, Accessibility.Internal, canHaveMultipleDeclarations); TryRegisterRefactoring(accessibilityFlags, Accessibility.Protected, canHaveMultipleDeclarations); TryRegisterRefactoring(accessibilityFlags, Accessibility.Private, canHaveMultipleDeclarations); } } void TryRegisterRefactoring(AccessibilityFlags accessibilityFlags, Accessibility accessibility, bool canHaveMultipleDeclarations) { if ((accessibilityFlags & accessibility.GetAccessibilityFlag()) != 0) { if (canHaveMultipleDeclarations) { context.RegisterRefactoring( ChangeAccessibilityRefactoring.GetTitle(accessibility), async cancellationToken => { SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); return(await ChangeAccessibilityRefactoring.RefactorAsync(context.Document.Solution(), selectedMembers, accessibility, semanticModel, cancellationToken).ConfigureAwait(false)); }); } else { context.RegisterRefactoring( ChangeAccessibilityRefactoring.GetTitle(accessibility), cancellationToken => ChangeAccessibilityRefactoring.RefactorAsync(context.Document, selectedMembers, accessibility, cancellationToken)); } } } bool CanHaveMultipleDeclarations() { foreach (MemberDeclarationSyntax member in selectedMembers) { switch (member.Kind()) { case SyntaxKind.ClassDeclaration: { if (((ClassDeclarationSyntax)member).Modifiers.Contains(SyntaxKind.PartialKeyword)) { return(true); } break; } case SyntaxKind.InterfaceDeclaration: { if (((InterfaceDeclarationSyntax)member).Modifiers.Contains(SyntaxKind.PartialKeyword)) { return(true); } break; } case SyntaxKind.StructDeclaration: { if (((StructDeclarationSyntax)member).Modifiers.Contains(SyntaxKind.PartialKeyword)) { return(true); } break; } case SyntaxKind.MethodDeclaration: { if (((MethodDeclarationSyntax)member).Modifiers.ContainsAny(SyntaxKind.PartialKeyword, SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword)) { return(true); } break; } case SyntaxKind.PropertyDeclaration: { if (((PropertyDeclarationSyntax)member).Modifiers.ContainsAny(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword)) { return(true); } break; } case SyntaxKind.IndexerDeclaration: { if (((IndexerDeclarationSyntax)member).Modifiers.ContainsAny(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword)) { return(true); } break; } case SyntaxKind.EventDeclaration: { if (((EventDeclarationSyntax)member).Modifiers.ContainsAny(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword)) { return(true); } break; } case SyntaxKind.EventFieldDeclaration: { if (((EventFieldDeclarationSyntax)member).Modifiers.ContainsAny(SyntaxKind.AbstractKeyword, SyntaxKind.VirtualKeyword, SyntaxKind.OverrideKeyword)) { return(true); } break; } } } return(false); } }
private static async Task RenameMethodAccoringToTypeNameAsync( RefactoringContext context, MethodDeclarationSyntax methodDeclaration) { TypeSyntax returnType = methodDeclaration.ReturnType; if (returnType?.IsVoid() != false) { return; } SyntaxToken identifier = methodDeclaration.Identifier; if (!context.Span.IsEmptyAndContainedInSpanOrBetweenSpans(identifier)) { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken); ITypeSymbol typeSymbol = GetType(returnType, semanticModel, context.CancellationToken); if (typeSymbol == null) { return; } string newName = NameGenerator.CreateName(typeSymbol); if (string.IsNullOrEmpty(newName)) { return; } newName = "Get" + newName; if (methodSymbol.IsAsync) { newName += "Async"; } string oldName = identifier.ValueText; if (string.Equals(oldName, newName, StringComparison.Ordinal)) { return; } if (!await MemberNameGenerator.IsUniqueMemberNameAsync( newName, methodSymbol, context.Solution, cancellationToken: context.CancellationToken).ConfigureAwait(false)) { return; } context.RegisterRefactoring( $"Rename '{oldName}' to '{newName}'", cancellationToken => Renamer.RenameSymbolAsync(context.Solution, methodSymbol, newName, default(OptionSet), cancellationToken)); }
private static bool ComputeRefactoring( RefactoringContext context, MemberDeclarationSyntax memberDeclaration, BaseTypeSyntax baseType, ITypeSymbol explicitInterfaceSymbol, ISymbol memberSymbol, SemanticModel semanticModel) { TypeSyntax type = baseType.Type; if (type == null) { return(false); } var interfaceSymbol = semanticModel.GetTypeSymbol(type, context.CancellationToken) as INamedTypeSymbol; if (interfaceSymbol?.TypeKind != TypeKind.Interface) { return(false); } if (interfaceSymbol.Language != LanguageNames.CSharp) { return(false); } if (!(interfaceSymbol.GetSyntaxOrDefault(context.CancellationToken) is InterfaceDeclarationSyntax interfaceDeclaration)) { return(false); } if (interfaceSymbol.Equals(explicitInterfaceSymbol)) { return(false); } ImmutableArray <ISymbol> members = interfaceSymbol.GetMembers(); SyntaxKind kind = memberDeclaration.Kind(); for (int i = 0; i < members.Length; i++) { if (CheckKind(members[i], kind)) { ISymbol symbol = memberSymbol.ContainingType.FindImplementationForInterfaceMember(members[i]); if (memberSymbol.OriginalDefinition.Equals(symbol?.OriginalDefinition)) { return(false); } } } string displayName = SymbolDisplay.ToMinimalDisplayString(interfaceSymbol.OriginalDefinition, semanticModel, type.SpanStart, SymbolDisplayFormats.Default); Document document = context.Document; string title = $"Add to interface '{displayName}'"; string equivalenceKey = RefactoringIdentifiers.AddMemberToInterface + "." + displayName; if (memberDeclaration.SyntaxTree == interfaceDeclaration.SyntaxTree) { context.RegisterRefactoring( title, cancellationToken => { InterfaceDeclarationSyntax newNode = CreateNewNode(memberDeclaration, interfaceDeclaration); return(document.ReplaceNodeAsync(interfaceDeclaration, newNode, cancellationToken)); }, equivalenceKey); } else { context.RegisterRefactoring( title, cancellationToken => { InterfaceDeclarationSyntax newNode = CreateNewNode(memberDeclaration, interfaceDeclaration); return(document.Solution().ReplaceNodeAsync(interfaceDeclaration, newNode, cancellationToken)); }, equivalenceKey); } return(true); }
public static async Task ComputeRefactoringAsync( RefactoringContext context, PropertyDeclarationSyntax property) { AccessorDeclarationSyntax setter = property.Setter(); if (setter == null) { return; } ExpressionSyntax expression = GetExpression(); if (expression == null) { return; } SimpleAssignmentExpressionInfo simpleAssignment = SyntaxInfo.SimpleAssignmentExpressionInfo(expression); if (!simpleAssignment.Success) { return; } if (!simpleAssignment.Left.IsKind(SyntaxKind.IdentifierName)) { return; } if (!(simpleAssignment.Right is IdentifierNameSyntax identifierName)) { return; } if (identifierName.Identifier.ValueText != "value") { return; } SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); INamedTypeSymbol containingType = semanticModel .GetDeclaredSymbol(property, context.CancellationToken)? .ContainingType; if (containingType == null) { return; } if (!containingType.Implements(MetadataNames.System_ComponentModel_INotifyPropertyChanged, allInterfaces: true)) { return; } IMethodSymbol methodSymbol = SymbolUtility.FindMethodThatRaisePropertyChanged(containingType, expression.SpanStart, semanticModel); if (methodSymbol == null) { return; } Document document = context.Document; context.RegisterRefactoring( "Notify when property change", ct => RefactorAsync(document, property, methodSymbol.Name, ct), RefactoringIdentifiers.NotifyWhenPropertyChange); ExpressionSyntax GetExpression() { BlockSyntax body = setter.Body; if (body != null) { if (body.Statements.SingleOrDefault(shouldThrow: false) is ExpressionStatementSyntax expressionStatement) { return(expressionStatement.Expression); } } else { return(setter.ExpressionBody?.Expression); } return(null); } }
private static void RegisterRefactoring(RefactoringContext context, ExpressionSyntax expression) { context.RegisterRefactoring( Title, cancellationToken => RefactorAsync(context.Document, expression, context.CancellationToken)); }
public static async Task ComputeRefactoringsAsync(RefactoringContext context, MemberDeclarationSyntax member) { SyntaxKind kind = member.Kind(); switch (kind) { case SyntaxKind.MethodDeclaration: case SyntaxKind.IndexerDeclaration: case SyntaxKind.PropertyDeclaration: case SyntaxKind.OperatorDeclaration: case SyntaxKind.ConversionOperatorDeclaration: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.EventDeclaration: case SyntaxKind.NamespaceDeclaration: case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: case SyntaxKind.InterfaceDeclaration: case SyntaxKind.EnumDeclaration: { if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.RemoveMember, RefactoringIdentifiers.DuplicateMember, RefactoringIdentifiers.CommentOutMember) && BraceContainsSpan(member, context.Span)) { if (member.IsParentKind( SyntaxKind.NamespaceDeclaration, SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration, SyntaxKind.InterfaceDeclaration, SyntaxKind.CompilationUnit)) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveMember)) { context.RegisterRefactoring(CodeActionFactory.RemoveMemberDeclaration(context.Document, member, equivalenceKey: RefactoringIdentifiers.RemoveMember)); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.DuplicateMember)) { context.RegisterRefactoring( $"Duplicate {CSharpFacts.GetTitle(member)}", cancellationToken => DuplicateMemberDeclarationRefactoring.RefactorAsync(context.Document, member, cancellationToken), RefactoringIdentifiers.DuplicateMember); } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.CommentOutMember)) { CommentOutRefactoring.RegisterRefactoring(context, member); } } break; } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveAllStatements)) { RemoveAllStatementsRefactoring.ComputeRefactoring(context, member); } if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemoveAllMemberDeclarations)) { RemoveAllMemberDeclarationsRefactoring.ComputeRefactoring(context, member); } if (context.IsAnyRefactoringEnabled( RefactoringIdentifiers.SwapMemberDeclarations, RefactoringIdentifiers.RemoveMemberDeclarations) && !member.Span.IntersectsWith(context.Span)) { MemberDeclarationsRefactoring.ComputeRefactoring(context, member); } switch (kind) { case SyntaxKind.NamespaceDeclaration: { var namespaceDeclaration = (NamespaceDeclarationSyntax)member; NamespaceDeclarationRefactoring.ComputeRefactorings(context, namespaceDeclaration); if (MemberDeclarationListSelection.TryCreate(namespaceDeclaration, context.Span, out MemberDeclarationListSelection selectedMembers)) { await SelectedMemberDeclarationsRefactoring.ComputeRefactoringAsync(context, selectedMembers).ConfigureAwait(false); } break; } case SyntaxKind.ClassDeclaration: { var classDeclaration = (ClassDeclarationSyntax)member; await ClassDeclarationRefactoring.ComputeRefactoringsAsync(context, classDeclaration).ConfigureAwait(false); if (MemberDeclarationListSelection.TryCreate(classDeclaration, context.Span, out MemberDeclarationListSelection selectedMembers)) { await SelectedMemberDeclarationsRefactoring.ComputeRefactoringAsync(context, selectedMembers).ConfigureAwait(false); } break; } case SyntaxKind.StructDeclaration: { var structDeclaration = (StructDeclarationSyntax)member; await StructDeclarationRefactoring.ComputeRefactoringsAsync(context, structDeclaration).ConfigureAwait(false); if (MemberDeclarationListSelection.TryCreate(structDeclaration, context.Span, out MemberDeclarationListSelection selectedMembers)) { await SelectedMemberDeclarationsRefactoring.ComputeRefactoringAsync(context, selectedMembers).ConfigureAwait(false); } break; } case SyntaxKind.InterfaceDeclaration: { var interfaceDeclaration = (InterfaceDeclarationSyntax)member; InterfaceDeclarationRefactoring.ComputeRefactorings(context, interfaceDeclaration); if (MemberDeclarationListSelection.TryCreate(interfaceDeclaration, context.Span, out MemberDeclarationListSelection selectedMembers)) { await SelectedMemberDeclarationsRefactoring.ComputeRefactoringAsync(context, selectedMembers).ConfigureAwait(false); } break; } case SyntaxKind.EnumDeclaration: { await EnumDeclarationRefactoring.ComputeRefactoringAsync(context, (EnumDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.EnumMemberDeclaration: { await EnumMemberDeclarationRefactoring.ComputeRefactoringAsync(context, (EnumMemberDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.DelegateDeclaration: { DelegateDeclarationRefactoring.ComputeRefactorings(context, (DelegateDeclarationSyntax)member); break; } case SyntaxKind.MethodDeclaration: { await MethodDeclarationRefactoring.ComputeRefactoringsAsync(context, (MethodDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.ConstructorDeclaration: { await ConstructorDeclarationRefactoring.ComputeRefactoringsAsync(context, (ConstructorDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.DestructorDeclaration: { DestructorDeclarationRefactoring.ComputeRefactorings(context, (DestructorDeclarationSyntax)member); break; } case SyntaxKind.IndexerDeclaration: { await IndexerDeclarationRefactoring.ComputeRefactoringsAsync(context, (IndexerDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.PropertyDeclaration: { await PropertyDeclarationRefactoring.ComputeRefactoringsAsync(context, (PropertyDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.OperatorDeclaration: { ComputeRefactorings(context, (OperatorDeclarationSyntax)member); break; } case SyntaxKind.ConversionOperatorDeclaration: { ComputeRefactorings(context, (ConversionOperatorDeclarationSyntax)member); break; } case SyntaxKind.FieldDeclaration: { await FieldDeclarationRefactoring.ComputeRefactoringsAsync(context, (FieldDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.EventDeclaration: { await EventDeclarationRefactoring.ComputeRefactoringsAsync(context, (EventDeclarationSyntax)member).ConfigureAwait(false); break; } case SyntaxKind.EventFieldDeclaration: { await EventFieldDeclarationRefactoring.ComputeRefactoringsAsync(context, (EventFieldDeclarationSyntax)member).ConfigureAwait(false); break; } } if (context.IsRefactoringEnabled(RefactoringIdentifiers.MoveUnsafeContextToContainingDeclaration)) { MoveUnsafeContextToContainingDeclarationRefactoring.ComputeRefactoring(context, member); } }
public static async Task ComputeRefactoringAsync(RefactoringContext context, SelectedStatementCollection selectedStatements) { if (selectedStatements.IsMultiple) { StatementSyntax lastStatement = selectedStatements.Last; if (lastStatement.IsKind(SyntaxKind.WhileStatement)) { IEnumerable <StatementSyntax> statements = selectedStatements .Take(selectedStatements.LastIndex - selectedStatements.FirstIndex); SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); List <LocalDeclarationStatementSyntax> localDeclarations = null; List <ExpressionSyntax> expressions = null; foreach (StatementSyntax statement in statements) { SyntaxKind kind = statement.Kind(); if (kind == SyntaxKind.LocalDeclarationStatement) { var localDeclaration = (LocalDeclarationStatementSyntax)statement; if (!IsAnySymbolReferenced(localDeclaration, selectedStatements.ToImmutableArray(), selectedStatements.LastIndex + 1, semanticModel, context.CancellationToken)) { if (localDeclarations == null) { localDeclarations = new List <LocalDeclarationStatementSyntax>(); } localDeclarations.Add(localDeclaration); } else { return; } } else if (kind == SyntaxKind.ExpressionStatement) { var expressionStatement = (ExpressionStatementSyntax)statement; ExpressionSyntax expression = expressionStatement.Expression; if (expression != null) { if (CanBeInitializer(expression)) { if (expressions == null) { expressions = new List <ExpressionSyntax>(); } expressions.Add(expression); } else { return; } } } else { return; } } if (localDeclarations == null || expressions == null) { if (localDeclarations == null || localDeclarations .Select(f => f.Declaration) .Where(f => f != null) .Select(f => semanticModel.GetTypeSymbol(f.Type, context.CancellationToken)) .Distinct() .Count() == 1) { context.RegisterRefactoring( Title, cancellationToken => RefactorAsync(context.Document, localDeclarations, expressions, (WhileStatementSyntax)lastStatement, cancellationToken)); } } } } }
public static void ComputeRefactoring(RefactoringContext context, SwitchStatementSyntax switchStatement) { SyntaxList <SwitchSectionSyntax> sections = switchStatement.Sections; bool containsSectionWithoutDefault = false; foreach (SwitchSectionSyntax section in sections) { bool containsPattern = false; bool containsDefault = false; foreach (SwitchLabelSyntax label in section.Labels) { switch (label.Kind()) { case SyntaxKind.CasePatternSwitchLabel: { containsPattern = true; break; } case SyntaxKind.CaseSwitchLabel: { break; } case SyntaxKind.DefaultSwitchLabel: { containsDefault = true; break; } default: { Debug.Fail(label.Kind().ToString()); return; } } if (containsDefault) { if (containsPattern) { return; } } else { containsSectionWithoutDefault = true; } } } if (!containsSectionWithoutDefault) { return; } context.RegisterRefactoring( (sections.Count == 1) ? "Replace switch with if" : "Replace switch with if-else", cancellationToken => RefactorAsync(context.Document, switchStatement, cancellationToken), RefactoringIdentifiers.ReplaceSwitchWithIf); }