From 8484d257acd96526c45cfff2a668eb3de1d6e40b Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Mon, 24 Jun 2024 22:01:49 +0700 Subject: [PATCH 01/14] added directives and preprocessing for the directives --- .../src/main/scala/scala/build/Project.scala | 23 ++++++++++++++- .../DirectivesPreprocessingUtils.scala | 1 + .../directives/SourceGenerator.scala | 29 +++++++++++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index f6d793be82..bd23a5538c 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -50,6 +50,26 @@ final case class Project( bridgeJars = scalaCompiler0.bridgeJarsOpt.map(_.map(_.toNIO).toList) ) } + + val sourceGen: BloopConfig.SourceGenerator = { + val command = "/Users/kiki/Kerja/scala-cli/testing-a/source-generator.py" + + + val sourceGlobs = BloopConfig.SourcesGlobs( + (os.root / "Users" / "kiki" / "Kerja" / "scala-cli" / "testing-a" / "generator-inputs").toNIO, + None, + List("glob:test.in"), + Nil + ) + + BloopConfig.SourceGenerator( + List(sourceGlobs), + (os.root / "Users" / "kiki" / "Kerja" / "scala-cli" / "testing-a" / "source-generator-a").toNIO, + List("python3",command) + // Nil + ) + } + baseBloopProject( projectName, directory.toNIO, @@ -65,7 +85,8 @@ final case class Project( platform = Some(platform), `scala` = scalaConfigOpt, java = Some(BloopConfig.Java(javacOptions)), - resolution = resolution + resolution = resolution, + sourceGenerators = Some(List(sourceGen)) ) } diff --git a/modules/build/src/main/scala/scala/build/preprocessing/directives/DirectivesPreprocessingUtils.scala b/modules/build/src/main/scala/scala/build/preprocessing/directives/DirectivesPreprocessingUtils.scala index 1201bf3b71..da5114cfa3 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/directives/DirectivesPreprocessingUtils.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/directives/DirectivesPreprocessingUtils.scala @@ -30,6 +30,7 @@ object DirectivesPreprocessingUtils { directives.ScalaJs.handler, directives.ScalaNative.handler, directives.ScalaVersion.handler, + directives.SourceGenerator.handler, directives.Sources.handler, directives.Tests.handler ).map(_.mapE(_.buildOptions)) diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala new file mode 100644 index 0000000000..bbf25dafe2 --- /dev/null +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -0,0 +1,29 @@ +package scala.build.preprocessing.directives + +import scala.build.directives.* +import scala.build.errors.BuildException +import scala.build.options.BuildOptions +import scala.cli.commands.SpecificationLevel + +@DirectiveExamples("//> using generator") +@DirectiveUsage( + "//> using generator", + "`//> using generator`" +) +@DirectiveDescription("Generate code using Source Generator") +@DirectiveLevel(SpecificationLevel.EXPERIMENTAL) +final case class SourceGenerator ( + placeHolderGenerator: Boolean = false +) extends HasBuildOptions { + def buildOptions: Either[BuildException, BuildOptions] = { + val buildOpt = BuildOptions( + useBuildServer = Some(true) + ) + Right(buildOpt) + } +} + + +object SourceGenerator { + val handler: DirectiveHandler[SourceGenerator] = DirectiveHandler.derive +} From 315e51601a260ad802f4c0c44af37124bb60d111 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:30:26 +0700 Subject: [PATCH 02/14] feat: Hardcoded Derivatives WIP --- modules/build/src/main/scala/scala/build/Build.scala | 5 ++++- modules/build/src/main/scala/scala/build/Project.scala | 7 +++---- .../build/preprocessing/directives/SourceGenerator.scala | 7 ++----- .../src/main/scala/scala/build/options/BuildOptions.scala | 3 ++- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Build.scala b/modules/build/src/main/scala/scala/build/Build.scala index 332a7da206..a939458cc8 100644 --- a/modules/build/src/main/scala/scala/build/Build.scala +++ b/modules/build/src/main/scala/scala/build/Build.scala @@ -866,6 +866,8 @@ object Build { if (options.useBuildServer.getOrElse(true)) None else releaseFlag(options, compilerJvmVersionOpt, logger).map(_.toString) + val hardcodedSource = options.generateSource + val scalaCompilerParamsOpt = artifacts.scalaOpt match { case Some(scalaArtifacts) => val params = value(options.scalaParams).getOrElse { @@ -1014,7 +1016,8 @@ object Build { resourceDirs = sources.resourceDirs, scope = scope, javaHomeOpt = Option(options.javaHomeLocation().value), - javacOptions = javacOptions + javacOptions = javacOptions, + generateSource = hardcodedSource ) project } diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index bd23a5538c..d0284a3fb8 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -28,7 +28,8 @@ final case class Project( resourceDirs: Seq[os.Path], javaHomeOpt: Option[os.Path], scope: Scope, - javacOptions: List[String] + javacOptions: List[String], + generateSource: Option[Boolean] ) { import Project._ @@ -53,8 +54,6 @@ final case class Project( val sourceGen: BloopConfig.SourceGenerator = { val command = "/Users/kiki/Kerja/scala-cli/testing-a/source-generator.py" - - val sourceGlobs = BloopConfig.SourcesGlobs( (os.root / "Users" / "kiki" / "Kerja" / "scala-cli" / "testing-a" / "generator-inputs").toNIO, None, @@ -86,7 +85,7 @@ final case class Project( `scala` = scalaConfigOpt, java = Some(BloopConfig.Java(javacOptions)), resolution = resolution, - sourceGenerators = Some(List(sourceGen)) + sourceGenerators = if (generateSource.getOrElse(false)) Some(List(sourceGen)) else None ) } diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index bbf25dafe2..2e9682a313 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -6,10 +6,7 @@ import scala.build.options.BuildOptions import scala.cli.commands.SpecificationLevel @DirectiveExamples("//> using generator") -@DirectiveUsage( - "//> using generator", - "`//> using generator`" -) +@DirectiveUsage("//> using generator", "`//> using generator`") @DirectiveDescription("Generate code using Source Generator") @DirectiveLevel(SpecificationLevel.EXPERIMENTAL) final case class SourceGenerator ( @@ -17,7 +14,7 @@ final case class SourceGenerator ( ) extends HasBuildOptions { def buildOptions: Either[BuildException, BuildOptions] = { val buildOpt = BuildOptions( - useBuildServer = Some(true) + generateSource = Some(placeHolderGenerator) ) Right(buildOpt) } diff --git a/modules/options/src/main/scala/scala/build/options/BuildOptions.scala b/modules/options/src/main/scala/scala/build/options/BuildOptions.scala index 695022ec04..4dd2c6b9d2 100644 --- a/modules/options/src/main/scala/scala/build/options/BuildOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/BuildOptions.scala @@ -46,7 +46,8 @@ final case class BuildOptions( testOptions: TestOptions = TestOptions(), notForBloopOptions: PostBuildOptions = PostBuildOptions(), sourceGeneratorOptions: SourceGeneratorOptions = SourceGeneratorOptions(), - useBuildServer: Option[Boolean] = None + useBuildServer: Option[Boolean] = None, + generateSource: Option[Boolean] = None ) { import BuildOptions.JavaHomeInfo From 5b2c47c43a3255b2c23715e40b529b082ef4218a Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:30:37 +0700 Subject: [PATCH 03/14] experiment test --- .../scala/build/preprocessing/DirectivesPreprocessor.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala index 3006196cf4..5742d01d7d 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala @@ -78,6 +78,9 @@ case class DirectivesPreprocessor( ) } + for (vals <- unusedDirectives) println(s"preprocess- ${vals.toString} ${vals.key}") + + val (optionsWithActualRequirements, optionsWithEmptyRequirements) = buildOptionsWithTargetRequirements.global.partition(_.requirements.nonEmpty) val summedOptionsWithNoRequirements = @@ -121,6 +124,7 @@ case class DirectivesPreprocessor( logger: Logger ): Either[BuildException, ProcessedDirective[T]] = if !allowRestrictedFeatures && (handler.isRestricted || handler.isExperimental) then + print("Reached Error Flow") Left(DirectiveErrors( ::(WarningMessages.powerDirectiveUsedInSip(scopedDirective, handler), Nil), Seq(scopedDirective.directive.position(scopedDirective.maybePath)) @@ -128,6 +132,7 @@ case class DirectivesPreprocessor( else if handler.isExperimental && !shouldSuppressExperimentalFeatures then logger.experimentalWarning(scopedDirective.directive.toString, FeatureType.Directive) + print("Reached Here") handler.handleValues(scopedDirective, logger) val handlersMap = handlers @@ -137,6 +142,7 @@ case class DirectivesPreprocessor( .toMap val unused = directives.filter(d => !handlersMap.contains(d.key)) + for (vals <- unused) println(s"${vals.toString} ${vals.key}") val res = directives .iterator From 86a9a4e36ff61e49120c6de0c3cae57d7e5317af Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Sat, 6 Jul 2024 16:03:15 +0700 Subject: [PATCH 04/14] feat: working directive --- .../src/main/scala/scala/build/Build.scala | 2 +- .../src/main/scala/scala/build/Project.scala | 60 +++++++++++++------ .../DirectivesPreprocessor.scala | 2 - .../directives/SourceGenerator.scala | 40 +++++++++---- .../scala/build/options/BuildOptions.scala | 1 - .../scala/build/options/SourceGenerator.scala | 36 +++++++++++ .../options/SourceGeneratorOptions.scala | 3 +- 7 files changed, 109 insertions(+), 35 deletions(-) create mode 100644 modules/options/src/main/scala/scala/build/options/SourceGenerator.scala diff --git a/modules/build/src/main/scala/scala/build/Build.scala b/modules/build/src/main/scala/scala/build/Build.scala index a939458cc8..9999ec31c5 100644 --- a/modules/build/src/main/scala/scala/build/Build.scala +++ b/modules/build/src/main/scala/scala/build/Build.scala @@ -866,7 +866,7 @@ object Build { if (options.useBuildServer.getOrElse(true)) None else releaseFlag(options, compilerJvmVersionOpt, logger).map(_.toString) - val hardcodedSource = options.generateSource + val hardcodedSource = options.sourceGeneratorOptions.generatorConfig val scalaCompilerParamsOpt = artifacts.scalaOpt match { case Some(scalaArtifacts) => diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index d0284a3fb8..0cf38ba500 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -10,7 +10,7 @@ import java.nio.charset.StandardCharsets import java.nio.file.Path import java.util.Arrays -import scala.build.options.{ScalacOpt, Scope, ShadowingSeq} +import scala.build.options.{GeneratorConfig, ScalacOpt, Scope, ShadowingSeq} final case class Project( workspace: os.Path, @@ -29,7 +29,7 @@ final case class Project( javaHomeOpt: Option[os.Path], scope: Scope, javacOptions: List[String], - generateSource: Option[Boolean] + generateSource: Option[GeneratorConfig] ) { import Project._ @@ -52,22 +52,48 @@ final case class Project( ) } - val sourceGen: BloopConfig.SourceGenerator = { - val command = "/Users/kiki/Kerja/scala-cli/testing-a/source-generator.py" - val sourceGlobs = BloopConfig.SourcesGlobs( - (os.root / "Users" / "kiki" / "Kerja" / "scala-cli" / "testing-a" / "generator-inputs").toNIO, - None, - List("glob:test.in"), - Nil - ) + val sourceGen0: Option[List[BloopConfig.SourceGenerator]] = + generateSource.map(config => + println(os.pwd) + println(config.commandFilePath) + println(config.inputDir) + println(config.glob) + val command0 = s"${os.pwd}/testing-a/${config.commandFilePath}" + val sourceGlobs0 = BloopConfig.SourcesGlobs( + (os.pwd / "testing-a" / config.inputDir).toNIO, + None, + config.glob, + Nil + ) + + val sourceGen = BloopConfig.SourceGenerator( + List(sourceGlobs0), + (os.pwd / "testing-a" / "source-generator-output").toNIO, + List("python3", command0) + // Nil + ) - BloopConfig.SourceGenerator( - List(sourceGlobs), - (os.root / "Users" / "kiki" / "Kerja" / "scala-cli" / "testing-a" / "source-generator-a").toNIO, - List("python3",command) - // Nil + List(sourceGen) ) - } + + // val sourceGen: BloopConfig.SourceGenerator = { + // val command = s"${os.pwd}/${generateSource.commandFilePath}" + // val sourceGlobs = BloopConfig.SourcesGlobs( + // (os.pwd / generateSource.inputDir).toNIO, + // None, + // List(generateSource.glob), + // Nil + // ) + + // BloopConfig.SourceGenerator( + // List(sourceGlobs), + // (os.pwd / "testing-a" / "source-generator-output").toNIO, + // List("python3", command) + // // Nil + // ) + // } + + baseBloopProject( projectName, @@ -85,7 +111,7 @@ final case class Project( `scala` = scalaConfigOpt, java = Some(BloopConfig.Java(javacOptions)), resolution = resolution, - sourceGenerators = if (generateSource.getOrElse(false)) Some(List(sourceGen)) else None + sourceGenerators = sourceGen0 ) } diff --git a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala index 5742d01d7d..40047f564b 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala @@ -124,7 +124,6 @@ case class DirectivesPreprocessor( logger: Logger ): Either[BuildException, ProcessedDirective[T]] = if !allowRestrictedFeatures && (handler.isRestricted || handler.isExperimental) then - print("Reached Error Flow") Left(DirectiveErrors( ::(WarningMessages.powerDirectiveUsedInSip(scopedDirective, handler), Nil), Seq(scopedDirective.directive.position(scopedDirective.maybePath)) @@ -132,7 +131,6 @@ case class DirectivesPreprocessor( else if handler.isExperimental && !shouldSuppressExperimentalFeatures then logger.experimentalWarning(scopedDirective.directive.toString, FeatureType.Directive) - print("Reached Here") handler.handleValues(scopedDirective, logger) val handlersMap = handlers diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index 2e9682a313..73f1b9776f 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -1,25 +1,39 @@ package scala.build.preprocessing.directives -import scala.build.directives.* -import scala.build.errors.BuildException -import scala.build.options.BuildOptions import scala.cli.commands.SpecificationLevel +import scala.build.directives.* +import scala.build.EitherCps.{either, value} +import scala.build.Ops.* +import scala.build.errors.{BuildException, CompositeBuildException} +import scala.build.options.{BuildOptions, SourceGeneratorOptions, GeneratorConfig} +import scala.build.options.GeneratorConfig +import scala.build.{Positioned, options} -@DirectiveExamples("//> using generator") -@DirectiveUsage("//> using generator", "`//> using generator`") +@DirectiveUsage("//> using sourceGenerator", "`//> using sourceGenerator`") @DirectiveDescription("Generate code using Source Generator") @DirectiveLevel(SpecificationLevel.EXPERIMENTAL) -final case class SourceGenerator ( - placeHolderGenerator: Boolean = false +final case class SourceGenerator( + sourceGenerator: Option[Positioned[String]] = None ) extends HasBuildOptions { - def buildOptions: Either[BuildException, BuildOptions] = { - val buildOpt = BuildOptions( - generateSource = Some(placeHolderGenerator) - ) - Right(buildOpt) + def buildOptions: Either[BuildException, BuildOptions] = either { + val maybeGenerateSource = sourceGenerator + .map(GeneratorConfig.parse) + .sequence + + // val buildOpt = BuildOptions( + // generateSource = Some(generateSource0) + // ) + + val generateSource = maybeGenerateSource match { + case Left(buildException) => throw buildException + case Right(config) => config } -} + BuildOptions(sourceGeneratorOptions = + SourceGeneratorOptions(generatorConfig = generateSource) + ) + } +} object SourceGenerator { val handler: DirectiveHandler[SourceGenerator] = DirectiveHandler.derive diff --git a/modules/options/src/main/scala/scala/build/options/BuildOptions.scala b/modules/options/src/main/scala/scala/build/options/BuildOptions.scala index 4dd2c6b9d2..e8d34db3ab 100644 --- a/modules/options/src/main/scala/scala/build/options/BuildOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/BuildOptions.scala @@ -47,7 +47,6 @@ final case class BuildOptions( notForBloopOptions: PostBuildOptions = PostBuildOptions(), sourceGeneratorOptions: SourceGeneratorOptions = SourceGeneratorOptions(), useBuildServer: Option[Boolean] = None, - generateSource: Option[Boolean] = None ) { import BuildOptions.JavaHomeInfo diff --git a/modules/options/src/main/scala/scala/build/options/SourceGenerator.scala b/modules/options/src/main/scala/scala/build/options/SourceGenerator.scala new file mode 100644 index 0000000000..d80d857d44 --- /dev/null +++ b/modules/options/src/main/scala/scala/build/options/SourceGenerator.scala @@ -0,0 +1,36 @@ +package scala.build.options + +import scala.build.Positioned +import scala.build.errors.{BuildException, MalformedInputError} + +final case class GeneratorConfig( + inputDir: String, + glob: List[String], + commandFilePath: String +) + +object GeneratorConfig { + + def parse(input: Positioned[String]): Either[BuildException, GeneratorConfig] = + input.value.split("\\|", 3) match { + case Array(inputDir, glob, commandFilePath) => + Right(GeneratorConfig(inputDir, List(glob), commandFilePath)) + case _ => + Left( + new MalformedInputError( + "sourceGenerator", + input.value, + "inputDir|glob|commandFilePath", + input.positions + ) + ) + } + + // def formatPath( + // inputDir: String, + // glob: String, + // commandFilePath: String, + // ): GeneratorConfig = { + + // } +} diff --git a/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala b/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala index fca0cf7967..10177f94ff 100644 --- a/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala @@ -3,7 +3,8 @@ package scala.build.options final case class SourceGeneratorOptions( useBuildInfo: Option[Boolean] = None, projectVersion: Option[String] = None, - computeVersion: Option[ComputeVersion] = None + computeVersion: Option[ComputeVersion] = None, + generatorConfig: Option[GeneratorConfig] = None ) object SourceGeneratorOptions { From da562787d2c6d81646468c075e05383cbc07789e Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Fri, 12 Jul 2024 23:49:00 +0700 Subject: [PATCH 05/14] working with ${.} unclean --- .../src/main/scala/scala/build/Project.scala | 16 +++++++++------- .../build/directives/DirectiveValueParser.scala | 1 + .../directives/SourceGenerator.scala | 10 ++++------ 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index 0cf38ba500..13d2f8cb66 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -7,7 +7,7 @@ import coursier.core.Classifier import java.io.ByteArrayOutputStream import java.nio.charset.StandardCharsets -import java.nio.file.Path +import java.nio.file.{Path, Paths} import java.util.Arrays import scala.build.options.{GeneratorConfig, ScalacOpt, Scope, ShadowingSeq} @@ -54,13 +54,14 @@ final case class Project( val sourceGen0: Option[List[BloopConfig.SourceGenerator]] = generateSource.map(config => - println(os.pwd) - println(config.commandFilePath) - println(config.inputDir) - println(config.glob) - val command0 = s"${os.pwd}/testing-a/${config.commandFilePath}" + println(s"Input Directory => ${config.inputDir}") + println(s"Globber => ${config.glob}") + println(s"Command File Path => ${config.commandFilePath}") + // val command0 = s"${os.pwd}/testing-a/${config.commandFilePath}" + val command0 = config.commandFilePath val sourceGlobs0 = BloopConfig.SourcesGlobs( - (os.pwd / "testing-a" / config.inputDir).toNIO, + // (os.pwd / "testing-a" / config.inputDir).toNIO, + Paths.get(config.inputDir), None, config.glob, Nil @@ -69,6 +70,7 @@ final case class Project( val sourceGen = BloopConfig.SourceGenerator( List(sourceGlobs0), (os.pwd / "testing-a" / "source-generator-output").toNIO, + // Paths.get(config.inputDir), List("python3", command0) // Nil ) diff --git a/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala b/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala index 866653ecaa..c25465fcff 100644 --- a/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala +++ b/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala @@ -138,6 +138,7 @@ object DirectiveValueParser { given DirectiveSingleValueParser[String] = (key, value, scopePath, path) => value.asString.toRight { + println("do we get here?") val pos = value.position(path) new MalformedDirectiveError( message = diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index 73f1b9776f..bf3ed88548 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -13,17 +13,15 @@ import scala.build.{Positioned, options} @DirectiveDescription("Generate code using Source Generator") @DirectiveLevel(SpecificationLevel.EXPERIMENTAL) final case class SourceGenerator( - sourceGenerator: Option[Positioned[String]] = None + sourceGenerator: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = DirectiveValueParser.WithScopePath.empty(None) ) extends HasBuildOptions { def buildOptions: Either[BuildException, BuildOptions] = either { - val maybeGenerateSource = sourceGenerator + val sourceGen = sourceGenerator.value + + val maybeGenerateSource = sourceGen .map(GeneratorConfig.parse) .sequence - // val buildOpt = BuildOptions( - // generateSource = Some(generateSource0) - // ) - val generateSource = maybeGenerateSource match { case Left(buildException) => throw buildException case Right(config) => config From 28cf22a9a4328f4a1ca013ffb9b6def4acc449cc Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Sun, 14 Jul 2024 19:59:21 +0700 Subject: [PATCH 06/14] supports multi-line directives for Source Generator --- .../src/main/scala/scala/build/Build.scala | 2 +- .../src/main/scala/scala/build/Project.scala | 62 ++++++------------- .../directives/SourceGenerator.scala | 34 +++++----- ...eGenerator.scala => GeneratorConfig.scala} | 15 ++--- .../options/SourceGeneratorOptions.scala | 2 +- 5 files changed, 41 insertions(+), 74 deletions(-) rename modules/options/src/main/scala/scala/build/options/{SourceGenerator.scala => GeneratorConfig.scala} (70%) diff --git a/modules/build/src/main/scala/scala/build/Build.scala b/modules/build/src/main/scala/scala/build/Build.scala index 9999ec31c5..0eed6e87a8 100644 --- a/modules/build/src/main/scala/scala/build/Build.scala +++ b/modules/build/src/main/scala/scala/build/Build.scala @@ -1017,7 +1017,7 @@ object Build { scope = scope, javaHomeOpt = Option(options.javaHomeLocation().value), javacOptions = javacOptions, - generateSource = hardcodedSource + generateSource = Option(sourceGeneratorConfig) ) project } diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index 13d2f8cb66..075ee63222 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -29,7 +29,7 @@ final case class Project( javaHomeOpt: Option[os.Path], scope: Scope, javacOptions: List[String], - generateSource: Option[GeneratorConfig] + generateSource: Option[Seq[GeneratorConfig]] ) { import Project._ @@ -52,51 +52,25 @@ final case class Project( ) } - val sourceGen0: Option[List[BloopConfig.SourceGenerator]] = - generateSource.map(config => - println(s"Input Directory => ${config.inputDir}") - println(s"Globber => ${config.glob}") - println(s"Command File Path => ${config.commandFilePath}") - // val command0 = s"${os.pwd}/testing-a/${config.commandFilePath}" - val command0 = config.commandFilePath - val sourceGlobs0 = BloopConfig.SourcesGlobs( - // (os.pwd / "testing-a" / config.inputDir).toNIO, - Paths.get(config.inputDir), - None, - config.glob, - Nil - ) - - val sourceGen = BloopConfig.SourceGenerator( - List(sourceGlobs0), - (os.pwd / "testing-a" / "source-generator-output").toNIO, - // Paths.get(config.inputDir), - List("python3", command0) - // Nil - ) + val sourceGenerator: Option[List[BloopConfig.SourceGenerator]] = + generateSource.map(configs => + configs.map { config => + val command0 = config.commandFilePath + val sourceGlobs0 = BloopConfig.SourcesGlobs( + Paths.get(config.inputDir), + None, + config.glob, + Nil + ) - List(sourceGen) + BloopConfig.SourceGenerator( + List(sourceGlobs0), + (config.outputPath / "source-generator-output").toNIO, + List("python3", command0) + ) + }.toList ) - // val sourceGen: BloopConfig.SourceGenerator = { - // val command = s"${os.pwd}/${generateSource.commandFilePath}" - // val sourceGlobs = BloopConfig.SourcesGlobs( - // (os.pwd / generateSource.inputDir).toNIO, - // None, - // List(generateSource.glob), - // Nil - // ) - - // BloopConfig.SourceGenerator( - // List(sourceGlobs), - // (os.pwd / "testing-a" / "source-generator-output").toNIO, - // List("python3", command) - // // Nil - // ) - // } - - - baseBloopProject( projectName, directory.toNIO, @@ -113,7 +87,7 @@ final case class Project( `scala` = scalaConfigOpt, java = Some(BloopConfig.Java(javacOptions)), resolution = resolution, - sourceGenerators = sourceGen0 + sourceGenerators = sourceGenerator ) } diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index bf3ed88548..a2d60ee183 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -13,26 +13,26 @@ import scala.build.{Positioned, options} @DirectiveDescription("Generate code using Source Generator") @DirectiveLevel(SpecificationLevel.EXPERIMENTAL) final case class SourceGenerator( - sourceGenerator: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = DirectiveValueParser.WithScopePath.empty(None) + sourceGenerator: DirectiveValueParser.WithScopePath[List[Positioned[String]]] = + DirectiveValueParser.WithScopePath.empty(Nil) ) extends HasBuildOptions { - def buildOptions: Either[BuildException, BuildOptions] = either { - val sourceGen = sourceGenerator.value - - val maybeGenerateSource = sourceGen - .map(GeneratorConfig.parse) - .sequence - - val generateSource = maybeGenerateSource match { - case Left(buildException) => throw buildException - case Right(config) => config - } - - BuildOptions(sourceGeneratorOptions = - SourceGeneratorOptions(generatorConfig = generateSource) - ) - } + def buildOptions: Either[BuildException, BuildOptions] = + SourceGenerator.buildOptions(sourceGenerator) } object SourceGenerator { val handler: DirectiveHandler[SourceGenerator] = DirectiveHandler.derive + def buildOptions(sourceGenerator: DirectiveValueParser.WithScopePath[List[Positioned[String]]]) + : Either[BuildException, BuildOptions] = { + val sourceGenValue = sourceGenerator.value + sourceGenValue + .map(config => GeneratorConfig.parse(config, sourceGenerator.scopePath.subPath)) + .sequence + .left.map(CompositeBuildException(_)) + .map { configs => + BuildOptions(sourceGeneratorOptions = + SourceGeneratorOptions(generatorConfig = configs) + ) + } + } } diff --git a/modules/options/src/main/scala/scala/build/options/SourceGenerator.scala b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala similarity index 70% rename from modules/options/src/main/scala/scala/build/options/SourceGenerator.scala rename to modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala index d80d857d44..5dc7bf606a 100644 --- a/modules/options/src/main/scala/scala/build/options/SourceGenerator.scala +++ b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala @@ -6,15 +6,16 @@ import scala.build.errors.{BuildException, MalformedInputError} final case class GeneratorConfig( inputDir: String, glob: List[String], - commandFilePath: String + commandFilePath: String, + outputPath: os.SubPath ) object GeneratorConfig { - def parse(input: Positioned[String]): Either[BuildException, GeneratorConfig] = + def parse(input: Positioned[String], output: os.SubPath): Either[BuildException, GeneratorConfig] = input.value.split("\\|", 3) match { case Array(inputDir, glob, commandFilePath) => - Right(GeneratorConfig(inputDir, List(glob), commandFilePath)) + Right(GeneratorConfig(inputDir, List(glob), commandFilePath, output)) case _ => Left( new MalformedInputError( @@ -25,12 +26,4 @@ object GeneratorConfig { ) ) } - - // def formatPath( - // inputDir: String, - // glob: String, - // commandFilePath: String, - // ): GeneratorConfig = { - - // } } diff --git a/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala b/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala index 10177f94ff..50d8d98bc1 100644 --- a/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/SourceGeneratorOptions.scala @@ -4,7 +4,7 @@ final case class SourceGeneratorOptions( useBuildInfo: Option[Boolean] = None, projectVersion: Option[String] = None, computeVersion: Option[ComputeVersion] = None, - generatorConfig: Option[GeneratorConfig] = None + generatorConfig: Seq[GeneratorConfig] = Nil, ) object SourceGeneratorOptions { From 15693d57a561f4a9d2edd51ff80f565a58e7d8d1 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Wed, 17 Jul 2024 13:24:01 +0700 Subject: [PATCH 07/14] abstracts commandProcessor --- modules/build/src/main/scala/scala/build/Project.scala | 2 +- .../src/main/scala/scala/build/options/GeneratorConfig.scala | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index 075ee63222..559841d346 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -66,7 +66,7 @@ final case class Project( BloopConfig.SourceGenerator( List(sourceGlobs0), (config.outputPath / "source-generator-output").toNIO, - List("python3", command0) + command0 ) }.toList ) diff --git a/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala index 5dc7bf606a..ac900f4eda 100644 --- a/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala +++ b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala @@ -6,7 +6,7 @@ import scala.build.errors.{BuildException, MalformedInputError} final case class GeneratorConfig( inputDir: String, glob: List[String], - commandFilePath: String, + commandFilePath: List[String], outputPath: os.SubPath ) @@ -15,7 +15,8 @@ object GeneratorConfig { def parse(input: Positioned[String], output: os.SubPath): Either[BuildException, GeneratorConfig] = input.value.split("\\|", 3) match { case Array(inputDir, glob, commandFilePath) => - Right(GeneratorConfig(inputDir, List(glob), commandFilePath, output)) + val commandFileList = commandFilePath.split(" ").toList + Right(GeneratorConfig(inputDir, List(glob), commandFileList, output)) case _ => Left( new MalformedInputError( From af2442131a4ff28b75a96c8c76bfd331a52c68db Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Mon, 22 Jul 2024 19:50:19 +0700 Subject: [PATCH 08/14] fix: renamed var on build.scala --- modules/build/src/main/scala/scala/build/Build.scala | 2 +- .../scala/build/preprocessing/DirectivesPreprocessor.scala | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Build.scala b/modules/build/src/main/scala/scala/build/Build.scala index 0eed6e87a8..b2369fdf11 100644 --- a/modules/build/src/main/scala/scala/build/Build.scala +++ b/modules/build/src/main/scala/scala/build/Build.scala @@ -866,7 +866,7 @@ object Build { if (options.useBuildServer.getOrElse(true)) None else releaseFlag(options, compilerJvmVersionOpt, logger).map(_.toString) - val hardcodedSource = options.sourceGeneratorOptions.generatorConfig + val sourceGeneratorConfig = options.sourceGeneratorOptions.generatorConfig val scalaCompilerParamsOpt = artifacts.scalaOpt match { case Some(scalaArtifacts) => diff --git a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala index 40047f564b..3fda875977 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala @@ -45,6 +45,7 @@ case class DirectivesPreprocessor( def preprocess(extractedDirectives: ExtractedDirectives) : Either[BuildException, PreprocessedDirectives] = either { val ExtractedDirectives(directives, directivesPositions) = extractedDirectives + println(s"DirectivesPreprocessor: $directives") val ( buildOptionsWithoutRequirements: PartiallyProcessedDirectives[BuildOptions], @@ -78,9 +79,6 @@ case class DirectivesPreprocessor( ) } - for (vals <- unusedDirectives) println(s"preprocess- ${vals.toString} ${vals.key}") - - val (optionsWithActualRequirements, optionsWithEmptyRequirements) = buildOptionsWithTargetRequirements.global.partition(_.requirements.nonEmpty) val summedOptionsWithNoRequirements = @@ -140,7 +138,6 @@ case class DirectivesPreprocessor( .toMap val unused = directives.filter(d => !handlersMap.contains(d.key)) - for (vals <- unused) println(s"${vals.toString} ${vals.key}") val res = directives .iterator From dd9d66058f7af0e46bc9cf7614cc98809284b47e Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Wed, 31 Jul 2024 19:57:33 +0700 Subject: [PATCH 09/14] using new directive style --- .../DirectivesPreprocessor.scala | 3 +- .../directives/DirectiveValueParser.scala | 1 - .../directives/SourceGenerator.scala | 103 +++++++++++++++--- 3 files changed, 91 insertions(+), 16 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala index 3fda875977..0494bfd989 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala @@ -45,8 +45,6 @@ case class DirectivesPreprocessor( def preprocess(extractedDirectives: ExtractedDirectives) : Either[BuildException, PreprocessedDirectives] = either { val ExtractedDirectives(directives, directivesPositions) = extractedDirectives - println(s"DirectivesPreprocessor: $directives") - val ( buildOptionsWithoutRequirements: PartiallyProcessedDirectives[BuildOptions], buildOptionsWithTargetRequirements: PartiallyProcessedDirectives[ @@ -129,6 +127,7 @@ case class DirectivesPreprocessor( else if handler.isExperimental && !shouldSuppressExperimentalFeatures then logger.experimentalWarning(scopedDirective.directive.toString, FeatureType.Directive) + // println(scopedDirective.cwd) handler.handleValues(scopedDirective, logger) val handlersMap = handlers diff --git a/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala b/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala index c25465fcff..866653ecaa 100644 --- a/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala +++ b/modules/directives/src/main/scala/scala/build/directives/DirectiveValueParser.scala @@ -138,7 +138,6 @@ object DirectiveValueParser { given DirectiveSingleValueParser[String] = (key, value, scopePath, path) => value.asString.toRight { - println("do we get here?") val pos = value.position(path) new MalformedDirectiveError( message = diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index a2d60ee183..92efcc1cd4 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -1,5 +1,17 @@ package scala.build.preprocessing.directives +// Virtuslab Processor +import com.virtuslab.using_directives.UsingDirectivesProcessor +import com.virtuslab.using_directives.custom.model.{ + BooleanValue, + EmptyValue, + StringValue, + UsingDirectives, + Value +} +import com.virtuslab.using_directives.custom.utils.ast._ +import scala.jdk.CollectionConverters.* + import scala.cli.commands.SpecificationLevel import scala.build.directives.* import scala.build.EitherCps.{either, value} @@ -8,31 +20,96 @@ import scala.build.errors.{BuildException, CompositeBuildException} import scala.build.options.{BuildOptions, SourceGeneratorOptions, GeneratorConfig} import scala.build.options.GeneratorConfig import scala.build.{Positioned, options} +import scala.build.directives.DirectiveValueParser.WithScopePath +@DirectiveGroupName("SourceGenerator") +@DirectivePrefix("sourceGenerator.") @DirectiveUsage("//> using sourceGenerator", "`//> using sourceGenerator`") @DirectiveDescription("Generate code using Source Generator") @DirectiveLevel(SpecificationLevel.EXPERIMENTAL) final case class SourceGenerator( - sourceGenerator: DirectiveValueParser.WithScopePath[List[Positioned[String]]] = - DirectiveValueParser.WithScopePath.empty(Nil) + testy: DirectiveValueParser.WithScopePath[List[Positioned[String]]] = + DirectiveValueParser.WithScopePath.empty(Nil), + scripts: DirectiveValueParser.WithScopePath[List[Positioned[String]]] = + DirectiveValueParser.WithScopePath.empty(Nil), + excludeScripts: Option[Boolean] = None, + inputDirectory: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = + DirectiveValueParser.WithScopePath.empty(None), + glob: Option[Positioned[String]] = None, + commandProcessor: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = + DirectiveValueParser.WithScopePath.empty(None), ) extends HasBuildOptions { def buildOptions: Either[BuildException, BuildOptions] = - SourceGenerator.buildOptions(sourceGenerator) + // println(s"ScopePath of Scripts: ${scripts.scopePath}") + // println(s"Values of Scripts: ${scripts.value(0).value}") + // println(s"Values of InputDir: ${inputDirectory.value}") + SourceGenerator.buildOptions(testy,scripts) } object SourceGenerator { val handler: DirectiveHandler[SourceGenerator] = DirectiveHandler.derive - def buildOptions(sourceGenerator: DirectiveValueParser.WithScopePath[List[Positioned[String]]]) - : Either[BuildException, BuildOptions] = { - val sourceGenValue = sourceGenerator.value - sourceGenValue - .map(config => GeneratorConfig.parse(config, sourceGenerator.scopePath.subPath)) - .sequence - .left.map(CompositeBuildException(_)) - .map { configs => - BuildOptions(sourceGeneratorOptions = - SourceGeneratorOptions(generatorConfig = configs) + def buildOptions( + sourceGenerator: DirectiveValueParser.WithScopePath[List[Positioned[String]]], + scripts: DirectiveValueParser.WithScopePath[List[Positioned[String]]] + ): Either[BuildException, BuildOptions] = { + val proc = UsingDirectivesProcessor() + val scriptConvert = scripts.value + .map(script => os.Path(script.value)) + .map(os.read(_)) + .map(_.toCharArray()) + .map(proc.extract(_).asScala) + .map(_.headOption) + + // println(scriptConvert.size) + + def modify(script: Option[UsingDirectives]) = { + script.toSeq.flatMap { directives => + def toStrictValue(value: UsingValue): Seq[Value[_]] = value match { + case uvs: UsingValues => uvs.values.asScala.toSeq.flatMap(toStrictValue) + case el: EmptyLiteral => Seq(EmptyValue(el)) + case sl: StringLiteral => Seq(StringValue(sl.getValue(), sl)) + case bl: BooleanLiteral => Seq(BooleanValue(bl.getValue(), bl)) + } + def toStrictDirective(ud: UsingDef) = StrictDirective( + ud.getKey(), + toStrictValue(ud.getValue()), + ud.getPosition().getColumn() ) + + // println(directives.getAst()) + + directives.getAst match + case uds: UsingDefs => uds.getUsingDefs.asScala.toSeq.map(toStrictDirective) + case _ => Nil // There should be nothing else here other than UsingDefs } + } + + val strictDirectives = scriptConvert + .map(modify(_)) + .map(_.take(3)) + + // println(scripts.scopePath.subPath) + // strictDirectives.map(f => f.map(w => println(w))) + + val directive = strictDirectives.collect { + case Seq(inputDir, glob, processor) => + GeneratorConfig(inputDir.values.mkString, List(glob.values.mkString), processor.values.mkString.split(" ").toList,scripts.scopePath.subPath) + } + println(directive.size) + + // val sourceGenValue = sourceGenerator.value + // sourceGenValue + // .map(config => GeneratorConfig.parse(config, sourceGenerator.scopePath.subPath)) + // .sequence + // .left.map(CompositeBuildException(_)) + // .map { configs => + // BuildOptions(sourceGeneratorOptions = + // SourceGeneratorOptions(generatorConfig = configs) + // ) + // } + + // directive.map { f => println(f)} + + Right(BuildOptions(sourceGeneratorOptions = SourceGeneratorOptions(generatorConfig = directive))) } } From 5758cc8e296cb96ecd8c351289966dfe2503a5b4 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Tue, 6 Aug 2024 21:17:52 +0700 Subject: [PATCH 10/14] working wip --- .../src/main/scala/scala/build/Project.scala | 3 +- .../directives/DirectiveSpecialSyntax.scala | 1 + .../directives/SourceGenerator.scala | 35 +++++++++++-------- .../scala/build/options/GeneratorConfig.scala | 32 ++++++++--------- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index 559841d346..23a1abd1b9 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -63,10 +63,11 @@ final case class Project( Nil ) + println(s"This is script path ${command0}") BloopConfig.SourceGenerator( List(sourceGlobs0), (config.outputPath / "source-generator-output").toNIO, - command0 + List("/Users/kiki/Kerja/scala-cli/testing-a/scala-cli", "--power", "run", command0) ) }.toList ) diff --git a/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala b/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala index 892fa770e5..3004ecbabf 100644 --- a/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala +++ b/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala @@ -21,6 +21,7 @@ object DirectiveSpecialSyntax { val pattern = """(((?:\$)+)(\{\.\}))""".r path match { case Right(p) => + println(p) pattern.replaceAllIn( directiveValue, (m: Regex.Match) => { diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index 92efcc1cd4..e317847854 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -36,20 +36,17 @@ final case class SourceGenerator( inputDirectory: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = DirectiveValueParser.WithScopePath.empty(None), glob: Option[Positioned[String]] = None, - commandProcessor: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = - DirectiveValueParser.WithScopePath.empty(None), ) extends HasBuildOptions { def buildOptions: Either[BuildException, BuildOptions] = // println(s"ScopePath of Scripts: ${scripts.scopePath}") // println(s"Values of Scripts: ${scripts.value(0).value}") // println(s"Values of InputDir: ${inputDirectory.value}") - SourceGenerator.buildOptions(testy,scripts) + SourceGenerator.buildOptions(scripts) } object SourceGenerator { val handler: DirectiveHandler[SourceGenerator] = DirectiveHandler.derive def buildOptions( - sourceGenerator: DirectiveValueParser.WithScopePath[List[Positioned[String]]], scripts: DirectiveValueParser.WithScopePath[List[Positioned[String]]] ): Either[BuildException, BuildOptions] = { val proc = UsingDirectivesProcessor() @@ -84,18 +81,25 @@ object SourceGenerator { } } - val strictDirectives = scriptConvert - .map(modify(_)) - .map(_.take(3)) + val componentKeyword = Seq("inputDirectory", "glob") + val strictDirectives = scriptConvert.map(modify(_)) - // println(scripts.scopePath.subPath) - // strictDirectives.map(f => f.map(w => println(w))) + val generatorComponents = strictDirectives.map(directiveSeq => + directiveSeq.filter(rawDirective => + componentKeyword.exists(keyword => rawDirective.key.contains(keyword)) + ) + ) - val directive = strictDirectives.collect { - case Seq(inputDir, glob, processor) => - GeneratorConfig(inputDir.values.mkString, List(glob.values.mkString), processor.values.mkString.split(" ").toList,scripts.scopePath.subPath) + // generatorComponents.map(f => f.map(g => println(g.values))) + val directive = generatorComponents.collect { + case Seq(inputDir, glob) => + GeneratorConfig( + inputDir.values.mkString, + List(glob.values.mkString), + scripts.value(0).value, + scripts.scopePath.subPath + ) } - println(directive.size) // val sourceGenValue = sourceGenerator.value // sourceGenValue @@ -107,9 +111,10 @@ object SourceGenerator { // SourceGeneratorOptions(generatorConfig = configs) // ) // } - // directive.map { f => println(f)} - Right(BuildOptions(sourceGeneratorOptions = SourceGeneratorOptions(generatorConfig = directive))) + Right(BuildOptions(sourceGeneratorOptions = + SourceGeneratorOptions(generatorConfig = directive) + )) } } diff --git a/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala index ac900f4eda..7b59db3483 100644 --- a/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala +++ b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala @@ -6,25 +6,25 @@ import scala.build.errors.{BuildException, MalformedInputError} final case class GeneratorConfig( inputDir: String, glob: List[String], - commandFilePath: List[String], + commandFilePath: String, outputPath: os.SubPath ) object GeneratorConfig { - def parse(input: Positioned[String], output: os.SubPath): Either[BuildException, GeneratorConfig] = - input.value.split("\\|", 3) match { - case Array(inputDir, glob, commandFilePath) => - val commandFileList = commandFilePath.split(" ").toList - Right(GeneratorConfig(inputDir, List(glob), commandFileList, output)) - case _ => - Left( - new MalformedInputError( - "sourceGenerator", - input.value, - "inputDir|glob|commandFilePath", - input.positions - ) - ) - } + // def parse(input: Positioned[String], output: os.SubPath): Either[BuildException, GeneratorConfig] = + // input.value.split("\\|", 3) match { + // case Array(inputDir, glob, commandFilePath) => + // val commandFileList = commandFilePath.split(" ").toList + // Right(GeneratorConfig(inputDir, List(glob), commandFileList, output)) + // case _ => + // Left( + // new MalformedInputError( + // "sourceGenerator", + // input.value, + // "inputDir|glob|commandFilePath", + // input.positions + // ) + // ) + // } } From 67941bfaf571aa383c51412add75892358be81e4 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Sun, 18 Aug 2024 20:07:15 +0700 Subject: [PATCH 11/14] add excludescript --- .../src/main/scala/scala/build/Project.scala | 3 +- .../directives/DirectiveSpecialSyntax.scala | 1 - .../directives/SourceGenerator.scala | 59 +++++++++++-------- 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/Project.scala b/modules/build/src/main/scala/scala/build/Project.scala index 23a1abd1b9..3e3eaf975d 100644 --- a/modules/build/src/main/scala/scala/build/Project.scala +++ b/modules/build/src/main/scala/scala/build/Project.scala @@ -63,11 +63,10 @@ final case class Project( Nil ) - println(s"This is script path ${command0}") BloopConfig.SourceGenerator( List(sourceGlobs0), (config.outputPath / "source-generator-output").toNIO, - List("/Users/kiki/Kerja/scala-cli/testing-a/scala-cli", "--power", "run", command0) + List("/Users/kiki/Kerja/scala-cli/testing-a/scala-cli", "run", command0, "--power", "--") ) }.toList ) diff --git a/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala b/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala index 3004ecbabf..892fa770e5 100644 --- a/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala +++ b/modules/directives/src/main/scala/scala/build/directives/DirectiveSpecialSyntax.scala @@ -21,7 +21,6 @@ object DirectiveSpecialSyntax { val pattern = """(((?:\$)+)(\{\.\}))""".r path match { case Right(p) => - println(p) pattern.replaceAllIn( directiveValue, (m: Regex.Match) => { diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index e317847854..923e4bd152 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -21,6 +21,9 @@ import scala.build.options.{BuildOptions, SourceGeneratorOptions, GeneratorConfi import scala.build.options.GeneratorConfig import scala.build.{Positioned, options} import scala.build.directives.DirectiveValueParser.WithScopePath +import scala.util.matching.Regex +import java.nio.file.Paths +import scala.build.options.InternalOptions @DirectiveGroupName("SourceGenerator") @DirectivePrefix("sourceGenerator.") @@ -35,19 +38,17 @@ final case class SourceGenerator( excludeScripts: Option[Boolean] = None, inputDirectory: DirectiveValueParser.WithScopePath[Option[Positioned[String]]] = DirectiveValueParser.WithScopePath.empty(None), - glob: Option[Positioned[String]] = None, + glob: Option[Positioned[String]] = None ) extends HasBuildOptions { def buildOptions: Either[BuildException, BuildOptions] = - // println(s"ScopePath of Scripts: ${scripts.scopePath}") - // println(s"Values of Scripts: ${scripts.value(0).value}") - // println(s"Values of InputDir: ${inputDirectory.value}") - SourceGenerator.buildOptions(scripts) + SourceGenerator.buildOptions(scripts, excludeScripts) } object SourceGenerator { val handler: DirectiveHandler[SourceGenerator] = DirectiveHandler.derive def buildOptions( - scripts: DirectiveValueParser.WithScopePath[List[Positioned[String]]] + scripts: DirectiveValueParser.WithScopePath[List[Positioned[String]]], + excludeScripts: Option[Boolean] ): Either[BuildException, BuildOptions] = { val proc = UsingDirectivesProcessor() val scriptConvert = scripts.value @@ -57,9 +58,12 @@ object SourceGenerator { .map(proc.extract(_).asScala) .map(_.headOption) - // println(scriptConvert.size) + val scriptsValue = scripts.value + .map(script => + os.Path(script.value) + ) - def modify(script: Option[UsingDirectives]) = { + def modify(script: Option[UsingDirectives]) = script.toSeq.flatMap { directives => def toStrictValue(value: UsingValue): Seq[Value[_]] = value match { case uvs: UsingValues => uvs.values.asScala.toSeq.flatMap(toStrictValue) @@ -79,6 +83,20 @@ object SourceGenerator { case uds: UsingDefs => uds.getUsingDefs.asScala.toSeq.map(toStrictDirective) case _ => Nil // There should be nothing else here other than UsingDefs } + + def replaceSpecialSyntax(directiveValue: String, path: os.Path): String = { + val pattern = """(((?:\$)+)(\{\.\}))""".r + pattern.replaceAllIn( + directiveValue, + (m: Regex.Match) => { + val dollarSigns = m.group(2) + val dollars = "\\$" * (dollarSigns.length / 2) + if (dollarSigns.length % 2 == 0) + s"$dollars${m.group(3)}" + else + s"$dollars${path / os.up}" + } + ) } val componentKeyword = Seq("inputDirectory", "glob") @@ -90,31 +108,26 @@ object SourceGenerator { ) ) - // generatorComponents.map(f => f.map(g => println(g.values))) + val pathModifier = scriptsValue.iterator val directive = generatorComponents.collect { case Seq(inputDir, glob) => + val relPath = pathModifier.next() GeneratorConfig( - inputDir.values.mkString, + replaceSpecialSyntax(inputDir.values.mkString, relPath), List(glob.values.mkString), scripts.value(0).value, scripts.scopePath.subPath ) } - // val sourceGenValue = sourceGenerator.value - // sourceGenValue - // .map(config => GeneratorConfig.parse(config, sourceGenerator.scopePath.subPath)) - // .sequence - // .left.map(CompositeBuildException(_)) - // .map { configs => - // BuildOptions(sourceGeneratorOptions = - // SourceGeneratorOptions(generatorConfig = configs) - // ) - // } - // directive.map { f => println(f)} + val excludedGeneratorPath = excludeScripts.match { + case Some(true) => scripts.value + case _ => List.empty[Positioned[String]] + } - Right(BuildOptions(sourceGeneratorOptions = - SourceGeneratorOptions(generatorConfig = directive) + Right(BuildOptions( + sourceGeneratorOptions = SourceGeneratorOptions(generatorConfig = directive), + internal = InternalOptions(exclude = excludedGeneratorPath) )) } } From 947efa3ffbd83589b8aeda5c12a5d56ab0641752 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Sun, 18 Aug 2024 23:29:58 +0700 Subject: [PATCH 12/14] refactor: sourceGenerator variable name --- .../directives/SourceGenerator.scala | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index 923e4bd152..84275a83df 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -50,20 +50,20 @@ object SourceGenerator { scripts: DirectiveValueParser.WithScopePath[List[Positioned[String]]], excludeScripts: Option[Boolean] ): Either[BuildException, BuildOptions] = { - val proc = UsingDirectivesProcessor() - val scriptConvert = scripts.value + val directiveProcessor = UsingDirectivesProcessor() + val parsedDirectives = scripts.value .map(script => os.Path(script.value)) .map(os.read(_)) .map(_.toCharArray()) - .map(proc.extract(_).asScala) + .map(directiveProcessor.extract(_).asScala) .map(_.headOption) - val scriptsValue = scripts.value + val scriptPaths = scripts.value .map(script => os.Path(script.value) ) - def modify(script: Option[UsingDirectives]) = + def processDirectives(script: Option[UsingDirectives]) = script.toSeq.flatMap { directives => def toStrictValue(value: UsingValue): Seq[Value[_]] = value match { case uvs: UsingValues => uvs.values.asScala.toSeq.flatMap(toStrictValue) @@ -77,8 +77,6 @@ object SourceGenerator { ud.getPosition().getColumn() ) - // println(directives.getAst()) - directives.getAst match case uds: UsingDefs => uds.getUsingDefs.asScala.toSeq.map(toStrictDirective) case _ => Nil // There should be nothing else here other than UsingDefs @@ -98,20 +96,24 @@ object SourceGenerator { } ) } + val processedDirectives = parsedDirectives.map(processDirectives(_)) - val componentKeyword = Seq("inputDirectory", "glob") - val strictDirectives = scriptConvert.map(modify(_)) - - val generatorComponents = strictDirectives.map(directiveSeq => + val sourceGeneratorKeywords = Seq("inputDirectory", "glob") + val sourceGeneratorDirectives = processedDirectives.map(directiveSeq => directiveSeq.filter(rawDirective => - componentKeyword.exists(keyword => rawDirective.key.contains(keyword)) + sourceGeneratorKeywords.exists(keyword => rawDirective.key.contains(keyword)) ) ) - val pathModifier = scriptsValue.iterator - val directive = generatorComponents.collect { + sourceGeneratorDirectives.foreach { components => + if (components.length != components.distinct.length) + throw new IllegalArgumentException(s"Duplicate elements found in sequence: $components") + } + + val pathIterator = scriptPaths.iterator + val generatorConfigs = sourceGeneratorDirectives.collect { case Seq(inputDir, glob) => - val relPath = pathModifier.next() + val relPath = pathIterator.next() GeneratorConfig( replaceSpecialSyntax(inputDir.values.mkString, relPath), List(glob.values.mkString), @@ -126,7 +128,7 @@ object SourceGenerator { } Right(BuildOptions( - sourceGeneratorOptions = SourceGeneratorOptions(generatorConfig = directive), + sourceGeneratorOptions = SourceGeneratorOptions(generatorConfig = generatorConfigs), internal = InternalOptions(exclude = excludedGeneratorPath) )) } From ffbc59aadbee480c12b8e3624f398198caf64075 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Mon, 19 Aug 2024 18:09:06 +0700 Subject: [PATCH 13/14] remove comments --- .../DirectivesPreprocessor.scala | 1 - .../scala/build/options/GeneratorConfig.scala | 19 ------------------- 2 files changed, 20 deletions(-) diff --git a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala index 0494bfd989..cda127e6cc 100644 --- a/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala +++ b/modules/build/src/main/scala/scala/build/preprocessing/DirectivesPreprocessor.scala @@ -127,7 +127,6 @@ case class DirectivesPreprocessor( else if handler.isExperimental && !shouldSuppressExperimentalFeatures then logger.experimentalWarning(scopedDirective.directive.toString, FeatureType.Directive) - // println(scopedDirective.cwd) handler.handleValues(scopedDirective, logger) val handlersMap = handlers diff --git a/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala index 7b59db3483..af87b14777 100644 --- a/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala +++ b/modules/options/src/main/scala/scala/build/options/GeneratorConfig.scala @@ -9,22 +9,3 @@ final case class GeneratorConfig( commandFilePath: String, outputPath: os.SubPath ) - -object GeneratorConfig { - - // def parse(input: Positioned[String], output: os.SubPath): Either[BuildException, GeneratorConfig] = - // input.value.split("\\|", 3) match { - // case Array(inputDir, glob, commandFilePath) => - // val commandFileList = commandFilePath.split(" ").toList - // Right(GeneratorConfig(inputDir, List(glob), commandFileList, output)) - // case _ => - // Left( - // new MalformedInputError( - // "sourceGenerator", - // input.value, - // "inputDir|glob|commandFilePath", - // input.positions - // ) - // ) - // } -} From e2c50093ca068858ebdc04c7f916750f6c288949 Mon Sep 17 00:00:00 2001 From: Rizky Maulana <71255973+Perklone@users.noreply.github.com> Date: Wed, 21 Aug 2024 20:02:53 +0700 Subject: [PATCH 14/14] don't allow duplicate directives inside generator files --- .../directives/SourceGenerator.scala | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala index 84275a83df..e71dd62f21 100644 --- a/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala +++ b/modules/directives/src/main/scala/scala/build/preprocessing/directives/SourceGenerator.scala @@ -58,11 +58,6 @@ object SourceGenerator { .map(directiveProcessor.extract(_).asScala) .map(_.headOption) - val scriptPaths = scripts.value - .map(script => - os.Path(script.value) - ) - def processDirectives(script: Option[UsingDirectives]) = script.toSeq.flatMap { directives => def toStrictValue(value: UsingValue): Seq[Value[_]] = value match { @@ -96,6 +91,13 @@ object SourceGenerator { } ) } + + def checkForDuplicateDirective(listOfDirective: Seq[StrictDirective]): Unit = { + val directiveKeys = listOfDirective.map(directive => directive.key) + if (directiveKeys.length != directiveKeys.distinct.length) + throw new IllegalArgumentException(s"Duplicate directives found in generator files.") + } + val processedDirectives = parsedDirectives.map(processDirectives(_)) val sourceGeneratorKeywords = Seq("inputDirectory", "glob") @@ -105,15 +107,15 @@ object SourceGenerator { ) ) - sourceGeneratorDirectives.foreach { components => - if (components.length != components.distinct.length) - throw new IllegalArgumentException(s"Duplicate elements found in sequence: $components") - } + sourceGeneratorDirectives.foreach(components => checkForDuplicateDirective(components)) + + val scriptPathIterator = scripts.value.map(script => + os.Path(script.value) + ).iterator - val pathIterator = scriptPaths.iterator val generatorConfigs = sourceGeneratorDirectives.collect { case Seq(inputDir, glob) => - val relPath = pathIterator.next() + val relPath = scriptPathIterator.next() GeneratorConfig( replaceSpecialSyntax(inputDir.values.mkString, relPath), List(glob.values.mkString),