mirror of https://github.com/sbt/sbt.git
[2.0.x] fix: Fix error with "-language:postfixOps" (#9158)
Co-authored-by: kenji yoshida <6b656e6a69@gmail.com>
This commit is contained in:
parent
5fe73c82fd
commit
06e53a0ae4
|
|
@ -29,7 +29,7 @@ import sbt.io.{ Hash, IO }
|
|||
* - mkReporter - an optional factory method to create a reporter
|
||||
*/
|
||||
class Eval(
|
||||
nonCpOptions: Seq[String],
|
||||
private[internal] val nonCpOptions: Seq[String],
|
||||
classpath: Seq[Path],
|
||||
backingDir: Option[Path],
|
||||
mkReporter: Option[() => EvalReporter]
|
||||
|
|
|
|||
|
|
@ -93,10 +93,11 @@ private[sbt] object EvaluateConfigurations {
|
|||
file: VirtualFileRef,
|
||||
lines: Seq[String],
|
||||
builtinImports: Seq[String],
|
||||
offset: Int
|
||||
offset: Int,
|
||||
options: Seq[String]
|
||||
): ParsedFile = {
|
||||
def loseTree(l: (String, Tree, LineRange)): (String, LineRange) = (l._1, l._3)
|
||||
val (importStatements, settingsAndDefinitions) = splitExpressions(file, lines)
|
||||
val (importStatements, settingsAndDefinitions) = splitExpressions(file, lines, options)
|
||||
val allImports = builtinImports.map(s => (s, -1)) ++ addOffset(offset, importStatements)
|
||||
val (definitions, settings) = splitSettingsDefinitions(
|
||||
addOffsetToRange(offset, settingsAndDefinitions)
|
||||
|
|
@ -147,7 +148,7 @@ private[sbt] object EvaluateConfigurations {
|
|||
val name = file match
|
||||
case file: PathBasedFile => file.toPath.toString
|
||||
case file => file.id
|
||||
val parsed = parseConfiguration(file, lines, imports, offset)
|
||||
val parsed = parseConfiguration(file, lines, imports, offset, eval.nonCpOptions)
|
||||
val (importDefs, definitions) =
|
||||
if (parsed.definitions.isEmpty) (Nil, DefinedSbtValues.empty)
|
||||
else {
|
||||
|
|
@ -277,15 +278,22 @@ private[sbt] object EvaluateConfigurations {
|
|||
case _ => Nil
|
||||
}
|
||||
|
||||
private[sbt] def splitExpressions(
|
||||
file: VirtualFileRef,
|
||||
lines: Seq[String],
|
||||
): (Seq[(String, Int)], Seq[(String, Tree, LineRange)]) =
|
||||
splitExpressions(file, lines, Nil)
|
||||
|
||||
/**
|
||||
* Splits a set of lines into (imports, expressions). That is,
|
||||
* anything on the right of the tuple is a scala expression (definition or setting).
|
||||
*/
|
||||
private[sbt] def splitExpressions(
|
||||
file: VirtualFileRef,
|
||||
lines: Seq[String]
|
||||
lines: Seq[String],
|
||||
options: Seq[String]
|
||||
): (Seq[(String, Int)], Seq[(String, Tree, LineRange)]) =
|
||||
val split = SbtParser(file, lines)
|
||||
val split = SbtParser(file, lines, options)
|
||||
// TODO - Look at pulling the parsed expression trees from the SbtParser and stitch them back into a different
|
||||
// scala compiler rather than re-parsing.
|
||||
(
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import dotty.tools.dotc.reporting.Diagnostic
|
|||
import dotty.tools.dotc.reporting.Reporter
|
||||
import dotty.tools.dotc.reporting.StoreReporter
|
||||
import scala.util.Random
|
||||
import scala.collection.concurrent.TrieMap
|
||||
import xsbti.VirtualFileRef
|
||||
|
||||
private[sbt] object SbtParser:
|
||||
|
|
@ -50,6 +51,9 @@ private[sbt] object SbtParser:
|
|||
private final val defaultClasspath =
|
||||
sbt.io.Path.makeString(sbt.io.IO.classLocationPath(classOf[Product]).toFile :: Nil)
|
||||
|
||||
def apply(path: VirtualFileRef, lines: Seq[String]): SbtParser =
|
||||
new SbtParser(path, lines)
|
||||
|
||||
def isIdentifier(ident: String): Boolean =
|
||||
val code = s"val $ident = 0; val ${ident}${ident} = $ident"
|
||||
try
|
||||
|
|
@ -135,10 +139,21 @@ private[sbt] object SbtParser:
|
|||
// Retry since Scala 3 compiler initialization can fail due to sys.props change
|
||||
private[sbt] val defaultGlobalForParser: ParseDriver =
|
||||
Retry(ParseDriver())
|
||||
private[sbt] final class ParseDriver extends Driver:
|
||||
|
||||
private val parseDriverCache: TrieMap[Seq[String], ParseDriver] =
|
||||
TrieMap.empty
|
||||
|
||||
private[sbt] def defaultGlobalForParserWithOption(options: Seq[String]): ParseDriver =
|
||||
parseDriverCache.getOrElseUpdate(
|
||||
options,
|
||||
Retry(ParseDriver(options.toList))
|
||||
)
|
||||
|
||||
private[sbt] final class ParseDriver(
|
||||
options: List[String] = List("-classpath", s"$defaultClasspath")
|
||||
) extends Driver:
|
||||
override protected val sourcesRequired: Boolean = false
|
||||
val compileCtx0 = initCtx.fresh
|
||||
val options = List("-classpath", s"$defaultClasspath")
|
||||
val compileCtx1 = setup(options.toArray, compileCtx0) match
|
||||
case Some((_, ctx)) => ctx
|
||||
case _ => sys.error(s"initialization failed for $options")
|
||||
|
|
@ -219,8 +234,15 @@ end ParsedSbtFileExpressions
|
|||
* @param path The path we're parsing (may be a dummy file)
|
||||
* @param lines The parsed "lines" of the file, where each string is a line.
|
||||
*/
|
||||
private[sbt] case class SbtParser(path: VirtualFileRef, lines: Seq[String])
|
||||
extends ParsedSbtFileExpressions:
|
||||
private[sbt] case class SbtParser(
|
||||
path: VirtualFileRef,
|
||||
lines: Seq[String],
|
||||
private val options: Seq[String]
|
||||
) extends ParsedSbtFileExpressions:
|
||||
|
||||
def this(path: VirtualFileRef, lines: Seq[String]) =
|
||||
this(path, lines, Nil)
|
||||
|
||||
// settingsTrees,modifiedContent needed for "session save"
|
||||
// TODO - We should look into splitting out "definitions" vs. "settings" here instead of further string lookups, since we have the
|
||||
// parsed trees.
|
||||
|
|
@ -241,7 +263,12 @@ private[sbt] case class SbtParser(path: VirtualFileRef, lines: Seq[String])
|
|||
VirtualFile(reporterId, wrapCode.getBytes(StandardCharsets.UTF_8)),
|
||||
scala.io.Codec.UTF8
|
||||
)
|
||||
given Context = SbtParser.defaultGlobalForParser.compileCtx.fresh.setSource(sourceFile)
|
||||
val ctx =
|
||||
if options.isEmpty then SbtParser.defaultGlobalForParser
|
||||
else SbtParser.defaultGlobalForParserWithOption(options)
|
||||
|
||||
given Context = ctx.compileCtx.fresh.setSource(sourceFile)
|
||||
|
||||
val parsedTrees = parse(fileName, reporterId)
|
||||
|
||||
// Check No val (a,b) = foo *or* val a,b = foo as these are problematic to range positions and the WHOLE architecture.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package sbt.internal
|
||||
|
||||
import sbt.internal.parser.SbtParser
|
||||
import sbt.internal.util.LineRange
|
||||
import sbt.internal.util.{ LineRange, MessageOnlyException }
|
||||
import xsbti.VirtualFileRef
|
||||
|
||||
object SbtParserTest extends verify.BasicTestSuite:
|
||||
|
|
@ -102,4 +102,15 @@ val x = 1
|
|||
test("isIdentifier") {
|
||||
assert(SbtParser.isIdentifier("1a") == false)
|
||||
}
|
||||
|
||||
test("postfix") {
|
||||
val ref = VirtualFileRef.of("vfile")
|
||||
val src = "Nil head"
|
||||
intercept[MessageOnlyException] {
|
||||
SbtParser(ref, Seq(src))
|
||||
}
|
||||
val p = SbtParser(ref, Seq(src), Seq("-language:postfixOps"))
|
||||
assert(p.imports.isEmpty)
|
||||
assert(p.lines == Seq(src))
|
||||
}
|
||||
end SbtParserTest
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
def foo: Int = Seq(2) head
|
||||
|
|
@ -0,0 +1 @@
|
|||
scalacOptions += "-language:postfixOps"
|
||||
|
|
@ -0,0 +1 @@
|
|||
> name
|
||||
Loading…
Reference in New Issue