summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/common/Logger.cpp143
-rw-r--r--src/core/common/Logger.hpp61
-rw-r--r--src/core/common/SourceContextReader.cpp18
-rw-r--r--src/core/common/SourceContextReader.hpp20
-rw-r--r--src/core/frontend/Terminal.cpp (renamed from src/core/common/Terminal.cpp)20
-rw-r--r--src/core/frontend/Terminal.hpp (renamed from src/core/common/Terminal.hpp)14
-rw-r--r--src/core/frontend/TerminalLogger.cpp177
-rw-r--r--src/core/frontend/TerminalLogger.hpp79
-rw-r--r--src/core/resource/ResourceManager.cpp9
-rw-r--r--src/core/resource/ResourceManager.hpp20
10 files changed, 361 insertions, 200 deletions
diff --git a/src/core/common/Logger.cpp b/src/core/common/Logger.cpp
index aa61e6a..54156f2 100644
--- a/src/core/common/Logger.cpp
+++ b/src/core/common/Logger.cpp
@@ -20,8 +20,6 @@
#include <sstream>
#include "Logger.hpp"
-#include "Terminal.hpp"
-#include "Utils.hpp"
namespace ousia {
@@ -118,49 +116,49 @@ void LoggerFork::commit()
purge();
}
-/* Class ScopedLogger */
+/* Class GuardedLogger */
-ScopedLogger::ScopedLogger(Logger &parent, SourceLocation loc)
+GuardedLogger::GuardedLogger(Logger &parent, SourceLocation loc)
: parent(parent), depth(0)
{
pushDefaultLocation(loc);
}
-ScopedLogger::~ScopedLogger()
+GuardedLogger::~GuardedLogger()
{
while (depth > 0) {
popDefaultLocation();
}
}
-void ScopedLogger::processMessage(const Message &msg)
+void GuardedLogger::processMessage(const Message &msg)
{
parent.processMessage(msg);
}
-bool ScopedLogger::filterMessage(const Message &msg)
+bool GuardedLogger::filterMessage(const Message &msg)
{
return parent.filterMessage(msg);
}
-void ScopedLogger::processPushDefaultLocation(const SourceLocation &loc)
+void GuardedLogger::processPushDefaultLocation(const SourceLocation &loc)
{
parent.processPushDefaultLocation(loc);
depth++;
}
-void ScopedLogger::processPopDefaultLocation()
+void GuardedLogger::processPopDefaultLocation()
{
depth--;
parent.processPopDefaultLocation();
}
-void ScopedLogger::processSetDefaultLocation(const SourceLocation &loc)
+void GuardedLogger::processSetDefaultLocation(const SourceLocation &loc)
{
parent.processSetDefaultLocation(loc);
}
-void ScopedLogger::processSetSourceContextCallback(
+void GuardedLogger::processSetSourceContextCallback(
SourceContextCallback sourceContextCallback)
{
parent.processSetSourceContextCallback(sourceContextCallback);
@@ -265,128 +263,5 @@ bool ConcreteLogger::hasFatalError()
return getSeverityCount(Severity::FATAL_ERROR) > 0;
}
-/* Class TerminalLogger */
-
-void TerminalLogger::processMessage(const Message &msg)
-{
- Terminal t(useColor);
-
- // Fetch filename, position and context
- const SourceContext ctx = messageContext(msg);
-
- // Print the file name
- if (ctx.hasFile()) {
- os << t.bright() << ctx.filename << t.reset();
- }
-
- // Print line and column number
- if (ctx.hasLine()) {
- if (ctx.hasFile()) {
- os << ':';
- }
- os << t.bright() << ctx.startLine << t.reset();
- if (ctx.hasColumn()) {
- os << ':' << ctx.startColumn;
- }
- }
-
- // Print the optional seperator
- if (ctx.hasFile() || ctx.hasLine()) {
- os << ": ";
- }
-
- // Print the severity
- switch (msg.severity) {
- case Severity::DEBUG:
- break;
- case Severity::NOTE:
- os << t.color(Terminal::CYAN, true) << "note: ";
- break;
- case Severity::WARNING:
- os << t.color(Terminal::MAGENTA, true) << "warning: ";
- break;
- case Severity::ERROR:
- os << t.color(Terminal::RED, true) << "error: ";
- break;
- case Severity::FATAL_ERROR:
- os << t.color(Terminal::RED, true) << "fatal error: ";
- break;
- }
- os << t.reset();
-
- // Print the actual message
- os << msg.msg << std::endl;
-
- // Print the error message context if available
- if (ctx.hasText()) {
- // Iterate over each line in the text
- std::vector<std::string> lines = Utils::split(ctx.text, '\n');
-
- const size_t relLen = ctx.relLen ? ctx.relLen : 1;
- const size_t relPos = ctx.relPos;
- const size_t pstart = relPos;
- const size_t pend = relPos + relLen;
-
- size_t lstart = 0;
- size_t lend = 0;
- for (size_t n = 0; n < lines.size(); n++) {
- bool firstLine = n == 0;
- bool lastLine = n == lines.size() - 1;
-
- // Indicate truncation and indent non-first lines
- if (ctx.truncatedStart && firstLine) {
- os << "[...] ";
- }
- if (!firstLine) {
- os << "\t";
- }
-
- // Print the actual line
- os << lines[n];
-
- // Indicate truncation
- if (ctx.truncatedEnd && lastLine) {
- os << " [...]";
- }
- os << std::endl;
-
- // Repeat truncation or indendation space in the next line
- if (ctx.truncatedStart && firstLine) {
- os << " ";
- }
- if (!firstLine) {
- os << "\t";
- }
-
- // Print the position indicators
- lend = lastLine ? pend : lstart + lines[n].size();
- for (size_t i = lstart; i < lend; i++) {
- if (i >= pstart && i < pend) {
- os << t.color(Terminal::GREEN);
- for (; i < std::min(lend, pend); i++) {
- if (relLen == 1) {
- os << '^';
- } else {
- os << '~';
- }
- if (i < ctx.text.size() && ctx.text[i] == '\t') {
- os << '\t';
- }
- }
- os << t.reset();
- } else {
- if (i < ctx.text.size() && ctx.text[i] == '\t') {
- os << '\t';
- } else {
- os << ' ';
- }
- }
- }
- os << std::endl;
-
- lstart = lend;
- }
- }
-}
}
diff --git a/src/core/common/Logger.hpp b/src/core/common/Logger.hpp
index 85b1bb1..afe58be 100644
--- a/src/core/common/Logger.hpp
+++ b/src/core/common/Logger.hpp
@@ -19,9 +19,8 @@
/**
* @file Logger.hpp
*
- * Contains classes for logging messages in Ousía. Provides a generic Logger
- * class, and TerminalLogger, an extension of Logger which logs do an output
- * stream.
+ * Contains classes for logging messages in Ousía. Provides various base Logger
+ * classes that allow to Fork logger instances or to create a GuardedLogger.
*
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
*/
@@ -30,7 +29,6 @@
#define _OUSIA_LOGGER_HPP_
#include <cstdint>
-#include <ostream>
#include <string>
#include <vector>
@@ -109,7 +107,7 @@ inline MessageMode operator|(MessageMode a, MessageMode b)
// Forward declaration
class LoggerFork;
-class ScopedLogger;
+class GuardedLogger;
/**
* The Logger class is the base class the individual logging systems should
@@ -123,7 +121,7 @@ class ScopedLogger;
class Logger {
public:
friend LoggerFork;
- friend ScopedLogger;
+ friend GuardedLogger;
/**
* The message struct represents a single log message and all information
@@ -611,12 +609,12 @@ public:
};
/**
- * The ScopedLogger class can be used to automatically pop any pushed file from
+ * The GuardedLogger class can be used to automatically pop any pushed file from
* the File stack maintained by a Logger class (in a RAII manner). This
* simplifies managing pushing and popping files in case there are multiple
* return calls or exceptions thrown.
*/
-class ScopedLogger : public Logger {
+class GuardedLogger : public Logger {
private:
/**
* Reference to the parent logger instance.
@@ -668,20 +666,20 @@ protected:
public:
/**
- * Constructor of the ScopedLogger class, pushes a first file instance onto
+ * Constructor of the GuardedLogger class, pushes a first file instance onto
* the file stack.
*
* @param parent is the parent logger instance to which all calls should
* be relayed.
* @param loc specifies the first source location.
*/
- ScopedLogger(Logger &parent, SourceLocation loc = SourceLocation{});
+ GuardedLogger(Logger &parent, SourceLocation loc = SourceLocation{});
/**
- * Destructor of the ScopedLogger class, automatically unwinds the file
+ * Destructor of the GuardedLogger class, automatically unwinds the file
* stack.
*/
- ~ScopedLogger();
+ ~GuardedLogger();
};
/**
@@ -818,45 +816,6 @@ public:
bool hasFatalError();
};
-/**
- * Class extending the Logger class and printing the log messages to the
- * given
- * stream.
- */
-class TerminalLogger : public ConcreteLogger {
-private:
- /**
- * Reference to the target output stream.
- */
- std::ostream &os;
-
- /**
- * If true, the TerminalLogger will use colors to make the log messages
- * prettier.
- */
- bool useColor;
-
-protected:
- void processMessage(const Message &msg) override;
-
-public:
- /**
- * Constructor of the TerminalLogger class.
- *
- * @param os is the output stream the log messages should be logged to.
- * Should be set to std::cerr in most cases.
- * @param useColor if true, the TerminalLogger class will do its best to
- * use ANSI/VT100 control sequences for colored log messages.
- * @param minSeverity is the minimum severity below which log messages
- *are
- * discarded.
- */
- TerminalLogger(std::ostream &os, bool useColor = false,
- Severity minSeverity = DEFAULT_MIN_SEVERITY)
- : ConcreteLogger(minSeverity), os(os), useColor(useColor)
- {
- }
-};
}
#endif /* _OUSIA_LOGGER_HPP_ */
diff --git a/src/core/common/SourceContextReader.cpp b/src/core/common/SourceContextReader.cpp
index 65a6281..d5d379c 100644
--- a/src/core/common/SourceContextReader.cpp
+++ b/src/core/common/SourceContextReader.cpp
@@ -56,8 +56,8 @@ SourceContext SourceContextReader::readContext(CharReader &reader,
size_t offs = 0;
auto it = std::lower_bound(cache.begin(), cache.end(), start);
if (it != cache.begin()) {
- it--; // Go to the previous entry
- offs = *it; // Read the corresponding byte offset
+ it--; // Go to the previous entry
+ offs = *it; // Read the corresponding byte offset
size_t line = it - cache.begin() + 1;
ctx.startLine = line;
ctx.endLine = line;
@@ -182,17 +182,23 @@ SourceContext SourceContextReader::readContext(CharReader &reader,
}
// Update the relative position and length, set the "truncated" flags
- size_t us = static_cast<size_t>(s), ue = static_cast<size_t>(e);
- ctx.relPos = start - lineBufStart - us;
- ctx.relLen = std::min(ctx.relLen, ue - us);
+ ctx.relPos = std::max<ssize_t>(0, start - lineBufStart - s);
+ ctx.relLen = std::min<ssize_t>(ctx.relLen, e - s);
ctx.truncatedStart = s > ts || lastLineStart < lineBufStart;
ctx.truncatedEnd = e < te;
// Copy the selected area to the output string
- ctx.text = std::string{&lineBuf[s], ue - us};
+ ctx.text = std::string{&lineBuf[s], static_cast<size_t>(e - s)};
}
return ctx;
}
+
+SourceContext SourceContextReader::readContext(CharReader &reader,
+ const SourceRange &range,
+ const std::string &filename)
+{
+ return readContext(reader, range, MAX_MAX_CONTEXT_LENGTH, filename);
+}
}
diff --git a/src/core/common/SourceContextReader.hpp b/src/core/common/SourceContextReader.hpp
index 35e71b3..cd29880 100644
--- a/src/core/common/SourceContextReader.hpp
+++ b/src/core/common/SourceContextReader.hpp
@@ -82,7 +82,25 @@ public:
* @return a SourceContext instance describing the
*/
SourceContext readContext(CharReader &reader, const SourceRange &range,
- size_t maxContextLength = MAX_MAX_CONTEXT_LENGTH,
+ size_t maxContextLength,
+ const std::string &filename = "");
+
+ /**
+ * Returns the context for the char reader and the given SourceRange.
+ * Returns an invalid source context if either the given range is invalid
+ * or the byte offset described in the SourceRange cannot be reached because
+ * the CharReader cannot be seeked back to this position. Does not limit
+ * the output context.
+ *
+ * @param reader is the CharReader instance from which the context should be
+ * read.
+ * @param range describes the Range within the source file for which the
+ * context should be extraced.
+ * @param filename is the filename that should be stored in the returned
+ * context.
+ * @return a SourceContext instance describing the
+ */
+ SourceContext readContext(CharReader &reader, const SourceRange &range,
const std::string &filename = "");
};
}
diff --git a/src/core/common/Terminal.cpp b/src/core/frontend/Terminal.cpp
index 447e595..5664564 100644
--- a/src/core/common/Terminal.cpp
+++ b/src/core/frontend/Terminal.cpp
@@ -41,9 +41,23 @@ std::string Terminal::bright() const
if (!useColor) {
return std::string{};
}
- std::stringstream ss;
- ss << "\x1b[1m";
- return ss.str();
+ return "\x1b[1m";
+}
+
+std::string Terminal::italic() const
+{
+ if (!useColor) {
+ return std::string{};
+ }
+ return "\x1b[3m";
+}
+
+std::string Terminal::underline() const
+{
+ if (!useColor) {
+ return std::string{};
+ }
+ return "\x1b[4m";
}
std::string Terminal::reset() const
diff --git a/src/core/common/Terminal.hpp b/src/core/frontend/Terminal.hpp
index 730853d..90a2e6f 100644
--- a/src/core/common/Terminal.hpp
+++ b/src/core/frontend/Terminal.hpp
@@ -112,6 +112,20 @@ public:
std::string bright() const;
/**
+ * Makes the text italic.
+ *
+ * @return a control string to be included in the output stream.
+ */
+ std::string italic() const;
+
+ /**
+ * Underlines the text.
+ *
+ * @return a control string to be included in the output stream.
+ */
+ std::string underline() const;
+
+ /**
* Returns a control string for switching to the default mode.
*
* @return a control string to be included in the output stream.
diff --git a/src/core/frontend/TerminalLogger.cpp b/src/core/frontend/TerminalLogger.cpp
new file mode 100644
index 0000000..3bead06
--- /dev/null
+++ b/src/core/frontend/TerminalLogger.cpp
@@ -0,0 +1,177 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <core/common/Utils.hpp>
+
+#include "Terminal.hpp"
+#include "TerminalLogger.hpp"
+
+namespace ousia {
+
+/* Class TerminalLogger */
+
+void TerminalLogger::processMessage(const Message &msg)
+{
+ Terminal t(useColor);
+
+ // Fetch filename, position and context
+ const SourceContext ctx = messageContext(msg);
+
+ // Print the file name
+ if (ctx.hasFile()) {
+ os << t.bright() << ctx.filename << t.reset();
+ }
+
+ // Print line and column number
+ if (ctx.hasLine()) {
+ if (ctx.hasFile()) {
+ os << ':';
+ }
+ os << t.bright() << ctx.startLine << t.reset();
+ if (ctx.hasColumn()) {
+ os << ':' << ctx.startColumn;
+ }
+ }
+
+ // Print the optional seperator
+ if (ctx.hasFile() || ctx.hasLine()) {
+ os << ": ";
+ }
+
+ // Print the severity
+ switch (msg.severity) {
+ case Severity::DEBUG:
+ break;
+ case Severity::NOTE:
+ os << t.color(Terminal::CYAN, true) << "note: ";
+ break;
+ case Severity::WARNING:
+ os << t.color(Terminal::MAGENTA, true) << "warning: ";
+ break;
+ case Severity::ERROR:
+ os << t.color(Terminal::RED, true) << "error: ";
+ break;
+ case Severity::FATAL_ERROR:
+ os << t.color(Terminal::RED, true) << "fatal error: ";
+ break;
+ }
+ os << t.reset();
+
+ // Print the actual message
+ os << msg.msg << std::endl;
+
+ // Print the error message context if available
+ if (ctx.hasText()) {
+ // Iterate over each line in the text
+ std::vector<std::string> lines = Utils::split(ctx.text, '\n');
+
+ const size_t relLen = ctx.relLen ? ctx.relLen : 1;
+ const size_t relPos = ctx.relPos;
+ const size_t pstart = relPos;
+ const size_t pend = relPos + relLen;
+
+ size_t lstart = 0;
+ size_t lend = 0;
+ for (size_t n = 0; n < lines.size(); n++) {
+ bool firstLine = n == 0;
+ bool lastLine = n == lines.size() - 1;
+
+ // Indicate truncation and indent non-first lines
+ if (ctx.truncatedStart && firstLine) {
+ os << t.italic() << "[...] " << t.reset();
+ }
+ if (!firstLine) {
+ os << "\t";
+ }
+
+ // Print the actual line, replace tabs
+ for (char c: lines[n]) {
+ if (c == '\t') {
+ os << " ";
+ } else {
+ os << c;
+ }
+ }
+ if (!lastLine) {
+ os << t.color(Terminal::BLACK) << "¶" << t.reset();
+ }
+
+ // Indicate truncation
+ if (ctx.truncatedEnd && lastLine) {
+ os << t.italic() << " [...]" << t.reset();
+ }
+ os << std::endl;
+
+ // Repeat truncation or indendation space in the next line
+ if (ctx.truncatedStart && firstLine) {
+ os << " ";
+ }
+ if (!firstLine) {
+ os << "\t";
+ }
+
+ // Print the position indicators
+ lend = lastLine ? pend : lstart + lines[n].size();
+ bool inRegion = false;
+ for (size_t i = lstart; i < lend + 1; i++) {
+ if (i >= pstart && i < pend) {
+ if (!inRegion) {
+ os << t.color(Terminal::GREEN);
+ inRegion = true;
+ }
+ } else {
+ if (inRegion) {
+ os << t.reset();
+ inRegion = false;
+ }
+ }
+ char c = i < ctx.text.size() ? ctx.text[i] : ' ';
+ if (c == '\t') {
+ if (inRegion) {
+ if (relLen == 1) {
+ os << "^ ";
+ } else {
+ os << "~~~~";
+ }
+ } else {
+ os << " ";
+ }
+ } else {
+ if (inRegion) {
+ if (relLen == 1) {
+ os << "^";
+ } else {
+ os << "~";
+ }
+ } else {
+ os << " ";
+ }
+ }
+ }
+ if (inRegion) {
+ os << t.reset();
+ }
+ os << std::endl;
+
+ lstart = lend + 1; // skip newline
+ }
+ }
+}
+
+}
+
diff --git a/src/core/frontend/TerminalLogger.hpp b/src/core/frontend/TerminalLogger.hpp
new file mode 100644
index 0000000..03930e9
--- /dev/null
+++ b/src/core/frontend/TerminalLogger.hpp
@@ -0,0 +1,79 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file TerminalLogger.hpp
+ *
+ * Provides the TerminalLogger class, which is used to log messages to an output
+ * stream, possibly a Terminal.
+ *
+ * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
+ */
+
+#ifndef _OUSIA_TERMINAL_LOGGER_HPP_
+#define _OUSIA_TERMINAL_LOGGER_HPP_
+
+#include <ostream>
+
+#include <core/common/Logger.hpp>
+
+namespace ousia {
+
+/**
+ * Class extending the Logger class and printing (possibly colored) log messages
+ * to the given stream.
+ */
+class TerminalLogger : public ConcreteLogger {
+private:
+ /**
+ * Reference to the target output stream.
+ */
+ std::ostream &os;
+
+ /**
+ * If true, the TerminalLogger will use colors to make the log messages
+ * prettier.
+ */
+ bool useColor;
+
+protected:
+ void processMessage(const Message &msg) override;
+
+public:
+ /**
+ * Constructor of the TerminalLogger class.
+ *
+ * @param os is the output stream the log messages should be logged to.
+ * Should be set to std::cerr in most cases.
+ * @param useColor if true, the TerminalLogger class will do its best to
+ * use ANSI/VT100 control sequences for colored log messages.
+ * @param minSeverity is the minimum severity below which log messages
+ * are discarded.
+ */
+ TerminalLogger(std::ostream &os, bool useColor = false,
+ Severity minSeverity = DEFAULT_MIN_SEVERITY)
+ : ConcreteLogger(minSeverity), os(os), useColor(useColor)
+ {
+ }
+};
+
+}
+
+#endif /* _OUSIA_TERMINAL_LOGGER_HPP_ */
+
+
diff --git a/src/core/resource/ResourceManager.cpp b/src/core/resource/ResourceManager.cpp
index a5e76b0..184a16d 100644
--- a/src/core/resource/ResourceManager.cpp
+++ b/src/core/resource/ResourceManager.cpp
@@ -22,6 +22,7 @@
#include <core/common/Exceptions.hpp>
#include <core/common/Logger.hpp>
#include <core/common/Rtti.hpp>
+#include <core/common/SourceContextReader.hpp>
#include <core/common/Utils.hpp>
#include <core/model/Node.hpp>
#include <core/parser/ParserContext.hpp>
@@ -128,7 +129,7 @@ Rooted<Node> ResourceManager::parse(ParserContext &ctx, Resource &resource,
Rooted<Node> node;
try {
// Set the current source id in the logger instance
- ScopedLogger logger(ctx.logger, SourceLocation{sourceId});
+ GuardedLogger logger(ctx.logger, SourceLocation{sourceId});
// Fetch the input stream and create a char reader
std::unique_ptr<std::istream> is = resource.stream();
@@ -280,5 +281,11 @@ SourceContext ResourceManager::readContext(const SourceLocation &location,
}
return SourceContext{};
}
+
+SourceContext ResourceManager::readContext(const SourceLocation &location)
+{
+ return readContext(location, SourceContextReader::MAX_MAX_CONTEXT_LENGTH);
+}
+
}
diff --git a/src/core/resource/ResourceManager.hpp b/src/core/resource/ResourceManager.hpp
index d5381b9..221e2cc 100644
--- a/src/core/resource/ResourceManager.hpp
+++ b/src/core/resource/ResourceManager.hpp
@@ -34,7 +34,6 @@
#include <core/common/Location.hpp>
#include <core/common/Rtti.hpp>
-#include <core/common/SourceContextReader.hpp>
#include <core/managed/Managed.hpp>
#include "Resource.hpp"
@@ -230,9 +229,22 @@ public:
* @return a valid SourceContext if a valid SourceLocation was given or an
* invalid SourceContext if the location is invalid.
*/
- SourceContext readContext(
- const SourceLocation &location,
- size_t maxContextLength = SourceContextReader::MAX_MAX_CONTEXT_LENGTH);
+ SourceContext readContext(const SourceLocation &location,
+ size_t maxContextLength);
+ /**
+ * Creates and returns a SourceContext structure containing information
+ * about the given SourceLocation (such as line and column number). Throws
+ * a LoggableException if an irrecoverable error occurs while looking up the
+ * context (such as a no longer existing resource). Does not limit the
+ * context length.
+ *
+ * @param location is the SourceLocation for which context information
+ * should be retrieved. This method is used by the Logger class to print
+ * pretty messages.
+ * @return a valid SourceContext if a valid SourceLocation was given or an
+ * invalid SourceContext if the location is invalid.
+ */
+ SourceContext readContext(const SourceLocation &location);
};
}