c# - 用方法替换 C# 代码中的所有变量

标签 c# code-analysis roslyn

我需要解析用户编写的 C# 代码片段,并用方法调用替换所有未在本地定义的变量。即

public class Foo
{
  public dynamic Bar()
  {
     return Math.Min(x + width, maxWidth);
  }
}

必须变成:

public class Foo
{
  public dynamic Bar()
  {
      return Math.Min(Resolve("x") + Resolve("width"), Resolve("maxWidth"));
  }
}

我正在使用 Microsoft.CodeAnalysis.CSharp 和 CSharpSyntaxTree 检查字符串,但它没有提供足够的信息来执行替换。或者即使有,我也不知道去哪里找。我在下面粘贴了 SyntaxTree 布局。所有变量都作为 IdentifierName 节点出现,但我不知道如何区分不同的 IdentifierNames。从这里去哪里?

CompilationUnit[0..99) {
 code:  public class Foo\n{\n  public dynamic Bar()\n  {\n    return Math.Min(x + width, maxWidth);\n  }\n}
 tokens: EndOfFileToken[] 
 nodes{
  ClassDeclaration[0..99) {
   code:  public class Foo\n{\n  public dynamic Bar()\n  {\n    return Math.Min(x + width, maxWidth);\n  }\n}
   tokens: PublicKeyword[public ] ClassKeyword[class ] IdentifierToken[Foo\n] OpenBraceToken[{\n] CloseBraceToken[}] 
   nodes{
    MethodDeclaration[21..98) {
     code:    public dynamic Bar()\n  {\n    return Math.Min(x + width, maxWidth);\n  }\n
     tokens: PublicKeyword[  public ] IdentifierToken[Bar] 
     nodes{
      IdentifierName[30..38) {
       code:  dynamic 
       tokens: IdentifierToken[dynamic ] 
      }
      ParameterList[41..45) {
       code:  ()\n
       tokens: OpenParenToken[(] CloseParenToken[)\n] 
      }
      Block[45..98) {
       code:    {\n    return Math.Min(x + width, maxWidth);\n  }\n
       tokens: OpenBraceToken[  {\n] CloseBraceToken[  }\n] 
       nodes{
        ReturnStatement[50..93) {
         code:      return Math.Min(x + width, maxWidth);\n
         tokens: ReturnKeyword[    return ] SemicolonToken[;\n] 
         nodes{
          InvocationExpression[61..90) {
           code:  Math.Min(x + width, maxWidth)
           nodes{
            SimpleMemberAccessExpression[61..69) {
             code:  Math.Min
             tokens: DotToken[.] 
             nodes{
              IdentifierName[61..65) {
               code:  Math
               tokens: IdentifierToken[Math] 
              }
              IdentifierName[66..69) {
               code:  Min
               tokens: IdentifierToken[Min] 
              }
             }
            }
            ArgumentList[69..90) {
             code:  (x + width, maxWidth)
             tokens: OpenParenToken[(] CommaToken[, ] CloseParenToken[)] 
             nodes{
              Argument[70..79) {
               code:  x + width
               nodes{
                AddExpression[70..79) {
                 code:  x + width
                 tokens: PlusToken[+ ] 
                 nodes{
                  IdentifierName[70..72) {
                   code:  x 
                   tokens: IdentifierToken[x ] 
                  }
                  IdentifierName[74..79) {
                   code:  width
                   tokens: IdentifierToken[width] 
                  }
                 }
                }
               }
              }
              Argument[81..89) {
               code:  maxWidth
               nodes{
                IdentifierName[81..89) {
                 code:  maxWidth
                 tokens: IdentifierToken[maxWidth] 
                }
               }
              }
             }
            }
           }
          }
         }
        }
       }
      }
     }
    }
   }
  }
 }
}

最佳答案

我认为你需要使用语义模型。这是一个(非常基本的)示例,展示了如何查找未解析的符号:

var tree = CSharpSyntaxTree.ParseFile(fileName);
var root = tree.GetRoot();
var refs = new MetadataReference[]
{
    new MetadataFileReference(@"C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll", new MetadataReferenceProperties(MetadataImageKind.Assembly))
};
var compilation = CSharpCompilation.Create("testRoslyn", new[] { tree }, refs);
var model = compilation.GetSemanticModel(tree);

var unknownSymbols =
    from node in root.DescendantNodes()
    where node.IsKind(SyntaxKind.IdentifierName)
    let symbolInfo = model.GetSymbolInfo(node)
    where symbolInfo.Symbol == null && !symbolInfo.CandidateSymbols.Any()
    select node;

从那里您可以用 Resolve(name) 替换节点。

关于c# - 用方法替换 C# 代码中的所有变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24798188/

相关文章:

c# - 使用 Foreach 函数搜索 Gtk# TreeModel

c# - 远程服务器返回错误 : (405) Method Allowed

c# - 如何改进此设计以处理相交的日期范围并解决日期范围冲突?

c# - 如何判断变量是否在 Roslyn 的某个语法节点的范围内?

c# - 如何使用一个属性来初始化另一个属性?

c# - 为什么 Enum.Parse 创建未定义的条目?

.net - .NET的TeamCity静态代码分析工具

tdd - 与测试驱动开发相结合时,代码分析 checkin 策略会降低生产力

visual-studio-2008 - 如何从 VS2008 代码分析中排除 MFC 代码

c# - 到处查找枚举转换为字符串