在Visual Studio扩展中,我正在使用DocumentEditor(Microsoft.CodeAnalysis.Editing.DocumentEditor)类对源文件进行多次更新。
其中一项更改是将构造函数添加到类中。构造函数必须具有特定的参数,该参数通过依赖项注入传递,并且必须将参数保存到成员变量中。 如果构造函数已经存在,则应检查参数并检查赋值语句。
大多数方法都有效,但是如果我必须向空函数添加一条语句,则会出现问题。
如果构造函数已经存在并且包含一些语句,我可以添加一个新语句
RoslynEditor.InsertBefore ( cons.Body.Statements.First(), assExpr ) ;
如果构造函数存在,但为空,则此构造将不起作用。到目前为止,我还没有找到使用DocumentEditor类将语句插入到空函数体中的任何方法。
目前,我选择了大锤方法,使用DocumentEditor.ReplaceNode替换完整的构造方法。
那么有没有办法(如果主体为空)使用DocumentEditor类将语句插入到函数主体中?
这是我的代码的一部分。 _RoslynUtilCS中的函数仅返回一些roslyn语法。
// 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 ) ;
}
}
}
答案 0 :(得分:1)
Insert
和Add
方法是InsertMembers
的{{1}},无论如何他们用新的AKA SyntaxGenerator
替换了原始节点。
检查此方法的source code,您将看到插入成员以0个成员的方式阻止主体(对于Replace
而言)是返回声明本身而没有更改,这就是为什么您不能做简单的ConstructorDeclarationSyntax
。
您可以定义一个新的扩展方法来为您执行此操作,或者编写类似这样的内容来替换主体:
editor.Insert\Add..
或
editor.ReplaceNode(ctor.Body, SyntaxFactory.Block(newStatement));