Skip to content

Commit

Permalink
fixed some more issues in tree diffing
Browse files Browse the repository at this point in the history
SQUASHED: AUTO-COMMIT-demos-tree-sitter-matches.md,AUTO-COMMIT-demos-zhangShashaMapping.md,AUTO-COMMIT-src-client-tree-sitter.js,AUTO-COMMIT-src-client-utils.js,AUTO-COMMIT-src-external-tree-edit-distance-zhang-shasha.js,
  • Loading branch information
JensLincke committed Oct 9, 2023
1 parent 9e03c4a commit 276f99d
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 8 deletions.
4 changes: 3 additions & 1 deletion demos/tree-sitter/matches.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
editor1.editor.on("change", (() => update()).debounce(500));
editor2.editor.on("change", (() => update()).debounce(500));


function update() {
vis.tree2 = parser.parse(editor2.value );
vis.tree1 = parser.parse(editor1.value);
vis.matches = match(vis.tree1.rootNode, vis.tree2.rootNode, 0, 100)

// lively.openInspector(vis.matches)

vis.update()
}

Expand Down
116 changes: 116 additions & 0 deletions demos/zhangShashaMapping.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# ZhangShasha Mapping

<script>

import { visit, Parser, JavaScript, addMapping} from 'src/client/tree-sitter.js';
import { mapping as zhangShashaMapping } from "src/external/tree-edit-distance/zhang-shasha.js"
import { qGramsDifference } from "utils"

let editor1 = await (<lively-code-mirror style="display:inline-block; width: 400px; height: 200px; border: 1px solid gray"></lively-code-mirror>)
let editor2 = await (<lively-code-mirror style="display:inline-block; width: 400px; height: 200px; border: 1px solid gray"></lively-code-mirror>)


var parser = new Parser();
parser.setLanguage(JavaScript);
var vis = await (<treesitter-matches></treesitter-matches>)

// editor1.value = `let a = 3 + 4`
editor1.value = `let a = 3`
// editor2.value = `let a = 3 + 4\na++`
editor2.value = `{let a = 2+4}`

editor1.editor.on("change", (() => update()).debounce(500));
editor2.editor.on("change", (() => update()).debounce(500));

let treedistMatrix = []
let operationsMatrix = []
let table = <table></table>
let operationsList = <div></div>


function update() {
vis.tree2 = parser.parse(editor2.value );
vis.tree1 = parser.parse(editor1.value);
var mappings = []

function label(node) {

if (node.children && node.children.length === 0) {
return node.text
}
return node.type
}



let zsMappings = zhangShashaMapping(vis.tree1.rootNode, vis.tree2.rootNode,
function children(node) { return node.children },
function insertCost() { return 1 },
function removeCost() { return 1 },
function updateCost(from, to) {


if (from.type === to.type) {
var cost = qGramsDifference(label(from), label(to), 2)
if (isNaN(cost)) {
throw new Error("qGramsDifference went wrong" )
}
return cost
} else {
return 1
}
}, function debugInfo(operations, treedist, LR_keyroots1, LR_keyroots2) {
debugger
operationsMatrix = operations
treedistMatrix = treedist
});
debugger

for (let candidate of zsMappings) {
if (candidate.t1 && candidate.t2) {
mappings.push({ node1: candidate.t1, node2: candidate.t2 })
}
}

vis.matches = mappings

// lively.openInspector(vis.matches)

table.textContent = ""



debugger
for(let i in treedistMatrix) {
let row = treedistMatrix[i]
let tr = <tr></tr>

for(let j in row) {
let ea = row[j]
let operations = operationsMatrix[i][j]
tr.appendChild(<td click={ () => {
operationsList.textContent = ""
operations.forEach(ea => operationsList.appendChild(<span style="padding:2px">{ea.type}</span>))
}}>{ea}</td>)
}
table.appendChild(tr)
}

vis.update()
}




update()

let pane = <div>
{editor1}{editor2}
{operationsList}
{table}
{vis}
</div>


pane
</script>
8 changes: 7 additions & 1 deletion src/client/tree-sitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ function lastChanceMatch(mappings, src, dst, maxSize) {
function removeCost() { return 1 },
function updateCost(from, to) {
if (from.type === to.type) {
return qGramsDifference(label(from), label(from), 2)
return qGramsDifference(label(from), label(to), 2)
} else {
return 1
}
Expand All @@ -365,6 +365,12 @@ export function hasMapping(mappings, t1, t2) {
export function addMapping(mappings, t1, t2) {
if (!t1) { throw new Error("t1 is null") }
if (!t2) { throw new Error("t2 is null") }


if (t1.type !== t2.type && t1.children.length > 0) {
debugger
throw new Error("mapping gone wrong?")
}
mappings.push({ node1: t1, node2: t2 })
}

Expand Down
3 changes: 3 additions & 0 deletions src/client/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,9 @@ export function qGramsDifference(str1, str2, q) {
const union = new Set([...qGrams1, ...qGrams2]);
const intersection = qGrams1.filter(item => qGrams2.includes(item));

if (union.size === 0) return 1


return (union.size - intersection.length) / union.size;
}

Expand Down
16 changes: 10 additions & 6 deletions src/external/tree-edit-distance/zhang-shasha.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,20 @@ var MATCH = 'match'
var REMOVE = 'remove'
var UPDATE = 'update'

export function distance(rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost ) {
return zhangShasha(false, rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost)
export function distance(rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost,debugInfo) {
return zhangShasha(false, rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost, debugInfo)
}

export function mapping(rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost ) {
return zhangShasha(true, rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost)
export function mapping(rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost, debugInfo) {
return zhangShasha(true, rootOfT1, rootOfT2, childrenOf, insertCost, removeCost, updateCost, debugInfo)
}

function zhangShasha(isMapping, rootOfT1, rootOfT2,
childrenOf=function(node) {return node.children},
insertCost=function() { return 1 },
removeCost=function() { return 1 },
updateCost=function (from, to) {return from.label === to.label ? 0 : 1}) {
updateCost=function (from, to) {return from.label === to.label ? 0 : 1},
debugInfo) {
// Paper: "Preprocessing"
var T1 = preprocess(rootOfT1, childrenOf)
var T2 = preprocess(rootOfT2, childrenOf)
Expand All @@ -54,7 +55,10 @@ function zhangShasha(isMapping, rootOfT1, rootOfT2,
compute_treedist(LR_keyroots1[iprime], LR_keyroots2[jprime])
}
}


if (debugInfo) debugInfo(operations, treedist)


if(isMapping) {
return operations[orderOfT1 - 1][orderOfT2 - 1].reverse()
} else {
Expand Down

0 comments on commit 276f99d

Please sign in to comment.