From 0c64995ea28febcc7d38e1519da8d93391ce2e7d Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 7 Jun 2022 14:10:49 -0700 Subject: Major language server features. (#2264) * Major language server features. * Include slangd in binary release. * Fix compiler issues. * Fix compiler error. * Completion resolve. * Various improvements. * Update diagnostic test expected output. * Bug fix for source locations. * Adjust diagnostic update frequency. * Update github actions to store artifacts. * Fix infinite parser loop. * Fix parser recovery. * Fix parser recovery. * Update test. * Fix test. * Disable IR gen for language server. * Allow commit characters in auto completion. * Fix lookup for invoke exprs. * More parser robustness fixes. * update solution file Co-authored-by: Yong He --- source/compiler-core/slang-diagnostic-sink.cpp | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'source/compiler-core/slang-diagnostic-sink.cpp') 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) -- cgit v1.2.3