diff options
| author | jsmall-nvidia <jsmall@nvidia.com> | 2021-05-19 17:53:24 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-05-19 14:53:24 -0700 |
| commit | c4c90f5a6da45229405533372215ba40de91df37 (patch) | |
| tree | b9fdf847656199c5f9b34f081d37ff7f466b7a6d /source/compiler-core/slang-diagnostic-sink.cpp | |
| parent | 61e9154cb797cffe19cfbf3205b4a5a614e8b552 (diff) | |
SourceLoc use in command line processing (#1848)
* #include an absolute path didn't work - because paths were taken to always be relative.
* Added SourceLoc handling for command line parsing.
* Fix typo in debug.
* Fix issue around the DiagnosticSink used in options parsing not having a writer available - by having DiagnosticSink parenting.
* Small rename for clarity.
Co-authored-by: T. Foley <tfoleyNV@users.noreply.github.com>
Diffstat (limited to 'source/compiler-core/slang-diagnostic-sink.cpp')
| -rw-r--r-- | source/compiler-core/slang-diagnostic-sink.cpp | 161 |
1 files changed, 127 insertions, 34 deletions
diff --git a/source/compiler-core/slang-diagnostic-sink.cpp b/source/compiler-core/slang-diagnostic-sink.cpp index 727c322a5..0ad16b2b4 100644 --- a/source/compiler-core/slang-diagnostic-sink.cpp +++ b/source/compiler-core/slang-diagnostic-sink.cpp @@ -131,12 +131,15 @@ static void formatDiagnosticMessage(StringBuilder& sb, char const* format, int a } } -static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& diagnostic, StringBuilder& outBuilder) +static void formatDiagnostic(const HumaneSourceLoc& humaneLoc, Diagnostic const& diagnostic, DiagnosticSink::Flags flags, StringBuilder& outBuilder) { - outBuilder << humaneLoc.pathInfo.foundPath; - outBuilder << "("; - outBuilder << Int32(humaneLoc.line); - outBuilder << "): "; + if (flags & DiagnosticSink::Flag::HumaneLoc) + { + outBuilder << humaneLoc.pathInfo.foundPath; + outBuilder << "("; + outBuilder << Int32(humaneLoc.line); + outBuilder << "): "; + } outBuilder << getSeverityName(diagnostic.severity); @@ -236,7 +239,15 @@ static UnownedStringSlice _extractLineContainingPosition(const UnownedStringSlic return UnownedStringSlice(start, end); } -static void _sourceLocationNoteDiagnostic(SourceView* sourceView, SourceLoc sourceLoc, DiagnosticSink::SourceLocationLexer lexer, StringBuilder& sb) +static void _reduceLength(Index startIndex, StringBuilder& ioBuf) +{ + StringBuilder buf; + buf << "..."; + buf.append(ioBuf.getUnownedSlice().tail(startIndex)); + ioBuf = buf; +} + +static void _sourceLocationNoteDiagnostic(DiagnosticSink* sink, SourceView* sourceView, SourceLoc sourceLoc, StringBuilder& sb) { SourceFile* sourceFile = sourceView->getSourceFile(); if (!sourceFile) @@ -266,7 +277,7 @@ static void _sourceLocationNoteDiagnostic(SourceView* sourceView, SourceLoc sour // TODO(JS): The tab size should ideally be configurable from command line. // For now just go with 4. const Index tabSize = 4; - + StringBuilder sourceLine; StringBuilder caretLine; @@ -282,10 +293,13 @@ static void _sourceLocationNoteDiagnostic(SourceView* sourceView, SourceLoc sour const Index length = caretLine.getLength(); caretLine.Clear(); caretLine.appendRepeatedChar(' ', length); - + + Index caretIndex = caretLine.getLength(); + // Add caret caretLine << "^"; + auto lexer = sink->getSourceLocationLexer(); if (lexer) { UnownedStringSlice token = lexer(UnownedStringSlice(pos, line.end())); @@ -295,6 +309,28 @@ static void _sourceLocationNoteDiagnostic(SourceView* sourceView, SourceLoc sour caretLine.appendRepeatedChar('~', token.getLength() - 1); } } + + const Index maxLength = sink->getSourceLineMaxLength(); + if (maxLength > 0) + { + Index endIndex = lexer ? caretLine.getLength() : (caretIndex + (maxLength / 4)); + + if (endIndex > maxLength) + { + Index startIndex = endIndex - (maxLength - 3); + + _reduceLength(startIndex, sourceLine); + _reduceLength(startIndex, caretLine); + } + + if (sourceLine.getLength() > maxLength) + { + StringBuilder buf; + buf.append(sourceLine.getUnownedSlice().head(maxLength - 3)); + buf << "..."; + sourceLine = buf; + } + } } // We could have handling here for if the line is too long, that we surround the important section @@ -322,7 +358,7 @@ static void formatDiagnostic( { humaneLoc = sourceView->getHumaneLoc(sourceLoc); } - formatDiagnostic(humaneLoc, diagnostic, sb); + formatDiagnostic(humaneLoc, diagnostic, sink->getFlags(), sb); { SourceView* currentView = sourceView; @@ -353,7 +389,7 @@ static void formatDiagnostic( HumaneSourceLoc pasteHumaneLoc = initiatingView->getHumaneLoc(sourceView->getInitiatingSourceLoc()); // Okay we should output where the token paste took place - formatDiagnostic(pasteHumaneLoc, initiationDiagnostic, sb); + formatDiagnostic(pasteHumaneLoc, initiationDiagnostic, sink->getFlags(), sb); // Make the initiatingView the current view currentView = initiatingView; @@ -365,7 +401,7 @@ static void formatDiagnostic( // 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) { - _sourceLocationNoteDiagnostic(sourceView, sourceLoc, sink->getSourceLocationLexer(), sb); + _sourceLocationNoteDiagnostic(sink, sourceView, sourceLoc, sb); } if (sourceView && sink->isFlagSet(DiagnosticSink::Flag::VerbosePath)) @@ -380,7 +416,7 @@ static void formatDiagnostic( actualHumaneLoc.line != humaneLoc.line || actualHumaneLoc.column != humaneLoc.column) { - formatDiagnostic(actualHumaneLoc, diagnostic, sb); + formatDiagnostic(actualHumaneLoc, diagnostic, sink->getFlags(), sb); } } } @@ -390,10 +426,11 @@ void DiagnosticSink::init(SourceManager* sourceManager, SourceLocationLexer sour m_errorCount = 0; m_internalErrorLocsNoted = 0; - m_flags = 0; - m_sourceManager = sourceManager; m_sourceLocationLexer = sourceLocationLexer; + m_sourceLineMaxLength = 0; + + m_flags = Flag::HumaneLoc; // If we have a source location lexer, we'll by default enable source location output if (sourceLocationLexer) @@ -402,45 +439,96 @@ void DiagnosticSink::init(SourceManager* sourceManager, SourceLocationLexer sour } } -void DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo const& info, int argCount, DiagnosticArg const* const* args) +void DiagnosticSink::noteInternalErrorLoc(SourceLoc const& loc) { - StringBuilder sb; - formatDiagnosticMessage(sb, info.messageFormat, argCount, args); + // Don't consider invalid source locations. + if (!loc.isValid()) + return; - Diagnostic diagnostic; - diagnostic.ErrorID = info.id; - diagnostic.Message = sb.ProduceString(); - diagnostic.loc = pos; - diagnostic.severity = info.severity; + if (m_parentSink) + { + m_parentSink->noteInternalErrorLoc(loc); + } - if (diagnostic.severity >= Severity::Error) + // If this is the first source location being noted, + // then emit a message to help the user isolate what + // code might have confused the compiler. + if (m_internalErrorLocsNoted == 0) { - m_errorCount++; + diagnose(loc, MiscDiagnostics::noteLocationOfInternalError); } + m_internalErrorLocsNoted++; +} - // Did the client supply a callback for us to use? - if( writer ) +SlangResult DiagnosticSink::getBlobIfNeeded(ISlangBlob** outBlob) +{ + // If the client doesn't want an output blob, there is nothing to do. + // + if (!outBlob) return SLANG_OK; + + // For outputBuffer to be valid and hold diagnostics, writer must not be set + SLANG_ASSERT(writer == nullptr); + + // If there were no errors, and there was no diagnostic output, there is nothing to do. + if (getErrorCount() == 0 && outputBuffer.getLength() == 0) { - // If so, pass the error string along to them - StringBuilder messageBuilder; - formatDiagnostic(this, diagnostic, messageBuilder); + return SLANG_OK; + } + + Slang::ComPtr<ISlangBlob> blob = Slang::StringUtil::createStringBlob(outputBuffer); + *outBlob = blob.detach(); + + return SLANG_OK; +} + +void DiagnosticSink::diagnoseImpl(DiagnosticInfo const& info, const UnownedStringSlice& formattedMessage) +{ + if (info.severity >= Severity::Error) + { + m_errorCount++; + } - writer->write(messageBuilder.getBuffer(), messageBuilder.getLength()); + if (writer) + { + writer->write(formattedMessage.begin(), formattedMessage.getLength()); } else { - // If the user doesn't have a callback, then just - // collect our diagnostic messages into a buffer - formatDiagnostic(this, diagnostic, outputBuffer); + outputBuffer.append(formattedMessage); } - if (diagnostic.severity >= Severity::Fatal) + if (m_parentSink) + { + m_parentSink->diagnoseImpl(info, formattedMessage); + } + + if (info.severity >= Severity::Fatal) { // TODO: figure out a better policy for aborting compilation throw AbortCompilationException(); } } +void DiagnosticSink::diagnoseImpl(SourceLoc const& pos, DiagnosticInfo const& info, int argCount, DiagnosticArg const* const* args) +{ + StringBuilder messageBuilder; + { + StringBuilder sb; + formatDiagnosticMessage(sb, info.messageFormat, argCount, args); + + Diagnostic diagnostic; + diagnostic.ErrorID = info.id; + diagnostic.Message = sb.ProduceString(); + diagnostic.loc = pos; + diagnostic.severity = info.severity; + + // If so, pass the error string along to them + formatDiagnostic(this, diagnostic, messageBuilder); + } + + diagnoseImpl(info, messageBuilder.getUnownedSlice()); +} + void DiagnosticSink::diagnoseRaw( Severity severity, char const* message) @@ -470,6 +558,11 @@ void DiagnosticSink::diagnoseRaw( outputBuffer.append(message); } + if (m_parentSink) + { + m_parentSink->diagnoseRaw(severity, message); + } + if (severity >= Severity::Fatal) { // TODO: figure out a better policy for aborting compilation |
