1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
10import Control.Monad.Except (liftIO)
11import qualified Data.List as List
12import qualified Data.Map as Map
13import qualified Data.Maybe as Maybe
15import qualified Deps.Cache as Cache
16import Deps.Diff (PackageChanges(..), ModuleChanges(..), Changes(..), Magnitude(..))
17import qualified Deps.Diff as Diff
18import qualified Elm.Compiler.Module as Module
19import qualified Elm.Compiler.Type as Type
20import qualified Elm.Docs as Docs
21import qualified Elm.Name as N
22import qualified Elm.Package as Pkg
23import qualified Elm.Project as Project
24import qualified Elm.Project.Json as Project
25import qualified Elm.Project.Summary as Summary
26import Reporting.Doc ((<>), (<+>))
27import qualified Reporting.Doc as D
28import qualified Reporting.Exit as Exit
29import qualified Reporting.Exit.Diff as E
30import qualified Reporting.Exit.Help as Help
31import qualified Reporting.Render.Type.Localizer as L
32import qualified Reporting.Task as Task
41 | CodeVsExactly Pkg.Version
42 | LocalInquiry Pkg.Version Pkg.Version
43 | GlobalInquiry Pkg.Name Pkg.Version Pkg.Version
46diff :: Args -> Task.Task ()
49 GlobalInquiry name v1 v2 ->
50 do registry <- Cache.mandatoryUpdate
51 case Cache.getVersions name registry of
53 throw $ E.UnknownPackage name suggestions
56 do oldDocs <- getDocs name vsns (min v1 v2)
57 newDocs <- getDocs name vsns (max v1 v2)
58 writeDiff oldDocs newDocs
61 do (_, name, vsns) <- getPackageInfo
62 oldDocs <- getDocs name vsns (min v1 v2)
63 newDocs <- getDocs name vsns (max v1 v2)
64 writeDiff oldDocs newDocs
67 do (summary, name, vsns) <- getPackageInfo
68 oldDocs <- getDocs name vsns (maximum vsns)
69 newDocs <- Task.silently (Project.generateDocs summary)
70 writeDiff oldDocs newDocs
72 CodeVsExactly version ->
73 do (summary, name, vsns) <- getPackageInfo
74 oldDocs <- getDocs name vsns version
75 newDocs <- Task.silently (Project.generateDocs summary)
76 writeDiff oldDocs newDocs
79throw :: E.Exit -> Task.Task a
81 Task.throw $ Exit.Diff exit
88getDocs :: Pkg.Name -> [Pkg.Version] -> Pkg.Version -> Task.Task Docs.Documentation
89getDocs name allVersions version =
90 if elem version allVersions then
91 Cache.getDocs name version
93 throw $ E.UnknownVersion name version allVersions
96getPackageInfo :: Task.Task (Summary.Summary, Pkg.Name, [Pkg.Version])
98 do summary <- Project.getRoot
99 case Summary._project summary of
101 throw $ E.Application
103 Project.Pkg (Project.PkgInfo name _ _ _ _ _ _ _) ->
104 do registry <- Cache.mandatoryUpdate
105 case Cache.getVersions name registry of
107 return ( summary, name, vsns )
117writeDiff :: Docs.Documentation -> Docs.Documentation -> Task.Task ()
118writeDiff oldDocs newDocs =
120 changes = Diff.diff oldDocs newDocs
121 localizer = L.fromNames (Map.union oldDocs newDocs)
123 liftIO $ Help.toStdout (toDoc localizer changes <> "\n")
130toDoc :: L.Localizer -> PackageChanges -> D.Doc
131toDoc localizer changes@(PackageChanges added changed removed) =
132 if null added && Map.null changed && null removed then
133 "No API changes detected, so this is a" <+> D.green "PATCH" <+> "change."
137 D.fromString (Diff.magnitudeToString (Diff.toMagnitude changes))
140 "This is a" <+> D.green magDoc <+> "change."
143 if null added then [] else
144 [ Chunk "ADDED MODULES" MINOR $
145 D.vcat $ map (D.fromString . Module.nameToString) added
149 if null removed then [] else
150 [ Chunk "REMOVED MODULES" MAJOR $
151 D.vcat $ map (D.fromString . Module.nameToString) removed
155 addedChunk ++ removedChunk ++ map (changesToChunk localizer) (Map.toList changed)
157 D.vcat (header : "" : map chunkToDoc chunks)
163 , _magnitude :: Magnitude
168chunkToDoc :: Chunk -> D.Doc
169chunkToDoc (Chunk title magnitude details) =
172 Diff.magnitudeToString magnitude
175 "----" <+> D.fromString title <+> "-" <+> D.fromString magDoc <+> "----"
186changesToChunk :: L.Localizer -> (N.Name, ModuleChanges) -> Chunk
187changesToChunk localizer (name, changes@(ModuleChanges unions aliases values binops)) =
190 Diff.moduleChangeMagnitude changes
192 (unionAdd, unionChange, unionRemove) =
193 changesToDocTriple (unionToDoc localizer) unions
195 (aliasAdd, aliasChange, aliasRemove) =
196 changesToDocTriple (aliasToDoc localizer) aliases
198 (valueAdd, valueChange, valueRemove) =
199 changesToDocTriple (valueToDoc localizer) values
201 (binopAdd, binopChange, binopRemove) =
202 changesToDocTriple (binopToDoc localizer) binops
204 Chunk (N.toString name) magnitude $
205 D.vcat $ List.intersperse "" $ Maybe.catMaybes $
206 [ changesToDoc "Added" unionAdd aliasAdd valueAdd binopAdd
207 , changesToDoc "Removed" unionRemove aliasRemove valueRemove binopRemove
208 , changesToDoc "Changed" unionChange aliasChange valueChange binopChange
212changesToDocTriple :: (k -> v -> D.Doc) -> Changes k v -> ([D.Doc], [D.Doc], [D.Doc])
213changesToDocTriple entryToDoc (Changes added changed removed) =
215 indented (name, value) =
216 D.indent 4 (entryToDoc name value)
218 diffed (name, (oldValue, newValue)) =
220 [ " - " <> entryToDoc name oldValue
221 , " + " <> entryToDoc name newValue
225 ( map indented (Map.toList added)
226 , map diffed (Map.toList changed)
227 , map indented (Map.toList removed)
231changesToDoc :: String -> [D.Doc] -> [D.Doc] -> [D.Doc] -> [D.Doc] -> Maybe D.Doc
232changesToDoc categoryName unions aliases values binops =
233 if null unions && null aliases && null values && null binops then
238 D.fromString categoryName <> ":" : unions ++ aliases ++ binops ++ values
241unionToDoc :: L.Localizer -> N.Name -> Docs.Union -> D.Doc
242unionToDoc localizer name (Docs.Union _ tvars ctors) =
245 "type" <+> D.fromName name <+> D.hsep (map D.fromName tvars)
247 ctorDoc (ctor, tipes) =
248 typeDoc localizer (Type.Type ctor tipes)
250 D.hang 4 (D.sep (setup : zipWith (<+>) ("=" : repeat "|") (map ctorDoc ctors)))
253aliasToDoc :: L.Localizer -> N.Name -> Docs.Alias -> D.Doc
254aliasToDoc localizer name (Docs.Alias _ tvars tipe) =
257 "type" <+> "alias" <+> D.hsep (map D.fromName (name:tvars)) <+> "="
259 D.hang 4 (D.sep [ declaration, typeDoc localizer tipe ])
262valueToDoc :: L.Localizer -> N.Name -> Docs.Value -> D.Doc
263valueToDoc localizer name (Docs.Value _ tipe) =
264 D.hang 4 $ D.sep [ D.fromName name <+> ":", typeDoc localizer tipe ]
267binopToDoc :: L.Localizer -> N.Name -> Docs.Binop -> D.Doc
268binopToDoc localizer name (Docs.Binop _ tipe associativity (Docs.Precedence n)) =
269 "(" <> D.fromName name <> ")" <+> ":" <+> typeDoc localizer tipe <> D.black details
272 " (" <> D.fromName assoc <> "/" <> D.fromInt n <> ")"
275 case associativity of
278 Docs.Right -> "right"
281typeDoc :: L.Localizer -> Type.Type -> D.Doc
282typeDoc localizer tipe =
283 Type.toDoc localizer Type.None tipe
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list