Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3be229f

Browse files
committed
C#: Separate visitors to dedicated files, rename and reorganize comment extraction related classes
1 parent cf860f1 commit 3be229f

7 files changed

Lines changed: 205 additions & 195 deletions

File tree

csharp/extractor/Semmle.Extraction.CSharp/Analyser.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,9 +374,9 @@ private void DoExtractTree(SyntaxTree tree)
374374
if (!upToDate)
375375
{
376376
var cx = extractor.CreateContext(compilation.Clone(), trapWriter, new SourceScope(tree), AddAssemblyTrapPrefix);
377-
Populators.CompilationUnit.Extract(cx, tree.GetRoot());
377+
CompilationUnitVisitor.Extract(cx, tree.GetRoot());
378378
cx.PopulateAll();
379-
cx.ExtractComments(cx.CommentGenerator);
379+
TriviaPopulator.ExtractCommentBlocks(cx, cx.CommentGenerator);
380380
cx.PopulateAll();
381381
}
382382
}

csharp/extractor/Semmle.Extraction.CSharp/Entities/CommentLine.cs

Lines changed: 1 addition & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -21,97 +21,6 @@ private CommentLine(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLine
2121
public string Text { get { return symbol.Item2; } }
2222
public string RawText { get; private set; }
2323

24-
public static void Extract(Context cx, SyntaxTrivia trivia)
25-
{
26-
switch (trivia.Kind())
27-
{
28-
case SyntaxKind.SingleLineDocumentationCommentTrivia:
29-
/*
30-
This is actually a multi-line comment consisting of /// lines.
31-
So split it up.
32-
*/
33-
34-
var text = trivia.ToFullString();
35-
36-
var split = text.Split('\n');
37-
var currentLocation = trivia.GetLocation().SourceSpan.Start - 3;
38-
39-
for (var line = 0; line < split.Length - 1; ++line)
40-
{
41-
var fullLine = split[line];
42-
var nextLineLocation = currentLocation + fullLine.Length + 1;
43-
fullLine = fullLine.TrimEnd('\r');
44-
var trimmedLine = fullLine;
45-
46-
var leadingSpaces = trimmedLine.IndexOf('/');
47-
if (leadingSpaces != -1)
48-
{
49-
fullLine = fullLine.Substring(leadingSpaces);
50-
currentLocation += leadingSpaces;
51-
trimmedLine = trimmedLine.Substring(leadingSpaces + 3); // Remove leading spaces and the "///"
52-
trimmedLine = trimmedLine.Trim();
53-
54-
var span = Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(currentLocation, currentLocation + fullLine.Length);
55-
var location = Microsoft.CodeAnalysis.Location.Create(trivia.SyntaxTree, span);
56-
var commentType = CommentLineType.XmlDoc;
57-
cx.CommentGenerator.AddComment(Create(cx, location, commentType, trimmedLine, fullLine));
58-
}
59-
else
60-
{
61-
cx.ModelError("Unexpected comment format");
62-
}
63-
currentLocation = nextLineLocation;
64-
}
65-
break;
66-
67-
case SyntaxKind.SingleLineCommentTrivia:
68-
{
69-
var contents = trivia.ToString().Substring(2);
70-
var commentType = CommentLineType.Singleline;
71-
if (contents.Length > 0 && contents[0] == '/')
72-
{
73-
commentType = CommentLineType.XmlDoc;
74-
contents = contents.Substring(1); // An XML comment.
75-
}
76-
cx.CommentGenerator.AddComment(Create(cx, trivia.GetLocation(), commentType, contents.Trim(), trivia.ToFullString()));
77-
}
78-
break;
79-
case SyntaxKind.MultiLineDocumentationCommentTrivia:
80-
case SyntaxKind.MultiLineCommentTrivia:
81-
/* We receive a single SyntaxTrivia for a multiline block spanning several lines.
82-
So we split it into separate lines
83-
*/
84-
text = trivia.ToFullString();
85-
86-
split = text.Split('\n');
87-
currentLocation = trivia.GetLocation().SourceSpan.Start;
88-
89-
for (var line = 0; line < split.Length; ++line)
90-
{
91-
var fullLine = split[line];
92-
var nextLineLocation = currentLocation + fullLine.Length + 1;
93-
fullLine = fullLine.TrimEnd('\r');
94-
var trimmedLine = fullLine;
95-
if (line == 0)
96-
trimmedLine = trimmedLine.Substring(2);
97-
if (line == split.Length - 1)
98-
trimmedLine = trimmedLine.Substring(0, trimmedLine.Length - 2);
99-
trimmedLine = trimmedLine.Trim();
100-
101-
var span = Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(currentLocation, currentLocation + fullLine.Length);
102-
var location = Microsoft.CodeAnalysis.Location.Create(trivia.SyntaxTree, span);
103-
var commentType = line == 0 ? CommentLineType.Multiline : CommentLineType.MultilineContinuation;
104-
cx.CommentGenerator.AddComment(Create(cx, location, commentType, trimmedLine, fullLine));
105-
currentLocation = nextLineLocation;
106-
}
107-
break;
108-
// Strangely, these are reported as SingleLineCommentTrivia.
109-
case SyntaxKind.DocumentationCommentExteriorTrivia:
110-
cx.ModelError($"Unhandled comment type {trivia.Kind()} for {trivia}");
111-
break;
112-
}
113-
}
114-
11524
private Extraction.Entities.Location location;
11625

11726
public override void Populate(TextWriter trapFile)
@@ -131,7 +40,7 @@ public override void WriteId(TextWriter trapFile)
13140
trapFile.Write(";commentline");
13241
}
13342

134-
private static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw)
43+
internal static CommentLine Create(Context cx, Microsoft.CodeAnalysis.Location loc, CommentLineType type, string text, string raw)
13544
{
13645
var init = (loc, type, text, raw);
13746
return CommentLineFactory.Instance.CreateEntity(cx, init, init);

csharp/extractor/Semmle.Extraction.CSharp/Populators/Comments.cs

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using Semmle.Util.Logging;
5+
6+
namespace Semmle.Extraction.CSharp.Populators
7+
{
8+
internal class CompilationUnitVisitor : TypeOrNamespaceVisitor
9+
{
10+
private CompilationUnitVisitor(Context cx)
11+
: base(cx, cx.TrapWriter.Writer, null) { }
12+
13+
public override void VisitExternAliasDirective(ExternAliasDirectiveSyntax node)
14+
{
15+
// This information is not yet extracted.
16+
cx.ExtractionError("Not implemented extern alias directive", node.ToFullString(), Extraction.Entities.Location.Create(cx, node.GetLocation()), "", Severity.Info);
17+
}
18+
19+
public override void VisitCompilationUnit(CompilationUnitSyntax compilationUnit)
20+
{
21+
foreach (var m in compilationUnit.ChildNodes())
22+
{
23+
cx.Try(m, null, () => ((CSharpSyntaxNode)m).Accept(this));
24+
}
25+
26+
// Gather comments:
27+
foreach (var trivia in compilationUnit.DescendantTrivia(compilationUnit.Span))
28+
{
29+
TriviaPopulator.ExtractTrivia(cx, trivia);
30+
}
31+
32+
foreach (var trivia in compilationUnit.GetLeadingTrivia())
33+
{
34+
TriviaPopulator.ExtractTrivia(cx, trivia);
35+
}
36+
37+
foreach (var trivia in compilationUnit.GetTrailingTrivia())
38+
{
39+
TriviaPopulator.ExtractTrivia(cx, trivia);
40+
}
41+
}
42+
43+
public static void Extract(Context cx, SyntaxNode unit)
44+
{
45+
// Ensure that the file itself is populated in case the source file is totally empty
46+
Extraction.Entities.File.Create(cx, unit.SyntaxTree.FilePath);
47+
48+
((CSharpSyntaxNode)unit).Accept(new CompilationUnitVisitor(cx));
49+
}
50+
}
51+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Semmle.Extraction.CommentProcessing;
4+
using Semmle.Extraction.CSharp.Entities;
5+
using System;
6+
7+
namespace Semmle.Extraction.CSharp.Populators
8+
{
9+
/// <summary>
10+
/// Populators for trivias.
11+
/// </summary>
12+
public static class TriviaPopulator
13+
{
14+
public static void ExtractCommentBlocks(Context cx, ICommentGenerator gen)
15+
{
16+
cx.Try(null, null, () =>
17+
{
18+
gen.GenerateBindings((entity, duplicationGuardKey, block, binding) =>
19+
{
20+
var commentBlock = Entities.CommentBlock.Create(cx, block);
21+
Action a = () =>
22+
{
23+
commentBlock.BindTo(entity, binding);
24+
};
25+
// When the duplication guard key exists, it means that the entity is guarded against
26+
// trap duplication (<see cref = "Context.BindComments(IEntity, Location)" />).
27+
// We must therefore also guard comment construction.
28+
if (duplicationGuardKey != null)
29+
cx.WithDuplicationGuard(duplicationGuardKey, a);
30+
else
31+
a();
32+
});
33+
});
34+
}
35+
36+
public static void ExtractTrivia(Context cx, SyntaxTrivia trivia)
37+
{
38+
switch (trivia.Kind())
39+
{
40+
case SyntaxKind.SingleLineDocumentationCommentTrivia:
41+
/*
42+
This is actually a multi-line comment consisting of /// lines.
43+
So split it up.
44+
*/
45+
46+
var text = trivia.ToFullString();
47+
48+
var split = text.Split('\n');
49+
var currentLocation = trivia.GetLocation().SourceSpan.Start - 3;
50+
51+
for (var line = 0; line < split.Length - 1; ++line)
52+
{
53+
var fullLine = split[line];
54+
var nextLineLocation = currentLocation + fullLine.Length + 1;
55+
fullLine = fullLine.TrimEnd('\r');
56+
var trimmedLine = fullLine;
57+
58+
var leadingSpaces = trimmedLine.IndexOf('/');
59+
if (leadingSpaces != -1)
60+
{
61+
fullLine = fullLine.Substring(leadingSpaces);
62+
currentLocation += leadingSpaces;
63+
trimmedLine = trimmedLine.Substring(leadingSpaces + 3); // Remove leading spaces and the "///"
64+
trimmedLine = trimmedLine.Trim();
65+
66+
var span = Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(currentLocation, currentLocation + fullLine.Length);
67+
var location = Microsoft.CodeAnalysis.Location.Create(trivia.SyntaxTree, span);
68+
var commentType = CommentLineType.XmlDoc;
69+
cx.CommentGenerator.AddComment(CommentLine.Create(cx, location, commentType, trimmedLine, fullLine));
70+
}
71+
else
72+
{
73+
cx.ModelError("Unexpected comment format");
74+
}
75+
currentLocation = nextLineLocation;
76+
}
77+
break;
78+
79+
case SyntaxKind.SingleLineCommentTrivia:
80+
{
81+
var contents = trivia.ToString().Substring(2);
82+
var commentType = CommentLineType.Singleline;
83+
if (contents.Length > 0 && contents[0] == '/')
84+
{
85+
commentType = CommentLineType.XmlDoc;
86+
contents = contents.Substring(1); // An XML comment.
87+
}
88+
cx.CommentGenerator.AddComment(CommentLine.Create(cx, trivia.GetLocation(), commentType, contents.Trim(), trivia.ToFullString()));
89+
}
90+
break;
91+
case SyntaxKind.MultiLineDocumentationCommentTrivia:
92+
case SyntaxKind.MultiLineCommentTrivia:
93+
/* We receive a single SyntaxTrivia for a multiline block spanning several lines.
94+
So we split it into separate lines
95+
*/
96+
text = trivia.ToFullString();
97+
98+
split = text.Split('\n');
99+
currentLocation = trivia.GetLocation().SourceSpan.Start;
100+
101+
for (var line = 0; line < split.Length; ++line)
102+
{
103+
var fullLine = split[line];
104+
var nextLineLocation = currentLocation + fullLine.Length + 1;
105+
fullLine = fullLine.TrimEnd('\r');
106+
var trimmedLine = fullLine;
107+
if (line == 0)
108+
trimmedLine = trimmedLine.Substring(2);
109+
if (line == split.Length - 1)
110+
trimmedLine = trimmedLine.Substring(0, trimmedLine.Length - 2);
111+
trimmedLine = trimmedLine.Trim();
112+
113+
var span = Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(currentLocation, currentLocation + fullLine.Length);
114+
var location = Microsoft.CodeAnalysis.Location.Create(trivia.SyntaxTree, span);
115+
var commentType = line == 0 ? CommentLineType.Multiline : CommentLineType.MultilineContinuation;
116+
cx.CommentGenerator.AddComment(CommentLine.Create(cx, location, commentType, trimmedLine, fullLine));
117+
currentLocation = nextLineLocation;
118+
}
119+
break;
120+
// Strangely, these are reported as SingleLineCommentTrivia.
121+
case SyntaxKind.DocumentationCommentExteriorTrivia:
122+
cx.ModelError($"Unhandled comment type {trivia.Kind()} for {trivia}");
123+
break;
124+
}
125+
}
126+
}
127+
}

0 commit comments

Comments
 (0)