C#Roslyn更改了评论类型

我正在尝试为Visual Studio做一个扩展,它改变了代码中的一些语法。 实际上,我已经完成了第一步,即改变变量的名称,如果这个名称不是我们在公司使用的规则。 例如:

int newVariable; double test; 

将改为:

 int iNewVariable; double dblTest; 

现在我必须更改此类评论:(SingleLineComment)

 //this is a single line Comment 

进入MultiLineComment

 /*Here it's a MultiLine one*/ 

我使用Roslyn语法Visualiser来查找生成正确代码的类型和种类,但没有任何作用。 这就是我为Diagnostic做的事情:

 using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace CodeFix { [DiagnosticAnalyzer] [ExportDiagnosticAnalyzer(DiagnosticId, LanguageNames.CSharp)] public class DiagnosticAnalyzer : ISyntaxNodeAnalyzer { internal const string DiagnosticId = "CodeFix"; internal const string Description = "Mauvais formattage"; internal const string MessageFormat = "'{0}'"; internal const string Category = "Correction"; internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Description, MessageFormat, Category, DiagnosticSeverity.Warning); public ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } } public ImmutableArray SyntaxKindsOfInterest //Ce qui nous intéresse { get { return ImmutableArray.Create(SyntaxKind.IfStatement, SyntaxKind.ElseClause, SyntaxKind.LocalDeclarationStatement, SyntaxKind.ConstKeyword, SyntaxKind.SingleLineCommentTrivia, SyntaxKind.SimpleAssignmentExpression); } } public void AnalyzeNode(SyntaxNode node, SemanticModel model, Action addDiagnostic, CancellationToken cancellationToken) //Analyse des Nodes { var ifStatement = node as IfStatementSyntax; //Récupération des IfStatement parmis tous les nodes if (ifStatement != null && ifStatement.Statement != null && !ifStatement.Statement.IsKind(SyntaxKind.Block)) { addDiagnostic(Diagnostic.Create(Rule, ifStatement.IfKeyword.GetLocation(), "Le if require des crochets")); } var elseClause = node as ElseClauseSyntax; //Récupération des Else parmis tous les nodes if (elseClause != null && elseClause.Statement != null && !elseClause.Statement.IsKind(SyntaxKind.Block) && //Pas que ce soit déjà un block avec {} !elseClause.Statement.IsKind(SyntaxKind.IfStatement)) //A cause des else if { addDiagnostic(Diagnostic.Create(Rule, elseClause.ElseKeyword.GetLocation(), "le else require des crochets")); } } } internal class IDiagnosticAnalyzer : ISyntaxTreeAnalyzer { internal const string DiagnosticIdComment = "CommentChanger"; internal const string DescriptionComment = "Les commentaires doivent être en format /* */"; internal const string MessageFormatComment = "'{0}' doit être en multiline"; internal const string CategoryComment = "Renommage"; internal static DiagnosticDescriptor RuleComment = new DiagnosticDescriptor(DiagnosticIdComment, DescriptionComment, MessageFormatComment, CategoryComment, DiagnosticSeverity.Warning); public ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(RuleComment); } } public void AnalyzeSyntaxTree(SyntaxTree tree, Action addDiagnostic, CancellationToken cancellationToken) { var root = tree.GetRoot(); var trivia = root.DescendantTrivia(); var a = trivia.Where(x => x.IsKind(SyntaxKind.SingleLineCommentTrivia)).ToList(); foreach (var b in a) { addDiagnostic(Diagnostic.Create(RuleComment, b.GetLocation(), "Commentaire sur une ligne")); } } } } 

这是CodeFix:

 using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Rename; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Formatting; using System; namespace CodeFix { [ExportCodeFixProvider(DiagnosticAnalyzer.DiagnosticId, LanguageNames.CSharp)] internal class CodeFixProvider : ICodeFixProvider { public IEnumerable GetFixableDiagnosticIds() { return new[] { DiagnosticAnalyzer.DiagnosticId }; } public async Task<IEnumerable> GetFixesAsync(Document document, TextSpan span, IEnumerable diagnostics, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); //Document à utiliser (root) var token = root.FindToken(span.Start); // if (token.IsKind(SyntaxKind.IfKeyword)) { var ifStatement = (IfStatementSyntax)token.Parent; var newIfStatement = ifStatement .WithStatement(SyntaxFactory.Block(ifStatement.Statement)) .WithAdditionalAnnotations(Formatter.Annotation); //Pour que ce soit indenté juste var newRoot = root.ReplaceNode(ifStatement, newIfStatement); return new[] { CodeAction.Create("Ajouter des crochets", document.WithSyntaxRoot(newRoot)) }; } if (token.IsKind(SyntaxKind.ElseKeyword)) { var elseClause = (ElseClauseSyntax)token.Parent; var newElseClause = elseClause .WithStatement(SyntaxFactory.Block(elseClause.Statement)) .WithAdditionalAnnotations(Formatter.Annotation); var newRoot = root.ReplaceNode(elseClause, newElseClause); return new[] { CodeAction.Create("Ajouter des crochets", document.WithSyntaxRoot(newRoot)) }; } if (token.IsKind(SyntaxKind.SingleLineCommentTrivia)) { var root1 = await document.GetSyntaxRootAsync(cancellationToken); var token1 = root1.FindToken(span.Start); var allTrivia = token1.GetAllTrivia(); foreach (var singleTrivia in allTrivia) { if (singleTrivia.IsKind(SyntaxKind.SingleLineCommentTrivia)) { var commentContent = singleTrivia.ToString().Replace("//", string.Empty); var newComment = SyntaxFactory.Comment(string.Format("/*{0}*/", commentContent)); var newRoot = root.ReplaceTrivia(singleTrivia, newComment); return new[] { CodeAction.Create("Convert to multiline", document.WithSyntaxRoot(newRoot)) }; } } } return null; } } } 

用户必须单击我的程序提供的广告,并且评论将被更改。

但我的程序永远不会进入我必须调用方法的地方。

我正在与罗斯林迈出第一步,所以我不知道很多事情,但我正在学习它……

编辑:

所有代码都添加了

我已经使用带有诊断function的CodeFix组合了一个示例,该示例使用多行注释替换单行注释。 这是一些代码。 很多都是基于来自Build的Dustin Campbell的Roslyn演示,可以在http://channel9.msdn.com/Events/Build/2014/2-577上看到

从ISyntaxTreeAnalyzer AnalyzeSyntaxTree实现以查找单行注释:

 [DiagnosticAnalyzer] [ExportDiagnosticAnalyzer(DiagnosticId, LanguageNames.CSharp)] internal class DiagnosticAnalyzer : ISyntaxTreeAnalyzer { internal const string DiagnosticId = "CommentChanger"; internal const string Description = "Single comments should be multiline comments"; internal const string MessageFormat = "'{0}' should be multiline"; internal const string Category = "Naming"; internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Description, MessageFormat, Category, DiagnosticSeverity.Warning); public ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } } public void AnalyzeSyntaxTree(SyntaxTree tree, Action addDiagnostic, CancellationToken cancellationToken) { var root = tree.GetRoot(); var trivia = root.DescendantTrivia(); var a = trivia.Where(x => x.IsKind(SyntaxKind.SingleLineCommentTrivia)).ToList(); foreach(var b in a) { addDiagnostic(Diagnostic.Create(Rule, b.GetLocation(), "Single comment")); } } } 

来自ICodeFixProvider的GetFixesAsync实现:

 public async Task> GetFixesAsync(Document document, TextSpan span, IEnumerable diagnostics, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken); var token = root.FindToken(span.Start); var allTrivia = token.GetAllTrivia(); foreach(var singleTrivia in allTrivia) { if (singleTrivia.IsKind(SyntaxKind.SingleLineCommentTrivia)) { var commentContent = singleTrivia.ToString().Replace("//", string.Empty); var newComment = SyntaxFactory.Comment(string.Format("/*{0}*/", commentContent)); var newRoot = root.ReplaceTrivia(singleTrivia, newComment); return new[] { CodeAction.Create("Convert to multiline", document.WithSyntaxRoot(newRoot)) }; } } return null; }