Я использую API компилятора .NET для написания некоторых анализаторов кода / исправителей кода в Roslyn.Я хочу, чтобы исправление кода преобразовало следующий код:
string.Format("{0} {1}", A, B)
В
StringExtensions.SafeJoin(" ", A, B)
Пока у меня есть этот код:
private async Task<Document> UseJoinAsync(Document document, InvocationExpressionSyntax invocationExpr, CancellationToken cancellationToken)
{
var argumentList = invocationExpr.ArgumentList;
var firstArgument = argumentList.Arguments[1];
var secondArgument = argumentList.Arguments[2];
var statement =
InvocationExpression(
MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression,
IdentifierName("StringExtensions"), // requires using Trilogy.Miscellaneous
IdentifierName("SafeJoin")))
.WithArgumentList(
ArgumentList(
SeparatedList<ArgumentSyntax>(
new SyntaxNodeOrToken[]
{
Argument(
LiteralExpression(
SyntaxKind.StringLiteralExpression,
Literal(" "))),
Token(SyntaxKind.CommaToken),
firstArgument,
Token(SyntaxKind.CommaToken),
secondArgument
}))).WithLeadingTrivia(invocationExpr.GetLeadingTrivia()).WithTrailingTrivia(invocationExpr.GetTrailingTrivia())
.WithAdditionalAnnotations(Formatter.Annotation);
var root = await document.GetSyntaxRootAsync(cancellationToken);
var newRoot = root.ReplaceNode(invocationExpr, statement);
var newDocument = document.WithSyntaxRoot(newRoot);
return newDocument;
}
Однако яесть две нерешенные проблемы:
1) Как я могу добавить необходимые using Trilogy.Miscellaneous
в начало файла.
и
2) Как я могу определить, еслина требуемую сборку ссылается мой проект.В этом случае, если на мою сборку Trilogy.Common
нет ссылки, я бы либо не предложил исправление кода, либо я бы предложил string.Join(" ", A, B)
вместо моей собственной реализации SafeJoin
.
UPDATE
Я решил # 1, обновив свой код следующим образом ...
var newRoot = root.ReplaceNode(invocationExpr, statement);
// Iterate through our usings to see if we've got what we need...
if (root?.Usings.Any(u => u.Name.ToString() == "Trilogy.Miscellaneous") == false)
{
// Create and add the using statement...
var usingStatement = UsingDirective(QualifiedName(IdentifierName("Trilogy"), IdentifierName("Miscellaneous")));
newRoot = newRoot.AddUsings(usingStatement);
}
var newDocument = document.WithSyntaxRoot(newRoot);
return newDocument;
Все еще надеемся на некоторую помощь с пунктом № 2.