on master help sign in
Refactor categorizing issues (#111)

* Behaviour -> Behavior (consistency) * Introduce more issue kinds * typo * Add equivalence relations on issues * Refactor issue segregation in the report

commit958a653cfcd0e621bd9d1af261ce64bf978eaa9b authormniip <mniip@users.noreply.github.com> dateFri 23 Jul 2021, 13:57 (5 years ago) parent23bb0f7
64 files changed+364−221
src/OpenAPI/Checker/Behavior.hs+40−2 src/OpenAPI/Checker/PathsPrefixTree.hs+24−2 src/OpenAPI/Checker/Report.hs+58−22 src/OpenAPI/Checker/Report/Jet.hs+1−1 src/OpenAPI/Checker/Run.hs+5−5 src/OpenAPI/Checker/Validate/Header.hs+4−2 src/OpenAPI/Checker/Validate/Link.hs+2−2 src/OpenAPI/Checker/Validate/MediaTypeObject.hs+7−7 src/OpenAPI/Checker/Validate/OAuth2Flows.hs+9−4 src/OpenAPI/Checker/Validate/Operation.hs+17−12 src/OpenAPI/Checker/Validate/Param.hs+4−2 src/OpenAPI/Checker/Validate/RequestBody.hs+3−2 src/OpenAPI/Checker/Validate/Responses.hs+4−3 src/OpenAPI/Checker/Validate/Schema/Issues.hs+83−14 src/OpenAPI/Checker/Validate/Server.hs+4−2 test/golden/common/bad-oneof-unchanged/trace-tree.yaml+2−2 test/golden/common/enum-added/trace-tree.yaml+2−2 test/golden/common/enum-anyof/trace-tree.yaml+2−2 test/golden/common/id/trace-tree.yaml+2−2 test/golden/common/json/recursive/trace-tree.yaml+2−2 test/golden/common/maximum-lowered/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/change/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/required/false/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/required/false/del/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/required/reset/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/required/set/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/required/true/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/parameters/required/true/del/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/requestBody/required/reset/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/requestBody/required/set/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/headers/optional/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/headers/optional/del/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/trace-tree.yaml+2−2 test/golden/common/pathItem/operation/responses/del/trace-tree.yaml+2−2 test/golden/common/property-removed-additional/trace-tree.yaml+2−2 test/golden/common/property-removed/report.md+3−19 test/golden/common/property-removed/trace-tree.yaml+2−2 test/golden/common/property-required/trace-tree.yaml+2−2 test/golden/common/random-example/trace-tree.yaml+2−2 test/golden/common/recursive/trace-tree.yaml+2−2 test/golden/common/security-scheme/trace-tree.yaml+2−2 test/golden/common/servers/trace-tree.yaml+2−2 test/golden/common/tuple-items/heterogeneous-component-mismatch/trace-tree.yaml+2−2 test/golden/common/tuple-items/heterogeneous-length-mismatch/report.md+3−19 test/golden/common/tuple-items/heterogeneous-length-mismatch/trace-tree.yaml+2−2 test/golden/common/tuple-items/homogeneous-component-mismatch/report.md+1−9 test/golden/common/tuple-items/homogeneous-component-mismatch/trace-tree.yaml+2−2 test/golden/common/tuple-items/homogeneous-length-mismatch/trace-tree.yaml+2−2 test/golden/common/tuple-items/homogeneous-vector/trace-tree.yaml+2−2 test/golden/common/type-changing/trace-tree.yaml+2−2 test/golden/common/unguarded-recursive/trace-tree.yaml+2−2 test/golden/common/variant-added/trace-tree.yaml+2−2 test/golden/common/variant-changed/trace-tree.yaml+2−2 test/golden/common/variant-deep-changed/trace-tree.yaml+2−2
src/OpenAPI/Checker/Behavior.hs+40−2
@@ -1,11 +1,15 @@
11module OpenAPI.Checker.Behavior
22 ( BehaviorLevel (..)
33 , Behavable (..)
4+ , IssueKind (..)
45 , Issuable (..)
56 , Orientation (..)
67 , toggleOrientation
78 , Behavior
89 , AnIssue (..)
10+ , withClass
11+ , anIssueKind
12+ , relatedAnIssues
913 )
1014where
1115
@@ -39,10 +43,23 @@ class
3943 Behavable (a :: BehaviorLevel) (b :: BehaviorLevel)
4044 where
4145 data Behave a b
42− describeBehaviour :: Behave a b -> Inlines
46+ describeBehavior :: Behave a b -> Inlines
4347
4448type instance AdditionalQuiverConstraints Behave a b = Behavable a b
4549
50+data IssueKind
51+ = -- | This is certainly an issue, we can demonstrate a "counterexample"
52+ CertainIssue
53+ | -- | Change looks breaking but we don't have a complete comprehension of the problem
54+ ProbablyIssue
55+ | -- | We don't really support this feature at all, outside structural comparison
56+ Unsupported
57+ | -- | This is not an issue in itself, but a clarifying comment providing context for some other issues
58+ Comment
59+ | -- | We detected an issue with one of the input schemata itself
60+ SchemaInvalid
61+ deriving stock (Eq, Ord, Show)
62+
4663class (Typeable l, Ord (Issue l), Show (Issue l)) => Issuable (l :: BehaviorLevel) where
4764 data Issue l :: Type
4865
@@ -58,7 +75,22 @@ class (Typeable l, Ord (Issue l), Show (Issue l)) => Issuable (l :: BehaviorLeve
5875 -- If _producer_ doesn't have something, the element was "added".
5976 describeIssue :: Orientation -> Issue l -> Blocks
6077
61− issueIsUnsupported :: Issue l -> Bool
78+ issueKind :: Issue l -> IssueKind
79+
80+ -- | An equivalence relation designating whether two issues are talking about the aspect of the schema. This is used
81+ -- to remove duplicates from the "reverse" error tree we get when we look for non-breaking changes.
82+ -- Generally if checking X->Y raises issue I, and checking Y->X raises issue J, I and J should be related.
83+ relatedIssues :: Issue l -> Issue l -> Bool
84+ relatedIssues = (==)
85+
86+-- Utility function for 'relatedIssues'. In @withClass eq f@, @f@ attempts to partition inputs into equivalence classes,
87+-- and two items in the same equivalence class are related. If both items aren't assigned to a class by @f@, instead
88+-- @eq@ is used to compare them.
89+withClass :: Eq b => (a -> a -> Bool) -> (a -> Maybe b) -> a -> a -> Bool
90+withClass eq f = \x y -> case (f x, f y) of
91+ (Just fx, Just fy) -> fx == fy
92+ (Nothing, Nothing) -> eq x y
93+ (_, _) -> False
6294
6395data Orientation = Forward | Backward
6496 deriving stock (Eq, Ord, Show)
@@ -84,3 +116,9 @@ deriving stock instance Ord (AnIssue l)
84116
85117instance ToJSON (AnIssue l) where
86118 toJSON (AnIssue _ issue) = toJSON issue
119+
120+anIssueKind :: AnIssue l -> IssueKind
121+anIssueKind (AnIssue _ i) = issueKind i
122+
123+relatedAnIssues :: AnIssue l -> AnIssue l -> Bool
124+relatedAnIssues (AnIssue _ x) (AnIssue _ y) = relatedIssues x y
src/OpenAPI/Checker/PathsPrefixTree.hs+24−2
@@ -10,7 +10,9 @@ module OpenAPI.Checker.PathsPrefixTree
1010 , foldWith
1111 , toList
1212 , filter
13+ , filterWithKey
1314 , takeSubtree
15+ , lookup
1416 , embed
1517 , size
1618 , partition
@@ -33,7 +35,7 @@ import qualified Data.Vector as V
3335import qualified GHC.Exts as Exts
3436import OpenAPI.Checker.Paths
3537import Type.Reflection
36−import Prelude hiding (filter, map, null)
38+import Prelude hiding (filter, map, null, lookup)
3739
3840-- | A list of @AnItem r f@, but optimized into a prefix tree.
3941data PathsPrefixTree (q :: k -> k -> Type) (f :: k -> Type) (r :: k) = PathsPrefixTree
@@ -56,10 +58,27 @@ filter f (PathsPrefixTree roots branches) = PathsPrefixTree roots' branches'
5658 roots' = filterASet f roots
5759 branches' =
5860 Exts.fromList
59− . fmap (\(TRM.WrapTypeable (AStep x)) -> TRM.WrapTypeable . AStep . M.filter (not . null) . fmap (filter f) $ x)
61+ . fmap (\(TRM.WrapTypeable (AStep x)) -> TRM.WrapTypeable . AStep . M.mapMaybe (maybeNonEmpty . filter f) $ x)
6062 . Exts.toList
6163 $ branches
6264
65+ maybeNonEmpty = mfilter (not . null) . Just
66+
67+filterWithKey :: (forall a. Paths q r a -> f a -> Bool) -> PathsPrefixTree q f r -> PathsPrefixTree q f r
68+filterWithKey = go Root
69+ where
70+ go :: Paths q r b -> (forall a. Paths q r a -> f a -> Bool) -> PathsPrefixTree q f b -> PathsPrefixTree q f b
71+ go xs f (PathsPrefixTree roots branches) = PathsPrefixTree roots' branches'
72+ where
73+ roots' = filterASet (f xs) roots
74+ branches' =
75+ Exts.fromList
76+ . fmap (\(TRM.WrapTypeable (AStep x)) -> TRM.WrapTypeable . AStep . M.mapMaybeWithKey (\k -> maybeNonEmpty . go (xs `Snoc` k) f) $ x)
77+ . Exts.toList
78+ $ branches
79+
80+ maybeNonEmpty = mfilter (not . null) . Just
81+
6382-- | The number of leaves.
6483size :: PathsPrefixTree q f r -> Int
6584size (PathsPrefixTree root branches) =
@@ -225,6 +244,9 @@ takeSubtree (Snoc xs x) t =
225244 foldMap (\(AStep m) -> fold $ M.lookup x m) $
226245 TRM.lookup @a $ snocItems $ takeSubtree xs t
227246
247+lookup :: Paths q r a -> PathsPrefixTree q f r -> S.Set (f a)
248+lookup xs = toSet . rootItems . takeSubtree xs
249+
228250-- | Embed a subtree in a larger tree with given prefix
229251embed :: Paths q r a -> PathsPrefixTree q f a -> PathsPrefixTree q f r
230252embed Root t = t
src/OpenAPI/Checker/Report.hs+58−22
@@ -1,6 +1,8 @@
11module OpenAPI.Checker.Report
22 ( generateReport
3+ , CheckerOutput(..)
34 , ReportInput (..)
5+ , segregateIssues
46 , ReportStatus (..)
57 , Pandoc
68 , ReportConfig (..)
@@ -43,14 +45,38 @@ import Text.Pandoc.Builder
4345
4446type Changes = P.PathsPrefixTree Behave AnIssue 'APILevel
4547
48+data CheckerOutput = CheckerOutput
49+ { forwardChanges :: Changes
50+ , backwardChanges :: Changes
51+ }
52+ deriving stock (Generic)
53+ deriving (Semigroup, Monoid) via (Generically CheckerOutput)
54+ deriving anyclass (ToJSON)
55+
4656data ReportInput = ReportInput
47− { breakingChanges :: Changes
48− , nonBreakingChanges :: Changes
57+ { breakingChanges :: Changes -- ^ forward 'CertainIssue', 'ProbablyIssue' and 'Comment'
58+ , nonBreakingChanges :: Changes -- ^ backward 'CertainIssue', 'ProbablyIssue' and 'Comment', except those shadowed by 'relatedIssues'
59+ , unsupportedChanges :: Changes -- ^ forward and backward 'Unsupported' (assumed to be the same anyway)
60+ , schemaIssues :: Changes -- ^ forward and backward 'SchemaInvalid' (assumed to be the same anyway)
4961 }
5062 deriving stock (Generic)
5163 deriving (Semigroup, Monoid) via (Generically ReportInput)
5264 deriving anyclass (ToJSON)
5365
66+segregateIssues :: CheckerOutput -> ReportInput
67+segregateIssues CheckerOutput {forwardChanges = fwd, backwardChanges = bck} = ReportInput
68+ { breakingChanges = P.filter isBreaking fwd
69+ , nonBreakingChanges = invertIssueOrientationP $ P.filterWithKey isNonBreaking bck
70+ , unsupportedChanges = P.filter isUnsupported fwd <> P.filter isUnsupported bck
71+ , schemaIssues = P.filter isSchemaIssue fwd <> P.filter isSchemaIssue bck
72+ }
73+ where
74+ isBreaking i = anIssueKind i `elem` [CertainIssue, ProbablyIssue, Comment]
75+ isNonBreaking :: Paths Behave 'APILevel a -> AnIssue a -> Bool
76+ isNonBreaking xs i = isBreaking i && all (\j -> not $ relatedAnIssues i j) (P.lookup xs fwd)
77+ isUnsupported i = anIssueKind i == Unsupported
78+ isSchemaIssue i = anIssueKind i == SchemaInvalid
79+
5480data ReportStatus
5581 = BreakingChanges
5682 | NoBreakingChanges
@@ -80,13 +106,11 @@ twoRowTable x = simpleTable (para . fst <$> x) [para . snd <$> x]
80106
81107generateReport :: ReportConfig -> ReportInput -> (Pandoc, ReportStatus)
82108generateReport cfg inp =
83− let partitionUnsupported = P.partition (\(AnIssue _ i) -> issueIsUnsupported i)
84− (bUnsupported, breaking) = partitionUnsupported $ breakingChanges inp
85− (nbUnsupported, invertIssueOrientationP -> nonBreaking) = partitionUnsupported $ nonBreakingChanges inp
86− unsupported = bUnsupported <> nbUnsupported
87− breakingChangesPresent = not $ P.null breaking
88− nonBreakingChangesPresent = not $ P.null nonBreaking
89− unsupportedChangesPresent = not $ P.null unsupported
109+ let
110+ schemaIssuesPresent = not $ P.null $ schemaIssues inp
111+ breakingChangesPresent = not $ P.null $ breakingChanges inp
112+ nonBreakingChangesPresent = not $ P.null $ nonBreakingChanges inp
113+ unsupportedChangesPresent = not $ P.null $ unsupportedChanges inp
90114 nonBreakingChangesShown = case reportMode cfg of
91115 All -> True
92116 OnlyErrors -> False
@@ -95,32 +119,43 @@ generateReport cfg inp =
95119 doc $
96120 header 1 "Summary"
97121 <> twoRowTable
98− ([ ( refOpt breakingChangesPresent breakingChangesId "⚠️ Breaking changes"
99− , show' $ P.size breaking
100− )
101− ]
122+ (when'
123+ schemaIssuesPresent
124+ [ ( refOpt schemaIssuesPresent schemaIssuesId "❌ Schema issues"
125+ , show' $ P.size $ schemaIssues inp
126+ )
127+ ]
128+ ++
129+ [ ( refOpt breakingChangesPresent breakingChangesId "⚠️ Breaking changes"
130+ , show' $ P.size $ breakingChanges inp
131+ )
132+ ]
102133 ++ when'
103134 nonBreakingChangesShown
104135 [ ( refOpt nonBreakingChangesPresent nonBreakingChangesId "🙆 Non-breaking changes"
105− , show' $ P.size nonBreaking
136+ , show' $ P.size $ nonBreakingChanges inp
106137 )
107138 ]
108139 ++ [ ( refOpt unsupportedChangesPresent unsupportedChangesId "🤷 Unsupported feature changes"
109− , show' $ P.size unsupported
140+ , show' $ P.size $ unsupportedChanges inp
110141 )
111142 ])
143+ <> when'
144+ schemaIssuesPresent
145+ (header 1 (anchor schemaIssuesId <> "❌ Schema issues")
146+ <> builder (showErrs $ schemaIssues inp))
112147 <> when'
113148 breakingChangesPresent
114149 (header 1 (anchor breakingChangesId <> "⚠️ Breaking changes")
115− <> builder (showErrs breaking))
150+ <> builder (showErrs $ breakingChanges inp))
116151 <> when'
117152 (nonBreakingChangesPresent && nonBreakingChangesShown)
118153 (header 1 (anchor nonBreakingChangesId <> "🙆 Non-breaking changes")
119− <> builder (showErrs nonBreaking))
154+ <> builder (showErrs $ nonBreakingChanges inp))
120155 <> when'
121156 unsupportedChangesPresent
122157 (header 1 (anchor unsupportedChangesId <> "🤷 Unsupported feature changes")
123− <> builder (showErrs unsupported))
158+ <> builder (showErrs $ unsupportedChanges inp))
124159 status =
125160 if
126161 | breakingChangesPresent -> BreakingChanges
@@ -135,10 +170,11 @@ generateReport cfg inp =
135170 refOpt False _ i = i
136171 refOpt True a i = link ("#" <> a) "" i
137172
138− breakingChangesId, nonBreakingChangesId, unsupportedChangesId :: Text
173+ breakingChangesId, nonBreakingChangesId, unsupportedChangesId, schemaIssuesId :: Text
139174 breakingChangesId = "breaking-changes"
140175 unsupportedChangesId = "unsupported-changes"
141176 nonBreakingChangesId = "non-breaking-changes"
177+ schemaIssuesId = "schema-issues"
142178
143179 when' :: Monoid m => Bool -> m -> m
144180 when' True m = m
@@ -180,7 +216,7 @@ showErrs x@(P.PathsPrefixNode currentIssues _) =
180216 flip foldMap (M.toList m) $ \(bhv, subErrors) ->
181217 if P.null subErrors
182218 then mempty
183− else singletonHeader (describeBehaviour bhv) $ showErrs subErrors
219+ else singletonHeader (describeBehavior bhv) $ showErrs subErrors
184220 in issues <> paths <> rest
185221
186222unfoldFunctions :: forall m a. (Monoid m, Eq a) => a -> [a -> (m, a)] -> (a -> m) -> m
@@ -198,11 +234,11 @@ jets =
198234 unwrapReportJetResult
199235 <$> [ constructReportJet $
200236 curry $ \case
201− (OfType Object, p@(InPartition _)) -> Just $ describeBehaviour p :: Maybe Inlines
237+ (OfType Object, p@(InPartition _)) -> Just $ describeBehavior p :: Maybe Inlines
202238 _ -> Nothing
203239 , constructReportJet jsonPathJet
204240 , constructReportJet $ \p@(AtPath _) op@(InOperation _) ->
205− strong (describeBehaviour op) <> " " <> describeBehaviour p :: Inlines
241+ strong (describeBehavior op) <> " " <> describeBehavior p :: Inlines
206242 , constructReportJet $ \(WithStatusCode c) ResponsePayload PayloadSchema ->
207243 "📱⬅️ JSON Response – " <> str (T.pack . show $ c) :: Inlines
208244 , constructReportJet $ \InRequest InPayload PayloadSchema -> "📱➡️ JSON Request" :: Inlines
src/OpenAPI/Checker/Report/Jet.hs+1−1
@@ -23,7 +23,7 @@ import Text.Pandoc.Builder
2323-- The term "jet" in this context was introduced in the Urbit project:
2424-- https://urbit.org/docs/vere/jetting/
2525--
26−-- The pattern fits well for simplifying 'Behaviour' tree paths.
26+-- The pattern fits well for simplifying 'Behavior' tree paths.
2727class ConstructReportJet x f where
2828 constructReportJet :: x -> ReportJetResult f (Maybe Inlines)
2929
src/OpenAPI/Checker/Run.hs+5−5
@@ -12,11 +12,11 @@ import OpenAPI.Checker.Report
1212import OpenAPI.Checker.Subtree
1313import OpenAPI.Checker.Validate.OpenApi ()
1414
15−runChecker :: (OpenApi, OpenApi) -> ReportInput
15+runChecker :: (OpenApi, OpenApi) -> CheckerOutput
1616runChecker (client, server) =
17− ReportInput
18− { breakingChanges = run client server
19− , nonBreakingChanges = run server client
17+ CheckerOutput
18+ { forwardChanges = run client server
19+ , backwardChanges = run server client
2020 }
2121 where
2222 toPC p c =
@@ -27,4 +27,4 @@ runChecker (client, server) =
2727 run p c = either id mempty . runCompatFormula . checkCompatibility Root HNil $ toPC p c
2828
2929runReport :: ReportConfig -> (OpenApi, OpenApi) -> (Pandoc, ReportStatus)
30−runReport cfg = generateReport cfg . runChecker
30+runReport cfg = generateReport cfg . segregateIssues . runChecker
src/OpenAPI/Checker/Validate/Header.hs+4−2
@@ -50,7 +50,9 @@ instance Issuable 'HeaderLevel where
5050 | NonEmptyHeaderRequired
5151 | HeaderSchemaRequired
5252 deriving stock (Eq, Ord, Show)
53− issueIsUnsupported _ = False
53+ issueKind = \case
54+ HeaderSchemaRequired -> ProbablyIssue -- catch-all schema?
55+ _ -> CertainIssue
5456 describeIssue Forward RequiredHeaderMissing = para "Header has become required."
5557 describeIssue Backward RequiredHeaderMissing = para "Header is no longer required."
5658 describeIssue Forward NonEmptyHeaderRequired = para "The header does not allow empty values anymore."
@@ -61,4 +63,4 @@ instance Behavable 'HeaderLevel 'SchemaLevel where
6163 data Behave 'HeaderLevel 'SchemaLevel
6264 = InSchema
6365 deriving stock (Eq, Ord, Show)
64− describeBehaviour InSchema = "JSON Schema"
66+ describeBehavior InSchema = "JSON Schema"
src/OpenAPI/Checker/Validate/Link.hs+2−2
@@ -17,6 +17,6 @@ instance Issuable 'LinkLevel where
1717 data Issue 'LinkLevel
1818 = LinksUnsupported
1919 deriving stock (Eq, Ord, Show)
20− issueIsUnsupported = \case
21− LinksUnsupported -> True
20+ issueKind = \case
21+ LinksUnsupported -> Unsupported
2222 describeIssue _ LinksUnsupported = para "OpenApi Diff does not currently support Link Objects."
src/OpenAPI/Checker/Validate/MediaTypeObject.hs+7−7
@@ -38,9 +38,9 @@ instance Issuable 'PayloadLevel where
3838 | MediaEncodingMissing Text
3939 | EncodingNotSupported
4040 deriving stock (Eq, Ord, Show)
41− issueIsUnsupported = \case
42− EncodingNotSupported -> True
43− _ -> False
41+ issueKind = \case
42+ EncodingNotSupported -> Unsupported
43+ _ -> CertainIssue
4444
4545 describeIssue _ MediaTypeSchemaRequired = para "Media type expected, but was not specified."
4646 describeIssue Forward (MediaEncodingMissing enc) = para $ "Media encoding " <> str enc <> " has been removed."
@@ -51,7 +51,7 @@ instance Behavable 'PayloadLevel 'SchemaLevel where
5151 data Behave 'PayloadLevel 'SchemaLevel
5252 = PayloadSchema
5353 deriving stock (Eq, Ord, Show)
54− describeBehaviour PayloadSchema = "JSON Schema"
54+ describeBehavior PayloadSchema = "JSON Schema"
5555
5656instance Subtree MediaTypeObject where
5757 type SubtreeLevel MediaTypeObject = 'PayloadLevel
@@ -143,7 +143,7 @@ instance Behavable 'OperationLevel 'ResponseLevel where
143143 data Behave 'OperationLevel 'ResponseLevel
144144 = WithStatusCode HttpStatusCode
145145 deriving stock (Eq, Ord, Show)
146− describeBehaviour (WithStatusCode c) = "Response code " <> (fromString . show $ c)
146+ describeBehavior (WithStatusCode c) = "Response code " <> (fromString . show $ c)
147147
148148instance Issuable 'OperationLevel where
149149 data Issue 'OperationLevel
@@ -152,8 +152,8 @@ instance Issuable 'OperationLevel where
152152 | PathFragmentNotMatched Int
153153 | NoRequestBody
154154 deriving stock (Eq, Ord, Show)
155− issueIsUnsupported = \case
156− _ -> False
155+ issueKind = \case
156+ _ -> CertainIssue
157157 describeIssue Forward (ConsumerDoesntHaveResponseCode c) =
158158 para $ "Response code " <> (str . T.pack . show $ c) <> " has been removed."
159159 describeIssue Backward (ConsumerDoesntHaveResponseCode c) =
src/OpenAPI/Checker/Validate/OAuth2Flows.hs+9−4
@@ -103,7 +103,9 @@ instance Issuable 'SecurityRequirementLevel where
103103 = SecurityRequirementNotMet
104104 | UndefinedSecurityScheme Text
105105 deriving stock (Eq, Ord, Show)
106− issueIsUnsupported _ = False
106+ issueKind = \case
107+ SecurityRequirementNotMet -> CertainIssue
108+ UndefinedSecurityScheme _ -> SchemaInvalid
107109 describeIssue Forward SecurityRequirementNotMet = para "Security scheme has been removed."
108110 describeIssue Backward SecurityRequirementNotMet = para "Security scheme was added."
109111 describeIssue _ (UndefinedSecurityScheme k) = para $ "Security scheme " <> code k <> " is not defined."
@@ -129,11 +131,14 @@ instance Issuable 'SecuritySchemeLevel where
129131 | CanNotHaveScopes
130132 | ScopeNotDefined Text
131133 deriving stock (Eq, Ord, Show)
132− issueIsUnsupported _ = False
134+ issueKind = \case
135+ CanNotHaveScopes -> SchemaInvalid
136+ ScopeNotDefined _ -> SchemaInvalid
137+ _ -> CertainIssue
133138 describeIssue _ RefreshUrlsDontMatch = para "Refresh URL changed."
134139 describeIssue _ (HttpSchemeTypesDontMatch _ _) = para "HTTP scheme type changed."
135140 describeIssue _ (ApiKeyParamsDontMatch _ _) = para "API Key parameters changed."
136− describeIssue _ (OpenIdConnectUrlsDontMatch _ _) = para "OpenaId Connect URL changed."
141+ describeIssue _ (OpenIdConnectUrlsDontMatch _ _) = para "OpenID Connect URL changed."
137142 describeIssue _ (CustomHttpSchemesDontMatch e a) =
138143 para $ "Changed HTTP scheme from " <> code e <> " to " <> code a <> "."
139144 describeIssue Forward ConsumerDoesNotSupportImplicitFlow = para "Implicit flow support has been removed."
@@ -162,4 +167,4 @@ instance Behavable 'SecurityRequirementLevel 'SecuritySchemeLevel where
162167 data Behave 'SecurityRequirementLevel 'SecuritySchemeLevel
163168 = SecuritySchemeStep Text
164169 deriving stock (Eq, Ord, Show)
165− describeBehaviour (SecuritySchemeStep s) = text s
170+ describeBehavior (SecuritySchemeStep s) = text s
src/OpenAPI/Checker/Validate/Operation.hs+17−12
@@ -101,21 +101,21 @@ instance Behavable 'OperationLevel 'PathFragmentLevel where
101101 = InParam Text
102102 | InFragment (PathFragment Text)
103103 deriving stock (Eq, Ord, Show)
104− describeBehaviour (InParam p) = "Parameter " <> text p
105− describeBehaviour (InFragment (StaticPath p)) = "Static fragment " <> code p
106− describeBehaviour (InFragment (DynamicPath p)) = "Dynamic fragment " <> code p
104+ describeBehavior (InParam p) = "Parameter " <> text p
105+ describeBehavior (InFragment (StaticPath p)) = "Static fragment " <> code p
106+ describeBehavior (InFragment (DynamicPath p)) = "Dynamic fragment " <> code p
107107
108108instance Behavable 'OperationLevel 'RequestLevel where
109109 data Behave 'OperationLevel 'RequestLevel
110110 = InRequest
111111 deriving stock (Eq, Ord, Show)
112− describeBehaviour InRequest = "Request"
112+ describeBehavior InRequest = "Request"
113113
114114instance Behavable 'OperationLevel 'SecurityRequirementLevel where
115115 data Behave 'OperationLevel 'SecurityRequirementLevel
116116 = SecurityRequirementStep Int
117117 deriving stock (Eq, Ord, Show)
118− describeBehaviour (SecurityRequirementStep i) =
118+ describeBehavior (SecurityRequirementStep i) =
119119 "Security requirement " <> (text . T.pack . show $ i)
120120
121121instance Subtree MatchedOperation where
@@ -335,7 +335,11 @@ instance Issuable 'APILevel where
335335 | AllPathsFailed FilePath
336336 -- When several paths match given but all checks failed
337337 deriving stock (Eq, Ord, Show)
338− issueIsUnsupported _ = False
338+ issueKind = \case
339+ _ -> CertainIssue
340+ relatedIssues = (==) `withClass` \case
341+ NoPathsMatched fp -> Just fp
342+ AllPathsFailed fp -> Just fp
339343 describeIssue Forward (NoPathsMatched p) = para $ "The path " <> (code . T.pack) p <> " has been removed."
340344 describeIssue Backward (NoPathsMatched p) = para $ "The path " <> (code . T.pack) p <> " has been added."
341345 describeIssue Forward (AllPathsFailed p) = para $ "The path " <> (code . T.pack) p <> " has been removed."
@@ -346,7 +350,7 @@ instance Behavable 'APILevel 'PathLevel where
346350 = AtPath FilePath
347351 deriving stock (Eq, Ord, Show)
348352
349− describeBehaviour (AtPath p) = str (T.pack p)
353+ describeBehavior (AtPath p) = str (T.pack p)
350354
351355instance Subtree ProcessedPathItems where
352356 type SubtreeLevel ProcessedPathItems = 'APILevel
@@ -440,7 +444,8 @@ instance Issuable 'PathLevel where
440444 data Issue 'PathLevel
441445 = OperationMissing OperationMethod
442446 deriving stock (Eq, Ord, Show)
443− issueIsUnsupported _ = False
447+ issueKind = \case
448+ OperationMissing _ -> CertainIssue
444449 describeIssue Forward (OperationMissing op) = para $ "Method " <> strong (showMethod op) <> " has been removed."
445450 describeIssue Backward (OperationMissing op) = para $ "Method " <> strong (showMethod op) <> " has been added."
446451
@@ -449,7 +454,7 @@ instance Behavable 'PathLevel 'OperationLevel where
449454 = InOperation OperationMethod
450455 deriving stock (Eq, Ord, Show)
451456
452− describeBehaviour (InOperation method) = showMethod method
457+ describeBehavior (InOperation method) = showMethod method
453458
454459showMethod :: IsString s => OperationMethod -> s
455460showMethod = \case
@@ -557,8 +562,8 @@ instance Issuable 'CallbackLevel where
557562 data Issue 'CallbackLevel
558563 = CallbacksUnsupported
559564 deriving stock (Eq, Ord, Show)
560− issueIsUnsupported = \case
561− CallbacksUnsupported -> True
565+ issueKind = \case
566+ CallbacksUnsupported -> Unsupported
562567 describeIssue _ CallbacksUnsupported = para "OpenApi Diff does not currently support callbacks."
563568
564569tracedCallbackPathItems :: Traced Callback -> Traced ProcessedPathItems
@@ -573,4 +578,4 @@ instance Behavable 'OperationLevel 'CallbackLevel where
573578 data Behave 'OperationLevel 'CallbackLevel = OperationCallback Text
574579 deriving stock (Eq, Ord, Show)
575580
576− describeBehaviour (OperationCallback key) = "Operation " <> code key
581+ describeBehavior (OperationCallback key) = "Operation " <> code key
src/OpenAPI/Checker/Validate/Param.hs+4−2
@@ -68,7 +68,9 @@ instance Issuable 'PathFragmentLevel where
6868 ParamSchemaMismatch
6969 | PathFragmentsDontMatch (ProdCons Text)
7070 deriving stock (Eq, Ord, Show)
71− issueIsUnsupported _ = False
71+ issueKind = \case
72+ ParamSchemaMismatch -> ProbablyIssue -- the schema could be catch-all (?)
73+ _ -> CertainIssue
7274 describeIssue _ ParamNameMismatch = para "The path fragments don't match."
7375 describeIssue Forward ParamEmptinessIncompatible = para "The parameter can no longer be empty."
7476 describeIssue Backward ParamEmptinessIncompatible = para "The parameter can now be empty."
@@ -85,7 +87,7 @@ instance Behavable 'PathFragmentLevel 'SchemaLevel where
8587 = InParamSchema
8688 deriving stock (Eq, Ord, Show)
8789
88− describeBehaviour InParamSchema = "JSON Schema"
90+ describeBehavior InParamSchema = "JSON Schema"
8991
9092instance Subtree Param where
9193 type SubtreeLevel Param = 'PathFragmentLevel
src/OpenAPI/Checker/Validate/RequestBody.hs+3−2
@@ -30,7 +30,8 @@ instance Issuable 'RequestLevel where
3030 = RequestBodyRequired
3131 | RequestMediaTypeNotFound MediaType
3232 deriving stock (Eq, Ord, Show)
33− issueIsUnsupported _ = False
33+ issueKind = \case
34+ _ -> CertainIssue
3435 describeIssue Forward RequestBodyRequired =
3536 para "Request body has become required."
3637 describeIssue Backward RequestBodyRequired =
@@ -44,7 +45,7 @@ instance Behavable 'RequestLevel 'PayloadLevel where
4445 data Behave 'RequestLevel 'PayloadLevel
4546 = InPayload
4647 deriving stock (Eq, Ord, Show)
47− describeBehaviour InPayload = "Payload"
48+ describeBehavior InPayload = "Payload"
4849
4950instance Subtree RequestBody where
5051 type SubtreeLevel RequestBody = 'RequestLevel
src/OpenAPI/Checker/Validate/Responses.hs+4−3
@@ -71,7 +71,8 @@ instance Issuable 'ResponseLevel where
7171 = ConsumerDoesntHaveMediaType MediaType
7272 | ProducerDoesntHaveResponseHeader HeaderName
7373 deriving stock (Eq, Ord, Show)
74− issueIsUnsupported _ = False
74+ issueKind = \case
75+ _ -> CertainIssue
7576 describeIssue Forward (ConsumerDoesntHaveMediaType t) =
7677 para $ "Media type was removed: " <> (code . T.pack . show $ t) <> "."
7778 describeIssue Backward (ConsumerDoesntHaveMediaType t) =
@@ -86,14 +87,14 @@ instance Behavable 'ResponseLevel 'PayloadLevel where
8687 = ResponsePayload
8788 deriving stock (Eq, Ord, Show)
8889
89− describeBehaviour ResponsePayload = "Payload"
90+ describeBehavior ResponsePayload = "Payload"
9091
9192instance Behavable 'ResponseLevel 'HeaderLevel where
9293 data Behave 'ResponseLevel 'HeaderLevel
9394 = InHeader HeaderName
9495 deriving stock (Eq, Ord, Show)
9596
96− describeBehaviour (InHeader name) = "Header " <> code name
97+ describeBehavior (InHeader name) = "Header " <> code name
9798
9899instance Subtree Response where
99100 type SubtreeLevel Response = 'ResponseLevel
src/OpenAPI/Checker/Validate/Schema/Issues.hs+83−14
@@ -87,7 +87,66 @@ instance Issuable 'TypedSchemaLevel where
8787 | -- | consumer indicates that no values in a particular partition are allowed, but we weren't able to conclude this in the producer
8888 PartitionBecomesEmpty Partition
8989 deriving stock (Eq, Ord, Show)
90− issueIsUnsupported _ = False
90+ issueKind = \case
91+ NoMatchingEnum _ -> ProbablyIssue
92+ MatchingMaximumWeak _ -> ProbablyIssue -- interplay with MultipleOf could make this not an issue
93+ MatchingMinimumWeak _ -> ProbablyIssue -- ditto
94+ MatchingMultipleOfWeak _ -> ProbablyIssue -- ditto
95+ NoMatchingFormat _ -> Unsupported
96+ NoMatchingPattern _ -> Unsupported
97+ ArrayToTuple -> Comment
98+ TupleToArray -> Comment
99+ NoMatchingProperties -> ProbablyIssue -- TODO: #109
100+ TypeBecomesEmpty -> ProbablyIssue -- TODO: #70
101+ PartitionBecomesEmpty _ -> ProbablyIssue -- ditto
102+ _ -> CertainIssue
103+ relatedIssues = (==) `withClass` \case
104+ EnumDoesntSatisfy v -> Just v
105+ NoMatchingEnum v -> Just v
106+ _ -> Nothing
107+ `withClass` \case
108+ NoMatchingMaximum _ -> Just ()
109+ MatchingMaximumWeak _ -> Just ()
110+ _ -> Nothing
111+ `withClass` \case
112+ NoMatchingMinimum _ -> Just ()
113+ MatchingMinimumWeak _ -> Just ()
114+ _ -> Nothing
115+ `withClass` \case
116+ NoMatchingMultipleOf _ -> Just ()
117+ MatchingMultipleOfWeak _ -> Just ()
118+ _ -> Nothing
119+ `withClass` \case
120+ NoMatchingMaxLength _ -> Just ()
121+ MatchingMaxLengthWeak _ -> Just ()
122+ _ -> Nothing
123+ `withClass` \case
124+ NoMatchingMinLength _ -> Just ()
125+ MatchingMinLengthWeak _ -> Just ()
126+ _ -> Nothing
127+ `withClass` \case
128+ NoMatchingItems -> Just ()
129+ ArrayToTuple -> Just ()
130+ TupleToArray -> Just ()
131+ NoMatchingTupleItems -> Just ()
132+ TupleItemsLengthChanged _ -> Just ()
133+ _ -> Nothing
134+ `withClass` \case
135+ NoMatchingMaxItems _ -> Just ()
136+ MatchingMaxItemsWeak _ -> Just ()
137+ _ -> Nothing
138+ `withClass` \case
139+ NoMatchingMinItems _ -> Just ()
140+ MatchingMinItemsWeak _ -> Just ()
141+ _ -> Nothing
142+ `withClass` \case
143+ NoMatchingMaxProperties _ -> Just ()
144+ MatchingMaxPropertiesWeak _ -> Just ()
145+ _ -> Nothing
146+ `withClass` \case
147+ NoMatchingMinProperties _ -> Just ()
148+ MatchingMinPropertiesWeak _ -> Just ()
149+ _ -> Nothing
91150 describeIssue Forward (EnumDoesntSatisfy v) = para "The following enum value was removed:" <> showJSONValue v
92151 describeIssue Backward (EnumDoesntSatisfy v) = para "The following enum value was added:" <> showJSONValue v
93152 describeIssue Forward (NoMatchingEnum v) = para "The following enum value has been added:" <> showJSONValue v
@@ -186,13 +245,23 @@ instance Issuable 'SchemaLevel where
186245 | -- | producer allows a property that is not allowed in the consumer
187246 UnexpectedProperty
188247 deriving stock (Eq, Ord, Show)
189− issueIsUnsupported = \case
190− NotSupported _ -> True
191− OneOfNotDisjoint -> True
192− InvalidSchema _ -> True
193− UnguardedRecursion -> True
194− _ -> False
195−
248+ issueKind = \case
249+ NotSupported _ -> Unsupported
250+ OneOfNotDisjoint -> Unsupported
251+ InvalidSchema _ -> SchemaInvalid
252+ UnguardedRecursion -> Unsupported
253+ AdditionalToProperty -> Comment
254+ PropertyToAdditional -> Comment
255+ TypesRestricted _ -> ProbablyIssue -- TODO: #70
256+ _ -> CertainIssue
257+ relatedIssues = (==) `withClass` \case
258+ AdditionalToProperty -> Just ()
259+ PropertyToAdditional -> Just ()
260+ _ -> Nothing
261+ `withClass` \case
262+ PropertyNowRequired -> Just ()
263+ UnexpectedProperty -> Just ()
264+ _ -> Nothing
196265 describeIssue _ (NotSupported i) =
197266 para (emph "Encountered a feature that OpenApi Diff does not support: " <> text i <> ".")
198267 describeIssue _ OneOfNotDisjoint =
@@ -227,14 +296,14 @@ instance Behavable 'SchemaLevel 'TypedSchemaLevel where
227296 = OfType JsonType
228297 deriving stock (Eq, Ord, Show)
229298
230− describeBehaviour (OfType t) = describeJSONType t
299+ describeBehavior (OfType t) = describeJSONType t
231300
232301instance Behavable 'TypedSchemaLevel 'TypedSchemaLevel where
233302 data Behave 'TypedSchemaLevel 'TypedSchemaLevel
234303 = InPartition Partition
235304 deriving stock (Eq, Ord, Show)
236305
237− describeBehaviour (InPartition partition) = "In cases where " <> showPartition partition
306+ describeBehavior (InPartition partition) = "In cases where " <> showPartition partition
238307
239308instance Behavable 'TypedSchemaLevel 'SchemaLevel where
240309 data Behave 'TypedSchemaLevel 'SchemaLevel
@@ -244,7 +313,7 @@ instance Behavable 'TypedSchemaLevel 'SchemaLevel where
244313 | InAdditionalProperty
245314 deriving stock (Eq, Ord, Show)
246315
247− describeBehaviour InItems = "Items"
248− describeBehaviour (InItem i) = "Item " <> show' i
249− describeBehaviour (InProperty p) = "Property " <> code p
250− describeBehaviour InAdditionalProperty = "Additional properties"
316+ describeBehavior InItems = "Items"
317+ describeBehavior (InItem i) = "Item " <> show' i
318+ describeBehavior (InProperty p) = "Property " <> code p
319+ describeBehavior InAdditionalProperty = "Additional properties"
src/OpenAPI/Checker/Validate/Server.hs+4−2
@@ -46,7 +46,7 @@ instance Behavable 'OperationLevel 'ServerLevel where
4646 = InServer Text
4747 deriving stock (Eq, Ord, Show)
4848
49− describeBehaviour (InServer n) = "Server " <> code n
49+ describeBehavior (InServer n) = "Server " <> code n
5050
5151instance Subtree [Server] where
5252 type SubtreeLevel [Server] = 'OperationLevel
@@ -133,7 +133,9 @@ instance Issuable 'ServerLevel where
133133 | ServerVariableNotDefined Text
134134 | ServerNotMatched
135135 deriving stock (Eq, Ord, Show)
136− issueIsUnsupported _ = False
136+ issueKind = \case
137+ ServerVariableNotDefined _ -> SchemaInvalid
138+ _ -> CertainIssue
137139 describeIssue Forward (EnumValueNotConsumed _ v) =
138140 para $ "Enum value " <> code v <> " has been removed."
139141 describeIssue Backward (EnumValueNotConsumed _ v) =
test/golden/common/bad-oneof-unchanged/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -7,7 +7,7 @@ breakingChanges:
77 WithStatusCode 200:
88 ResponsePayload:
99 PayloadSchema: OneOfNotDisjoint
10−nonBreakingChanges:
10+backwardChanges:
1111 AtPath "/test":
1212 InOperation PostMethod:
1313 InRequest:
test/golden/common/enum-added/trace-tree.yaml+2−2
@@ -1,11 +1,11 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 WithStatusCode 200:
55 ResponsePayload:
66 PayloadSchema:
77 OfType String: EnumDoesntSatisfy (String "C")
8−nonBreakingChanges:
8+backwardChanges:
99 AtPath "/test":
1010 InOperation PostMethod:
1111 InRequest:
test/golden/common/enum-anyof/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/id/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/json/recursive/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/maximum-lowered/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -6,7 +6,7 @@ breakingChanges:
66 PayloadSchema:
77 OfType Number: MatchingMaximumWeak (ProdCons {producer = Inclusive 3.0,
88 consumer = Inclusive 2.0})
9−nonBreakingChanges:
9+backwardChanges:
1010 AtPath "/test":
1111 InOperation PostMethod:
1212 WithStatusCode 200:
test/golden/common/pathItem/operation/parameters/allowEmptyValue/reset/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InParam "test1": ParamEmptinessIncompatible
5−nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/allowEmptyValue/set/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod:
55 InParam "test1": ParamEmptinessIncompatible
test/golden/common/pathItem/operation/parameters/change/trace-tree.yaml+2−2
@@ -1,10 +1,10 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InParam "test":
55 InParamSchema:
66 OfType String: TypeBecomesEmpty
7−nonBreakingChanges:
7+backwardChanges:
88 AtPath "/test":
99 InOperation PostMethod:
1010 InParam "test":
test/golden/common/pathItem/operation/parameters/required/false/add/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/false/del/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/reset/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod:
55 InParam "test1": ParamRequired
test/golden/common/pathItem/operation/parameters/required/set/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InParam "test1": ParamRequired
5−nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/true/add/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod: ParamNotMatched "test2"
4−nonBreakingChanges: {}
4+backwardChanges: {}
test/golden/common/pathItem/operation/parameters/required/true/del/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod: ParamNotMatched "test2"
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/add/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod:
55 InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/change/trace-tree.yaml+2−2
@@ -1,11 +1,11 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
55 InPayload:
66 PayloadSchema:
77 OfType String: TypeBecomesEmpty
8−nonBreakingChanges:
8+backwardChanges:
99 AtPath "/test":
1010 InOperation PostMethod:
1111 InRequest:
test/golden/common/pathItem/operation/requestBody/mediaTypeObject/del/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest: RequestMediaTypeNotFound application/x-www-form-urlencoded
5−nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/requestBody/required/reset/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod:
55 InRequest: RequestBodyRequired
test/golden/common/pathItem/operation/requestBody/required/set/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest: RequestBodyRequired
5−nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/responses/add/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod: ConsumerDoesntHaveResponseCode 500
4−nonBreakingChanges: {}
4+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/headers/mandatory/add/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod:
55 WithStatusCode 200: ProducerDoesntHaveResponseHeader "Test2"
test/golden/common/pathItem/operation/responses/change/headers/mandatory/del/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 WithStatusCode 200: ProducerDoesntHaveResponseHeader "Test2"
5−nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/headers/optional/add/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/headers/optional/del/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/add/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 WithStatusCode 200: ConsumerDoesntHaveMediaType application/x-www-form-urlencoded
5−nonBreakingChanges: {}
5+backwardChanges: {}
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/change/trace-tree.yaml+2−2
@@ -1,11 +1,11 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 WithStatusCode 200:
55 ResponsePayload:
66 PayloadSchema:
77 OfType Number: TypeBecomesEmpty
8−nonBreakingChanges:
8+backwardChanges:
99 AtPath "/test":
1010 InOperation PostMethod:
1111 WithStatusCode 200:
test/golden/common/pathItem/operation/responses/change/mediaTypeObject/del/trace-tree.yaml+2−2
@@ -1,5 +1,5 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod:
55 WithStatusCode 200: ConsumerDoesntHaveMediaType application/x-www-form-urlencoded
test/golden/common/pathItem/operation/responses/del/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges: {}
2−nonBreakingChanges:
1+forwardChanges: {}
2+backwardChanges:
33 AtPath "/test":
44 InOperation PostMethod: ConsumerDoesntHaveResponseCode 500
test/golden/common/property-removed-additional/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 WithStatusCode 200:
@@ -9,7 +9,7 @@ breakingChanges:
99 - TypesRestricted [Number]
1010 - AdditionalToProperty
1111 - PropertyNowRequired
12−nonBreakingChanges:
12+backwardChanges:
1313 AtPath "/test":
1414 InOperation PostMethod:
1515 InRequest:
test/golden/common/property-removed/report.md+3−19
@@ -1,8 +1,8 @@
11# Summary
22
3−| [⚠️ Breaking changes](#breaking-changes) | [🙆 Non-breaking changes](#non-breaking-changes) | 🤷 Unsupported feature changes |
4−|------------------------------------------|-------------------------------------------------|-------------------------------|
5−| 2 | 2 | 0 |
3+| [⚠️ Breaking changes](#breaking-changes) | 🙆 Non-breaking changes | 🤷 Unsupported feature changes |
4+|------------------------------------------|------------------------|-------------------------------|
5+| 2 | 0 | 0 |
66
77# <span id="breaking-changes"></span>⚠️ Breaking changes
88
@@ -19,19 +19,3 @@ The property has been removed.
1919#### `$.property2`
2020
2121The property may not be present.
22−
23−# <span id="non-breaking-changes"></span>🙆 Non-breaking changes
24−
25−## **POST** /test
26−
27−### 📱➡️ JSON Request
28−
29−#### `$.property2`
30−
31−The property may not be present.
32−
33−### 📱⬅️ JSON Response – 200
34−
35−#### `$.property2`
36−
37−The property has been removed.
test/golden/common/property-removed/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -11,7 +11,7 @@ breakingChanges:
1111 PayloadSchema:
1212 OfType Object:
1313 InProperty "property2": PropertyNowRequired
14−nonBreakingChanges:
14+backwardChanges:
1515 AtPath "/test":
1616 InOperation PostMethod:
1717 InRequest:
test/golden/common/property-required/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -6,7 +6,7 @@ breakingChanges:
66 PayloadSchema:
77 OfType Object:
88 InProperty "property2": PropertyNowRequired
9−nonBreakingChanges:
9+backwardChanges:
1010 AtPath "/test":
1111 InOperation PostMethod:
1212 WithStatusCode 200:
test/golden/common/random-example/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/pets":
33 InOperation GetMethod:
44 WithStatusCode 200:
@@ -20,7 +20,7 @@ breakingChanges:
2020 - TypesRestricted [Number]
2121 - AdditionalToProperty
2222 - OfType Number: NoMatchingMultipleOf 1.0
23−nonBreakingChanges:
23+backwardChanges:
2424 AtPath "/pets":
2525 InOperation GetMethod:
2626 WithStatusCode 200:
test/golden/common/recursive/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/api/foo":
33 InOperation GetMethod:
44 InRequest:
@@ -11,7 +11,7 @@ breakingChanges:
1111 OfType Object:
1212 InProperty "foo":
1313 OfType String: NoMatchingEnum (String "a")
14−nonBreakingChanges:
14+backwardChanges:
1515 AtPath "/api/foo":
1616 InOperation GetMethod:
1717 WithStatusCode 200:
test/golden/common/security-scheme/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/oauth/sign_out":
33 InOperation GetMethod:
44 SecurityRequirementStep 1:
@@ -7,7 +7,7 @@ breakingChanges:
77 InOperation PostMethod:
88 SecurityRequirementStep 0:
99 SecuritySchemeStep "oauth": SecuritySchemeNotMatched
10−nonBreakingChanges:
10+backwardChanges:
1111 AtPath "/oauth/check":
1212 InOperation PostMethod:
1313 SecurityRequirementStep 0:
test/golden/common/servers/trace-tree.yaml+2−2
@@ -1,11 +1,11 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/pets":
33 InOperation GetMethod:
44 InServer "http://{x}variable.path/{y}/{openVariable1}/{openVariable2}":
55 - EnumValueNotConsumed 1 "a"
66 - ConsumerNotOpen 7
77 InServer "http://missing.url": ServerNotMatched
8−nonBreakingChanges:
8+backwardChanges:
99 AtPath "/pets":
1010 InOperation GetMethod:
1111 InServer "http://{x}variable.path/{y}/{openVariable1}/{openVariable2}": EnumValueNotConsumed
test/golden/common/tuple-items/heterogeneous-component-mismatch/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -13,7 +13,7 @@ breakingChanges:
1313 OfType Array:
1414 InItem 1:
1515 OfType Object: TypeBecomesEmpty
16−nonBreakingChanges:
16+backwardChanges:
1717 AtPath "/test":
1818 InOperation PostMethod:
1919 InRequest:
test/golden/common/tuple-items/heterogeneous-length-mismatch/report.md+3−19
@@ -1,8 +1,8 @@
11# Summary
22
3−| [⚠️ Breaking changes](#breaking-changes) | [🙆 Non-breaking changes](#non-breaking-changes) | 🤷 Unsupported feature changes |
4−|------------------------------------------|-------------------------------------------------|-------------------------------|
5−| 2 | 2 | 0 |
3+| [⚠️ Breaking changes](#breaking-changes) | 🙆 Non-breaking changes | 🤷 Unsupported feature changes |
4+|------------------------------------------|------------------------|-------------------------------|
5+| 2 | 0 | 0 |
66
77# <span id="breaking-changes"></span>⚠️ Breaking changes
88
@@ -19,19 +19,3 @@ Tuple length changed from 3 to 2.
1919#### `$(Array)`
2020
2121Tuple length changed from 3 to 2.
22−
23−# <span id="non-breaking-changes"></span>🙆 Non-breaking changes
24−
25−## **POST** /test
26−
27−### 📱➡️ JSON Request
28−
29−#### `$(Array)`
30−
31−Tuple length changed from 3 to 2.
32−
33−### 📱⬅️ JSON Response – 200
34−
35−#### `$(Array)`
36−
37−Tuple length changed from 3 to 2.
test/golden/common/tuple-items/heterogeneous-length-mismatch/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -11,7 +11,7 @@ breakingChanges:
1111 PayloadSchema:
1212 OfType Array: TupleItemsLengthChanged (ProdCons {producer = 2, consumer
1313 = 3})
14−nonBreakingChanges:
14+backwardChanges:
1515 AtPath "/test":
1616 InOperation PostMethod:
1717 InRequest:
test/golden/common/tuple-items/homogeneous-component-mismatch/report.md+1−9
@@ -2,7 +2,7 @@
22
33| [⚠️ Breaking changes](#breaking-changes) | [🙆 Non-breaking changes](#non-breaking-changes) | 🤷 Unsupported feature changes |
44|------------------------------------------|-------------------------------------------------|-------------------------------|
5−| 4 | 4 | 0 |
5+| 4 | 2 | 0 |
66
77# <span id="breaking-changes"></span>⚠️ Breaking changes
88
@@ -34,20 +34,12 @@ The type has been added.
3434
3535### 📱➡️ JSON Request
3636
37−#### `$(Array)`
38−
39−The array is no longer explicitly defined as a tuple.
40−
4137#### `$[0](Number)`
4238
4339The type has been added.
4440
4541### 📱⬅️ JSON Response – 200
4642
47−#### `$(Array)`
48−
49−The array is no longer explicitly defined as a tuple.
50−
5143#### `$[0](String)`
5244
5345The type has been removed.
test/golden/common/tuple-items/homogeneous-component-mismatch/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -15,7 +15,7 @@ breakingChanges:
1515 - ArrayToTuple
1616 - InItem 0:
1717 OfType Number: TypeBecomesEmpty
18−nonBreakingChanges:
18+backwardChanges:
1919 AtPath "/test":
2020 InOperation PostMethod:
2121 InRequest:
test/golden/common/tuple-items/homogeneous-length-mismatch/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test3":
33 InOperation PostMethod:
44 InRequest:
@@ -24,7 +24,7 @@ breakingChanges:
2424 ResponsePayload:
2525 PayloadSchema:
2626 OfType Array: NoMatchingTupleItems
27−nonBreakingChanges:
27+backwardChanges:
2828 AtPath "/test3":
2929 InOperation PostMethod:
3030 InRequest:
test/golden/common/tuple-items/homogeneous-vector/trace-tree.yaml+2−2
@@ -1,2 +1,2 @@
1−breakingChanges: {}
2−nonBreakingChanges: {}
1+forwardChanges: {}
2+backwardChanges: {}
test/golden/common/type-changing/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test5":
33 InOperation PostMethod:
44 InRequest:
@@ -28,7 +28,7 @@ breakingChanges:
2828 InRequest:
2929 InPayload:
3030 PayloadSchema: TypesRestricted [Number,Array,Object]
31−nonBreakingChanges:
31+backwardChanges:
3232 AtPath "/test5":
3333 InOperation PostMethod:
3434 WithStatusCode 200:
test/golden/common/unguarded-recursive/trace-tree.yaml+2−2
@@ -1,10 +1,10 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/api/foo":
33 InOperation GetMethod:
44 WithStatusCode 200:
55 ResponsePayload:
66 PayloadSchema: UnguardedRecursion
7−nonBreakingChanges:
7+backwardChanges:
88 AtPath "/api/foo":
99 InOperation GetMethod:
1010 WithStatusCode 200:
test/golden/common/variant-added/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 WithStatusCode 200:
@@ -6,7 +6,7 @@ breakingChanges:
66 PayloadSchema:
77 OfType Object: PartitionBecomesEmpty (PInProperty "tag" PHere,CByEnumValue
88 (fromList [String "C"]))
9−nonBreakingChanges:
9+backwardChanges:
1010 AtPath "/test":
1111 InOperation PostMethod:
1212 InRequest:
test/golden/common/variant-changed/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -15,7 +15,7 @@ breakingChanges:
1515 InPartition (PInProperty "tag" PHere,CByEnumValue (fromList [String "B"])):
1616 InProperty "prop_B":
1717 OfType String: TypeBecomesEmpty
18−nonBreakingChanges:
18+backwardChanges:
1919 AtPath "/test":
2020 InOperation PostMethod:
2121 InRequest:
test/golden/common/variant-deep-changed/trace-tree.yaml+2−2
@@ -1,4 +1,4 @@
1−breakingChanges:
1+forwardChanges:
22 AtPath "/test":
33 InOperation PostMethod:
44 InRequest:
@@ -15,7 +15,7 @@ breakingChanges:
1515 InPartition (PInProperty "desc" (PInProperty "name" PHere),CByEnumValue (fromList [String "B"])):
1616 InProperty "prop_B":
1717 OfType String: TypeBecomesEmpty
18−nonBreakingChanges:
18+backwardChanges:
1919 AtPath "/test":
2020 InOperation PostMethod:
2121 InRequest: