Skip to content

Commit

Permalink
Render source snippet on location (#291)
Browse files Browse the repository at this point in the history
This is something I implemented in my project's test implementation and found very helpful on large source generator samples - rendering the actual source snippet as an output comment, with squiggly lines underlining the problematic section, similar to what you get when compiling in the console.

Unfortunately, only one test in this repo uses locations from actual source trees, so it might be harder to see the benefits, but even this modified example should give an idea of what it looks like.
  • Loading branch information
RReverser committed Sep 18, 2024
1 parent 5ee50d8 commit d39a929
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
: (1,0)-(1,14)
/*
class Foo {
void Bar() { }
^^^^^^^^^^^^^^
}
*/
theFile.cs: (1,0)-(1,14)
2 changes: 1 addition & 1 deletion src/Tests/SyntaxLocationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ void Bar() { }
""";

var source = SourceText.From(sourceText);
var syntaxTree = SyntaxFactory.ParseSyntaxTree(source);
var syntaxTree = SyntaxFactory.ParseSyntaxTree(source, path: "theFile.cs");

var methodDeclarationSyntax = syntaxTree
.GetRoot()
Expand Down
37 changes: 34 additions & 3 deletions src/Verify.SourceGenerators/Converters/LocationConverter.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
class LocationConverter :
WriteOnlyJsonConverter<Location>
{
public override void Write(VerifyJsonWriter writer, Location value) =>
writer.Serialize(value.GetMappedLineSpan());
}
const int contextLines = 1;

public override void Write(VerifyJsonWriter writer, Location value)
{
var lineSpan = value.GetMappedLineSpan();

// Pretty-print the error with the source code snippet.
if (value.SourceTree is { } source)
{
var comment = new StringBuilder().AppendLine();
var lines = source.GetText().Lines;
var startLine = Math.Max(lineSpan.StartLinePosition.Line - contextLines, 0);
var endLine = Math.Min(lineSpan.EndLinePosition.Line + contextLines, lines.Count - 1);
for (var lineIdx = startLine; lineIdx <= endLine; lineIdx++)
{
var line = lines[lineIdx];
// print the source line
comment.AppendLine(line.ToString());
// print squiggly line highlighting the location
if (line.Span.Intersection(value.SourceSpan) is { } intersection)
{
comment
.Append(' ', intersection.Start - line.Start)
.Append('^', intersection.Length)
.AppendLine();
}
}
writer.WriteComment(comment.ToString());
writer.WriteWhitespace("\n");
}

writer.Serialize(lineSpan);
}
}

0 comments on commit d39a929

Please sign in to comment.