코드의 일부 구문을 변경하는 Visual Studio 용 확장 프로그램을 만들려고합니다. 사실, 나는이 이름이 회사에서 사용하는 규칙에 맞지 않으면 변수의 이름을 변경하는 첫 번째 단계를 수행했습니다. 예를 들어하십시오 MultiLineCommentC# Roslyn이 주석 유형 변경
/*Here it's a MultiLine one*/
속으로 (SingleLineComment)
//this is a single line Comment
:
int iNewVariable;
double dblTest;
가 지금은 이러한 종류의 주석을 변경해야합니다 :
는int newVariable;
double test;
는로 변경됩니다
Roslyn Sy를 사용합니다. ntax Visualiser는 올바른 코드를 만들 수있는 종류와 종류를 찾지 만 아무 것도 작동하지 않습니다. 은 여기 내가 진단을 위해 무슨 짓을했는지의 :
여기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<SyntaxKind>
{
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<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(Rule); }
}
public ImmutableArray<SyntaxKind> 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<Diagnostic> 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<DiagnosticDescriptor> SupportedDiagnostics
{
get { return ImmutableArray.Create(RuleComment); }
}
public void AnalyzeSyntaxTree(SyntaxTree tree, Action<Diagnostic> 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<string> GetFixableDiagnosticIds()
{
return new[] { DiagnosticAnalyzer.DiagnosticId };
}
public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> 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;
}
}
}
사용자는 내 프로그램을 제공하고 주석이 변경 될 광고를 클릭한다.
그러나 프로그램을 호출해야하는 곳에서는 프로그램이 실행되지 않습니다.
내가 로슬린 내 첫 번째 단계를하고 있어요, 그래서 이미 많은 것들을 모르겠지만, 나는 그것에 대해 배우고 ..
편집 :
모든 코드 덧붙여서
을 감사! 하지만 질문이 있습니다. 공용 클래스 DiagnosticAnalyzer : {} 또는이 하나 개 공용 클래스 IDiagnosticAnalyzer 같은 다른 클래스 ISyntaxNodeAnalyzer : ISyntaxTreeAnalyzer 느린 응답에 대한 {} –
Maloz
사과를 나는에 코드를 삽입해야합니다. 이 예제에서는 ISyntaxTreeAnalyzer를 사용합니다. 클래스의 나머지 코드를 위 코드에 추가했습니다. AnaylzeSyntaxTree 메서드는 ISyntaxTreeAnalyzer 인터페이스에 의해 구현되었습니다. – rh072005
그래서, 이미 시도한 바입니다.하지만 DiagnosticAnalyzer에서 2 클래스를 사용하는 것이 문제 일 수 있습니까? 왜냐하면 나는 어떤 진단도 없기 때문에 ... 당신의 코드를 가져가더라도, 같은 것을 붙여 넣습니다. 오류는 없지만 진단은 없습니다. 유일한 차이점은 내 DiagnosticAnalyzer에 다른 클래스가 있다는 점입니다.일부 노드를 분석하는 데 사용되는 cs입니다. public class DiagnosticAnalyzer : ISyntaxNodeAnalyzer {} –
Maloz