2016-12-01 12 views
1

私はRoslynにもう少し興味を持って、ソリューションを分析するのに役立つアプリケーションを作成しようとしています。深くネストされたオブジェクトを含むツリービュー?

は、私はまだC#とWPFへの比較的新しいので、私はここで重要なのか、明らかに何かを見逃して、指摘しておかなければ。

私のソリューションの構造をツリービューに表示したいと思います。 私はすでにこのような出力をテキストファイルに私の解決策の構造をエクスポートすることができるよ:

+ Analysing the following project: Testtool 
|+ Analysing the following document: Converters.cs 
||+ The following namespaces are referenced for the analysed file: 
|||- System 
|||- System.Collections.Generic 
|||- System.Linq 
|||- System.Text 
|||- System.Threading.Tasks 
|||- System.Windows.Data 
||- The file lives in the following namespace: Testtool 
||+ Analysing the following class of the current file: BooleanInverter 
|||+ The following modifiers are used for the class: 
||||- public 
||||- partial 
|||+ The following methods are defined in the currently analysed class: 
||||+ Convert 
|||||+ The following modifiers are used for the method: 
||||||- public 
||||+ ConvertBack 
|||||+ The following modifiers are used for the method: 
||||||- public 
|+ Analysing the following document: LoadingControl.xaml.cs 
||+ The following namespaces are referenced for the analysed file: 
|||- System 
|||- System.Collections.Generic 
|||- System.Linq 
|||- System.Text 
|||- System.Threading.Tasks 
|||- System.Windows 
|||- System.Windows.Controls 
|||- System.Windows.Data 
|||- System.Windows.Documents 
|||- System.Windows.Input 
|||- System.Windows.Media 
|||- System.Windows.Media.Imaging 
|||- System.Windows.Navigation 
|||- System.Windows.Shapes 
|||- System.ComponentModel 
||- The file lives in the following namespace: Testtool 
||+ Analysing the following class of the current file: LoadingControl 
|||+ The following modifiers are used for the class: 
||||- public 
||||- partial 
|||+ The following methods are defined in the currently analysed class: 
||||+ OnPropertyChanged 
|||||+ The following modifiers are used for the method: 
||||||- public 
|||+ The following properties are defined in the currently analysed class: 
||||+ SpinnerText 
|||||+ The following modifiers are used for the Property: 
||||||- public 

今、私は良い方法がオブジェクトにこの構造を表示するにはどうなるかわかりません。つまり、より良い可能性がなければ、対応するオブジェクトモデルを作成しますが、そのような深くネストされたオブジェクトの必要性は間違っていると感じています。 だから、誰かがこれについてもっと良いアイデアを持っているかもしれませんか?

+1

たぶん[SyntaxVisualizerソースコード(https://github.com/dotnet/roslyn/tree/614299ff83da9959fa07131c6d0ffbc58873b6ae/src/:

 // Open the solution from the supplied path string solutionPath = @"Path to your solution"; MSBuildWorkspace msWorkspace = MSBuildWorkspace.Create(); Solution solution = msWorkspace.OpenSolutionAsync(solutionPath).Result; // Analyze each project. foreach (var project in solution.Projects) { // Set project node SyntaxTreeNode projectNode = new SyntaxTreeNode(); projectNode.Name = project.Name; projectNode.Type = "Project"; projectNode.SyntaxTreeNodes = new ObservableCollection<SyntaxTreeNode>(); // Add the defined node to the collection (first tree level). TreeViewNodes.Add(projectNode); // Set the recently added node as a “parentNode”. This will be used later to add the prebuild subnode (or a list of subnodes). SyntaxTreeNode parentProjectNode = CommonDataAccess.TreeViewNodes[CommonDataAccess.TreeViewNodes.Count - 1]; // Get the list of referenced assemblies for the project. Subsequently create a new node that will then show them (a “root node” for the references if you want to say so). At this point the node does NOT yet get added to the collection that’s bound to the TreeView. IReadOnlyList<MetadataReference> projectReferences = project.MetadataReferences; SyntaxTreeNode referenceNode = new SyntaxTreeNode(); referenceNode.Name = "Referenced assemblies"; referenceNode.Type = "Reference list"; referenceNode.SyntaxTreeNodes = new ObservableCollection<SyntaxTreeNode>(); // Create a new node for each reference entry under the reference “root node” defined above. foreach (MetadataReference reference in projectReferences) { SyntaxTreeNode refNode = new SyntaxTreeNode(); int refNameStart = reference.Display.LastIndexOf("\\") + 1; int refNameLength = reference.Display.Length - refNameStart; refNode.Name = reference.Display.Substring(refNameStart, refNameLength); refNode.Type = "Reference"; referenceNode.SyntaxTreeNodes.Add(refNode); } // Now add the prebuild reference “root node” with the single reference nodes to the earlier defined project node (therefore creating a structure with two sublevels). parentProjectNode.SyntaxTreeNodes.Add(referenceNode); // Now go through the documents for the current project. foreach (Document document in project.Documents) { // Add a subnode to the current project for the document. SyntaxTreeNode TreeNode = new SyntaxTreeNode(); TreeNode.Name = document.Name; TreeNode.Type = "File"; parentProjectNode.SyntaxTreeNodes.Add(TreeNode); string path = document.FilePath; FileStream stream = File.OpenRead(path); SyntaxTree tree = CSharpSyntaxTree.ParseText(SourceText.From(stream), path: path); CompilationUnitSyntax root = (CompilationUnitSyntax)tree.GetRoot(); // Similar to the project level, determine the node for each document now and set it as “parentNode”. So this is actually now on a sublevel (most likely the first). SyntaxTreeNode actNode = parentProjectNode.SyntaxTreeNodes[parentProjectNode.SyntaxTreeNodes.Count - 1]; // Call the method for adding the subnodes for the current document. Passing with ref so no need to return a node. getSubNodes(root, ref actNode); } } } // Simple method for getting the childs of the SyntaxTree, init the sublevel collection and adding prepared subnodes to the parent node. public void getSubNodes(CompilationUnitSyntax parentTree, ref SyntaxTreeNode parentNode) { ChildSyntaxList childs = parentTree.ChildNodesAndTokens(); List<SyntaxTreeNode> nodesToAdd = iterateSubNodes(childs); foreach (SyntaxTreeNode node in nodesToAdd) { if (parentNode.SyntaxTreeNodes == null) parentNode.SyntaxTreeNodes = new ObservableCollection<SyntaxTreeNode>(); parentNode.SyntaxTreeNodes.Add(node); } } // Method for examing the kind of the current node. If no proper kind was found “recursively” searching through the nodes. Has to be improved, expanded and refactored still (dictionary could be suitable for this). public List<SyntaxTreeNode> iterateSubNodes (ChildSyntaxList syntaxList) { List<SyntaxTreeNode> nodesToReturn = new List<SyntaxTreeNode>(); foreach (SyntaxNodeOrToken nodeOrToken in syntaxList) { SyntaxKind childKind = nodeOrToken.Kind(); if (childKind == SyntaxKind.UsingDirective) { SyntaxTreeNode tokenToAdd = new SyntaxTreeNode(); UsingDirectiveSyntax usingNode = (UsingDirectiveSyntax)nodeOrToken; tokenToAdd = addUsing(usingNode); nodesToReturn.Add(tokenToAdd); } else if (childKind == SyntaxKind.NamespaceDeclaration) { SyntaxTreeNode tokenToAdd = new SyntaxTreeNode(); NamespaceDeclarationSyntax namespaceNode = (NamespaceDeclarationSyntax)nodeOrToken; tokenToAdd = addNamespace(namespaceNode); nodesToReturn.Add(tokenToAdd); } else { iterateSubNodes(nodeOrToken.ChildNodesAndTokens()); } } // Return the node (or a list of them) for further processing. return nodesToReturn; } // Method for defining the parameters for a NameSpaceDeclaration. private SyntaxTreeNode addNamespace(NamespaceDeclarationSyntax namespaceSyntax) { SyntaxTreeNode nodeToReturn = new SyntaxTreeNode(); nodeToReturn.Name = namespaceSyntax.Name.ToString(); nodeToReturn.Type = "Namespace Definition"; return nodeToReturn; } // The same as for Namespace, here just for usingDirectives. private SyntaxTreeNode addUsing(UsingDirectiveSyntax usingSyntax) { SyntaxTreeNode nodeToReturn = new SyntaxTreeNode(); nodeToReturn.Name = usingSyntax.Name.ToString(); nodeToReturn.Type = usingSyntax.Kind().ToString(); return nodeToReturn; } 

上記のコードは私に最後に、このようなビューを与えますツール/ソース/ SyntaxVisualizer)はあなたを助けます –

答えて

0

デュディが既に示しているように、構文ビジュアライザも全体の構文木とツリービューを提供し、しかし、あなたのコンソール出力を見て、あなたが「裸の構文木」の要約を表示したいようです。解析では構文木が非常に多く要約されているので、対応するオブジェクトモデルを探しています。そのため、多くのビューモデルは必要ありません。

WPFでツリービューを使用している経験はありませんが、おそらく、Solutionを表すトップレベルのビューモデルにバインドするだけで、子どもたちはProjectビューモデルを返します。暗黙的なデータテンプレートを使用すると、残りの処理が実行されます。

あなたは、このためのいくつかのサンプルコードが必要な場合、私はそれを追加することがうれしいです。

+0

私のために働く解決策を少し投稿します。その間にあなたの答えをありがとう、それは本当に私を助けた! – CuttingWide

0

最初はお返事いただきありがとうございます。彼らは私を助け、良い考えを持ち出しました。 しかし、「純粋なオブジェクトモデル」アプローチについては、私が大いに嫌っていたことがいくつか残っていました。しかし、いくつかの検索の後、私のニーズに合った解決策を考えながら、私の意見では維持するのが良いと思っています。 RoslynのSyntax Visualizerのソースコードは私にそれをもたらしました。 要点:

  • 単一の "SyntaxTreeNode"プロパティを定義します。このプロパティは に他のSyntaxTreeNodeオブジェクトのリストを含めることができます。
  • 所定の方法で溶液を繰り返し、必要な情報を抽出します。
  • 新しいノードが が追加されなければならない「はparentNode」を指定する方法を実装します。現在調べているSyntaxNode/Tokenの種類を確認してください。種類によって
  • は(ここではまだ改善/リファクタリングのためのいくつかの良い部屋です)に応じて ノードのパラメータを設定します。
  • サブノードがビルドされたら、決定した親に追加します。
  • のObservableCollectionとしてプロパティを定義し、それに ツリービューItemSourceをバインドします。

私はSyncfusions sfTreeGridを使用しているので、列の処理方法が異なる可能性があります。しかし、それはポイントを得る必要があります。

SyntaxTreeNode定義

// The property used for binding the ItemsSource of the sfTreeView 
    private ObservableCollection<SyntaxTreeNode> _TreeViewNodes; 
    public ObservableCollection<SyntaxTreeNode> TreeViewNodes 
    { 
     get { return _TreeViewNodes; } 
     set 
     { 
      _TreeViewNodes = value; 
     } 
    } 

ソリューション階層オブジェクトを取得するための中央の方法を検討したクラスで

public class SyntaxTreeNode 
{ 
    // A node can contain other nodes 
    public ObservableCollection<SyntaxTreeNode> SyntaxTreeNodes { get; set; } 
    public string Name { get; set; } 
    public string Type { get; set; } 
} 

。まだ正しくリファクタリングされていません。 public void displaySyntaxTree() { //プロパティを初期化します。 TreeViewNodes = new ObservableCollection();

enter image description here
関連する問題