-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from scalacenter/topic/add-case-app
Add reproduced version of case-app inefficiency
- Loading branch information
Showing
9 changed files
with
368 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
integrations/src/main/scala/profiling/integrations/caseapp/CliOptions.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package profiling.integrations | ||
|
||
import java.nio.file.Path | ||
|
||
import caseapp.{ExtraName, HelpMessage, Recurse, ValueDescription} | ||
|
||
case class CliOptions( | ||
@ExtraName("c") | ||
@HelpMessage("File path to the bloop config directory.") | ||
@ValueDescription(".bloop") | ||
configDir: Option[Path] = None, | ||
@ExtraName("v") | ||
@HelpMessage("If set, print the about section at the beginning of the execution.") | ||
version: Boolean = false, | ||
@HelpMessage("If set, print out debugging information to stderr.") | ||
verbose: Boolean = false, | ||
@Recurse common: CommonOptions = CommonOptions.default, | ||
) | ||
|
||
object CliOptions { | ||
val default = CliOptions() | ||
} |
176 changes: 176 additions & 0 deletions
176
integrations/src/main/scala/profiling/integrations/caseapp/Commands.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
package profiling.integrations | ||
|
||
import java.nio.file.Path | ||
|
||
import caseapp.core.ArgParser | ||
import caseapp.{ArgsName, CommandName, ExtraName, HelpMessage, Hidden, Recurse} | ||
import caseapp.core.CommandMessages | ||
|
||
object Commands { | ||
|
||
/* sealed abstract class Mode(val name: String) | ||
/** The kind of items that should be returned for autocompletion */ | ||
object Mode { | ||
case object Commands extends Mode("commands") | ||
case object Projects extends Mode("projects") | ||
case object ProjectBoundCommands extends Mode("project-commands") | ||
case object Flags extends Mode("flags") | ||
case object Reporters extends Mode("reporters") | ||
case object Protocols extends Mode("protocols") | ||
case object TestsFQCN extends Mode("testsfqcn") | ||
case object MainsFQCN extends Mode("mainsfqcn") | ||
implicit val completionModeRead: ArgParser[Mode] = ??? | ||
} | ||
sealed abstract class BspProtocol(val name: String) | ||
object BspProtocol { | ||
case object Local extends BspProtocol("local") | ||
case object Tcp extends BspProtocol("tcp") | ||
implicit val bspProtocolRead: ArgParser[BspProtocol] = ??? | ||
} | ||
sealed abstract class ReporterKind(val name: String) | ||
case object ScalacReporter extends ReporterKind("scalac") | ||
case object BloopReporter extends ReporterKind("bloop")*/ | ||
|
||
sealed trait RawCommand { | ||
def cliOptions: CliOptions | ||
} | ||
|
||
sealed trait CompilingCommand extends RawCommand { | ||
//def project: String | ||
//def reporter: ReporterKind | ||
} | ||
|
||
/* sealed trait Tree[A] | ||
case class Leaf[A](value: A) extends Tree[A] | ||
case class Branch[A]( | ||
left: Tree[A], | ||
right: Tree[A] | ||
) extends Tree[A]*/ | ||
|
||
case class Help( | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends RawCommand | ||
|
||
case class Autocomplete( | ||
@Recurse cliOptions: CliOptions = CliOptions.default, | ||
//mode: Mode, | ||
//format: Format, | ||
/* command: Option[String], | ||
project: Option[String]*/ | ||
) extends RawCommand | ||
|
||
case class About( | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends RawCommand | ||
|
||
case class Projects( | ||
/* @ExtraName("dot") | ||
@HelpMessage("Print out a dot graph you can pipe into `dot`. By default, false.") | ||
dotGraph: Boolean = false,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends RawCommand | ||
|
||
case class Configure( | ||
/* @ExtraName("parallelism") | ||
@HelpMessage("Set the number of threads used for parallel compilation and test execution.") | ||
threads: Int = 4,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends RawCommand | ||
|
||
case class Clean( | ||
/* @ExtraName("p") | ||
@HelpMessage("The projects to clean.") | ||
project: List[String] = Nil, | ||
@HelpMessage("Do not run clean for dependencies. By default, false.") | ||
isolated: Boolean = false,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default, | ||
) extends RawCommand | ||
|
||
@CommandName("bsp") | ||
case class Bsp( | ||
/*/* @ExtraName("p") | ||
@HelpMessage("The connection protocol for the bsp server. By default, local.") | ||
protocol: BspProtocol = BspProtocol.Local,*/ | ||
@ExtraName("h") | ||
@HelpMessage("The server host for the bsp server (TCP only).") | ||
host: String = "127.0.0.1", | ||
@HelpMessage("The port for the bsp server (TCP only).") | ||
port: Int = 5101, | ||
@ExtraName("s") | ||
@HelpMessage("A path to a socket file to communicate through Unix sockets (local only).") | ||
socket: Option[Path] = None, | ||
@ExtraName("pn") | ||
@HelpMessage( | ||
"A path to a new existing socket file to communicate through Unix sockets (local only)." | ||
) | ||
pipeName: Option[String] = None,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends RawCommand | ||
|
||
case class Compile( | ||
/* @ExtraName("p") | ||
@HelpMessage("The project to compile (will be inferred from remaining cli args).") | ||
project: String = "", | ||
@HelpMessage("Compile the project incrementally. By default, true.") | ||
incremental: Boolean = true, | ||
/* @HelpMessage("Pick reporter to show compilation messages. By default, bloop's used.") | ||
reporter: ReporterKind = BloopReporter,*/ | ||
@ExtraName("w") | ||
@HelpMessage("Run the command when projects' source files change. By default, false.") | ||
watch: Boolean = false,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default, | ||
) extends CompilingCommand | ||
|
||
case class Test( | ||
/* @ExtraName("p") | ||
@HelpMessage("The project to test (will be inferred from remaining cli args).") | ||
project: String = "", | ||
@HelpMessage("Do not run tests for dependencies. By default, false.") | ||
isolated: Boolean = false, | ||
@ExtraName("o") | ||
@HelpMessage("The list of test suite filters to test for only.") | ||
only: List[String] = Nil, | ||
@HelpMessage("The arguments to pass in to the test framework.") | ||
args: List[String] = Nil, | ||
/* @HelpMessage("Pick reporter to show compilation messages. By default, bloop's used.") | ||
reporter: ReporterKind = BloopReporter,*/ | ||
@ExtraName("w") | ||
@HelpMessage("Run the command when projects' source files change. By default, false.") | ||
watch: Boolean = false,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends CompilingCommand | ||
|
||
case class Console( | ||
/* @ExtraName("p") | ||
@HelpMessage("The project to run the console at (will be inferred from remaining cli args).") | ||
project: String = "", | ||
/* @HelpMessage("Pick reporter to show compilation messages. By default, bloop's used.") | ||
reporter: ReporterKind = BloopReporter,*/ | ||
@HelpMessage("Start up the console compiling only the target project's dependencies.") | ||
excludeRoot: Boolean = false,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends CompilingCommand | ||
|
||
case class Run( | ||
/* @ExtraName("p") | ||
@HelpMessage("The project to run (will be inferred from remaining cli args).") | ||
project: String = "", | ||
@ExtraName("m") | ||
@HelpMessage("The main class to run. Leave unset to let bloop select automatically.") | ||
main: Option[String] = None, | ||
/* @HelpMessage("Pick reporter to show compilation messages. By default, bloop's used.") | ||
reporter: ReporterKind = BloopReporter,*/ | ||
@HelpMessage("The arguments to pass in to the main class.") | ||
args: List[String] = Nil, | ||
@ExtraName("w") | ||
@HelpMessage("If set, run the command whenever projects' source files change.") | ||
watch: Boolean = false,*/ | ||
@Recurse cliOptions: CliOptions = CliOptions.default | ||
) extends CompilingCommand | ||
} |
50 changes: 50 additions & 0 deletions
50
integrations/src/main/scala/profiling/integrations/caseapp/CommonOptions.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package profiling.integrations | ||
|
||
import java.io.{InputStream, PrintStream} | ||
import java.util.Properties | ||
|
||
import caseapp.Hidden | ||
|
||
/** | ||
* Describes the common options for any command or CLI operation. | ||
* | ||
* They exist for two purposes: testing and nailgun. In both cases we | ||
* need a precise handling of these parameters because they change | ||
* depending on the environment we're running on. | ||
* | ||
* They are hidden because they are optional. | ||
*/ | ||
case class CommonOptions( | ||
@Hidden workingDirectory: String = System.getProperty("user.dir"), | ||
@Hidden out: PrintStream = System.out, | ||
@Hidden in: InputStream = System.in, | ||
@Hidden err: PrintStream = System.err, | ||
@Hidden ngout: PrintStream = System.out, | ||
@Hidden ngerr: PrintStream = System.err | ||
) | ||
|
||
object CommonOptions { | ||
final val default = CommonOptions() | ||
|
||
// Our own version of properties in which we override `toString` | ||
final class PrettyProperties extends Properties { | ||
override def toString: String = synchronized { | ||
super.keySet().toArray.map(_.toString).mkString(", ") | ||
} | ||
} | ||
|
||
object PrettyProperties { | ||
def from(p: Properties): PrettyProperties = { | ||
val pp = new PrettyProperties() | ||
pp.putAll(p) | ||
pp | ||
} | ||
} | ||
|
||
final lazy val currentEnv: PrettyProperties = { | ||
import scala.collection.JavaConverters._ | ||
System.getenv().asScala.foldLeft(new PrettyProperties()) { | ||
case (props, (key, value)) => props.setProperty(key, value); props | ||
} | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
integrations/src/main/scala/profiling/integrations/caseapp/Parsers.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
package profiling.integrations | ||
|
||
import java.io.{InputStream, PrintStream} | ||
import java.nio.file.{Path, Paths} | ||
|
||
import CommonOptions.PrettyProperties | ||
import caseapp.{CaseApp, CommandParser} | ||
import caseapp.util.{Implicit, AnnotationList} | ||
import caseapp.core.{ArgParser, DefaultBaseCommand, HListParser, Parser, Default} | ||
import shapeless.{Annotations, Coproduct, LabelledGeneric, Strict, Generic, HList} | ||
import caseapp.{Name, ValueDescription, HelpMessage, Hidden, Recurse} | ||
|
||
import scala.util.Try | ||
|
||
trait CachedImplicits { | ||
implicit val inputStreamRead: ArgParser[InputStream] = | ||
ArgParser.instance[InputStream]("stdin")(_ => Right(System.in)) | ||
implicit val printStreamRead: ArgParser[PrintStream] = | ||
ArgParser.instance[PrintStream]("stdout")(_ => Right(System.out)) | ||
|
||
implicit val pathParser: ArgParser[Path] = ArgParser.instance("A filepath parser") { | ||
case supposedPath: String => | ||
val toPath = Try(Paths.get(supposedPath)).toEither | ||
toPath.left.map(t => s"The provided path ${supposedPath} is not valid: '${t.getMessage()}'.") | ||
} | ||
|
||
implicit val propertiesParser: ArgParser[PrettyProperties] = { | ||
ArgParser.instance("A properties parser") { | ||
case whatever => Left("You cannot pass in properties through the command line.") | ||
} | ||
} | ||
|
||
import shapeless.{HNil, CNil, :+:, ::} | ||
implicit val implicitHNil: Implicit[HNil] = Implicit.hnil | ||
implicit val implicitNone: Implicit[None.type] = Implicit.instance(None) | ||
implicit val implicitNoneCnil: Implicit[None.type :+: CNil] = | ||
Implicit.instance(Coproduct(None)) | ||
|
||
implicit val implicitOptionDefaultString: Implicit[Option[Default[String]]] = | ||
Implicit.instance(Some(caseapp.core.Defaults.string)) | ||
|
||
implicit val implicitOptionDefaultInt: Implicit[Option[Default[Int]]] = | ||
Implicit.instance(Some(caseapp.core.Defaults.int)) | ||
|
||
implicit val implicitOptionDefaultBoolean: Implicit[Option[Default[Boolean]]] = | ||
Implicit.instance(Some(caseapp.core.Defaults.boolean)) | ||
|
||
implicit val implicitDefaultBoolean: Implicit[Default[Boolean]] = | ||
Implicit.instance(caseapp.core.Defaults.boolean) | ||
|
||
implicit val implicitOptionDefaultOptionPath: Implicit[Option[Default[Option[Path]]]] = | ||
Implicit.instance(None) | ||
|
||
implicit val implicitOptionDefaultPrintStream: Implicit[Option[Default[PrintStream]]] = | ||
Implicit.instance(Some(Default.instance[PrintStream](System.out))) | ||
|
||
implicit val implicitOptionDefaultInputStream: Implicit[Option[Default[InputStream]]] = | ||
Implicit.instance(Some(Default.instance[InputStream](System.in))) | ||
} | ||
|
||
object Parsers extends CachedImplicits { | ||
|
||
import shapeless.{the, HNil, ::} | ||
|
||
implicit val labelledGenericCommonOptions: LabelledGeneric.Aux[CommonOptions, _] = LabelledGeneric.materializeProduct | ||
implicit val commonOptionsParser: Parser.Aux[CommonOptions, _] = Parser.generic | ||
implicit val labelledGenericCliOptions: LabelledGeneric.Aux[CliOptions, _] = LabelledGeneric.materializeProduct | ||
implicit val cliOptionsParser: Parser.Aux[CliOptions, _] = Parser.generic | ||
|
||
implicit val strictAutocompleteParser: Parser.Aux[Commands.Autocomplete, _] = Parser.generic | ||
implicit val strictAboutParser: Parser.Aux[Commands.About, _] = Parser.generic | ||
implicit val strictBspParser: Parser.Aux[Commands.Bsp, _] = Parser.generic | ||
implicit val strictCleanParser: Parser.Aux[Commands.Clean, _] = Parser.generic | ||
implicit val strictCompileParser: Parser.Aux[Commands.Compile, _] = Parser.generic | ||
implicit val strictConfigureParser: Parser.Aux[Commands.Configure, _] = Parser.generic | ||
implicit val strictConsoleParser: Parser.Aux[Commands.Console, _] = Parser.generic | ||
implicit val strictHelpParser: Parser.Aux[Commands.Help, _] = Parser.generic | ||
implicit val strictProjectsParser: Parser.Aux[Commands.Projects, _] = Parser.generic | ||
implicit val strictRunParser: Parser.Aux[Commands.Run, _] = Parser.generic | ||
implicit val strictTestParser: Parser.Aux[Commands.Test, _] = Parser.generic | ||
|
||
val BaseMessages: caseapp.core.Messages[DefaultBaseCommand] = | ||
caseapp.core.Messages[DefaultBaseCommand] | ||
val CommandsMessages: caseapp.core.CommandsMessages[Commands.RawCommand] = | ||
implicitly[caseapp.core.CommandsMessages[Commands.RawCommand]] | ||
val CommandsParser: CommandParser[Commands.RawCommand] = | ||
implicitly[caseapp.core.CommandParser[Commands.RawCommand]] | ||
} | ||
|
||
object Main extends App { | ||
import Parsers._ | ||
/* assert(CommandsParser != null) | ||
assert(CommandsMessages != null)*/ | ||
println("Hello World!") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.