我可以使用Roslyn DocumentEditor将语句插入到空函数体中

问题描述 投票:0回答:1

在我的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 ) ;
    }
  }
}
visual-studio roslyn
1个回答
1
投票

编辑的InsertAdd方法最终是InsertMembersSyntaxGenerator,他们无论如何用新的AKA Replace替换原始节点。

检查这个方法的source code,你会看到插入成员阻塞正文有0个成员(如果是ConstructorDeclarationSyntax)返回声明本身没有变化,这就是为什么你不能做简单的editor.Insert\Add..

您可以定义一个新的扩展方法,为您执行此操作,或者编写类似于替换正文的内容:

editor.ReplaceNode(ctor.Body, SyntaxFactory.Block(newStatement));

要么

editor.ReplaceNode(ctor, ctor.WithBody(ctor.Body.AddStatements(newStatement)));
© www.soinside.com 2019 - 2024. All rights reserved.