В моем расширении Visual Studio я использую класс DocumentEditor (Microsoft.CodeAnalysis.Editing.DocumentEditor) для многократного обновления исходного файла.
Одно из изменений - добавление конструктора вучебный класс.Конструктор должен иметь определенный параметр, который передается путем внедрения зависимости, и должен сохранять параметр в переменной-члене.Если конструктор уже присутствует, он должен проверить параметр и проверить оператор присваивания.
Большая часть этого работает, но возникает проблема, если мне нужно добавить оператор в пустую функцию.
Если конструктор уже существует и содержит некоторые операторы, я могу добавить новый оператор с помощью
RoslynEditor.InsertBefore ( cons.Body.Statements.First(), assExpr ) ;
Если конструктор существует, но пуст, тогда это не будет работать.До сих пор я не нашел способа вставить оператор в пустое тело функции с помощью класса DocumentEditor.
В настоящее время я выбрал метод кувалды для замены завершенного конструктора с помощью DocumentEditor.ReplaceNode.
Так есть ли способ вставить инструкцию в тело функции - используя класс DocumentEditor - если тело пусто?
Вот часть моегокод.Функции в _RoslynUtilCS просто возвращают синтаксис Розлина.
// Look for the constructor
var cons = c.DescendantNodes().OfType<ConstructorDeclarationSyntax>().FirstOrDefault() ;
if ( cons == null )
{
// There is no constructor.
cons = _RoslynUtilCS.ControllerConstructor ( ShortClassName )
.WithAdditionalAnnotations ( Formatter.Annotation )
.WithTrailingTrivia ( _RoslynUtilCS.LineFeedSyntax() ) ;
RoslynEditor.InsertBefore ( c.Members.First(), cons ) ;
}
else
{
string parameterName = null ;
// There is a constructor.
// Does it already have a parameter of the generic IStringLocalizer type
foreach ( var p in cons.ParameterList.Parameters )
{
var t = p.Type ;
var gt = t as GenericNameSyntax ;
if ( gt != null )
{
if ( gt.Identifier.ToString() == "IStringLocalizer" )
{
parameterName = p.Identifier.ToString() ;
}
}
}
if ( string.IsNullOrEmpty ( parameterName ) )
{
// Add a parameter
var param = _RoslynUtilCS.LocalizerParameter ( ShortClassName ) ;
RoslynEditor.AddParameter ( cons, param ) ;
// Add an assignment statement to assign the parameter to the localizer member variable.
var assExpr = _RoslynUtilCS.LocalizerAsignment()
.WithAdditionalAnnotations ( Formatter.Annotation ) ;
if ( cons.Body.Statements.Count == 0 )
{
// -------------------------------------------------------------------
// Here I replace the complete constructor.
// because I don't know how to insert a statement into
// the empty constructor body.
// -------------------------------------------------------------------
var newcons = _RoslynUtilCS.ControllerConstructor ( ShortClassName )
.WithAdditionalAnnotations ( Formatter.Annotation )
.WithTrailingTrivia ( _RoslynUtilCS.LineFeedSyntax() ) ;
RoslynEditor.ReplaceNode ( cons, newcons ) ;
}
else
{
RoslynEditor.InsertBefore ( cons.Body.Statements.First(), assExpr ) ;
}
}
else
{
// NOT TESTED
// It seems a bit over the top, but having found a parameter, we should look
// for an assignment to the member variable and add it if it is missing.
var count = cons.DescendantNodes()
.OfType<AssignmentExpressionSyntax>()
.Where(node => node.Kind() == SyntaxKind.SimpleAssignmentExpression)
.Where(node => node.Left.ToString() == "_localizer")
.Where(node => node.Right.ToString() == "localizer")
.Count() ;
if ( count == 0 )
{
// Add an assignment statement to assign the parameter to the localizer member variable.
var assExpr = _RoslynUtilCS.LocalizerAsignment() ;
// -------------------------------------------------------------------
// This is likely to have the same problem.
// It won't work if the body contains no statements.
// -------------------------------------------------------------------
RoslynEditor.InsertBefore ( cons.Body.Statements.First(), assExpr ) ;
}
}
}