mirror of https://github.com/sbt/sbt.git
Merge pull request #7251 from eed3si9n/wip/problem
Add concrete impl for Action
This commit is contained in:
commit
f539e12645
|
|
@ -369,7 +369,7 @@ lazy val utilLogging = (project in file("internal") / "util-logging")
|
|||
.enablePlugins(ContrabandPlugin, JsonCodecPlugin)
|
||||
.dependsOn(utilInterface, collectionProj, coreMacrosProj)
|
||||
.settings(
|
||||
utilCommonSettings,
|
||||
testedBaseSettings,
|
||||
name := "Util Logging",
|
||||
libraryDependencies ++=
|
||||
Seq(
|
||||
|
|
@ -383,7 +383,6 @@ lazy val utilLogging = (project in file("internal") / "util-logging")
|
|||
sjsonNewScalaJson.value,
|
||||
scalaReflect.value
|
||||
),
|
||||
libraryDependencies ++= Seq(scalacheck % "test", scalatest % "test"),
|
||||
Compile / scalacOptions ++= (scalaVersion.value match {
|
||||
case v if v.startsWith("2.12.") => List("-Ywarn-unused:-locals,-explicits,-privates")
|
||||
case _ => List()
|
||||
|
|
@ -397,6 +396,7 @@ lazy val utilLogging = (project in file("internal") / "util-logging")
|
|||
if (name == "Throwable") Nil
|
||||
else old(tpe)
|
||||
},
|
||||
Test / fork := true,
|
||||
utilMimaSettings,
|
||||
mimaBinaryIssueFilters ++= Seq(
|
||||
exclude[DirectMissingMethodProblem]("sbt.internal.util.SuccessEvent.copy*"),
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// Note: Update InterfaceUtil.scala as well.
|
||||
|
||||
public interface Problem {
|
||||
String category();
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,17 @@ import java.util.Optional
|
|||
import java.util.function.Supplier
|
||||
import java.{ util => ju }
|
||||
|
||||
import xsbti.{ DiagnosticCode, DiagnosticRelatedInformation, Position, Problem, Severity, T2 }
|
||||
import xsbti.{
|
||||
Action,
|
||||
DiagnosticCode,
|
||||
DiagnosticRelatedInformation,
|
||||
Position,
|
||||
Problem,
|
||||
Severity,
|
||||
TextEdit,
|
||||
WorkspaceEdit,
|
||||
T2,
|
||||
}
|
||||
|
||||
import scala.collection.mutable.ListBuffer
|
||||
|
||||
|
|
@ -130,6 +140,7 @@ object InterfaceUtil {
|
|||
): Problem =
|
||||
problem(cat, pos, msg, sev, rendered, None, List.empty[DiagnosticRelatedInformation])
|
||||
|
||||
@deprecated("Use the overload of this method with more arguments", "1.9.0")
|
||||
def problem(
|
||||
cat: String,
|
||||
pos: Position,
|
||||
|
|
@ -139,7 +150,59 @@ object InterfaceUtil {
|
|||
diagnosticCode: Option[DiagnosticCode],
|
||||
diagnosticRelatedInforamation: List[DiagnosticRelatedInformation]
|
||||
): Problem =
|
||||
new ConcreteProblem(cat, pos, msg, sev, rendered, diagnosticCode, diagnosticRelatedInforamation)
|
||||
problem(
|
||||
cat,
|
||||
pos,
|
||||
msg,
|
||||
sev,
|
||||
rendered,
|
||||
diagnosticCode,
|
||||
diagnosticRelatedInforamation,
|
||||
List.empty[Action],
|
||||
)
|
||||
|
||||
def problem(
|
||||
cat: String,
|
||||
pos: Position,
|
||||
msg: String,
|
||||
sev: Severity,
|
||||
rendered: Option[String],
|
||||
diagnosticCode: Option[DiagnosticCode],
|
||||
diagnosticRelatedInformation: List[DiagnosticRelatedInformation],
|
||||
actions: List[Action],
|
||||
): Problem =
|
||||
new ConcreteProblem(
|
||||
cat,
|
||||
pos,
|
||||
msg,
|
||||
sev,
|
||||
rendered,
|
||||
diagnosticCode,
|
||||
diagnosticRelatedInformation,
|
||||
actions,
|
||||
)
|
||||
|
||||
def action(
|
||||
title: String,
|
||||
description: Option[String],
|
||||
edit: WorkspaceEdit,
|
||||
): Action =
|
||||
new ConcreteAction(title, description, edit)
|
||||
|
||||
def workspaceEdit(changes: List[TextEdit]): WorkspaceEdit =
|
||||
new ConcreteWorkspaceEdit(changes)
|
||||
|
||||
def textEdit(position: Position, newText: String): TextEdit =
|
||||
new ConcreteTextEdit(position, newText)
|
||||
|
||||
def diagnosticCode(code: String, explanation: Option[String]): DiagnosticCode =
|
||||
new ConcreteDiagnosticCode(code, explanation)
|
||||
|
||||
def diagnosticRelatedInformation(
|
||||
position: Position,
|
||||
message: String
|
||||
): DiagnosticRelatedInformation =
|
||||
new ConcreteDiagnosticRelatedInformation(position, message)
|
||||
|
||||
private final class ConcreteT2[A1, A2](a1: A1, a2: A2) extends T2[A1, A2] {
|
||||
val get1: A1 = a1
|
||||
|
|
@ -187,6 +250,42 @@ object InterfaceUtil {
|
|||
override val startColumn = o2jo(startColumn0)
|
||||
override val endLine = o2jo(endLine0)
|
||||
override val endColumn = o2jo(endColumn0)
|
||||
override def toString: String = {
|
||||
val src = sourcePath0 match {
|
||||
case Some(x) => s"$x"
|
||||
case None => "none"
|
||||
}
|
||||
val line = line0 match {
|
||||
case Some(x) => s":$x"
|
||||
case None => ""
|
||||
}
|
||||
val offset = offset0 match {
|
||||
case Some(x) => s":$x"
|
||||
case None => ""
|
||||
}
|
||||
s"""$src$line$offset"""
|
||||
}
|
||||
private def toTuple(p: Position) =
|
||||
(
|
||||
p.line,
|
||||
p.lineContent,
|
||||
p.offset,
|
||||
p.pointer,
|
||||
p.pointerSpace,
|
||||
p.sourcePath,
|
||||
p.sourceFile,
|
||||
p.startOffset,
|
||||
p.endOffset,
|
||||
p.startLine,
|
||||
p.startColumn,
|
||||
p.endLine,
|
||||
p.endColumn,
|
||||
)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: Position => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private final class ConcreteProblem(
|
||||
|
|
@ -196,7 +295,8 @@ object InterfaceUtil {
|
|||
sev: Severity,
|
||||
rendered0: Option[String],
|
||||
diagnosticCode0: Option[DiagnosticCode],
|
||||
diagnosticRelatedInformation0: List[DiagnosticRelatedInformation]
|
||||
diagnosticRelatedInformation0: List[DiagnosticRelatedInformation],
|
||||
actions0: List[Action],
|
||||
) extends Problem {
|
||||
val category = cat
|
||||
val position = pos
|
||||
|
|
@ -204,8 +304,116 @@ object InterfaceUtil {
|
|||
val severity = sev
|
||||
override val rendered = o2jo(rendered0)
|
||||
override def diagnosticCode: Optional[DiagnosticCode] = o2jo(diagnosticCode0)
|
||||
override def diagnosticRelatedInforamation(): ju.List[DiagnosticRelatedInformation] =
|
||||
override def diagnosticRelatedInformation(): ju.List[DiagnosticRelatedInformation] =
|
||||
l2jl(diagnosticRelatedInformation0)
|
||||
@deprecated("use diagnosticRelatedInformation", "1.9.0")
|
||||
override def diagnosticRelatedInforamation(): ju.List[DiagnosticRelatedInformation] =
|
||||
diagnosticRelatedInformation()
|
||||
override def actions(): ju.List[Action] =
|
||||
l2jl(actions0)
|
||||
override def toString = s"[$severity] $pos: $message"
|
||||
private def toTuple(p: Problem) =
|
||||
(
|
||||
p.category,
|
||||
p.position,
|
||||
p.message,
|
||||
p.severity,
|
||||
p.rendered,
|
||||
p.diagnosticCode,
|
||||
p.diagnosticRelatedInformation,
|
||||
p.actions,
|
||||
)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: Problem => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private final class ConcreteAction(
|
||||
title0: String,
|
||||
description0: Option[String],
|
||||
edit0: WorkspaceEdit,
|
||||
) extends Action {
|
||||
val title: String = title0
|
||||
val edit: WorkspaceEdit = edit0
|
||||
override def description(): Optional[String] =
|
||||
o2jo(description0)
|
||||
override def toString(): String =
|
||||
s"Action($title0, $description0, $edit0)"
|
||||
private def toTuple(a: Action) =
|
||||
(
|
||||
a.title,
|
||||
a.description,
|
||||
a.edit,
|
||||
)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: Action => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private final class ConcreteWorkspaceEdit(changes0: List[TextEdit]) extends WorkspaceEdit {
|
||||
override def changes(): ju.List[TextEdit] = l2jl(changes0)
|
||||
override def toString(): String =
|
||||
s"WorkspaceEdit($changes0)"
|
||||
private def toTuple(w: WorkspaceEdit) = jl2l(w.changes)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: WorkspaceEdit => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private final class ConcreteTextEdit(position0: Position, newText0: String) extends TextEdit {
|
||||
val position: Position = position0
|
||||
val newText: String = newText0
|
||||
override def toString(): String =
|
||||
s"TextEdit($position, $newText)"
|
||||
private def toTuple(edit: TextEdit) =
|
||||
(
|
||||
edit.position,
|
||||
edit.newText,
|
||||
)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: TextEdit => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private final class ConcreteDiagnosticCode(code0: String, explanation0: Option[String])
|
||||
extends DiagnosticCode {
|
||||
val code: String = code0
|
||||
val explanation: Optional[String] = o2jo(explanation0)
|
||||
override def toString(): String = s"DiagnosticCode($code)"
|
||||
private def toTuple(c: DiagnosticCode) =
|
||||
(
|
||||
c.code,
|
||||
c.explanation,
|
||||
)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: DiagnosticCode => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
|
||||
private final class ConcreteDiagnosticRelatedInformation(position0: Position, message0: String)
|
||||
extends DiagnosticRelatedInformation {
|
||||
val position: Position = position0
|
||||
val message: String = message0
|
||||
override def toString(): String = s"DiagnosticRelatedInformation($position, $message)"
|
||||
private def toTuple(info: DiagnosticRelatedInformation) =
|
||||
(
|
||||
info.position,
|
||||
info.message,
|
||||
)
|
||||
override def hashCode: Int = toTuple(this).##
|
||||
override def equals(o: Any): Boolean = o match {
|
||||
case o: DiagnosticRelatedInformation => toTuple(this) == toTuple(o)
|
||||
case _ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* sbt
|
||||
* Copyright 2011 - 2018, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* Licensed under Apache License 2.0 (see LICENSE)
|
||||
*/
|
||||
|
||||
package sbt
|
||||
|
||||
import java.net.URI
|
||||
import hedgehog._
|
||||
import hedgehog.runner._
|
||||
import _root_.sbt.util.InterfaceUtil
|
||||
import InterfaceUtil.{ jl2l, jo2o, l2jl }
|
||||
import xsbti._
|
||||
|
||||
object ProblemTest extends Properties {
|
||||
override def tests: List[Test] = List(
|
||||
property(
|
||||
"All problems can toString",
|
||||
genProblem.forAll.map(toStringCheck),
|
||||
),
|
||||
property(
|
||||
"All problems can be compared structurally",
|
||||
genProblem.forAll.map(equalityCheck),
|
||||
),
|
||||
property(
|
||||
"All diagnostic codes can be compared structurally",
|
||||
genDiagnosticCode.forAll.map(equalityCheck),
|
||||
),
|
||||
property(
|
||||
"All diagnostic related information can be compared structurally",
|
||||
genDiagnosticRelatedInformation.forAll.map(equalityCheck),
|
||||
),
|
||||
property(
|
||||
"All actions can be compared structurally",
|
||||
genAction.forAll.map(equalityCheck),
|
||||
),
|
||||
)
|
||||
|
||||
def toStringCheck(p: Problem): Result =
|
||||
Result.assert(p.toString() != "")
|
||||
|
||||
def equalityCheck(p: Problem): Result = {
|
||||
val other = InterfaceUtil.problem(
|
||||
p.category,
|
||||
p.position,
|
||||
p.message,
|
||||
p.severity,
|
||||
jo2o(p.rendered),
|
||||
jo2o(p.diagnosticCode).map(copy),
|
||||
jl2l(p.diagnosticRelatedInformation).map(copy),
|
||||
jl2l(p.actions).map(copy),
|
||||
)
|
||||
Result
|
||||
.assert(p == other)
|
||||
.log(s"$p == $other")
|
||||
}
|
||||
|
||||
def equalityCheck(c: DiagnosticCode): Result = {
|
||||
val other = copy(c)
|
||||
Result.assert(c == other)
|
||||
}
|
||||
|
||||
def equalityCheck(info: DiagnosticRelatedInformation): Result = {
|
||||
val other = copy(info)
|
||||
Result.assert(info == other)
|
||||
}
|
||||
|
||||
def equalityCheck(a: Action): Result = {
|
||||
val other = copy(a)
|
||||
Result.assert(a == other)
|
||||
}
|
||||
|
||||
lazy val genProblem: Gen[Problem] =
|
||||
for {
|
||||
cat <- genString
|
||||
pos <- genPosition
|
||||
msg <- genString
|
||||
sev <- genSeverity
|
||||
rendered <- optString
|
||||
code <- optDiagnosticCode
|
||||
info <- listDiagnosticRelatedInformation
|
||||
actions <- listAction
|
||||
} yield InterfaceUtil.problem(
|
||||
cat,
|
||||
pos,
|
||||
msg,
|
||||
sev,
|
||||
rendered,
|
||||
code,
|
||||
info,
|
||||
actions,
|
||||
)
|
||||
|
||||
lazy val optDiagnosticCode: Gen[Option[DiagnosticCode]] =
|
||||
Gen.choice1(genDiagnosticCode.map(Some(_)), Gen.constant(None))
|
||||
|
||||
lazy val genDiagnosticCode: Gen[DiagnosticCode] =
|
||||
for {
|
||||
code <- Gen.int(Range.linear(0, 1024))
|
||||
} yield InterfaceUtil.diagnosticCode("E" + code.toString, None)
|
||||
|
||||
lazy val genSeverity: Gen[Severity] =
|
||||
Gen.element(Severity.Info, List(Severity.Warn, Severity.Error))
|
||||
|
||||
lazy val genPosition: Gen[Position] =
|
||||
for {
|
||||
line <- optIntGen
|
||||
content <- genString
|
||||
offset <- optIntGen
|
||||
} yield InterfaceUtil.position(
|
||||
line,
|
||||
content,
|
||||
offset,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
|
||||
lazy val listDiagnosticRelatedInformation: Gen[List[DiagnosticRelatedInformation]] =
|
||||
Gen.list(genDiagnosticRelatedInformation, Range.linear(0, 2))
|
||||
|
||||
lazy val genDiagnosticRelatedInformation: Gen[DiagnosticRelatedInformation] =
|
||||
for {
|
||||
pos <- genPosition
|
||||
message <- genString
|
||||
} yield InterfaceUtil.diagnosticRelatedInformation(pos, message)
|
||||
|
||||
lazy val listAction: Gen[List[Action]] =
|
||||
Gen.list(genAction, Range.linear(0, 2))
|
||||
|
||||
lazy val genAction: Gen[Action] =
|
||||
for {
|
||||
title <- genString
|
||||
description <- optString
|
||||
edit <- genWorkspaceEdit
|
||||
} yield InterfaceUtil.action(title, description, edit)
|
||||
|
||||
lazy val genWorkspaceEdit: Gen[WorkspaceEdit] =
|
||||
for {
|
||||
changes <- listTextEdit
|
||||
} yield InterfaceUtil.workspaceEdit(changes)
|
||||
|
||||
lazy val listTextEdit: Gen[List[TextEdit]] =
|
||||
Gen.list(genTextEdit, Range.linear(0, 2))
|
||||
|
||||
lazy val genTextEdit: Gen[TextEdit] =
|
||||
for {
|
||||
pos <- genPosition
|
||||
newText <- genString
|
||||
} yield InterfaceUtil.textEdit(pos, newText)
|
||||
|
||||
lazy val genUri: Gen[URI] =
|
||||
for {
|
||||
ssp <- genString
|
||||
} yield new URI("file", "///" + ssp, null)
|
||||
|
||||
lazy val optString: Gen[Option[String]] =
|
||||
Gen.choice1(genString.map(Some(_)), Gen.constant(None))
|
||||
|
||||
lazy val genString = Gen.string(Gen.alphaNum, Range.linear(0, 256))
|
||||
|
||||
lazy val optIntGen: Gen[Option[Integer]] =
|
||||
Gen.choice1(Gen.int(Range.linear(0, 1024)).map(Some(_)), Gen.constant(None))
|
||||
|
||||
private def copy(c: DiagnosticCode): DiagnosticCode =
|
||||
new DiagnosticCode() {
|
||||
val code = c.code
|
||||
override def explanation = c.explanation
|
||||
}
|
||||
|
||||
private def copy(info: DiagnosticRelatedInformation): DiagnosticRelatedInformation =
|
||||
new DiagnosticRelatedInformation() {
|
||||
override def position = info.position
|
||||
override def message = info.message
|
||||
}
|
||||
|
||||
private def copy(a: Action): Action =
|
||||
new Action {
|
||||
override def title = a.title
|
||||
override def description = a.description
|
||||
override def edit = copy(a.edit)
|
||||
}
|
||||
|
||||
private def copy(edit: WorkspaceEdit): WorkspaceEdit =
|
||||
new WorkspaceEdit {
|
||||
override def changes() =
|
||||
l2jl(jl2l(edit.changes).map(copy))
|
||||
}
|
||||
|
||||
private def copy(edit: TextEdit): TextEdit =
|
||||
new TextEdit {
|
||||
override val position = edit.position
|
||||
override val newText = edit.newText
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue