diff --git a/build.sbt b/build.sbt index 7a2d78ce6..9a07324dd 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" @@ -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 795e6a4c3..3b5ed4986 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 { @@ -23,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/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/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 5a85c9b67..1de667f5b 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, @@ -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 75d7a439d..3e543b5ce 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, @@ -116,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) }