Skip to content

Commit 9d6e4e1

Browse files
authored
fix: correctly report error position on unknown directive without values (#3518)
* fix: correctly report error position on unknown directive without values * revert unneeded change
1 parent 3d6a25e commit 9d6e4e1

File tree

9 files changed

+81
-31
lines changed

9 files changed

+81
-31
lines changed

modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ case class DirectivesPreprocessor(
147147
val res = directives
148148
.iterator
149149
.flatMap {
150-
case d @ StrictDirective(k, _, _) =>
150+
case d @ StrictDirective(k, _, _, _) =>
151151
handlersMap.get(k).iterator.map(_(ScopedDirective(d, path, cwd), logger))
152152
}
153153
.toVector

modules/build/src/main/scala/scala/build/preprocessing/ExtractedDirectives.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,13 @@ object ExtractedDirectives {
7777
case sl: StringLiteral => Seq(StringValue(sl.getValue(), sl))
7878
case bl: BooleanLiteral => Seq(BooleanValue(bl.getValue(), bl))
7979
}
80-
def toStrictDirective(ud: UsingDef) = StrictDirective(
81-
ud.getKey(),
82-
toStrictValue(ud.getValue()),
83-
ud.getPosition().getColumn()
84-
)
80+
def toStrictDirective(ud: UsingDef) =
81+
StrictDirective(
82+
ud.getKey(),
83+
toStrictValue(ud.getValue()),
84+
ud.getPosition().getColumn(),
85+
ud.getPosition().getLine()
86+
)
8587

8688
directives.getAst match
8789
case uds: UsingDefs => uds.getUsingDefs.asScala.toSeq.map(toStrictDirective)

modules/cli/src/main/scala/scala/cli/commands/fix/BuiltInRules.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ object BuiltInRules extends CommandHelpers {
286286
val (withTestEquivalent, noTestEquivalent) =
287287
noInitialTestPrefix.partition(_.existsTestEquivalent)
288288
val transformedToTestEquivalents = withTestEquivalent.map {
289-
case StrictDirective(key, values, _) => StrictDirective("test." + key, values)
289+
case StrictDirective(key, values, _, _) => StrictDirective("test." + key, values)
290290
}
291291

292292
TransformedTestDirectives(

modules/core/src/main/scala/scala/build/errors/UnusedDirectiveError.scala

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package scala.build.errors
22

33
import scala.build.Position
44

5-
final class UnusedDirectiveError(key: String, values: Seq[String], positions: Seq[Position])
5+
final class UnusedDirectiveError(key: String, values: Seq[String], position: Position)
66
extends BuildException(
7-
s"Unrecognized directive: $key with values: ${values.mkString(", ")}",
8-
positions = positions
7+
s"Unrecognized directive: $key${
8+
if values.isEmpty then "" else s" with values: ${values.mkString(", ")}"
9+
}",
10+
positions = List(position)
911
)

modules/directives/src/main/scala/scala/build/preprocessing/directives/DirectiveUtil.scala

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,10 @@ object DirectiveUtil {
3838

3939
def concatAllValues(
4040
scopedDirective: ScopedDirective
41-
): Seq[Positioned[String]] =
42-
scopedDirective.directive.values.map {
43-
case v: StringValue =>
44-
val pos = position(v, scopedDirective.maybePath)
45-
Positioned(pos, v.get)
46-
case v: BooleanValue =>
47-
val pos = position(v, scopedDirective.maybePath)
48-
Positioned(pos, v.get.toString)
49-
case v: EmptyValue =>
50-
val pos = position(v, scopedDirective.maybePath)
51-
Positioned(pos, v.get)
52-
}
41+
): Seq[String] =
42+
scopedDirective.directive.values.collect:
43+
case v: StringValue => v.get
44+
case v: BooleanValue => v.get.toString
5345

5446
def positions(
5547
values: Seq[Value[_]],
Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package scala.build.preprocessing.directives
22

3+
import scala.build.Position
34
import scala.build.errors.UnusedDirectiveError
45
import scala.build.preprocessing.ScopePath
56

@@ -9,12 +10,16 @@ case class ScopedDirective(
910
cwd: ScopePath
1011
) {
1112
def unusedDirectiveError: UnusedDirectiveError = {
12-
val values =
13-
DirectiveUtil.concatAllValues(this)
13+
val values = DirectiveUtil.concatAllValues(this)
14+
val keyPos = Position.File(
15+
maybePath,
16+
(directive.startLine, directive.startColumn),
17+
(directive.startLine, directive.startColumn + directive.key.length())
18+
)
1419
new UnusedDirectiveError(
1520
directive.key,
16-
values.map(_.value),
17-
values.flatMap(_.positions)
21+
values,
22+
keyPos
1823
)
1924
}
2025
}

modules/directives/src/main/scala/scala/build/preprocessing/directives/StrictDirective.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import scala.build.Position
1717
case class StrictDirective(
1818
key: String,
1919
values: Seq[Value[?]],
20-
startColumn: Int = 0
20+
startColumn: Int = 0,
21+
startLine: Int = 0
2122
) {
2223
override def toString: String = {
2324
val suffix = if validValues.isEmpty then "" else s" ${validValues.mkString(" ")}"

modules/integration/src/test/scala/scala/cli/integration/BspTestDefinitions.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,9 @@ abstract class BspTestDefinitions extends ScalaCliSuite with TestScalaVersionArg
402402
expectedMessage = "Unrecognized directive: resource with values: ./resources",
403403
expectedSeverity = b.DiagnosticSeverity.ERROR,
404404
expectedStartLine = 0,
405-
expectedStartCharacter = 19,
405+
expectedStartCharacter = 10,
406406
expectedEndLine = 0,
407-
expectedEndCharacter = 30,
407+
expectedEndCharacter = 18,
408408
strictlyCheckMessage = false
409409
)
410410
}
@@ -1374,9 +1374,9 @@ abstract class BspTestDefinitions extends ScalaCliSuite with TestScalaVersionArg
13741374
s"Unrecognized directive: $directiveKey with values: $directiveValue",
13751375
expectedSeverity = b.DiagnosticSeverity.ERROR,
13761376
expectedStartLine = 0,
1377-
expectedStartCharacter = 33,
1377+
expectedStartCharacter = 10,
13781378
expectedEndLine = 0,
1379-
expectedEndCharacter = 38
1379+
expectedEndCharacter = 32
13801380
)
13811381
}
13821382
}

modules/integration/src/test/scala/scala/cli/integration/CompileTestDefinitions.scala

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,4 +821,52 @@ abstract class CompileTestDefinitions
821821

822822
}
823823
}
824+
825+
test("i3389") {
826+
val filename = "Main.scala"
827+
val inputs = TestInputs(
828+
os.rel / filename ->
829+
"""//> using optionsdeprecation
830+
|""".stripMargin
831+
)
832+
833+
inputs.fromRoot { root =>
834+
val result = os.proc(TestUtil.cli, "compile", ".", extraOptions).call(
835+
cwd = root,
836+
check = false,
837+
mergeErrIntoOut = true
838+
)
839+
assertEquals(
840+
TestUtil.fullStableOutput(result).trim(),
841+
s"""|[error] .${File.separatorChar}Main.scala:1:11
842+
|[error] Unrecognized directive: optionsdeprecation
843+
|[error] //> using optionsdeprecation
844+
|[error] ^^^^^^^^^^^^^^^^^^""".stripMargin
845+
)
846+
}
847+
}
848+
849+
test("i3389-2") {
850+
val filename = "Main.scala"
851+
val inputs = TestInputs(
852+
os.rel / filename ->
853+
"""//> using unrecognised.directive value1 value2
854+
|""".stripMargin
855+
)
856+
857+
inputs.fromRoot { root =>
858+
val result = os.proc(TestUtil.cli, "compile", ".", extraOptions).call(
859+
cwd = root,
860+
check = false,
861+
mergeErrIntoOut = true
862+
)
863+
assertEquals(
864+
TestUtil.fullStableOutput(result).trim(),
865+
s"""|[error] .${File.separatorChar}Main.scala:1:11
866+
|[error] Unrecognized directive: unrecognised.directive with values: value1, value2
867+
|[error] //> using unrecognised.directive value1 value2
868+
|[error] ^^^^^^^^^^^^^^^^^^^^^^""".stripMargin
869+
)
870+
}
871+
}
824872
}

0 commit comments

Comments
 (0)