public sealed override async Task ComputeRefactoringsAsync( CodeRefactoringContext context) { var document = context.Document; var documentFileNameWithoutExtension = Path.GetFileNameWithoutExtension(document.FilePath); var root = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var model = await document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); var typesToRemove = root.GetTypesToRemove( model, documentFileNameWithoutExtension); if (typesToRemove.Length > 1) { context.RegisterRefactoring(CodeAction.Create( "Move types to files in folders", async token => await ExtractTypesToFilesCodeRefactoringProvider.CreateFiles( document, root, model, typesToRemove, _ => _.Replace(".", "\\"), token))); context.RegisterRefactoring(CodeAction.Create( "Move types to files in current folder", async token => await ExtractTypesToFilesCodeRefactoringProvider.CreateFiles( document, root, model, typesToRemove, _ => string.Empty, token))); } }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var node = root.FindNode(context.Span); if (node.IsKind(SyntaxKind.Argument)) { var argSyntax = (ArgumentSyntax)node; if (argSyntax == null) return; //Exit if not valid XML if (!IsXml(argSyntax.Expression.GetFirstToken().ValueText)) return; var action = CodeAction.Create("Format XML", c => FormatXmlAsync(context.Document, argSyntax, c)); context.RegisterRefactoring(action); } if (node.IsKind(SyntaxKind.StringLiteralExpression)) { var sleSyntax = (LiteralExpressionSyntax)node; if (sleSyntax == null) return; //Exit if not valid XML var text = sleSyntax.GetFirstToken().ValueText; if (!IsXml(text)) return; var action = CodeAction.Create("Format XML", c => FormatXmlAsync(context.Document, sleSyntax, c)); context.RegisterRefactoring(action); } }
//*** This is the entry point when user hits Ctrl + . *** public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); // Find the Property at the selection var node = root.FindNode(context.Span); var property = node.FirstAncestorOrSelf<PropertyDeclarationSyntax>(); if (property == null) { return; // No property here... move along! } // Check if user is on an Auto property if (property.IsAutoProperty() || property.IsExpressionProperty()) { // Auto Property is selected (Get ready for EXPLOSION) var explodeAction = CodeAction.Create("Explode Property...", c => ExplodePropertyAsync(root, context.Document, property, c)); context.RegisterRefactoring(explodeAction); // Register Explode Code Action (This will show Explode Property... in the context menu) } else if (property.HasGetter()) { // Full Property is selected (Get ready to CRUNCH) var implodeAction = CodeAction.Create("Crunch Property...", c => CrunchPropertyAsync(root, context.Document, property, c)); context.RegisterRefactoring(implodeAction); // Register Crunch Code Action (This will show Crunch Property... in the context menu) } }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); SyntaxToken token = root.FindToken(span.Start); if (!token.IsKind(SyntaxKind.IdentifierToken)) return; var property = token.Parent as PropertyDeclarationSyntax; if (property == null || !property.Identifier.Span.Contains(span)) return; if (IsEmptyComputedProperty(property)) { context.RegisterRefactoring( CodeActionFactory.Create( token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Convert to auto-property"), t2 => { var newRoot = root.ReplaceNode(property, CreateNewProperty(property).WithAdditionalAnnotations(Formatter.Annotation).WithLeadingTrivia(property.GetLeadingTrivia())); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ) ); return; } var field = GetBackingField(model, property); if (!IsValidField(field, property.Parent as TypeDeclarationSyntax)) return; //variable declarator->declaration->field declaration var backingFieldNode = root.FindNode(field.Locations.First().SourceSpan).Ancestors().OfType<FieldDeclarationSyntax>().First(); var propertyAnnotation = new SyntaxAnnotation(); var fieldAnnotation = new SyntaxAnnotation(); //annotate our property node and our field node root = root.ReplaceNode((SyntaxNode)property, property.WithAdditionalAnnotations(propertyAnnotation)); root = root.ReplaceNode((SyntaxNode)root.FindNode(backingFieldNode.Span), backingFieldNode.WithAdditionalAnnotations(fieldAnnotation)); context.RegisterRefactoring( CodeActionFactory.Create(token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Convert to auto-property"), PerformAction(document, model, root, field.Name, CreateNewProperty(property), propertyAnnotation, fieldAnnotation)) ); }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { if (!await TypeAndFileNameMismatch(context)) return; context.RegisterRefactoring(await new RenameTypeRefactoring(context).GetCodeAction()); context.RegisterRefactoring(await new RenameFileRefactoring(DTE,context).GetCodeAction()); context.RegisterRefactoring(await new MoveTypeToFileRefactoring(context).GetCodeAction()); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(span) as BinaryExpressionSyntax; if (node == null || !(node.IsKind(SyntaxKind.EqualsExpression) || node.IsKind(SyntaxKind.NotEqualsExpression))) return; context.RegisterRefactoring( CodeActionFactory.Create( span, DiagnosticSeverity.Info, GettextCatalog.GetString("To 'Equals' call"), t2 => Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode((SyntaxNode)node, CreateEquals(model, node)))) ) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); if (!token.IsKind(SyntaxKind.StringLiteralToken) || token.Value.ToString() != "") return; context.RegisterRefactoring( CodeActionFactory.Create( token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Use 'string.Empty'"), t2 => { var newRoot = root.ReplaceNode((SyntaxNode)token.Parent, SyntaxFactory.ParseExpression("string.Empty")); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ) ); }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { try { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); // Find the node at the selection. var node = root.FindNode(context.Span); // Only offer a refactoring if the selected node is a method declaration node. var methodDecl = node as MethodDeclarationSyntax; if (methodDecl == null) return; // Only offer a refactoring if the method declaration node matches a signature pattern we recognize. var refactoringProviderList = BuildRefactoringProviderList(); foreach (var mapper in refactoringProviderList) { if (await mapper.CanRefactor(context.Document, methodDecl)) { // Register mapping code action. var action = CodeAction.Create(mapper.Description, c => mapper.Refactor(context.Document, methodDecl, c)); context.RegisterRefactoring(action); break; } } } catch (Exception ex) { string error = ex.ToString(); } }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; var textSpan = context.Span; var cancellationToken = context.CancellationToken; var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) as CompilationUnitSyntax; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); // if length is 0 then no particular range is selected, so pick the first enclosing member if (textSpan.Length == 0) { var decl = root.FindToken(textSpan.Start).Parent.AncestorsAndSelf().OfType<MemberDeclarationSyntax>().FirstOrDefault(); if (decl != null) { textSpan = decl.FullSpan; } } var properties = ExpansionChecker.GetExpandableProperties(textSpan, root, model); if (properties.Any()) { #pragma warning disable RS0005 context.RegisterRefactoring( CodeAction.Create("Apply INotifyPropertyChanged pattern", (c) => ImplementNotifyPropertyChangedAsync(document, root, model, properties, c))); #pragma warning restore RS0005 } }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var node = root.FindNode(context.Span); if (node == null) return; //process string literal or interpolated string. if (!node.IsKind(SyntaxKind.StringLiteralExpression)) { node = node.AncestorsAndSelf().OfType<InterpolatedStringExpressionSyntax>().FirstOrDefault(); } if (node == null) return; if (node.IsKind(SyntaxKind.StringLiteralExpression) || node.IsKind(SyntaxKind.InterpolatedStringExpression)) { var tree = root.SyntaxTree; var lines = tree.GetText().Lines; // find add-expression in the same line (left end and right start). var addExpression = node.Ancestors() .TakeWhile(n => n.IsKind(SyntaxKind.AddExpression)) .Cast<BinaryExpressionSyntax>() .TakeWhile(n => lines.GetLinePosition(n.Left.Span.End).Line == lines.GetLinePosition(n.Right.Span.Start).Line) .LastOrDefault(); if (addExpression != null) { var action = CodeAction.Create("Integrate strings", c => IntegrateStringsAsync(context.Document, addExpression, c), ActionKeyStringIntegration); context.RegisterRefactoring(action); } } }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var node = root.FindNode(context.Span); var currentRoot = await context.Document.GetSyntaxTreeAsync().Result.GetRootAsync(); var classCount = currentRoot.DescendantNodesAndSelf().Where(n => n is ClassStatementSyntax).Count(); // only for a type declaration node that doesn't match the current file name // also omit all private classes var typeDecl = node as ClassStatementSyntax; var className = typeDecl.Identifier.GetIdentifierText() + ".vb"; //Is the name of the file the same as the name of the class then do nothing. if(typeDecl == null || context.Document.Name.ToLowerInvariant() == className.ToLowerInvariant() || typeDecl.Modifiers.Any(SyntaxKind.PrivateKeyword)) { return; } //We know the name of the class is not the same as the file. If this is the only class in the file we will offer a rename file refactoring. if(classCount == 1) { var renameFileActino = CodeAction.Create("Rename file to \"" + className + "\" ", c => RenameDocumentAsync(context.Document, className,c)); }else { var action = CodeAction.Create("Move class to file \"" + className + "\" ", c => MoveClassIntoNewFileAsync(context.Document, typeDecl, className, c)); context.RegisterRefactoring(action); } }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindToken(span.Start).Parent; if (node.Parent == null || node.Parent.Parent == null || !node.Parent.Parent.IsKind(SyntaxKind.InvocationExpression)) return; var symbol = model.GetSymbolInfo(node.Parent).Symbol; if (symbol == null || symbol.Kind != SymbolKind.Method || symbol.ContainingType.SpecialType != SpecialType.System_Enum || symbol.Name != "HasFlag") return; var invocationNode = (InvocationExpressionSyntax)node.Parent.Parent; var arg = invocationNode.ArgumentList.Arguments.Select(a => a.Expression).First(); if (!arg.DescendantNodesAndSelf().OfType<BinaryExpressionSyntax>().All(bop => bop.IsKind(SyntaxKind.BitwiseOrExpression))) return; context.RegisterRefactoring( CodeActionFactory.Create(node.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To bitwise flag comparison"), t2 => Task.FromResult(PerformAction(document, root, invocationNode))) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax expr; SyntaxToken token; if (!GetRelationalExpression(root, span, out expr, out token)) return; context.RegisterRefactoring( CodeActionFactory.Create( span, DiagnosticSeverity.Info, string.Format(GettextCatalog.GetString("Negate '{0}'"), expr), t2 => { var newRoot = root.ReplaceNode((SyntaxNode) expr, CSharpUtil.InvertCondition(expr).WithAdditionalAnnotations(Formatter.Annotation) ); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); var parameter = token.Parent as ParameterSyntax; if (parameter != null) { var ctor = parameter.Parent.Parent as ConstructorDeclarationSyntax; if (ctor == null) return; context.RegisterRefactoring( CodeActionFactory.Create( parameter.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Initialize field from parameter"), t2 => { var newFieldName = NameProposalService.GetNameProposal(parameter.Identifier.ValueText, SyntaxKind.FieldDeclaration, Accessibility.Private, false, context.Document, ctor.SpanStart); var newField = SyntaxFactory.FieldDeclaration( SyntaxFactory.VariableDeclaration( parameter.Type, SyntaxFactory.SingletonSeparatedList<VariableDeclaratorSyntax>(SyntaxFactory.VariableDeclarator(newFieldName))) ).WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.ReadOnlyKeyword))) .WithAdditionalAnnotations(Formatter.Annotation); var assignmentStatement = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(newFieldName)), SyntaxFactory.IdentifierName(newFieldName) ) ).WithAdditionalAnnotations(Formatter.Annotation); var trackedRoot = root.TrackNodes(ctor); var newRoot = trackedRoot.InsertNodesBefore(trackedRoot.GetCurrentNode(ctor), new List<SyntaxNode>() { newField }); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(ctor), ctor.WithBody( ctor.Body.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { assignmentStatement }.Concat(ctor.Body.Statements))) )); return Task.FromResult(document.WithSyntaxRoot(newRoot)); }) ); } }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); if (!token.IsKind(SyntaxKind.EqualsToken)) return; var node = token.Parent as AssignmentExpressionSyntax; if (node == null) return; var assignment = CreateAssignment(node); if (assignment == null) return; assignment = assignment.WithAdditionalAnnotations(Formatter.Annotation); context.RegisterRefactoring( CodeActionFactory.Create(span, DiagnosticSeverity.Info, String.Format(GettextCatalog.GetString("To '{0}='"), node.Left.ToString()), document.WithSyntaxRoot( root.ReplaceNode((SyntaxNode)node, assignment))) ); }
public async override Task ComputeRefactoringsAsync (CodeRefactoringContext context) { var document = context.Document; var span = context.Span; var cancellationToken = context.CancellationToken; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait (false); if (model.IsFromGeneratedCode (cancellationToken)) return; var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait (false); var token = root.FindToken(span.Start); var type = token.Parent as BaseTypeDeclarationSyntax; if (type == null) return; if (Path.GetFileNameWithoutExtension (document.FilePath) == type.Identifier.ToString ()) return; string title; if (IsSingleType (root)) { title = String.Format (GettextCatalog.GetString ("Rename file to '{0}'"), Path.GetFileName (GetCorrectFileName (document, type))); } else { title = String.Format (GettextCatalog.GetString ("Move type to file '{0}'"), Path.GetFileName (GetCorrectFileName (document, type))); } context.RegisterRefactoring (new MyCodeAction (document, title, root, type)); }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; var textSpan = context.Span; var cancellationToken = context.CancellationToken; var root = (SyntaxNode)await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(textSpan.Start); // Only trigger if the text span is within the 'if' keyword token of an if-else statement. if (token.Kind() != SyntaxKind.IfKeyword || !token.Span.IntersectsWith(textSpan.Start) || !token.Span.IntersectsWith(textSpan.End)) { return; } var ifStatement = token.Parent as IfStatementSyntax; if (ifStatement == null || ifStatement.Else == null) { return; } var semanticModel = (SemanticModel)await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ReturnStatementSyntax returnStatement; if (ReturnConditionalAnalyzer.TryGetNewReturnStatement(ifStatement, semanticModel, out returnStatement)) { var action = new ConvertToConditionalCodeAction("Convert to conditional expression", (c) => Task.FromResult(ConvertToConditional(document, semanticModel, ifStatement, returnStatement, c))); context.RegisterRefactoring(action); } }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; var textSpan = context.Span; var cancellationToken = context.CancellationToken; var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(textSpan.Start); if (token.Parent == null) { return; } var propertyDeclaration = token.Parent.FirstAncestorOrSelf<PropertyDeclarationSyntax>(); // Refactor only properties with both a getter and a setter. if (propertyDeclaration == null || !HasBothAccessors(propertyDeclaration) || !propertyDeclaration.Identifier.Span.IntersectsWith(textSpan.Start)) { return; } context.RegisterRefactoring( new ConvertToAutoPropertyCodeAction("Convert to auto property", (c) => ConvertToAutoPropertyAsync(document, propertyDeclaration, c))); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); var boP = token.Parent as BinaryExpressionSyntax; if (boP == null || !boP.OperatorToken.Span.Contains(span)) return; ExpressionSyntax flagsExpression, targetExpression; bool testFlagset; if (!AnalyzeComparisonWithNull(boP, out flagsExpression, out targetExpression, out testFlagset) && !AnalyzeComparisonWithFlags(boP, out flagsExpression, out targetExpression, out testFlagset)) return; if (!testFlagset && !flagsExpression.DescendantNodesAndSelf().OfType<BinaryExpressionSyntax>().All(bop => bop.IsKind(SyntaxKind.BitwiseOrExpression))) return; if (testFlagset && !flagsExpression.DescendantNodesAndSelf().OfType<BinaryExpressionSyntax>().All(bop => bop.IsKind(SyntaxKind.BitwiseAndExpression))) return; context.RegisterRefactoring( CodeActionFactory.Create(token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To 'Enum.HasFlag'"), t2 => Task.FromResult(PerformAction(document, root, boP, flagsExpression, targetExpression, testFlagset))) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); if (!token.IsKind(SyntaxKind.IntegerLiteralToken)) return; var value = token.Value; if (!((value is int) || (value is long) || (value is short) || (value is sbyte) || (value is uint) || (value is ulong) || (value is ushort) || (value is byte))) { return; } var literalValue = token.ToString(); if (literalValue.StartsWith("&H", System.StringComparison.OrdinalIgnoreCase)) return; context.RegisterRefactoring(CodeActionFactory.Create(token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To hex"), t2 => Task.FromResult(PerformAction(document, root, token)))); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindToken(span.Start).Parent as InterpolatedStringTextSyntax; if (node == null) return; context.RegisterRefactoring( CodeActionFactory.Create( node.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To format string"), t => { var newRoot = root.ReplaceNode(node.Parent, CreateFormatString(node)); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; var textSpan = context.Span; var cancellationToken = context.CancellationToken; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) { return; } var model = await document.GetSemanticModelAsync (cancellationToken).ConfigureAwait (false); if (model.IsFromGeneratedCode (cancellationToken)) return; var root = await document.GetCSharpSyntaxRootAsync(cancellationToken).ConfigureAwait(false); if (textSpan.Start >= root.FullSpan.Length) return; var token = root.FindToken(textSpan.Start); if (!token.Span.Contains(textSpan)) { return; } var node = token.Parent.AncestorsAndSelf ().FirstOrDefault (n => n.IsKind(SyntaxKind.UsingDirective) || n.IsParentKind(SyntaxKind.ExternAliasDirective)); if (node == null) { return; } context.RegisterRefactoring( new DocumentChangeAction(node.Span, DiagnosticSeverity.Info, GettextCatalog.GetString ("Sort usings"), (t) => OrganizeImportsCommandHandler.SortUsingsAsync(document, t))); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); if (!token.IsKind(SyntaxKind.AsKeyword)) return; var node = token.Parent as BinaryExpressionSyntax; context.RegisterRefactoring( CodeActionFactory.Create(token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Convert 'as' to cast"), t2 => Task.FromResult(PerformAction(document, root, node))) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); var castExpression = token.Parent.AncestorsAndSelf().OfType<CastExpressionSyntax>().FirstOrDefault(); if (castExpression == null || castExpression.IsKind(SyntaxKind.TryCastExpression) || castExpression.Expression.Span.Contains(span)) return; var type = model.GetTypeInfo(castExpression.Type).Type; if (type == null || type.IsValueType && !type.IsNullableType()) return; context.RegisterRefactoring( CodeActionFactory.Create( token.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Convert cast to 'TryCast'"), t2 => Task.FromResult(PerformAction(document, root, castExpression)) ) ); }
public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); var node = root.FindNode(context.Span); var parameter = node as ParameterSyntax; if ((parameter == null) || !(node?.Parent?.Parent is ConstructorDeclarationSyntax)) // constructor parameters only { return; } var parameterName = RoslynHelpers.GetParameterName(parameter); var underscorePrefix = "_" + parameterName; var uppercase = parameterName.Substring(0, 1).ToUpper() + parameterName.Substring(1); if (RoslynHelpers.VariableExists(root, parameterName, underscorePrefix, uppercase)) { return; } var action = CodeAction.Create( "Introduce and initialize field '" + parameterName + "'", ct => CreateFieldAsync(context, parameter, parameterName, parameterName, ct)); context.RegisterRefactoring(action); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); var parameter = token.Parent as ParameterSyntax; if (parameter != null) { var ctor = parameter.Parent.Parent as ConstructorDeclarationSyntax; if (ctor == null) return; context.RegisterRefactoring( CodeActionFactory.Create( parameter.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("Initialize auto-property from parameter"), t2 => { var propertyName = GetPropertyName(parameter.Identifier.ToString()); var accessorDeclList = new SyntaxList<AccessorDeclarationSyntax>().Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))).Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration).WithSemicolonToken(SyntaxFactory.Token(SyntaxKind.SemicolonToken))); var newProperty = SyntaxFactory.PropertyDeclaration(parameter.Type, propertyName) .WithAccessorList(SyntaxFactory.AccessorList(accessorDeclList)) .WithModifiers(SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword))) .WithAdditionalAnnotations(Formatter.Annotation); var assignmentStatement = SyntaxFactory.ExpressionStatement( SyntaxFactory.AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, propertyName != parameter.Identifier.ToString() ? (ExpressionSyntax)SyntaxFactory.IdentifierName(propertyName) : SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName(parameter.Identifier)), SyntaxFactory.IdentifierName(parameter.Identifier) ) ).WithAdditionalAnnotations(Formatter.Annotation); root = root.TrackNodes(ctor); var newRoot = root.InsertNodesBefore(root.GetCurrentNode(ctor), new List<SyntaxNode>() { newProperty }); newRoot = newRoot.ReplaceNode(newRoot.GetCurrentNode(ctor), ctor.WithBody( ctor.Body.WithStatements(SyntaxFactory.List<StatementSyntax>(new[] { assignmentStatement }.Concat(ctor.Body.Statements))) )); return Task.FromResult(document.WithSyntaxRoot(newRoot)); }) ); } }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(span); if (!node.IsKind(SyntaxKind.IdentifierName)) return; var nodeGrandparent = node.Parent?.Parent; if ((nodeGrandparent is EventDeclarationSyntax) || (nodeGrandparent is EventFieldDeclarationSyntax)) return; if (node.Parent.IsKind(SyntaxKind.SimpleMemberAccessExpression)) node = node.Parent; var info = model.GetTypeInfo(node, cancellationToken); var type = info.ConvertedType ?? info.Type; if (type == null) return; var invocationMethod = type.GetDelegateInvokeMethod(); if (invocationMethod == null) return; context.RegisterRefactoring( CodeActionFactory.Create( node.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To anonymous method"), t2 => { var expr = SyntaxFactory.InvocationExpression( (ExpressionSyntax)node, SyntaxFactory.ArgumentList(SyntaxFactory.SeparatedList(invocationMethod.Parameters.Select(p => SyntaxFactory.Argument(SyntaxFactory.IdentifierName(p.Name))))) ); var parameters = invocationMethod.Parameters.Select(p => CreateParameterSyntax(model, node, p)).ToList(); var stmt = invocationMethod.ReturnType.SpecialType == SpecialType.System_Void ? (StatementSyntax)SyntaxFactory.ExpressionStatement(expr) : SyntaxFactory.ReturnStatement(expr); var ame = SyntaxFactory.AnonymousMethodExpression( parameters.Count == 0 ? null : SyntaxFactory.ParameterList(SyntaxFactory.SeparatedList(parameters)), SyntaxFactory.Block(stmt) ); var newRoot = root.ReplaceNode((SyntaxNode)node, ame.WithAdditionalAnnotations(Formatter.Annotation)); return Task.FromResult(document.WithSyntaxRoot(newRoot)); } ) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var property = root.FindNode(span) as PropertyDeclarationSyntax; if (property == null || !property.Identifier.Span.Contains(span)) return; if (property.AccessorList.Accessors.Any(b => b.Body != null)) //ignore properties with >=1 accessor body return; context.RegisterRefactoring( CodeActionFactory.Create( property.Identifier.Span, DiagnosticSeverity.Info, GettextCatalog.GetString("To computed property"), t2 => { //string name = GetNameProposal(property.Identifier.ValueText, model, root); //create our new property //var fieldExpression = name == "value" ? // (ExpressionSyntax)SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.ThisExpression(), SyntaxFactory.IdentifierName("value")) : // SyntaxFactory.IdentifierName(name); var getBody = SyntaxFactory.Block( SyntaxFactory.ThrowStatement( SyntaxFactory.ObjectCreationExpression( SyntaxFactory.QualifiedName( SyntaxFactory.IdentifierName(@"System"), SyntaxFactory.IdentifierName(@"NotImplementedException") ).WithoutAnnotations(Simplifier.Annotation) ).WithArgumentList(SyntaxFactory.ArgumentList()) ) ); var getter = SyntaxFactory.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration, getBody); var setter = SyntaxFactory.AccessorDeclaration(SyntaxKind.SetAccessorDeclaration, getBody); //var newPropAnno = new SyntaxAnnotation(); var newProperty = property.WithAccessorList(SyntaxFactory.AccessorList(new SyntaxList<AccessorDeclarationSyntax>().Add(getter).Add(setter))); newProperty = newProperty.WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode((SyntaxNode)property, newProperty); return Task.FromResult(document.WithSyntaxRoot(newRoot)); }) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var node = root.FindNode(span) as BinaryExpressionSyntax; //ignore nodes except string concat. if (node == null || !node.OperatorToken.IsKind(SyntaxKind.PlusToken)) return; LiteralExpressionSyntax left; var leftBinaryExpr = node.Left as BinaryExpressionSyntax; //if there is something other than a string literal on the left, then just take the right node (e.g. a+b+c => a+(b+c)) if (leftBinaryExpr != null && leftBinaryExpr.OperatorToken.IsKind(SyntaxKind.PlusToken)) left = leftBinaryExpr.Right as LiteralExpressionSyntax; else left = node.Left as LiteralExpressionSyntax; var right = node.Right as LiteralExpressionSyntax; //ignore non-string literals if (left == null || right == null || !left.IsKind(SyntaxKind.StringLiteralExpression) || !right.IsKind(SyntaxKind.StringLiteralExpression)) return; bool isLeftVerbatim = left.Token.IsVerbatimStringLiteral(); bool isRightVerbatim = right.Token.IsVerbatimStringLiteral(); if (isLeftVerbatim != isRightVerbatim) return; String newString = left.Token.ValueText + right.Token.ValueText; LiteralExpressionSyntax stringLit; if (isLeftVerbatim) stringLit = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal("@\"" + newString + "\"", newString)); else stringLit = SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(newString)); ExpressionSyntax exprNode; if (leftBinaryExpr == null) exprNode = stringLit; else exprNode = leftBinaryExpr.WithRight(stringLit); context.RegisterRefactoring( CodeActionFactory.Create(span, DiagnosticSeverity.Info, GettextCatalog.GetString("Join strings"), document.WithSyntaxRoot(root.ReplaceNode((SyntaxNode)node, exprNode as ExpressionSyntax))) ); }
public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context) { var document = context.Document; if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles) return; var span = context.Span; if (!span.IsEmpty) return; var cancellationToken = context.CancellationToken; if (cancellationToken.IsCancellationRequested) return; var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (model.IsFromGeneratedCode(cancellationToken)) return; var root = await model.SyntaxTree.GetRootAsync(cancellationToken).ConfigureAwait(false); var token = root.FindToken(span.Start); if (token.Parent == null) return; var bracketedList = token.Parent.AncestorsAndSelf().OfType<BracketedArgumentListSyntax>().FirstOrDefault(); if (bracketedList == null) return; var elementAccess = bracketedList.AncestorsAndSelf().OfType<ElementAccessExpressionSyntax>().FirstOrDefault(); if (elementAccess == null) return; var elementType = model.GetTypeInfo(elementAccess.Expression); var type = elementType.Type; if (type == null) return; if (!IsCollection(type as INamedTypeSymbol) && !type.AllInterfaces.Any(IsCollection)) return; var argument = elementAccess.ArgumentList?.Arguments.FirstOrDefault(); if (argument == null) return; context.RegisterRefactoring( CodeActionFactory.Create( span, DiagnosticSeverity.Info, string.Format(GettextCatalog.GetString("Check 'if ({0}.Count > {1})'"), elementAccess.Expression, argument), t2 => { var parentStatement = elementAccess.Parent.AncestorsAndSelf().OfType<StatementSyntax>().FirstOrDefault(); var newParent = SyntaxFactory.IfStatement( SyntaxFactory.BinaryExpression( SyntaxKind.GreaterThanExpression, SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, elementAccess.Expression, SyntaxFactory.IdentifierName("Count")), argument.Expression ), parentStatement ); return Task.FromResult(document.WithSyntaxRoot(root.ReplaceNode((SyntaxNode)parentStatement, newParent.WithAdditionalAnnotations(Formatter.Annotation)))); } ) ); }