summaryrefslogtreecommitdiff
path: root/source/compiler-core/slang-diagnostic-sink.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/compiler-core/slang-diagnostic-sink.cpp')
-rw-r--r--source/compiler-core/slang-diagnostic-sink.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/source/compiler-core/slang-diagnostic-sink.cpp b/source/compiler-core/slang-diagnostic-sink.cpp
index 314ec1c2c..0110b16d7 100644
--- a/source/compiler-core/slang-diagnostic-sink.cpp
+++ b/source/compiler-core/slang-diagnostic-sink.cpp
@@ -138,6 +138,10 @@ static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const&
outBuilder << humaneLoc.pathInfo.foundPath;
outBuilder << "(";
outBuilder << Int32(humaneLoc.line);
+ if (flags & DiagnosticSink::Flag::LanguageServer)
+ {
+ outBuilder << ", " << humaneLoc.column;
+ }
outBuilder << "): ";
}
@@ -348,6 +352,47 @@ static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sour
sb << caretLine << "\n";
}
+// Output the length of the token at `sourceLoc`. This is used by language server.
+static void _tokenLengthNoteDiagnostic(
+ DiagnosticSink* sink, SourceView* sourceView, SourceLoc sourceLoc, StringBuilder& sb)
+{
+ SourceFile* sourceFile = sourceView->getSourceFile();
+ if (!sourceFile)
+ {
+ return;
+ }
+
+ UnownedStringSlice content = sourceFile->getContent();
+
+ // Make sure the offset is within content.
+ // This is important because it's possible to have a 'SourceFile' that doesn't contain any
+ // content (for example when reconstructed via serialization with just line offsets, the actual
+ // source text 'content' isn't available).
+ const int offset = sourceView->getRange().getOffset(sourceLoc);
+ if (offset < 0 || offset >= content.getLength())
+ {
+ return;
+ }
+
+ // Work out the position of the SourceLoc in the source
+ const char* const pos = content.begin() + offset;
+
+ UnownedStringSlice line = _extractLineContainingPosition(content, pos);
+
+ // Trim any trailing white space
+ line = UnownedStringSlice(line.begin(), line.trim().end());
+
+ auto lexer = sink->getSourceLocationLexer();
+ if (lexer)
+ {
+ UnownedStringSlice token = lexer(UnownedStringSlice(pos, line.end()));
+
+ if (token.getLength() > 1)
+ {
+ sb << "^+" << token.getLength() << "\n";
+ }
+ }
+}
static void formatDiagnostic(
DiagnosticSink* sink,
@@ -365,6 +410,7 @@ static void formatDiagnostic(
{
humaneLoc = sourceView->getHumaneLoc(sourceLoc);
}
+
formatDiagnostic(humaneLoc, diagnostic, sink->getFlags(), sb);
{
@@ -404,6 +450,12 @@ static void formatDiagnostic(
}
}
+ // If we are a language server, output additional token length info.
+ if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::LanguageServer))
+ {
+ _tokenLengthNoteDiagnostic(sink, sourceView, sourceLoc, sb);
+ }
+
// We don't don't output source line information if this is a 'note' as a note is extra information for one
// of the other main severity types, and so the information should already be output on the initial line
if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::SourceLocationLine) && diagnostic.severity != Severity::Note)