Skip to content

Instantly share code, notes, and snippets.

@threecourse
Created October 5, 2014 11:22
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save threecourse/2c2c612646b492ae24bd to your computer and use it in GitHub Desktop.
Save threecourse/2c2c612646b492ae24bd to your computer and use it in GitHub Desktop.
analyze codes with roslyn
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace MyRoslyn.CSharp
{
class Program
{
static void MainCSharp(string[] args)
{
// ソリューションを取得し、そこからComplilationを取得する。
var ws = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var sol = ws.OpenSolutionAsync(@"C:\Users\Administrator2\Documents\Visual Studio 14\Projects\RoslynTarget\RoslynTarget.sln").Result;
var proj = sol.Projects.First();
var comp = proj.GetCompilationAsync().Result;
// Compilationから情報を解析する。
GetMethodsClass.Analyze(comp);
Console.Read();
}
}
public class GetMethodsClass
{
public static void Analyze(Compilation comp)
{
// ファイルごとにSyntaxTreeが分かれているので、各SyntaxTreeごとに処理する。
foreach (var tree in comp.SyntaxTrees)
{
Console.WriteLine("================================================");
Console.WriteLine(tree.FilePath);
Console.WriteLine("------------------------------------------------");
var model = comp.GetSemanticModel(tree);
var root = tree.GetRoot();
// Method宣言を表すノードを取得し、各ノードごとに処理する。
var methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (MethodDeclarationSyntax methodDeclareNode in methods)
{
// Methodの情報を取得する。
var symbol = model.GetDeclaredSymbol(methodDeclareNode);
Console.WriteLine(symbol.ToDisplayString());
Console.WriteLine("----");
// 代入を表すノードを判定するためのメソッドを作成する。
SyntaxKind[] AssignKinds = new SyntaxKind[]
{ SyntaxKind.AddAssignmentExpression,
SyntaxKind.AndAssignmentExpression,
SyntaxKind.SimpleAssignmentExpression,
SyntaxKind.SimpleAssignmentExpression ,
SyntaxKind.AddAssignmentExpression ,
SyntaxKind.SubtractAssignmentExpression ,
SyntaxKind.MultiplyAssignmentExpression ,
SyntaxKind.DivideAssignmentExpression ,
SyntaxKind.ModuloAssignmentExpression ,
SyntaxKind.AndAssignmentExpression ,
SyntaxKind.ExclusiveOrAssignmentExpression ,
SyntaxKind.OrAssignmentExpression ,
SyntaxKind.LeftShiftAssignmentExpression ,
SyntaxKind.RightShiftAssignmentExpression};
Func<SyntaxKind, bool> isTargetSyntax = (SyntaxKind syntaxKind) => (Array.IndexOf(AssignKinds, syntaxKind) >= 0);
// 代入を表すノードを取得し、各ノードごとに処理する。
var assignnodes = methodDeclareNode.DescendantNodes().OfType<BinaryExpressionSyntax>().Where(exp => isTargetSyntax(exp.CSharpKind()));
foreach (BinaryExpressionSyntax assignNode in assignnodes)
{
// 代入式の左辺を取得する。
var left = assignNode.Left;
Console.WriteLine("{0} --- {1}", left.ToString(), assignNode.ToString());
// 代入式の左辺からWalkerで情報を取得する。
var walker = new GetSymbolWalker { SemanticModel = model };
walker.Visit(left);
Console.WriteLine(walker.Results);
}
Console.WriteLine();
}
Console.WriteLine("================================================");
Console.WriteLine();
}
}
}
// ノードに含まれるSymbolを取得し、情報を書き出す。
// FAQ(10)を参照
public class GetSymbolWalker : CSharpSyntaxWalker
{
public SemanticModel SemanticModel { get; set; }
public StringBuilder Results { get; private set; }
public GetSymbolWalker()
{
Results = new StringBuilder();
}
public override void Visit(SyntaxNode node)
{
if (node is IdentifierNameSyntax)
{
var symbol = SemanticModel.GetSymbolInfo(node).Symbol;
var type = SemanticModel.GetTypeInfo(node).Type;
if (type != null)
{
Results.Append(symbol.ToDisplayString());
Results.Append(" : ");
Results.Append(type.ToDisplayString());
Results.AppendLine();
}
}
base.Visit(node);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment