工作代码处理文档实例 – 我创建一个单独的文档,每个片段包含单个方法和所有潜在的导入,将其添加到项目中,然后删除不必要的使用指令,如下所示:
private async static Task<Document> RemoveUnusedImportsAsync(Document document) { var compilation = await document.Project.GetCompilationAsync(); var tree = await document.GetSyntaxTreeAsync(); var root = tree.GetRoot(); var unusedImportNodes = compilation.GetDiagnostics() .Where(d => d.Id == "CS8019") .Where(d => d.Location?.sourceTree == tree) .Select(d => root.FindNode(d.Location.sourceSpan)) .ToList(); return document.WithSyntaxRoot( root.RemoveNodes(unusedImportNodes,SyntaxRemoveOptions.KeepNoTrivia)); }
我了解到,在使用文档时我可以使用IOrganizeImportsService,但是我想把它写成一个脚本,因为它以各种方式变得更干净.
创建脚本很容易,所以我只想分析一下未使用的导入(在一些早期的清理步骤之后).这里的代码我希望工作的脚本:
private static Script RemoveUnusedImports(Script script) { var compilation = script.GetCompilation(); var tree = compilation.SyntaxTrees.Single(); var root = tree.GetRoot(); var unusedImportNodes = compilation.GetDiagnostics() .Where(d => d.Id == "CS8019") .Where(d => d.Location?.sourceTree == tree) .Select(d => root.FindNode(d.Location.sourceSpan)) .ToList(); var newRoot = root.RemoveNodes(unusedImportNodes,SyntaxRemoveOptions.KeepNoTrivia); return csharpscript.Create(newRoot.ToFullString(),script.Options); }
不幸的是,这根本没有发现任何诊断 – 它们只是在编译时才产生:(
以下是一个简短的示例应用程序:
using System; using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; class Program { static void Main(string[] args) { string text = @" using System; using System.Collections.Generic; Console.WriteLine(""I only need to use System"");"; Script script = csharpscript.Create(text); // Not sure whether this *should* be required,but it doesn't help... script.Compile(); var compilation = script.GetCompilation(); foreach (var d in compilation.GetDiagnostics()) { Console.WriteLine($"{d.Id}: {d.GetMessage()}"); } } }
必需包:Microsoft.CodeAnalysis.CSharp.Scripting(例如v2.1.0)
这不产生任何输出:(
我的猜测是这是打算的,因为脚本通常有不同的用例.但是,有没有办法为脚本目的启用更多诊断?还是有一些替代方法来检测脚本中的未使用的导入?如果没有,我会回到我的基于文档的方法 – 这很可惜,因为其他一切似乎都很好地与脚本工作…
解决方法
但是,您可以通过跳过脚本引擎并自行直接创建编译来实现您之前所做的工作.这实际上是脚本主机在幕后添加了一些编译默认值以及一些奇怪的东西,如提升类声明.跳过脚本主机并自己创建编译的代码看起来像:
using System; using System.IO; using System.Reflection; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; class Program { static void Main(string[] args) { string text = @" using System; using System.Collections.Generic; Console.WriteLine(""I only need to use System"");"; SyntaxTree SyntaxTree = CSharpSyntaxTree.ParseText(text,new CSharpParSEOptions(kind: SourceCodeKind.Script)); var coreDir = Path.GetDirectoryName(typeof(object).GetTypeInfo().Assembly.Location); var mscorlib = MetadataReference.CreateFromFile(Path.Combine(coreDir,"mscorlib.dll")); var options = new CSharpCompilationoptions(OutputKind.DynamicallyLinkedLibrary); var compilation = CSharpCompilation.Create("MyAssembly") .AddSyntaxTrees(SyntaxTree) .AddReferences(mscorlib) .WithOptions(options); foreach (var d in compilation.GetDiagnostics()) { Console.WriteLine($"{d.Id}: {d.GetMessage()}"); } } }
您会注意到这会产生一些关于缺少引用的不合需要的诊断信息,因此编译引用需要稍加调整以包含默认库(您可以在上面查看mscorlib的模式).您还应该看到关于未使用的语句的所需诊断.
原文地址:https://www.jb51.cc/csharp/94644.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。