@@ -35,6 +35,7 @@ import LexerModelicaDiff.{Token,TokenId,tokenContent,printToken,modelicaDiffToke
3535
3636protected
3737
38+ import AvlSetString ;
3839import DiffAlgorithm ;
3940import DiffAlgorithm . {diff,Diff };
4041import Error ;
@@ -99,6 +100,7 @@ algorithm
99100 end match;
100101 t2_updated := moveComments(t1, t2_updated);
101102 res := treeDiffWork1(t1, t2_updated, nTokens);
103+ res := moveCommentsAfterDiff(res);
102104end treeDiff;
103105
104106partial function CmpParseTreeFunc
@@ -1543,6 +1545,193 @@ algorithm
15431545 end for ;
15441546end moveComments;
15451547
1548+ function moveCommentsAfterDiff
1549+ input output list< tuple< Diff ,list< ParseTree >>> res;
1550+ protected
1551+ list< tuple< Token , list< ParseTree > , String >> c1, c2, remaining;
1552+ Token tok;
1553+ String foundComment;
1554+ ParseTree tree, foundTree;
1555+ list< ParseTree > trees, before, after, acc2;
1556+ AvlSetString . Tree comments;
1557+ list< tuple< Diff ,list< ParseTree >>> acc, lst;
1558+ tuple< Diff ,list< ParseTree >> diff;
1559+ Boolean found;
1560+ algorithm
1561+ // O(N*D); scales with number of diffs since we restart whenever we move a comment
1562+ comments := findAddedComments(res);
1563+ acc := {};
1564+ lst := res;
1565+ if AvlSetString . isEmpty(comments) then
1566+ return ;
1567+ end if ;
1568+ while not listEmpty(lst) loop
1569+ diff::lst := lst;
1570+ _ := match diff
1571+ case (Diff . Delete , trees)
1572+ algorithm
1573+ acc2 := {};
1574+ while not listEmpty(trees) loop
1575+ tree::trees := trees;
1576+ (found,before,foundTree,after,foundComment) := fixDeletedComments(tree, comments);
1577+ if found then
1578+ acc := (Diff . Add , listAppend(listReverse(acc2),before))::acc;
1579+ res := listAppend(listReverse(acc),(Diff . Equal ,{foundTree})::(Diff . Add , listAppend(after, trees))::lst);
1580+ res := removeAddedCommentFromDiff(res, foundComment);
1581+ // Continue until we can't fix more comments
1582+ res := moveCommentsAfterDiff(res);
1583+ return ;
1584+ end if ;
1585+ acc2 := tree::acc2;
1586+ end while ;
1587+ then ();
1588+ else ();
1589+ end match;
1590+ acc := diff::acc;
1591+ end while ;
1592+ end moveCommentsAfterDiff;
1593+
1594+ function findAddedComments
1595+ input list< tuple< Diff ,list< ParseTree >>> tree;
1596+ output AvlSetString . Tree comments = AvlSetString . EMPTY ();
1597+ protected
1598+ list< ParseTree > addedTrees;
1599+ algorithm
1600+ (addedTrees,) := extractAdditionsDeletions(tree);
1601+ for t in addedTrees loop
1602+ comments := findAddedComments2(t, comments);
1603+ end for ;
1604+ end findAddedComments;
1605+
1606+ function findAddedComments2
1607+ input ParseTree tree;
1608+ input output AvlSetString . Tree comments;
1609+ protected
1610+ list< ParseTree > nodes;
1611+ Token tok;
1612+ algorithm
1613+ comments := match tree
1614+ case LEAF () guard parseTreeIsComment(tree) then AvlSetString . add(comments, tokenContent(tree. token));
1615+ case NODE (nodes= nodes)
1616+ algorithm
1617+ for n in nodes loop
1618+ comments := findAddedComments2(n, comments);
1619+ end for ;
1620+ then comments;
1621+ else comments;
1622+ end match;
1623+ end findAddedComments2;
1624+
1625+ function removeAddedCommentFromDiff
1626+ input output list< tuple< Diff ,list< ParseTree >>> tree;
1627+ input String comment;
1628+ protected
1629+ list< tuple< Diff ,list< ParseTree >>> acc, lst;
1630+ tuple< Diff ,list< ParseTree >> diff;
1631+ list< ParseTree > lst2;
1632+ Boolean b;
1633+ algorithm
1634+ lst := tree;
1635+ acc := {};
1636+ while not listEmpty(lst) loop
1637+ diff::lst := lst;
1638+ _ := match diff
1639+ case (Diff . Add ,lst2)
1640+ algorithm
1641+ (b,lst2) := removeAddedCommentFromDiff2(lst2, comment);
1642+ if b then
1643+ tree := listAppend(listReverse(acc),(Diff . Add ,lst2)::lst);
1644+ return ;
1645+ end if ;
1646+ then ();
1647+ else ();
1648+ end match;
1649+ acc := diff::acc;
1650+ end while ;
1651+ Error . addInternalError("Failed to remove comment `" + comment+ "` from diff; but we know it is in there somewhere" , sourceInfo());
1652+ end removeAddedCommentFromDiff;
1653+
1654+ function removeAddedCommentFromDiff2
1655+ output Boolean removed= false ;
1656+ input output list< ParseTree > trees;
1657+ input String comment;
1658+ protected
1659+ list< ParseTree > acc, lst, nodes;
1660+ ParseTree tree;
1661+ String content;
1662+ algorithm
1663+ acc := {};
1664+ lst := trees;
1665+ while not listEmpty(lst) loop
1666+ tree::lst := lst;
1667+ (removed, tree) := match tree
1668+ case LEAF () guard parseTreeIsComment(tree)
1669+ algorithm
1670+ content := tokenContent(tree. token);
1671+ then (content== comment, if content== comment then EMPTY () else tree);
1672+ case NODE (nodes= nodes)
1673+ algorithm
1674+ (removed, nodes) := removeAddedCommentFromDiff2(nodes, comment);
1675+ if removed then
1676+ tree. nodes := nodes;
1677+ end if ;
1678+ then (removed, tree);
1679+ else (false , tree);
1680+ end match;
1681+ if removed then
1682+ lst := if isEmpty(tree) then lst else (tree::lst);
1683+ lst := listAppend(listReverse(acc), lst);
1684+ trees := lst;
1685+ return ;
1686+ end if ;
1687+ acc := tree::acc;
1688+ end while ;
1689+ end removeAddedCommentFromDiff2;
1690+
1691+ function fixDeletedComments
1692+ input ParseTree tree;
1693+ input AvlSetString . Tree addedComments;
1694+ output Boolean found = false ;
1695+ output list< ParseTree > before = {};
1696+ output ParseTree foundTree = tree;
1697+ output list< ParseTree > after = {};
1698+ output String foundComment = "" ;
1699+ protected
1700+ list< ParseTree > nodes, before2, after2;
1701+ Boolean b;
1702+ ParseTree t;
1703+ String content;
1704+ algorithm
1705+ found := match tree
1706+ case LEAF () guard parseTreeIsComment(tree)
1707+ algorithm
1708+ content := tokenContent(tree. token);
1709+ b := AvlSetString . hasKey(addedComments, content);
1710+ if b then
1711+ foundComment := content;
1712+ end if ;
1713+ then b;
1714+ case NODE (nodes= nodes)
1715+ algorithm
1716+ while not listEmpty(nodes) loop
1717+ t::nodes := nodes;
1718+ (found, before2, foundTree, after2, foundComment) := fixDeletedComments(t, addedComments);
1719+ if found then
1720+ before := listAppend(listReverse(before), before2);
1721+ after := listAppend(after2, nodes);
1722+ return ;
1723+ end if ;
1724+ before := t::before;
1725+ end while ;
1726+ before := {};
1727+ foundTree := tree;
1728+ after := {};
1729+ foundComment := "" ;
1730+ then false ;
1731+ else false ;
1732+ end match;
1733+ end fixDeletedComments;
1734+
15461735function addCommentAtLabelPath
15471736 input output list< ParseTree > tree;
15481737 input Token tok;
0 commit comments