mirror of
https://github.com/github/semantic.git
synced 2024-12-25 16:02:43 +03:00
Merge remote-tracking branch 'origin/master' into typescript-assignment
This commit is contained in:
commit
d0fb557bec
@ -138,24 +138,6 @@ executable semantic
|
||||
default-language: Haskell2010
|
||||
default-extensions: FlexibleInstances, OverloadedStrings, RecordWildCards
|
||||
|
||||
executable slurp
|
||||
hs-source-dirs: app
|
||||
main-is: Slurp.hs
|
||||
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||
build-depends: base
|
||||
, aeson
|
||||
, base64-bytestring
|
||||
, bytestring
|
||||
, filepath
|
||||
, github
|
||||
, netrc
|
||||
, regex-compat
|
||||
, text
|
||||
, text-conversions
|
||||
, vector
|
||||
default-language: Haskell2010
|
||||
default-extensions: FlexibleInstances, OverloadedStrings, RecordWildCards
|
||||
|
||||
test-suite test
|
||||
type: exitcode-stdio-1.0
|
||||
hs-source-dirs: test
|
||||
|
@ -32,9 +32,6 @@ instance GAlign Identity where
|
||||
instance Apply GAlign fs => GAlign (Union fs) where
|
||||
galignWith f = (join .) . apply2' (Proxy :: Proxy GAlign) (\ inj -> (fmap inj .) . galignWith f)
|
||||
|
||||
instance GAlign (Union '[]) where
|
||||
galignWith _ _ _ = Nothing
|
||||
|
||||
instance GAlign NonEmpty where
|
||||
galignWith f (a:|as) (b:|bs) = Just (f (These a b) :| alignWith f as bs)
|
||||
|
||||
|
@ -4,16 +4,20 @@ module Interpreter
|
||||
, decoratingWith
|
||||
, diffTermsWith
|
||||
, comparableByConstructor
|
||||
, equivalentTerms
|
||||
) where
|
||||
|
||||
import Algorithm
|
||||
import Control.Monad.Free.Freer
|
||||
import Data.Align.Generic
|
||||
import Data.Functor.Classes (Eq1)
|
||||
import Data.Functor.Classes (Eq1(..))
|
||||
import Data.Hashable (Hashable)
|
||||
import Data.Maybe (isJust)
|
||||
import Data.Record
|
||||
import Data.Text (Text)
|
||||
import Data.These
|
||||
import Data.Union
|
||||
import qualified Data.Syntax.Declaration as Declaration
|
||||
import Diff
|
||||
import Info hiding (Return)
|
||||
import RWS
|
||||
@ -26,7 +30,7 @@ diffTerms :: (HasField fields1 Category, HasField fields2 Category)
|
||||
=> Term Syntax (Record fields1) -- ^ A term representing the old state.
|
||||
-> Term Syntax (Record fields2) -- ^ A term representing the new state.
|
||||
-> Diff Syntax (Record fields1) (Record fields2)
|
||||
diffTerms = decoratingWith getLabel getLabel (diffTermsWith algorithmWithTerms comparableByCategory)
|
||||
diffTerms = decoratingWith getLabel getLabel (diffTermsWith algorithmWithTerms comparableByCategory (equalTerms comparableByCategory))
|
||||
|
||||
-- | Diff two terms by decorating with feature vectors computed using the supplied labelling algebra, and stripping the feature vectors from the resulting diff.
|
||||
decoratingWith :: (Hashable label, Traversable syntax)
|
||||
@ -43,17 +47,18 @@ diffTermsWith :: forall syntax fields1 fields2
|
||||
. (Eq1 syntax, GAlign syntax, Traversable syntax)
|
||||
=> (Term syntax (Record (FeatureVector ': fields1)) -> Term syntax (Record (FeatureVector ': fields2)) -> Algorithm (Term syntax) (Diff syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2))) (Diff syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2)))) -- ^ A function producing syntax-directed continuations of the algorithm.
|
||||
-> ComparabilityRelation syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2)) -- ^ A relation on terms used to determine comparability and equality.
|
||||
-> (Term syntax (Record (FeatureVector ': fields1)) -> Term syntax (Record (FeatureVector ': fields2)) -> Bool) -- ^ A relation used to determine term equivalence.
|
||||
-> Term syntax (Record (FeatureVector ': fields1)) -- ^ A term representing the old state.
|
||||
-> Term syntax (Record (FeatureVector ': fields2)) -- ^ A term representing the new state.
|
||||
-> Diff syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2)) -- ^ The resulting diff.
|
||||
diffTermsWith refine comparable t1 t2 = runFreer decompose (diff t1 t2)
|
||||
diffTermsWith refine comparable eqTerms t1 t2 = runFreer decompose (diff t1 t2)
|
||||
where decompose :: AlgorithmF (Term syntax) (Diff syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2))) result -> Algorithm (Term syntax) (Diff syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2))) result
|
||||
decompose step = case step of
|
||||
Algorithm.Diff t1 t2 -> refine t1 t2
|
||||
Linear t1 t2 -> case galignWith diffThese (unwrap t1) (unwrap t2) of
|
||||
Just result -> merge (extract t1, extract t2) <$> sequenceA result
|
||||
_ -> byReplacing t1 t2
|
||||
RWS as bs -> traverse diffThese (rws comparable as bs)
|
||||
RWS as bs -> traverse diffThese (rws comparable eqTerms as bs)
|
||||
Delete a -> pure (deleting a)
|
||||
Insert b -> pure (inserting b)
|
||||
Replace a b -> pure (replacing a b)
|
||||
@ -116,3 +121,20 @@ comparableByCategory (In a _) (In b _) = category a == category b
|
||||
-- | Test whether two terms are comparable by their constructor.
|
||||
comparableByConstructor :: GAlign syntax => ComparabilityRelation syntax ann1 ann2
|
||||
comparableByConstructor (In _ a) (In _ b) = isJust (galign a b)
|
||||
|
||||
-- | Equivalency relation for terms. Equivalence is determined by functions and
|
||||
-- methods with equal identifiers/names and recursively by equivalent terms with
|
||||
-- identical shapes.
|
||||
equivalentTerms :: (Declaration.Method :< fs, Declaration.Function :< fs, Apply Functor fs, Apply Foldable fs, Apply GAlign fs, Apply Eq1 fs)
|
||||
=> Term (Union fs) a
|
||||
-> Term (Union fs) b
|
||||
-> Bool
|
||||
equivalentTerms a b | Just (Declaration.Method _ _ identifierA _ _) <- prj (unwrap a)
|
||||
, Just (Declaration.Method _ _ identifierB _ _) <- prj (unwrap b)
|
||||
= liftEq equivalentTerms (unwrap identifierA) (unwrap identifierB)
|
||||
| Just (Declaration.Function _ identifierA _ _) <- prj (unwrap a)
|
||||
, Just (Declaration.Function _ identifierB _ _) <- prj (unwrap b)
|
||||
= liftEq equivalentTerms (unwrap identifierA) (unwrap identifierB)
|
||||
| Just aligned <- galignWith (these (const False) (const False) equivalentTerms) (unwrap a) (unwrap b)
|
||||
= and aligned
|
||||
| otherwise = False
|
||||
|
@ -10,6 +10,7 @@ import Data.Syntax (makeTerm, parseError)
|
||||
import qualified Data.Syntax as Syntax
|
||||
import Data.Syntax.Assignment hiding (Assignment, Error)
|
||||
import qualified Data.Syntax.Assignment as Assignment
|
||||
import qualified Data.Syntax.Declaration as Declaration
|
||||
import qualified Data.Syntax.Literal as Literal
|
||||
import Language.JSON.Grammar as Grammar
|
||||
import qualified Term
|
||||
@ -26,6 +27,9 @@ type Syntax =
|
||||
, Literal.Null
|
||||
, Literal.String
|
||||
, Literal.TextElement
|
||||
-- NB: Diffing requires Methods and Functions in the union.
|
||||
, Declaration.Method
|
||||
, Declaration.Function
|
||||
, Syntax.Error
|
||||
, []
|
||||
]
|
||||
|
@ -1,4 +1,4 @@
|
||||
{-# LANGUAGE DataKinds, DeriveAnyClass, GADTs, RankNTypes, TypeOperators #-}
|
||||
{-# LANGUAGE DataKinds, GADTs, RankNTypes, TypeOperators #-}
|
||||
module Language.Markdown.Syntax
|
||||
( assignment
|
||||
, Syntax
|
||||
@ -14,6 +14,7 @@ import Data.Syntax (makeTerm)
|
||||
import qualified Data.Syntax as Syntax
|
||||
import Data.Syntax.Assignment hiding (Assignment, Error)
|
||||
import qualified Data.Syntax.Assignment as Assignment
|
||||
import qualified Data.Syntax.Declaration as Declaration
|
||||
import qualified Data.Syntax.Markup as Markup
|
||||
import qualified Data.Text as Text
|
||||
import Data.Text.Encoding (encodeUtf8)
|
||||
@ -45,6 +46,9 @@ type Syntax =
|
||||
, Markup.Strong
|
||||
, Markup.Text
|
||||
, Markup.Strikethrough
|
||||
-- NB: Diffing requires Methods and Functions in the union.
|
||||
, Declaration.Method
|
||||
, Declaration.Function
|
||||
-- Assignment errors; cmark does not provide parse errors.
|
||||
, Syntax.Error
|
||||
, []
|
||||
|
@ -5,6 +5,8 @@ import Language.Haskell.TH
|
||||
import TreeSitter.Language
|
||||
import TreeSitter.Python
|
||||
|
||||
-- Regenerate template haskell code when these files change:
|
||||
addDependentFileRelative "../../../vendor/haskell-tree-sitter/languages/python/vendor/tree-sitter-python/src/parser.c"
|
||||
|
||||
-- | Statically-known rules corresponding to symbols in the grammar.
|
||||
-- v4 - bump this to regenerate
|
||||
mkSymbolDatatype (mkName "Grammar") tree_sitter_python
|
||||
|
@ -37,6 +37,8 @@ type Syntax =
|
||||
, Declaration.Decorator
|
||||
, Declaration.Function
|
||||
, Declaration.Import
|
||||
-- NB: Diffing requires Methods in the union.
|
||||
, Declaration.Method
|
||||
, Declaration.Variable
|
||||
, Expression.Arithmetic
|
||||
, Expression.Boolean
|
||||
|
@ -795,7 +795,7 @@ expressions :: Assignment
|
||||
expressions = makeTerm <$> location <*> many expression
|
||||
|
||||
identifier :: Assignment
|
||||
identifier = (makeTerm <$> symbol Identifier <*> (Syntax.Identifier <$> source)) <|> (makeTerm <$> symbol Identifier' <*> (Syntax.Identifier <$> source))
|
||||
identifier = (makeTerm <$> symbol Identifier' <*> (Syntax.Identifier <$> source)) <|> (makeTerm <$> symbol Identifier <*> (Syntax.Identifier <$> source))
|
||||
|
||||
literal :: Assignment
|
||||
literal =
|
||||
|
12
src/RWS.hs
12
src/RWS.hs
@ -8,6 +8,7 @@ module RWS
|
||||
, pqGramDecorator
|
||||
, Gram(..)
|
||||
, defaultD
|
||||
, equalTerms
|
||||
) where
|
||||
|
||||
import Control.Applicative (empty)
|
||||
@ -57,14 +58,15 @@ data TermOrIndexOrNone term = Term term | Index {-# UNPACK #-} !Int | None
|
||||
|
||||
rws :: (Eq1 syntax, Foldable syntax, Functor syntax, GAlign syntax)
|
||||
=> ComparabilityRelation syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2))
|
||||
-> (Term syntax (Record (FeatureVector ': fields1)) -> Term syntax (Record (FeatureVector ': fields2)) -> Bool)
|
||||
-> [Term syntax (Record (FeatureVector ': fields1))]
|
||||
-> [Term syntax (Record (FeatureVector ': fields2))]
|
||||
-> RWSEditScript syntax (Record (FeatureVector ': fields1)) (Record (FeatureVector ': fields2))
|
||||
rws _ as [] = This <$> as
|
||||
rws _ [] bs = That <$> bs
|
||||
rws canCompare [a] [b] = if canCompareTerms canCompare a b then [These a b] else [That b, This a]
|
||||
rws canCompare as bs =
|
||||
let sesDiffs = ses (equalTerms canCompare) as bs
|
||||
rws _ _ as [] = This <$> as
|
||||
rws _ _ [] bs = That <$> bs
|
||||
rws canCompare _ [a] [b] = if canCompareTerms canCompare a b then [These a b] else [That b, This a]
|
||||
rws canCompare equivalent as bs =
|
||||
let sesDiffs = ses equivalent as bs
|
||||
(featureAs, featureBs, mappedDiffs, allDiffs) = genFeaturizedTermsAndDiffs sesDiffs
|
||||
(diffs, remaining) = findNearestNeighboursToDiff canCompare allDiffs featureAs featureBs
|
||||
diffs' = deleteRemaining diffs remaining
|
||||
|
@ -1,4 +1,4 @@
|
||||
{-# LANGUAGE DeriveAnyClass, MultiParamTypeClasses, RankNTypes, TypeOperators #-}
|
||||
{-# LANGUAGE MultiParamTypeClasses, RankNTypes, TypeOperators, ScopedTypeVariables #-}
|
||||
module Renderer.TOC
|
||||
( renderToCDiff
|
||||
, renderToCTerm
|
||||
@ -29,6 +29,7 @@ import Data.Functor.Both hiding (fst, snd)
|
||||
import Data.Functor.Foldable (cata)
|
||||
import Data.Function (on)
|
||||
import Data.List.NonEmpty (nonEmpty)
|
||||
import Data.List (sortOn)
|
||||
import Data.Maybe (fromMaybe, mapMaybe)
|
||||
import Data.Output
|
||||
import Data.Record
|
||||
@ -112,7 +113,7 @@ syntaxDeclarationAlgebra Blob{..} (In a r) = case r of
|
||||
where getSource = toText . flip Source.slice blobSource . byteRange . extract
|
||||
|
||||
-- | Compute 'Declaration's for methods and functions.
|
||||
declarationAlgebra :: (Declaration.Function :< fs, Declaration.Method :< fs, Syntax.Error :< fs, Syntax.Empty :< fs, Apply Functor fs, HasField fields Range, HasField fields Span)
|
||||
declarationAlgebra :: (Declaration.Function :< fs, Declaration.Method :< fs, Syntax.Empty :< fs, Syntax.Error :< fs, Apply Functor fs, HasField fields Range, HasField fields Span)
|
||||
=> Blob
|
||||
-> RAlgebra (TermF (Union fs) (Record fields)) (Term (Union fs) (Record fields)) (Maybe Declaration)
|
||||
declarationAlgebra Blob{..} (In a r)
|
||||
@ -137,6 +138,7 @@ declarationAlgebra Blob{..} (In a r)
|
||||
| Just err@Syntax.Error{} <- prj r
|
||||
= Just $ ErrorDeclaration (T.pack (formatTOCError (Syntax.unError (sourceSpan a) err))) blobLanguage
|
||||
| otherwise = Nothing
|
||||
|
||||
where getSource = toText . flip Source.slice blobSource . byteRange
|
||||
|
||||
-- | Compute 'Declaration's with the headings of 'Markup.Section's.
|
||||
@ -185,18 +187,32 @@ termTableOfContentsBy selector = cata termAlgebra
|
||||
where termAlgebra r | Just a <- selector r = [a]
|
||||
| otherwise = fold r
|
||||
|
||||
dedupe :: HasField fields (Maybe Declaration) => [Entry (Record fields)] -> [Entry (Record fields)]
|
||||
dedupe = foldl' go []
|
||||
where go xs x | (_, _:_) <- find (exactMatch `on` entryPayload) x xs = xs
|
||||
| (front, similar : back) <- find (similarMatch `on` entryPayload) x xs =
|
||||
front <> (Replaced (entryPayload similar) : back)
|
||||
| otherwise = xs <> [x]
|
||||
newtype DedupeKey = DedupeKey (Maybe T.Text, Maybe T.Text) deriving (Eq, Ord)
|
||||
|
||||
find p x = List.break (p x)
|
||||
exactMatch = (==) `on` getDeclaration
|
||||
similarMatch a b = sameCategory a b && similarDeclaration a b
|
||||
sameCategory = (==) `on` fmap toCategoryName . getDeclaration
|
||||
similarDeclaration = (==) `on` fmap (toLower . declarationIdentifier) . getDeclaration
|
||||
-- Dedupe entries in a final pass. This catches two specific scenarios with
|
||||
-- different behaviors:
|
||||
-- 1. Identical entries are in the list.
|
||||
-- Action: take the first one, drop all subsequent.
|
||||
-- 2. Two similar entries (defined by a case insensitive comparision of their
|
||||
-- identifiers) are in the list.
|
||||
-- Action: Combine them into a single Replaced entry.
|
||||
dedupe :: forall fields. HasField fields (Maybe Declaration) => [Entry (Record fields)] -> [Entry (Record fields)]
|
||||
dedupe = let tuples = sortOn fst . Map.elems . snd . foldl' go (0, Map.empty) in (fmap . fmap) snd tuples
|
||||
where
|
||||
go :: HasField fields (Maybe Declaration)
|
||||
=> (Int, Map.Map DedupeKey (Int, Entry (Record fields)))
|
||||
-> Entry (Record fields)
|
||||
-> (Int, Map.Map DedupeKey (Int, Entry (Record fields)))
|
||||
go (index, m) x | Just (_, similar) <- Map.lookup (dedupeKey x) m
|
||||
= if exactMatch similar x
|
||||
then (succ index, m)
|
||||
else
|
||||
let replacement = Replaced (entryPayload similar)
|
||||
in (succ index, Map.insert (dedupeKey replacement) (index, replacement) m)
|
||||
| otherwise = (succ index, Map.insert (dedupeKey x) (index, x) m)
|
||||
|
||||
dedupeKey entry = DedupeKey ((fmap toCategoryName . getDeclaration . entryPayload) entry, (fmap (toLower . declarationIdentifier) . getDeclaration . entryPayload) entry)
|
||||
exactMatch = (==) `on` (getDeclaration . entryPayload)
|
||||
|
||||
-- | Construct a 'JSONSummary' from an 'Entry'. Returns 'Nothing' for 'Unchanged' patches.
|
||||
entrySummary :: (HasField fields (Maybe Declaration), HasField fields Span) => Entry (Record fields) -> Maybe JSONSummary
|
||||
|
@ -46,7 +46,7 @@ parseBlobs renderer = fmap toOutput . distributeFoldMap (parseBlob renderer) . f
|
||||
parseBlob :: TermRenderer output -> Blob -> Task output
|
||||
parseBlob renderer blob@Blob{..} = case (renderer, blobLanguage) of
|
||||
(ToCTermRenderer, Just Language.Markdown) -> parse markdownParser blob >>= decorate (markupSectionAlgebra blob) >>= render (renderToCTerm blob)
|
||||
(ToCTermRenderer, Just Language.Python) -> parse pythonParser blob >>= decorate (declarationAlgebra blob) . hoistTerm (weaken :: Union fs a -> Union (Declaration.Method ': fs) a) >>= render (renderToCTerm blob)
|
||||
(ToCTermRenderer, Just Language.Python) -> parse pythonParser blob >>= decorate (declarationAlgebra blob) >>= render (renderToCTerm blob)
|
||||
(ToCTermRenderer, Just Language.TypeScript) -> parse typescriptParser blob >>= decorate (declarationAlgebra blob) >>= render (renderToCTerm blob)
|
||||
(ToCTermRenderer, _) -> parse syntaxParser blob >>= decorate (syntaxDeclarationAlgebra blob) >>= render (renderToCTerm blob)
|
||||
(JSONTermRenderer, Just Language.Markdown) -> parse markdownParser blob >>= decorate constructorLabel >>= render (renderJSONTerm blob)
|
||||
@ -75,7 +75,7 @@ diffBlobPairs renderer = fmap toOutput . distributeFoldMap (diffBlobPair rendere
|
||||
diffBlobPair :: DiffRenderer output -> Both Blob -> Task output
|
||||
diffBlobPair renderer blobs = case (renderer, effectiveLanguage) of
|
||||
(ToCDiffRenderer, Just Language.Markdown) -> run (\ blob -> parse markdownParser blob >>= decorate (markupSectionAlgebra blob)) diffRecursively (renderToCDiff blobs)
|
||||
(ToCDiffRenderer, Just Language.Python) -> run (\ blob -> parse pythonParser blob >>= decorate (declarationAlgebra blob) . hoistTerm (weaken :: Union fs a -> Union (Declaration.Method ': fs) a)) diffRecursively (renderToCDiff blobs)
|
||||
(ToCDiffRenderer, Just Language.Python) -> run (\ blob -> parse pythonParser blob >>= decorate (declarationAlgebra blob)) diffRecursively (renderToCDiff blobs)
|
||||
(ToCDiffRenderer, Just Language.TypeScript) -> run (\ blob -> parse typescriptParser blob >>= decorate (declarationAlgebra blob)) diffRecursively (renderToCDiff blobs)
|
||||
(ToCDiffRenderer, _) -> run (\ blob -> parse syntaxParser blob >>= decorate (syntaxDeclarationAlgebra blob)) diffTerms (renderToCDiff blobs)
|
||||
(JSONDiffRenderer, Just Language.Markdown) -> run (parse markdownParser) diffRecursively (renderJSONDiff blobs)
|
||||
@ -100,8 +100,11 @@ diffBlobPair renderer blobs = case (renderer, effectiveLanguage) of
|
||||
run :: Functor syntax => (Blob -> Task (Term syntax ann)) -> (Term syntax ann -> Term syntax ann -> Diff syntax ann ann) -> (Diff syntax ann ann -> output) -> Task output
|
||||
run parse diff renderer = distributeFor blobs parse >>= runBothWith (diffTermPair blobs diff) >>= render renderer
|
||||
|
||||
diffRecursively :: (Eq1 syntax, GAlign syntax, Show1 syntax, Traversable syntax, Diffable syntax) => Term syntax (Record fields1) -> Term syntax (Record fields2) -> Diff syntax (Record fields1) (Record fields2)
|
||||
diffRecursively = decoratingWith constructorNameAndConstantFields constructorNameAndConstantFields (diffTermsWith algorithmForTerms comparableByConstructor)
|
||||
diffRecursively :: (Declaration.Method :< fs, Declaration.Function :< fs, Apply Eq1 fs, Apply GAlign fs, Apply Show1 fs, Apply Foldable fs, Apply Functor fs, Apply Traversable fs, Apply Diffable fs)
|
||||
=> Term (Union fs) (Record fields1)
|
||||
-> Term (Union fs) (Record fields2)
|
||||
-> Diff (Union fs) (Record fields1) (Record fields2)
|
||||
diffRecursively = decoratingWith constructorNameAndConstantFields constructorNameAndConstantFields (diffTermsWith algorithmForTerms comparableByConstructor equivalentTerms)
|
||||
|
||||
-- | A task to diff a pair of 'Term's, producing insertion/deletion 'Patch'es for non-existent 'Blob's.
|
||||
diffTermPair :: Functor syntax => Both Blob -> Differ syntax ann1 ann2 -> Term syntax ann1 -> Term syntax ann2 -> Task (Diff syntax ann1 ann2)
|
||||
|
@ -41,7 +41,8 @@ diffWithParser :: (HasField fields Data.Span.Span,
|
||||
Apply Eq1 fs, Apply Show1 fs,
|
||||
Apply Traversable fs, Apply Functor fs,
|
||||
Apply Foldable fs, Apply Diffable fs,
|
||||
GAlign (Data.Union.Union fs)) =>
|
||||
Apply GAlign fs
|
||||
) =>
|
||||
Parser (Term (Data.Union.Union fs) (Record fields))
|
||||
-> Both Blob
|
||||
-> Task (Diff (Union fs) (Record (Maybe Declaration ': fields)) (Record (Maybe Declaration ': fields)))
|
||||
@ -49,6 +50,9 @@ diffWithParser parser = run (\ blob -> parse parser blob >>= decorate (declarati
|
||||
where
|
||||
run parse sourceBlobs = distributeFor sourceBlobs parse >>= runBothWith (diffTermPair sourceBlobs diffRecursively)
|
||||
|
||||
diffRecursively :: (Eq1 f, GAlign f, Show1 f, Traversable f, Diffable f) => Term f (Record fields) -> Term f (Record fields) -> Diff f (Record fields) (Record fields)
|
||||
diffRecursively = decoratingWith constructorNameAndConstantFields constructorNameAndConstantFields (diffTermsWith algorithmForTerms comparableByConstructor)
|
||||
diffRecursively :: (Declaration.Method :< fs, Declaration.Function :< fs, Apply Eq1 fs, Apply GAlign fs, Apply Show1 fs, Apply Foldable fs, Apply Functor fs, Apply Traversable fs, Apply Diffable fs)
|
||||
=> Term (Union fs) (Record fields1)
|
||||
-> Term (Union fs) (Record fields2)
|
||||
-> Diff (Union fs) (Record fields1) (Record fields2)
|
||||
diffRecursively = decoratingWith constructorNameAndConstantFields constructorNameAndConstantFields (diffTermsWith algorithmForTerms comparableByConstructor equivalentTerms)
|
||||
|
||||
|
@ -34,12 +34,12 @@ spec = parallel $ do
|
||||
\ (as, bs) -> let tas = decorate <$> (as :: [Term Syntax (Record '[Category])])
|
||||
tbs = decorate <$> (bs :: [Term Syntax (Record '[Category])])
|
||||
root = termIn (Program :. Nil) . Indexed
|
||||
diff = merge ((Program :. Nil, Program :. Nil)) (Indexed (stripDiff . diffThese <$> rws canCompare tas tbs)) in
|
||||
diff = merge ((Program :. Nil, Program :. Nil)) (Indexed (stripDiff . diffThese <$> rws canCompare (equalTerms canCompare) tas tbs)) in
|
||||
(beforeTerm diff, afterTerm diff) `shouldBe` (Just (root (stripTerm <$> tas)), Just (root (stripTerm <$> tbs)))
|
||||
|
||||
it "produces unbiased insertions within branches" $
|
||||
let (a, b) = (decorate (Term ((StringLiteral :. Nil) `In` Indexed [ Term ((StringLiteral :. Nil) `In` Leaf "a") ])), decorate (Term ((StringLiteral :. Nil) `In` Indexed [ Term ((StringLiteral :. Nil) `In` Leaf "b") ]))) in
|
||||
fmap (bimap stripTerm stripTerm) (rws canCompare [ b ] [ a, b ]) `shouldBe` fmap (bimap stripTerm stripTerm) [ That a, These b b ]
|
||||
fmap (bimap stripTerm stripTerm) (rws canCompare (equalTerms canCompare) [ b ] [ a, b ]) `shouldBe` fmap (bimap stripTerm stripTerm) [ That a, These b b ]
|
||||
|
||||
where canCompare a b = termAnnotation a == termAnnotation b
|
||||
|
||||
|
@ -1,18 +1,12 @@
|
||||
(Program
|
||||
{+(Annotation
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{+(Identifier)+})+}
|
||||
(Annotation
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{-(Identifier)-}
|
||||
(Identifier)
|
||||
{+(Identifier)+}
|
||||
(
|
||||
{ (Identifier)
|
||||
->(Identifier) }))
|
||||
|
@ -1,42 +1,42 @@
|
||||
(Program
|
||||
{+(Annotation
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{+(Identifier)+})+}
|
||||
(Annotation
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{+(Identifier)+}
|
||||
(Identifier)
|
||||
{-(Identifier)-}
|
||||
(
|
||||
{ (Identifier)
|
||||
->(Identifier) }))
|
||||
(Empty))
|
||||
(Identifier))
|
||||
(Annotation
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{+(Identifier)+}
|
||||
(
|
||||
{ (Identifier)
|
||||
->(Identifier) }))
|
||||
(Empty))
|
||||
(Identifier))
|
||||
{-(Annotation
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
{-(Identifier)-})-})
|
||||
{-(Identifier)-})-}
|
||||
(Annotation
|
||||
(Annotation
|
||||
(Function
|
||||
(Identifier)
|
||||
(
|
||||
{ (Identifier)
|
||||
->(Identifier) }))
|
||||
(Empty))
|
||||
(Identifier))
|
||||
(Annotation
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{-(Identifier)-}
|
||||
(
|
||||
{ (Identifier)
|
||||
->(Identifier) }))
|
||||
(Empty))
|
||||
(Identifier))
|
||||
{+(Annotation
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{+(Identifier)+})+})
|
||||
|
@ -1,21 +1,20 @@
|
||||
(Program
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
(
|
||||
(Identifier)))
|
||||
(Empty))
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
(Annotation
|
||||
(Function
|
||||
(Identifier)
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{ (Identifier)
|
||||
@ -27,23 +26,16 @@
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Annotation
|
||||
{+(Assignment
|
||||
{+(Identifier)+}
|
||||
{+(Integer)+})+}
|
||||
{+(Identifier)+})+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
@ -53,15 +45,18 @@
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(Annotation
|
||||
{-(Assignment
|
||||
{-(Identifier)-}
|
||||
{-(TextElement)-})-}
|
||||
{-(Identifier)-})-}
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-})
|
||||
(Annotation
|
||||
(Function
|
||||
(Identifier)
|
||||
(Annotation
|
||||
(Assignment
|
||||
(Identifier)
|
||||
{ (TextElement)
|
||||
->(Integer) })
|
||||
{ (Identifier)
|
||||
->(Identifier) })
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
(
|
||||
(Identifier)))
|
||||
(Empty)))
|
||||
|
@ -1,24 +1,29 @@
|
||||
(Program
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
(
|
||||
{+(Identifier)+}
|
||||
{-(Identifier)-}))
|
||||
(Empty))
|
||||
(Annotation
|
||||
(Function
|
||||
(Identifier)
|
||||
{+(Identifier)+}
|
||||
(
|
||||
{+(Identifier)+}
|
||||
{-(Identifier)-}))
|
||||
(Empty))
|
||||
(Annotation
|
||||
(Function
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
{+(Identifier)+}
|
||||
(
|
||||
{+(Identifier)+}
|
||||
{-(Identifier)-}))
|
||||
@ -32,40 +37,18 @@
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{+(Annotation
|
||||
{+(Function
|
||||
{+(Identifier)+}
|
||||
{+(Annotation
|
||||
{+(Assignment
|
||||
{+(Identifier)+}
|
||||
{+(TextElement)+})+}
|
||||
{+(Identifier)+})+}
|
||||
{+(Identifier)+}
|
||||
{+(
|
||||
{+(Identifier)+})+})+}
|
||||
{+(Empty)+})+}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-}
|
||||
{-(Annotation
|
||||
{-(Function
|
||||
{-(Identifier)-}
|
||||
{-(Annotation
|
||||
{-(Assignment
|
||||
{-(Identifier)-}
|
||||
{-(Integer)-})-}
|
||||
{-(Identifier)-})-}
|
||||
{-(Identifier)-}
|
||||
{-(
|
||||
{-(Identifier)-})-})-}
|
||||
{-(Empty)-})-})
|
||||
(Annotation
|
||||
(Function
|
||||
(Identifier)
|
||||
(Annotation
|
||||
(Assignment
|
||||
(Identifier)
|
||||
{ (Integer)
|
||||
->(TextElement) })
|
||||
{ (Identifier)
|
||||
->(Identifier) })
|
||||
{ (Identifier)
|
||||
->(Identifier) }
|
||||
(
|
||||
(Identifier)))
|
||||
(Empty)))
|
||||
|
Loading…
Reference in New Issue
Block a user