@@ -39,11 +39,12 @@ import qualified Data.Set as S
39import Data.Text (Text)
39import Data.Text (Text)
40import qualified Data.Text as T hiding (singleton)
40import qualified Data.Text as T hiding (singleton)
41import Data.Typeable
41import Data.Typeable
42+import OpenAPI.Checker.Behavior
42import OpenAPI.Checker.Orphans ()
43import OpenAPI.Checker.Orphans ()
43import OpenAPI.Checker.References
44import OpenAPI.Checker.References
45+import OpenAPI.Checker.Paths
46+import qualified OpenAPI.Checker.PathsPrefixTree as P
44import OpenAPI.Checker.Subtree
47import OpenAPI.Checker.Subtree
45−import OpenAPI.Checker.Trace
46−import qualified OpenAPI.Checker.TracePrefixTree as T
48-- | Type of a JSON value
49-- | Type of a JSON value
49data JsonType
50data JsonType
@@ -53,7 +54,7 @@ data JsonType
56− deriving (Eq, Show)
57+ deriving stock (Eq, Ord, Show)
58-- | A 'A.Value' whose type we know
59-- | A 'A.Value' whose type we know
59data TypedValue :: JsonType -> Type where
60data TypedValue :: JsonType -> Type where
@@ -88,8 +89,8 @@ instance Ord a => Ord (Bound a) where
89data Property = Property
90data Property = Property
90 { propRequired :: Bool
91 { propRequired :: Bool
91− , propFormula :: ForeachType (JsonFormula OpenApi)
92+ , propFormula :: ForeachType JsonFormula
92− , propRefSchema :: Traced OpenApi (Referenced Schema)
93+ , propRefSchema :: Traced (Referenced Schema)
94 deriving stock (Eq, Ord, Show)
95 deriving stock (Eq, Ord, Show)
@@ -106,17 +107,17 @@ data Condition :: JsonType -> Type where
106 Pattern :: !Pattern -> Condition 'String
107 Pattern :: !Pattern -> Condition 'String
107 StringFormat :: !Format -> Condition 'String
108 StringFormat :: !Format -> Condition 'String
109− :: !(ForeachType (JsonFormula OpenApi))
110+ :: !(ForeachType JsonFormula)
110− -> !(Traced OpenApi (Referenced Schema))
111+ -> !(Traced (Referenced Schema))
111 -> Condition 'Array
112 -> Condition 'Array
112 MaxItems :: !Integer -> Condition 'Array
113 MaxItems :: !Integer -> Condition 'Array
113 MinItems :: !Integer -> Condition 'Array
114 MinItems :: !Integer -> Condition 'Array
114 UniqueItems :: Condition 'Array
115 UniqueItems :: Condition 'Array
115 Properties
116 Properties
116 :: !(M.Map Text Property)
117 :: !(M.Map Text Property)
117− -> !(ForeachType (JsonFormula OpenApi))
118+ -> !(ForeachType JsonFormula)
118 -- ^ formula for additional properties
119 -- ^ formula for additional properties
119− -> !(Maybe (Traced OpenApi (Referenced Schema)))
120+ -> !(Maybe (Traced (Referenced Schema)))
120 -- ^ schema for additional properties, Nothing means bottom
121 -- ^ schema for additional properties, Nothing means bottom
121 -> Condition 'Object
122 -> Condition 'Object
122 MaxProperties :: !Integer -> Condition 'Object
123 MaxProperties :: !Integer -> Condition 'Object
@@ -158,7 +159,7 @@ deriving stock instance Ord (Condition t)
158deriving stock instance Show (Condition t)
159deriving stock instance Show (Condition t)
160data SomeCondition where
161data SomeCondition where
161− SomeCondition :: Typeable t => Traced OpenApi (Condition t) -> SomeCondition
162+ SomeCondition :: Typeable t => Condition t -> SomeCondition
163instance Eq SomeCondition where
164instance Eq SomeCondition where
164 SomeCondition x == SomeCondition y = case cast x of
165 SomeCondition x == SomeCondition y = case cast x of
@@ -175,26 +176,24 @@ deriving stock instance Show SomeCondition
175-- | A boolean formula (without "not") of 'Condition's. Represented as a
176-- | A boolean formula (without "not") of 'Condition's. Represented as a
176-- Disjunctive Normal Form: the formula is a disjunction of a set of conjuncts,
177-- Disjunctive Normal Form: the formula is a disjunction of a set of conjuncts,
177-- each of which is a conjunction of a set of 'Condition's.
178-- each of which is a conjunction of a set of 'Condition's.
178−newtype JsonFormula r t
179+newtype JsonFormula t
179− = DNF (S.Set (M.Map (Condition t) (Trace r (Condition t))))
180+ = DNF (S.Set (S.Set (Condition t)))
180 deriving stock (Eq, Ord, Show)
181 deriving stock (Eq, Ord, Show)
183− :: JsonFormula r t
184+ :: JsonFormula t
184− -> M.Map (Condition t) (Trace r (Condition t))
185+ -> S.Set (Condition t)
185− -> JsonFormula r t
186+ -> JsonFormula t
186disjAdd (DNF yss) xs
187disjAdd (DNF yss) xs
187− | any (`isMapSubsetOf` xs) yss = DNF yss
188+ | any (`S.isSubsetOf` xs) yss = DNF yss
188− | otherwise = DNF $ S.insert xs $ S.filter (not . isMapSubsetOf xs) yss
189+ | otherwise = DNF $ S.insert xs $ S.filter (not . S.isSubsetOf xs) yss
190− isMapSubsetOf a b = M.keysSet a `S.isSubsetOf` M.keysSet b
192−instance Lattice (JsonFormula r t) where
191+instance Lattice (JsonFormula t) where
193 xss \/ DNF yss = S.foldl' disjAdd xss yss
192 xss \/ DNF yss = S.foldl' disjAdd xss yss
194 DNF xss /\ DNF yss = F.foldl' disjAdd bottom $
193 DNF xss /\ DNF yss = F.foldl' disjAdd bottom $
195− liftA2 M.union (S.toList xss) (S.toList yss)
194+ liftA2 S.union (S.toList xss) (S.toList yss)
197−pattern BottomFormula :: JsonFormula r t
196+pattern BottomFormula :: JsonFormula t
198pattern BottomFormula <- DNF (S.null -> True)
197pattern BottomFormula <- DNF (S.null -> True)
199 where BottomFormula = DNF S.empty
198 where BottomFormula = DNF S.empty
@@ -203,35 +202,35 @@ isSingleton s
203 | S.size s == 1 = S.lookupMin s
202 | S.size s == 1 = S.lookupMin s
204 | otherwise = Nothing
203 | otherwise = Nothing
206−pattern Conjunct :: [Traced r (Condition t)] -> M.Map (Condition t) (Trace r (Condition t))
205+pattern Conjunct :: [Condition t] -> S.Set (Condition t)
207−pattern Conjunct xs <- (map (uncurry $ flip traced) . M.toList -> xs)
206+pattern Conjunct xs <- (S.toList -> xs)
208− where Conjunct xs = M.fromList $ (extract &&& ask) <$> xs
207+ where Conjunct = S.fromList
209{-# COMPLETE Conjunct #-}
208{-# COMPLETE Conjunct #-}
211−pattern SingleConjunct :: [Traced r (Condition t)] -> JsonFormula r t
210+pattern SingleConjunct :: [Condition t] -> JsonFormula t
212pattern SingleConjunct xs <- DNF (isSingleton -> Just (Conjunct xs))
211pattern SingleConjunct xs <- DNF (isSingleton -> Just (Conjunct xs))
213 where SingleConjunct xs = DNF $ S.singleton $ Conjunct xs
212 where SingleConjunct xs = DNF $ S.singleton $ Conjunct xs
215−pattern TopFormula :: JsonFormula r t
214+pattern TopFormula :: JsonFormula t
216−pattern TopFormula <- DNF (isSingleton -> Just (M.null -> True))
215+pattern TopFormula <- DNF (isSingleton -> Just (S.null -> True))
217− where TopFormula = DNF $ S.singleton M.empty
216+ where TopFormula = DNF $ S.singleton S.empty
219−instance BoundedJoinSemiLattice (JsonFormula r t) where
218+instance BoundedJoinSemiLattice (JsonFormula t) where
220 bottom = BottomFormula
219 bottom = BottomFormula
222−instance BoundedMeetSemiLattice (JsonFormula r t) where
221+instance BoundedMeetSemiLattice (JsonFormula t) where
223 top = TopFormula
222 top = TopFormula
225foldLattice
224foldLattice
226 :: BoundedLattice l
225 :: BoundedLattice l
227− => (Traced r (Condition t) -> l)
226+ => (Condition t -> l)
228− -> JsonFormula r t
227+ -> JsonFormula t
230foldLattice f (DNF xss) = S.foldl' (\z w ->
229foldLattice f (DNF xss) = S.foldl' (\z w ->
231− z \/ M.foldlWithKey' (\x y t -> x /\ f (traced t y)) top w) bottom xss
230+ z \/ S.foldl' (\x y -> x /\ f y) top w) bottom xss
233−satisfiesFormula :: TypedValue t -> JsonFormula r t -> Bool
232+satisfiesFormula :: TypedValue t -> JsonFormula t -> Bool
234−satisfiesFormula val = foldLattice (satisfiesTyped val . extract)
233+satisfiesFormula val = foldLattice (satisfiesTyped val)
236data ForeachType (f :: JsonType -> Type) = ForeachType
235data ForeachType (f :: JsonType -> Type) = ForeachType
237 { forNull :: f 'Null
236 { forNull :: f 'Null
@@ -242,7 +241,7 @@ data ForeachType (f :: JsonType -> Type) = ForeachType
242 , forObject :: f 'Object
241 , forObject :: f 'Object
245−satisfies :: A.Value -> ForeachType (JsonFormula r) -> Bool
244+satisfies :: A.Value -> ForeachType JsonFormula -> Bool
246satisfies val p = case val of
245satisfies val p = case val of
247 A.Null -> satisfiesFormula TNull $ forNull p
246 A.Null -> satisfiesFormula TNull $ forNull p
248 A.Bool b -> satisfiesFormula (TBool b) $ forBoolean p
247 A.Bool b -> satisfiesFormula (TBool b) $ forBoolean p
@@ -257,27 +256,27 @@ deriving stock instance (forall x. Typeable x => Show (f x)) => Show (ForeachTyp
259 :: Monoid m
258 :: Monoid m
260− => (forall x. Typeable x => (ForeachType f -> f x) -> m)
259+ => (forall x. Typeable x => JsonType -> (ForeachType f -> f x) -> m)
262foldType k =
261foldType k =
263− k forNull <>
262+ k Null forNull <>
264− k forBoolean <>
263+ k Boolean forBoolean <>
265− k forNumber <>
264+ k Number forNumber <>
266− k forString <>
265+ k String forString <>
267− k forArray <>
266+ k Array forArray <>
268− k forObject
267+ k Object forObject
271 :: Applicative m
270 :: Applicative m
272− => (forall x. Typeable x => (ForeachType f -> f x) -> m ())
271+ => (forall x. Typeable x => JsonType -> (ForeachType f -> f x) -> m ())
274forType_ k = do
273forType_ k = do
275− k forNull
274+ k Null forNull
276− k forBoolean
275+ k Boolean forBoolean
277− k forNumber
276+ k Number forNumber
278− k forString
277+ k String forString
279− k forArray
278+ k Array forArray
280− k forObject
279+ k Object forObject
283instance (forall x. Lattice (f x)) => Lattice (ForeachType f) where
282instance (forall x. Lattice (f x)) => Lattice (ForeachType f) where
@@ -320,6 +319,7 @@ instance (forall x. BoundedMeetSemiLattice (f x))
320 , forObject = top
319 , forObject = top
323instance Typeable t => Steppable Schema (Condition t) where
323instance Typeable t => Steppable Schema (Condition t) where
324 data Step Schema (Condition t)
324 data Step Schema (Condition t)
325 = EnumField
325 = EnumField
@@ -340,6 +340,11 @@ instance Typeable t => Steppable Schema (Condition t) where
340 | NullableField
340 | NullableField
341 | IntegerType -- type=integer
341 | IntegerType -- type=integer
342 deriving (Eq, Ord, Show)
342 deriving (Eq, Ord, Show)
345+instance Behavable 'SchemaLevel 'SchemaLevel where
346+ data Behave 'SchemaLevel 'SchemaLevel
347+ deriving (Eq, Ord, Show)
344instance Steppable Schema (Referenced Schema) where
349instance Steppable Schema (Referenced Schema) where
345 data Step Schema (Referenced Schema)
350 data Step Schema (Referenced Schema)
@@ -352,44 +357,42 @@ instance Steppable Schema (Referenced Schema) where
352 | PropertiesStep Text
357 | PropertiesStep Text
353 deriving (Eq, Ord, Show)
358 deriving (Eq, Ord, Show)
355−type ProcessM = ReaderT (Definitions Schema) (Writer (T.TracePrefixTree SubtreeCheckIssue OpenApi))
360+type ProcessM = ReaderT (Traced (Definitions Schema)) (Writer (P.PathsPrefixTree Behave AnIssue 'SchemaLevel))
357−warn
362+warn :: Issue 'SchemaLevel -> ProcessM ()
358− :: (Subtree t, ComonadEnv (Trace OpenApi t) w)
359− => w x -> CheckIssue t -> ProcessM ()
360−warn t issue = tell $ T.singleton $ AnItem (ask t) $ SubtreeCheckIssue issue
363+warn issue = tell $ P.singleton $ AnItem Root $ AnIssue issue
362processRefSchema
365processRefSchema
363− :: Traced OpenApi (Referenced Schema)
366+ :: Traced (Referenced Schema)
364− -> ProcessM (ForeachType (JsonFormula OpenApi))
367+ -> ProcessM (ForeachType JsonFormula)
365processRefSchema x = do
368processRefSchema x = do
366 defs <- R.ask
369 defs <- R.ask
367 processSchema $ dereference defs x
370 processSchema $ dereference defs x
369−tracedAllOf :: Traced r Schema -> Maybe [Traced r (Referenced Schema)]
372+tracedAllOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
370tracedAllOf sch = _schemaAllOf (extract sch) <&> \xs ->
373tracedAllOf sch = _schemaAllOf (extract sch) <&> \xs ->
371 [ traced (ask sch >>> step (AllOfStep i)) x | (i, x) <- zip [0..] xs ]
374 [ traced (ask sch >>> step (AllOfStep i)) x | (i, x) <- zip [0..] xs ]
373−tracedAnyOf :: Traced r Schema -> Maybe [Traced r (Referenced Schema)]
376+tracedAnyOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
374tracedAnyOf sch = _schemaAnyOf (extract sch) <&> \xs ->
377tracedAnyOf sch = _schemaAnyOf (extract sch) <&> \xs ->
375 [ traced (ask sch >>> step (AnyOfStep i)) x | (i, x) <- zip [0..] xs ]
378 [ traced (ask sch >>> step (AnyOfStep i)) x | (i, x) <- zip [0..] xs ]
377−tracedOneOf :: Traced r Schema -> Maybe [Traced r (Referenced Schema)]
380+tracedOneOf :: Traced Schema -> Maybe [Traced (Referenced Schema)]
378tracedOneOf sch = _schemaOneOf (extract sch) <&> \xs ->
381tracedOneOf sch = _schemaOneOf (extract sch) <&> \xs ->
379 [ traced (ask sch >>> step (OneOfStep i)) x | (i, x) <- zip [0..] xs ]
382 [ traced (ask sch >>> step (OneOfStep i)) x | (i, x) <- zip [0..] xs ]
381−tracedItems :: Traced r Schema -> Maybe (Either (Traced r (Referenced Schema)) [Traced r (Referenced Schema)])
384+tracedItems :: Traced Schema -> Maybe (Either (Traced (Referenced Schema)) [Traced (Referenced Schema)])
382tracedItems sch = _schemaItems (extract sch) <&> \case
385tracedItems sch = _schemaItems (extract sch) <&> \case
383 OpenApiItemsObject x -> Left $ traced (ask sch >>> step ItemsObjectStep) x
386 OpenApiItemsObject x -> Left $ traced (ask sch >>> step ItemsObjectStep) x
384 OpenApiItemsArray xs -> Right
387 OpenApiItemsArray xs -> Right
385 [ traced (ask sch >>> step (ItemsArrayStep i)) x | (i, x) <- zip [0..] xs ]
388 [ traced (ask sch >>> step (ItemsArrayStep i)) x | (i, x) <- zip [0..] xs ]
387−tracedAdditionalProperties :: Traced r Schema -> Maybe (Either Bool (Traced r (Referenced Schema)))
390+tracedAdditionalProperties :: Traced Schema -> Maybe (Either Bool (Traced (Referenced Schema)))
388tracedAdditionalProperties sch = _schemaAdditionalProperties (extract sch) <&> \case
391tracedAdditionalProperties sch = _schemaAdditionalProperties (extract sch) <&> \case
389 AdditionalPropertiesAllowed b -> Left b
392 AdditionalPropertiesAllowed b -> Left b
390 AdditionalPropertiesSchema x -> Right $ traced (ask sch >>> step AdditionalPropertiesStep) x
393 AdditionalPropertiesSchema x -> Right $ traced (ask sch >>> step AdditionalPropertiesStep) x
392−tracedProperties :: Traced r Schema -> IOHM.InsOrdHashMap Text (Traced r (Referenced Schema))
395+tracedProperties :: Traced Schema -> IOHM.InsOrdHashMap Text (Traced (Referenced Schema))
393tracedProperties sch = IOHM.mapWithKey (\k -> traced (ask sch >>> step (PropertiesStep k)))
396tracedProperties sch = IOHM.mapWithKey (\k -> traced (ask sch >>> step (PropertiesStep k)))
394 $ _schemaProperties $ extract sch
397 $ _schemaProperties $ extract sch
@@ -397,35 +400,35 @@ tracedProperties sch = IOHM.mapWithKey (\k -> traced (ask sch >>> step (Properti
397-- for every possible type of a JSON value. The conditions are independent, and
400-- for every possible type of a JSON value. The conditions are independent, and
398-- are thus checked independently.
401-- are thus checked independently.
399processSchema
402processSchema
400− :: Traced OpenApi Schema
403+ :: Traced Schema
401− -> ProcessM (ForeachType (JsonFormula OpenApi))
404+ -> ProcessM (ForeachType JsonFormula)
402processSchema sch@(extract -> Schema{..}) = do
405processSchema sch@(extract -> Schema{..}) = do
404− singletonFormula :: Typeable t => Step Schema (Condition t) -> Condition t -> JsonFormula OpenApi t
407+ singletonFormula :: Condition t -> JsonFormula t
405− singletonFormula t f = SingleConjunct [traced (ask sch >>> step t) f]
408+ singletonFormula f = SingleConjunct [f]
407 allClauses <- case tracedAllOf sch of
410 allClauses <- case tracedAllOf sch of
408 Nothing -> pure []
411 Nothing -> pure []
409− Just [] -> [] <$ warn sch (InvalidSchema "no items in allOf")
412+ Just [] -> [] <$ warn (InvalidSchema "no items in allOf")
410 Just xs -> mapM processRefSchema xs
413 Just xs -> mapM processRefSchema xs
412 anyClause <- case tracedAnyOf sch of
415 anyClause <- case tracedAnyOf sch of
413 Nothing -> pure top
416 Nothing -> pure top
414− Just [] -> bottom <$ warn sch (InvalidSchema "no items in anyOf")
417+ Just [] -> bottom <$ warn (InvalidSchema "no items in anyOf")
415 Just xs -> joins <$> mapM processRefSchema xs
418 Just xs -> joins <$> mapM processRefSchema xs
417 oneClause <- case tracedOneOf sch of
420 oneClause <- case tracedOneOf sch of
418 Nothing -> pure top
421 Nothing -> pure top
419− Just [] -> bottom <$ warn sch (InvalidSchema "no items in oneOf")
422+ Just [] -> bottom <$ warn (InvalidSchema "no items in oneOf")
420 Just xs -> do
423 Just xs -> do
421 checkOneOfDisjoint xs >>= \case
424 checkOneOfDisjoint xs >>= \case
422 True -> pure ()
425 True -> pure ()
423− False -> warn sch (NotSupported "Could not determine that oneOf branches are disjoint")
426+ False -> warn (NotSupported "Could not determine that oneOf branches are disjoint")
424 joins <$> mapM processRefSchema xs
427 joins <$> mapM processRefSchema xs
426 case _schemaNot of
429 case _schemaNot of
427 Nothing -> pure ()
430 Nothing -> pure ()
428− Just _ -> warn sch (NotSupported "not clause is unsupported")
431+ Just _ -> warn (NotSupported "not clause is unsupported")
431 typeClause = case _schemaType of
434 typeClause = case _schemaType of
@@ -437,7 +440,7 @@ processSchema sch@(extract -> Schema{..}) = do
437 Just OpenApiNumber -> bottom
440 Just OpenApiNumber -> bottom
438 { forBoolean = top }
441 { forBoolean = top }
439 Just OpenApiInteger -> bottom
442 Just OpenApiInteger -> bottom
440− { forNumber = singletonFormula IntegerType $ MultipleOf 1 }
443+ { forNumber = singletonFormula $ MultipleOf 1 }
441 Just OpenApiString -> bottom
444 Just OpenApiString -> bottom
442 { forString = top }
445 { forString = top }
443 Just OpenApiArray -> bottom
446 Just OpenApiArray -> bottom
@@ -447,27 +450,27 @@ processSchema sch@(extract -> Schema{..}) = do
449 valueEnum A.Null = bottom
452 valueEnum A.Null = bottom
450− { forNull = singletonFormula EnumField $ Exactly TNull }
453+ { forNull = singletonFormula $ Exactly TNull }
451 valueEnum (A.Bool b) = bottom
454 valueEnum (A.Bool b) = bottom
452− { forBoolean = singletonFormula EnumField $ Exactly $ TBool b }
455+ { forBoolean = singletonFormula $ Exactly $ TBool b }
453 valueEnum (A.Number n) = bottom
456 valueEnum (A.Number n) = bottom
454− { forNumber = singletonFormula EnumField $ Exactly $ TNumber n }
457+ { forNumber = singletonFormula $ Exactly $ TNumber n }
455 valueEnum (A.String s) = bottom
458 valueEnum (A.String s) = bottom
456− { forString = singletonFormula EnumField $ Exactly $ TString s }
459+ { forString = singletonFormula $ Exactly $ TString s }
457 valueEnum (A.Array a) = bottom
460 valueEnum (A.Array a) = bottom
458− { forArray = singletonFormula EnumField $ Exactly $ TArray a }
461+ { forArray = singletonFormula $ Exactly $ TArray a }
459 valueEnum (A.Object o) = bottom
462 valueEnum (A.Object o) = bottom
460− { forObject = singletonFormula EnumField $ Exactly $ TObject o }
463+ { forObject = singletonFormula $ Exactly $ TObject o }
461 enumClause <- case _schemaEnum of
464 enumClause <- case _schemaEnum of
462 Nothing -> pure top
465 Nothing -> pure top
463− Just [] -> bottom <$ warn sch (InvalidSchema "no items in enum")
466+ Just [] -> bottom <$ warn (InvalidSchema "no items in enum")
464 Just xs -> pure $ joins (valueEnum <$> xs)
467 Just xs -> pure $ joins (valueEnum <$> xs)
467 maximumClause = case _schemaMaximum of
470 maximumClause = case _schemaMaximum of
468 Nothing -> top
471 Nothing -> top
469 Just n -> top
472 Just n -> top
470− { forNumber = singletonFormula MaximumFields $ Maximum $
473+ { forNumber = singletonFormula $ Maximum $
471 case _schemaExclusiveMaximum of
474 case _schemaExclusiveMaximum of
472 Just True -> Exclusive n
475 Just True -> Exclusive n
473 _ -> Inclusive n }
476 _ -> Inclusive n }
@@ -475,7 +478,7 @@ processSchema sch@(extract -> Schema{..}) = do
475 minimumClause = case _schemaMinimum of
478 minimumClause = case _schemaMinimum of
476 Nothing -> top
479 Nothing -> top
477 Just n -> top
480 Just n -> top
478− { forNumber = singletonFormula MinimumFields $ Minimum $ Down $
481+ { forNumber = singletonFormula $ Minimum $ Down $
479 case _schemaExclusiveMinimum of
482 case _schemaExclusiveMinimum of
480 Just True -> Exclusive $ Down n
483 Just True -> Exclusive $ Down n
481 _ -> Inclusive $ Down n }
484 _ -> Inclusive $ Down n }
@@ -483,53 +486,53 @@ processSchema sch@(extract -> Schema{..}) = do
483 multipleOfClause = case _schemaMultipleOf of
486 multipleOfClause = case _schemaMultipleOf of
484 Nothing -> top
487 Nothing -> top
485 Just n -> top
488 Just n -> top
486− { forNumber = singletonFormula MultipleOfField $ MultipleOf n }
489+ { forNumber = singletonFormula $ MultipleOf n }
488 formatClause <- case _schemaFormat of
491 formatClause <- case _schemaFormat of
489 Nothing -> pure top
492 Nothing -> pure top
490 Just f | f `elem` ["int32", "int64", "float", "double"] -> pure top
493 Just f | f `elem` ["int32", "int64", "float", "double"] -> pure top
491− { forNumber = singletonFormula FormatField $ NumberFormat f }
494+ { forNumber = singletonFormula $ NumberFormat f }
492 Just f | f `elem` ["byte", "binary", "date", "date-time", "password"] -> pure top
495 Just f | f `elem` ["byte", "binary", "date", "date-time", "password"] -> pure top
493− { forString = singletonFormula FormatField $ StringFormat f }
496+ { forString = singletonFormula $ StringFormat f }
494− Just f -> top <$ warn sch (NotSupported $ "Unknown format: " <> f)
497+ Just f -> top <$ warn (NotSupported $ "Unknown format: " <> f)
497 maxLengthClause = case _schemaMaxLength of
500 maxLengthClause = case _schemaMaxLength of
498 Nothing -> top
501 Nothing -> top
499 Just n -> top
502 Just n -> top
500− { forString = singletonFormula MaxLengthField $ MaxLength n }
503+ { forString = singletonFormula $ MaxLength n }
502 minLengthClause = case _schemaMinLength of
505 minLengthClause = case _schemaMinLength of
503 Nothing -> top
506 Nothing -> top
504 Just n -> top
507 Just n -> top
505− { forString = singletonFormula MinLengthField $ MinLength n }
508+ { forString = singletonFormula $ MinLength n }
507 patternClause = case _schemaPattern of
510 patternClause = case _schemaPattern of
508 Nothing -> top
511 Nothing -> top
509 Just p -> top
512 Just p -> top
510− { forString = singletonFormula PatternField $ Pattern p }
513+ { forString = singletonFormula $ Pattern p }
512 itemsClause <- case tracedItems sch of
515 itemsClause <- case tracedItems sch of
513 Nothing -> pure top
516 Nothing -> pure top
514 Just (Left rs) -> do
517 Just (Left rs) -> do
515 f <- processRefSchema rs
518 f <- processRefSchema rs
516− pure top { forArray = singletonFormula ItemsField $ Items f rs }
519+ pure top { forArray = singletonFormula $ Items f rs }
517− Just (Right _) -> top <$ warn sch (NotSupported "array in items is not supported")
520+ Just (Right _) -> top <$ warn (NotSupported "array in items is not supported")
520 maxItemsClause = case _schemaMaxItems of
523 maxItemsClause = case _schemaMaxItems of
521 Nothing -> top
524 Nothing -> top
522 Just n -> top
525 Just n -> top
523− { forArray = singletonFormula MaxItemsField $ MaxItems n }
526+ { forArray = singletonFormula $ MaxItems n }
525 minItemsClause = case _schemaMinItems of
528 minItemsClause = case _schemaMinItems of
526 Nothing -> top
529 Nothing -> top
527 Just n -> top
530 Just n -> top
528− { forArray = singletonFormula MinItemsField $ MinItems n }
531+ { forArray = singletonFormula $ MinItems n }
530 uniqueItemsClause = case _schemaUniqueItems of
533 uniqueItemsClause = case _schemaUniqueItems of
531 Just True -> top
534 Just True -> top
532− { forArray = singletonFormula UniqueItemsField UniqueItems }
535+ { forArray = singletonFormula UniqueItems }
535 (addProps, addPropSchema) <- case tracedAdditionalProperties sch of
538 (addProps, addPropSchema) <- case tracedAdditionalProperties sch of
@@ -546,10 +549,10 @@ processSchema sch@(extract -> Schema{..}) = do
546 in pure (addProps, fromMaybe fakeSchema addPropSchema)
549 in pure (addProps, fromMaybe fakeSchema addPropSchema)
547 pure (k, Property (k `elem` _schemaRequired) f psch)
550 pure (k, Property (k `elem` _schemaRequired) f psch)
549− allBottom f = getAll $ foldType $ \ty -> case ty f of
552+ allBottom f = getAll $ foldType $ \_ ty -> case ty f of
550 BottomFormula -> All True
553 BottomFormula -> All True
551 _ -> All False
554 _ -> All False
552− allTop f = getAll $ foldType $ \ty -> case ty f of
555+ allTop f = getAll $ foldType $ \_ ty -> case ty f of
553 TopFormula -> All True
556 TopFormula -> All True
554 _ -> All False
557 _ -> All False
555 -- remove optional fields whose schemata match that of additional props
558 -- remove optional fields whose schemata match that of additional props
@@ -561,21 +564,21 @@ processSchema sch@(extract -> Schema{..}) = do
561 = top -- if all fields are optional and have trivial schemata
564 = top -- if all fields are optional and have trivial schemata
562 | otherwise
565 | otherwise
564− { forObject = singletonFormula PropertiesFields $ Properties propMap addProps addPropSchema }
567+ { forObject = singletonFormula $ Properties propMap addProps addPropSchema }
566 maxPropertiesClause = case _schemaMaxProperties of
569 maxPropertiesClause = case _schemaMaxProperties of
567 Nothing -> top
570 Nothing -> top
568 Just n -> top
571 Just n -> top
569− { forObject = singletonFormula MaxPropertiesField $ MaxProperties n }
572+ { forObject = singletonFormula $ MaxProperties n }
571 minPropertiesClause = case _schemaMinProperties of
574 minPropertiesClause = case _schemaMinProperties of
572 Nothing -> top
575 Nothing -> top
573 Just n -> top
576 Just n -> top
574− { forObject = singletonFormula MinPropertiesField $ MinProperties n }
577+ { forObject = singletonFormula $ MinProperties n }
576 nullableClause
579 nullableClause
577 | Just True <- _schemaNullable = bottom
580 | Just True <- _schemaNullable = bottom
578− { forNull = singletonFormula NullableField $ Exactly TNull }
581+ { forNull = singletonFormula $ Exactly TNull }
579 | otherwise = bottom
582 | otherwise = bottom
581 pure $ nullableClause \/ meets (allClauses <>
584 pure $ nullableClause \/ meets (allClauses <>
@@ -585,24 +588,24 @@ processSchema sch@(extract -> Schema{..}) = do
585 , uniqueItemsClause, propertiesClause, maxPropertiesClause, minPropertiesClause])
588 , uniqueItemsClause, propertiesClause, maxPropertiesClause, minPropertiesClause])
586{- TODO: ReadOnly/WriteOnly -}
589{- TODO: ReadOnly/WriteOnly -}
588−checkOneOfDisjoint :: [Traced OpenApi (Referenced Schema)] -> ProcessM Bool
591+checkOneOfDisjoint :: [Traced (Referenced Schema)] -> ProcessM Bool
589checkOneOfDisjoint = const $ pure True -- TODO
592checkOneOfDisjoint = const $ pure True -- TODO
591schemaToFormula
594schemaToFormula
592− :: Definitions Schema
595+ :: Traced (Definitions Schema)
593− -> Traced OpenApi Schema
596+ -> Traced Schema
594− -> (ForeachType (JsonFormula OpenApi), T.TracePrefixTree SubtreeCheckIssue OpenApi)
597+ -> (ForeachType JsonFormula, P.PathsPrefixTree Behave AnIssue 'SchemaLevel)
595schemaToFormula defs rs = runWriter . (`runReaderT` defs) $ processSchema rs
598schemaToFormula defs rs = runWriter . (`runReaderT` defs) $ processSchema rs
597checkFormulas
600checkFormulas
598 :: HasAll (CheckEnv Schema) xs
601 :: HasAll (CheckEnv Schema) xs
599 => HList xs
602 => HList xs
600− -> Trace OpenApi Schema
603+ -> Behavior 'SchemaLevel
601− -> ProdCons (ForeachType (JsonFormula OpenApi), T.TracePrefixTree SubtreeCheckIssue OpenApi)
604+ -> ProdCons (ForeachType JsonFormula, P.PathsPrefixTree Behave AnIssue 'SchemaLevel)
602 -> CompatFormula ()
605 -> CompatFormula ()
603−checkFormulas env tr (ProdCons (fp, ep) (fc, ec)) =
606+checkFormulas env beh (ProdCons (fp, ep) (fc, ec)) =
604− case T.toList ep ++ T.toList ec of
607+ case P.toList ep ++ P.toList ec of
605− issues@(_:_) -> F.for_ issues $ \(AnItem t (SubtreeCheckIssue e)) -> issueAtTrace t e
608+ issues@(_:_) -> F.for_ issues $ \(AnItem t (AnIssue e)) -> issueAt (beh >>> t) e
607 -- We have the following isomorphisms:
610 -- We have the following isomorphisms:
608 -- (A ⊂ X ∪ Y) = (A ⊂ X) \/ (A ⊂ Y)
611 -- (A ⊂ X ∪ Y) = (A ⊂ X) \/ (A ⊂ Y)
@@ -631,120 +634,122 @@ checkFormulas env tr (ProdCons (fp, ep) (fc, ec)) =
631 -- (⋃_i ⋂_j A[i,j]) ⊂ ∅ = /\_i (⋂_j A[i,j]) ⊂ ∅
634 -- (⋃_i ⋂_j A[i,j]) ⊂ ∅ = /\_i (⋂_j A[i,j]) ⊂ ∅
632 -- where we again delegate (⋂_j A[j]) ⊂ ∅ to a heuristic, though here the
635 -- where we again delegate (⋂_j A[j]) ⊂ ∅ to a heuristic, though here the
633 -- shortcut of \/_j A[j] ⊂ ∅ hardly helps.
636 -- shortcut of \/_j A[j] ⊂ ∅ hardly helps.
634− forType_ $ \ty ->
637+ forType_ $ \tyName ty -> do
638+ let beh' = beh >>> step (OfType tyName)
635 case (ty fp, ty fc) of
639 case (ty fp, ty fc) of
636− (DNF pss, BottomFormula) -> F.for_ pss $ \(Conjunct ps) -> checkContradiction tr ps
640+ (DNF pss, BottomFormula) -> F.for_ pss $ \(Conjunct ps) -> checkContradiction beh' ps
637 (DNF pss, SingleConjunct cs) -> F.for_ pss $ \(Conjunct ps) -> do
641 (DNF pss, SingleConjunct cs) -> F.for_ pss $ \(Conjunct ps) -> do
638− F.for_ cs $ checkImplication env ps -- avoid disjuntion if there's only one conjunct
642+ F.for_ cs $ checkImplication env beh' ps -- avoid disjuntion if there's only one conjunct
639 (DNF pss, DNF css) -> F.for_ pss $ \(Conjunct ps) -> do
643 (DNF pss, DNF css) -> F.for_ pss $ \(Conjunct ps) -> do
640− anyOfM tr (NoMatchingCondition $ SomeCondition <$> ps)
644+ anyOfAt beh' (NoMatchingCondition $ SomeCondition <$> ps)
641− [F.for_ cs $ checkImplication env ps | Conjunct cs <- S.toList css]
645+ [F.for_ cs $ checkImplication env beh' ps | Conjunct cs <- S.toList css]
643checkContradiction
647checkContradiction
644− :: Trace OpenApi Schema
648+ :: Behavior 'TypedSchemaLevel
645− -> [Traced OpenApi (Condition t)]
649+ -> [Condition t]
646 -> CompatFormula ()
650 -> CompatFormula ()
647−checkContradiction tr _ = issueAtTrace tr NoContradiction -- TODO
651+checkContradiction beh _ = issueAt beh NoContradiction -- TODO
649checkImplication
653checkImplication
650− :: (HasAll (CheckEnv Schema) xs, Typeable t)
654+ :: (HasAll (CheckEnv Schema) xs)
651 => HList xs
655 => HList xs
656+ -> Behavior 'TypedSchemaLevel
652− -> [Traced OpenApi (Condition t)]
657+ -> [Condition t]
653− -> Traced OpenApi (Condition t)
658+ -> Condition t
654 -> CompatFormula ()
659 -> CompatFormula ()
655−checkImplication env prods cons = case findExactly prods of
660+checkImplication env beh prods cons = case findExactly prods of
657− | all (satisfiesTyped e) (extract <$> prods) ->
662+ | all (satisfiesTyped e) prods ->
658− if satisfiesTyped e $ extract cons then pure ()
663+ if satisfiesTyped e cons then pure ()
659− else issueAt cons (EnumDoesntSatisfy e)
664+ else issueAt beh (EnumDoesntSatisfy $ untypeValue e)
660 | otherwise -> pure () -- vacuously true
665 | otherwise -> pure () -- vacuously true
661− Nothing -> case extract cons of
666+ Nothing -> case cons of
662 -- the above code didn't catch it, so there's no Exactly condition on the lhs
667 -- the above code didn't catch it, so there's no Exactly condition on the lhs
663− Exactly e -> issueAt cons (NoMatchingEnum e)
668+ Exactly e -> issueAt beh (NoMatchingEnum $ untypeValue e)
664 Maximum m -> case findRelevant min (\case Maximum m' -> Just m'; _ -> Nothing) prods of
669 Maximum m -> case findRelevant min (\case Maximum m' -> Just m'; _ -> Nothing) prods of
665 Just m' -> if m' <= m then pure ()
670 Just m' -> if m' <= m then pure ()
666− else issueAt cons (MatchingMaximumWeak m m')
671+ else issueAt beh (MatchingMaximumWeak m m')
667− Nothing -> issueAt cons (NoMatchingMaximum m)
672+ Nothing -> issueAt beh (NoMatchingMaximum m)
668 Minimum m -> case findRelevant max (\case Minimum m' -> Just m'; _ -> Nothing) prods of
673 Minimum m -> case findRelevant max (\case Minimum m' -> Just m'; _ -> Nothing) prods of
669 Just m' -> if m' >= m then pure ()
674 Just m' -> if m' >= m then pure ()
670− else issueAt cons (MatchingMinimumWeak (coerce m) (coerce m'))
675+ else issueAt beh (MatchingMinimumWeak (coerce m) (coerce m'))
671− Nothing -> issueAt cons (NoMatchingMinimum (coerce m))
676+ Nothing -> issueAt beh (NoMatchingMinimum (coerce m))
672 MultipleOf m -> case findRelevant lcmScientific (\case MultipleOf m' -> Just m'; _ -> Nothing) prods of
677 MultipleOf m -> case findRelevant lcmScientific (\case MultipleOf m' -> Just m'; _ -> Nothing) prods of
673 Just m' -> if lcmScientific m m' == m' then pure ()
678 Just m' -> if lcmScientific m m' == m' then pure ()
674− else issueAt cons (MatchingMultipleOfWeak m m')
679+ else issueAt beh (MatchingMultipleOfWeak m m')
675− Nothing -> issueAt cons (NoMatchingMultipleOf m)
680+ Nothing -> issueAt beh (NoMatchingMultipleOf m)
676− NumberFormat f -> if any (\case NumberFormat f' -> f == f'; _ -> False) $ extract <$> prods
681+ NumberFormat f -> if any (\case NumberFormat f' -> f == f'; _ -> False) prods
677− then pure () else issueAt cons (NoMatchingFormat f)
682+ then pure () else issueAt beh (NoMatchingFormat f)
678 MaxLength m -> case findRelevant min (\case MaxLength m' -> Just m'; _ -> Nothing) prods of
683 MaxLength m -> case findRelevant min (\case MaxLength m' -> Just m'; _ -> Nothing) prods of
679 Just m' -> if m' <= m then pure ()
684 Just m' -> if m' <= m then pure ()
680− else issueAt cons (MatchingMaxLengthWeak m m')
685+ else issueAt beh (MatchingMaxLengthWeak m m')
681− Nothing -> issueAt cons (NoMatchingMaxLength m)
686+ Nothing -> issueAt beh (NoMatchingMaxLength m)
682 MinLength m -> case findRelevant max (\case MinLength m' -> Just m'; _ -> Nothing) prods of
687 MinLength m -> case findRelevant max (\case MinLength m' -> Just m'; _ -> Nothing) prods of
683 Just m' -> if m' >= m then pure ()
688 Just m' -> if m' >= m then pure ()
684− else issueAt cons (MatchingMinLengthWeak m m')
689+ else issueAt beh (MatchingMinLengthWeak m m')
685− Nothing -> issueAt cons (NoMatchingMinLength m)
690+ Nothing -> issueAt beh (NoMatchingMinLength m)
686− Pattern p -> if any (\case Pattern p' -> p == p'; _ -> False) $ extract <$> prods
691+ Pattern p -> if any (\case Pattern p' -> p == p'; _ -> False) prods
687− then pure () else issueAt cons (NoMatchingPattern p)
692+ then pure () else issueAt beh (NoMatchingPattern p) -- TODO: regex comparison
688− StringFormat f -> if any (\case StringFormat f' -> f == f'; _ -> False) $ extract <$> prods
693+ StringFormat f -> if any (\case StringFormat f' -> f == f'; _ -> False) prods
689− then pure () else issueAt cons (NoMatchingFormat f)
694+ then pure () else issueAt beh (NoMatchingFormat f)
690 Items _ cons' -> case findRelevant (<>) (\case Items _ rs -> Just (rs NE.:| []); _ -> Nothing) prods of
695 Items _ cons' -> case findRelevant (<>) (\case Items _ rs -> Just (rs NE.:| []); _ -> Nothing) prods of
691− Just (rs NE.:| []) -> checkCompatibility env $ ProdCons rs cons'
696+ Just (rs NE.:| []) -> checkCompatibility env (beh >>> step InItems) $ ProdCons rs cons'
692 Just rs -> do
697 Just rs -> do
693 let sch = Inline mempty { _schemaAllOf = Just . NE.toList $ extract <$> rs }
698 let sch = Inline mempty { _schemaAllOf = Just . NE.toList $ extract <$> rs }
694− checkCompatibility env $ ProdCons (traced (ask $ NE.head rs) sch) cons' -- TODO: bad trace
699+ checkCompatibility env (beh >>> step InItems) $ ProdCons (traced (ask $ NE.head rs) sch) cons' -- TODO: bad trace
695− Nothing -> issueAt cons NoMatchingItems
700+ Nothing -> issueAt beh NoMatchingItems
696 MaxItems m -> case findRelevant min (\case MaxItems m' -> Just m'; _ -> Nothing) prods of
701 MaxItems m -> case findRelevant min (\case MaxItems m' -> Just m'; _ -> Nothing) prods of
697 Just m' -> if m' <= m then pure ()
702 Just m' -> if m' <= m then pure ()
698− else issueAt cons (MatchingMaxItemsWeak m m')
703+ else issueAt beh (MatchingMaxItemsWeak m m')
699− Nothing -> issueAt cons (NoMatchingMaxItems m)
704+ Nothing -> issueAt beh (NoMatchingMaxItems m)
700 MinItems m -> case findRelevant max (\case MinItems m' -> Just m'; _ -> Nothing) prods of
705 MinItems m -> case findRelevant max (\case MinItems m' -> Just m'; _ -> Nothing) prods of
701 Just m' -> if m' >= m then pure ()
706 Just m' -> if m' >= m then pure ()
702− else issueAt cons (MatchingMinItemsWeak m m')
707+ else issueAt beh (MatchingMinItemsWeak m m')
703− Nothing -> issueAt cons (NoMatchingMinItems m)
708+ Nothing -> issueAt beh (NoMatchingMinItems m)
704− UniqueItems -> if any (== UniqueItems) $ extract <$> prods then pure ()
709+ UniqueItems -> if any (== UniqueItems) $ prods then pure ()
705− else issueAt cons NoMatchingUniqueItems
710+ else issueAt beh NoMatchingUniqueItems
706 Properties props _ madd -> case findRelevant (<>) (\case Properties props' _ madd' -> Just $ (props', madd') NE.:| []; _ -> Nothing) prods of
711 Properties props _ madd -> case findRelevant (<>) (\case Properties props' _ madd' -> Just $ (props', madd') NE.:| []; _ -> Nothing) prods of
707 Just ((props', madd') NE.:| []) -> do
712 Just ((props', madd') NE.:| []) -> do
708 F.for_ (S.fromList $ M.keys props <> M.keys props') $ \k -> do
713 F.for_ (S.fromList $ M.keys props <> M.keys props') $ \k -> do
709− let go sch sch' = checkCompatibility env (ProdCons sch sch')
714+ let go sch sch' = checkCompatibility env (beh >>> step (InProperty k)) (ProdCons sch sch')
710 case (M.lookup k props', madd', M.lookup k props, madd) of
715 case (M.lookup k props', madd', M.lookup k props, madd) of
711 (Nothing, Nothing, _, _) -> pure () -- vacuously
716 (Nothing, Nothing, _, _) -> pure () -- vacuously
712− (_, _, Nothing, Nothing) -> issueAt cons (UnexpectedProperty k)
717+ (_, _, Nothing, Nothing) -> issueAt beh (UnexpectedProperty k)
713 (Just p', _, Just p, _) -> go (propRefSchema p') (propRefSchema p)
718 (Just p', _, Just p, _) -> go (propRefSchema p') (propRefSchema p)
714 (Nothing, Just add', Just p, _) -> go add' (propRefSchema p)
719 (Nothing, Just add', Just p, _) -> go add' (propRefSchema p)
715 (Just p', _, Nothing, Just add) -> go (propRefSchema p') add
720 (Just p', _, Nothing, Just add) -> go (propRefSchema p') add
716 (Nothing, Just _, Nothing, Just _) -> pure ()
721 (Nothing, Just _, Nothing, Just _) -> pure ()
717 case (maybe False propRequired $ M.lookup k props', maybe False propRequired $ M.lookup k props) of
722 case (maybe False propRequired $ M.lookup k props', maybe False propRequired $ M.lookup k props) of
718− (False, True) -> issueAt cons (PropertyNowRequired k)
723+ (False, True) -> issueAt beh (PropertyNowRequired k)
719 _ -> pure ()
724 _ -> pure ()
721 case (madd', madd) of
726 case (madd', madd) of
722 (Nothing, _) -> pure () -- vacuously
727 (Nothing, _) -> pure () -- vacuously
723− (_, Nothing) -> issueAt cons NoAdditionalProperties
728+ (_, Nothing) -> issueAt beh NoAdditionalProperties
724− (Just add', Just add) -> checkCompatibility env (ProdCons add' add)
729+ (Just add', Just add) -> checkCompatibility env (beh >>> step InAdditionalProperty) (ProdCons add' add)
726− Nothing -> issueAt cons NoMatchingProperties
731+ Nothing -> issueAt beh NoMatchingProperties
727 MaxProperties m -> case findRelevant min (\case MaxProperties m' -> Just m'; _ -> Nothing) prods of
732 MaxProperties m -> case findRelevant min (\case MaxProperties m' -> Just m'; _ -> Nothing) prods of
728 Just m' -> if m' <= m then pure ()
733 Just m' -> if m' <= m then pure ()
729− else issueAt cons (MatchingMaxPropertiesWeak m m')
734+ else issueAt beh (MatchingMaxPropertiesWeak m m')
730− Nothing -> issueAt cons (NoMatchingMaxProperties m)
735+ Nothing -> issueAt beh (NoMatchingMaxProperties m)
731 MinProperties m -> case findRelevant max (\case MinProperties m' -> Just m'; _ -> Nothing) prods of
736 MinProperties m -> case findRelevant max (\case MinProperties m' -> Just m'; _ -> Nothing) prods of
732 Just m' -> if m' >= m then pure ()
737 Just m' -> if m' >= m then pure ()
733− else issueAt cons (MatchingMinPropertiesWeak m m')
738+ else issueAt beh (MatchingMinPropertiesWeak m m')
734− Nothing -> issueAt cons (NoMatchingMinProperties m)
739+ Nothing -> issueAt beh (NoMatchingMinProperties m)
736− findExactly ((extract -> Exactly x):_) = Just x
741+ findExactly (Exactly x:_) = Just x
737 findExactly (_:xs) = findExactly xs
742 findExactly (_:xs) = findExactly xs
738 findExactly [] = Nothing
743 findExactly [] = Nothing
739 findRelevant combine extr
744 findRelevant combine extr
740− = fmap (foldr1 combine) . NE.nonEmpty . mapMaybe (extr . extract)
745+ = fmap (foldr1 combine) . NE.nonEmpty . mapMaybe extr
741 lcmScientific (toRational -> a) (toRational -> b)
746 lcmScientific (toRational -> a) (toRational -> b)
742 = fromRational $ lcm (numerator a) (numerator b) % gcd (denominator a) (denominator b)
747 = fromRational $ lcm (numerator a) (numerator b) % gcd (denominator a) (denominator b)
744−instance Typeable t => Subtree (Condition t) where
749+instance Issuable 'TypedSchemaLevel where
745− data CheckIssue (Condition t)
750+ data Issue 'TypedSchemaLevel
746− = EnumDoesntSatisfy (TypedValue t)
751+ = EnumDoesntSatisfy A.Value
747− | NoMatchingEnum (TypedValue t)
752+ | NoMatchingEnum A.Value
748 | NoMatchingMaximum (Bound Scientific)
753 | NoMatchingMaximum (Bound Scientific)
749 | MatchingMaximumWeak (Bound Scientific) (Bound Scientific)
754 | MatchingMaximumWeak (Bound Scientific) (Bound Scientific)
750 | NoMatchingMinimum (Bound Scientific)
755 | NoMatchingMinimum (Bound Scientific)
@@ -771,29 +776,42 @@ instance Typeable t => Subtree (Condition t) where
771 | MatchingMaxPropertiesWeak Integer Integer
776 | MatchingMaxPropertiesWeak Integer Integer
772 | NoMatchingMinProperties Integer
777 | NoMatchingMinProperties Integer
773 | MatchingMinPropertiesWeak Integer Integer
778 | MatchingMinPropertiesWeak Integer Integer
779+ | NoMatchingCondition [SomeCondition]
774 deriving stock (Eq, Ord, Show)
781 deriving stock (Eq, Ord, Show)
775− type CheckEnv (Condition t) = CheckEnv Schema
782+ issueIsUnsupported _ = False
776− normalizeTrace = undefined
777− checkCompatibility env pc = checkImplication env [producer pc] (consumer pc)
779−instance Subtree Schema where
784+instance Issuable 'SchemaLevel where
780− data CheckIssue Schema
785+ data Issue 'SchemaLevel
781 = NotSupported Text
786 = NotSupported Text
782 | InvalidSchema Text
787 | InvalidSchema Text
783− | NoMatchingCondition [SomeCondition]
785 deriving stock (Eq, Ord, Show)
788 deriving stock (Eq, Ord, Show)
789+ issueIsUnsupported _ = True
791+instance Behavable 'SchemaLevel 'TypedSchemaLevel where
792+ data Behave 'SchemaLevel 'TypedSchemaLevel
794+ deriving stock (Eq, Ord, Show)
796+instance Behavable 'TypedSchemaLevel 'SchemaLevel where
797+ data Behave 'TypedSchemaLevel 'SchemaLevel
800+ | InAdditionalProperty
801+ deriving stock (Eq, Ord, Show)
803+instance Subtree Schema where
804+ type SubtreeLevel Schema = 'SchemaLevel
786− type CheckEnv Schema = '[ProdCons (Definitions Schema)]
805+ type CheckEnv Schema = '[ProdCons (Traced (Definitions Schema))]
787− checkCompatibility env schs = do
806+ checkCompatibility env beh schs = do
788 let defs = getH env
807 let defs = getH env
789− checkFormulas env (ask $ producer schs) $ schemaToFormula <$> defs <*> schs
808+ checkFormulas env beh $ schemaToFormula <$> defs <*> schs
791instance Subtree (Referenced Schema) where
810instance Subtree (Referenced Schema) where
792− data CheckIssue (Referenced Schema)
811+ type SubtreeLevel (Referenced Schema) = 'SchemaLevel
793− deriving stock (Eq, Ord, Show)
794 type CheckEnv (Referenced Schema) = CheckEnv Schema
812 type CheckEnv (Referenced Schema) = CheckEnv Schema
795− checkCompatibility env refs = do
813+ checkCompatibility env beh refs = do
797 defs = getH env
815 defs = getH env
798 schs = dereference <$> defs <*> refs
816 schs = dereference <$> defs <*> refs
799− checkFormulas env (ask $ producer schs) $ schemaToFormula <$> defs <*> schs
817+ checkFormulas env beh $ schemaToFormula <$> defs <*> schs