@@ -236,6 +236,7 @@ class ProvideMacroInspection extends LocalInspectionTool {
236
236
237
237
private def visitIssue (holder : ProblemsHolder , expr : ScExpression )(issue : ConstructionIssue ): Unit =
238
238
issue match {
239
+ case UnsupportedIssue => ()
239
240
case error : ConstructionError => visitError(holder, expr)(error)
240
241
case warning : ConstructionWarning => visitWarning(holder, expr)(warning)
241
242
}
@@ -253,7 +254,7 @@ class ProvideMacroInspection extends LocalInspectionTool {
253
254
duplicates.foreach {
254
255
case (tpe, exprs) =>
255
256
exprs.foreach { expr =>
256
- holder.registerProblem(expr.value, ambigousLayersError (tpe, exprs), errorHighlight)
257
+ holder.registerProblem(expr.value, ambiguousLayersError (tpe, exprs), errorHighlight)
257
258
}
258
259
}
259
260
case CircularityError (circular) =>
@@ -311,7 +312,16 @@ final case class LayerBuilder(
311
312
typeToLayer : ZType => String
312
313
)(implicit pContext : ProjectContext , scalaFeatures : ScalaFeatures ) {
313
314
314
- def tryBuild : Either [ConstructionIssue , Unit ] = assertNoAmbiguity.flatMap(_ => tryBuildInternal)
315
+ // TODO find a better way!
316
+ def tryBuild (expr : ScExpression ): Either [ConstructionIssue , Unit ] = assertNoAmbiguity.flatMap(_ =>
317
+ layerTreeEither match {
318
+ case Left (buildErrors) => Left (graphToConstructionErrors(buildErrors))
319
+ case Right (tree) =>
320
+ // forgive me for I have side-effected :(
321
+ expr.putUserData(GraphDataKey , tree)
322
+ Right (warnUnused(tree))
323
+ }
324
+ )
315
325
316
326
private val target =
317
327
if (method.isProvideSomeShared) target0.filterNot(t => remainder.exists(_.isSubtypeOf(t)))
@@ -334,27 +344,21 @@ final case class LayerBuilder(
334
344
else Left (DuplicateLayersError (duplicates))
335
345
}
336
346
337
- private def tryBuildInternal : Either [ConstructionIssue , Unit ] = {
347
+ def layerTreeEither : Either [:: [ GraphError ], LayerTree [ ZExpr ] ] = {
338
348
339
349
/**
340
350
* Build the layer tree. This represents the structure of a successfully
341
351
* constructed ZLayer that will build the target types. This, of course, may
342
352
* fail with one or more GraphErrors.
343
353
*/
344
- val layerTreeEither : Either [:: [GraphError ], LayerTree [ZExpr ]] = {
345
- val nodes = providedLayerNodes ++ remainderNodes ++ sideEffectNodes
346
- val graph = Graph (nodes, _.isSubtypeOf(_))
347
354
348
- for {
349
- original <- graph.buildComplete(target)
350
- sideEffects <- graph.buildNodes(sideEffectNodes)
351
- } yield sideEffects ++ original
352
- }
355
+ val nodes = providedLayerNodes ++ remainderNodes ++ sideEffectNodes
356
+ val graph = Graph (nodes, _.isSubtypeOf(_))
353
357
354
- layerTreeEither match {
355
- case Left (buildErrors) => Left (graphToConstructionErrors(buildErrors) )
356
- case Right (tree) => warnUnused(tree )
357
- }
358
+ for {
359
+ original <- graph.buildComplete(target )
360
+ sideEffects <- graph.buildNodes(sideEffectNodes )
361
+ } yield sideEffects ++ original
358
362
}
359
363
360
364
/**
@@ -449,6 +453,27 @@ final case class LayerBuilder(
449
453
450
454
object LayerBuilder {
451
455
456
+ final case class MermaidGraph (topLevel : List [String ], deps : Map [String , List [String ]]) {
457
+ def ++ (that : MermaidGraph ): MermaidGraph =
458
+ MermaidGraph (topLevel ++ that.topLevel, deps ++ that.deps)
459
+
460
+ def >>> (that : MermaidGraph ): MermaidGraph = {
461
+ val newDeps =
462
+ that.deps.map {
463
+ case (key, values) =>
464
+ key -> (values ++ topLevel)
465
+ }
466
+ MermaidGraph (that.topLevel, deps ++ newDeps)
467
+ }
468
+ }
469
+
470
+ object MermaidGraph {
471
+ def empty : MermaidGraph = MermaidGraph (List .empty, Map .empty)
472
+
473
+ def make (string : String ): MermaidGraph =
474
+ MermaidGraph (List (string), Map (string -> List .empty))
475
+ }
476
+
452
477
// version specific: making sure ScType <: Has[_]
453
478
def tryBuildZIO1 (expr : ScExpression )(
454
479
target : Seq [ScType ],
@@ -489,7 +514,7 @@ object LayerBuilder {
489
514
val remainder0 = remainder.toList.flatMap(toZType)
490
515
val providedLayerNodes0 = providedLayers.toList.flatMap(layerToNode)
491
516
492
- if (containsNothingAsRequirement(target, remainder, providedLayerNodes0)) Right (() )
517
+ if (containsNothingAsRequirement(target, remainder, providedLayerNodes0)) Left ( UnsupportedIssue )
493
518
else if (nonHasTypes.nonEmpty)
494
519
Left (NonHasTypesError (nonHasTypes.toSet))
495
520
else
@@ -500,7 +525,7 @@ object LayerBuilder {
500
525
sideEffectNodes = Nil ,
501
526
method = method,
502
527
typeToLayer = tpe => s " _root_.zio.ZLayer.requires[ $tpe] "
503
- ).tryBuild
528
+ ).tryBuild(expr)
504
529
}
505
530
506
531
// version-specific: taking care of Debug and side-effect layers
@@ -532,7 +557,7 @@ object LayerBuilder {
532
557
val (sideEffectNodes, providedLayerNodes) =
533
558
providedLayers.toList.flatMap(layerToNode).partition(_.outputs.exists(o => api.Unit .conforms(o.value)))
534
559
535
- if (containsNothingAsRequirement(target, remainder, providedLayerNodes)) Right (() )
560
+ if (containsNothingAsRequirement(target, remainder, providedLayerNodes)) Left ( UnsupportedIssue )
536
561
else
537
562
LayerBuilder (
538
563
target0 = target.toList.flatMap(ZType (_)),
@@ -541,7 +566,7 @@ object LayerBuilder {
541
566
sideEffectNodes = sideEffectNodes,
542
567
method = method,
543
568
typeToLayer = tpe => s " _root_.zio.ZLayer.environment[ $tpe] "
544
- ).tryBuild
569
+ ).tryBuild(expr)
545
570
}
546
571
547
572
// Sometimes IntelliJ fails to infer actual type and uses `Nothing` instead.
@@ -603,6 +628,7 @@ object LayerBuilder {
603
628
}
604
629
605
630
sealed trait ConstructionIssue
631
+ case object UnsupportedIssue extends ConstructionIssue // in case of Scala 3 / IntelliJ inference issues
606
632
607
633
sealed trait ConstructionError extends ConstructionIssue
608
634
final case class DuplicateLayersError (duplicates : Map [ZType , Seq [ZExpr ]]) extends ConstructionError
@@ -628,6 +654,9 @@ sealed abstract class LayerTree[+A] { self =>
628
654
def ++ [A1 >: A ](that : LayerTree [A1 ]): LayerTree [A1 ] =
629
655
if (self eq Empty ) that else if (that eq Empty ) self else ComposeH (self, that)
630
656
657
+ def map [B ](f : A => B ): LayerTree [B ] =
658
+ fold[LayerTree [B ]](Empty , a => Value (f(a)), ComposeH (_, _), ComposeV (_, _))
659
+
631
660
def fold [B ](z : B , value : A => B , composeH : (B , B ) => B , composeV : (B , B ) => B ): B = self match {
632
661
case Empty => z
633
662
case Value (value0) => value(value0)
@@ -638,7 +667,6 @@ sealed abstract class LayerTree[+A] { self =>
638
667
}
639
668
640
669
def toSet [A1 >: A ]: Set [A1 ] = fold[Set [A1 ]](Set .empty[A1 ], Set (_), _ ++ _, _ ++ _)
641
-
642
670
}
643
671
644
672
object LayerTree {
@@ -756,17 +784,15 @@ object ErrorRendering {
756
784
List (header, topLevelString, transitiveStrings, footer).flatten.mkString(lineSeparator)
757
785
}
758
786
759
- def ambigousLayersError (tpe : ZType , providedBy : Seq [ZExpr ]): String =
787
+ def ambiguousLayersError (tpe : ZType , providedBy : Seq [ZExpr ]): String =
760
788
s """ Ambiguous layers! $tpe is provided by:
761
789
| ${providedBy.mkString(lineSeparator)}""" .stripMargin
762
790
763
791
def circularityError (a : ZExpr , b : ZExpr ): String =
764
792
s """ |Circular Dependency Detected
765
793
|A layer simultaneously requires and is required by another:
766
794
| "◉" $b
767
-
768
795
| "╰─◉" $a
769
-
770
796
| "╰─ ◉" $b""" .stripMargin
771
797
772
798
def nonHasTypeError (types : Set [ZType ]): String =
0 commit comments