查找所有未使用 Roslyn 继承 C# 类 并更改为从基础对象继承(java-like)
Finding all not inheriting C# classes with Roslyn and changing to inheriting from base object (java-like)
我正在做一个 Roslyn 小项目,其中包括更改解析树和将更改写回文件。我已经开始使用独立代码分析器,并希望将其构建为命令行应用程序。不过,我遇到了挑战。
与:
Find classes which derive from a specific base class with Roslyn 部分,主要是:
https://github.com/dotnet/roslyn/wiki/Getting-Started-C%23-Syntax-Analysis 我创建了这个小项目:
class Program
{
static void Main(string[] args)
{
try
{
if (args.Length < 1)
throw new ArgumentException();
SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(args[0]));
var root = (CompilationUnitSyntax) tree.GetRoot();
var classes = from ClassDeclarationSyntax in root.DescendantNodesAndSelf() select ClassDeclarationSyntax;
foreach (var c in classes)
{
if (/*Not inheriting*/)
{
/*Add inherition*/
}
}
/*Write changes to file*/
}
catch (Exception e)
{
Console.WriteLine("Fatal error ocured.");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
正如代码中的注释所述,我需要检查 class 是否继承自某些东西(并选择第二个选项)然后更改解析树并最后将其写入文件,现在我很高兴知道如何仅检查“非继承”,尽管也欢迎对第二步和第三步的任何指示。要解析和更改的文件由路径作为程序参数提供:
if (args.Length < 1)
throw new ArgumentException();
SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(args[0]));
**解决方案**
在收到的答案的支持下,我想出了可以工作的应用程序。
这是我的代码,可能不完美但可以工作
class Program
{
static void Main(string[] args)
{
try
{
if (args.Length < 1)
throw new ArgumentException();
SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(args[0]));
var root = (CompilationUnitSyntax) tree.GetRoot();
IdentifierNameSyntax iname = SyntaxFactory.IdentifierName("Object");
BaseTypeSyntax bts = SyntaxFactory.SimpleBaseType(iname);
SeparatedSyntaxList<BaseTypeSyntax> ssl = new SeparatedSyntaxList<BaseTypeSyntax>();
ssl = ssl.Add(bts);
BaseListSyntax bls = SyntaxFactory.BaseList(ssl);
bool x = true;
while(x) //Way to handle all nodes due to impossibility to handle more than one in foreach
{
foreach (var c in root.DescendantNodesAndSelf())
{
x = false;
var classDeclaration = c as ClassDeclarationSyntax;
if (classDeclaration == null)
continue;
if (classDeclaration.BaseList != null) //Inherits
continue;
else //Not inherits
{
root = root.ReplaceNode(classDeclaration, classDeclaration.WithBaseList(bls));
x = true;
break;
}
}
}
if (args.Length > 1) //Write to given file
using (var sw = new StreamWriter(File.Open(args[1], FileMode.Open)))
{
root.WriteTo(sw);
}
else //Overwrite source
using (var sw = new StreamWriter(File.Open(args[0], FileMode.Open)))
{
root.WriteTo(sw);
}
}
catch (Exception e)
{
Console.WriteLine("Fatal error ocured.");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
ClassDeclarationSyntax
有 BaseList
包含 Types
。因此,您可以使用这些字段检索有关基础 classes 的信息:
foreach (var c in correctRoot.DescendantNodesAndSelf())
{
var classDeclaration = c as ClassDeclarationSyntax;
if (classDeclaration == null)
{
continue;
}
if (classDeclaration.BaseList?.Types.Count > 0)
{
Console.WriteLine("This class has base class or it implements interfaces");
}
else
{
/*Add inherition*/
}
}
不幸的是,您需要额外的逻辑来区分您的 class 具有基础 class 还是仅实现接口。如果你想解决这个问题,你需要使用 semantical model
分析 base object(class/interface) 来获取相应的信息ISymbol
或尝试在 syntax tree
中查找这些节点的声明,如果此声明在您的 projects/solutions.
中定义
此外,如果您想向 class 添加继承,您需要使用 SyntaxFactory.SimpleBaseType(...)
和 SyntaxFactory.BaseList(...)
将新创建的节点设置为 BaseList
我正在做一个 Roslyn 小项目,其中包括更改解析树和将更改写回文件。我已经开始使用独立代码分析器,并希望将其构建为命令行应用程序。不过,我遇到了挑战。 与: Find classes which derive from a specific base class with Roslyn 部分,主要是: https://github.com/dotnet/roslyn/wiki/Getting-Started-C%23-Syntax-Analysis 我创建了这个小项目:
class Program
{
static void Main(string[] args)
{
try
{
if (args.Length < 1)
throw new ArgumentException();
SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(args[0]));
var root = (CompilationUnitSyntax) tree.GetRoot();
var classes = from ClassDeclarationSyntax in root.DescendantNodesAndSelf() select ClassDeclarationSyntax;
foreach (var c in classes)
{
if (/*Not inheriting*/)
{
/*Add inherition*/
}
}
/*Write changes to file*/
}
catch (Exception e)
{
Console.WriteLine("Fatal error ocured.");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
正如代码中的注释所述,我需要检查 class 是否继承自某些东西(并选择第二个选项)然后更改解析树并最后将其写入文件,现在我很高兴知道如何仅检查“非继承”,尽管也欢迎对第二步和第三步的任何指示。要解析和更改的文件由路径作为程序参数提供:
if (args.Length < 1)
throw new ArgumentException();
SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(args[0]));
**解决方案**
在收到的答案的支持下,我想出了可以工作的应用程序。 这是我的代码,可能不完美但可以工作
class Program
{
static void Main(string[] args)
{
try
{
if (args.Length < 1)
throw new ArgumentException();
SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(args[0]));
var root = (CompilationUnitSyntax) tree.GetRoot();
IdentifierNameSyntax iname = SyntaxFactory.IdentifierName("Object");
BaseTypeSyntax bts = SyntaxFactory.SimpleBaseType(iname);
SeparatedSyntaxList<BaseTypeSyntax> ssl = new SeparatedSyntaxList<BaseTypeSyntax>();
ssl = ssl.Add(bts);
BaseListSyntax bls = SyntaxFactory.BaseList(ssl);
bool x = true;
while(x) //Way to handle all nodes due to impossibility to handle more than one in foreach
{
foreach (var c in root.DescendantNodesAndSelf())
{
x = false;
var classDeclaration = c as ClassDeclarationSyntax;
if (classDeclaration == null)
continue;
if (classDeclaration.BaseList != null) //Inherits
continue;
else //Not inherits
{
root = root.ReplaceNode(classDeclaration, classDeclaration.WithBaseList(bls));
x = true;
break;
}
}
}
if (args.Length > 1) //Write to given file
using (var sw = new StreamWriter(File.Open(args[1], FileMode.Open)))
{
root.WriteTo(sw);
}
else //Overwrite source
using (var sw = new StreamWriter(File.Open(args[0], FileMode.Open)))
{
root.WriteTo(sw);
}
}
catch (Exception e)
{
Console.WriteLine("Fatal error ocured.");
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
}
ClassDeclarationSyntax
有 BaseList
包含 Types
。因此,您可以使用这些字段检索有关基础 classes 的信息:
foreach (var c in correctRoot.DescendantNodesAndSelf())
{
var classDeclaration = c as ClassDeclarationSyntax;
if (classDeclaration == null)
{
continue;
}
if (classDeclaration.BaseList?.Types.Count > 0)
{
Console.WriteLine("This class has base class or it implements interfaces");
}
else
{
/*Add inherition*/
}
}
不幸的是,您需要额外的逻辑来区分您的 class 具有基础 class 还是仅实现接口。如果你想解决这个问题,你需要使用 semantical model
分析 base object(class/interface) 来获取相应的信息ISymbol
或尝试在 syntax tree
中查找这些节点的声明,如果此声明在您的 projects/solutions.
此外,如果您想向 class 添加继承,您需要使用 SyntaxFactory.SimpleBaseType(...)
和 SyntaxFactory.BaseList(...)
BaseList