Skip to content

Commit

Permalink
implemented invoke, added -Werror -Wunused:all -deprecation -feature …
Browse files Browse the repository at this point in the history
…and cleaned up the core codebase
  • Loading branch information
lbialy committed Nov 28, 2023
1 parent 2b86c0c commit fee16d4
Show file tree
Hide file tree
Showing 26 changed files with 259 additions and 225 deletions.
4 changes: 3 additions & 1 deletion core/.scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ align.openParenCallSite = false
align.openParenDefnSite = false
align.tokens = [{code = "=>", owner = "Case"}, "<-", "%", "%%", "="]
indent.defnSite = 2
maxColumn = 120
maxColumn = 140

rewrite.scala3.insertEndMarkerMinLines = 40
1 change: 1 addition & 0 deletions core/project.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//> using dep "com.lihaoyi::pprint:0.6.6" // TODO BALEET

//> using options "-java-output-version:11", "-Ysafe-init"
//> using options -Werror -Wunused:all -deprecation -feature

//#> using options "-Xmax-inlines:64"

Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/besom/experimental/Monad.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension [F[+_]: Monad, A](fa: F[A])
def flatMap[B](f: A => F[B]): F[B] = Monad[F].flatMap(fa)(f)
def fork: F[A] = Monad[F].fork(fa)

import scala.concurrent.{ExecutionContext, Future, Promise}
import scala.concurrent.{ExecutionContext, Future}

class FutureMonad(implicit val ec: ExecutionContext) extends Monad[Future]:

Expand Down
6 changes: 1 addition & 5 deletions core/src/main/scala/besom/internal/CodecMacros.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ object CodecMacros:
inline def summonLabels[A] = ${ summonLabelsImpl[A] }

private def summonLabelsImpl[A: Type](using Quotes): Expr[List[String]] =
import quotes.reflect.*
Expr(recSummonLabelsImpl(Type.of[A]))

private def recSummonLabelsImpl(t: Type[?])(using Quotes): List[String] =
Expand All @@ -22,8 +21,6 @@ object CodecMacros:
inline def summonDecoders[A]: List[Decoder[?]] = ${ summonDecodersImpl[A] }

private def summonDecodersImpl[A: Type](using Quotes): Expr[List[Decoder[?]]] =
import quotes.reflect.*
// report.info(s"Deriving for ${Type.show[A]}")
Expr.ofList(recSummonDecodersImpl(Type.of[A]))

private def recSummonDecodersImpl(t: Type[?])(using Quotes): List[Expr[Decoder[?]]] =
Expand All @@ -40,7 +37,6 @@ object CodecMacros:
inline def summonEncoders[A]: List[Encoder[?]] = ${ summonEncodersImpl[A] }

private def summonEncodersImpl[A: Type](using Quotes): Expr[List[Encoder[?]]] =
import quotes.reflect.*
Expr.ofList(recSummonEncodersImpl(Type.of[A]))

private def recSummonEncodersImpl(t: Type[?])(using Quotes): List[Expr[Encoder[?]]] =
Expand All @@ -57,7 +53,6 @@ object CodecMacros:
inline def summonJsonEncoders[A]: List[JsonEncoder[?]] = ${ summonJsonEncodersImpl[A] }

private def summonJsonEncodersImpl[A: Type](using Quotes): Expr[List[JsonEncoder[?]]] =
import quotes.reflect.*
Expr.ofList(recSummonJsonEncodersImpl(Type.of[A]))

private def recSummonJsonEncodersImpl(t: Type[?])(using Quotes): List[Expr[JsonEncoder[?]]] =
Expand All @@ -77,3 +72,4 @@ object CodecMacros:
// import quotes.reflect.*

// '{ List.empty[TC[Any]] }
end CodecMacros
27 changes: 9 additions & 18 deletions core/src/main/scala/besom/internal/Context.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import besom.util.*
import besom.types.{ResourceType, FunctionToken, URN, Label, ProviderType}
import besom.internal.logging.*
import scala.annotation.implicitNotFound
import besom.internal.ComponentResource

case class InvokeOptions()

type Providers = Map[String, ProviderResource]
case class InvokeOptions(parent: Option[Resource], provider: Option[ProviderResource], version: Option[String])

@implicitNotFound(s"""|Pulumi code has to be written with a Context in scope.
|
Expand Down Expand Up @@ -70,6 +67,7 @@ trait Context extends TaskTracker:
args: A,
opts: InvokeOptions
)(using Context): Output[R]
end Context

class ComponentContext(private val globalContext: Context, private val componentURN: Result[URN]) extends Context:
export globalContext.{getParentURN => _, *}
Expand All @@ -94,8 +92,8 @@ class ContextImpl(
override private[besom] def isDryRun: Boolean = runInfo.dryRun

override private[besom] def pulumiOrganization: Option[NonEmptyString] = runInfo.organization
override private[besom] def pulumiProject: NonEmptyString = runInfo.project
override private[besom] def pulumiStack: NonEmptyString = runInfo.stack
override private[besom] def pulumiProject: NonEmptyString = runInfo.project
override private[besom] def pulumiStack: NonEmptyString = runInfo.stack

override private[besom] def getParentURN: Result[URN] =
stackPromise.get.flatMap(_.urn.getData).map(_.getValue).flatMap {
Expand Down Expand Up @@ -158,23 +156,15 @@ class ContextImpl(
ResourceOps().registerResourceOutputsInternal(urnResult, outputs)
}

private[besom] def readOrRegisterResource[R <: Resource: ResourceDecoder, A: ArgsEncoder](
typ: ResourceType,
name: NonEmptyString,
args: A,
options: ResourceOptions
): Output[R] =
// val effect: Output[R] = ???
// registerResourceCreation(typ, name, effect) // put into ConcurrentHashMap eagerly!
// effect
???

override private[besom] def invoke[A: ArgsEncoder, R: Decoder](
token: FunctionToken,
args: A,
opts: InvokeOptions
)(using Context): Output[R] =
??? // TODO: ResourceOps().invoke[A, R](token, args, opts)
BesomMDC(Key.LabelKey, Label.fromFunctionToken(token)) {
ResourceOps().invoke[A, R](token, args, opts)
}
end ContextImpl

object Context:

Expand Down Expand Up @@ -218,3 +208,4 @@ object Context:
ctx <- apply(runInfo, featureSupport, config, logger, monitor, engine, taskTracker)
_ <- ctx.initializeStack
yield ctx
end Context
3 changes: 2 additions & 1 deletion core/src/main/scala/besom/internal/Exports.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ object Export extends Dynamic:
else
Expr.summon[Encoder[v]] match
case Some(encoder) =>
Right('{ ${encoder}.encode(${value}).map { (deps, value1) => (${name}, value1) }})
// TODO make sure we don't need deps here (replaced with _)
Right('{ ${encoder}.encode(${value}).map { (_, value1) => (${name}, value1) }})
case None =>
Left(() => report.error(s"Encoder[${Type.show[v]}] is missing", value))
}
Expand Down
21 changes: 10 additions & 11 deletions core/src/main/scala/besom/internal/Input.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ object Input:
extension [A](optional: A | Option[A])
private def asOption: Option[A] =
optional match
case option: Option[A @ unchecked] => option
case a: A @unchecked => Option(a)
case option: Option[A @unchecked] => option
case a: A @unchecked => Option(a)

given simpleInputOps: {} with
extension [A](input: Input[A])
private[Input] def wrappedAsOutput(isSecret: Boolean = false)(using ctx: Context): Output[A] =
input match
case output: Output[_] => output.asInstanceOf[Output[A]]
case a: A @unchecked => if isSecret then Output.secret(a) else Output(a)
case a: A @unchecked => if isSecret then Output.secret(a) else Output(a)

extension [A](input: Input[A])
def asOutput(isSecret: Boolean = false)(using ctx: Context): Output[A] =
Expand All @@ -25,7 +25,7 @@ object Input:
extension [A](input: Input.Optional[A])
private[Input] def wrappedAsOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[A]] =
val output = input match
case output: Output[_] => output.asInstanceOf[Output[A | Option[A]]]
case output: Output[_] => output.asInstanceOf[Output[A | Option[A]]]
case maybeA: (A | Option[A]) @unchecked => if isSecret then Output.secret(maybeA) else Output(maybeA)
output.map(_.asOption)

Expand All @@ -34,19 +34,18 @@ object Input:

given mapInputOps: {} with
private def inputMapToMapOutput[A](inputMap: Map[String, Input[A]], isSecret: Boolean)(using ctx: Context): Output[Map[String, A]] =
val outputMap = inputMap.mapValues(_.asOutput(isSecret)).toMap
val outputMap = inputMap.view.mapValues(_.asOutput(isSecret)).toMap
Output.traverseMap(outputMap)

extension [A](input: Input[Map[String, Input[A]]])
def asOutput(isSecret: Boolean = false)(using ctx: Context): Output[Map[String, A]] =
input.wrappedAsOutput(isSecret).flatMap(inputMapToMapOutput(_, isSecret = isSecret))


extension [A](input: Input.Optional[Map[String, Input[A]]])
def asOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[Map[String, A]]] =
input.wrappedAsOptionOutput(isSecret).flatMap {
input.wrappedAsOptionOutput(isSecret).flatMap {
case Some(map) => inputMapToMapOutput(map, isSecret = isSecret).map(Option(_))
case None => Output(None)
case None => Output(None)
}

given listInputOps: {} with
Expand All @@ -60,8 +59,8 @@ object Input:

extension [A](input: Input.Optional[List[Input[A]]])
def asOptionOutput(isSecret: Boolean = false)(using ctx: Context): Output[Option[List[A]]] =
input.wrappedAsOptionOutput(isSecret).flatMap {
input.wrappedAsOptionOutput(isSecret).flatMap {
case Some(map) => inputListToListOutput(map, isSecret = isSecret).map(Option(_))
case None => Output(None)
case None => Output(None)
}
end Input
14 changes: 8 additions & 6 deletions core/src/main/scala/besom/internal/Output.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package besom.internal

import scala.util.{NotGiven => Not}
import scala.reflect.Typeable
import scala.collection.BuildFrom

/** Output is a wrapper for a monadic effect used to model async execution that allows Pulumi to track information about
* dependencies between resources and properties of data (whether it's known or a secret for instance).
/** Output is a wrapper for a monadic effect used to model async execution that allows Pulumi to track information about dependencies
* between resources and properties of data (whether it's known or a secret for instance).
*
* Invariant: dataResult has to be registered in TaskTracker by the time it reaches the constructor here!
* @param dataResult
Expand Down Expand Up @@ -63,6 +63,7 @@ class Output[+A] private[internal] (using private[besom] val ctx: Context)(
o <- dataResult
yield o.withIsSecret(secret)
)
end Output

/** These factory methods should be the only way to create Output instances in user code!
*/
Expand All @@ -89,14 +90,14 @@ trait OutputExtensionsFactory:
def traverse[B, To](f: A => Output[B])(using BuildFrom[CC[Output[B]], B, To], Context): Output[To] =
coll.iterator.map(f).asInstanceOf[CC[Output[B]]].sequence
implicit final class OutputOptionOps[A](output: Output[Option[A]]):
def getOrElse[B >: A](default: => B | Output[B])(using ctx: Context): Output[B] =
def getOrElse[B >: A: Typeable](default: => B | Output[B])(using ctx: Context): Output[B] =
output.flatMap { opt =>
opt match
case Some(a) => Output(a)
case None =>
default match
case b: Output[B] => b
case b: B => Output(b)
case b: Output[B @unchecked] => b
case b: B => Output(b)
}
def orElse[B >: A](alternative: => Option[B] | Output[Option[B]])(using ctx: Context): Output[Option[B]] =
output.flatMap { opt =>
Expand Down Expand Up @@ -151,3 +152,4 @@ object Output:

def secret[A](value: A)(using ctx: Context): Output[A] =
new Output[A](ctx.registerTask(Result.pure(OutputData(value, Set.empty, isSecret = true))))
end Output
1 change: 0 additions & 1 deletion core/src/main/scala/besom/internal/Resource.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package besom.internal
import besom.util.NonEmptyString
import besom.types.*
import com.google.protobuf.struct.*
import scala.quoted.*
import scala.deriving.Mirror
import scala.annotation.implicitNotFound
import besom.util.*
Expand Down
11 changes: 6 additions & 5 deletions core/src/main/scala/besom/internal/ResourceDecoder.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package besom.internal

import com.google.protobuf.struct.{Struct, Value}
import com.google.protobuf.struct.Value
import scala.quoted.*
import scala.deriving.Mirror
import scala.util.chaining.*
import besom.util.*
import besom.internal.logging.*
import besom.types.{Label, URN, ResourceId}
Expand Down Expand Up @@ -31,13 +30,13 @@ object ResourceDecoder:
fields
.get(NameUnmangler.unmanglePropertyName(propertyName))
.map { value =>
log.trace(s"extracting custom property $propertyName from $value using decoder $decoder")
scribe.debug(s"extracting custom property $propertyName from $value using decoder $decoder") // TODO
decoder.decode(value, propertyLabel).map(_.withDependency(resource)) match
case Validated.Invalid(err) =>
log.trace(s"failed to extract custom property $propertyName from $value: $err")
scribe.debug(s"failed to extract custom property $propertyName from $value: $err") // TODO
Validated.Invalid(err)
case Validated.Valid(value) =>
log.trace(s"extracted custom property $propertyName from $value")
scribe.debug(s"extracted custom property $propertyName from $value") // TODO
Validated.Valid(value)
}
.getOrElse {
Expand Down Expand Up @@ -119,6 +118,7 @@ object ResourceDecoder:

(resource, resolver)
}
end makeResolver

inline def derived[A <: Resource]: ResourceDecoder[A] = ${ derivedImpl[A] }

Expand Down Expand Up @@ -156,3 +156,4 @@ object ResourceDecoder:
customPropertyExtractors = ${ customPropertyExtractorsExpr }.toVector
)
}
end ResourceDecoder
Loading

0 comments on commit fee16d4

Please sign in to comment.