Skip to content
This repository was archived by the owner on Jun 10, 2020. It is now read-only.

Commit 15522a0

Browse files
committed
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).
1 parent e905b44 commit 15522a0

File tree

6 files changed

+42
-10
lines changed

6 files changed

+42
-10
lines changed

build.sbt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@ lazy val utilLogging = (project in internalPath / "util-logging")
124124
exclude[DirectMissingMethodProblem]("sbt.internal.util.SuccessEvent.copy*"),
125125
exclude[DirectMissingMethodProblem]("sbt.internal.util.TraceEvent.copy*"),
126126
exclude[DirectMissingMethodProblem]("sbt.internal.util.StringEvent.copy*"),
127-
// Private final class constructor changed
127+
// Private final class constructors changed
128128
exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcretePosition.this"),
129+
exclude[DirectMissingMethodProblem]("sbt.util.InterfaceUtil#ConcreteProblem.this"),
129130
),
130131
)
131132
.configure(addSbtIO)

internal/util-interface/src/main/java/xsbti/Problem.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,20 @@
33
*/
44
package xsbti;
55

6+
import java.util.Optional;
7+
68
public interface Problem
79
{
810
String category();
911
Severity severity();
1012
String message();
1113
Position position();
12-
}
14+
15+
// Default value to avoid breaking binary compatibility
16+
/**
17+
* If present, the string shown to the user when displaying this Problem.
18+
* Otherwise, the Problem will be shown in an implementation-defined way
19+
* based on the values of its other fields.
20+
*/
21+
default Optional<String> rendered() { return Optional.empty(); }
22+
}

internal/util-logging/src/main/contraband/interface.contra.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ type Problem {
2929
severity: Severity!
3030
message: String!
3131
position: Position!
32+
rendered: String
3233
}

internal/util-logging/src/main/scala/sbt/internal/util/codec/ProblemFormats.scala

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,29 @@
44
package sbt.internal.util.codec
55

66
import xsbti.{ Problem, Severity, Position }
7-
import sbt.util.InterfaceUtil.problem
87
import _root_.sjsonnew.{ deserializationError, Builder, JsonFormat, Unbuilder }
8+
import java.util.Optional
99

1010
trait ProblemFormats { self: SeverityFormats with PositionFormats with sjsonnew.BasicJsonProtocol =>
1111
implicit lazy val ProblemFormat: JsonFormat[Problem] = new JsonFormat[Problem] {
1212
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): Problem = {
1313
jsOpt match {
1414
case Some(js) =>
1515
unbuilder.beginObject(js)
16-
val category = unbuilder.readField[String]("category")
17-
val severity = unbuilder.readField[Severity]("severity")
18-
val message = unbuilder.readField[String]("message")
19-
val position = unbuilder.readField[Position]("position")
16+
val category0 = unbuilder.readField[String]("category")
17+
val severity0 = unbuilder.readField[Severity]("severity")
18+
val message0 = unbuilder.readField[String]("message")
19+
val position0 = unbuilder.readField[Position]("position")
20+
val rendered0 = unbuilder.readField[Optional[String]]("rendered")
21+
2022
unbuilder.endObject()
21-
problem(category, position, message, severity)
23+
new Problem {
24+
override val category = category0
25+
override val position = position0
26+
override val message = message0
27+
override val severity = severity0
28+
override val rendered = rendered0
29+
}
2230
case None =>
2331
deserializationError("Expected JsObject but found None")
2432
}
@@ -29,6 +37,7 @@ trait ProblemFormats { self: SeverityFormats with PositionFormats with sjsonnew.
2937
builder.addField("severity", obj.severity)
3038
builder.addField("message", obj.message)
3139
builder.addField("position", obj.position)
40+
builder.addField("rendered", obj.rendered)
3241
builder.endObject()
3342
}
3443
}

internal/util-logging/src/main/scala/sbt/util/InterfaceUtil.scala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,16 @@ object InterfaceUtil {
8989
endLine0,
9090
endColumn0)
9191

92+
@deprecated("Use the overload of this method with more arguments", "1.2.2")
9293
def problem(cat: String, pos: Position, msg: String, sev: Severity): Problem =
93-
new ConcreteProblem(cat, pos, msg, sev)
94+
problem(cat, pos, msg, sev, None)
95+
96+
def problem(cat: String,
97+
pos: Position,
98+
msg: String,
99+
sev: Severity,
100+
rendered: Option[String]): Problem =
101+
new ConcreteProblem(cat, pos, msg, sev, rendered)
94102

95103
private final class ConcreteT2[A1, A2](a1: A1, a2: A2) extends T2[A1, A2] {
96104
val get1: A1 = a1
@@ -144,12 +152,14 @@ object InterfaceUtil {
144152
cat: String,
145153
pos: Position,
146154
msg: String,
147-
sev: Severity
155+
sev: Severity,
156+
rendered0: Option[String]
148157
) extends Problem {
149158
val category = cat
150159
val position = pos
151160
val message = msg
152161
val severity = sev
162+
override val rendered = o2jo(rendered0)
153163
override def toString = s"[$severity] $pos: $message"
154164
}
155165
}

internal/util-logging/src/main/scala/sbt/util/Logger.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ object Logger {
117117
sourceFile0
118118
)
119119

120+
@deprecated("Use InterfaceUtil.problem", "1.2.2")
120121
def problem(cat: String, pos: Position, msg: String, sev: Severity): Problem =
121122
InterfaceUtil.problem(cat, pos, msg, sev)
122123
}

0 commit comments

Comments
 (0)