1{-# OPTIONS_GHC -Wall #-}
2{-# LANGUAGE OverloadedStrings #-}
9 , moduleChangeMagnitude
17import Control.Monad (zipWithM)
18import Data.Function (on)
19import qualified Data.List as List
20import qualified Data.Map as Map
21import qualified Data.Set as Set
22import qualified Data.Text as Text
24import qualified Elm.Compiler.Module as Module
25import qualified Elm.Compiler.Type as Type
26import qualified Elm.Docs as Docs
27import qualified Elm.Name as N
28import qualified Elm.Package as Pkg
37 { _modules_added :: [Module.Raw]
38 , _modules_changed :: Map.Map Module.Raw ModuleChanges
39 , _modules_removed :: [Module.Raw]
45 { _unions :: Changes N.Name Docs.Union
46 , _aliases :: Changes N.Name Docs.Alias
47 , _values :: Changes N.Name Docs.Value
48 , _binops :: Changes N.Name Docs.Binop
54 { _added :: Map.Map k v
55 , _changed :: Map.Map k (v,v)
56 , _removed :: Map.Map k v
60getChanges :: (Ord k) => (v -> v -> Bool) -> Map.Map k v -> Map.Map k v -> Changes k v
61getChanges isEquivalent old new =
63 overlap = Map.intersectionWith (,) old new
64 changed = Map.filter (not . uncurry isEquivalent) overlap
66 Changes (Map.difference new old) changed (Map.difference old new)
73diff :: Docs.Documentation -> Docs.Documentation -> PackageChanges
76 filterOutPatches chngs =
77 Map.filter (\chng -> moduleChangeMagnitude chng /= PATCH) chngs
79 (Changes added changed removed) =
80 getChanges (\_ _ -> False) oldDocs newDocs
84 (filterOutPatches (Map.map diffModule changed))
89diffModule :: (Docs.Module, Docs.Module) -> ModuleChanges
90diffModule (Docs.Module _ _ u1 a1 v1 b1, Docs.Module _ _ u2 a2 v2 b2) =
92 (getChanges isEquivalentUnion u1 u2)
93 (getChanges isEquivalentAlias a1 a2)
94 (getChanges isEquivalentValue v1 v2)
95 (getChanges isEquivalentBinop b1 b2)
102isEquivalentUnion :: Docs.Union -> Docs.Union -> Bool
103isEquivalentUnion (Docs.Union oldComment oldVars oldCtors) (Docs.Union newComment newVars newCtors) =
104 length oldCtors == length newCtors
105 && and (zipWith (==) (map fst oldCtors) (map fst newCtors))
106 && and (Map.elems (Map.intersectionWith equiv (Map.fromList oldCtors) (Map.fromList newCtors)))
108 equiv :: [Type.Type] -> [Type.Type] -> Bool
109 equiv oldTypes newTypes =
114 (map (Docs.Alias oldComment oldVars) oldTypes)
115 (map (Docs.Alias newComment newVars) newTypes)
117 length oldTypes == length newTypes
121isEquivalentAlias :: Docs.Alias -> Docs.Alias -> Bool
122isEquivalentAlias (Docs.Alias _ oldVars oldType) (Docs.Alias _ newVars newType) =
123 case diffType oldType newType of
128 length oldVars == length newVars
129 && isEquivalentRenaming (zip oldVars newVars ++ renamings)
132isEquivalentValue :: Docs.Value -> Docs.Value -> Bool
133isEquivalentValue (Docs.Value c1 t1) (Docs.Value c2 t2) =
134 isEquivalentAlias (Docs.Alias c1 [] t1) (Docs.Alias c2 [] t2)
137isEquivalentBinop :: Docs.Binop -> Docs.Binop -> Bool
138isEquivalentBinop (Docs.Binop c1 t1 a1 p1) (Docs.Binop c2 t2 a2 p2) =
139 isEquivalentAlias (Docs.Alias c1 [] t1) (Docs.Alias c2 [] t2)
148diffType :: Type.Type -> Type.Type -> Maybe [(N.Name,N.Name)]
149diffType oldType newType =
150 case (oldType, newType) of
151 (Type.Var oldName, Type.Var newName) ->
152 Just [(oldName, newName)]
154 (Type.Lambda a b, Type.Lambda a' b') ->
159 (Type.Type oldName oldArgs, Type.Type newName newArgs) ->
160 if not (isSameName oldName newName) || length oldArgs /= length newArgs then
163 concat <$> zipWithM diffType oldArgs newArgs
165 (Type.Record fields maybeExt, Type.Record fields' maybeExt') ->
166 case (maybeExt, maybeExt') of
173 (Nothing, Nothing) ->
174 diffFields fields fields'
176 (Just oldExt, Just newExt) ->
177 (:) (oldExt, newExt) <$> diffFields fields fields'
183-- handle very old docs that do not use qualified names
184isSameName :: N.Name -> N.Name -> Bool
185isSameName oldFullName newFullName =
188 reverse (Text.splitOn "." (N.toText name))
190 case ( dedot oldFullName, dedot newFullName ) of
191 (oldName:[], newName:_) ->
194 (oldName:_, newName:[]) ->
198 oldFullName == newFullName
201diffFields :: [(N.Name, Type.Type)] -> [(N.Name, Type.Type)] -> Maybe [(N.Name,N.Name)]
202diffFields oldRawFields newRawFields =
204 sort = List.sortBy (compare `on` fst)
205 oldFields = sort oldRawFields
206 newFields = sort newRawFields
208 if length oldRawFields /= length newRawFields then
211 else if or (zipWith ((/=) `on` fst) oldFields newFields) then
215 concat <$> zipWithM (diffType `on` snd) oldFields newFields
222isEquivalentRenaming :: [(N.Name,N.Name)] -> Bool
223isEquivalentRenaming varPairs =
226 Map.toList (foldr insert Map.empty varPairs)
228 insert (old,new) dict =
229 Map.insertWith (++) old [new] dict
237 if all (new ==) rest then
243 length list == Set.size (Set.fromList list)
245 case mapM verify renamings of
249 Just verifiedRenamings ->
250 all compatableVars verifiedRenamings
252 allUnique (map snd verifiedRenamings)
255compatableVars :: (N.Name, N.Name) -> Bool
256compatableVars (old, new) =
257 case (categorizeVar old, categorizeVar new) of
258 (CompAppend, CompAppend) -> True
259 (Comparable, Comparable) -> True
260 (Appendable, Appendable) -> True
261 (Number , Number ) -> True
263 (Comparable, CompAppend) -> True
264 (Appendable, CompAppend) -> True
265 (Number , CompAppend) -> True
266 (Number , Comparable) -> True
281categorizeVar :: N.Name -> TypeVarCategory
283 | N.startsWith "compappend" name = CompAppend
284 | N.startsWith "comparable" name = Comparable
285 | N.startsWith "appendable" name = Appendable
286 | N.startsWith "number" name = Number
301magnitudeToString :: Magnitude -> String
302magnitudeToString magnitude =
314bump :: PackageChanges -> Pkg.Version -> Pkg.Version
315bump changes version =
316 case toMagnitude changes of
318 Pkg.bumpPatch version
321 Pkg.bumpMinor version
324 Pkg.bumpMajor version
327toMagnitude :: PackageChanges -> Magnitude
328toMagnitude (PackageChanges added changed removed) =
330 addMag = if null added then PATCH else MINOR
331 removeMag = if null removed then PATCH else MAJOR
332 changeMags = map moduleChangeMagnitude (Map.elems changed)
334 maximum (addMag : removeMag : changeMags)
337moduleChangeMagnitude :: ModuleChanges -> Magnitude
338moduleChangeMagnitude (ModuleChanges unions aliases values binops) =
340 [ changeMagnitude unions
341 , changeMagnitude aliases
342 , changeMagnitude values
343 , changeMagnitude binops
347changeMagnitude :: Changes k v -> Magnitude
348changeMagnitude (Changes added changed removed) =
349 if Map.size removed > 0 || Map.size changed > 0 then
352 else if Map.size added > 0 then
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