All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dependency.literal.Extensions.scala Maven / Gradle / Ivy

The newest version!
package dependency
package literal

import dependency.parser.{DependencyParser, ModuleParser}

import scala.quoted._

// some inspiration from https://github.com/typelevel/literally/blob/d1f4e84e1b521cfe25805aacc3b9e225fd7cbc26/core/shared/src/main/scala-3/org/typelevel/literally/Literally.scala

object Extensions {

  private def inputStrings(strCtxExpr: Expr[StringContext])(using Quotes): Seq[String] =
    strCtxExpr.value match {
      case None =>
        quotes.reflect.report.error("StringContext args must be statically known")
        ???
      case Some(sc) =>
        sc.parts
    }

  private def option[T: ToExpr : Type](opt: Option[T])(using Quotes): Expr[Option[T]] =
    opt match {
      case None => '{None}
      case Some(value) => '{Some(${Expr(value)})}
    }

  private def nameAttr(nameAttr: NameAttributes)(using Quotes): Expr[NameAttributes] =
    nameAttr match {
      case NoAttributes => '{NoAttributes}
      case ScalaNameAttributes(fullCrossVersion, platform) =>
        '{ScalaNameAttributes(${option(fullCrossVersion)}, ${option(platform)})}
    }

  private def module(mod: ModuleLike[NameAttributes], mappings: Mappings)(using Quotes): Expr[ModuleLike[NameAttributes]] =
    '{
      ModuleLike(
        ${mappings.Expr(mod.organization)},
        ${mappings.Expr(mod.name)},
        ${nameAttr(mod.nameAttributes)},
        ${mappings.mapStringString(mod.attributes)}
      )
    }

  private def dependency(dep: DependencyLike[NameAttributes, NameAttributes], mappings: Mappings)(using Quotes): Expr[DependencyLike[NameAttributes, NameAttributes]] = {
    val excludes = dep.exclude.toVector.sortBy(_.toString).map(module(_, mappings))
    '{
      DependencyLike(
        ${module(dep.module, mappings)},
        ${mappings.Expr(dep.version)},
        Set(${Varargs(excludes)}: _*),
        ${mappings.mapStringStringOption(dep.userParams)}
      )
    }
  }

  def parseModule(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using Quotes): Expr[ModuleLike[NameAttributes]] = {

    val inputs = inputStrings(strCtxExpr)
    val mappings = Mappings.from(inputs, argsExpr)
    val input = mappings.input(inputs)

    ModuleParser.parse(input) match {
      case Left(msg) =>
        quotes.reflect.report.error(s"parsing module failed: $msg")
        ???
      case Right(mod) =>
        module(mod, mappings)
    }
  }

  def parseDependency(strCtxExpr: Expr[StringContext], argsExpr: Expr[Seq[Any]])(using Quotes): Expr[DependencyLike[NameAttributes, NameAttributes]] = {

    val inputs = inputStrings(strCtxExpr)
    val mappings = Mappings.from(inputs, argsExpr)
    val input = mappings.input(inputs)

    DependencyParser.parse(input) match {
      case Left(msg) =>
        quotes.reflect.report.error(s"parsing dependency failed: $msg", argsExpr)
        ???
      case Right(dep) =>
        dependency(dep, mappings)
    }
  }
}

trait Extensions {
  extension (inline sc: StringContext)
    inline def mod(inline args: Any*): ModuleLike[NameAttributes] =
      ${Extensions.parseModule('sc, 'args)}
    inline def dep(inline args: Any*): DependencyLike[NameAttributes, NameAttributes] =
      ${Extensions.parseDependency('sc, 'args)}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy