diff --git a/src/Arguments.hs b/src/Arguments.hs index 4cc0a8cda..96402da00 100644 --- a/src/Arguments.hs +++ b/src/Arguments.hs @@ -44,7 +44,7 @@ patchDiff :: DiffArguments' patchDiff = DiffArguments PatchRenderer identityDecorator jsonDiff :: DiffArguments' -jsonDiff = DiffArguments JSONDiffRenderer identityDecorator +jsonDiff = DiffArguments JSONDiffRenderer (const identifierDecorator) sExpressionDiff :: DiffArguments' sExpressionDiff = DiffArguments (SExpressionDiffRenderer TreeOnly) identityDecorator diff --git a/src/RWS.hs b/src/RWS.hs index ae6729002..0eec3c653 100644 --- a/src/RWS.hs +++ b/src/RWS.hs @@ -183,17 +183,16 @@ findNearestNeighbourTo editDistance canCompare kdTrees term@(UnmappedTerm j _ b) (previous, unmappedA, unmappedB) <- get fromMaybe (insertion previous unmappedA unmappedB term) $ do -- Look up the nearest unmapped term in `unmappedA`. - foundA@(UnmappedTerm i _ a) <- nearestUnmapped editDistance canCompare (IntMap.filterWithKey (\ k _ -> - isInMoveBounds previous k) - unmappedA) (Both.fst kdTrees) term + foundA@(UnmappedTerm i _ a) <- nearestUnmapped editDistance canCompare (termsWithinMoveBoundsFrom previous unmappedA) (Both.fst kdTrees) term -- Look up the nearest `foundA` in `unmappedB` - UnmappedTerm j' _ _ <- nearestUnmapped editDistance canCompare unmappedB (Both.snd kdTrees) foundA + UnmappedTerm j' _ _ <- nearestUnmapped editDistance canCompare (termsWithinMoveBoundsFrom (pred j) unmappedB) (Both.snd kdTrees) foundA -- Return Nothing if their indices don't match guard (j == j') guard (canCompare a b) pure $! do put (i, IntMap.delete i unmappedA, IntMap.delete j unmappedB) pure (These i j, These a b) + where termsWithinMoveBoundsFrom bound = IntMap.filterWithKey (\ k _ -> isInMoveBounds bound k) isInMoveBounds :: Int -> Int -> Bool isInMoveBounds previous i = previous < i && i < previous + defaultMoveBound @@ -391,4 +390,3 @@ instance Listable1 Gram where instance Listable a => Listable (Gram a) where tiers = tiers1 - diff --git a/src/Renderer.hs b/src/Renderer.hs index f73fc28d0..75c990c9d 100644 --- a/src/Renderer.hs +++ b/src/Renderer.hs @@ -1,10 +1,11 @@ -{-# LANGUAGE DataKinds, GADTs, MultiParamTypeClasses, TypeOperators #-} +{-# LANGUAGE DataKinds, GADTs, GeneralizedNewtypeDeriving, MultiParamTypeClasses, TypeOperators #-} module Renderer ( DiffRenderer(..) , SExpressionFormat(..) , resolveDiffRenderer , runDiffRenderer , declarationDecorator +, identifierDecorator , ParseTreeRenderer(..) , resolveParseTreeRenderer , runParseTreeRenderer @@ -51,15 +52,8 @@ runDiffRenderer = foldMap . uncurry . resolveDiffRenderer declarationDecorator :: Source -> Term (Syntax Text) (Record DefaultFields) -> Term (Syntax Text) (Record (Maybe Declaration ': DefaultFields)) declarationDecorator = decoratorWithAlgebra . declarationAlgebra - -data ParseTreeRenderer fields output where - SExpressionParseTreeRenderer :: (HasField fields Category, HasField fields SourceSpan) => SExpressionFormat -> ParseTreeRenderer fields ByteString - JSONParseTreeRenderer :: (ToJSONFields (Record fields), HasField fields Range) => ParseTreeRenderer fields [Value] - -resolveParseTreeRenderer :: (Monoid output, StringConv output ByteString) => ParseTreeRenderer fields output -> SourceBlob -> Term (Syntax Text) (Record fields) -> output -resolveParseTreeRenderer renderer blob = case renderer of - SExpressionParseTreeRenderer format -> R.sExpressionParseTree format blob - JSONParseTreeRenderer -> R.jsonFile blob . decoratorWithAlgebra identifierAlg +identifierDecorator :: Term (Syntax Text) (Record fields) -> Term (Syntax Text) (Record (Maybe Identifier ': fields)) +identifierDecorator = decoratorWithAlgebra identifierAlg where identifierAlg :: RAlgebra (CofreeF (Syntax Text) a) (Cofree (Syntax Text) a) (Maybe Identifier) identifierAlg (_ :< syntax) = case syntax of S.Assignment f _ -> identifier f @@ -78,9 +72,18 @@ resolveParseTreeRenderer renderer blob = case renderer of _ -> Nothing where identifier = fmap Identifier . extractLeafValue . unwrap . fst +data ParseTreeRenderer fields output where + SExpressionParseTreeRenderer :: (HasField fields Category, HasField fields SourceSpan) => SExpressionFormat -> ParseTreeRenderer fields ByteString + JSONParseTreeRenderer :: (ToJSONFields (Record fields), HasField fields Range) => ParseTreeRenderer fields [Value] + +resolveParseTreeRenderer :: (Monoid output, StringConv output ByteString) => ParseTreeRenderer fields output -> SourceBlob -> Term (Syntax Text) (Record fields) -> output +resolveParseTreeRenderer renderer blob = case renderer of + SExpressionParseTreeRenderer format -> R.sExpressionParseTree format blob + JSONParseTreeRenderer -> R.jsonFile blob . identifierDecorator + newtype Identifier = Identifier Text - deriving (Eq, Show) + deriving (Eq, NFData, Show) instance ToJSONFields Identifier where toJSONFields (Identifier i) = ["identifier" .= i] diff --git a/test/SemanticCmdLineSpec.hs b/test/SemanticCmdLineSpec.hs index f6265c6d5..c3364017e 100644 --- a/test/SemanticCmdLineSpec.hs +++ b/test/SemanticCmdLineSpec.hs @@ -76,8 +76,8 @@ instance Listable DiffFixture where patchOutput = "diff --git a/test/fixtures/ruby/method-declaration.A.rb b/test/fixtures/ruby/method-declaration.B.rb\nindex 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644\n--- a/test/fixtures/ruby/method-declaration.A.rb\n+++ b/test/fixtures/ruby/method-declaration.B.rb\n@@ -1,3 +1,4 @@\n-def foo\n+def bar(a)\n+ baz\n end\n\n" patchOutput' = "diff --git a/methods.rb b/methods.rb\nnew file mode 100644\nindex 0000000000000000000000000000000000000000..ff7bbbe9495f61d9e1e58c597502d152bab1761e\n--- /dev/null\n+++ b/methods.rb\n+def foo\n+end\n\n" - jsonOutput = "{\"diff\":{\"after\":{\"category\":\"Program\",\"sourceRange\":[0,21],\"sourceSpan\":{\"start\":[1,1],\"end\":[4,1]}},\"children\":[{\"after\":{\"category\":\"Method\",\"sourceRange\":[0,20],\"sourceSpan\":{\"start\":[1,1],\"end\":[3,4]}},\"children\":[{\"replace\":[{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[4,7],\"sourceSpan\":{\"start\":[1,5],\"end\":[1,8]}},{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[4,7],\"sourceSpan\":{\"start\":[1,5],\"end\":[1,8]}}]},{\"insert\":{\"category\":\"Params\",\"children\":[{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[8,9],\"sourceSpan\":{\"start\":[1,9],\"end\":[1,10]}}],\"sourceRange\":[7,13],\"sourceSpan\":{\"start\":[1,8],\"end\":[2,3]}}},{\"insert\":{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[13,16],\"sourceSpan\":{\"start\":[2,3],\"end\":[2,6]}}}],\"before\":{\"category\":\"Method\",\"sourceRange\":[0,11],\"sourceSpan\":{\"start\":[1,1],\"end\":[2,4]}}}],\"before\":{\"category\":\"Program\",\"sourceRange\":[0,12],\"sourceSpan\":{\"start\":[1,1],\"end\":[3,1]}}},\"oids\":[\"0000000000000000000000000000000000000000\",\"0000000000000000000000000000000000000000\"],\"paths\":[\"test/fixtures/ruby/method-declaration.A.rb\",\"test/fixtures/ruby/method-declaration.B.rb\"]}\n" - jsonOutput' = "{\"diff\":{\"insert\":{\"category\":\"Program\",\"children\":[{\"category\":\"Method\",\"children\":[{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[4,7],\"sourceSpan\":{\"start\":[1,5],\"end\":[1,8]}}],\"sourceRange\":[0,11],\"sourceSpan\":{\"start\":[1,1],\"end\":[2,4]}}],\"sourceRange\":[0,12],\"sourceSpan\":{\"start\":[1,1],\"end\":[3,1]}}},\"oids\":[\"0000000000000000000000000000000000000000\",\"ff7bbbe9495f61d9e1e58c597502d152bab1761e\"],\"paths\":[\"methods.rb\",\"methods.rb\"]}\n" + jsonOutput = "{\"diff\":{\"after\":{\"category\":\"Program\",\"sourceRange\":[0,21],\"sourceSpan\":{\"start\":[1,1],\"end\":[4,1]}},\"children\":[{\"after\":{\"category\":\"Method\",\"identifier\":\"bar\",\"sourceRange\":[0,20],\"sourceSpan\":{\"start\":[1,1],\"end\":[3,4]}},\"children\":[{\"replace\":[{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[4,7],\"sourceSpan\":{\"start\":[1,5],\"end\":[1,8]}},{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[4,7],\"sourceSpan\":{\"start\":[1,5],\"end\":[1,8]}}]},{\"insert\":{\"category\":\"Params\",\"children\":[{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[8,9],\"sourceSpan\":{\"start\":[1,9],\"end\":[1,10]}}],\"sourceRange\":[7,13],\"sourceSpan\":{\"start\":[1,8],\"end\":[2,3]}}},{\"insert\":{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[13,16],\"sourceSpan\":{\"start\":[2,3],\"end\":[2,6]}}}],\"before\":{\"category\":\"Method\",\"identifier\":\"foo\",\"sourceRange\":[0,11],\"sourceSpan\":{\"start\":[1,1],\"end\":[2,4]}}}],\"before\":{\"category\":\"Program\",\"sourceRange\":[0,12],\"sourceSpan\":{\"start\":[1,1],\"end\":[3,1]}}},\"oids\":[\"0000000000000000000000000000000000000000\",\"0000000000000000000000000000000000000000\"],\"paths\":[\"test/fixtures/ruby/method-declaration.A.rb\",\"test/fixtures/ruby/method-declaration.B.rb\"]}\n" + jsonOutput' = "{\"diff\":{\"insert\":{\"category\":\"Program\",\"children\":[{\"category\":\"Method\",\"children\":[{\"category\":\"Identifier\",\"children\":[],\"sourceRange\":[4,7],\"sourceSpan\":{\"start\":[1,5],\"end\":[1,8]}}],\"identifier\":\"foo\",\"sourceRange\":[0,11],\"sourceSpan\":{\"start\":[1,1],\"end\":[2,4]}}],\"sourceRange\":[0,12],\"sourceSpan\":{\"start\":[1,1],\"end\":[3,1]}}},\"oids\":[\"0000000000000000000000000000000000000000\",\"ff7bbbe9495f61d9e1e58c597502d152bab1761e\"],\"paths\":[\"methods.rb\",\"methods.rb\"]}\n" sExpressionOutput = "(Program\n (Method\n { (Identifier)\n ->(Identifier) }\n {+(Params\n (Identifier))+}\n {+(Identifier)+}))\n" sExpressionOutput' = "{+(Program\n (Method\n (Identifier)))+}\n" tocOutput = "{\"changes\":{\"test/fixtures/ruby/method-declaration.A.rb -> test/fixtures/ruby/method-declaration.B.rb\":[{\"span\":{\"start\":[1,1],\"end\":[3,4]},\"category\":\"Method\",\"term\":\"bar\",\"changeType\":\"modified\"}]},\"errors\":{}}\n" diff --git a/test/fixtures/go/channel-types.diffB-A.txt b/test/fixtures/go/channel-types.diffB-A.txt index 4d50123c4..6351b17e3 100644 --- a/test/fixtures/go/channel-types.diffB-A.txt +++ b/test/fixtures/go/channel-types.diffB-A.txt @@ -5,25 +5,23 @@ (Identifier) (Args) (Other "type_declaration" - {+(TypeDecl - (Identifier) - (ChannelTy - (ChannelTy - (Identifier))))+} (TypeDecl - (Identifier) + { (Identifier) + ->(Identifier) } (ChannelTy (ChannelTy { (Identifier) - ->(StructTy) }))) - (TypeDecl - (Identifier) - (ChannelTy - (ChannelTy - { (StructTy) ->(Identifier) }))) - {-(TypeDecl - (Identifier) + (TypeDecl + { (Identifier) + ->(Identifier) } (ChannelTy (ChannelTy - (Identifier))))-}))) + (StructTy)))) + (TypeDecl + { (Identifier) + ->(Identifier) } + (ChannelTy + (ChannelTy + { (Identifier) + ->(Identifier) })))))) diff --git a/test/fixtures/go/for-statements.diffA-B.txt b/test/fixtures/go/for-statements.diffA-B.txt index eac2d39fe..d31a354b6 100644 --- a/test/fixtures/go/for-statements.diffA-B.txt +++ b/test/fixtures/go/for-statements.diffA-B.txt @@ -4,11 +4,15 @@ (Function (Identifier) (Args) - {+(For - (FunctionCall - (Identifier)) - (Other "goto_statement" - (Identifier)))+} + { (For + (ExpressionStatements + (FunctionCall + (Identifier) + )(Other"goto_statement"(Identifier)))) + ->(For + (FunctionCall + (Identifier)) + (Other"goto_statement"(Identifier))) } {+(For (Other "expression_list" (Identifier)) @@ -30,14 +34,12 @@ (FunctionCall (Identifier)) (Continue))+} - (For + {+(For (ExpressionStatements (FunctionCall (Identifier) - {+(Identifier)+}) - {+(Break)+} - {-(Other "goto_statement" - (Identifier))-})) + (Identifier)) + (Break)))+} {-(For (VarDecl (Other "expression_list" diff --git a/test/fixtures/go/for-statements.diffB-A.txt b/test/fixtures/go/for-statements.diffB-A.txt index 988fcb0e1..7e5293744 100644 --- a/test/fixtures/go/for-statements.diffB-A.txt +++ b/test/fixtures/go/for-statements.diffB-A.txt @@ -4,12 +4,15 @@ (Function (Identifier) (Args) - {+(For + { (For + (FunctionCall + (Identifier)) + (Other"goto_statement"(Identifier))) + ->(For (ExpressionStatements (FunctionCall - (Identifier)) - (Other "goto_statement" - (Identifier))))+} + (Identifier) + )(Other"goto_statement"(Identifier)))) } {+(For (VarDecl (Other "expression_list" @@ -33,20 +36,18 @@ (Identifier)) (Continue (Identifier)))+} - (For + {+(For (FunctionCall (Identifier)) - { (Other "goto_statement" - (Identifier)) - ->(Continue) }) - (For - (Other "expression_list" - (Identifier)) + (Continue))+} + (For + (Other "expression_list" + (Identifier)) + (Identifier) + (FunctionCall (Identifier) - (FunctionCall - (Identifier) {+(Identifier)+}) - (Break + (Break {-(Identifier)-})) {-(For (FunctionCall @@ -66,4 +67,4 @@ (FunctionCall (Identifier) (Identifier)) - (Break)))-})) + (Break)))-})) diff --git a/test/fixtures/go/map-literals.diffA-B.txt b/test/fixtures/go/map-literals.diffA-B.txt index ef9322ed7..afe4be4e5 100644 --- a/test/fixtures/go/map-literals.diffA-B.txt +++ b/test/fixtures/go/map-literals.diffA-B.txt @@ -14,13 +14,13 @@ (Identifier) { (Identifier) ->(Identifier) }) - {+(Pair - (StringLiteral) - (StringLiteral))+} (Pair { (StringLiteral) ->(StringLiteral) } - (StringLiteral)) - {-(Pair - (StringLiteral) - (StringLiteral))-})))))) + { (StringLiteral) + ->(StringLiteral) }) + (Pair + { (StringLiteral) + ->(StringLiteral) } + { (StringLiteral) + ->(StringLiteral) }))))))) diff --git a/test/fixtures/go/parameter-declarations-with-types.diffB-A.txt b/test/fixtures/go/parameter-declarations-with-types.diffB-A.txt index 1b6fb7dfa..5fba968be 100644 --- a/test/fixtures/go/parameter-declarations-with-types.diffB-A.txt +++ b/test/fixtures/go/parameter-declarations-with-types.diffB-A.txt @@ -7,13 +7,13 @@ (Function (Identifier) (Args - {+(ParameterDecl - (Identifier) - (Identifier))+} (ParameterDecl - (Identifier) + { (Identifier) + ->(Identifier) } { (Identifier) ->(Identifier) }) - {-(ParameterDecl - (Identifier) - (Identifier))-}))) + (ParameterDecl + { (Identifier) + ->(Identifier) } + { (Identifier) + ->(Identifier) })))) diff --git a/test/fixtures/javascript/export.diffA-B.txt b/test/fixtures/javascript/export.diffA-B.txt index f863d867f..1ae760377 100644 --- a/test/fixtures/javascript/export.diffA-B.txt +++ b/test/fixtures/javascript/export.diffA-B.txt @@ -12,68 +12,54 @@ (Other "export_specifier" { (Identifier) ->(Identifier) })) -{+(Export - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier)))+} -{+(Export + (Export + (Other "export_specifier" + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) + (Other "export_specifier" + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) + (Other "export_specifier" + { (Identifier) + ->(Identifier)})) +(Export (VarDecl - (Identifier)) + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)) + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)))+} -{+(Export + { (Identifier) + ->(Identifier)})) +(Export (VarAssignment - (Identifier) - (Identifier)) + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) (VarAssignment - (Identifier) - (Identifier)) + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)) + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)))+} -{+(Export - (Identifier))+} + { (Identifier) + ->(Identifier)})) +(Export +{ (Identifier) +->(Identifier)}) {+(Export (Function (Identifier) (Params)))+} -{-(Export - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier)))-} -{-(Export - (VarDecl - (Identifier)) - (VarDecl - (Identifier)) - (VarDecl - (Identifier)))-} -{-(Export - (VarAssignment - (Identifier) - (Identifier)) - (VarAssignment - (Identifier) - (Identifier)) - (VarDecl - (Identifier)) - (VarDecl - (Identifier)))-} -{-(Export - (Identifier))-} (Export (Function (Params))) diff --git a/test/fixtures/javascript/export.diffB-A.txt b/test/fixtures/javascript/export.diffB-A.txt index d699d6ec5..4f82be907 100644 --- a/test/fixtures/javascript/export.diffB-A.txt +++ b/test/fixtures/javascript/export.diffB-A.txt @@ -63,16 +63,17 @@ (Export (Function (Params))) -{+(Export - (Function - (Identifier) - (Params)))+} (Export + {+(Function + (Identifier) + (Params))+} + {-(Other "export_specifier" + (Identifier) + (Identifier))-}) + {+(Export (Other "export_specifier" - { (Identifier) - ->(Identifier) } - { (Identifier) - ->(Identifier) })) + (Identifier) + (Identifier)))+} (Export { (StringLiteral) ->(StringLiteral) }) diff --git a/test/fixtures/typescript/export.diffA-B.txt b/test/fixtures/typescript/export.diffA-B.txt index f863d867f..1ae760377 100644 --- a/test/fixtures/typescript/export.diffA-B.txt +++ b/test/fixtures/typescript/export.diffA-B.txt @@ -12,68 +12,54 @@ (Other "export_specifier" { (Identifier) ->(Identifier) })) -{+(Export - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier)))+} -{+(Export + (Export + (Other "export_specifier" + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) + (Other "export_specifier" + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) + (Other "export_specifier" + { (Identifier) + ->(Identifier)})) +(Export (VarDecl - (Identifier)) + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)) + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)))+} -{+(Export + { (Identifier) + ->(Identifier)})) +(Export (VarAssignment - (Identifier) - (Identifier)) + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) (VarAssignment - (Identifier) - (Identifier)) + { (Identifier) + ->(Identifier)} + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)) + { (Identifier) + ->(Identifier)}) (VarDecl - (Identifier)))+} -{+(Export - (Identifier))+} + { (Identifier) + ->(Identifier)})) +(Export +{ (Identifier) +->(Identifier)}) {+(Export (Function (Identifier) (Params)))+} -{-(Export - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier) - (Identifier)) - (Other "export_specifier" - (Identifier)))-} -{-(Export - (VarDecl - (Identifier)) - (VarDecl - (Identifier)) - (VarDecl - (Identifier)))-} -{-(Export - (VarAssignment - (Identifier) - (Identifier)) - (VarAssignment - (Identifier) - (Identifier)) - (VarDecl - (Identifier)) - (VarDecl - (Identifier)))-} -{-(Export - (Identifier))-} (Export (Function (Params))) diff --git a/test/fixtures/typescript/export.diffB-A.txt b/test/fixtures/typescript/export.diffB-A.txt index d699d6ec5..4f82be907 100644 --- a/test/fixtures/typescript/export.diffB-A.txt +++ b/test/fixtures/typescript/export.diffB-A.txt @@ -63,16 +63,17 @@ (Export (Function (Params))) -{+(Export - (Function - (Identifier) - (Params)))+} (Export + {+(Function + (Identifier) + (Params))+} + {-(Other "export_specifier" + (Identifier) + (Identifier))-}) + {+(Export (Other "export_specifier" - { (Identifier) - ->(Identifier) } - { (Identifier) - ->(Identifier) })) + (Identifier) + (Identifier)))+} (Export { (StringLiteral) ->(StringLiteral) })