@@ -18,10 +18,14 @@ module OpenAPI.Checker.Subtree
18 , CompatFormula'
18 , CompatFormula'
19 , SemanticCompatFormula
19 , SemanticCompatFormula
20 , ProdCons (..)
20 , ProdCons (..)
21− , HasUnsupportedFeature (..)
22 , swapProdCons
21 , swapProdCons
23 , runCompatFormula
22 , runCompatFormula
26+ , invertIssueOrientation
27+ , invertIssueOrientationP
26 , structuralIssue
30 , structuralIssue
@@ -53,7 +57,6 @@ import Data.HList
53import qualified Data.HashMap.Strict.InsOrd as IOHM
57import qualified Data.HashMap.Strict.InsOrd as IOHM
54import Data.Hashable
58import Data.Hashable
55import Data.Kind
59import Data.Kind
57import Data.OpenApi
60import Data.OpenApi
58import qualified Data.Set as S
61import qualified Data.Set as S
59import Data.Typeable
62import Data.Typeable
@@ -106,8 +109,38 @@ data ProdCons a = ProdCons
107 deriving stock (Eq, Ord, Show, Functor, Foldable, Traversable)
110 deriving stock (Eq, Ord, Show, Functor, Foldable, Traversable)
109−swapProdCons :: ProdCons a -> ProdCons a
112+swapProdCons
114+ => (HList xs -> ProdCons x -> CompatFormula' q AnIssue r a)
115+ -> (HList xs -> ProdCons x -> CompatFormula' q AnIssue r a)
110−swapProdCons (ProdCons a b) = ProdCons b a
116+swapProdCons f e (ProdCons p c) =
117+ invertIssueOrientation $
118+ f (swapEnvRoles e) (ProdCons c p)
119+{-# INLINE swapProdCons #-}
121+type family IsProdCons (x :: Type) :: Bool where
122+ IsProdCons (ProdCons _) = 'True
123+ IsProdCons _ = 'False
125+type SwapEnvElementRoles x = SwapEnvElementRoles' x (IsProdCons x)
127+class IsProdCons x ~ f => SwapEnvElementRoles' (x :: Type) f where
128+ swapEnvElementRoles :: x -> x
130+instance SwapEnvElementRoles' (ProdCons x) 'True where
131+ swapEnvElementRoles (ProdCons p c) = ProdCons c p
133+instance IsProdCons x ~ 'False => SwapEnvElementRoles' x 'False where
134+ swapEnvElementRoles = id
136+class SwapEnvRoles xs where
137+ swapEnvRoles :: HList xs -> HList xs
139+instance SwapEnvRoles '[] where
142+instance (SwapEnvElementRoles x, SwapEnvRoles xs) => SwapEnvRoles (x ': xs) where
143+ swapEnvRoles (HCons x xs) = HCons (swapEnvElementRoles x) (swapEnvRoles xs)
112instance Applicative ProdCons where
145instance Applicative ProdCons where
113 pure x = ProdCons x x
146 pure x = ProdCons x x
@@ -145,14 +178,12 @@ class (Typeable t, Issuable (SubtreeLevel t)) => Subtree (t :: Type) where
145 type SubtreeLevel t :: BehaviorLevel
178 type SubtreeLevel t :: BehaviorLevel
147 checkStructuralCompatibility
180 checkStructuralCompatibility
148− :: (HasAll (CheckEnv t) xs)
181+ :: HList (CheckEnv t)
150 -> ProdCons (Traced t)
182 -> ProdCons (Traced t)
151 -> StructuralCompatFormula ()
183 -> StructuralCompatFormula ()
153 checkSemanticCompatibility
185 checkSemanticCompatibility
154− :: (HasAll (CheckEnv t) xs)
186+ :: HList (CheckEnv t)
156 -> Behavior (SubtreeLevel t)
187 -> Behavior (SubtreeLevel t)
157 -> ProdCons (Traced t)
188 -> ProdCons (Traced t)
158 -> SemanticCompatFormula ()
189 -> SemanticCompatFormula ()
@@ -162,29 +193,33 @@ class (Typeable t, Issuable (SubtreeLevel t)) => Subtree (t :: Type) where
162{-# WARNING checkSemanticCompatibility "You should not be calling this directly. Use 'checkCompatibility'" #-}
193{-# WARNING checkSemanticCompatibility "You should not be calling this directly. Use 'checkCompatibility'" #-}
164checkCompatibility
195checkCompatibility
165− :: (HasAll (CheckEnv t) xs, Subtree t)
197+ (ReassembleHList xs (CheckEnv t), Subtree t)
167− -> Behavior (SubtreeLevel t)
198+ => Behavior (SubtreeLevel t)
168 -> ProdCons (Traced t)
200 -> ProdCons (Traced t)
169 -> SemanticCompatFormula ()
201 -> SemanticCompatFormula ()
170−checkCompatibility e bhv = memo bhv SemanticMemoKey $ \pc ->
202+checkCompatibility bhv e = memo bhv SemanticMemoKey $ \pc ->
171 case runCompatFormula $ checkSubstructure e pc of
203 case runCompatFormula $ checkSubstructure e pc of
172− Left _ -> checkSemanticCompatibility e bhv pc
204+ Left _ -> checkSemanticCompatibility (reassemble e) bhv pc
173 Right () -> pure ()
205 Right () -> pure ()
206+{-# INLINE checkCompatibility #-}
175checkSubstructure
208checkSubstructure
176− :: (HasAll (CheckEnv t) xs, Subtree t)
209+ :: (ReassembleHList xs (CheckEnv t), Subtree t)
177 => HList xs
210 => HList xs
178 -> ProdCons (Traced t)
211 -> ProdCons (Traced t)
179 -> StructuralCompatFormula ()
212 -> StructuralCompatFormula ()
180−checkSubstructure e = memo Root StructuralMemoKey $ checkStructuralCompatibility e
213+checkSubstructure e = memo Root StructuralMemoKey $ checkStructuralCompatibility (reassemble e)
214+{-# INLINE checkSubstructure #-}
182structuralMaybe
216structuralMaybe
183− :: (Subtree a, HasAll (CheckEnv a) xs)
217+ :: (Subtree a, ReassembleHList xs (CheckEnv a))
184 => HList xs
218 => HList xs
185 -> ProdCons (Maybe (Traced a))
219 -> ProdCons (Maybe (Traced a))
186 -> StructuralCompatFormula ()
220 -> StructuralCompatFormula ()
187structuralMaybe e = structuralMaybeWith (checkSubstructure e)
221structuralMaybe e = structuralMaybeWith (checkSubstructure e)
222+{-# INLINE structuralMaybe #-}
189structuralMaybeWith
224structuralMaybeWith
190 :: (ProdCons a -> StructuralCompatFormula ())
225 :: (ProdCons a -> StructuralCompatFormula ())
@@ -193,9 +228,10 @@ structuralMaybeWith
193structuralMaybeWith f (ProdCons (Just a) (Just b)) = f $ ProdCons a b
228structuralMaybeWith f (ProdCons (Just a) (Just b)) = f $ ProdCons a b
194structuralMaybeWith _ (ProdCons Nothing Nothing) = pure ()
229structuralMaybeWith _ (ProdCons Nothing Nothing) = pure ()
195structuralMaybeWith _ _ = structuralIssue
230structuralMaybeWith _ _ = structuralIssue
231+{-# INLINE structuralMaybeWith #-}
197structuralList
233structuralList
198− :: (Subtree a, HasAll (CheckEnv a) xs)
234+ :: (Subtree a, ReassembleHList xs (CheckEnv a))
199 => HList xs
235 => HList xs
200 -> ProdCons [Traced a]
236 -> ProdCons [Traced a]
201 -> StructuralCompatFormula ()
237 -> StructuralCompatFormula ()
@@ -205,17 +241,20 @@ structuralList e (ProdCons (a : aa) (b : bb)) = do
205 structuralList e $ ProdCons aa bb
241 structuralList e $ ProdCons aa bb
207structuralList _ _ = structuralIssue
243structuralList _ _ = structuralIssue
244+{-# INLINE structuralList #-}
209structuralEq :: (Eq a, Comonad w) => ProdCons (w a) -> StructuralCompatFormula ()
246structuralEq :: (Eq a, Comonad w) => ProdCons (w a) -> StructuralCompatFormula ()
210structuralEq (ProdCons a b) = if extract a == extract b then pure () else structuralIssue
247structuralEq (ProdCons a b) = if extract a == extract b then pure () else structuralIssue
248+{-# INLINE structuralEq #-}
212iohmStructural
250iohmStructural
213− :: (HasAll (CheckEnv v) (k ': xs), Ord k, Subtree v, Hashable k, Typeable k, Show k)
251+ :: (ReassembleHList (k ': xs) (CheckEnv v), Ord k, Subtree v, Hashable k, Typeable k, Show k)
214 => HList xs
252 => HList xs
215 -> ProdCons (Traced (IOHM.InsOrdHashMap k v))
253 -> ProdCons (Traced (IOHM.InsOrdHashMap k v))
216 -> StructuralCompatFormula ()
254 -> StructuralCompatFormula ()
217iohmStructural e =
255iohmStructural e =
218 iohmStructuralWith (\k -> checkSubstructure (k `HCons` e))
256 iohmStructuralWith (\k -> checkSubstructure (k `HCons` e))
257+{-# INLINE iohmStructural #-}
220instance (Typeable k, Typeable v, Ord k, Show k) => Steppable (IOHM.InsOrdHashMap k v) v where
259instance (Typeable k, Typeable v, Ord k, Show k) => Steppable (IOHM.InsOrdHashMap k v) v where
221 data Step (IOHM.InsOrdHashMap k v) v = InsOrdHashMapKeyStep k
260 data Step (IOHM.InsOrdHashMap k v) v = InsOrdHashMapKeyStep k
@@ -235,41 +274,36 @@ iohmStructuralWith f pc = do
235 (\eKey ->
274 (\eKey ->
236 f eKey $ stepTraced (InsOrdHashMapKeyStep eKey) . fmap (IOHM.lookupDefault (error "impossible") eKey) <$> pc)
275 f eKey $ stepTraced (InsOrdHashMapKeyStep eKey) . fmap (IOHM.lookupDefault (error "impossible") eKey) <$> pc)
237 else structuralIssue
276 else structuralIssue
238−
277+{-# INLINE iohmStructuralWith #-}
239−class HasUnsupportedFeature x where
240− hasUnsupportedFeature :: x -> Bool
242−instance HasUnsupportedFeature () where
243− hasUnsupportedFeature () = False
246− (HasUnsupportedFeature a, HasUnsupportedFeature b)
247− => HasUnsupportedFeature (Either a b)
249− hasUnsupportedFeature (Left x) = hasUnsupportedFeature x
250− hasUnsupportedFeature (Right x) = hasUnsupportedFeature x
252−instance Issuable l => HasUnsupportedFeature (Issue l) where
253− hasUnsupportedFeature = issueIsUnsupported
255−instance HasUnsupportedFeature (AnIssue l) where
256− hasUnsupportedFeature (AnIssue issue) = hasUnsupportedFeature issue
259− (forall x. HasUnsupportedFeature (f x))
260− => HasUnsupportedFeature (P.PathsPrefixTree q f r)
262− hasUnsupportedFeature =
263− getAny . P.foldWith (\_ fa -> Any $ hasUnsupportedFeature fa)
265runCompatFormula
279runCompatFormula
266 :: CompatFormula' q f r a
280 :: CompatFormula' q f r a
267 -> Either (P.PathsPrefixTree q f r) a
281 -> Either (P.PathsPrefixTree q f r) a
268runCompatFormula (Compose f) =
282runCompatFormula (Compose f) =
269 calculate . runIdentity . runMemo 0 . unCompatM $ f
283 calculate . runIdentity . runMemo 0 . unCompatM $ f
284+{-# INLINE runCompatFormula #-}
286+embedFormula :: Paths q r l -> CompatFormula' q f l a -> CompatFormula' q f r a
287+embedFormula bhv (Compose x) = Compose $ mapErrors (P.embed bhv) <$> x
271issueAt :: Issuable l => Paths q r l -> Issue l -> CompatFormula' q AnIssue r a
289issueAt :: Issuable l => Paths q r l -> Issue l -> CompatFormula' q AnIssue r a
272−issueAt xs issue = Compose $ pure $ anError $ AnItem xs $ AnIssue issue
290+issueAt xs issue = Compose $ pure $ anError $ AnItem xs $ anIssue issue
291+{-# INLINE issueAt #-}
293+anIssue :: Issuable l => Issue l -> AnIssue l
294+anIssue = AnIssue Forward
295+{-# INLINE anIssue #-}
297+anItem :: AnItem q AnIssue r -> CompatFormula' q AnIssue r a
298+anItem = Compose . pure . anError
299+{-# INLINE anItem #-}
301+invertIssueOrientation :: CompatFormula' q AnIssue r a -> CompatFormula' q AnIssue r a
302+invertIssueOrientation (Compose x) =
303+ Compose $ mapErrors invertIssueOrientationP <$> x
305+invertIssueOrientationP :: P.PathsPrefixTree q AnIssue r -> P.PathsPrefixTree q AnIssue r
306+invertIssueOrientationP = P.map (\(AnIssue ori i) -> AnIssue (toggleOrientation ori) i)
274structuralIssue :: StructuralCompatFormula a
308structuralIssue :: StructuralCompatFormula a
275structuralIssue = Compose $ pure $ anError $ AnItem Root Proxy
309structuralIssue = Compose $ pure $ anError $ AnItem Root Proxy
@@ -282,7 +316,7 @@ anyOfAt
282 -> CompatFormula' q AnIssue r a
316 -> CompatFormula' q AnIssue r a
283anyOfAt _ _ [x] = x
317anyOfAt _ _ [x] = x
284anyOfAt xs issue fs =
318anyOfAt xs issue fs =
285− Compose $ (`eitherOf` AnItem xs (AnIssue issue)) <$> sequenceA (getCompose <$> fs)
319+ Compose $ (`eitherOf` AnItem xs (anIssue issue)) <$> sequenceA (getCompose <$> fs)
287fixpointKnot
321fixpointKnot
288 :: MonadState (MemoState VarRef) m
322 :: MonadState (MemoState VarRef) m