Добавить модификатор доступа к методу с использованием Roslyn CodeFixProvider?
Я был в TechEd несколько дней назад, и я увидел этот разговор Кевина Пильча-Биссона (значительная часть начинается примерно через 18 минут)... я мысль была довольно крутой, поэтому я решил поиграть с Рослином.
Я пытаюсь сделать правило "Модификатор доступа должен быть объявлен" (Stylecop SA1400) - значение,
Это нарушает правило:
static void Main(string[] args)
{
}
Это нормально:
public static void Main(string[] args)
{
}
Он должен иметь явное внутреннее ключевое слово, ключевое слово public, ключевое слово private или защищенное ключевое слово.
Обнаружение нарушения было довольно простым, но теперь я пытаюсь обеспечить исправление. Я пробовал вещи и искал везде, но я не могу узнать, как добавлять модификаторы доступа.
Это то, что у меня есть до сих пор:
public async Task<IEnumerable<CodeAction>> GetFixesAsync(Document document, TextSpan span, IEnumerable<Diagnostic> diagnostics, CancellationToken cancellationToken)
{
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var token = root.FindToken(span.Start);
var methodDeclaration = token.Parent as MethodDeclarationSyntax;
//var newModifiers = methodDeclaration.Modifiers.Add(SyntaxFactory.AccessorDeclaration(SyntaxKind.PublicKeyword));
//var newModifiers = new SyntaxTokenList() { new SyntaxToken() };
MethodDeclarationSyntax newMethodDeclaration = methodDeclaration.WithModifiers(methodDeclaration.Modifiers);
var newRoot = root.ReplaceNode(methodDeclaration, newMethodDeclaration);
var newDocument = document.WithSyntaxRoot(newRoot);
return new[] { CodeAction.Create("Add Public Keyword", newDocument) };
}
Для WithModifiers
требуется SyntaxTokenList
, для которого я могу использовать New(), но я не знаю, как сделать его SyntaxKind.PublicKeyword
. Я также не уверен, что я даже предполагаю, что это новое, или используйте SyntaxFactory
. Однако при использовании SyntaxFactory
я также не могу понять, какой метод мне нужен, чтобы создать SyntaxToken
из SyntaxKind.PublicKeyword
Я могу опубликовать все, включая DiagnosticAnalyzer
, если есть интерес...
Ответы
Ответ 1
Я действительно нуждался в этом:
var newModifiers = SyntaxFactory.TokenList(SyntaxFactory.Token(accessModifierToken))
.AddRange(methodDeclaration.Modifiers);
Его почти то, что предложил Крис Элмаа, но с этим предложением я закончил с static public void Main
, который действителен, но уродлив.
Добавление публики добавляет его в конец списка, и, насколько я знаю, модификатор доступа всегда должен быть первым.
Ответ 2
Рад, что вам понравилось! На самом деле у нас есть некоторые помощники в синтаксической модели, чтобы упростить добавление элементов в списки, поэтому вы должны иметь возможность сделать что-то вроде:
var newMethodDeclaration = methodDeclaration.AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
Чтобы получить новое объявление метода.
Развернутая форма этого будет выглядеть примерно так:
var newModifiers = SyntaxFactory.TokenList(modifiers.Concat(new[] { SyntaxFactory.Token(SyntaxKind.PublicKeyword)}));
var newMethodDeclaration = methodDeclaration.WithModifiers(newModifiers);
Надеюсь, что это поможет
Ответ 3
Ну, чтобы создать модификаторы, указывающие public static
, вы можете использовать это:
var modifiers = SyntaxFactory.TokenList(
new SyntaxToken[] {
SyntaxFactory.Token(SyntaxKind.PublicKeyword),
SyntaxFactory.Token(SyntaxKind.StaticKeyword)
}),
Но в вашем случае я не понимаю, почему
var updatedModifiers = methodDeclaration
.Modifiers
.Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
methodDeclaration.WithModifiers(updatedModifiers);
не будет работать.