aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/reporting/diagnostic/Message.scala')
-rw-r--r--src/dotty/tools/dotc/reporting/diagnostic/Message.scala54
1 files changed, 40 insertions, 14 deletions
diff --git a/src/dotty/tools/dotc/reporting/diagnostic/Message.scala b/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
index 8b1f65673..8018a8777 100644
--- a/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
+++ b/src/dotty/tools/dotc/reporting/diagnostic/Message.scala
@@ -6,6 +6,8 @@ package diagnostic
import util.SourcePosition
import core.Contexts.Context
+import messages._
+
object Message {
/** This implicit conversion provides a fallback for error messages that have
* not yet been ported to the new scheme. Comment out this `implicit def` to
@@ -20,6 +22,13 @@ object Message {
* into a `MessageContainer` which contains the log level and can later be
* consumed by a subclass of `Reporter`.
*
+ * NOTE: you should not be persisting messages. Most messages take an implicit
+ * `Context` and these contexts weigh in at about 4mb per instance, as such
+ * persisting these will result in a memory leak.
+ *
+ * Instead use the `persist` method to create an instance that does not keep a
+ * reference to these contexts.
+ *
* @param errorId a unique number identifying the message, this will later be
* used to reference documentation online
*/
@@ -47,45 +56,62 @@ abstract class Message(val errorId: Int) { self =>
*/
def explanation: String
- /** It is possible to map `msg` to add details, this is at the loss of
- * precision since the type of the resulting `Message` won't be original
- * extending class
- *
- * @return a `Message` with the mapped message
+ /** The implicit `Context` in messages is a large thing that we don't want
+ * persisted. This method gets around that by duplicating the message
+ * without the implicit context being passed along.
*/
- def mapMsg(f: String => String) = new Message(errorId) {
- val msg = f(self.msg)
+ def persist: Message = new Message (errorId) {
+ val msg = self.msg
+ val kind = self.kind
+ val explanation = self.explanation
+ }
+}
+
+/** An extended message keeps the contained message from being evaluated, while
+ * allowing for extension for the `msg` string
+ *
+ * This is useful when we need to add additional information to an existing
+ * message.
+ */
+class ExtendMessage(_msg: () => Message)(f: String => String) { self =>
+ lazy val msg = f(_msg().msg)
+ lazy val kind = _msg().kind
+ lazy val explanation = _msg().explanation
+ lazy val errorId = _msg().errorId
+
+ private def toMessage = new Message(errorId) {
+ val msg = self.msg
val kind = self.kind
val explanation = self.explanation
}
/** Enclose this message in an `Error` container */
def error(pos: SourcePosition) =
- new Error(self, pos)
+ new Error(toMessage, pos)
/** Enclose this message in an `Warning` container */
def warning(pos: SourcePosition) =
- new Warning(self, pos)
+ new Warning(toMessage, pos)
/** Enclose this message in an `Info` container */
def info(pos: SourcePosition) =
- new Info(self, pos)
+ new Info(toMessage, pos)
/** Enclose this message in an `FeatureWarning` container */
def featureWarning(pos: SourcePosition) =
- new FeatureWarning(self, pos)
+ new FeatureWarning(toMessage, pos)
/** Enclose this message in an `UncheckedWarning` container */
def uncheckedWarning(pos: SourcePosition) =
- new UncheckedWarning(self, pos)
+ new UncheckedWarning(toMessage, pos)
/** Enclose this message in an `DeprecationWarning` container */
def deprecationWarning(pos: SourcePosition) =
- new DeprecationWarning(self, pos)
+ new DeprecationWarning(toMessage, pos)
/** Enclose this message in an `MigrationWarning` container */
def migrationWarning(pos: SourcePosition) =
- new MigrationWarning(self, pos)
+ new MigrationWarning(toMessage, pos)
}
/** The fallback `Message` containing no explanation and having no `kind` */