Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade to scalameta 3.7.0 with default settings. #675

Merged
merged 10 commits into from
Apr 9, 2018
40 changes: 28 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import sbt.ScriptedPlugin
import sbt.ScriptedPlugin._
import Dependencies._

Expand Down Expand Up @@ -147,6 +146,7 @@ val cli = MultiScalaProject(
mainClass in assembly := Some("scalafix.cli.Cli"),
assemblyJarName in assembly := "scalafix.jar",
libraryDependencies ++= Seq(
metacp,
"com.github.alexarchambault" %% "case-app" % "1.2.0",
"org.typelevel" %% "paiges-core" % "0.2.0",
"com.martiansoftware" % "nailgun-server" % "0.9.1",
Expand Down Expand Up @@ -207,10 +207,18 @@ val scalafixSbt = MultiSbtProject(
).enablePlugins(BuildInfoPlugin)
.disablePlugins(ScalafixPlugin)
)
lazy val scalafixSbt1 =
scalafixSbt(scala212, sbt1, _.dependsOn(testUtils212 % Test))
lazy val scalafixSbt013 =
scalafixSbt(scala210, sbt013, _.dependsOn(testUtils210 % Test))
lazy val scalafixSbt1 = scalafixSbt(
scala212,
sbt1,
_.dependsOn(testUtils212 % Test)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this formatting change intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, for consistency with the changes below

)
lazy val scalafixSbt013 = scalafixSbt(
scala210,
sbt013,
_.settings(
scalacOptions -= warnUnusedImports
).dependsOn(testUtils210 % Test)
)

val testUtils = MultiScalaProject(
"test-utils",
Expand All @@ -221,7 +229,12 @@ val testUtils = MultiScalaProject(
)
)
)
lazy val testUtils210 = testUtils(scala210)
lazy val testUtils210 = testUtils(
scala210,
_.settings(
scalacOptions -= warnUnusedImports
)
)
lazy val testUtils211 = testUtils(scala211)
lazy val testUtils212 = testUtils(scala212)

Expand Down Expand Up @@ -259,10 +272,13 @@ val testsInput = TestProject(
project.settings(
noPublish,
semanticdbSettings,
scalacOptions += {
val sourceroot = baseDirectory.in(ThisBuild).value / srcMain
s"-P:semanticdb:sourceroot:$sourceroot"
},
scalacOptions ++= List(
{
val sourceroot = baseDirectory.in(ThisBuild).value / srcMain
s"-P:semanticdb:sourceroot:$sourceroot"
},
s"-P:semanticdb:denotations:all"
),
scalacOptions ~= (_.filterNot(_ == "-Yno-adapted-args")),
scalacOptions += "-Ywarn-adapted-args", // For NoAutoTupling
scalacOptions += "-Ywarn-unused-import", // For RemoveUnusedImports
Expand Down Expand Up @@ -325,8 +341,8 @@ def unit(
javaOptions := Nil,
buildInfoPackage := "scalafix.tests",
buildInfoObject := "BuildInfo",
sources.in(Test) += (baseDirectory
.in(ThisBuild))
sources.in(Test) += baseDirectory
.in(ThisBuild)
.value / "scalafix-sbt" / "src" / "main" / "scala" / "scalafix" / "internal" / "sbt" / "ScalafixJarFetcher.scala",
libraryDependencies ++= coursierDeps ++ testsDeps
).enablePlugins(BuildInfoPlugin)
Expand Down
3 changes: 2 additions & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import org.scalajs.sbtplugin.ScalaJSPlugin.autoImport._
/* scalafmt: { maxColumn = 120 }*/

object Dependencies {
val scalametaV = "3.3.1"
val scalametaV = "3.7.2"
val metaconfigV = "0.6.0-RC1"
def dotty = "0.1.1-bin-20170530-f8f52cc-NIGHTLY"
def scala210 = "2.10.6"
Expand All @@ -26,6 +26,7 @@ object Dependencies {
def ammonite = "com.lihaoyi" %% "ammonite-ops" % "0.9.0"
def googleDiff = "com.googlecode.java-diff-utils" % "diffutils" % "1.3.0"

def metacp = "org.scalameta" %% "metacp" % scalametaV
def scalameta = Def.setting("org.scalameta" %%% "contrib" % scalametaV)
val scalatest = "org.scalatest" %% "scalatest" % "3.0.0"

Expand Down
2 changes: 1 addition & 1 deletion project/ScalafixBuild.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ object ScalafixBuild extends AutoPlugin with GhpagesKeys {
)
lazy val warnUnusedImports = "-Ywarn-unused-import"
lazy val compilerOptions = Seq(
"-Xlint",
warnUnusedImports,
"-deprecation",
"-encoding",
"UTF-8",
Expand Down
54 changes: 39 additions & 15 deletions scalafix-cli/src/main/scala/scalafix/cli/CliRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import java.util.concurrent.atomic.AtomicReference
import java.util.function.UnaryOperator
import java.util.regex.Pattern
import java.util.regex.PatternSyntaxException

import scala.meta._
import scala.meta.inputs.Input
import scala.meta.internal.inputs._
Expand Down Expand Up @@ -42,6 +41,7 @@ import scalafix.syntax._
import metaconfig.Configured.Ok
import metaconfig._
import metaconfig.ConfError
import scalafix.internal.cli.ClasspathOps

sealed abstract case class CliRunner(
sourceroot: AbsolutePath,
Expand Down Expand Up @@ -89,7 +89,11 @@ sealed abstract case class CliRunner(
val code = exitCode.get()
if (config.lint.reporter.hasErrors) {
ExitStatus.merge(ExitStatus.LinterError, code)
} else code
} else if (config.reporter.hasErrors) {
ExitStatus.merge(ExitStatus.UnexpectedError, code)
} else {
code
}
}
display.completedTask(msg, exit == ExitStatus.Ok)
display.stop()
Expand Down Expand Up @@ -315,7 +319,7 @@ object CliRunner {
.map(path => AbsolutePath(path)(common.workingPath))
.toList

def resolveClasspath: Configured[Classpath] =
def resolveClasspath: Configured[Classpath] = {
classpath match {
case Some(cp) =>
val paths = toClasspath(cp)
Expand All @@ -336,6 +340,7 @@ object CliRunner {
.notOk
}
}
}

val resolvedSourceroot: Configured[AbsolutePath] = {
val result = sourceroot
Expand All @@ -357,18 +362,37 @@ object CliRunner {
val result: Configured[SemanticdbIndex] = cachedDatabase.getOrElse {
(resolveClasspath |@| resolvedSourceroot).andThen {
case (classpath, root) =>
val patched = Database.load(classpath, Sourcepath(root))
val db =
EagerInMemorySemanticdbIndex(patched, Sourcepath(root), classpath)
if (verbose) {
common.err.println(
s"Loaded database with ${db.documents.length} documents.")
}
if (db.documents.nonEmpty) Ok(db)
else {
ConfError
.message("Missing SemanticdbIndex, found no semanticdb files!")
.notOk
val index = Database.load(classpath, Sourcepath(root))
val deps = dependencyClasspath.map(toClasspath).getOrElse(Nil)
val symbolTable = ClasspathOps.newSymbolTable(
classpath = Classpath(classpath.shallow ++ deps),
cacheDirectory = metacpCacheDir.map(AbsolutePath(_)),
parallel = !metacpNoPar,
out = common.out)
symbolTable match {
case None =>
ConfError
.message(
"Failed to load symbol table from --dependency-classpath")
.notOk
case Some(symtab) =>
val db = EagerInMemorySemanticdbIndex(
index,
Sourcepath(root),
classpath,
symtab
)
if (verbose) {
common.err.println(
s"Loaded database with ${db.documents.length} documents.")
}
if (db.documents.nonEmpty) Ok(db)
else {
ConfError
.message(
"Missing SemanticdbIndex, found no semanticdb files!")
.notOk
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,54 @@
package scalafix.internal.cli

import java.io.File
import java.io.OutputStream
import java.io.PrintStream
import org.langmeta.io.AbsolutePath
import scala.meta.Classpath
import scala.meta.metacp
import scalafix.internal.util.LazySymbolTable
import scalafix.internal.util.SymbolTable

object ClasspathOps {

def bootClasspath: Option[Classpath] = sys.props.collectFirst {
case (k, v) if k.endsWith(".boot.class.path") => Classpath(v)
}

val devNull = new PrintStream(new OutputStream {
override def write(b: Int): Unit = ()
})

/** Process classpath with metacp to build semanticdbs of global symbols. **/
def toMetaClasspath(
sclasspath: Classpath,
cacheDirectory: Option[AbsolutePath],
parallel: Boolean, // unused until we upgrade scalameta for https://github.com/scalameta/scalameta/pull/1474
out: PrintStream): Option[Classpath] = {
val withJDK = Classpath(
bootClasspath.fold(sclasspath.shallow)(_.shallow ::: sclasspath.shallow))
val default = metacp.Settings()
val settings = default
.withClasspath(withJDK)
.withScalaLibrarySynthetics(true)
.withCacheDir(cacheDirectory.getOrElse(default.cacheDir))
val reporter = metacp
.Reporter()
.withOut(devNull) // out prints classpath of proccessed classpath, which is not relevant for scalafix.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, this is unfortunate, given that we're calling process directly.

.withErr(out)
val mclasspath = scala.meta.cli.Metacp.process(settings, reporter)
mclasspath
}

def newSymbolTable(
classpath: Classpath,
cacheDirectory: Option[AbsolutePath] = None,
parallel: Boolean = true,
out: PrintStream = System.out): Option[SymbolTable] = {
toMetaClasspath(classpath, cacheDirectory, parallel, out)
.map(new LazySymbolTable(_))
}

def getCurrentClasspath: String = {
Thread.currentThread.getContextClassLoader match {
case url: java.net.URLClassLoader =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,30 @@ case class ScalafixOptions(
sourceroot: Option[String] = None,
@HelpMessage(
"java.io.File.pathSeparator separated list of directories or jars containing " +
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a list or a single directory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It remains a list, unchanged from the previous behavior of --classpath. I've renamed it back to --classpath and added more details about --dependency-classpath.

"'.semanticdb' files. The 'semanticdb' files are emitted by the " +
"META-INF/semanticdb/**/*.semanticdb files. SemanticDB files are emitted by the " +
"semanticdb-scalac compiler plugin and are necessary for semantic rules " +
"like ExplicitResultTypes to function."
)
@ValueDescription("entry1.jar:entry2.jar:target/scala-2.12/classes/")
classpath: Option[String] = None,
@HelpMessage(
"Same as --classpath except for dependencies that do not need to be compiled with SemanticDB. " +
"Must be accompanied with --classpath. " +
"This option is required for rules like ExplicitResultTypes to lookup symbol information from the classpath." +
"This option is processed with metacp and produced artifacts are globally cached using --metacp-cache-dir"
)
@ValueDescription("entry1.jar:entry2.jar:target/scala-2.12/classes/")
dependencyClasspath: Option[String] = None,
@HelpMessage(
"Global cache location to persist metacp artifacts produced by analyzing --dependency-classpath. " +
"The default location depends on the OS and is computed with https://github.com/soc/directories-jvm " +
"using the project name 'semanticdb'. " +
"On macOS the default cache directory is ~/Library/Caches/semanticdb. ")
metacpCacheDir: Option[String] = None,
@HelpMessage(
"Set this flag to disable parallel processing with metacp. " +
"Metacp uses the standard library parallel collections, which may enter deadlocks.")
metacpNoPar: Boolean = false,
@HelpMessage(
"Automatically infer --classpath starting from these directories. " +
"Ignored if --classpath is provided.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ package scala.meta.internal.scalafix
import scala.meta.Dialect
import scala.meta.Tree
import scala.meta.internal.trees.Origin
import scala.meta.dialects

object ScalafixScalametaHacks {
def dialect(language: String): Dialect = Dialect.standards(language)
def dialect(language: String): Dialect =
if (language == "Scala") dialects.Scala212
else if (language.isEmpty) dialects.Scala212
else Dialect.standards(language)
def resetOrigin(tree: Tree): Tree = tree.withOrigin(Origin.None)
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import scalafix.syntax._
import scalafix.util.TokenOps
import metaconfig.Conf
import metaconfig.Configured
import org.langmeta.internal.semanticdb.XtensionDenotationsInternal

case class ExplicitResultTypes(
index: SemanticdbIndex,
Expand Down Expand Up @@ -74,9 +75,16 @@ case class ExplicitResultTypes(
def defnType(defn: Defn): Option[(Type, Patch)] =
for {
name <- defnName(defn)
symbol <- name.symbol
typ <- symbol.resultType
} yield TypeSyntax.prettify(typ, ctx, config.unsafeShortenNames)
denot <- name.denotation
tpe <- denot.tpeInternal
// Skip existential types for now since they cause problems.
if !tpe.tag.isExistentialType
result <- TypeSyntax.prettify(
tpe,
ctx,
config.unsafeShortenNames,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this config passed? https://scalacenter.github.io/scalafix/docs/users/configuration shows how to add rules to the scalafix config, but does not show if it is possible to pass rule specific config.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's configuration for ExplicitResultTypes documented here https://scalacenter.github.io/scalafix/docs/rules/ExplicitResultTypes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn’t able to put that together from the docs for some reason but I get it now, thanks.

name.pos)
} yield result
import scala.meta._
def fix(defn: Defn, body: Term): Patch = {
val lst = ctx.tokenList
Expand Down
Loading