Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
lihaoyi committed Sep 28, 2023
2 parents be1c912 + 084f7f4 commit 8ef2171
Show file tree
Hide file tree
Showing 31 changed files with 545 additions and 162 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
fail-fast: false
matrix:
java-version: [8, 11]
scala-version: [2.12.17, 2.13.10, 3.2.2]
scala-version: [2.12.18, 2.13.12, 3.3.1]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -29,7 +29,7 @@ jobs:
fail-fast: false
matrix:
java-version: [8, 11]
scala-version: [2.12.17, 2.13.10, 3.2.2]
scala-version: [2.12.18, 2.13.12, 3.3.1]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand Down
22 changes: 9 additions & 13 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
License
=======
MIT License


The MIT License (MIT)

Copyright (c) 2014 Li Haoyi (haoyi.sg@gmail.com)
Copyright (c) 2015 Li Haoyi (haoyi.sg@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -13,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ abstract class CompilerBuilder {
headFrame: => Frame,
dependencyCompleter: => Option[String => (Int, Seq[String])],
whiteList: Set[Seq[String]],
initialClassLoader: ClassLoader
initialClassLoader: ClassLoader,
settings: Seq[String]
): CompilerLifecycleManager

def create(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ammonite.compiler

import ammonite.util.Classpath

import scala.reflect.internal.util.{CodeAction, Position}
import scala.reflect.io.FileZipArchive
import scala.tools.nsc
import scala.tools.nsc.classpath.{AggregateClassPath, ZipAndJarClassPathFactory}
import scala.tools.nsc.{Global, Settings}
import scala.tools.nsc.interactive.{InteractiveAnalyzer, Global => InteractiveGlobal}
import scala.tools.nsc.plugins.Plugin
import scala.tools.nsc.reporters.FilteringReporter
import scala.tools.nsc.typechecker.Analyzer

object MakeReporter {

type Reporter = scala.tools.nsc.reporters.Reporter

def makeReporter(errorLogger: (Position, String) => Unit,
warningLogger: (Position, String) => Unit,
infoLogger: (Position, String) => Unit,
outerSettings: Settings): Reporter =
new FilteringReporter {

override
def doReport(pos: scala.reflect.internal.util.Position,
msg: String,
severity: Severity,
actions: List[CodeAction]): Unit =
display(pos, msg, severity)

def display(pos: Position, msg: String, severity: Severity) =
severity match{
case ERROR =>
Classpath.traceClasspathProblem(s"ERROR: $msg")
errorLogger(pos, msg)
case WARNING =>
warningLogger(pos, msg)
case INFO =>
infoLogger(pos, msg)
}

def settings = outerSettings
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,8 @@ object Compiler{
output.write(bytes)
output.close()

for (dir <- outputDir0) {
val dest = dir / elems
os.makeDir.all(dest / os.up)
os.write(dest, bytes)
}
for (dir <- outputDir0)
os.write.over(dir / elems, bytes, createFolders = true)
}

}
Expand Down Expand Up @@ -196,7 +193,6 @@ object Compiler{

settings.outputDirs.setSingleOutput(vd)

settings.nowarnings.value = true
// Otherwise the presence of `src`'s source files mixed with
// classfiles causes scalac to get confused
settings.termConflict.value = "object"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,17 @@ case class CompilerBuilder(
headFrame: => Frame,
dependencyCompleter: => Option[String => (Int, Seq[String])],
whiteList: Set[Seq[String]],
initialClassLoader: ClassLoader
initialClassLoader: ClassLoader,
settings: Seq[String]
): CompilerLifecycleManager =
new CompilerLifecycleManager(
rtCacheDir,
headFrame,
dependencyCompleter,
whiteList,
initialClassLoader,
outputDir
outputDir,
settings
)

def scalaVersion = CompilerBuilder.scalaVersion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class CompilerLifecycleManager(
dependencyCompleteOpt: => Option[String => (Int, Seq[String])],
classPathWhitelist: Set[Seq[String]],
initialClassLoader: ClassLoader,
val outputDir: Option[Path]
val outputDir: Option[Path],
initialSettings: Seq[String]
) extends ICompilerLifecycleManager {

def scalaVersion = scala.util.Properties.versionNumberString
Expand Down Expand Up @@ -88,6 +89,9 @@ class CompilerLifecycleManager(
// Otherwise activating autocomplete makes the presentation compiler mangle
// the shared settings and makes the main compiler sad
val settings = Option(compiler).fold(new Settings)(_.compiler.settings.copy)
val (success, trailingSettings) = settings.processArguments(initialSettings.toList, processAll = true)
if (!success)
System.err.println(s"Error processing initial settings ${initialSettings.mkString(" ")}")
onSettingsInit.foreach(_(settings))

val initialClassPath = Classpath.classpath(initialClassLoader, rtCacheDir)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,13 @@ class DefaultPreprocessor(parse: => String => Either[String, Seq[G#Tree]],

val Import = Processor{
case (name, code, tree: G#Import) =>
val Array(keyword, body) = code.split(" ", 2)
val tq = "\"\"\""
val body = fastparse.parse(code, Parsers.ImportFinder(_)) match {
case s: fastparse.Parsed.Success[String] =>
s.value
case _ =>
val Array(keyword, body) = code.split(" ", 2)
body
}
Expanded(code, Seq(
s"""
_root_.ammonite
Expand Down
56 changes: 39 additions & 17 deletions amm/compiler/src/main/scala-2/ammonite/compiler/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object Parsers extends IParser {
private def `_`[_: P] = scalaparse.Scala.Underscore


private def ImportSplitter[_: P]: P[Seq[ammonite.util.ImportTree]] = {
private def ImportExpr[_: P]: P[ammonite.util.ImportTree] = {
def IdParser = P( (Id | `_` ).! ).map(
s => if (s(0) == '`') s.drop(1).dropRight(1) else s
)
Expand All @@ -28,18 +28,22 @@ object Parsers extends IParser {
)
def Prefix = P( IdParser.rep(1, sep = ".") )
def Suffix = P( "." ~/ (BulkImport | Selectors) )
def ImportExpr: P[ammonite.util.ImportTree] = {
// Manually use `WL0` parser here, instead of relying on WhitespaceApi, as
// we do not want the whitespace to be consumed even if the WL0 parser parses
// to the end of the input (which is the default behavior for WhitespaceApi)
P( Index ~~ Prefix ~~ (WL0 ~~ Suffix).? ~~ Index).map{
case (start, idSeq, selectors, end) =>
ammonite.util.ImportTree(idSeq, selectors, start, end)
}

// Manually use `WL0` parser here, instead of relying on WhitespaceApi, as
// we do not want the whitespace to be consumed even if the WL0 parser parses
// to the end of the input (which is the default behavior for WhitespaceApi)
P( Index ~~ Prefix ~~ (WL0 ~~ Suffix).? ~~ Index).map{
case (start, idSeq, selectors, end) =>
ammonite.util.ImportTree(idSeq, selectors, start, end)
}
P( `import` ~/ ImportExpr.rep(1, sep = ","./) )
}

def ImportSplitter[_: P]: P[Seq[ammonite.util.ImportTree]] =
P( WL ~ `import` ~/ ImportExpr.rep(1, sep = ","./) )

def ImportFinder[_: P]: P[String] =
P(WL ~ `import` ~/ ImportExpr.! ~ End)

private def PatVarSplitter[_: P] = {
def Prefixes = P(Prelude ~ (`var` | `val`))
def Lhs = P( Prefixes ~/ BindPattern.rep(1, "," ~/ Pass) ~ (`:` ~/ Type).? )
Expand All @@ -63,8 +67,11 @@ object Parsers extends IParser {
private def StatementBlock[_: P](blockSep: => P0) =
P( Semis.? ~ (Index ~ (!blockSep ~ TmplStat ~~ WS ~~ (Semis | &("}") | End)).!).repX)

private def Splitter0[_: P] = P( StatementBlock(Fail) )
def Splitter[_: P] = P( ("{" ~ Splitter0 ~ "}" | Splitter0) ~ End )
private def Splitter0[_: P] = P(StatementBlock(Fail))

private def HighlightSplitter[_: P] = P( ("{" ~ Splitter0 ~ "}" | Splitter0) ~ End )

def Splitter[_: P] = P(("{" ~~ WL.! ~~ Splitter0 ~ "}" | WL.! ~~ Splitter0) ~ End)

private def ObjParser[_: P] = P( ObjDef )

Expand Down Expand Up @@ -94,14 +101,29 @@ object Parsers extends IParser {
case f @ Parsed.Failure(_, _, _) => Some(Left(
formatFastparseError(fileName, code, f)
))
case Parsed.Success(value, index) => Some(Right(value.map(_._2)))
case Parsed.Success(value, index) => {
val (str, seq) = value
if (seq.isEmpty) {
Some(Right(Nil))
} else {
Some(Right(Seq(str + seq.head._2) ++ seq.tail.map(_._2)))
}
}
}
} else
parse(code, Splitter(_)) match{
case f @ Parsed.Failure(_, _, _) => Some(Left(
formatFastparseError(fileName, code, f)
))
case Parsed.Success(value, index) => Some(Right(value.map(_._2)))
case Parsed.Success(value, index) => {
val (str, seq) = value
if (seq.isEmpty) {
Some(Right(Nil))
} else {
Some(Right(Seq(str + seq.head._2) ++ seq.tail.map(_._2)))
}

}
}

def isObjDef(code: String): Boolean = {
Expand Down Expand Up @@ -265,19 +287,19 @@ object Parsers extends IParser {
keyword: fansi.Attrs,
notImplemented: fansi.Attrs,
reset: fansi.Attrs) = {
Highlighter.defaultHighlight0(Splitter(_), buffer, comment, `type`, literal, keyword, reset)
Highlighter.defaultHighlight0(HighlightSplitter(_), buffer, comment, `type`, literal, keyword, reset)
}
def defaultHighlightIndices(buffer: Vector[Char],
comment: fansi.Attrs,
`type`: fansi.Attrs,
literal: fansi.Attrs,
keyword: fansi.Attrs,
reset: fansi.Attrs) = Highlighter.defaultHighlightIndices0(
Splitter(_), buffer, comment, `type`, literal, keyword, reset
HighlightSplitter(_), buffer, comment, `type`, literal, keyword, reset
)

def highlightIndices[T](buffer: Vector[Char],
ruleColors: PartialFunction[String, T],
endColor: T): Seq[(Int, T)] =
Highlighter.highlightIndices(Parsers.Splitter(_), buffer, ruleColors, endColor)
Highlighter.highlightIndices(Parsers.HighlightSplitter(_), buffer, ruleColors, endColor)
}
Loading

0 comments on commit 8ef2171

Please sign in to comment.