2012-03-28 44 views
7

Sắp xếp và xóa (không sử dụng) bằng cách sử dụng câu lệnh Roslyn script/code? Tôi đang tìm một số mã .NET/Roslyn (trình biên dịch dưới dạng dịch vụ) có thể chạy qua một dự án và sắp xếp và loại bỏ các câu lệnh không sử dụng. Tôi tin rằng điều này là có thể với Roslyn? Bất cứ ai có thể chỉ cho tôi để mã mà có thể làm điều này viết lại?Sắp xếp và xóa (không sử dụng) bằng cách sử dụng câu lệnh Roslyn script/code?

Trả lời

5

Đây là một tính năng trong Visual Studio, nhưng học tập tôi nghĩ rằng bạn sẽ thu thập sử dụng báo cáo từ SyntaxTree của bạn như thế này:

var usings = syntaxTree.Root.DescendentNodes().Where(node is UsingDirectiveSyntax); 

... và so sánh với các không gian tên giải quyết bằng các bảng biểu tượng như thế này:

private static IEnumerable<INamespaceSymbol> GetNamespaceSymbol(ISymbol symbol) 
{ 
    if (symbol != null && symbol.ContainingNamespace != null) 
     yield return symbol.ContainingNamespace; 
} 

var ns = semanticModel.SyntaxTree.Root.DescendentNodes().SelectMany(node => 
    GetNamespaceSymbol(semanticModel.GetSemanticInfo(node).Symbol)).Distinct(); 
+1

Bạn có thể sử dụng ".OfType ()" thay vì" .Where (nút là UsingDirectiveSyntax) " –

1

Kiểm tra dự án mẫu OrganizeSolution đi kèm với Roslyn. Nó làm một cái gì đó tương tự như những gì bạn muốn. Nó có phần phân loại. Bạn cũng sẽ phải sử dụng SemanticModel như Jeff hiển thị để xác định xem không có tham chiếu đến một không gian tên cụ thể trong nguồn.

0

Để xóa câu lệnh, hãy xem mục Câu hỏi thường gặp 30 trong giải pháp trong thư mục sau, trong tệp FAQ.cs: (Lưu ý đây là phiên bản CTP tháng 6 năm 2012 của Roslyn).

% userprofile% \ Documents \ Microsoft Roslyn CTP - Tháng Sáu 2012 \ CSharp \ APISampleUnitTestsCS

Ngoài ra còn có một câu hỏi thường gặp trong đó đề cập đến dự án này:

http://www.codeplex.com/Download?ProjectName=dlr&DownloadId=386858

Đây là Ổ ghi mẫu từ mã mẫu, loại bỏ các câu lệnh gán.

// Below SyntaxRewriter removes multiple assignement statements from under the 
// SyntaxNode being visited. 
public class AssignmentStatementRemover : SyntaxRewriter 
{ 
    public override SyntaxNode VisitExpressionStatement(ExpressionStatementSyntax node) 
    { 
     SyntaxNode updatedNode = base.VisitExpressionStatement(node); 

     if (node.Expression.Kind == SyntaxKind.AssignExpression) 
     { 
      if (node.Parent.Kind == SyntaxKind.Block) 
      { 
       // There is a parent block so it is ok to remove the statement completely. 
       updatedNode = null; 
      } 
      else 
      { 
       // The parent context is some statement like an if statement without a block. 
       // Return an empty statement. 
       updatedNode = Syntax.EmptyStatement() 
        .WithLeadingTrivia(updatedNode.GetLeadingTrivia()) 
        .WithTrailingTrivia(updatedNode.GetTrailingTrivia()); 
      } 
     } 
    return updatedNode; 
    } 
} 
1

Roslyn CTP tháng 9 năm 2012 cung cấp phương thức GetUnusedImportDirectives(), được sử dụng tuyệt vời tại đây.

Bằng cách sửa đổi OrganizeSolution dự án mẫu Matt tham chiếu bạn có thể đạt được cả việc phân loại và loại bỏ (không sử dụng) bằng chỉ thị. Có thể tìm thấy phiên bản (đã lỗi thời) của dự án này tại đây: http://go.microsoft.com/fwlink/?LinkId=263977. Đó là lỗi thời vì document.GetUpdatedDocument() không tồn tại nữa,

var document = newSolution.GetDocument(documentId); 
var transformation = document.OrganizeImports(); 
var newDocument = transformation.GetUpdatedDocument(); 

có thể được đơn giản hóa để

var document = newSolution.GetDocument(documentId); 
var newDocument = document.OrganizeImports(); 

Thêm newDocument = RemoveUnusedImportDirectives(newDocument); và cung cấp các phương pháp sau đây sẽ làm các trick.

private static IDocument RemoveUnusedImportDirectives(IDocument document) 
{ 
    var root = document.GetSyntaxRoot(); 
    var semanticModel = document.GetSemanticModel(); 

    // An IDocument can refer to both a CSharp as well as a VisualBasic source file. 
    // Therefore we need to distinguish those cases and provide appropriate casts. 
    // Since the question was tagged c# only the CSharp way is provided. 
    switch (document.LanguageServices.Language) 
    { 
     case LanguageNames.CSharp: 
      var oldUsings = ((CompilationUnitSyntax)root).Usings; 
      var unusedUsings = ((SemanticModel)semanticModel).GetUnusedImportDirectives(); 
      var newUsings = Syntax.List(oldUsings.Where(item => !unusedUsings.Contains(item))); 
      root = ((CompilationUnitSyntax)root).WithUsings(newUsings); 
      document = document.UpdateSyntaxRoot(root); 
      break; 

     case LanguageNames.VisualBasic: 
      // TODO 
      break; 
    } 
    return document; 
} 
1

tôi sử dụng này phương pháp mở rộng sau để sắp xếp usings

internal static SyntaxList<UsingDirectiveSyntax> Sort(this SyntaxList<UsingDirectiveSyntax> usingDirectives, bool placeSystemNamespaceFirst = false) => 
    SyntaxFactory.List(
     usingDirectives 
     .OrderBy(x => x.StaticKeyword.IsKind(SyntaxKind.StaticKeyword) ? 1 : x.Alias == null ? 0 : 2) 
     .ThenBy(x => x.Alias?.ToString()) 
     .ThenByDescending(x => placeSystemNamespaceFirst && x.Name.ToString().StartsWith(nameof(System) + ".")) 
     .ThenBy(x => x.Name.ToString())); 

compilationUnit = compilationUnit.WithUsings(SortUsings(compilationUnit.Usings)) 
Các vấn đề liên quan