Code analysis with roslyn - Getting all elements of a given type
-
2 ธันวาคม 2554 13:19
Hi
I'm currently playing with roslyn.
whats the easiest way to get all elements of a given type from a source file?
For example getting all "if" from a cs file ?
- แก้ไขโดย Gentlehag 2 ธันวาคม 2554 13:20
ตอบทั้งหมด
-
2 ธันวาคม 2554 18:41
To get all the IfStatementSyntax nodes from a cs file, first get the SyntaxTree for the file and then use the DescendentNodes() method on the root node, followed by the LINQ OfType operator.
var ifStatements = tree.Root.DescendantNodes().OfType<IfStatementSyntax>();
Wayward LINQ Lacky -
2 ธันวาคม 2554 20:17เจ้าของ
If you wish to 'process' all nodes of type IfStatementSyntax in a SyntaxTree, you could also implement a SyntaxWalker / SyntaxVisitor -
class Program
{
static void Main(string[] args)
{
var source = @"
class Program
{
static void Main()
{
if (true) Console.WriteLine(""First"");
if (false) Console.WriteLine(""Second"");
}
}";
var tree = SyntaxTree.ParseCompilationUnit(source);
var walker = new Walker();
walker.Visit(tree.Root);
}
}
class Walker : SyntaxWalker
{
private int count = 0;
protected override void VisitIfStatement(IfStatementSyntax node)
{
count++;
Console.WriteLine(count + ": " + node.GetText());
base.VisitIfStatement(node);
}
}The above program prints the following output -
1: if (true) Console.WriteLine("First");
2: if (false) Console.WriteLine("Second");
Shyam Namboodiripad | Software Development Engineer in Test | Roslyn Compilers Team- แก้ไขโดย Shyam NamboodiripadMicrosoft, Owner 2 ธันวาคม 2554 20:18
- แก้ไขโดย Shyam NamboodiripadMicrosoft, Owner 2 ธันวาคม 2554 20:18
- เสนอเป็นคำตอบโดย Shyam NamboodiripadMicrosoft, Owner 4 มกราคม 2555 2:03
-
3 ธันวาคม 2554 11:40
Hi
the walker was what I'm loogik for.
What is there correct way to count empty and not empty lines ?
For examlple to make some LOC and LLOC Metrics ? Is there a explizit visit method for empty lines or an explicite visit method for non empty lines ?
Should I accumulate the different nodes types like "BlockSyntax" and so on ?
Or should I count the semicolon token?
Many thanks in advances
- แก้ไขโดย Gentlehag 3 ธันวาคม 2554 11:41
-
5 ธันวาคม 2554 22:42เจ้าของI think there are different ways to do this depending on your definition of LOC and LLOC :)You shouldn't need a Walker to count just the total LOC -var tree = SyntaxTree.ParseCompilationUnit(source);
Console.WriteLine("Total LOC: " + tree.Text.LineCount);
// OR
// Console.WriteLine(tree.Root.GetFullTextAsIText().LineCount);
var linesWithNoText = 0;
foreach (var l in tree.Text.Lines)
{
if (string.IsNullOrEmpty(l.GetText().Trim()))
{
++linesWithNoText;
}
}If you want to count the number of semi-colons in the code you could write a SyntaxWalker that counts this as follows -static void Main()
{
var source = @"
class Program
{
// A comment
/* A multi-line
comment */
#if false
Some disabled code
#endif
static void Main()
{
if (true) Console.WriteLine(""First"");
if (false) Console.WriteLine(""Second"");
}
}";
var tree = SyntaxTree.ParseCompilationUnit(source);
var walker = new Walker();
walker.Visit(tree.Root);
Console.WriteLine("SemiColon Count: " + walker.SemiColonCount);
}
class Walker : SyntaxWalker
{
public Walker()
: base(visitIntoStructuredTrivia: true)
{
}
public int SemiColonCount { get; private set; }
protected override void VisitToken(SyntaxToken token)
{
base.VisitToken(token);
if (token.Kind == SyntaxKind.SemicolonToken)
{
++SemiColonCount;
}
}
}You could also count the EndOfLineTrivia in the SyntaxTree by overriding VisitTrivia() in your SyntaxWalker - however, this would only count "significant" new lines (for example this wouldn't count new lines within a MultiLineCommentTrivia).class Walker2 : SyntaxWalker
{
public Walker2()
: base(visitIntoStructuredTrivia: true)
{
}
public int SignificantEOLCount { get; private set; }
protected override void VisitTrivia(SyntaxTrivia trivia)
{
base.VisitTrivia(trivia);
if (trivia.Kind == SyntaxKind.EndOfLineTrivia)
{
++SignificantEOLCount;
}
}
}
Shyam Namboodiripad | Software Development Engineer in Test | Roslyn Compilers Team- แก้ไขโดย Shyam NamboodiripadMicrosoft, Owner 5 ธันวาคม 2554 22:46
- แก้ไขโดย Shyam NamboodiripadMicrosoft, Owner 5 ธันวาคม 2554 22:46
- แก้ไขโดย Shyam NamboodiripadMicrosoft, Owner 5 ธันวาคม 2554 22:47
- เสนอเป็นคำตอบโดย Shyam NamboodiripadMicrosoft, Owner 4 มกราคม 2555 2:03
- ยกเลิกการนำเสนอเป็นคำตอบโดย Shyam NamboodiripadMicrosoft, Owner 4 มกราคม 2555 2:03
-
6 ธันวาคม 2554 19:56เจ้าของ
To clarify a bit about Roslyn's Syntax model, parts of the source text that are insignificant from the point of view of compilation (e.g. whitespace, new lines, comments etc.) are parsed into objects of type SyntaxTrivia which are attached under SyntaxTokens. Parts of source text that are significant from point of view of compilation (e.g. identifiers, keywords etc.) are parsed into SyntaxTokens and these SyntaxTokens are in turn attached under a hierarchy of SyntaxNodes (e.g. if statements, class declarations etc.). Some SyntaxTrivia such as those for preprocessor directives and xml documentation comments have 'structure' (and can contain child SyntaxNodes and SyntaxTokens) - these special trivia are called structured trivia -http://social.msdn.microsoft.com/Forums/en-US/roslyn/thread/7bcc72a1-e54e-44eb-a488-0a0ace0ed903.
The Roslyn Project Overview Document contains a nice overview regarding the shape and contents of syntax trees (see section 3). This doc also contains a nice overview of the compilation pipeline (Syntax, Symbols, Semantics, Code Generation) and the APIs exposed in Roslyn for each stage in this pipeline.
The Roslyn CTP also ships with a couple of syntax visulaizer tools. You could use 'Syntax Visualizer Tool Window' tool to understand how the tree looks for specific forms of source code and figure out what Kinds / Types you would need special handling for in your Walker...
Shyam Namboodiripad | Software Development Engineer in Test | Roslyn Compilers Team