From 366ab8f1bdc7c7b1c38723de2497d398372981a3 Mon Sep 17 00:00:00 2001 From: Kai Date: Sun, 20 Oct 2019 19:35:08 +0100 Subject: [PATCH 1/2] distage-roles: move *Impls to companion object --- .../izumi/distage/roles/RoleAppLauncher.scala | 46 +++--- .../distage/roles/config/ContextOptions.scala | 11 ++ .../distage/roles/internal/ConfigWriter.scala | 10 +- .../izumi/distage/roles/internal/Help.scala | 3 +- .../logger/SimpleLoggerConfigurator.scala | 4 +- .../roles/services/ActivationParser.scala | 22 +-- .../distage/roles/services/ConfigLoader.scala | 136 +++++++++++++++++ .../services/ConfigLoaderLocalFSImpl.scala | 139 ----------------- .../roles/services/IntegrationCheck.scala | 68 --------- .../roles/services/IntegrationChecker.scala | 71 +++++++++ .../roles/services/ModuleProvider.scala | 75 +++++++++- .../roles/services/ModuleProviderImpl.scala | 90 ----------- .../PlanCircularDependencyCheck.scala | 4 +- .../distage/roles/services/PluginSource.scala | 24 ++- .../roles/services/PluginSourceImpl.scala | 20 --- .../services/PruningPlanMergingPolicy.scala | 22 ++- .../roles/services/RoleAppExecutor.scala | 140 +++++++++++++++++ .../roles/services/RoleAppExecutorImpl.scala | 141 ------------------ .../roles/services/RoleAppPlanner.scala | 58 ++++++- .../roles/services/RoleAppPlannerImpl.scala | 56 ------- .../distage/roles/services/RoleProvider.scala | 85 ++++++++++- .../roles/services/RoleProviderImpl.scala | 87 ----------- .../roles/services/StartupPlanExecutor.scala | 47 ++++-- .../services/StartupPlanExecutorImpl.scala | 36 ----- .../plugins/ModuleRequirements.scala | 12 +- .../plugins/StaticPluginChecker.scala | 7 +- .../macrodefs/StaticPluginCheckerMacro.scala | 68 +++++---- .../dstest/DistageTestEnvironment.scala | 11 +- .../dstest/DistageTestEnvironmentImpl.scala | 18 +-- .../dstest/TestEnvironmentProviderImpl.scala | 6 +- .../st/adapter/DistagePluginTestSupport.scala | 10 +- .../st/adapter/DistageTestSupport.scala | 41 +++-- .../DistageScalatestTestSuiteRunner.scala | 8 +- .../distage/testkit/st/TestkitTest.scala | 13 +- 34 files changed, 786 insertions(+), 803 deletions(-) create mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/config/ContextOptions.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoaderLocalFSImpl.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationCheck.scala create mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationChecker.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProviderImpl.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSourceImpl.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutorImpl.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlannerImpl.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProviderImpl.scala delete mode 100644 distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutorImpl.scala diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/RoleAppLauncher.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/RoleAppLauncher.scala index 8c3cc3c154..3ce5f4f110 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/RoleAppLauncher.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/RoleAppLauncher.scala @@ -1,17 +1,19 @@ package izumi.distage.roles import cats.effect.LiftIO -import izumi.distage.config.model.AppConfig +import distage._ import izumi.distage.config.ConfigInjectionOptions +import izumi.distage.config.model.AppConfig import izumi.distage.model.definition.Axis.AxisValue import izumi.distage.model.definition.AxisBase import izumi.distage.model.definition.StandardAxis.{Env, ExternalApi, Repo} import izumi.distage.model.monadic.DIEffect import izumi.distage.model.reflection.universe.MirrorProvider import izumi.distage.plugins.merge.{PluginMergeStrategy, SimplePluginMergeStrategy} +import izumi.distage.roles.RoleAppLauncher.Options +import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.model.meta.{LibraryReference, RolesInfo} import izumi.distage.roles.model.{AppActivation, DiAppBootstrapException} -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions import izumi.distage.roles.services.PluginSource.AllLoadedPlugins import izumi.distage.roles.services.ResourceRewriter.RewriteRules import izumi.distage.roles.services._ @@ -22,10 +24,9 @@ import izumi.fundamentals.platform.language.Quirks import izumi.fundamentals.platform.resources.IzManifest import izumi.fundamentals.platform.strings.IzString._ import izumi.logstage.api.IzLogger -import distage._ import scala.concurrent.ExecutionContext -import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.ExecutionContext.global import scala.reflect.ClassTag /** @@ -49,8 +50,6 @@ import scala.reflect.ClassTag */ abstract class RoleAppLauncher[F[_] : TagK : DIEffect] { - import RoleAppLauncher._ - private val loggers = new EarlyLoggers() protected def bootstrapConfig: BootstrapConfig @@ -101,19 +100,20 @@ abstract class RoleAppLauncher[F[_] : TagK : DIEffect] { protected def bsOverride: BootstrapModule = BootstrapModule.empty - protected def defaultActivations: Map[AxisBase, AxisValue] = Map( - Env -> Env.Prod, - Repo -> Repo.Prod, - ExternalApi -> ExternalApi.Prod, - ) - + protected def defaultActivations: Map[AxisBase, AxisValue] = { + Map( + Env -> Env.Prod, + Repo -> Repo.Prod, + ExternalApi -> ExternalApi.Prod, + ) + } protected def requiredActivations: Map[AxisBase, AxisValue] = Map.empty protected def gcRoots(rolesInfo: RolesInfo): Set[DIKey] = { rolesInfo.requiredComponents } -protected def makeBootstrapMergeStrategy(lateLogger: IzLogger, parameters: RawAppArgs): PluginMergeStrategy = { + protected def makeBootstrapMergeStrategy(lateLogger: IzLogger, parameters: RawAppArgs): PluginMergeStrategy = { Quirks.discard(lateLogger, parameters) SimplePluginMergeStrategy } @@ -124,15 +124,15 @@ protected def makeBootstrapMergeStrategy(lateLogger: IzLogger, parameters: RawAp } protected def makePlanner(options: ContextOptions, bsModule: BootstrapModule, activation: AppActivation, lateLogger: IzLogger): RoleAppPlanner[F] = { - new RoleAppPlannerImpl[F](options, bsModule, activation, lateLogger) + new RoleAppPlanner.Impl[F](options, bsModule, activation, lateLogger) } protected def makeExecutor(parameters: RawAppArgs, roles: RolesInfo, lateLogger: IzLogger, injector: Injector): RoleAppExecutor[F] = { - new RoleAppExecutorImpl[F](hook, roles, injector, lateLogger, parameters) + new RoleAppExecutor.Impl[F](hook, roles, injector, lateLogger, parameters) } -protected def makeModuleProvider(options: ContextOptions, parameters: RawAppArgs, activation: AppActivation, roles: RolesInfo, config: AppConfig, lateLogger: IzLogger): ModuleProvider[F] = { - new ModuleProviderImpl[F]( + protected def makeModuleProvider(options: ContextOptions, parameters: RawAppArgs, activation: AppActivation, roles: RolesInfo, config: AppConfig, lateLogger: IzLogger): ModuleProvider[F] = { + new ModuleProvider.Impl[F]( lateLogger, config, roles, @@ -155,7 +155,7 @@ protected def makeModuleProvider(options: ContextOptions, parameters: RawAppArgs protected def loadRoles(parameters: RawAppArgs, logger: IzLogger, plugins: AllLoadedPlugins): RolesInfo = { val activeRoleNames = parameters.roles.map(_.role).toSet val mp = MirrorProvider.Impl - val roleProvider: RoleProvider[F] = new RoleProviderImpl(logger, activeRoleNames, mp) + val roleProvider: RoleProvider[F] = new RoleProvider.Impl(logger, activeRoleNames, mp) val bindings = plugins.app.flatMap(_.bindings) val bsBindings = plugins.app.flatMap(_.bindings) logger.info(s"Available ${plugins.app.size -> "app plugins"} with ${bindings.size -> "app bindings"} and ${plugins.bootstrap.size -> "bootstrap plugins"} with ${bsBindings.size -> "bootstrap bindings"} ...") @@ -187,10 +187,12 @@ protected def makeModuleProvider(options: ContextOptions, parameters: RawAppArgs logger.info(s"Available ${availableRoleInfo.niceList() -> "roles"}") } -protected def showBanner(logger: IzLogger, referenceLibraries: Seq[LibraryReference]): this.type = { + protected def showBanner(logger: IzLogger, referenceLibraries: Seq[LibraryReference]): this.type = { val withIzumi = referenceLibraries :+ LibraryReference("izumi-r2", classOf[ConfigLoader]) showDepData(logger, "Application is about to start", this.getClass) - withIzumi.foreach { u => showDepData(logger, s"... using ${u.libraryName}", u.clazz) } + withIzumi.foreach { + u => showDepData(logger, s"... using ${u.libraryName}", u.clazz) + } this } @@ -212,7 +214,7 @@ protected def showBanner(logger: IzLogger, referenceLibraries: Seq[LibraryRefere } protected def makePluginLoader(bootstrapConfig: BootstrapConfig): PluginSource = { - new PluginSourceImpl(bootstrapConfig) + new PluginSource.Impl(bootstrapConfig) } protected def makeConfigLoader(logger: IzLogger, parameters: RawAppArgs): ConfigLoader = { @@ -222,7 +224,7 @@ protected def showBanner(logger: IzLogger, referenceLibraries: Seq[LibraryRefere r => r.role -> Options.configParam.findValue(r.roleParameters).asFile } - new ConfigLoaderLocalFSImpl(logger, maybeGlobalConfig, roleConfigs.toMap) + new ConfigLoader.LocalFSImpl(logger, maybeGlobalConfig, roleConfigs.toMap) } } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/config/ContextOptions.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/config/ContextOptions.scala new file mode 100644 index 0000000000..77ce534b64 --- /dev/null +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/config/ContextOptions.scala @@ -0,0 +1,11 @@ +package izumi.distage.roles.config + +import izumi.distage.config.ConfigInjectionOptions +import izumi.distage.roles.services.ResourceRewriter.RewriteRules + +case class ContextOptions( + addGvDump: Boolean, + warnOnCircularDeps: Boolean, + rewriteRules: RewriteRules, + configInjectionOptions: ConfigInjectionOptions, + ) diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala index a6b899c05e..299ee24a87 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala @@ -3,6 +3,7 @@ package izumi.distage.roles.internal import java.nio.charset.StandardCharsets import java.nio.file.{Files, Paths} +import com.typesafe.config.{Config, ConfigFactory, ConfigRenderOptions} import izumi.distage.config.model.AppConfig import izumi.distage.config.{ConfigModule, ResolvedConfig} import izumi.distage.model.definition.{Id, ModuleBase} @@ -12,7 +13,7 @@ import izumi.distage.model.plan.OrderedPlan import izumi.distage.roles.internal.ConfigWriter.{ConfigurableComponent, WriteReference} import izumi.distage.roles.model.meta.{RoleBinding, RolesInfo} import izumi.distage.roles.model.{RoleDescriptor, RoleTask} -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions +import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.services.RoleAppPlanner import izumi.fundamentals.platform.cli.model.raw.RawEntrypointParams import izumi.fundamentals.platform.cli.model.schema.{ParserDef, RoleParserSchema} @@ -21,7 +22,6 @@ import izumi.fundamentals.platform.resources.ArtifactVersion import izumi.logstage.api.IzLogger import izumi.logstage.api.logger.LogRouter import izumi.logstage.distage.LogstageModule -import com.typesafe.config.{Config, ConfigFactory, ConfigRenderOptions} import scala.util._ @@ -32,7 +32,7 @@ class ConfigWriter[F[_] : DIEffect] roleInfo: RolesInfo, context: RoleAppPlanner[F], options: ContextOptions, - appModule: ModuleBase@Id("application.module") + appModule: ModuleBase@Id("application.module"), ) extends RoleTask[F] { @@ -211,10 +211,10 @@ object ConfigWriter extends RoleDescriptor { final case class ConfigurableComponent( componentId: String , version: Option[ArtifactVersion] - , parent: Option[Config] = None + , parent: Option[Config] = None, ) -object P extends ParserDef { + object P extends ParserDef { final val targetDir = arg("target", "t", "target directory", "") final val excludeCommon = flag("exclude-common", "ec", "do not include shared sections") final val useComponentVersion = flag("version-use-component", "vc", "use component version instead of launcher version") diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/Help.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/Help.scala index 06e1492c26..b78a247030 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/Help.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/Help.scala @@ -13,8 +13,7 @@ class Help[F[_] : DIEffect] ( roleInfo: RolesInfo, activation: AppActivation, -) - extends RoleTask[F] { +) extends RoleTask[F] { override def start(roleParameters: RawEntrypointParams, freeArgs: Vector[String]): F[Unit] = { Quirks.discard(roleParameters, freeArgs) diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/logger/SimpleLoggerConfigurator.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/logger/SimpleLoggerConfigurator.scala index 06c2bd54e0..8ce2559f1a 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/logger/SimpleLoggerConfigurator.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/logger/SimpleLoggerConfigurator.scala @@ -13,7 +13,9 @@ import izumi.logstage.sink.{ConsoleSink, QueueingSink} import scala.util.{Failure, Success, Try} -class SimpleLoggerConfigurator(exceptionLogger: IzLogger) { +class SimpleLoggerConfigurator( + exceptionLogger: IzLogger, + ) { import SimpleLoggerConfigurator._ diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ActivationParser.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ActivationParser.scala index 29cd76f11e..406faf454d 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ActivationParser.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ActivationParser.scala @@ -1,13 +1,13 @@ package izumi.distage.roles.services +import distage.ModuleBase import izumi.distage.model.definition.Axis.AxisValue import izumi.distage.model.definition.{AxisBase, BindingTag} import izumi.distage.roles.RoleAppLauncher.Options import izumi.distage.roles.model.{AppActivation, DiAppBootstrapException} import izumi.fundamentals.platform.cli.model.raw.RawAppArgs -import izumi.logstage.api.IzLogger -import distage.ModuleBase import izumi.fundamentals.platform.strings.IzString._ +import izumi.logstage.api.IzLogger class ActivationParser { def parseActivation( @@ -20,12 +20,14 @@ class ActivationParser { val uses = Options.use.findValues(parameters.globalParameters) val availableUses: Map[AxisBase, Set[AxisValue]] = ActivationParser.findAvailableChoices(logger, defApp) -def options: String = availableUses - .map { - case (axis, members) => - s"$axis:${members.niceList().shift(2)}" - } - .niceList() + def options: String = { + availableUses + .map { + case (axis, members) => + s"$axis:${members.niceList().shift(2)}" + } + .niceList() + } val activeChoices = uses .map { @@ -69,7 +71,9 @@ def options: String = availableUses object ActivationParser { def findAvailableChoices(logger: IzLogger, defApp: ModuleBase): Map[AxisBase, Set[AxisValue]] = { - val allChoices = defApp.bindings.flatMap(_.tags).collect({ case BindingTag.AxisTag(choice) => choice }) + val allChoices = defApp.bindings.flatMap(_.tags).collect({ + case BindingTag.AxisTag(choice) => choice + }) val allAxis = allChoices.map(_.axis).groupBy(_.name) val badAxis = allAxis.filter(_._2.size > 1) if (badAxis.nonEmpty) { diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoader.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoader.scala index b3f0a522d7..63244677dc 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoader.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoader.scala @@ -1,7 +1,143 @@ package izumi.distage.roles.services +import java.io.File + +import com.typesafe.config.{Config, ConfigFactory} import distage.config.AppConfig +import izumi.fundamentals.platform.resources.IzResources +import izumi.logstage.api.IzLogger + +import scala.util.{Failure, Success, Try} trait ConfigLoader { def buildConfig(): AppConfig } + +object ConfigLoader { + + class LocalFSImpl( + logger: IzLogger, + primaryConfig: Option[File], + roleConfigs: Map[String, Option[File]], + ) extends ConfigLoader { + + import LocalFSImpl._ + import izumi.fundamentals.platform.strings.IzString._ + + import scala.collection.JavaConverters._ + + def buildConfig(): AppConfig = { + val commonConfigFile = toConfig("common", primaryConfig) + + val roleConfigFiles = roleConfigs.flatMap { + case (roleName, roleConfig) => + toConfig(roleName, roleConfig) + } + .toList + + val allConfigs = roleConfigFiles ++ commonConfigFile + + val cfgInfo = allConfigs.map { + case r: ConfigSource.Resource => + IzResources.getPath(r.name) match { + case Some(value) => + s"$r (exists: ${value.path})" + case None => + s"$r (missing)" + } + + case f: ConfigSource.File => + if (f.file.exists()) { + s"$f (exists: ${f.file.getCanonicalPath})" + } else { + s"$f (missing)" + } + } + + logger.info(s"Using system properties with fallback ${cfgInfo.niceList() -> "config files"}") + + val loaded = allConfigs.map { + case s@ConfigSource.File(file) => + s -> Try(ConfigFactory.parseFile(file)) + + case s@ConfigSource.Resource(name, _) => + s -> Try(ConfigFactory.parseResources(name)) + } + + val (good, bad) = loaded.partition(_._2.isSuccess) + + if (bad.nonEmpty) { + val failures = bad.collect { + case (s, Failure(f)) => + s"$s: $f" + } + + logger.error(s"Failed to load configs: ${failures.niceList() -> "failures"}") + } + + val folded = foldConfigs(good.collect({ + case (src, Success(c)) => src -> c + })) + + val config = ConfigFactory.systemProperties() + .withFallback(folded) + .resolve() + + AppConfig(config) + } + + protected def defaultConfigReferences(name: String): Seq[ConfigSource] = { + Seq( + ConfigSource.Resource(s"$name-reference.conf", ResourceConfigKind.Primary), + ConfigSource.Resource(s"$name-reference-dev.conf", ResourceConfigKind.Development), + ) + } + + protected def foldConfigs(roleConfigs: Seq[(ConfigSource, Config)]): Config = { + roleConfigs.foldLeft(ConfigFactory.empty()) { + case (acc, (src, cfg)) => + verifyConfigs(src, cfg, acc) + acc.withFallback(cfg) + } + } + + protected def verifyConfigs(src: ConfigSource, cfg: Config, acc: Config): Unit = { + val duplicateKeys = acc.entrySet().asScala.map(_.getKey).intersect(cfg.entrySet().asScala.map(_.getKey)) + if (duplicateKeys.nonEmpty) { + src match { + case ConfigSource.Resource(_, ResourceConfigKind.Development) => + logger.debug(s"Some keys in supplied ${src -> "development config"} duplicate already defined keys: ${duplicateKeys.niceList() -> "keys" -> null}") + + case _ => + logger.warn(s"Some keys in supplied ${src -> "config"} duplicate already defined keys: ${duplicateKeys.niceList() -> "keys" -> null}") + } + } + } + + private def toConfig(name: String, maybeConfigFile: Option[File]): Seq[ConfigSource] = { + maybeConfigFile.fold(defaultConfigReferences(name)) { + f => + Seq(ConfigSource.File(f)) + } + } + } + + object LocalFSImpl { + sealed trait ResourceConfigKind + object ResourceConfigKind { + case object Primary extends ResourceConfigKind + case object Development extends ResourceConfigKind + } + + sealed trait ConfigSource + object ConfigSource { + final case class Resource(name: String, kind: ResourceConfigKind) extends ConfigSource { + override def toString: String = s"resource:$name" + } + final case class File(file: java.io.File) extends ConfigSource { + override def toString: String = s"file:$file" + } + } + } + +} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoaderLocalFSImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoaderLocalFSImpl.scala deleted file mode 100644 index 168e6ad25a..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ConfigLoaderLocalFSImpl.scala +++ /dev/null @@ -1,139 +0,0 @@ -package izumi.distage.roles.services - -import java.io.File - -import izumi.distage.config.model.AppConfig -import izumi.fundamentals.platform.resources.IzResources -import izumi.logstage.api.IzLogger -import com.typesafe.config.{Config, ConfigFactory} - -import scala.util.{Failure, Success, Try} - -class ConfigLoaderLocalFSImpl( - logger: IzLogger, - primaryConfig: Option[File], - roleConfigs: Map[String, Option[File]] - ) extends ConfigLoader { - - import ConfigLoaderLocalFSImpl._ - import izumi.fundamentals.platform.strings.IzString._ - - import scala.collection.JavaConverters._ - - def buildConfig(): AppConfig = { - val commonConfigFile = toConfig("common", primaryConfig) - - val roleConfigFiles = roleConfigs.flatMap { - case (roleName, roleConfig) => - toConfig(roleName, roleConfig) - } - .toList - - val allConfigs = roleConfigFiles ++ commonConfigFile - - val cfgInfo = allConfigs.map { - case r: ConfigSource.Resource => - IzResources.getPath(r.name) match { - case Some(value) => - s"$r (exists: ${value.path})" - case None => - s"$r (missing)" - } - - case f: ConfigSource.File => - if (f.file.exists()) { - s"$f (exists: ${f.file.getCanonicalPath})" - } else { - s"$f (missing)" - } - } - - logger.info(s"Using system properties with fallback ${cfgInfo.niceList() -> "config files"}") - - val loaded = allConfigs.map { - case s@ConfigSource.File(file) => - s -> Try(ConfigFactory.parseFile(file)) - - case s@ConfigSource.Resource(name, _) => - s -> Try(ConfigFactory.parseResources(name)) - } - - val (good, bad) = loaded.partition(_._2.isSuccess) - - if (bad.nonEmpty) { - val failures = bad.collect { - case (s, Failure(f)) => - s"$s: $f" - } - - logger.error(s"Failed to load configs: ${failures.niceList() -> "failures"}") - } - - val folded = foldConfigs(good.collect({ case (src, Success(c)) => src -> c })) - - val config = ConfigFactory.systemProperties() - .withFallback(folded) - .resolve() - - AppConfig(config) - } - - protected def defaultConfigReferences(name: String): Seq[ConfigSource] = { - Seq( - ConfigSource.Resource(s"$name-reference.conf", ResourceConfigKind.Primary), - ConfigSource.Resource(s"$name-reference-dev.conf", ResourceConfigKind.Development), - ) - } - - protected def foldConfigs(roleConfigs: Seq[(ConfigSource, Config)]): Config = { - roleConfigs.foldLeft(ConfigFactory.empty()) { - case (acc, (src, cfg)) => - verifyConfigs(src, cfg, acc) - acc.withFallback(cfg) - } - } - - protected def verifyConfigs(src: ConfigSource, cfg: Config, acc: Config): Unit = { - val duplicateKeys = acc.entrySet().asScala.map(_.getKey).intersect(cfg.entrySet().asScala.map(_.getKey)) - if (duplicateKeys.nonEmpty) { - src match { - case ConfigSource.Resource(_, ResourceConfigKind.Development) => - logger.debug(s"Some keys in supplied ${src -> "development config"} duplicate already defined keys: ${duplicateKeys.niceList() -> "keys" -> null}") - - case _ => - logger.warn(s"Some keys in supplied ${src -> "config"} duplicate already defined keys: ${duplicateKeys.niceList() -> "keys" -> null}") - } - } - } - - private def toConfig(name: String, maybeConfigFile: Option[File]): Seq[ConfigSource] = { - maybeConfigFile.fold(defaultConfigReferences(name)) { - f => - Seq(ConfigSource.File(f)) - } - } -} - -object ConfigLoaderLocalFSImpl { - - sealed trait ConfigSource - - sealed trait ResourceConfigKind - object ResourceConfigKind { - case object Primary extends ResourceConfigKind - case object Development extends ResourceConfigKind - } - - object ConfigSource { - - final case class Resource(name: String, kind: ResourceConfigKind) extends ConfigSource { - override def toString: String = s"resource:$name" - } - - final case class File(file: java.io.File) extends ConfigSource { - override def toString: String = s"file:$file" - } - - } - -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationCheck.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationCheck.scala deleted file mode 100644 index 3795c91907..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationCheck.scala +++ /dev/null @@ -1,68 +0,0 @@ -package izumi.distage.roles.services - -import izumi.distage.model.Locator -import izumi.distage.model.exceptions.DIException -import izumi.distage.roles.model.{DiAppBootstrapException, IntegrationCheck} -import izumi.distage.roles.services.IntegrationChecker.IntegrationCheckException -import izumi.fundamentals.platform.integration.ResourceCheck -import izumi.fundamentals.platform.strings.IzString._ -import izumi.logstage.api.IzLogger -import distage.DIKey - -import scala.util.control.NonFatal - -trait IntegrationChecker { - def check(integrationComponents: Set[DIKey], integrationLocator: Locator): Option[Seq[ResourceCheck.Failure]] - - final def checkOrFail(integrationComponents: Set[DIKey], integrationLocator: Locator): Unit = { - check(integrationComponents, integrationLocator).fold(()) { - failures => - throw new IntegrationCheckException(s"Integration check failed, failures were: ${failures.niceList()}", failures) - } - } -} - -object IntegrationChecker { - class IntegrationCheckException(message: String, val failures: Seq[ResourceCheck.Failure]) extends DIException(message, null) -} - -class IntegrationCheckerImpl(logger: IzLogger) extends IntegrationChecker { - def check(integrationComponents: Set[DIKey], integrationLocator: Locator): Option[Seq[ResourceCheck.Failure]] = { - val integrations = integrationComponents.map { - ick => - integrationLocator.lookup[IntegrationCheck](ick) match { - case Some(ic) => - ic.value - case None => - throw new DiAppBootstrapException(s"Inconsistent locator state: integration component $ick is missing from plan") - } - } - failingIntegrations(integrations) - } - -private def failingIntegrations(integrations: Set[IntegrationCheck]): Option[Seq[ResourceCheck.Failure]] = { - logger.info(s"Going to check availability of ${integrations.size -> "resources"}") - - val failures = integrations.toSeq.flatMap { - resource => - logger.debug(s"Checking $resource") - try { - resource.resourcesAvailable() match { - case failure@ResourceCheck.ResourceUnavailable(reason, Some(cause)) => - logger.debug(s"Integration check failed, $resource unavailable: $reason, $cause") - Some(failure) - case failure@ResourceCheck.ResourceUnavailable(reason, None) => - logger.debug(s"Integration check failed, $resource unavailable: $reason") - Some(failure) - case ResourceCheck.Success() => - None - } - } catch { - case NonFatal(exception) => - logger.error(s"Integration check for $resource threw $exception") - Some(ResourceCheck.ResourceUnavailable(exception.getMessage, Some(exception))) - } - } - Some(failures).filter(_.nonEmpty) - } -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationChecker.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationChecker.scala new file mode 100644 index 0000000000..4c3983ddc5 --- /dev/null +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/IntegrationChecker.scala @@ -0,0 +1,71 @@ +package izumi.distage.roles.services + +import distage.DIKey +import izumi.distage.model.Locator +import izumi.distage.model.exceptions.DIException +import izumi.distage.roles.model.{DiAppBootstrapException, IntegrationCheck} +import izumi.distage.roles.services.IntegrationChecker.IntegrationCheckException +import izumi.fundamentals.platform.integration.ResourceCheck +import izumi.fundamentals.platform.strings.IzString._ +import izumi.logstage.api.IzLogger + +import scala.util.control.NonFatal + +trait IntegrationChecker { + def check(integrationComponents: Set[DIKey], integrationLocator: Locator): Option[Seq[ResourceCheck.Failure]] + + final def checkOrFail(integrationComponents: Set[DIKey], integrationLocator: Locator): Unit = { + check(integrationComponents, integrationLocator).fold(()) { + failures => + throw new IntegrationCheckException(s"Integration check failed, failures were: ${failures.niceList()}", failures) + } + } +} + +object IntegrationChecker { + class IntegrationCheckException(message: String, val failures: Seq[ResourceCheck.Failure]) extends DIException(message, null) + + class Impl( + logger: IzLogger, + ) extends IntegrationChecker { + def check(integrationComponents: Set[DIKey], integrationLocator: Locator): Option[Seq[ResourceCheck.Failure]] = { + val integrations = integrationComponents.map { + ick => + integrationLocator.lookup[IntegrationCheck](ick) match { + case Some(ic) => + ic.value + case None => + throw new DiAppBootstrapException(s"Inconsistent locator state: integration component $ick is missing from plan") + } + } + failingIntegrations(integrations) + } + + private def failingIntegrations(integrations: Set[IntegrationCheck]): Option[Seq[ResourceCheck.Failure]] = { + logger.info(s"Going to check availability of ${integrations.size -> "resources"}") + + val failures = integrations.toSeq.flatMap { + resource => + logger.debug(s"Checking $resource") + try { + resource.resourcesAvailable() match { + case failure@ResourceCheck.ResourceUnavailable(reason, Some(cause)) => + logger.debug(s"Integration check failed, $resource unavailable: $reason, $cause") + Some(failure) + case failure@ResourceCheck.ResourceUnavailable(reason, None) => + logger.debug(s"Integration check failed, $resource unavailable: $reason") + Some(failure) + case ResourceCheck.Success() => + None + } + } catch { + case NonFatal(exception) => + logger.error(s"Integration check for $resource threw $exception") + Some(ResourceCheck.ResourceUnavailable(exception.getMessage, Some(exception))) + } + } + Some(failures).filter(_.nonEmpty) + } + } + +} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProvider.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProvider.scala index 5b91e4b05b..c4dcd94cc0 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProvider.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProvider.scala @@ -1,10 +1,83 @@ package izumi.distage.roles.services import distage._ +import izumi.distage.config.ConfigModule +import izumi.distage.config.model.AppConfig +import izumi.distage.model.definition.{BootstrapModuleDef, Module, ModuleDef} +import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} +import izumi.distage.model.planning.{PlanMergingPolicy, PlanningHook} +import izumi.distage.planning.AutoSetModule +import izumi.distage.planning.extensions.GraphDumpBootstrapModule +import izumi.distage.roles.config.ContextOptions +import izumi.distage.roles.model.meta.RolesInfo +import izumi.distage.roles.model.{AbstractRoleF, AppActivation} +import izumi.distage.roles.services.ResourceRewriter.RewriteRules +import izumi.fundamentals.platform.cli.model.raw.RawAppArgs +import izumi.fundamentals.platform.functional.Identity +import izumi.logstage.api.IzLogger +import izumi.logstage.distage.LogstageModule trait ModuleProvider[F[_]] { def bootstrapModules(): Seq[BootstrapModuleDef] - def appModules(): Seq[Module] +} + +object ModuleProvider { + + class Impl[F[_] : TagK]( + logger: IzLogger, + config: AppConfig, + roles: RolesInfo, + options: ContextOptions, + args: RawAppArgs, + activation: AppActivation, + ) extends ModuleProvider[F] { + + def bootstrapModules(): Seq[BootstrapModuleDef] = { + val rolesModule = new BootstrapModuleDef { + make[RolesInfo].from(roles) + make[RawAppArgs].from(args) + make[AppActivation].from(activation) + make[PlanMergingPolicy].from[PruningPlanMergingPolicy] + } + + val loggerModule = new LogstageModule(logger.router, true) + + val autosetModule = AutoSetModule() + .register[AbstractRoleF[F]] + + val configModule = new ConfigModule(config, options.configInjectionOptions) + + val resourceRewriter = new BootstrapModuleDef { + make[RewriteRules].from(options.rewriteRules) + many[PlanningHook].add[ResourceRewriter] + } + + Seq( + Seq( + configModule, + autosetModule, + rolesModule, + resourceRewriter, + loggerModule, + ), + condModule(options.addGvDump, new GraphDumpBootstrapModule()) + ).flatten + } + + def appModules(): Seq[Module] = { + val baseMod = new ModuleDef { + addImplicit[DIEffect[Identity]] + make[DIEffectRunner[Identity]].from(DIEffectRunner.IdentityImpl) + } + + Seq(baseMod) + } + + private def condModule(condition: Boolean, module: => distage.BootstrapModuleDef): Seq[BootstrapModuleDef] = { + if (condition) Seq(module) else Seq.empty + } + + } } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProviderImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProviderImpl.scala deleted file mode 100644 index 2b100078f8..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/ModuleProviderImpl.scala +++ /dev/null @@ -1,90 +0,0 @@ -package izumi.distage.roles.services - -import izumi.distage.config.model.AppConfig -import izumi.distage.config.{ConfigInjectionOptions, ConfigModule} -import izumi.distage.model.definition.{BootstrapModuleDef, Module, ModuleDef} -import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} -import izumi.distage.model.planning.{PlanMergingPolicy, PlanningHook} -import izumi.distage.planning.AutoSetModule -import izumi.distage.planning.extensions.GraphDumpBootstrapModule -import izumi.distage.roles.model.{AbstractRoleF, AppActivation} -import izumi.distage.roles.model.meta.RolesInfo -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions -import izumi.distage.roles.services.ResourceRewriter.RewriteRules -import izumi.fundamentals.platform.cli.model.raw.RawAppArgs -import izumi.fundamentals.platform.functional.Identity -import izumi.logstage.api.IzLogger -import izumi.logstage.distage.LogstageModule -import distage.TagK - -class ModuleProviderImpl[F[_] : TagK]( - logger: IzLogger, - config: AppConfig, - roles: RolesInfo, - options: ContextOptions, - args: RawAppArgs, - activation: AppActivation, - ) extends ModuleProvider[F] { - def bootstrapModules(): Seq[BootstrapModuleDef] = { - val rolesModule = new BootstrapModuleDef { - make[RolesInfo].from(roles) - make[RawAppArgs].from(args) - make[AppActivation].from(activation) - make[PlanMergingPolicy].from[PruningPlanMergingPolicy] - } - - val loggerModule = new LogstageModule(logger.router, true) - - val autosetModule = AutoSetModule() - .register[AbstractRoleF[F]] - - val configModule = new ConfigModule(config, options.configInjectionOptions) - - val resourceRewriter = new BootstrapModuleDef { - make[RewriteRules].from(options.rewriteRules) - many[PlanningHook].add[ResourceRewriter] - } - - Seq( - Seq( - configModule, - autosetModule, - rolesModule, - resourceRewriter, - loggerModule, - ), - condModule(options.addGvDump, new GraphDumpBootstrapModule()) - ).flatten - } - - def appModules(): Seq[Module] = { - val baseMod = new ModuleDef { - addImplicit[DIEffect[Identity]] - make[DIEffectRunner[Identity]].from(DIEffectRunner.IdentityImpl) - } - - Seq( - baseMod - ) - } - - private def condModule(condition: Boolean, module: => distage.BootstrapModuleDef): Seq[BootstrapModuleDef] = { - if (condition) { - Seq(module) - } else { - Seq.empty - } - } - -} - -object ModuleProviderImpl { - - case class ContextOptions( - addGvDump: Boolean, - warnOnCircularDeps: Boolean, - rewriteRules: RewriteRules, - configInjectionOptions: ConfigInjectionOptions, - ) - -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PlanCircularDependencyCheck.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PlanCircularDependencyCheck.scala index 8cf4990cae..2845530b92 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PlanCircularDependencyCheck.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PlanCircularDependencyCheck.scala @@ -1,9 +1,9 @@ package izumi.distage.roles.services +import distage.OrderedPlan import izumi.distage.model.plan.ExecutableOp -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions +import izumi.distage.roles.config.ContextOptions import izumi.logstage.api.IzLogger -import distage.OrderedPlan class PlanCircularDependencyCheck( options: ContextOptions, diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSource.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSource.scala index 59232d0571..71a638c0e2 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSource.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSource.scala @@ -1,13 +1,33 @@ package izumi.distage.roles.services -import izumi.distage.roles.services.PluginSource.AllLoadedPlugins import distage.plugins.PluginBase +import izumi.distage.plugins.load.PluginLoader +import izumi.distage.roles.BootstrapConfig +import izumi.distage.roles.services.PluginSource.AllLoadedPlugins trait PluginSource { def load(): AllLoadedPlugins - } object PluginSource { case class AllLoadedPlugins(bootstrap: Seq[PluginBase], app: Seq[PluginBase]) + + class Impl( + config: BootstrapConfig, + ) extends PluginSource { + + def load(): AllLoadedPlugins = { + val bsl = mkBootstrapLoader().load() + val l = mkLoader().load() + AllLoadedPlugins(bsl, l) + } + + protected def mkBootstrapLoader(): PluginLoader = { + config.bootstrapPluginConfig.fold(PluginLoader.empty)(PluginLoader(_)) + } + + protected def mkLoader(): PluginLoader = { + PluginLoader(config.pluginConfig) + } + } } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSourceImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSourceImpl.scala deleted file mode 100644 index ff03c379e1..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PluginSourceImpl.scala +++ /dev/null @@ -1,20 +0,0 @@ -package izumi.distage.roles.services - -import izumi.distage.plugins.load.PluginLoader -import izumi.distage.roles.BootstrapConfig -import izumi.distage.roles.services.PluginSource.AllLoadedPlugins - -class PluginSourceImpl(config: BootstrapConfig) extends PluginSource { - def load(): AllLoadedPlugins = { - val bsl = mkBootstrapLoader().load() - val l = mkLoader().load() - AllLoadedPlugins(bsl, l) - } - def mkBootstrapLoader(): PluginLoader = { - config.bootstrapPluginConfig.fold(PluginLoader.empty)(PluginLoader(_)) - } - - def mkLoader(): PluginLoader = { - PluginLoader(config.pluginConfig) - } -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PruningPlanMergingPolicy.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PruningPlanMergingPolicy.scala index a5f01a33a0..080ac1d249 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PruningPlanMergingPolicy.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/PruningPlanMergingPolicy.scala @@ -1,5 +1,6 @@ package izumi.distage.roles.services +import distage.DIKey import izumi.distage.model.definition.BindingTag import izumi.distage.model.plan.{DodgyPlan, ExecutableOp, SemiPlan} import izumi.distage.model.planning.PlanMergingPolicy.DIKeyConflictResolution @@ -8,7 +9,6 @@ import izumi.distage.planning.PlanMergingPolicyDefaultImpl import izumi.distage.planning.gc.TracingDIGC import izumi.distage.roles.model.AppActivation import izumi.logstage.api.IzLogger -import distage.DIKey class PruningPlanMergingPolicy( logger: IzLogger, @@ -24,7 +24,9 @@ class PruningPlanMergingPolicy( .filter { op => op.binding.tags - .collect({ case BindingTag.AxisTag(t) => t }) + .collect({ + case BindingTag.AxisTag(t) => t + }) .forall(t => activeTags.contains(t)) } @@ -70,12 +72,16 @@ class PruningPlanMergingPolicy( } } - val failed = lastTry.collect({ case (k, f: DIKeyConflictResolution.Failed) => k -> f }) + val failed = lastTry.collect({ + case (k, f: DIKeyConflictResolution.Failed) => k -> f + }) if (failed.nonEmpty) { throwOnIssues(failed) } else { - val good = lastTry.collect({ case (k, DIKeyConflictResolution.Successful(s)) => k -> s }) + val good = lastTry.collect({ + case (k, DIKeyConflictResolution.Successful(s)) => k -> s + }) val erased = good.filter(_._2.isEmpty) logger.info(s"${erased.keys.niceList() -> "erased conflicts"}") logger.warn(s"Pruning strategy successfully resolved ${issues.size -> "conlicts"}, ${erased.size -> "erased"}, continuing...") @@ -92,8 +98,12 @@ class PruningPlanMergingPolicy( .toSeq .map { f => - val bindingTags = f.binding.tags.collect({ case BindingTag.AxisTag(t) => t }).diff(activeTags) - val alreadyActiveTags = f.binding.tags.collect({ case BindingTag.AxisTag(t) => t }).intersect(activeTags) + val bindingTags = f.binding.tags.collect({ + case BindingTag.AxisTag(t) => t + }).diff(activeTags) + val alreadyActiveTags = f.binding.tags.collect({ + case BindingTag.AxisTag(t) => t + }).intersect(activeTags) s"${f.binding.origin}, possible: {${bindingTags.mkString(", ")}}, active: {${alreadyActiveTags.mkString(", ")}}" } } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutor.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutor.scala index 7bfba4eec6..ce05e63e89 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutor.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutor.scala @@ -1,8 +1,148 @@ package izumi.distage.roles.services +import distage.{Injector, TagK} +import izumi.distage.model.Locator +import izumi.distage.model.monadic.DIEffect +import izumi.distage.model.monadic.DIEffect.syntax._ +import izumi.distage.roles._ +import izumi.distage.roles.model.meta.RolesInfo +import izumi.distage.roles.model.{AbstractRoleF, DiAppBootstrapException, RoleService, RoleTask} import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans +import izumi.distage.roles.services.StartupPlanExecutor.Filters +import izumi.fundamentals.platform.cli.model.raw.RawAppArgs +import izumi.logstage.api.IzLogger trait RoleAppExecutor[F[_]] { def runPlan(appPlan: AppStartupPlans): Unit } +object RoleAppExecutor { + + class Impl[F[_] : TagK]( + protected val hook: AppShutdownStrategy[F], + roles: RolesInfo, + injector: Injector, + lateLogger: IzLogger, + parameters: RawAppArgs, + ) extends RoleAppExecutor[F] { + + final def runPlan(appPlan: AppStartupPlans): Unit = { + try { + makeStartupExecutor().execute(appPlan, Filters.all[F])(doRun) + } finally { + hook.release() + } + } + + protected def makeStartupExecutor(): StartupPlanExecutor = { + StartupPlanExecutor.default(lateLogger, injector) + } + + protected def doRun(locator: Locator, effect: DIEffect[F]): F[Unit] = { + val roleIndex = getRoleIndex(locator) + implicit val e: DIEffect[F] = effect + for { + _ <- runTasks(roleIndex) + _ <- runRoles(roleIndex) + } yield () + } + + protected def runRoles(index: Map[String, AbstractRoleF[F]])(implicit effect: DIEffect[F]): F[Unit] = { + val rolesToRun = parameters.roles.flatMap { + r => + index.get(r.role) match { + case Some(_: RoleTask[F]) => + Seq.empty + case Some(value: RoleService[F]) => + Seq(value -> r) + case Some(v) => + throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} has unexpected type: $v") + case None => + throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} is missing") + } + } + + if (rolesToRun.nonEmpty) { + lateLogger.info(s"Going to run: ${rolesToRun.size -> "roles"}") + + val tt = rolesToRun.map { + case (task, cfg) => + + task.start(cfg.roleParameters, cfg.freeArgs) + } + + val finalizer = (_: Unit) => { + hook.await(lateLogger) + } + val f = tt.foldLeft(finalizer) { + case (acc, role) => + _ => + val loggedTask = for { + _ <- effect.maybeSuspend(lateLogger.info(s"Role is about to initialize: $role")) + _ <- role.use(acc) + _ <- effect.maybeSuspend(lateLogger.info(s"Role initialized: $role")) + } yield () + + effect.definitelyRecover(loggedTask) { + t => + for { + _ <- effect.maybeSuspend(lateLogger.error(s"Role $role failed: $t")) + _ <- effect.fail[Unit](t) + } yield () + } + } + f(()) + } else { + effect.maybeSuspend(lateLogger.info("No services to run, exiting...")) + } + } + + protected def runTasks(index: Map[String, Object])(implicit effect: DIEffect[F]): F[Unit] = { + val tasksToRun = parameters.roles.flatMap { + r => + index.get(r.role) match { + case Some(value: RoleTask[F]) => + Seq(value -> r) + case Some(_: RoleService[F]) => + Seq.empty + case Some(v) => + throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} has unexpected type: $v") + case None => + throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} is missing") + } + } + + lateLogger.info(s"Going to run: ${tasksToRun.size -> "tasks"}") + + effect.traverse_(tasksToRun) { + case (task, cfg) => + val loggedTask = for { + _ <- effect.maybeSuspend(lateLogger.info(s"Task is about to start: $task")) + _ <- task.start(cfg.roleParameters, cfg.freeArgs) + _ <- effect.maybeSuspend(lateLogger.info(s"Task finished: $task")) + } yield () + + effect.definitelyRecover(loggedTask) { + error => + for { + _ <- effect.maybeSuspend(lateLogger.error(s"Task failed: $task, $error")) + _ <- effect.fail[Unit](error) + } yield () + } + } + } + + private def getRoleIndex(rolesLocator: Locator): Map[String, AbstractRoleF[F]] = { + roles.availableRoleBindings.flatMap { + b => + rolesLocator.index.get(b.binding.key) match { + case Some(value: AbstractRoleF[F]) => + Seq(b.descriptor.id -> value) + case _ => + Seq.empty + } + }.toMap + } + } + +} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutorImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutorImpl.scala deleted file mode 100644 index 256e1bab47..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppExecutorImpl.scala +++ /dev/null @@ -1,141 +0,0 @@ -package izumi.distage.roles.services - -import izumi.distage.model.Locator -import izumi.distage.model.monadic.DIEffect -import izumi.distage.model.monadic.DIEffect.syntax._ -import izumi.distage.roles._ -import izumi.distage.roles.model.meta.RolesInfo -import izumi.distage.roles.model.{AbstractRoleF, DiAppBootstrapException, RoleService, RoleTask} -import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans -import izumi.distage.roles.services.StartupPlanExecutor.Filters -import izumi.fundamentals.platform.cli.model.raw.RawAppArgs -import izumi.logstage.api.IzLogger -import distage.{Injector, TagK} - -class RoleAppExecutorImpl[F[_] : TagK]( - protected val hook: AppShutdownStrategy[F], - roles: RolesInfo, - injector: Injector, - lateLogger: IzLogger, - parameters: RawAppArgs, - ) extends RoleAppExecutor[F] { - - final def runPlan(appPlan: AppStartupPlans): Unit = { - try { - makeStartupExecutor().execute(appPlan, Filters.all[F])(doRun) - } finally { - hook.release() - } - } - - protected def makeStartupExecutor(): StartupPlanExecutor = { - StartupPlanExecutor.default(lateLogger, injector) - } - - protected def doRun(locator: Locator, effect: DIEffect[F]): F[Unit] = { - val roleIndex = getRoleIndex(locator) - implicit val e: DIEffect[F] = effect - for { - _ <- runTasks(roleIndex) - _ <- runRoles(roleIndex) - } yield () - } - - protected def runRoles(index: Map[String, AbstractRoleF[F]])(implicit effect: DIEffect[F]): F[Unit] = { - val rolesToRun = parameters.roles.flatMap { - r => - index.get(r.role) match { - case Some(_: RoleTask[F]) => - Seq.empty - case Some(value: RoleService[F]) => - Seq(value -> r) - case Some(v) => - throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} has unexpected type: $v") - case None => - throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} is missing") - } - } - -if (rolesToRun.nonEmpty) { - lateLogger.info(s"Going to run: ${rolesToRun.size -> "roles"}") - - val tt = rolesToRun.map { - case (task, cfg) => - - task.start(cfg.roleParameters, cfg.freeArgs) - } - - val finalizer = (_: Unit) => { - hook.await(lateLogger) - } - val f = tt.foldLeft(finalizer) { - case (acc, role) => - _ => - val loggedTask = for { - _ <- effect.maybeSuspend(lateLogger.info(s"Role is about to initialize: $role")) - _ <- role.use(acc) - _ <- effect.maybeSuspend(lateLogger.info(s"Role initialized: $role")) - } yield () - - effect.definitelyRecover(loggedTask) { - t => - for { - _ <- effect.maybeSuspend(lateLogger.error(s"Role $role failed: $t")) - _ <- effect.fail[Unit](t) - } yield () - } - } - f(()) - } else { - effect.maybeSuspend(lateLogger.info("No services to run, exiting...")) - } - } - -protected def runTasks(index: Map[String, Object])(implicit effect: DIEffect[F]): F[Unit] = { - val tasksToRun = parameters.roles.flatMap { - r => - index.get(r.role) match { - case Some(value: RoleTask[F]) => - Seq(value -> r) - case Some(_: RoleService[F]) => - Seq.empty - case Some(v) => - throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} has unexpected type: $v") - case None => - throw new DiAppBootstrapException(s"Inconsistent state: requested entrypoint ${r.role} is missing") - } - } - - lateLogger.info(s"Going to run: ${tasksToRun.size -> "tasks"}") - - effect.traverse_(tasksToRun) { - case (task, cfg) => - val loggedTask = for { - _ <- effect.maybeSuspend(lateLogger.info(s"Task is about to start: $task")) - _ <- task.start(cfg.roleParameters, cfg.freeArgs) - _ <- effect.maybeSuspend(lateLogger.info(s"Task finished: $task")) - } yield () - - effect.definitelyRecover(loggedTask) { - error => - for { - _ <- effect.maybeSuspend(lateLogger.error(s"Task failed: $task, $error")) - _ <- effect.fail[Unit](error) - } yield () - } - } - } - - private def getRoleIndex(rolesLocator: Locator): Map[String, AbstractRoleF[F]] = { - roles.availableRoleBindings.flatMap { - b => - rolesLocator.index.get(b.binding.key) match { - case Some(value: AbstractRoleF[F]) => - Seq(b.descriptor.id -> value) - case _ => - Seq.empty - } - }.toMap - } - -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala index 1694ae4f23..04c380a816 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala @@ -1,9 +1,13 @@ package izumi.distage.roles.services -import izumi.distage.model.definition.ModuleBase +import distage.{BootstrapModule, DIKey, Injector, TagK, _} +import izumi.distage.model.definition.{ModuleBase, ModuleDef} +import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} import izumi.distage.model.plan.OrderedPlan +import izumi.distage.roles.model.{AppActivation, IntegrationCheck} +import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans -import distage.{BootstrapModule, DIKey, Injector} +import izumi.logstage.api.IzLogger trait RoleAppPlanner[F[_]] { def reboot(bsModule: BootstrapModule): RoleAppPlanner[F] @@ -16,6 +20,54 @@ object RoleAppPlanner { integration: OrderedPlan, integrationKeys: Set[DIKey], app: OrderedPlan, - injector: Injector + injector: Injector, ) + + class Impl[F[_] : TagK]( + options: ContextOptions, + bsModule: BootstrapModule, + activation: AppActivation, + logger: IzLogger, + ) extends RoleAppPlanner[F] { + self => + + private val injector = Injector.Standard(bsModule) + + override def reboot(bsOverride: BootstrapModule): RoleAppPlanner[F] = { + new RoleAppPlanner.Impl[F](options, bsModule overridenBy bsOverride, activation, logger) + } + + override def makePlan(appMainRoots: Set[DIKey], appModule: ModuleBase): AppStartupPlans = { + val fullAppModule = appModule + .overridenBy(new ModuleDef { + make[RoleAppPlanner[F]].from(self) + make[ContextOptions].from(options) + make[ModuleBase].named("application.module").from(appModule) + }) + + val runtimeGcRoots: Set[DIKey] = Set( + DIKey.get[DIEffectRunner[F]], + DIKey.get[DIEffect[F]], + ) + val runtimePlan = injector.plan(PlannerInput(fullAppModule, runtimeGcRoots)) + + val appPlan = injector.splitPlan(fullAppModule.drop(runtimeGcRoots), appMainRoots) { + _.collectChildren[IntegrationCheck].map(_.target).toSet + } + + val check = new PlanCircularDependencyCheck(options, logger) + check.verify(runtimePlan) + check.verify(appPlan.subplan) + check.verify(appPlan.primary) + + AppStartupPlans( + runtimePlan, + appPlan.subplan, + appPlan.subRoots, + appPlan.primary, + injector + ) + } + } + } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlannerImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlannerImpl.scala deleted file mode 100644 index 3e7f65451d..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlannerImpl.scala +++ /dev/null @@ -1,56 +0,0 @@ -package izumi.distage.roles.services - -import izumi.distage.model.definition.{ModuleBase, ModuleDef} -import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} -import izumi.distage.roles.model.{AppActivation, IntegrationCheck} -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions -import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans -import izumi.logstage.api.IzLogger -import distage._ - -class RoleAppPlannerImpl[F[_] : TagK]( - options: ContextOptions, - bsModule: BootstrapModule, - activation: AppActivation, - logger: IzLogger, - ) extends RoleAppPlanner[F] { - - private val injector = Injector.Standard(bsModule) - - override def reboot(bsOverride: BootstrapModule): RoleAppPlanner[F] = { - new RoleAppPlannerImpl[F](options, bsModule overridenBy bsOverride, activation, logger) - } - - override def makePlan(appMainRoots: Set[DIKey], appModule: ModuleBase): AppStartupPlans = { - val fullAppModule = appModule - .overridenBy(new ModuleDef { - make[RoleAppPlanner[F]].from(RoleAppPlannerImpl.this) - make[ContextOptions].from(options) - make[ModuleBase].named("application.module").from(appModule) - }) - - val runtimeGcRoots: Set[DIKey] = Set( - DIKey.get[DIEffectRunner[F]], - DIKey.get[DIEffect[F]], - ) - val runtimePlan = injector.plan(PlannerInput(fullAppModule, runtimeGcRoots)) - - val appPlan = injector.splitPlan(fullAppModule.drop(runtimeGcRoots), appMainRoots) { - _.collectChildren[IntegrationCheck].map(_.target).toSet - } - - val check = new PlanCircularDependencyCheck(options, logger) - check.verify(runtimePlan) - check.verify(appPlan.subplan) - check.verify(appPlan.primary) - - AppStartupPlans( - runtimePlan, - appPlan.subplan, - appPlan.subRoots, - appPlan.primary, - injector - ) - } -} - diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProvider.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProvider.scala index 968bd7afef..f92fdcf68e 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProvider.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProvider.scala @@ -1,8 +1,91 @@ package izumi.distage.roles.services +import distage._ import izumi.distage.model.definition.Binding -import izumi.distage.roles.model.meta.RolesInfo +import izumi.distage.model.definition.Binding.ImplBinding +import izumi.distage.model.reflection.universe.MirrorProvider +import izumi.distage.model.reflection.universe.RuntimeDIUniverse.SafeType +import izumi.distage.roles.model.meta.{RoleBinding, RolesInfo} +import izumi.distage.roles.model.{AbstractRoleF, RoleDescriptor} +import izumi.fundamentals.platform.resources.IzManifest +import izumi.logstage.api.IzLogger + +import scala.reflect.ClassTag trait RoleProvider[F[_]] { def getInfo(bindings: Seq[Binding]): RolesInfo } + +object RoleProvider { + + class Impl[F[_] : TagK]( + logger: IzLogger, + requiredRoles: Set[String], + mirrorProvider: MirrorProvider, + ) extends RoleProvider[F] { + + def getInfo(bindings: Seq[Binding]): RolesInfo = { + val availableBindings = getRoles(bindings) + + val roles = availableBindings.map(_.descriptor.id) + + val enabledRoles = availableBindings + .filter(b => isEnabledRole(b)) + + RolesInfo( + enabledRoles.map(_.binding.key).toSet, + enabledRoles, + roles, + availableBindings, + roles.toSet.diff(requiredRoles), + ) + } + + private def getRoles(bb: Seq[Binding]): Seq[RoleBinding] = { + bb.flatMap { + b => + b match { + case s: ImplBinding if isAvailableRoleType(s.implementation.implType) => + Seq((b, s.implementation.implType)) + + case _ => + Seq.empty + } + }.flatMap { + case (rb, impltype) => + getDescriptor(rb.key.tpe) match { + case Some(d) => + val runtimeClass = impltype.use(mirrorProvider.mirror.runtimeClass) + val src = IzManifest.manifest()(ClassTag(runtimeClass)).map(IzManifest.read) + Seq(RoleBinding(rb, runtimeClass, impltype, d, src)) + case None => + logger.error(s"${rb.key -> "role"} defined ${rb.origin -> "at"} has no companion object inherited from RoleDescriptor thus ignored") + Seq.empty + } + } + } + + private def isEnabledRole(b: RoleBinding): Boolean = { + requiredRoles.contains(b.descriptor.id) || requiredRoles.contains(b.tpe.use(_.typeSymbol.name.decodedName.toString.toLowerCase)) + } + + private def isAvailableRoleType(tpe: SafeType): Boolean = { + tpe <:< SafeType.get[AbstractRoleF[F]] + } + + private def getDescriptor(role: SafeType): Option[RoleDescriptor] = { + try { + role.use(t => mirrorProvider.mirror.reflectModule(t.dealias.companion.typeSymbol.asClass.module.asModule).instance) match { + case rd: RoleDescriptor => Some(rd) + case _ => None + } + } catch { + case t: Throwable => + logger.error(s"Failed to reflect descriptor for $role: $t") + None + } + } + + } + +} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProviderImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProviderImpl.scala deleted file mode 100644 index 500515d554..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleProviderImpl.scala +++ /dev/null @@ -1,87 +0,0 @@ -package izumi.distage.roles.services - -import _root_.distage._ -import izumi.distage.model.definition.Binding -import izumi.distage.model.definition.Binding.ImplBinding -import izumi.distage.model.reflection.universe.MirrorProvider -import izumi.distage.model.reflection.universe.RuntimeDIUniverse.SafeType -import izumi.distage.roles.model.meta.{RoleBinding, RolesInfo} -import izumi.distage.roles.model.{AbstractRoleF, RoleDescriptor, meta} -import izumi.fundamentals.platform.resources.IzManifest -import izumi.logstage.api.IzLogger - -import scala.reflect.ClassTag - -class RoleProviderImpl[F[_] : TagK]( - logger: IzLogger, - requiredRoles: Set[String], - mirrorProvider: MirrorProvider, - ) extends RoleProvider[F] { - - def getInfo(bindings: Seq[Binding]): RolesInfo = { - val availableBindings = getRoles(bindings) - - val roles = availableBindings.map(_.descriptor.id) - - val enabledRoles = availableBindings - .filter(b => isEnabledRole(b)) - - meta.RolesInfo( - enabledRoles.map(_.binding.key).toSet - , enabledRoles - , roles - , availableBindings - , roles.toSet.diff(requiredRoles - ) - ) - } - - private def getRoles(bb: Seq[Binding]): Seq[RoleBinding] = { - bb - .flatMap { - b => - b match { - case s: ImplBinding if isAvailableRoleType(s.implementation.implType) => - Seq((b, s.implementation.implType)) - - case _ => - Seq.empty - } - } - .flatMap { - case (rb, impltype) => - getDescriptor(rb.key.tpe) match { - case Some(d) => - val runtimeClass = impltype.use(mirrorProvider.mirror.runtimeClass) - val src = IzManifest.manifest()(ClassTag(runtimeClass)).map(IzManifest.read) - Seq(RoleBinding(rb, runtimeClass, impltype, d, src)) - case None => - logger.error(s"${rb.key -> "role"} defined ${rb.origin -> "at"} has no companion object inherited from RoleDescriptor thus ignored") - Seq.empty - } - - } - } - - private def isEnabledRole(b: RoleBinding): Boolean = { - requiredRoles.contains(b.descriptor.id) || requiredRoles.contains(b.tpe.use(_.typeSymbol.name.decodedName.toString.toLowerCase)) - } - - private def isAvailableRoleType(tpe: SafeType): Boolean = { - tpe <:< SafeType.get[AbstractRoleF[F]] - } - - private def getDescriptor(role: SafeType): Option[RoleDescriptor] = { - try { - role.use(t => mirrorProvider.mirror.reflectModule(t.dealias.companion.typeSymbol.asClass.module.asModule).instance) match { - case rd: RoleDescriptor => Some(rd) - case _ => None - } - } catch { - case t: Throwable => - logger.error(s"Failed to reflect descriptor for $role: $t") - None - } - } - -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutor.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutor.scala index dc0775a35d..44a0d5292f 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutor.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutor.scala @@ -1,11 +1,12 @@ package izumi.distage.roles.services -import izumi.distage.model.monadic.DIEffect +import distage.{Injector, TagK} +import izumi.distage.model.Locator +import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} import izumi.distage.model.provisioning.PlanInterpreter.FinalizersFilter import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans import izumi.fundamentals.platform.functional.Identity import izumi.logstage.api.IzLogger -import distage.{Injector, Locator, TagK} trait StartupPlanExecutor { def execute[F[_] : TagK](appPlan: AppStartupPlans, filters: StartupPlanExecutor.Filters[F])(doRun: (Locator, DIEffect[F]) => F[Unit]): Unit @@ -13,16 +14,44 @@ trait StartupPlanExecutor { object StartupPlanExecutor { def default(logger: IzLogger, injector: Injector): StartupPlanExecutor = { - val checker = new IntegrationCheckerImpl(logger) - new StartupPlanExecutorImpl(injector, checker) + val checker = new IntegrationChecker.Impl(logger) + new StartupPlanExecutor.Impl(injector, checker) } -case class Filters[F[_]]( - filterF: FinalizersFilter[F], - filterId: FinalizersFilter[Identity], - ) - + final case class Filters[F[_]]( + filterF: FinalizersFilter[F], + filterId: FinalizersFilter[Identity], + ) object Filters { def all[F[_]]: Filters[F] = Filters[F](FinalizersFilter.all, FinalizersFilter.all) } + + class Impl( + injector: Injector, + integrationChecker: IntegrationChecker, + ) extends StartupPlanExecutor { + final def execute[F[_] : TagK](appPlan: AppStartupPlans, filters: StartupPlanExecutor.Filters[F])(doRun: (Locator, DIEffect[F]) => F[Unit]): Unit = { + injector.produceFX[Identity](appPlan.runtime, filters.filterId) + .use { + runtimeLocator => + val runner = runtimeLocator.get[DIEffectRunner[F]] + implicit val effect: DIEffect[F] = runtimeLocator.get[DIEffect[F]] + + runner.run { + Injector.inherit(runtimeLocator) + .produceFX[F](appPlan.integration, filters.filterF) + .use { + integrationLocator => + integrationChecker.checkOrFail(appPlan.integrationKeys, integrationLocator) + + Injector.inherit(integrationLocator) + .produceFX[F](appPlan.app, filters.filterF) + .use(doRun(_, effect)) + } + } + } + } + + } + } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutorImpl.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutorImpl.scala deleted file mode 100644 index 1c65f426aa..0000000000 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/StartupPlanExecutorImpl.scala +++ /dev/null @@ -1,36 +0,0 @@ -package izumi.distage.roles.services - -import izumi.distage.model.Locator -import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} -import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans -import izumi.fundamentals.platform.functional.Identity -import distage.{Injector, TagK} - -class StartupPlanExecutorImpl( - injector: Injector, - integrationChecker: IntegrationChecker - ) extends StartupPlanExecutor { - final def execute[F[_] : TagK](appPlan: AppStartupPlans, filters: StartupPlanExecutor.Filters[F])(doRun: (Locator, DIEffect[F]) => F[Unit]): Unit = { - - injector.produceFX[Identity](appPlan.runtime, filters.filterId) - .use { - runtimeLocator => - val runner = runtimeLocator.get[DIEffectRunner[F]] - implicit val effect: DIEffect[F] = runtimeLocator.get[DIEffect[F]] - - runner.run { - Injector.inherit(runtimeLocator) - .produceFX[F](appPlan.integration, filters.filterF) - .use { - integrationLocator => - integrationChecker.checkOrFail(appPlan.integrationKeys, integrationLocator) - -Injector.inherit(integrationLocator) - .produceFX[F](appPlan.app, filters.filterF) - .use(doRun(_, effect)) - } - } - } - } - -} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/ModuleRequirements.scala b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/ModuleRequirements.scala index a7a4ff2859..148c091b7f 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/ModuleRequirements.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/ModuleRequirements.scala @@ -1,20 +1,20 @@ package izumi.distage.staticinjector.plugins +import distage.DIKey import izumi.distage.model.LoggerHook import izumi.distage.model.planning.PlanningObserver import izumi.logstage.api.IzLogger import izumi.logstage.api.Log.CustomContext import izumi.logstage.api.logger.LogRouter -import distage.DIKey class ModuleRequirements(val requiredKeys: Set[DIKey]) class NoModuleRequirements extends ModuleRequirements(Set.empty) class LogstageModuleRequirements extends ModuleRequirements(Set( - DIKey.get[LogRouter] -, DIKey.get[CustomContext] -, DIKey.get[IzLogger] -, DIKey.get[Set[PlanningObserver]] -, DIKey.get[LoggerHook] + DIKey.get[LogRouter], + DIKey.get[CustomContext], + DIKey.get[IzLogger], + DIKey.get[Set[PlanningObserver]], + DIKey.get[LoggerHook], )) diff --git a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/StaticPluginChecker.scala b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/StaticPluginChecker.scala index fbb76e7fe2..26be6b2d12 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/StaticPluginChecker.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/StaticPluginChecker.scala @@ -1,18 +1,13 @@ package izumi.distage.staticinjector.plugins -import izumi.distage.staticinjector.plugins.macrodefs.StaticPluginCheckerMacro import distage.plugins.PluginBase +import izumi.distage.staticinjector.plugins.macrodefs.StaticPluginCheckerMacro import scala.language.experimental.macros object StaticPluginChecker { - def check[GcRoot <: PluginBase, R <: ModuleRequirements](activations: String): Unit = macro StaticPluginCheckerMacro.implDefault[GcRoot, R] - def checkWithConfig[GcRoot <: PluginBase, R <: ModuleRequirements](activations: String, configFileRegex: String): Unit = macro StaticPluginCheckerMacro.implWithConfig[GcRoot, R] - def checkWithPlugins[GcRoot <: PluginBase, R <: ModuleRequirements](pluginPath: String, activations: String): Unit = macro StaticPluginCheckerMacro.implWithPlugin[GcRoot, R] - def checkWithPluginsConfig[GcRoot <: PluginBase, R <: ModuleRequirements](pluginPath: String, activations: String, configFileRegex: String): Unit = macro StaticPluginCheckerMacro.implWithPluginConfig[GcRoot, R] - } diff --git a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala index 94405edd0c..396b0e8903 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala @@ -1,5 +1,8 @@ package izumi.distage.staticinjector.plugins.macrodefs +import com.typesafe.config.ConfigFactory +import distage._ +import io.github.classgraph.ClassGraph import izumi.distage.bootstrap.BootstrapLocator import izumi.distage.config.annotations.AbstractConfId import izumi.distage.config.model.AppConfig @@ -20,53 +23,51 @@ import izumi.distage.staticinjector.plugins.ModuleRequirements import izumi.fundamentals.platform.cli.model.raw.{RawAppArgs, RawEntrypointParams, RawValue} import izumi.fundamentals.reflection.TreeTools import izumi.logstage.api.IzLogger -import com.typesafe.config.ConfigFactory -import distage._ -import io.github.classgraph.ClassGraph import scala.collection.JavaConverters._ -import scala.reflect.ClassTag import scala.reflect.macros.blackbox import scala.reflect.runtime.currentMirror +import scala.reflect.{ClassTag, classTag} object StaticPluginCheckerMacro { - def implDefault[T <: PluginBase: c.WeakTypeTag, R <: ModuleRequirements: c.WeakTypeTag](c: blackbox.Context)(activations: c.Expr[String]): c.Expr[Unit] = { + def implDefault[T <: PluginBase : c.WeakTypeTag, R <: ModuleRequirements : c.WeakTypeTag](c: blackbox.Context)(activations: c.Expr[String]): c.Expr[Unit] = { import c.universe._ implWithPluginConfig[T, R](c)(c.Expr[String](q"${""}"), activations, c.Expr[String](q"${""}")) } - def implWithConfig[T <: PluginBase: c.WeakTypeTag, R <: ModuleRequirements: c.WeakTypeTag](c: blackbox.Context)(activations: c.Expr[String], configFileRegex: c.Expr[String]): c.Expr[Unit] = { + def implWithConfig[T <: PluginBase : c.WeakTypeTag, R <: ModuleRequirements : c.WeakTypeTag](c: blackbox.Context)(activations: c.Expr[String], configFileRegex: c.Expr[String]): c.Expr[Unit] = { import c.universe._ implWithPluginConfig[T, R](c)(c.Expr[String](q"${""}"), activations, configFileRegex) } - def implWithPlugin[T <: PluginBase: c.WeakTypeTag, R <: ModuleRequirements: c.WeakTypeTag](c: blackbox.Context)(pluginPath: c.Expr[String], activations: c.Expr[String]): c.Expr[Unit] = { + def implWithPlugin[T <: PluginBase : c.WeakTypeTag, R <: ModuleRequirements : c.WeakTypeTag](c: blackbox.Context)(pluginPath: c.Expr[String], activations: c.Expr[String]): c.Expr[Unit] = { import c.universe._ implWithPluginConfig[T, R](c)(pluginPath, activations, c.Expr[String](q"${""}")) } - def implWithPluginConfig[T <: PluginBase: c.WeakTypeTag, R <: ModuleRequirements: c.WeakTypeTag](c: blackbox.Context)(pluginPath: c.Expr[String], activations: c.Expr[String], configFileRegex: c.Expr[String]): c.Expr[Unit] = { + def implWithPluginConfig[T <: PluginBase : c.WeakTypeTag, R <: ModuleRequirements : c.WeakTypeTag](c: blackbox.Context)(pluginPath: c.Expr[String], activations: c.Expr[String], configFileRegex: c.Expr[String]): c.Expr[Unit] = { import c.universe._ StaticPluginCheckerMacro.check(c)( - pluginPath - , c.Expr[String](q"${weakTypeOf[T].typeSymbol.asClass.fullName}") - , c.Expr[String](q"${weakTypeOf[R].typeSymbol.asClass.fullName}") - , activations - , configFileRegex + pluginPath, + c.Expr[String](q"${weakTypeOf[T].typeSymbol.asClass.fullName}"), + c.Expr[String](q"${weakTypeOf[R].typeSymbol.asClass.fullName}"), + activations, + configFileRegex, ) } def check(c: blackbox.Context) - ( pluginsPackage: c.Expr[String] - , gcRoot: c.Expr[String] - , requirements: c.Expr[String] - , activations: c.Expr[String] - , configFileRegex: c.Expr[String] + ( + pluginsPackage: c.Expr[String], + gcRoot: c.Expr[String], + requirements: c.Expr[String], + activations: c.Expr[String], + configFileRegex: c.Expr[String], ): c.Expr[Unit] = { val abort = c.abort(c.enclosingPosition, _: String): Unit @@ -127,13 +128,13 @@ object StaticPluginCheckerMacro { } def check( - loadedPlugins: Seq[PluginBase] - , configModule: Option[ConfigModule] - , additional: ModuleBase - , root: Option[ModuleBase] - , moduleRequirements: Option[ModuleRequirements] - , activations: Seq[String] - , abort: String => Unit + loadedPlugins: Seq[PluginBase], + configModule: Option[ConfigModule], + additional: ModuleBase, + root: Option[ModuleBase], + moduleRequirements: Option[ModuleRequirements], + activations: Seq[String], + abort: String => Unit, ): Unit = { val module = SimplePluginMergeStrategy.merge(loadedPlugins :+ additional.morph[PluginBase] :+ root.toList.merge.morph[PluginBase]) @@ -180,7 +181,7 @@ object StaticPluginCheckerMacro { ) } - private[this] def constructClass[T: ClassTag: ru.TypeTag](path: String, abort: String => Unit): T = { + private[this] def constructClass[T: ClassTag : ru.TypeTag](path: String, abort: String => Unit): T = { val mirror: ru.Mirror = currentMirror val clazz = mirror.staticClass(path) @@ -190,14 +191,17 @@ object StaticPluginCheckerMacro { abort(s"""Can't construct a value of `$expectTpe` from class found at "$path" - its class `$tpe` is NOT a subtype of `$expectTpe`!""") } - implicitly[ClassTag[T]].runtimeClass.cast { - mirror.reflectClass(clazz) - .reflectConstructor(tpe.decls.collectFirst { case m: ru.MethodSymbol@unchecked if m.isPrimaryConstructor => m }.get) - .apply() - }.asInstanceOf[T] + val instance = mirror.reflectClass(clazz) + .reflectConstructor { + tpe.decls.collectFirst { + case m: ru.MethodSymbol@unchecked if m.isPrimaryConstructor => m + }.get + }.apply() + + classTag[T].runtimeClass.cast(instance).asInstanceOf[T] } -// FIXME: move to distage-model + // FIXME: move to distage-model // blockers: AbstractConfId implicit final class OrderedPlanCheck(private val plan: OrderedPlan) { diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironment.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironment.scala index 3eb76b0288..81fb252765 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironment.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironment.scala @@ -1,12 +1,13 @@ package izumi.distage.testkit.services.dstest +import distage.config.AppConfig +import distage.{DIKey, ModuleBase} import izumi.distage.model.definition.BootstrapModule import izumi.distage.roles.model.AppActivation import izumi.distage.roles.model.meta.RolesInfo -import izumi.distage.roles.services.{ConfigLoader, ModuleProvider, ModuleProviderImpl} +import izumi.distage.roles.config.ContextOptions +import izumi.distage.roles.services.{ConfigLoader, ModuleProvider} import izumi.logstage.api.{IzLogger, Log} -import distage.config.AppConfig -import distage.{DIKey, ModuleBase} trait DistageTestEnvironment[F[_]] { @@ -21,9 +22,9 @@ trait DistageTestEnvironment[F[_]] { def makeLogger(): IzLogger - def contextOptions(): ModuleProviderImpl.ContextOptions + def contextOptions(): ContextOptions def makeConfigLoader(logger: IzLogger): ConfigLoader - def makeModuleProvider(options: ModuleProviderImpl.ContextOptions, config: AppConfig, lateLogger: IzLogger, roles: RolesInfo, activation: AppActivation): ModuleProvider[F] + def makeModuleProvider(options: ContextOptions, config: AppConfig, lateLogger: IzLogger, roles: RolesInfo, activation: AppActivation): ModuleProvider[F] } diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala index 54d4117f7f..e8f5ba0644 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala @@ -1,5 +1,7 @@ package izumi.distage.testkit.services.dstest +import distage.config.AppConfig +import distage.{DIKey, ModuleBase} import izumi.distage.config.ConfigInjectionOptions import izumi.distage.model.Locator.LocatorRef import izumi.distage.model.definition.Binding.SingletonBinding @@ -7,17 +9,15 @@ import izumi.distage.model.definition.{BootstrapModule, ImplDef, Module} import izumi.distage.model.reflection.universe.RuntimeDIUniverse.TagK import izumi.distage.roles.model.AppActivation import izumi.distage.roles.model.meta.RolesInfo -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions +import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.services.ResourceRewriter.RewriteRules -import izumi.distage.roles.services.{ConfigLoader, ConfigLoaderLocalFSImpl, ModuleProvider, ModuleProviderImpl} +import izumi.distage.roles.services.{ConfigLoader, ModuleProvider} import izumi.fundamentals.platform.cli.model.raw.RawAppArgs +import izumi.fundamentals.reflection.CodePositionMaterializer import izumi.logstage.api.IzLogger import izumi.logstage.api.Log.Level -import distage.config.AppConfig -import distage.{DIKey, ModuleBase} -import izumi.fundamentals.reflection.CodePositionMaterializer -class DistageTestEnvironmentImpl[F[_]: TagK](suiteClass: Class[_]) extends DistageTestEnvironment[F] { +class DistageTestEnvironmentImpl[F[_] : TagK](suiteClass: Class[_]) extends DistageTestEnvironment[F] { /** Override this to disable instantiation of fixture parameters that aren't bound in `makeBindings` */ def addUnboundParametersAsRoots(roots: Set[DIKey], primaryModule: ModuleBase): ModuleBase = { val paramsModule = Module.make { @@ -32,7 +32,6 @@ class DistageTestEnvironmentImpl[F[_]: TagK](suiteClass: Class[_]) extends Dista paramsModule overridenBy primaryModule } - def bootstrapOverride: BootstrapModule = BootstrapModule.empty def appOverride: ModuleBase = Module.empty @@ -59,13 +58,12 @@ class DistageTestEnvironmentImpl[F[_]: TagK](suiteClass: Class[_]) extends Dista s"$lastPackage-test" -> None, s"$classname-test" -> None, ) - new ConfigLoaderLocalFSImpl(logger, None, moreConfigs) + new ConfigLoader.LocalFSImpl(logger, None, moreConfigs) } - def makeModuleProvider(options: ContextOptions, config: AppConfig, lateLogger: IzLogger, roles: RolesInfo, activation: AppActivation): ModuleProvider[F] = { // roles descriptor is not actually required there, we bind it just in case someone wish to inject a class depending on it - new ModuleProviderImpl[F]( + new ModuleProvider.Impl[F]( lateLogger, config, roles, diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/TestEnvironmentProviderImpl.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/TestEnvironmentProviderImpl.scala index 4359a63876..2eab8583af 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/TestEnvironmentProviderImpl.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/TestEnvironmentProviderImpl.scala @@ -8,7 +8,7 @@ import izumi.distage.plugins.merge.{PluginMergeStrategy, SimplePluginMergeStrate import izumi.distage.roles.BootstrapConfig import izumi.distage.roles.model.AppActivation import izumi.distage.roles.model.meta.RolesInfo -import izumi.distage.roles.services.{ActivationParser, PluginSource, PluginSourceImpl} +import izumi.distage.roles.services.{ActivationParser, PluginSource} import izumi.distage.testkit.services.PluginsCache import izumi.distage.testkit.services.PluginsCache.{CacheKey, CacheValue} import izumi.fundamentals.platform.language.Quirks @@ -21,7 +21,7 @@ class TestEnvironmentProviderImpl protected val memoizedKeys: Set[DIKey], protected val bootstrapOverrides: BootstrapModule, protected val moduleOverrides: ModuleBase, - protected val pluginOverrides: Option[Seq[String]] + protected val pluginOverrides: Option[Seq[String]], ) extends TestEnvironmentProvider { /** @@ -86,7 +86,7 @@ class TestEnvironmentProviderImpl } override protected def makePluginLoader(bootstrapConfig: BootstrapConfig): PluginSource = { - new PluginSourceImpl(bootstrapConfig) + new PluginSource.Impl(bootstrapConfig) } protected def thisPackage: Seq[String] = Seq(suiteClass.getPackage.getName) diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistagePluginTestSupport.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistagePluginTestSupport.scala index a166b36d17..3ed9142a6a 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistagePluginTestSupport.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistagePluginTestSupport.scala @@ -1,5 +1,6 @@ package izumi.distage.testkit.services.st.adapter +import distage.SafeType import izumi.distage.model.definition.Axis.AxisValue import izumi.distage.model.definition.StandardAxis._ import izumi.distage.model.definition.{AxisBase, BootstrapModuleDef} @@ -10,13 +11,12 @@ import izumi.distage.plugins.merge.{PluginMergeStrategy, SimplePluginMergeStrate import izumi.distage.roles.BootstrapConfig import izumi.distage.roles.model.AppActivation import izumi.distage.roles.model.meta.RolesInfo -import izumi.distage.roles.services.{ActivationParser, PluginSource, PluginSourceImpl, PruningPlanMergingPolicy} +import izumi.distage.roles.services.{ActivationParser, PluginSource, PruningPlanMergingPolicy} import izumi.distage.testkit.services.PluginsCache import izumi.distage.testkit.services.PluginsCache.{CacheKey, CacheValue} import izumi.distage.testkit.services.dstest.TestEnvironment import izumi.fundamentals.platform.language.Quirks import izumi.logstage.api.IzLogger -import distage.SafeType @deprecated("Use dstest", "2019/Jul/18") abstract class DistagePluginTestSupport[F[_] : TagK] extends DistageTestSupport[F] { @@ -27,7 +27,9 @@ abstract class DistagePluginTestSupport[F[_] : TagK] extends DistageTestSupport[ * Though it has to be always explicitly specified because this behaviour applied by default * would be very obscure. */ - protected final def thisPackage: Seq[String] = Seq(this.getClass.getPackage.getName) + protected final def thisPackage: Seq[String] = { + Seq(this.getClass.getPackage.getName) + } protected def pluginPackages: Seq[String] @@ -105,7 +107,7 @@ abstract class DistagePluginTestSupport[F[_] : TagK] extends DistageTestSupport[ } protected def makePluginLoader(bootstrapConfig: BootstrapConfig): PluginSource = { - new PluginSourceImpl(bootstrapConfig) + new PluginSource.Impl(bootstrapConfig) } } diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala index b2ac6a8014..3bc2b54e7d 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala @@ -1,5 +1,7 @@ package izumi.distage.testkit.services.st.adapter +import distage.config.AppConfig +import distage.{DIKey, Injector, ModuleBase} import izumi.distage.config.ConfigInjectionOptions import izumi.distage.model.Locator import izumi.distage.model.Locator.LocatorRef @@ -12,7 +14,7 @@ import izumi.distage.model.reflection.universe.RuntimeDIUniverse.TagK import izumi.distage.roles.model.AppActivation import izumi.distage.roles.model.meta.RolesInfo import izumi.distage.roles.services.IntegrationChecker.IntegrationCheckException -import izumi.distage.roles.services.ModuleProviderImpl.ContextOptions +import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.services.ResourceRewriter.RewriteRules import izumi.distage.roles.services.StartupPlanExecutor.Filters import izumi.distage.roles.services._ @@ -20,14 +22,11 @@ import izumi.distage.testkit.services.dstest.TestEnvironment import izumi.distage.testkit.services.st.adapter.ExternalResourceProvider.{MemoizedInstance, OrderedFinalizer, PreparedShutdownRuntime} import izumi.fundamentals.platform.cli.model.raw.RawAppArgs import izumi.fundamentals.platform.functional.Identity -import izumi.fundamentals.platform.language.{CodePosition, Quirks} import izumi.fundamentals.platform.language.Quirks._ +import izumi.fundamentals.platform.language.{CodePosition, Quirks} +import izumi.fundamentals.reflection.CodePositionMaterializer import izumi.logstage.api.IzLogger import izumi.logstage.api.Log.Level -import distage.config.AppConfig -import distage.{DIKey, Injector, ModuleBase} -import izumi.fundamentals.reflection.CodePositionMaterializer - @deprecated("Use dstest", "2019/Jul/18") abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) @@ -54,7 +53,6 @@ abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) } } - override protected def takeIO(function: ProviderMagnet[F[_]], pos: CodePosition): Unit = { Quirks.discard(pos) verifyTotalSuppression() @@ -90,17 +88,17 @@ abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) try { makeExecutor(plan.injector, logger) .execute[F](plan, filters) { - (locator, effect) => - implicit val F: DIEffect[F] = effect - - for { - _ <- F.maybeSuspend(doMemoize(locator)) - _ <- F.maybeSuspend(verifyTotalSuppression()) - _ <- F.maybeSuspend(beforeRun(locator)) - _ <- F.maybeSuspend(verifyTotalSuppression()) - _ <- locator.run(function) - } yield () - } + (locator, effect) => + implicit val F: DIEffect[F] = effect + + for { + _ <- F.maybeSuspend(doMemoize(locator)) + _ <- F.maybeSuspend(verifyTotalSuppression()) + _ <- F.maybeSuspend(beforeRun(locator)) + _ <- F.maybeSuspend(verifyTotalSuppression()) + _ <- locator.run(function) + } yield () + } } catch { case i: IntegrationCheckException => suppressTheRestOfTestSuite() @@ -140,7 +138,6 @@ abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) b } - } } @@ -154,7 +151,7 @@ abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) protected def makeModuleProvider(options: ContextOptions, config: AppConfig, lateLogger: IzLogger, roles: RolesInfo, activation: AppActivation): ModuleProvider[F] = { // roles descriptor is not actually required there, we bind it just in case someone wish to inject a class depending on it - new ModuleProviderImpl[F]( + new ModuleProvider.Impl[F]( lateLogger, config, roles, @@ -174,7 +171,7 @@ abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) } protected def makePlanner(options: ContextOptions, bsModule: BootstrapModule, activation: AppActivation, logger: IzLogger): RoleAppPlanner[F] = { - new RoleAppPlannerImpl[F](options, bsModule, activation, logger) + new RoleAppPlanner.Impl[F](options, bsModule, activation, logger) } protected def makeExecutor(injector: Injector, logger: IzLogger): StartupPlanExecutor = { @@ -196,7 +193,7 @@ abstract class DistageTestSupport[F[_]](implicit val tagK: TagK[F]) s"$lastPackage-test" -> None, s"$classname-test" -> None, ) - new ConfigLoaderLocalFSImpl(logger, None, moreConfigs) + new ConfigLoader.LocalFSImpl(logger, None, moreConfigs) } /** Override this to disable instantiation of fixture parameters that aren't bound in `makeBindings` */ diff --git a/distage/distage-testkit/src/main/scala/org/scalatest/DistageScalatestTestSuiteRunner.scala b/distage/distage-testkit/src/main/scala/org/scalatest/DistageScalatestTestSuiteRunner.scala index 4d14efeaf8..7634ac2f14 100644 --- a/distage/distage-testkit/src/main/scala/org/scalatest/DistageScalatestTestSuiteRunner.scala +++ b/distage/distage-testkit/src/main/scala/org/scalatest/DistageScalatestTestSuiteRunner.scala @@ -1,12 +1,12 @@ package org.scalatest -import izumi.distage.roles.services.IntegrationCheckerImpl +import distage.TagK +import izumi.distage.roles.services.IntegrationChecker import izumi.distage.testkit.services.dstest.DistageTestRunner._ import izumi.distage.testkit.services.dstest.{AbstractDistageSpec, DistageTestEnvironment, DistageTestEnvironmentImpl, DistageTestRunner} import izumi.distage.testkit.services.st.dtest.DistageTestsRegistrySingleton import izumi.fundamentals.platform.language.Quirks import izumi.logstage.api.{IzLogger, Log} -import distage.TagK import org.scalatest.events._ import scala.collection.immutable.TreeSet @@ -112,7 +112,7 @@ trait DistageScalatestTestSuiteRunner[F[_]] extends Suite with AbstractDistageSp val logger = IzLogger.apply(Log.Level.Debug)("phase" -> "test") - val checker = new IntegrationCheckerImpl(logger) + val checker = new IntegrationChecker.Impl(logger) val dreporter = new TestReporter { @@ -216,7 +216,6 @@ trait DistageScalatestTestSuiteRunner[F[_]] extends Suite with AbstractDistageSp runner.run() } - private def addStub(args: Args, tracker: Tracker, failure: Option[Throwable]): Unit = { val FUCK_SCALATEST = "Scalatest is not good for your mental health" val SUITE_FAILED = "Whole suite failed :/" @@ -260,5 +259,4 @@ trait DistageScalatestTestSuiteRunner[F[_]] extends Suite with AbstractDistageSp } final override val styleName: String = "DistageSuite" - } diff --git a/distage/distage-testkit/src/test/scala/izumi/distage/testkit/st/TestkitTest.scala b/distage/distage-testkit/src/test/scala/izumi/distage/testkit/st/TestkitTest.scala index e195042af2..22d65dbe80 100644 --- a/distage/distage-testkit/src/test/scala/izumi/distage/testkit/st/TestkitTest.scala +++ b/distage/distage-testkit/src/test/scala/izumi/distage/testkit/st/TestkitTest.scala @@ -1,20 +1,16 @@ package izumi.distage.testkit.st import cats.effect.IO +import distage.{DIKey, ModuleBase, TagK} import izumi.distage.config.annotations.ConfPathId import izumi.distage.config.{ConfigInjectionOptions, ConfigProvider} import izumi.distage.model.Locator.LocatorRef import izumi.distage.model.definition.ModuleDef import izumi.distage.model.monadic.DIEffect -import izumi.distage.roles.services._ +import izumi.distage.roles.config.ContextOptions import izumi.distage.testkit.st.TestkitTest.NotAddedClass import izumi.distage.testkit.st.fixtures._ import izumi.fundamentals.platform.functional.Identity -import distage.{DIKey, ModuleBase, TagK} - - - - abstract class TestkitTest[F[_] : TagK] extends TestkitSelftest[F] { "testkit" must { @@ -69,8 +65,7 @@ abstract class TestkitTest[F[_] : TagK] extends TestkitSelftest[F] { } } - - override protected def contextOptions(): ModuleProviderImpl.ContextOptions = { + override protected def contextOptions(): ContextOptions = { super.contextOptions().copy(configInjectionOptions = ConfigInjectionOptions.make { // here we may patternmatch on config value context and rewrite it case (ConfigProvider.ConfigImport(_: ConfPathId, _), c: TestConfig) => @@ -78,7 +73,6 @@ abstract class TestkitTest[F[_] : TagK] extends TestkitSelftest[F] { }) } - override protected def refineBindings(roots: Set[DIKey], primaryModule: ModuleBase): ModuleBase = { super.refineBindings(roots, primaryModule) overridenBy new ModuleDef { make[TestConfig].named(ConfPathId(DIKey.get[TestService2], "", "missing-test-section")).from(TestConfig(111, 222)) @@ -96,5 +90,4 @@ object TestkitTest { case class NotAddedClass() - } From fb7abfd79305b04c4ef1413eb580a4c75125a272 Mon Sep 17 00:00:00 2001 From: Kai Date: Mon, 21 Oct 2019 21:28:24 +0100 Subject: [PATCH 2/2] Move macro debug log property declarations to DebugProperties objects, reformat fundamentals-reflection, move CodePositionMaterializer macro to fundamentals-platform --- build.sbt | 3 +- .../izumi/distage/injector/BasicTest.scala | 2 +- .../distage/model/definition/Bindings.scala | 2 +- .../distage/model/definition/LocatorDef.scala | 3 +- .../distage/model/definition/ModuleBase.scala | 16 +-- .../dsl/AbstractBindingDefDSL.scala | 3 +- .../model/definition/dsl/ModuleDefDSL.scala | 2 +- .../exceptions/TODOBindingException.scala | 2 +- .../model/providers/ProviderMagnet.scala | 4 +- .../macros/ProviderMagnetMacro.scala | 4 +- .../distage/roles/internal/ConfigWriter.scala | 1 + .../roles/services/RoleAppPlanner.scala | 5 +- .../macrodefs/StaticPluginCheckerMacro.scala | 12 +- .../distage/roles/test/TestEntrypoint.scala | 6 +- .../model/definition/StaticModuleDef.scala | 2 +- .../strategies/ConcreteConstructorMacro.scala | 2 +- .../strategies/DebugProperties.scala | 7 ++ .../strategies/FactoryConstructorMacro.scala | 2 +- .../provisioning/strategies/MacroLog.scala | 7 -- .../strategies/TraitConstructorMacro.scala | 2 +- .../dstest/DistageTestEnvironmentImpl.scala | 2 +- .../services/st/adapter/DISyntax.scala | 2 +- .../services/st/adapter/DISyntaxBIO.scala | 3 +- .../st/adapter/DistageTestSupport.scala | 3 +- .../dtest/DistageAbstractScalatestSpec.scala | 3 +- .../scala/izumi/functional/IzEither.scala | 28 +++-- .../language}/CodePositionMaterializer.scala | 20 ++-- .../language}/SourcePackageMaterializer.scala | 10 +- .../platform/logging/DebugProperties.scala | 17 +++ .../reflection/AnnotationTools.scala | 17 ++- .../reflection/DebugProperties.scala | 13 +++ .../reflection/ProjectAttributeMacro.scala | 3 +- .../reflection/ReflectionUtil.scala | 17 +-- .../fundamentals/reflection/TagMacro.scala | 67 ++++++------ .../izumi/fundamentals/reflection/Tags.scala | 103 +++++++++--------- .../{TreeTools.scala => TreeUtil.scala} | 3 +- .../reflection/TrivialMacroLogger.scala | 16 +-- .../reflection/macrortti/LTTRenderables.scala | 1 - .../reflection/macrortti/LTag.scala | 4 +- .../reflection/macrortti/LightTypeTag.scala | 11 +- .../macrortti/LightTypeTagImpl.scala | 28 ++--- .../macrortti/LightTypeTagInheritance.scala | 10 +- .../macrortti/LightTypeTagMacro.scala | 31 +++--- .../macrortti/LightTypeTagRef.scala | 2 - .../reflection/macrortti/RuntimeAPI.scala | 2 - .../izumi/logstage/api/AbstractLogger.scala | 2 +- .../main/scala/izumi/logstage/api/Log.scala | 3 +- .../logstage/macros/LoggerMacroMethods.scala | 6 +- .../izumi/logstage/macros/LogIOMacros.scala | 2 +- .../src/main/scala/logstage/LogCreateIO.scala | 2 +- .../src/main/scala/logstage/LogIO.scala | 2 +- .../main/scala/logstage/LogstageCats.scala | 2 +- .../src/main/scala/logstage/LogstageZIO.scala | 2 +- project/Deps.sc | 16 ++- 54 files changed, 291 insertions(+), 249 deletions(-) create mode 100644 distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/DebugProperties.scala delete mode 100644 distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/MacroLog.scala rename fundamentals/{fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection => fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language}/CodePositionMaterializer.scala (82%) rename fundamentals/{fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection => fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language}/SourcePackageMaterializer.scala (75%) create mode 100644 fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/logging/DebugProperties.scala create mode 100644 fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/DebugProperties.scala rename fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/{TreeTools.scala => TreeUtil.scala} (95%) diff --git a/build.sbt b/build.sbt index fa882afb32..2a403bbeea 100644 --- a/build.sbt +++ b/build.sbt @@ -127,7 +127,8 @@ lazy val `fundamentals-platform` = project.in(file("fundamentals/fundamentals-pl libraryDependencies ++= Seq( compilerPlugin("org.typelevel" % "kind-projector" % V.kind_projector cross CrossVersion.full), "org.scala-lang.modules" %% "scala-collection-compat" % V.collection_compat, - "org.scalatest" %% "scalatest" % V.scalatest % Test + "org.scalatest" %% "scalatest" % V.scalatest % Test, + "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided ) ) .settings( diff --git a/distage/distage-core/src/test/scala/izumi/distage/injector/BasicTest.scala b/distage/distage-core/src/test/scala/izumi/distage/injector/BasicTest.scala index 0931e6f5aa..f6ced455e7 100644 --- a/distage/distage-core/src/test/scala/izumi/distage/injector/BasicTest.scala +++ b/distage/distage-core/src/test/scala/izumi/distage/injector/BasicTest.scala @@ -9,7 +9,7 @@ import izumi.distage.model.definition.{Binding, BindingTag, Id, ImplDef} import izumi.distage.model.exceptions.{BadIdAnnotationException, ConflictingDIKeyBindingsException, ProvisioningException, UnsupportedWiringException} import izumi.distage.model.plan.ExecutableOp.ImportDependency import izumi.distage.reflection.SymbolIntrospectorDefaultImpl -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import org.scalatest.WordSpec class BasicTest extends WordSpec with MkInjector { diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/definition/Bindings.scala b/distage/distage-model/src/main/scala/izumi/distage/model/definition/Bindings.scala index bfe6e9bf43..0de12d12bc 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/definition/Bindings.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/definition/Bindings.scala @@ -2,7 +2,7 @@ package izumi.distage.model.definition import izumi.distage.model.providers.ProviderMagnet import izumi.distage.model.reflection.universe.RuntimeDIUniverse.{DIKey, SafeType, Tag} -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer object Bindings { import Binding._ diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/definition/LocatorDef.scala b/distage/distage-model/src/main/scala/izumi/distage/model/definition/LocatorDef.scala index 58bbf5613b..732e0e3444 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/definition/LocatorDef.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/definition/LocatorDef.scala @@ -17,8 +17,7 @@ import izumi.distage.model.reflection.universe.RuntimeDIUniverse import izumi.distage.model.reflection.universe.RuntimeDIUniverse.Wiring.SingletonWiring.Instance import izumi.distage.model.reflection.universe.RuntimeDIUniverse._ import izumi.distage.model.{GCMode, Locator, definition} -import izumi.fundamentals.platform.language.SourceFilePosition -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.{CodePositionMaterializer, SourceFilePosition} import scala.collection.mutable diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/definition/ModuleBase.scala b/distage/distage-model/src/main/scala/izumi/distage/model/definition/ModuleBase.scala index 359694e2fc..ec3913779c 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/definition/ModuleBase.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/definition/ModuleBase.scala @@ -2,6 +2,7 @@ package izumi.distage.model.definition import cats.Hash import cats.kernel.{BoundedSemilattice, PartialOrder} +import izumi.distage.model.definition.ModuleBase.ModuleBaseInstances.{CatsBoundedSemilattice, CatsPartialOrderHash, ModuleBaseSemilattice} import izumi.distage.model.definition.ModuleBaseInstances.{CatsBoundedSemilattice, CatsPartialOrderHash, ModuleBaseSemilattice} import izumi.distage.model.reflection.universe.RuntimeDIUniverse.DIKey import izumi.fundamentals.collections.IzCollections._ @@ -136,13 +137,14 @@ object ModuleBase { private[definition] def tagwiseMerge(bs: Iterable[Binding]): Set[Binding] = { val grouped = bs.groupBy(_.group) - val out = grouped - .map { - case (_, v) => - //assert(v.forall(_.key == k.key), s"${k.key}, ${v.map(_.key)}") - v.reduce(_ addTags _.tags) - } - .to[ListSet] + val out = ListSet.newBuilder.++= { + grouped + .map { + case (_, v) => + //assert(v.forall(_.key == k.key), s"${k.key}, ${v.map(_.key)}") + v.reduce(_ addTags _.tags) + } + }.result() out } diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/AbstractBindingDefDSL.scala b/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/AbstractBindingDefDSL.scala index ac0ef91c0b..a933e2737c 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/AbstractBindingDefDSL.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/AbstractBindingDefDSL.scala @@ -7,9 +7,8 @@ import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.SingletonInstruc import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.{BindingRef, SetRef, SingletonInstruction, SingletonRef} import izumi.distage.model.definition.{Binding, BindingTag, Bindings, ImplDef} import izumi.distage.model.reflection.universe.RuntimeDIUniverse.{DIKey, IdContract, Tag} -import izumi.fundamentals.reflection.CodePositionMaterializer import izumi.fundamentals.platform.language.Quirks._ -import izumi.fundamentals.platform.language.SourceFilePosition +import izumi.fundamentals.platform.language.{CodePositionMaterializer, SourceFilePosition} import scala.collection.mutable diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/ModuleDefDSL.scala b/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/ModuleDefDSL.scala index 0bdb351d95..841768c35c 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/ModuleDefDSL.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/definition/dsl/ModuleDefDSL.scala @@ -9,8 +9,8 @@ import izumi.distage.model.definition.dsl.AbstractBindingDefDSL.SingletonInstruc import izumi.distage.model.definition.dsl.AbstractBindingDefDSL._ import izumi.distage.model.providers.ProviderMagnet import izumi.distage.model.reflection.universe.RuntimeDIUniverse._ +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.fundamentals.platform.language.Quirks.discard -import izumi.fundamentals.reflection.CodePositionMaterializer /** * DSL for defining module Bindings. diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/exceptions/TODOBindingException.scala b/distage/distage-model/src/main/scala/izumi/distage/model/exceptions/TODOBindingException.scala index 7a70a1c27c..d07deef98c 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/exceptions/TODOBindingException.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/exceptions/TODOBindingException.scala @@ -1,6 +1,6 @@ package izumi.distage.model.exceptions import izumi.distage.model.reflection.universe.RuntimeDIUniverse -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer class TODOBindingException(message: String, val target: RuntimeDIUniverse.DIKey, val sourcePosition: CodePositionMaterializer) extends DIException(message, null) diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/providers/ProviderMagnet.scala b/distage/distage-model/src/main/scala/izumi/distage/model/providers/ProviderMagnet.scala index b666b1dd55..b4a8a76cc7 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/providers/ProviderMagnet.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/providers/ProviderMagnet.scala @@ -2,9 +2,9 @@ package izumi.distage.model.providers import izumi.distage.model.exceptions.TODOBindingException import izumi.distage.model.reflection.macros.{ProviderMagnetMacro, ProviderMagnetMacroGenerateUnsafeWeakSafeTypes} -import izumi.distage.model.reflection.universe.RuntimeDIUniverse.{Association, DIKey, DependencyContext, Provider, SafeType, Tag, SymbolInfo} +import izumi.distage.model.reflection.universe.RuntimeDIUniverse.{Association, DIKey, DependencyContext, Provider, SafeType, SymbolInfo, Tag} +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.fundamentals.platform.language.Quirks._ -import izumi.fundamentals.reflection.CodePositionMaterializer import scala.language.experimental.macros import scala.language.implicitConversions diff --git a/distage/distage-model/src/main/scala/izumi/distage/model/reflection/macros/ProviderMagnetMacro.scala b/distage/distage-model/src/main/scala/izumi/distage/model/reflection/macros/ProviderMagnetMacro.scala index 1e844c7666..b8bfaf4d8d 100644 --- a/distage/distage-model/src/main/scala/izumi/distage/model/reflection/macros/ProviderMagnetMacro.scala +++ b/distage/distage-model/src/main/scala/izumi/distage/model/reflection/macros/ProviderMagnetMacro.scala @@ -4,7 +4,7 @@ import izumi.distage.model.providers.ProviderMagnet import izumi.distage.model.reflection.universe.{RuntimeDIUniverse, StaticDIUniverse} import izumi.distage.reflection.{DependencyKeyProviderDefaultImpl, SymbolIntrospectorDefaultImpl} import izumi.fundamentals.reflection.macrortti.LightTypeTag -import izumi.fundamentals.reflection.{AnnotationTools, TrivialMacroLogger} +import izumi.fundamentals.reflection.{AnnotationTools, DebugProperties, TrivialMacroLogger} import scala.reflect.macros.blackbox @@ -25,7 +25,7 @@ class ProviderMagnetMacro(val c: blackbox.Context) { final val macroUniverse = StaticDIUniverse(c) - private final val logger = TrivialMacroLogger.make[this.type](c, LightTypeTag.loggerId) + private final val logger = TrivialMacroLogger.make[this.type](c, izumi.fundamentals.reflection.DebugProperties.`izumi.debug.macro.rtti`) private final val symbolIntrospector = SymbolIntrospectorDefaultImpl.Static(macroUniverse) private final val keyProvider = DependencyKeyProviderDefaultImpl.Static(macroUniverse)(symbolIntrospector) private final val tools = diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala index 299ee24a87..308c296424 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/internal/ConfigWriter.scala @@ -10,6 +10,7 @@ import izumi.distage.model.definition.{Id, ModuleBase} import izumi.distage.model.monadic.DIEffect import izumi.distage.model.plan.ExecutableOp.WiringOp import izumi.distage.model.plan.OrderedPlan +import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.internal.ConfigWriter.{ConfigurableComponent, WriteReference} import izumi.distage.roles.model.meta.{RoleBinding, RolesInfo} import izumi.distage.roles.model.{RoleDescriptor, RoleTask} diff --git a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala index 04c380a816..1db05e29ea 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/roles/services/RoleAppPlanner.scala @@ -4,8 +4,8 @@ import distage.{BootstrapModule, DIKey, Injector, TagK, _} import izumi.distage.model.definition.{ModuleBase, ModuleDef} import izumi.distage.model.monadic.{DIEffect, DIEffectRunner} import izumi.distage.model.plan.OrderedPlan -import izumi.distage.roles.model.{AppActivation, IntegrationCheck} import izumi.distage.roles.config.ContextOptions +import izumi.distage.roles.model.{AppActivation, IntegrationCheck} import izumi.distage.roles.services.RoleAppPlanner.AppStartupPlans import izumi.logstage.api.IzLogger @@ -28,8 +28,7 @@ object RoleAppPlanner { bsModule: BootstrapModule, activation: AppActivation, logger: IzLogger, - ) extends RoleAppPlanner[F] { - self => + ) extends RoleAppPlanner[F] { self => private val injector = Injector.Standard(bsModule) diff --git a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala index 396b0e8903..19f09e37e3 100644 --- a/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala +++ b/distage/distage-roles/src/main/scala/izumi/distage/staticinjector/plugins/macrodefs/StaticPluginCheckerMacro.scala @@ -21,7 +21,7 @@ import izumi.distage.roles.RoleAppLauncher import izumi.distage.roles.services.{ActivationParser, PruningPlanMergingPolicy} import izumi.distage.staticinjector.plugins.ModuleRequirements import izumi.fundamentals.platform.cli.model.raw.{RawAppArgs, RawEntrypointParams, RawValue} -import izumi.fundamentals.reflection.TreeTools +import izumi.fundamentals.reflection.TreeUtil import izumi.logstage.api.IzLogger import scala.collection.JavaConverters._ @@ -72,7 +72,7 @@ object StaticPluginCheckerMacro { val abort = c.abort(c.enclosingPosition, _: String): Unit - val pluginPath = TreeTools.stringLiteral(c)(c.universe)(pluginsPackage.tree) + val pluginPath = TreeUtil.stringLiteral(c)(c.universe)(pluginsPackage.tree) val loadedPlugins = if (pluginPath == "") { Seq.empty @@ -86,7 +86,7 @@ object StaticPluginCheckerMacro { pluginLoader.load() } - val configRegex = TreeTools.stringLiteral(c)(c.universe)(configFileRegex.tree) + val configRegex = TreeUtil.stringLiteral(c)(c.universe)(configFileRegex.tree) val configModule = if (configRegex == "") { None @@ -104,7 +104,7 @@ object StaticPluginCheckerMacro { Some(new ConfigModule(AppConfig(referenceConfig))) } - val gcRootPath = TreeTools.stringLiteral(c)(c.universe)(gcRoot.tree) + val gcRootPath = TreeUtil.stringLiteral(c)(c.universe)(gcRoot.tree) val gcRootModule = if (gcRootPath == "") { None @@ -112,7 +112,7 @@ object StaticPluginCheckerMacro { Some(constructClass[PluginBase](gcRootPath, abort)) } - val requirementsPath = TreeTools.stringLiteral(c)(c.universe)(requirements.tree) + val requirementsPath = TreeUtil.stringLiteral(c)(c.universe)(requirements.tree) val requirementsModule = if (requirementsPath == "") { None @@ -120,7 +120,7 @@ object StaticPluginCheckerMacro { Some(constructClass[ModuleRequirements](requirementsPath, abort)) } - val activationsVals = TreeTools.stringLiteral(c)(c.universe)(activations.tree).split(',').toSeq + val activationsVals = TreeUtil.stringLiteral(c)(c.universe)(activations.tree).split(',').toSeq check(loadedPlugins, configModule, additional = Module.empty, gcRootModule, requirementsModule, activationsVals, abort = abort) diff --git a/distage/distage-roles/src/test/scala/izumi/distage/roles/test/TestEntrypoint.scala b/distage/distage-roles/src/test/scala/izumi/distage/roles/test/TestEntrypoint.scala index 826b926e31..7a9a705481 100644 --- a/distage/distage-roles/src/test/scala/izumi/distage/roles/test/TestEntrypoint.scala +++ b/distage/distage-roles/src/test/scala/izumi/distage/roles/test/TestEntrypoint.scala @@ -3,10 +3,10 @@ package izumi.distage.roles.test import cats.effect.IO import izumi.distage.plugins.load.PluginLoader.PluginConfig import izumi.distage.roles.internal.{ConfigWriter, Help} -import izumi.distage.roles.test.fixtures.{AdoptedAutocloseablesCase, TestRole00, TestRole01, TestRole02, TestTask00} -import izumi.distage.roles.{AppShutdownStrategy, BootstrapConfig, ImmediateExitShutdownStrategy, RoleAppLauncher, RoleAppMain} +import izumi.distage.roles.test.fixtures._ +import izumi.distage.roles._ import izumi.fundamentals.platform.cli.model.raw.{RawEntrypointParams, RawRoleParams} -import izumi.fundamentals.reflection.SourcePackageMaterializer.thisPkg +import izumi.fundamentals.platform.language.SourcePackageMaterializer.thisPkg class TestLauncherBase extends RoleAppLauncher.LauncherF[IO]() { protected val bootstrapConfig: BootstrapConfig = BootstrapConfig( diff --git a/distage/distage-static/src/main/scala/izumi/distage/model/definition/StaticModuleDef.scala b/distage/distage-static/src/main/scala/izumi/distage/model/definition/StaticModuleDef.scala index 0fb47d53f1..9abfd50df2 100644 --- a/distage/distage-static/src/main/scala/izumi/distage/model/definition/StaticModuleDef.scala +++ b/distage/distage-static/src/main/scala/izumi/distage/model/definition/StaticModuleDef.scala @@ -2,7 +2,7 @@ package izumi.distage.model.definition import izumi.distage.model.reflection.universe.RuntimeDIUniverse.Tag import izumi.distage.provisioning.AnyConstructor -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer // TODO: improve trait StaticModuleDef extends ModuleDef with StaticDSL { diff --git a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/ConcreteConstructorMacro.scala b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/ConcreteConstructorMacro.scala index 8355afe26d..7f53910daf 100644 --- a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/ConcreteConstructorMacro.scala +++ b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/ConcreteConstructorMacro.scala @@ -23,7 +23,7 @@ object ConcreteConstructorMacro { val symbolIntrospector = SymbolIntrospectorDefaultImpl.Static(macroUniverse) val keyProvider = DependencyKeyProviderDefaultImpl.Static(macroUniverse)(symbolIntrospector) val reflectionProvider = ReflectionProviderDefaultImpl.Static(macroUniverse)(keyProvider, symbolIntrospector) - val logger = TrivialMacroLogger.make[this.type](c, MacroLog.id) + val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.static`) val targetType = weakTypeOf[T] diff --git a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/DebugProperties.scala b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/DebugProperties.scala new file mode 100644 index 0000000000..35b12ae0ff --- /dev/null +++ b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/DebugProperties.scala @@ -0,0 +1,7 @@ +package izumi.distage.provisioning.strategies + +import izumi.fundamentals.platform.logging.DebugProperties + +object DebugProperties extends DebugProperties { + final val `izumi.debug.macro.distage.static` = "izumi.debug.macro.distage.static" +} diff --git a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/FactoryConstructorMacro.scala b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/FactoryConstructorMacro.scala index 6713205350..aeb02dc428 100644 --- a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/FactoryConstructorMacro.scala +++ b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/FactoryConstructorMacro.scala @@ -20,7 +20,7 @@ object FactoryConstructorMacro { val symbolIntrospector = SymbolIntrospectorDefaultImpl.Static(macroUniverse) val keyProvider = DependencyKeyProviderDefaultImpl.Static(macroUniverse)(symbolIntrospector) val reflectionProvider = ReflectionProviderDefaultImpl.Static(macroUniverse)(keyProvider, symbolIntrospector) - val logger = TrivialMacroLogger.make[this.type](c, MacroLog.id) + val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.static`) // A hack to support generic methods inside factories. No viable type info is available for generic parameters of these methods // so we have to resort to WeakTypeTags and thread this ugly fucking `if` everywhere ;_; diff --git a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/MacroLog.scala b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/MacroLog.scala deleted file mode 100644 index dee5a27e14..0000000000 --- a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/MacroLog.scala +++ /dev/null @@ -1,7 +0,0 @@ -package izumi.distage.provisioning.strategies - -import izumi.fundamentals.reflection.TrivialMacroLogger - -object MacroLog { - final val id = TrivialMacroLogger.id("distage.static") -} diff --git a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/TraitConstructorMacro.scala b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/TraitConstructorMacro.scala index 7359221c96..eb5d912d0c 100644 --- a/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/TraitConstructorMacro.scala +++ b/distage/distage-static/src/main/scala/izumi/distage/provisioning/strategies/TraitConstructorMacro.scala @@ -23,7 +23,7 @@ object TraitConstructorMacro { val symbolIntrospector = SymbolIntrospectorDefaultImpl.Static(macroUniverse) val keyProvider = DependencyKeyProviderDefaultImpl.Static(macroUniverse)(symbolIntrospector) val reflectionProvider = ReflectionProviderDefaultImpl.Static(macroUniverse)(keyProvider, symbolIntrospector) - val logger = TrivialMacroLogger.make[this.type](c, MacroLog.id) + val logger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.distage.static`) val targetType = weakTypeOf[T] diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala index e8f5ba0644..5afa06dd41 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/dstest/DistageTestEnvironmentImpl.scala @@ -13,7 +13,7 @@ import izumi.distage.roles.config.ContextOptions import izumi.distage.roles.services.ResourceRewriter.RewriteRules import izumi.distage.roles.services.{ConfigLoader, ModuleProvider} import izumi.fundamentals.platform.cli.model.raw.RawAppArgs -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.logstage.api.IzLogger import izumi.logstage.api.Log.Level diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntax.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntax.scala index b065f870df..cd42196f3e 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntax.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntax.scala @@ -2,8 +2,8 @@ package izumi.distage.testkit.services.st.adapter import izumi.distage.model.providers.ProviderMagnet import izumi.distage.testkit.services.DISyntaxBase -import izumi.fundamentals.reflection.CodePositionMaterializer import distage.Tag +import izumi.fundamentals.platform.language.CodePositionMaterializer @deprecated("Use dstest", "2019/Jul/18") trait DISyntax[F[_]] extends DISyntaxBase[F] { diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntaxBIO.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntaxBIO.scala index 1bd1ab0651..46e257856c 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntaxBIO.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DISyntaxBIO.scala @@ -2,9 +2,8 @@ package izumi.distage.testkit.services.st.adapter import izumi.distage.model.providers.ProviderMagnet import izumi.distage.testkit.services.DISyntaxBIOBase -import izumi.fundamentals.reflection.CodePositionMaterializer import distage.Tag -import izumi.fundamentals.platform.language.CodePosition +import izumi.fundamentals.platform.language.{CodePosition, CodePositionMaterializer} @deprecated("Use dstest", "2019/Jul/18") trait DISyntaxBIO[F[+ _, + _]] extends DISyntaxBIOBase[F] { diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala index 3bc2b54e7d..845a4c5931 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/adapter/DistageTestSupport.scala @@ -23,8 +23,7 @@ import izumi.distage.testkit.services.st.adapter.ExternalResourceProvider.{Memoi import izumi.fundamentals.platform.cli.model.raw.RawAppArgs import izumi.fundamentals.platform.functional.Identity import izumi.fundamentals.platform.language.Quirks._ -import izumi.fundamentals.platform.language.{CodePosition, Quirks} -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.{CodePosition, CodePositionMaterializer, Quirks} import izumi.logstage.api.IzLogger import izumi.logstage.api.Log.Level diff --git a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/dtest/DistageAbstractScalatestSpec.scala b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/dtest/DistageAbstractScalatestSpec.scala index 6b6a32b363..a2266c4272 100644 --- a/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/dtest/DistageAbstractScalatestSpec.scala +++ b/distage/distage-testkit/src/main/scala/izumi/distage/testkit/services/st/dtest/DistageAbstractScalatestSpec.scala @@ -8,8 +8,7 @@ import izumi.distage.testkit.services.dstest.DistageTestRunner.{DistageTest, Tes import izumi.distage.testkit.services.dstest._ import izumi.distage.testkit.services.st.dtest.DistageAbstractScalatestSpec._ import izumi.distage.testkit.services.{DISyntaxBIOBase, DISyntaxBase} -import izumi.fundamentals.platform.language.{CodePosition, Quirks} -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.{CodePosition, CodePositionMaterializer, Quirks} import izumi.logstage.api.{IzLogger, Log} import org.scalactic.source diff --git a/fundamentals/fundamentals-functional/src/main/scala/izumi/functional/IzEither.scala b/fundamentals/fundamentals-functional/src/main/scala/izumi/functional/IzEither.scala index 4072d40181..06668f2233 100644 --- a/fundamentals/fundamentals-functional/src/main/scala/izumi/functional/IzEither.scala +++ b/fundamentals/fundamentals-functional/src/main/scala/izumi/functional/IzEither.scala @@ -5,9 +5,13 @@ package izumi.functional trait IzEither { implicit class EitherFolderExt1[L, R](result: Seq[Either[List[L], R]]) { def biAggregate: Either[List[L], List[R]] = { - val bad = result.collect({ case Left(e) => e }) + val bad = result.collect { + case Left(e) => e + } if (bad.isEmpty) { - Right(result.collect({ case Right(r) => r }).toList) + Right(result.collect { + case Right(r) => r + }.toList) } else { Left(bad.flatten.toList) } @@ -16,9 +20,13 @@ trait IzEither { implicit class EitherFolderExt2[L, R](result: Seq[Either[List[L], Iterable[R]]]) { def biFlatAggregate: Either[List[L], List[R]] = { - val bad = result.collect({ case Left(e) => e }) + val bad = result.collect { + case Left(e) => e + } if (bad.isEmpty) { - Right(result.collect({ case Right(r) => r }).flatten.toList) + Right(result.collect { + case Right(r) => r + }.flatten.toList) } else { Left(bad.flatten.toList) } @@ -27,8 +35,12 @@ trait IzEither { implicit class BiSplit[L, R](e: Seq[Either[L, R]]) { def lrPartition: (Seq[L], Seq[R]) = { - val left = e.collect({ case Left(l) => l }) - val right = e.collect({ case Right(r) => r }) + val left = e.collect { + case Left(l) => l + } + val right = e.collect { + case Right(r) => r + } (left, right) } } @@ -52,6 +64,4 @@ trait IzEither { } } -object IzEither extends IzEither { - -} +object IzEither extends IzEither diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/CodePositionMaterializer.scala b/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language/CodePositionMaterializer.scala similarity index 82% rename from fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/CodePositionMaterializer.scala rename to fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language/CodePositionMaterializer.scala index a48e8f3050..ed5bf95d21 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/CodePositionMaterializer.scala +++ b/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language/CodePositionMaterializer.scala @@ -1,6 +1,4 @@ -package izumi.fundamentals.reflection - -import izumi.fundamentals.platform.language.{CodePosition, SourceFilePosition} +package izumi.fundamentals.platform.language import scala.annotation.tailrec import scala.collection.mutable @@ -33,10 +31,10 @@ object CodePositionMaterializer { reify { CodePosition.apply( SourceFilePosition( - c.Expr[String](Literal(Constant(file))).splice - , c.Expr[Int](Literal(Constant(line))).splice - ) - , applicationPointId = c.Expr[String](Literal(Constant(applicationPointId))).splice + c.Expr[String](Literal(Constant(file))).splice, + c.Expr[Int](Literal(Constant(line))).splice, + ), + applicationPointId = c.Expr[String](Literal(Constant(applicationPointId))).splice, ) } } @@ -84,10 +82,10 @@ object CodePositionMaterializer { CodePosition( SourceFilePosition( - line = c.enclosingPosition.line - , file = c.enclosingPosition.source.file.name - ) - , applicationPointId = normalizedName + line = c.enclosingPosition.line, + file = c.enclosingPosition.source.file.name, + ), + applicationPointId = normalizedName, ) } } diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/SourcePackageMaterializer.scala b/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language/SourcePackageMaterializer.scala similarity index 75% rename from fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/SourcePackageMaterializer.scala rename to fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language/SourcePackageMaterializer.scala index ea65e7ec65..599c8e1383 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/SourcePackageMaterializer.scala +++ b/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/language/SourcePackageMaterializer.scala @@ -1,16 +1,14 @@ -package izumi.fundamentals.reflection - -import izumi.fundamentals.platform.language.SourcePackage +package izumi.fundamentals.platform.language import scala.language.experimental.macros import scala.reflect.macros.blackbox -final case class SourcePackageMaterializer(get: SourcePackage) +final case class SourcePackageMaterializer(get: SourcePackage) extends AnyVal object SourcePackageMaterializer { implicit def materialize: SourcePackageMaterializer = macro getSourcePackage - def apply()(implicit ev: SourcePackageMaterializer): SourcePackageMaterializer = ev + def apply()(implicit ev: SourcePackageMaterializer, dummy: DummyImplicit): SourcePackageMaterializer = ev def thisPkg(implicit pkg: SourcePackageMaterializer): String = pkg.get.pkg @@ -19,7 +17,7 @@ object SourcePackageMaterializer { import c.universe._ var current = c.internal.enclosingOwner var path = List.empty[String] - while(current != NoSymbol && current.toString != "package "){ + while (current != NoSymbol && current.toString != "package ") { if (current.isPackage) { path = current.name.decodedName.toString.trim :: path } diff --git a/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/logging/DebugProperties.scala b/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/logging/DebugProperties.scala new file mode 100644 index 0000000000..4978ffbacc --- /dev/null +++ b/fundamentals/fundamentals-platform/src/main/scala/izumi/fundamentals/platform/logging/DebugProperties.scala @@ -0,0 +1,17 @@ +package izumi.fundamentals.platform.logging + +/** + * Marker trait for objects that hold names of Java Properties + * that control Debug Output for macros, internals of `izumi` or + * other libraries. + * + * Search for inheritors of this trait to discover debugging java properties + * + * e.g. + * + * To see macro debug output during compilation, set `-Dizumi.debug.macro.rtti=true` java property! e.g. + * {{{ + * sbt -Dizumi.debug.macro.rtti=true compile + * }}} + */ +trait DebugProperties diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/AnnotationTools.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/AnnotationTools.scala index 7b47c21e0e..e6f0a6a2ef 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/AnnotationTools.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/AnnotationTools.scala @@ -3,10 +3,9 @@ package izumi.fundamentals.reflection import scala.reflect.api.Universe object AnnotationTools { - def find(u: Universe)(annType: u.Type, symb: u.Symbol): Option[u.Annotation] = ( + def find(u: Universe)(annType: u.Type, symb: u.Symbol): Option[u.Annotation] = findSymbolAnnotation(u)(annType, symb) - orElse findTypeAnnotation(u)(annType, symb.typeSignature.finalResultType) - ) + .orElse(findTypeAnnotation(u)(annType, symb.typeSignature.finalResultType)) def findSymbolAnnotation(u: Universe)(annType: u.Type, symb: u.Symbol): Option[u.Annotation] = symb.annotations.find(annotationTypeEq(u)(annType, _)) @@ -19,11 +18,11 @@ object AnnotationTools { def getAllTypeAnnotations(u: Universe)(typ: u.Type): List[u.Annotation] = typ match { - case t: u.AnnotatedTypeApi => - t.annotations - case _ => - List() - } + case t: u.AnnotatedTypeApi => + t.annotations + case _ => + List() + } def annotationTypeEq(u: Universe)(tpe: u.Type, ann: u.Annotation): Boolean = ann.tree.tpe.erasure =:= tpe.erasure @@ -33,7 +32,7 @@ object AnnotationTools { def collectFirstString[T: u.TypeTag](u: Universe)(symb: u.Symbol): Option[String] = collectFirstArgument[T, String](u)(symb, { - case l: u.Literal @unchecked if l.value.value.isInstanceOf[String] => l.value.value.asInstanceOf[String] // avoid unchecked warning + case l: u.Literal@unchecked if l.value.value.isInstanceOf[String] => l.value.value.asInstanceOf[String] // avoid unchecked warning }) def findArgument[R](ann: Universe#Annotation)(matcher: PartialFunction[Universe#Tree, R]): Option[R] = diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/DebugProperties.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/DebugProperties.scala new file mode 100644 index 0000000000..1f18cbb4fe --- /dev/null +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/DebugProperties.scala @@ -0,0 +1,13 @@ +package izumi.fundamentals.reflection + +import izumi.fundamentals.platform.logging.DebugProperties + +/** + * To see macro debug output during compilation, set `-Dizumi.debug.macro.rtti=true` java property! e.g. + * {{{ + * sbt -Dizumi.debug.macro.rtti=true compile + * }}} + */ +object DebugProperties extends DebugProperties { + final val `izumi.debug.macro.rtti` = "izumi.debug.macro.rtti" +} diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ProjectAttributeMacro.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ProjectAttributeMacro.scala index 4bda4aa70f..3d6abf245e 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ProjectAttributeMacro.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ProjectAttributeMacro.scala @@ -43,9 +43,8 @@ object ProjectAttributeMacro { } } - def extractAttrMacro(c: blackbox.Context)(name: c.Expr[String]): c.Expr[Option[String]] = { - val nameStr = TreeTools.stringLiteral(c)(c.universe)(name.tree) + val nameStr = TreeUtil.stringLiteral(c)(c.universe)(name.tree) extractAttr(c, nameStr) } diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ReflectionUtil.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ReflectionUtil.scala index 248ddc1f66..9722dbdf89 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ReflectionUtil.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/ReflectionUtil.scala @@ -3,11 +3,11 @@ package izumi.fundamentals.reflection import java.lang.reflect.Method import scala.collection.immutable.ListMap +import scala.language.reflectiveCalls import scala.reflect.api import scala.reflect.api.{Mirror, TypeCreator, Universe} import scala.reflect.internal.Symbols import scala.reflect.runtime.{universe => ru} -import scala.language.reflectiveCalls import scala.util.{Failure, Success, Try} abstract class ReflectionException(message: String, cause: Throwable = null) extends RuntimeException(message, cause) @@ -16,7 +16,6 @@ class RefinedTypeException(message: String, cause: Throwable = null) extends Ref class MethodMirrorException(message: String, cause: Throwable = null) extends ReflectionException(message, cause) - object ReflectionUtil { val mm: ru.Mirror = scala.reflect.runtime.currentMirror @@ -51,7 +50,7 @@ object ReflectionUtil { def typeToTypeTag[T](u: Universe)( tpe: u.Type, - mirror: Mirror[u.type] + mirror: Mirror[u.type], ): u.TypeTag[T] = { val creator: TypeCreator = new reflect.api.TypeCreator { def apply[U <: SingletonUniverse](m: Mirror[U]): U#Type = { @@ -64,17 +63,19 @@ object ReflectionUtil { } implicit final class WeakTypeTagMigrate[T](private val weakTypeTag: Universe#WeakTypeTag[T]) extends AnyVal { - def migrate[V <: SingletonUniverse](m: api.Mirror[V]): m.universe.WeakTypeTag[T] = + def migrate[V <: SingletonUniverse](m: api.Mirror[V]): m.universe.WeakTypeTag[T] = { weakTypeTag.in(m).asInstanceOf[m.universe.WeakTypeTag[T]] + } } - def deannotate[U <: SingletonUniverse](typ: U#Type): U#Type = + def deannotate[U <: SingletonUniverse](typ: U#Type): U#Type = { typ match { case t: U#AnnotatedTypeApi => t.underlying case _ => typ } + } def toTypeRef[U <: SingletonUniverse](tpe: U#TypeApi): Option[U#TypeRefApi] = { tpe match { @@ -91,8 +92,9 @@ object ReflectionUtil { * annotation recovered from a symbol via the .annotations method, it doesn't seem possible to avoid * calling this method. */ - def runtimeAnnotation(tpe: ru.Type, scalaArgs: List[ru.Tree], javaArgs: ListMap[ru.Name, ru.JavaArgument]): ru.Annotation = + def runtimeAnnotation(tpe: ru.Type, scalaArgs: List[ru.Tree], javaArgs: ListMap[ru.Name, ru.JavaArgument]): ru.Annotation = { ru.Annotation.apply(tpe, scalaArgs, javaArgs) + } def intersectionTypeMembers[U <: SingletonUniverse](targetType: U#Type): List[U#Type] = { def go(tpe: U#Type): List[U#Type] = { @@ -104,8 +106,9 @@ object ReflectionUtil { go(targetType).distinct } - def kindOf(tpe: Universe#Type): Kind = + def kindOf(tpe: Universe#Type): Kind = { Kind(tpe.typeParams.map(t => kindOf(t.typeSignature))) + } final case class Kind(args: List[Kind]) { override def toString: String = format("_") diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TagMacro.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TagMacro.scala index 5472f8d393..e8494bc079 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TagMacro.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TagMacro.scala @@ -3,7 +3,7 @@ package izumi.fundamentals.reflection import izumi.fundamentals.platform.console.TrivialLogger import izumi.fundamentals.reflection.ReflectionUtil.{Kind, kindOf} import izumi.fundamentals.reflection.Tags.{defaultTagImplicitError, hktagFormat, hktagFormatMap} -import izumi.fundamentals.reflection.macrortti.{LTag, LightTypeTag, LightTypeTagMacro, LightTypeTagMacro0} +import izumi.fundamentals.reflection.macrortti.{LTag, LightTypeTagMacro, LightTypeTagMacro0} import scala.annotation.{implicitNotFound, tailrec} import scala.collection.immutable.ListMap @@ -13,11 +13,12 @@ import scala.reflect.macros.{TypecheckException, blackbox, whitebox} // TODO: benchmark difference between searching all arguments vs. merge strategy // TODO: benchmark ProviderMagnet vs. identity macro vs. normal function class TagMacro(val c: blackbox.Context) { + import c.universe._ protected[this] val defaultError: String = defaultTagImplicitError - protected[this] val logger: TrivialLogger = TrivialMacroLogger.make[this.type](c, LightTypeTag.loggerId) + protected[this] val logger: TrivialLogger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.rtti`) /** * Workaround for a scalac bug whereby it loses the correct type of HKTag argument @@ -28,7 +29,7 @@ class TagMacro(val c: blackbox.Context) { * * TODO: report scalac bug */ - def fixupHKTagArgStruct[DIU <: Tags with Singleton: WeakTypeTag, T: WeakTypeTag]: c.Expr[DIU#HKTag[T]] = { + def fixupHKTagArgStruct[DIU <: Tags with Singleton : WeakTypeTag, T: WeakTypeTag]: c.Expr[DIU#HKTag[T]] = { val argStruct = weakTypeOf[T] val typeConstructor = argStruct.decls.head.info.typeConstructor @@ -68,7 +69,7 @@ class TagMacro(val c: blackbox.Context) { } } - def impl[DIU <: Tags with Singleton: c.WeakTypeTag, T: c.WeakTypeTag]: c.Expr[TagMaterializer[DIU, T]] = { + def impl[DIU <: Tags with Singleton : c.WeakTypeTag, T: c.WeakTypeTag]: c.Expr[TagMaterializer[DIU, T]] = { logger.log(s"GOT UNIVERSE: ${c.weakTypeOf[DIU]}") logger.log(s"Got compile tag: ${weakTypeOf[T]}") @@ -95,7 +96,7 @@ class TagMacro(val c: blackbox.Context) { } val res = reify { - { new TagMaterializer[DIU, T](tag.splice) } + {new TagMaterializer[DIU, T](tag.splice)} } addImplicitError(s" done: $tgt") @@ -105,7 +106,7 @@ class TagMacro(val c: blackbox.Context) { res } - def getImplicitError[DIU <: Tags with Singleton: c.WeakTypeTag](): String = { + def getImplicitError[DIU <: Tags with Singleton : c.WeakTypeTag](): String = { symbolOf[DIU#Tag[Any]].annotations.headOption.flatMap( AnnotationTools.findArgument(_) { case Literal(Constant(s: String)) => s @@ -114,7 +115,7 @@ class TagMacro(val c: blackbox.Context) { } @inline - protected[this] def mkRefined[DIU <: Tags with Singleton: c.WeakTypeTag, T: c.WeakTypeTag](universe: c.Expr[DIU], intersection: List[Type], struct: Type): c.Expr[DIU#Tag[T]] = { + protected[this] def mkRefined[DIU <: Tags with Singleton : c.WeakTypeTag, T: c.WeakTypeTag](universe: c.Expr[DIU], intersection: List[Type], struct: Type): c.Expr[DIU#Tag[T]] = { val intersectionsTags = c.Expr[List[DIU#ScalaReflectTypeTag[_]]](q"${ intersection.map { t0 => @@ -125,13 +126,13 @@ class TagMacro(val c: blackbox.Context) { val structTag = mkStruct[DIU](struct) reify { - { universe.splice.Tag.refinedTag[T](intersectionsTags.splice, structTag.splice) } + {universe.splice.Tag.refinedTag[T](intersectionsTags.splice, structTag.splice)} } } @inline // have to tag along the original intersection, because scalac dies on trying to summon typetag for a custom made refinedType from `internal.refinedType` ... - protected[this] def mkStruct[DIU <: Tags with Singleton: c.WeakTypeTag](struct: Type): c.Expr[DIU#ScalaReflectWeakTypeTag[_]] = { + protected[this] def mkStruct[DIU <: Tags with Singleton : c.WeakTypeTag](struct: Type): c.Expr[DIU#ScalaReflectWeakTypeTag[_]] = { struct.decls.find(_.info.typeSymbol.isParameter).foreach { s => @@ -147,7 +148,7 @@ class TagMacro(val c: blackbox.Context) { // we need to handle four cases – type args, refined types, type bounds and bounded wildcards(? check existence) @inline - protected[this] def mkTag[DIU <: Tags with Singleton: c.WeakTypeTag, T: c.WeakTypeTag](universe: c.Expr[DIU], tpe: c.Type): c.Expr[DIU#Tag[T]] = { + protected[this] def mkTag[DIU <: Tags with Singleton : c.WeakTypeTag, T: c.WeakTypeTag](universe: c.Expr[DIU], tpe: c.Type): c.Expr[DIU#Tag[T]] = { val ctor = tpe.typeConstructor val constructorTag: c.Expr[DIU#ScalaReflectTypeTag[_]] = paramKind(ctor) match { @@ -169,13 +170,13 @@ class TagMacro(val c: blackbox.Context) { val argTags = c.Expr[List[DIU#ScalaReflectTypeTag[_]]](q"${args.map(summonTag[DIU])}") reify { - { universe.splice.Tag.appliedTag[T](constructorTag.splice, argTags.splice) } + {universe.splice.Tag.appliedTag[T](constructorTag.splice, argTags.splice)} } } @inline protected[this] def paramKind(tpe: c.Type): Option[Kind] = { - // c.internal.isFreeType ? + // c.internal.isFreeType ? if (tpe.typeSymbol.isParameter) Some(kindOf(tpe)) else @@ -252,8 +253,7 @@ class TagMacro(val c: blackbox.Context) { } @inline - protected[this] def summonTag[DIU <: Tags with Singleton: c.WeakTypeTag](tpe: c.Type, kind: Kind): c.Expr[DIU#ScalaReflectTypeTag[_]] = { - + protected[this] def summonTag[DIU <: Tags with Singleton : c.WeakTypeTag](tpe: c.Type, kind: Kind): c.Expr[DIU#ScalaReflectTypeTag[_]] = { val summoned = try { if (kind == Kind(Nil)) { c.inferImplicitValue(appliedType(weakTypeOf[DIU#Tag[Nothing]].typeConstructor, tpe), silent = false) @@ -266,19 +266,21 @@ class TagMacro(val c: blackbox.Context) { case _: TypecheckException => val msg = s""" could not find implicit value for ${hktagFormat(tpe)} - |${hktagFormatMap.get(kind) match { - case Some(_) => "" - case None => - val (args, params) = kind.args.zipWithIndex.map { - case (k, i) => - val name = s"T${i+1}" - k.format(name) -> name - }.unzip - s"""\n$tpe is of a kind $kind, which doesn't have a tag name. Please create a tag synonym as follows:\n\n - | type TagXXX[${kind.format("K")}] = HKTag[ { type Arg[${args.mkString(", ")}] = K[${params.mkString(", ")}] } ]\n\n - |And use it in your context bound, as in def x[$tpe: TagXXX] = ... + |${ + hktagFormatMap.get(kind) match { + case Some(_) => "" + case None => + val (args, params) = kind.args.zipWithIndex.map { + case (k, i) => + val name = s"T${i + 1}" + k.format(name) -> name + }.unzip + s"""\n$tpe is of a kind $kind, which doesn't have a tag name. Please create a tag synonym as follows:\n\n + | type TagXXX[${kind.format("K")}] = HKTag[ { type Arg[${args.mkString(", ")}] = K[${params.mkString(", ")}] } ]\n\n + |And use it in your context bound, as in def x[$tpe: TagXXX] = ... """.stripMargin - }}""".stripMargin + } + }""".stripMargin addImplicitError(msg) c.abort(c.enclosingPosition, msg) } @@ -322,20 +324,21 @@ class TagMacro(val c: blackbox.Context) { } @inline - protected[this] def setImplicitError[DIU <: Tags with Singleton: c.WeakTypeTag](err: String): Unit = { + protected[this] def setImplicitError[DIU <: Tags with Singleton : c.WeakTypeTag](err: String): Unit = { import internal.decorators._ val _ = symbolOf[DIU#Tag[Any]].setAnnotations(Annotation(typeOf[implicitNotFound], List[Tree](Literal(Constant(err))), ListMap.empty)) } -// // TODO: in 2.13 we can use these little functions to enrich error messages further (possibly remove .setAnnotation hack completely) by attaching implicitNotFound to parameter -// c.Expr[DIU#ScalaReflectTypeTag[_]](q""" -// { def $name(implicit @_root_.scala.annotation.implicitNotFound($implicitMsg) -// $param: ${appliedType(weakTypeOf[DIU#Tag[Nothing]], t)}) = $param; $name.tag }""") + // // TODO: in 2.13 we can use these little functions to enrich error messages further (possibly remove .setAnnotation hack completely) by attaching implicitNotFound to parameter + // c.Expr[DIU#ScalaReflectTypeTag[_]](q""" + // { def $name(implicit @_root_.scala.annotation.implicitNotFound($implicitMsg) + // $param: ${appliedType(weakTypeOf[DIU#Tag[Nothing]], t)}) = $param; $name.tag }""") } -class TagLambdaMacro(override val c: whitebox.Context { type PrefixType <: Tags#TagObject }) extends TagMacro(c) { +class TagLambdaMacro(override val c: whitebox.Context {type PrefixType <: Tags#TagObject}) extends TagMacro(c) { + import c.universe._ import c.universe.internal.decorators._ diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/Tags.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/Tags.scala index c72b369ebd..22e1fa668d 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/Tags.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/Tags.scala @@ -21,28 +21,28 @@ trait Tags extends UniverseGeneric { self => } /** - * Like [[scala.reflect.api.TypeTags.TypeTag]], but supports higher-kinded type tags via `TagK` type class. - * - * In context of DI this lets you define modules parameterized by higher-kinded type parameters. - * This is especially helpful for applying [[https://www.beyondthelines.net/programming/introduction-to-tagless-final/ `tagless final` style]] - * - * Example: - * {{{ - * class MyModule[F[_]: Monad: TagK] { - * make[MyService[F]] - * make[F[Int]].named("lucky-number").from(Monad[F].pure(7)) - * } - * }}} - * - * Without a `TagK` constraint above, this example would fail with `no TypeTag available for MyService[F]` error - * - * Currently some limitations apply as to when a `Tag` will be correctly constructed: - * * Type Parameters do not yet resolve inside structural refinements, e.g. T in {{{ Tag[{ def x: T}] }}} - * * Type Parameters do not yet resolve inside higher-kinded type lambdas, e.g. T in {{{ TagK[Either[T, ?]] }}} - * * TagK* does not resolve for constructors with bounded parameters, e.g. S in {{{ class Abc[S <: String]; TagK[Abc] }}} - * (You can still have a bound in partial application: e.g. {{{ class Abc[S <: String, A]; TagK[Abc["hi", ?]] }}} - * * Further details at [[https://github.com/7mind/izumi/pull/369]] - */ + * Like [[scala.reflect.api.TypeTags.TypeTag]], but supports higher-kinded type tags via `TagK` type class. + * + * In context of DI this lets you define modules parameterized by higher-kinded type parameters. + * This is especially helpful for applying [[https://www.beyondthelines.net/programming/introduction-to-tagless-final/ `tagless final` style]] + * + * Example: + * {{{ + * class MyModule[F[_]: Monad: TagK] { + * make[MyService[F]] + * make[F[Int]].named("lucky-number").from(Monad[F].pure(7)) + * } + * }}} + * + * Without a `TagK` constraint above, this example would fail with `no TypeTag available for MyService[F]` error + * + * Currently some limitations apply as to when a `Tag` will be correctly constructed: + * * Type Parameters do not yet resolve inside structural refinements, e.g. T in {{{ Tag[{ def x: T}] }}} + * * Type Parameters do not yet resolve inside higher-kinded type lambdas, e.g. T in {{{ TagK[Either[T, ?]] }}} + * * TagK* does not resolve for constructors with bounded parameters, e.g. S in {{{ class Abc[S <: String]; TagK[Abc] }}} + * (You can still have a bound in partial application: e.g. {{{ class Abc[S <: String, A]; TagK[Abc["hi", ?]] }}} + * * Further details at [[https://github.com/7mind/izumi/pull/369]] + */ @implicitNotFound("could not find implicit value for Tag[${T}]. Did you forget to put on a Tag, TagK or TagKK context bound on one of the parameters in ${T}? e.g. def x[T: Tag, F[_]: TagK] = ...") trait Tag[T] extends TagInterface[T, TypeTag] { def tag: LightTypeTag @@ -75,17 +75,17 @@ trait Tags extends UniverseGeneric { self => * def x[K[_[_, _], _[_], _[_[_], _, _, _]: Tag.auto.T]: Tag.auto.T[K] = implicitly[Tag.auto.T[K]] * }}} * - * */ + **/ def auto: Any = macro TagLambdaMacro.lambdaImpl def apply[T: Tag]: Tag[T] = implicitly - def apply[T](t: TypeTag[T], FLTT: LightTypeTag): Tag[T] = + def apply[T](t: TypeTag[T], FLTT: LightTypeTag): Tag[T] = { new Tag[T] { override val tpe: TypeTag[T] = t override def tag: LightTypeTag = FLTT } - + } /** * Resulting [Tag] will not have the ability to migrate into a different universe * (which is not usually a problem, but still worth naming it 'unsafe') @@ -95,7 +95,6 @@ trait Tags extends UniverseGeneric { self => tpe.use(t => Tag(ReflectionUtil.typeToTypeTag[T](u: u.type)(t, mirror), tpe.tag)) } - /** * Create a Tag of a type formed by applying the type in `tag` to `args`. * @@ -181,12 +180,9 @@ trait Tags extends UniverseGeneric { self => trait HKTag[T] extends TagInterface[T, TypeTag] { def tag: LightTypeTag - override def toString: String = - s"${hktagFormat(tpe.tpe)}@@[$tag]" + override def toString: String = s"${hktagFormat(tpe.tpe)}@@[$tag]" - /** - * Internal `TypeTag` holding the `typeConstructor` of type `T` - **/ + /** Internal `TypeTag` holding the `typeConstructor` of type `T` */ def tpe: TypeTag[_] } @@ -260,14 +256,16 @@ trait Tags extends UniverseGeneric { self => object TagK { /** - * Construct a type tag for a higher-kinded type `K[_]` - * - * Example: - * {{{ - * TagK[Option] - * }}} - **/ - def apply[K[_]: TagK]: TagK[K] = implicitly + * Construct a type tag for a higher-kinded type `K[_]` + * + * Example: + * {{{ + * TagK[Option] + * }}} + **/ + def apply[K[_] : TagK]: TagK[K] = { + implicitly + } } object TagKK { @@ -305,7 +303,7 @@ trait Tags extends UniverseGeneric { self => // // We need to construct a SafeType signature for a generic method, but generic parameters have no type tags // So we resort to weak type parameters and pointer equality - trait WeakTag[T] extends TagInterface[T, WeakTypeTag]{ + trait WeakTag[T] extends TagInterface[T, WeakTypeTag] { def tag: LightTypeTag def tpe: u.WeakTypeTag[_] override final def toString: String = s"WeakTag[$tag]" @@ -314,11 +312,12 @@ trait Tags extends UniverseGeneric { self => object WeakTag extends WeakTagInstances0 { def apply[T: WeakTag]: WeakTag[T] = implicitly - def apply[T](t: WeakTypeTag[T], l: LightTypeTag): WeakTag[T] = + def apply[T](t: WeakTypeTag[T], l: LightTypeTag): WeakTag[T] = { new WeakTag[T] { override def tag: LightTypeTag = l override val tpe: WeakTypeTag[T] = t } + } } trait WeakTagInstances0 extends WeakTagInstances1 { @@ -344,16 +343,18 @@ object Tags extends Tags { final val defaultTagImplicitError: String = "could not find implicit value for Tag[${T}]. Did you forget to put on a Tag, TagK or TagKK context bound on one of the parameters in ${T}? e.g. def x[T: Tag, F[_]: TagK] = ..." - final def hktagFormatMap: Map[Kind, String] = Map( - Kind(Nil) -> "Tag" - , Kind(Kind(Nil) :: Nil) -> "TagK" - , Kind(Kind(Nil) :: Kind(Nil) :: Nil) -> "TagKK" - , Kind(Kind(Nil) :: Kind(Nil) :: Kind(Nil) :: Nil) -> "TagK3" - , Kind(Kind(Kind(Nil) :: Nil) :: Nil) -> "TagT" - , Kind(Kind(Kind(Nil) :: Nil) :: Kind(Nil) :: Nil) -> "TagTK" - , Kind(Kind(Kind(Nil) :: Nil) :: Kind(Nil) :: Kind(Nil) :: Nil) -> "TagTKK" - , Kind(Kind(Kind(Nil) :: Nil) :: Kind(Nil) :: Kind(Nil) :: Kind(Nil) :: Nil) -> "TagTK3" - ) + final def hktagFormatMap: Map[Kind, String] = { + Map( + Kind(Nil) -> "Tag", + Kind(Kind(Nil) :: Nil) -> "TagK", + Kind(Kind(Nil) :: Kind(Nil) :: Nil) -> "TagKK", + Kind(Kind(Nil) :: Kind(Nil) :: Kind(Nil) :: Nil) -> "TagK3", + Kind(Kind(Kind(Nil) :: Nil) :: Nil) -> "TagT", + Kind(Kind(Kind(Nil) :: Nil) :: Kind(Nil) :: Nil) -> "TagTK", + Kind(Kind(Kind(Nil) :: Nil) :: Kind(Nil) :: Kind(Nil) :: Nil) -> "TagTKK", + Kind(Kind(Kind(Nil) :: Nil) :: Kind(Nil) :: Kind(Nil) :: Kind(Nil) :: Nil) -> "TagTK3", + ) + } final def hktagFormat(tpe: Universe#Type): String = { val kind = kindOf(tpe) diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TreeTools.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TreeUtil.scala similarity index 95% rename from fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TreeTools.scala rename to fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TreeUtil.scala index 5845a3e8ef..bad3a22d08 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TreeTools.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TreeUtil.scala @@ -3,11 +3,10 @@ package izumi.fundamentals.reflection import scala.reflect.api.Universe import scala.reflect.macros.blackbox -object TreeTools { +object TreeUtil { def stringLiteral(c: blackbox.Context)(u: Universe)(tree: u.Tree): String = { tree.collect { case l: u.Literal@unchecked if l.value.value.isInstanceOf[String] => l.value.value.asInstanceOf[String] // avoid unchecked warning }.headOption.getOrElse(c.abort(c.enclosingPosition, "must use string literal")) } - } diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TrivialMacroLogger.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TrivialMacroLogger.scala index f7ed74c6d8..0a4c0959c1 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TrivialMacroLogger.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/TrivialMacroLogger.scala @@ -7,13 +7,15 @@ import scala.reflect.ClassTag import scala.reflect.macros.blackbox /** -* To see macro debug output during compilation, set `-Dizumi.debug.macro.rtti=true` java property! e.g. -* {{{ -* sbt -Dizumi.debug.macro.rtti=true compile -* }}} -*/ + * To see macro debug output during compilation, set `-Dizumi.debug.macro.rtti=true` java property! e.g. + * {{{ + * sbt -Dizumi.debug.macro.rtti=true compile + * }}} + * + * @see [[DebugProperties]] + */ object TrivialMacroLogger { - def id(s: String) = s"izumi.debug.macro.$s" - def make[T: ClassTag](c: blackbox.Context, id: String): TrivialLogger = + def make[T: ClassTag](c: blackbox.Context, id: String): TrivialLogger = { TrivialLogger.make[T](id, config = Config(sink = new ScalacSink(c))) + } } diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTTRenderables.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTTRenderables.scala index c8d78d7cb1..28ac40725c 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTTRenderables.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTTRenderables.scala @@ -33,7 +33,6 @@ trait LTTRenderables extends WithRenderableSyntax { s"(${value.reference.render()} & ${value.decls.map(_.render()).toSeq.sorted.mkString("{", ", ", "}")})" } - implicit lazy val r_RefinementDecl: Renderable[RefinementDecl] = { case RefinementDecl.Signature(name, input, output) => s"def $name${input.map(_.render()).mkString("(", ", ", ")")}: ${output.render()}" diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTag.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTag.scala index 0cd659f7f9..0ca05bb0e8 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTag.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LTag.scala @@ -5,8 +5,8 @@ import scala.language.experimental.macros final case class LTag[T](tag: LightTypeTag) /** - * these are different summoners for light tags, it's fine for them to be the same structurally - */ + * these are different summoners for light tags, it's fine for them to be the same structurally + */ object LTag { def apply[T: LTag]: LTag[T] = implicitly diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTag.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTag.scala index 8f4e801c03..67b64dbc52 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTag.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTag.scala @@ -4,7 +4,6 @@ import java.nio.ByteBuffer import boopickle.Default.Pickler import izumi.fundamentals.platform.language.Quirks._ -import izumi.fundamentals.reflection.TrivialMacroLogger import izumi.fundamentals.reflection.macrortti.LightTypeTag.ParsedLightTypeTag.SubtypeDBs import izumi.fundamentals.reflection.macrortti.LightTypeTagRef.{AbstractReference, AppliedReference, NameReference} @@ -28,12 +27,12 @@ abstract class LightTypeTag def combine(o: LightTypeTag*): LightTypeTag = { - def mergedInhDb: Map[NameReference, Set[NameReference]] = + def mergedInhDb: Map[NameReference, Set[NameReference]] = { o.foldLeft(idb) { case (acc, v) => LightTypeTag.mergeIDBs(acc, v.idb) } - + } def mergedBases: Map[AbstractReference, Set[AbstractReference]] = { o.foldLeft(basesdb) { case (acc, v) => @@ -137,13 +136,13 @@ object LightTypeTag { implicit lazy val dbsSerializer: Pickler[SubtypeDBs] = generatePickler[SubtypeDBs] // false positive unused warnings - appliedRefSerializer.discard(); nameRefSerializer.discard(); abstractRefSerializer.discard() + appliedRefSerializer.discard(); + nameRefSerializer.discard(); + abstractRefSerializer.discard() (refSerializer, dbsSerializer) } - final val loggerId = TrivialMacroLogger.id("rtti") - private[izumi] object ReflectionLock private[macrortti] def mergeIDBs[T](self: Map[T, Set[T]], other: Map[T, Set[T]]): Map[T, Set[T]] = { diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagImpl.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagImpl.scala index 0a80d3b7c9..10d4618609 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagImpl.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagImpl.scala @@ -2,15 +2,15 @@ package izumi.fundamentals.reflection.macrortti import java.util.concurrent.ConcurrentHashMap +import izumi.fundamentals.collections.IzCollections._ import izumi.fundamentals.platform.console.TrivialLogger import izumi.fundamentals.reflection.ReflectionUtil._ -import izumi.fundamentals.reflection.SingletonUniverse import izumi.fundamentals.reflection.macrortti.LightTypeTag.ReflectionLock import izumi.fundamentals.reflection.macrortti.LightTypeTagImpl.Broken import izumi.fundamentals.reflection.macrortti.LightTypeTagRef.RefinementDecl.TypeMember -import izumi.fundamentals.reflection.macrortti.LightTypeTagRef._ -import izumi.fundamentals.collections.IzCollections._ import izumi.fundamentals.reflection.macrortti.LightTypeTagRef.SymName.{SymLiteral, SymTermName, SymTypeName} +import izumi.fundamentals.reflection.macrortti.LightTypeTagRef._ +import izumi.fundamentals.reflection.{DebugProperties, SingletonUniverse} import scala.collection.mutable import scala.reflect.api.Universe @@ -20,7 +20,7 @@ object LightTypeTagImpl { def makeLightTypeTag(u: Universe)(typeTag: u.Type): LightTypeTag = { ReflectionLock.synchronized { - val logger = TrivialLogger.make[this.type](LightTypeTag.loggerId) + val logger = TrivialLogger.make[this.type](DebugProperties.`izumi.debug.macro.rtti`) new LightTypeTagImpl[u.type](u, withCache = false, logger).makeFullTagImpl(typeTag) } } @@ -54,7 +54,7 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea deannotate(tpe.dealias) } - @inline private[this] final def freeTermPrefixTypeSuffixHeuristicEq(op: (U#Type, U#Type) => Boolean, t: U#Type, that: U#Type): Boolean = + @inline private[this] final def freeTermPrefixTypeSuffixHeuristicEq(op: (U#Type, U#Type) => Boolean, t: U#Type, that: U#Type): Boolean = { t -> that match { case (tRef: U#TypeRefApi, oRef: U#TypeRefApi) => singletonFreeTermHeuristicEq(tRef.pre, oRef.pre) && ( @@ -70,8 +70,8 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea singletonFreeTermHeuristicEq(tRef.pre, oRef.pre) && tRef.sym == oRef.sym case _ => false } - - private[this] final def singletonFreeTermHeuristicEq(t: U#Type, that: U#Type): Boolean = + } + private[this] final def singletonFreeTermHeuristicEq(t: U#Type, that: U#Type): Boolean = { t.asInstanceOf[Any] -> that.asInstanceOf[Any] match { case (tpe: scala.reflect.internal.Types#UniqueSingleType, other: scala.reflect.internal.Types#UniqueSingleType) if tpe.sym.isFreeTerm && other.sym.isFreeTerm => @@ -80,7 +80,7 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea case _ => false } - + } override final val hashCode: Int = { dealiased.typeSymbol.name.toString.hashCode } @@ -206,7 +206,6 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea stableBases } - private def makeBaseClasses(tpe: Type): Seq[(AbstractReference, AbstractReference)] = { def makeBaseLambdas(tpe: Type): Seq[AbstractReference] = { val basetypes = tpe.baseClasses.map(b => tpe.baseType(b)) @@ -214,7 +213,6 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea val targs = tpe.etaExpand.typeParams - val lambdas = if (targs.nonEmpty) { basetypes.flatMap { base => @@ -261,7 +259,6 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea out } - private def allTypeReferences(tpe: Type): Set[Type] = { def extract(tpe: Type, inh: mutable.HashSet[Type]): Unit = { val current = Seq(tpe, tpe.dealias.resultType) @@ -360,7 +357,11 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea val reference = sub(result, lamParams.toMap) val out = Lambda(lamParams.map(_._2), reference) if (!out.allArgumentsReferenced) { - thisLevel.err(s"⚠️ unused 𝝺 args! type $t => $out, context: $terminalNames, 𝝺 params: ${lamParams.map({ case (k, v) => s"$v = $k" })}, 𝝺 result: $result => $reference, referenced: ${out.referenced} ") + thisLevel.err(s"⚠️ unused 𝝺 args! type $t => $out, context: $terminalNames, 𝝺 params: ${ + lamParams.map({ + case (k, v) => s"$v = $k" + }) + }, 𝝺 result: $result => $reference, referenced: ${out.referenced} ") } thisLevel.log(s"✳️ Restored $t => $out") @@ -449,13 +450,12 @@ final class LightTypeTagImpl[U <: SingletonUniverse](val u: U, withCache: Boolea lamParams } - object UniRefinement { def unapply(tpef: u.Type): Option[(List[Type], List[SymbolApi])] = { (tpef: AnyRef) match { case x: it.RefinementTypeRef => Some((x.parents.map(_.asInstanceOf[Type]), x.decls.toList.asInstanceOf[List[SymbolApi]])) - case r: u.RefinedTypeApi @unchecked => + case r: u.RefinedTypeApi@unchecked => Some((r.parents, r.decls.toList)) case _ => None diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagInheritance.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagInheritance.scala index a308b4efb0..7c1982e061 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagInheritance.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagInheritance.scala @@ -1,12 +1,12 @@ package izumi.fundamentals.reflection.macrortti import izumi.fundamentals.collections.ImmutableMultiMap -import izumi.fundamentals.reflection.macrortti.LightTypeTagRef._ import izumi.fundamentals.platform.basics.IzBoolean._ import izumi.fundamentals.platform.console.TrivialLogger import izumi.fundamentals.platform.console.TrivialLogger.Config import izumi.fundamentals.platform.strings.IzString._ import izumi.fundamentals.reflection.macrortti.LightTypeTagInheritance.Ctx +import izumi.fundamentals.reflection.macrortti.LightTypeTagRef._ import scala.collection.mutable @@ -145,8 +145,11 @@ final class LightTypeTagInheritance(self: LightTypeTag, other: LightTypeTag) { sameArity && parameterShapeCompatible } else if (ctx.isChild(self.asName, that.asName)) { val allParents = safeParentsOf(self) - val moreParents = bdb.collect({ case (l: Lambda, b) if isSame(l.output, self.asName) => b.collect({ case l: Lambda if l.input.size == self.parameters.size => l }) - .map(l => l.combine(self.parameters.map(_.ref))) + val moreParents = bdb.collect({ + case (l: Lambda, b) if isSame(l.output, self.asName) => b.collect({ + case l: Lambda if l.input.size == self.parameters.size => l + }) + .map(l => l.combine(self.parameters.map(_.ref))) }).flatten ctx.logger.log(s"ℹ️ all parents of $self: $allParents ==> $moreParents") (allParents ++ moreParents) @@ -176,7 +179,6 @@ final class LightTypeTagInheritance(self: LightTypeTag, other: LightTypeTag) { out.toSet } - private def parentsOf(t: NameReference, out: mutable.HashSet[NameReference], tested: mutable.HashSet[NameReference]): Unit = { val direct = ib.get(t).toSet.flatten tested += t diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagMacro.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagMacro.scala index 60a92bafaa..115cabe8e9 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagMacro.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagMacro.scala @@ -2,8 +2,8 @@ package izumi.fundamentals.reflection.macrortti import boopickle.{PickleImpl, Pickler} import izumi.fundamentals.platform.console.TrivialLogger -import izumi.fundamentals.reflection.TrivialMacroLogger import izumi.fundamentals.reflection.macrortti.LightTypeTag.ParsedLightTypeTag.SubtypeDBs +import izumi.fundamentals.reflection.{DebugProperties, TrivialMacroLogger} import scala.reflect.macros.blackbox @@ -15,7 +15,7 @@ private[reflection] class LightTypeTagMacro0[C <: blackbox.Context](val c: C) { final val lightTypeTag: Tree = q"${symbolOf[LightTypeTag.type].asClass.module}" - private val logger: TrivialLogger = TrivialMacroLogger.make[this.type](c, LightTypeTag.loggerId) + private val logger: TrivialLogger = TrivialMacroLogger.make[this.type](c, DebugProperties.`izumi.debug.macro.rtti`) def cacheEnabled: Boolean = c.settings.contains("ltt-cache") @@ -78,21 +78,24 @@ private[reflection] class LightTypeTagMacro0[C <: blackbox.Context](val c: C) { protected def allPartsStrong(tpe: Type): Boolean = { def selfStrong = !tpe.typeSymbol.isParameter - def prefixStrong = tpe match { - case t: TypeRefApi => - allPartsStrong(t.pre) - case _ => - true + def prefixStrong = { + tpe match { + case t: TypeRefApi => + allPartsStrong(t.pre) + case _ => + true + } } def argsStrong = tpe.typeArgs.forall(allPartsStrong) - def intersectionStructStrong = tpe match { - case t: RefinedTypeApi => - t.parents.forall(allPartsStrong) && - t.decls.forall(s => s.isTerm || allPartsStrong(s.asType.typeSignature)) - case _ => - true + def intersectionStructStrong = { + tpe match { + case t: RefinedTypeApi => + t.parents.forall(allPartsStrong) && + t.decls.forall(s => s.isTerm || allPartsStrong(s.asType.typeSignature)) + case _ => + true + } } - selfStrong && prefixStrong && argsStrong && intersectionStructStrong } } diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagRef.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagRef.scala index 781a735b62..c41fd5dbd6 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagRef.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/LightTypeTagRef.scala @@ -59,7 +59,6 @@ sealed trait LightTypeTagRef { } } - object LightTypeTagRef { import LTTRenderables.Short._ //import LTTRenderables.Long._ @@ -135,7 +134,6 @@ object LightTypeTagRef { override def toString: String = this.render() } - sealed trait RefinementDecl object RefinementDecl { final case class Signature(name: String, input: List[AppliedReference], output: AppliedReference) extends RefinementDecl diff --git a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/RuntimeAPI.scala b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/RuntimeAPI.scala index f1c7e76c38..ea8b3b7909 100644 --- a/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/RuntimeAPI.scala +++ b/fundamentals/fundamentals-reflection/src/main/scala/izumi/fundamentals/reflection/macrortti/RuntimeAPI.scala @@ -39,7 +39,6 @@ protected[izumi] object RuntimeAPI { } } - def applyLambda(lambda: Lambda, parameters: Map[String, AbstractReference]): AbstractReference = { val newParams = lambda.input.filterNot(p => parameters.contains(p.name)) @@ -82,7 +81,6 @@ protected[izumi] object RuntimeAPI { prefix.map(p => ensureApplied(p, replaceApplied(p))) } - def replaceBoundaries(boundaries: Boundaries): Boundaries = { boundaries match { case Boundaries.Defined(bottom, top) => diff --git a/logstage/logstage-api/src/main/scala/izumi/logstage/api/AbstractLogger.scala b/logstage/logstage-api/src/main/scala/izumi/logstage/api/AbstractLogger.scala index 5cd48882e9..8d78082b38 100644 --- a/logstage/logstage-api/src/main/scala/izumi/logstage/api/AbstractLogger.scala +++ b/logstage/logstage-api/src/main/scala/izumi/logstage/api/AbstractLogger.scala @@ -1,6 +1,6 @@ package izumi.logstage.api -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.logstage.api.Log.{CustomContext, LoggerId} import izumi.logstage.macros.LoggerMacroMethods._ diff --git a/logstage/logstage-api/src/main/scala/izumi/logstage/api/Log.scala b/logstage/logstage-api/src/main/scala/izumi/logstage/api/Log.scala index 0d2318a278..b7944a1cab 100644 --- a/logstage/logstage-api/src/main/scala/izumi/logstage/api/Log.scala +++ b/logstage/logstage-api/src/main/scala/izumi/logstage/api/Log.scala @@ -1,8 +1,7 @@ package izumi.logstage.api import izumi.fundamentals.collections.IzCollections._ -import izumi.fundamentals.platform.language.{CodePosition, SourceFilePosition} -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.{CodePosition, CodePositionMaterializer, SourceFilePosition} import izumi.logstage.macros.LogMessageMacro.logMessageMacro import scala.language.experimental.macros diff --git a/logstage/logstage-api/src/main/scala/izumi/logstage/macros/LoggerMacroMethods.scala b/logstage/logstage-api/src/main/scala/izumi/logstage/macros/LoggerMacroMethods.scala index 8cf6190e2a..d894dcf22e 100644 --- a/logstage/logstage-api/src/main/scala/izumi/logstage/macros/LoggerMacroMethods.scala +++ b/logstage/logstage-api/src/main/scala/izumi/logstage/macros/LoggerMacroMethods.scala @@ -1,7 +1,7 @@ package izumi.logstage.macros -import izumi.fundamentals.reflection.CodePositionMaterializer -import izumi.fundamentals.reflection.CodePositionMaterializer.getEnclosingPosition +import izumi.fundamentals.platform.language.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer.getEnclosingPosition import izumi.logstage.api.{AbstractLogger, Log} import izumi.logstage.macros.LogMessageMacro._ @@ -33,7 +33,7 @@ object LoggerMacroMethods { logMacro(c)(c.universe.reify(Log.Level.Crit), logMessageMacro(c)(message), getEnclosingPosition(c)) } - @inline private[this] def logMacro(c: blackbox.Context { type PrefixType = AbstractLogger })(level: c.Expr[Log.Level], message: c.Expr[Log.Message], position: c.Expr[CodePositionMaterializer]): c.Expr[Unit] = { + @inline private[this] def logMacro(c: blackbox.Context {type PrefixType = AbstractLogger})(level: c.Expr[Log.Level], message: c.Expr[Log.Message], position: c.Expr[CodePositionMaterializer]): c.Expr[Unit] = { c.universe.reify { { val self = c.prefix.splice diff --git a/logstage/logstage-core/src/main/scala/izumi/logstage/macros/LogIOMacros.scala b/logstage/logstage-core/src/main/scala/izumi/logstage/macros/LogIOMacros.scala index 4978ef3575..d925cc2a65 100644 --- a/logstage/logstage-core/src/main/scala/izumi/logstage/macros/LogIOMacros.scala +++ b/logstage/logstage-core/src/main/scala/izumi/logstage/macros/LogIOMacros.scala @@ -1,6 +1,6 @@ package izumi.logstage.macros -import izumi.fundamentals.reflection.CodePositionMaterializer.getEnclosingPosition +import izumi.fundamentals.platform.language.CodePositionMaterializer.getEnclosingPosition import izumi.logstage.macros.LogMessageMacro.logMessageMacro import logstage.{Log, LogIO} diff --git a/logstage/logstage-core/src/main/scala/logstage/LogCreateIO.scala b/logstage/logstage-core/src/main/scala/logstage/LogCreateIO.scala index 7472d43ed5..90b7cc8b5a 100644 --- a/logstage/logstage-core/src/main/scala/logstage/LogCreateIO.scala +++ b/logstage/logstage-core/src/main/scala/logstage/LogCreateIO.scala @@ -1,7 +1,7 @@ package logstage import izumi.functional.mono.SyncSafe -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.logstage.api.Log.{Context, CustomContext, Entry, Message} trait LogCreateIO[F[_]] { diff --git a/logstage/logstage-core/src/main/scala/logstage/LogIO.scala b/logstage/logstage-core/src/main/scala/logstage/LogIO.scala index 831484bdbf..71367d2f9f 100644 --- a/logstage/logstage-core/src/main/scala/logstage/LogIO.scala +++ b/logstage/logstage-core/src/main/scala/logstage/LogIO.scala @@ -1,7 +1,7 @@ package logstage import izumi.functional.mono.SyncSafe -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.logstage.api.AbstractLogger import izumi.logstage.api.Log._ import izumi.logstage.macros.LogIOMacros._ diff --git a/logstage/logstage-core/src/main/scala/logstage/LogstageCats.scala b/logstage/logstage-core/src/main/scala/logstage/LogstageCats.scala index 7a240df138..98097cee51 100644 --- a/logstage/logstage-core/src/main/scala/logstage/LogstageCats.scala +++ b/logstage/logstage-core/src/main/scala/logstage/LogstageCats.scala @@ -2,7 +2,7 @@ package logstage import cats.syntax.flatMap._ import izumi.functional.mono.SyncSafe -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.logstage.api.AbstractLogger import izumi.logstage.api.Log.{CustomContext, Entry, Message} import logstage.LogCreateIO.LogCreateIOSyncSafeInstance diff --git a/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala b/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala index a2db3f9206..b20c89ffff 100644 --- a/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala +++ b/logstage/logstage-core/src/main/scala/logstage/LogstageZIO.scala @@ -1,7 +1,7 @@ package logstage import izumi.functional.bio.SyncSafe2 -import izumi.fundamentals.reflection.CodePositionMaterializer +import izumi.fundamentals.platform.language.CodePositionMaterializer import izumi.logstage.api.AbstractLogger import izumi.logstage.api.Log.{CustomContext, Entry, Message} import logstage.LogCreateIO.LogCreateIOSyncSafeInstance diff --git a/project/Deps.sc b/project/Deps.sc index c2f7d3b42f..9c0823c0b1 100644 --- a/project/Deps.sc +++ b/project/Deps.sc @@ -1,4 +1,6 @@ -import $ivy.`io.7mind.izumi.sbt::sbtgen:0.0.38`, izumi.sbtgen._, izumi.sbtgen.model._ +import $ivy.`io.7mind.izumi.sbt::sbtgen:0.0.38` +import izumi.sbtgen._ +import izumi.sbtgen.model._ object Izumi { @@ -221,7 +223,7 @@ object Izumi { )""".raw, "scmInfo" in SettingScope.Build := """Some(ScmInfo(url("https://github.com/7mind/izumi"), "scm:git:https://github.com/7mind/izumi.git"))""".raw, SettingDef.RawSettingDef("""scalacOptions in ThisBuild ++= Seq("-Ybackend-parallelism", math.max(1, sys.runtime.availableProcessors() - 1).toString)"""), - "scalacOptions" in SettingScope.Build += s"""${"\""*3}-Xmacro-settings:scalatest-version=${V.scalatest}${"\""*3}""".raw, + "scalacOptions" in SettingScope.Build += s"""${"\"" * 3}-Xmacro-settings:scalatest-version=${V.scalatest}${"\"" * 3}""".raw, ) final val sharedSettings = Defaults.SbtMeta ++ Seq( @@ -320,7 +322,7 @@ object Izumi { } final val forkTests = Seq( - "fork" in (SettingScope.Test, Platform.Jvm) := true, + "fork" in(SettingScope.Test, Platform.Jvm) := true, ) final lazy val fundamentals = Aggregate( @@ -333,12 +335,14 @@ object Izumi { ), Artifact( name = Projects.fundamentals.platform, - libs = Seq.empty, + libs = Seq( + scala_reflect in Scope.Provided.jvm, + ), depends = Seq( Projects.fundamentals.collections in Scope.Compile.all ), settings = Seq( - "npmDependencies" in (SettingScope.Test, Platform.Js) ++= Seq("hash.js" -> "1.1.7"), + "npmDependencies" in(SettingScope.Test, Platform.Js) ++= Seq("hash.js" -> "1.1.7"), ), plugins = Plugins(Seq(Plugin("ScalaJSBundlerPlugin", Platform.Js))), ), @@ -432,7 +436,7 @@ object Izumi { libs = Seq(scalatest.dependency in Scope.Compile.all) ++ allMonads, depends = Seq(Projects.distage.config, Projects.distage.roles, Projects.distage.static, Projects.logstage.di).map(_ in Scope.Compile.all) ++ - Seq(Projects.distage.core, Projects.distage.plugins).map(_ tin Scope.Compile.all), + Seq(Projects.distage.core, Projects.distage.plugins).map(_ tin Scope.Compile.all), settings = Seq( "classLoaderLayeringStrategy" in SettingScope.Test := "ClassLoaderLayeringStrategy.Flat".raw, ),