From 81a1317e53eb4c9845d5c185b2f64e1e2ab4388d Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Wed, 1 Aug 2018 00:16:15 -0400 Subject: [PATCH 1/8] 1.2.1-SNAPSHOT --- build.sbt | 5 +++-- project/build.properties | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index f9726ff0c..1896a4191 100644 --- a/build.sbt +++ b/build.sbt @@ -32,7 +32,8 @@ def commonSettings: Seq[Setting[_]] = Seq( val mimaSettings = Def settings ( mimaPreviousArtifacts := Set( "1.0.0", "1.0.1", "1.0.2", "1.0.3", - "1.1.0", "1.1.1", "1.1.2", "1.1.3" + "1.1.0", "1.1.1", "1.1.2", "1.1.3", + "1.2.0", ) map (version => organization.value %% moduleName.value % version cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) @@ -53,7 +54,7 @@ lazy val utilRoot: Project = (project in file(".")) .settings( inThisBuild( Seq( - git.baseVersion := "1.2.0", + git.baseVersion := "1.2.1", version := { val v = version.value if (v contains "SNAPSHOT") git.baseVersion.value + "-SNAPSHOT" diff --git a/project/build.properties b/project/build.properties index d6e35076c..f59579fd6 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.1.6 +sbt.version=1.2.0 From f457696a999667b162e85e3d373549b13893120a Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 13 Aug 2018 01:03:08 +0900 Subject: [PATCH 2/8] Upgrade to sbt 1.2.1 --- project/build.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/build.properties b/project/build.properties index f59579fd6..5620cc502 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.2.0 +sbt.version=1.2.1 From 78834527dffb89408142047d9a3a8bb5b56caa95 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Mon, 13 Aug 2018 01:03:22 +0900 Subject: [PATCH 3/8] xsbti.Position: add startOffset and endOffset A position now has a start, an end, and a point (the existing `offset`), just like it does in the Scala compiler. This information is especially useful for displaying squiggly lines in an IDE. This commit and the next one are required for https://github.com/sbt/zinc/pull/571 --- build.sbt | 2 ++ .../src/main/java/xsbti/Position.java | 4 +++ .../main/scala/sbt/util/InterfaceUtil.scala | 30 +++++++++++++++++-- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 1896a4191..7a2d78ce6 100644 --- a/build.sbt +++ b/build.sbt @@ -124,6 +124,8 @@ lazy val utilLogging = (project in internalPath / "util-logging") exclude[DirectMissingMethodProblem]("sbt.internal.util.SuccessEvent.copy*"), exclude[DirectMissingMethodProblem]("sbt.internal.util.TraceEvent.copy*"), exclude[DirectMissingMethodProblem]("sbt.internal.util.StringEvent.copy*"), + // Private final class constructor changed + exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcretePosition.this"), ), ) .configure(addSbtIO) diff --git a/internal/util-interface/src/main/java/xsbti/Position.java b/internal/util-interface/src/main/java/xsbti/Position.java index be0239046..0f27e295e 100644 --- a/internal/util-interface/src/main/java/xsbti/Position.java +++ b/internal/util-interface/src/main/java/xsbti/Position.java @@ -18,4 +18,8 @@ public interface Position Optional sourcePath(); Optional sourceFile(); + + // Default values to avoid breaking binary compatibility + default Optional startOffset() { return Optional.empty(); } + default Optional endOffset() { return Optional.empty(); } } diff --git a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala index dc956ecbf..a2d705600 100644 --- a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala +++ b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala @@ -36,6 +36,7 @@ object InterfaceUtil { case None => Optional.empty[A]() } + // Overload to preserve binary compatibility def position( line0: Option[Integer], content: String, @@ -45,7 +46,28 @@ object InterfaceUtil { sourcePath0: Option[String], sourceFile0: Option[File] ): Position = - new ConcretePosition(line0, content, offset0, pointer0, pointerSpace0, sourcePath0, sourceFile0) + position(line0, content, offset0, pointer0, pointerSpace0, sourcePath0, sourceFile0, None, None) + + def position( + line0: Option[Integer], + content: String, + offset0: Option[Integer], + pointer0: Option[Integer], + pointerSpace0: Option[String], + sourcePath0: Option[String], + sourceFile0: Option[File], + startOffset0: Option[Integer], + endOffset0: Option[Integer] + ): Position = + new ConcretePosition(line0, + content, + offset0, + pointer0, + pointerSpace0, + sourcePath0, + sourceFile0, + startOffset0, + endOffset0) def problem(cat: String, pos: Position, msg: String, sev: Severity): Problem = new ConcreteProblem(cat, pos, msg, sev) @@ -75,7 +97,9 @@ object InterfaceUtil { pointer0: Option[Integer], pointerSpace0: Option[String], sourcePath0: Option[String], - sourceFile0: Option[File] + sourceFile0: Option[File], + startOffset0: Option[Integer], + endOffset0: Option[Integer] ) extends Position { val line = o2jo(line0) val lineContent = content @@ -84,6 +108,8 @@ object InterfaceUtil { val pointerSpace = o2jo(pointerSpace0) val sourcePath = o2jo(sourcePath0) val sourceFile = o2jo(sourceFile0) + override val startOffset = o2jo(startOffset0) + override val endOffset = o2jo(endOffset0) } private final class ConcreteProblem( From 5e3a102606a034dd6b4c4ac4b5ebed6028850f1d Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 14 Aug 2018 02:00:41 +0900 Subject: [PATCH 4/8] xsbti.Position: Also add {start,end}{Line,Column} Positions in the Language Server Protocol and Build Server Protocol are line/column-based instead of offset-based, so this is more convenient. Computing the line/column from the offset is possible but requires reading the source file. --- .../src/main/java/xsbti/Position.java | 4 ++++ .../main/scala/sbt/util/InterfaceUtil.scala | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/internal/util-interface/src/main/java/xsbti/Position.java b/internal/util-interface/src/main/java/xsbti/Position.java index 0f27e295e..c23c53b22 100644 --- a/internal/util-interface/src/main/java/xsbti/Position.java +++ b/internal/util-interface/src/main/java/xsbti/Position.java @@ -22,4 +22,8 @@ public interface Position // Default values to avoid breaking binary compatibility default Optional startOffset() { return Optional.empty(); } default Optional endOffset() { return Optional.empty(); } + default Optional startLine() { return Optional.empty(); } + default Optional startColumn() { return Optional.empty(); } + default Optional endLine() { return Optional.empty(); } + default Optional endColumn() { return Optional.empty(); } } diff --git a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala index a2d705600..b11a3e54c 100644 --- a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala +++ b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala @@ -46,7 +46,7 @@ object InterfaceUtil { sourcePath0: Option[String], sourceFile0: Option[File] ): Position = - position(line0, content, offset0, pointer0, pointerSpace0, sourcePath0, sourceFile0, None, None) + position(line0, content, offset0, pointer0, pointerSpace0, sourcePath0, sourceFile0, None, None, None, None, None, None) def position( line0: Option[Integer], @@ -57,7 +57,11 @@ object InterfaceUtil { sourcePath0: Option[String], sourceFile0: Option[File], startOffset0: Option[Integer], - endOffset0: Option[Integer] + endOffset0: Option[Integer], + startLine0: Option[Integer], + startColumn0: Option[Integer], + endLine0: Option[Integer], + endColumn0: Option[Integer] ): Position = new ConcretePosition(line0, content, @@ -67,7 +71,11 @@ object InterfaceUtil { sourcePath0, sourceFile0, startOffset0, - endOffset0) + endOffset0, + startLine0, + startColumn0, + endLine0, + endColumn0) def problem(cat: String, pos: Position, msg: String, sev: Severity): Problem = new ConcreteProblem(cat, pos, msg, sev) @@ -99,7 +107,11 @@ object InterfaceUtil { sourcePath0: Option[String], sourceFile0: Option[File], startOffset0: Option[Integer], - endOffset0: Option[Integer] + endOffset0: Option[Integer], + startLine0: Option[Integer], + startColumn0: Option[Integer], + endLine0: Option[Integer], + endColumn0: Option[Integer] ) extends Position { val line = o2jo(line0) val lineContent = content @@ -110,6 +122,10 @@ object InterfaceUtil { val sourceFile = o2jo(sourceFile0) override val startOffset = o2jo(startOffset0) override val endOffset = o2jo(endOffset0) + override val startLine = o2jo(startLine0) + override val startColumn = o2jo(startColumn0) + override val endLine = o2jo(endLine0) + override val endColumn = o2jo(endColumn0) } private final class ConcreteProblem( From 494f384c49ac4fa49b907dfde64048af9a400986 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Thu, 16 Aug 2018 16:36:41 -0400 Subject: [PATCH 5/8] Formatting --- .../src/main/scala/sbt/util/InterfaceUtil.scala | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala index b11a3e54c..5a85c9b67 100644 --- a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala +++ b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala @@ -46,7 +46,19 @@ object InterfaceUtil { sourcePath0: Option[String], sourceFile0: Option[File] ): Position = - position(line0, content, offset0, pointer0, pointerSpace0, sourcePath0, sourceFile0, None, None, None, None, None, None) + position(line0, + content, + offset0, + pointer0, + pointerSpace0, + sourcePath0, + sourceFile0, + None, + None, + None, + None, + None, + None) def position( line0: Option[Integer], From a90675635fb0c2c51870bc066686e8afb49d0606 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 28 Aug 2018 01:18:00 +0900 Subject: [PATCH 6/8] 1.2.2-SNAPSHOT --- build.sbt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 7a2d78ce6..e8f39ffea 100644 --- a/build.sbt +++ b/build.sbt @@ -33,7 +33,7 @@ val mimaSettings = Def settings ( mimaPreviousArtifacts := Set( "1.0.0", "1.0.1", "1.0.2", "1.0.3", "1.1.0", "1.1.1", "1.1.2", "1.1.3", - "1.2.0", + "1.2.0", "1.2.1" ) map (version => organization.value %% moduleName.value % version cross (if (crossPaths.value) CrossVersion.binary else CrossVersion.disabled) @@ -54,7 +54,7 @@ lazy val utilRoot: Project = (project in file(".")) .settings( inThisBuild( Seq( - git.baseVersion := "1.2.1", + git.baseVersion := "1.2.2", version := { val v = version.value if (v contains "SNAPSHOT") git.baseVersion.value + "-SNAPSHOT" From e905b44a3353e351f48e19b92af2416629ef5b64 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 28 Aug 2018 01:14:24 +0900 Subject: [PATCH 7/8] Follow-up to the fields added in #173 It turns out that there is more boilerplate to fill that I missed. Also add deprecation notices. --- .../src/main/contraband/interface.contra.txt | 6 ++++++ .../internal/util/codec/PositionFormats.scala | 21 +++++++++++++++++++ .../main/scala/sbt/util/InterfaceUtil.scala | 2 +- .../src/main/scala/sbt/util/Logger.scala | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/internal/util-logging/src/main/contraband/interface.contra.txt b/internal/util-logging/src/main/contraband/interface.contra.txt index 795e6a4c3..a42eb09cb 100644 --- a/internal/util-logging/src/main/contraband/interface.contra.txt +++ b/internal/util-logging/src/main/contraband/interface.contra.txt @@ -16,6 +16,12 @@ type Position { pointerSpace: String sourcePath: String sourceFile: java.io.File + startOffset: Int + endOffset: Int + startLine: Int + startColumn: Int + endLine: Int + endColumn: Int } type Problem { diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/codec/PositionFormats.scala b/internal/util-logging/src/main/scala/sbt/internal/util/codec/PositionFormats.scala index e43ff03bf..7fe9fd6ce 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/codec/PositionFormats.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/codec/PositionFormats.scala @@ -19,6 +19,13 @@ trait PositionFormats { self: sjsonnew.BasicJsonProtocol => val pointerSpace0 = unbuilder.readField[Optional[String]]("pointerSpace") val sourcePath0 = unbuilder.readField[Optional[String]]("sourcePath") val sourceFile0 = unbuilder.readField[Optional[java.io.File]]("sourceFile") + val startOffset0 = unbuilder.readField[Optional[java.lang.Integer]]("startOffset") + val endOffset0 = unbuilder.readField[Optional[java.lang.Integer]]("endOffset") + val startLine0 = unbuilder.readField[Optional[java.lang.Integer]]("startLine") + val startColumn0 = unbuilder.readField[Optional[java.lang.Integer]]("startColumn") + val endLine0 = unbuilder.readField[Optional[java.lang.Integer]]("endLine") + val endColumn0 = unbuilder.readField[Optional[java.lang.Integer]]("endColumn") + unbuilder.endObject() new Position() { override val line = line0 @@ -28,6 +35,13 @@ trait PositionFormats { self: sjsonnew.BasicJsonProtocol => override val pointerSpace = pointerSpace0 override val sourcePath = sourcePath0 override val sourceFile = sourceFile0 + override val startOffset = startOffset0 + override val endOffset = endOffset0 + override val startLine = startLine0 + override val startColumn = startColumn0 + override val endLine = endLine0 + override val endColumn = endColumn0 + } case None => deserializationError("Expected JsObject but found None") @@ -42,6 +56,13 @@ trait PositionFormats { self: sjsonnew.BasicJsonProtocol => builder.addField("pointerSpace", obj.pointerSpace) builder.addField("sourcePath", obj.sourcePath) builder.addField("sourceFile", obj.sourceFile) + builder.addField("startOffset", obj.startOffset) + builder.addField("endOffset", obj.endOffset) + builder.addField("startLine", obj.startLine) + builder.addField("startColumn", obj.startColumn) + builder.addField("endLine", obj.endLine) + builder.addField("endColumn", obj.endColumn) + builder.endObject() } } diff --git a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala index 5a85c9b67..a1ae332d8 100644 --- a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala +++ b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala @@ -36,7 +36,7 @@ object InterfaceUtil { case None => Optional.empty[A]() } - // Overload to preserve binary compatibility + @deprecated("Use the overload of this method with more arguments", "1.2.2") def position( line0: Option[Integer], content: String, diff --git a/internal/util-logging/src/main/scala/sbt/util/Logger.scala b/internal/util-logging/src/main/scala/sbt/util/Logger.scala index 75d7a439d..37a043cfa 100644 --- a/internal/util-logging/src/main/scala/sbt/util/Logger.scala +++ b/internal/util-logging/src/main/scala/sbt/util/Logger.scala @@ -97,6 +97,7 @@ object Logger { def jo2o[A](o: Optional[A]): Option[A] = InterfaceUtil.jo2o(o) def o2jo[A](o: Option[A]): Optional[A] = InterfaceUtil.o2jo(o) + @deprecated("Use InterfaceUtil.position", "1.2.2") def position( line0: Option[Integer], content: String, From 15522a0cbe1c0c89fa36c699f0442a3703deb4aa Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Tue, 28 Aug 2018 02:03:47 +0900 Subject: [PATCH 8/8] Add Problem#rendered to customize how problems are shown Dotty has its own logic for displaying problems with the proper file path, position, and caret, but if we store this information in Problem#message we end up with duplicated information in the output since Zinc will prepend/append similar things (see sbt.internal.inc.ProblemStringFormats). So far, we worked around this in Dotty by using an empty position in the sbt bridge reporter, but this means that crucial semantic information that could be used by a Build Server Protocol implementation and other tools is lost. This commit allows us to avoid by adding an optional `rendered` field to `Problem`: when this field is set, its value controls what the user sees, otherwise we fallback to the default behavior (the logic to do this will be added to Zinc after this PR is merged and a new release of sbt-util is made). --- build.sbt | 3 ++- .../src/main/java/xsbti/Problem.java | 12 ++++++++++- .../src/main/contraband/interface.contra.txt | 1 + .../internal/util/codec/ProblemFormats.scala | 21 +++++++++++++------ .../main/scala/sbt/util/InterfaceUtil.scala | 14 +++++++++++-- .../src/main/scala/sbt/util/Logger.scala | 1 + 6 files changed, 42 insertions(+), 10 deletions(-) diff --git a/build.sbt b/build.sbt index e8f39ffea..9a07324dd 100644 --- a/build.sbt +++ b/build.sbt @@ -124,8 +124,9 @@ lazy val utilLogging = (project in internalPath / "util-logging") exclude[DirectMissingMethodProblem]("sbt.internal.util.SuccessEvent.copy*"), exclude[DirectMissingMethodProblem]("sbt.internal.util.TraceEvent.copy*"), exclude[DirectMissingMethodProblem]("sbt.internal.util.StringEvent.copy*"), - // Private final class constructor changed + // Private final class constructors changed exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcretePosition.this"), + exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcreteProblem.this"), ), ) .configure(addSbtIO) diff --git a/internal/util-interface/src/main/java/xsbti/Problem.java b/internal/util-interface/src/main/java/xsbti/Problem.java index db7f67b22..db61f2bde 100644 --- a/internal/util-interface/src/main/java/xsbti/Problem.java +++ b/internal/util-interface/src/main/java/xsbti/Problem.java @@ -3,10 +3,20 @@ */ package xsbti; +import java.util.Optional; + public interface Problem { String category(); Severity severity(); String message(); Position position(); -} \ No newline at end of file + + // Default value to avoid breaking binary compatibility + /** + * If present, the string shown to the user when displaying this Problem. + * Otherwise, the Problem will be shown in an implementation-defined way + * based on the values of its other fields. + */ + default Optional rendered() { return Optional.empty(); } +} diff --git a/internal/util-logging/src/main/contraband/interface.contra.txt b/internal/util-logging/src/main/contraband/interface.contra.txt index a42eb09cb..3b5ed4986 100644 --- a/internal/util-logging/src/main/contraband/interface.contra.txt +++ b/internal/util-logging/src/main/contraband/interface.contra.txt @@ -29,4 +29,5 @@ type Problem { severity: Severity! message: String! position: Position! + rendered: String } diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/codec/ProblemFormats.scala b/internal/util-logging/src/main/scala/sbt/internal/util/codec/ProblemFormats.scala index 9820289da..fb7583a5c 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/codec/ProblemFormats.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/codec/ProblemFormats.scala @@ -4,8 +4,8 @@ package sbt.internal.util.codec import xsbti.{ Problem, Severity, Position } -import sbt.util.InterfaceUtil.problem import _root_.sjsonnew.{ deserializationError, Builder, JsonFormat, Unbuilder } +import java.util.Optional trait ProblemFormats { self: SeverityFormats with PositionFormats with sjsonnew.BasicJsonProtocol => implicit lazy val ProblemFormat: JsonFormat[Problem] = new JsonFormat[Problem] { @@ -13,12 +13,20 @@ trait ProblemFormats { self: SeverityFormats with PositionFormats with sjsonnew. jsOpt match { case Some(js) => unbuilder.beginObject(js) - val category = unbuilder.readField[String]("category") - val severity = unbuilder.readField[Severity]("severity") - val message = unbuilder.readField[String]("message") - val position = unbuilder.readField[Position]("position") + val category0 = unbuilder.readField[String]("category") + val severity0 = unbuilder.readField[Severity]("severity") + val message0 = unbuilder.readField[String]("message") + val position0 = unbuilder.readField[Position]("position") + val rendered0 = unbuilder.readField[Optional[String]]("rendered") + unbuilder.endObject() - problem(category, position, message, severity) + new Problem { + override val category = category0 + override val position = position0 + override val message = message0 + override val severity = severity0 + override val rendered = rendered0 + } case None => deserializationError("Expected JsObject but found None") } @@ -29,6 +37,7 @@ trait ProblemFormats { self: SeverityFormats with PositionFormats with sjsonnew. builder.addField("severity", obj.severity) builder.addField("message", obj.message) builder.addField("position", obj.position) + builder.addField("rendered", obj.rendered) builder.endObject() } } diff --git a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala index a1ae332d8..1de667f5b 100644 --- a/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala +++ b/internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala @@ -89,8 +89,16 @@ object InterfaceUtil { endLine0, endColumn0) + @deprecated("Use the overload of this method with more arguments", "1.2.2") def problem(cat: String, pos: Position, msg: String, sev: Severity): Problem = - new ConcreteProblem(cat, pos, msg, sev) + problem(cat, pos, msg, sev, None) + + def problem(cat: String, + pos: Position, + msg: String, + sev: Severity, + rendered: Option[String]): Problem = + new ConcreteProblem(cat, pos, msg, sev, rendered) private final class ConcreteT2[A1, A2](a1: A1, a2: A2) extends T2[A1, A2] { val get1: A1 = a1 @@ -144,12 +152,14 @@ object InterfaceUtil { cat: String, pos: Position, msg: String, - sev: Severity + sev: Severity, + rendered0: Option[String] ) extends Problem { val category = cat val position = pos val message = msg val severity = sev + override val rendered = o2jo(rendered0) override def toString = s"[$severity] $pos: $message" } } diff --git a/internal/util-logging/src/main/scala/sbt/util/Logger.scala b/internal/util-logging/src/main/scala/sbt/util/Logger.scala index 37a043cfa..3e543b5ce 100644 --- a/internal/util-logging/src/main/scala/sbt/util/Logger.scala +++ b/internal/util-logging/src/main/scala/sbt/util/Logger.scala @@ -117,6 +117,7 @@ object Logger { sourceFile0 ) + @deprecated("Use InterfaceUtil.problem", "1.2.2") def problem(cat: String, pos: Position, msg: String, sev: Severity): Problem = InterfaceUtil.problem(cat, pos, msg, sev) }