summaryrefslogtreecommitdiffstats
path: root/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
diff options
context:
space:
mode:
authorJohannes Altmanninger <aclopte@gmail.com>2017-08-20 12:09:07 +0000
committerJohannes Altmanninger <aclopte@gmail.com>2017-08-20 12:09:07 +0000
commitd196930799224f906ba4c5d3c64bafa1cad8d156 (patch)
tree1734d5463a02b3d25c6a372c7d3f9ba78dc4f3e8 /clang/lib/Tooling/ASTDiff/ASTDiff.cpp
parent6c9ce223ea0cd092ffbe0a913a5796b0c40be1f4 (diff)
downloadbcm5719-llvm-d196930799224f906ba4c5d3c64bafa1cad8d156.tar.gz
bcm5719-llvm-d196930799224f906ba4c5d3c64bafa1cad8d156.zip
[clang-diff] Fix similarity computation
Summary: Add separate tests for the top-down and the bottom-up phase, as well as one for the optimal matching. Reviewers: arphaman Subscribers: klimek Differential Revision: https://reviews.llvm.org/D36185 llvm-svn: 311284
Diffstat (limited to 'clang/lib/Tooling/ASTDiff/ASTDiff.cpp')
-rw-r--r--clang/lib/Tooling/ASTDiff/ASTDiff.cpp35
1 files changed, 22 insertions, 13 deletions
diff --git a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
index ada7cbcfc55..22f3a4e4f06 100644
--- a/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
+++ b/clang/lib/Tooling/ASTDiff/ASTDiff.cpp
@@ -92,7 +92,7 @@ private:
// Computes the ratio of common descendants between the two nodes.
// Descendants are only considered to be equal when they are mapped in M.
- double getSimilarity(const Mapping &M, NodeId Id1, NodeId Id2) const;
+ double getJaccardSimilarity(const Mapping &M, NodeId Id1, NodeId Id2) const;
// Returns the node that has the highest degree of similarity.
NodeId findCandidate(const Mapping &M, NodeId Id1) const;
@@ -714,8 +714,8 @@ bool ASTDiff::Impl::haveSameParents(const Mapping &M, NodeId Id1,
void ASTDiff::Impl::addOptimalMapping(Mapping &M, NodeId Id1,
NodeId Id2) const {
- if (std::max(T1.getNumberOfDescendants(Id1),
- T2.getNumberOfDescendants(Id2)) >= Options.MaxSize)
+ if (std::max(T1.getNumberOfDescendants(Id1), T2.getNumberOfDescendants(Id2)) >
+ Options.MaxSize)
return;
ZhangShashaMatcher Matcher(*this, T1, T2, Id1, Id2);
std::vector<std::pair<NodeId, NodeId>> R = Matcher.getMatchingNodes();
@@ -727,16 +727,23 @@ void ASTDiff::Impl::addOptimalMapping(Mapping &M, NodeId Id1,
}
}
-double ASTDiff::Impl::getSimilarity(const Mapping &M, NodeId Id1,
- NodeId Id2) const {
- if (Id1.isInvalid() || Id2.isInvalid())
- return 0.0;
+double ASTDiff::Impl::getJaccardSimilarity(const Mapping &M, NodeId Id1,
+ NodeId Id2) const {
int CommonDescendants = 0;
const Node &N1 = T1.getNode(Id1);
- for (NodeId Id = Id1 + 1; Id <= N1.RightMostDescendant; ++Id)
- CommonDescendants += int(T2.isInSubtree(M.getDst(Id), Id2));
- return 2.0 * CommonDescendants /
- (T1.getNumberOfDescendants(Id1) + T2.getNumberOfDescendants(Id2));
+ // Count the common descendants, excluding the subtree root.
+ for (NodeId Src = Id1 + 1; Src <= N1.RightMostDescendant; ++Src) {
+ NodeId Dst = M.getDst(Src);
+ CommonDescendants += int(Dst.isValid() && T2.isInSubtree(Dst, Id2));
+ }
+ // We need to subtract 1 to get the number of descendants excluding the root.
+ double Denominator = T1.getNumberOfDescendants(Id1) - 1 +
+ T2.getNumberOfDescendants(Id2) - 1 - CommonDescendants;
+ // CommonDescendants is less than the size of one subtree.
+ assert(Denominator >= 0 && "Expected non-negative denominator.");
+ if (Denominator == 0)
+ return 0;
+ return CommonDescendants / Denominator;
}
NodeId ASTDiff::Impl::findCandidate(const Mapping &M, NodeId Id1) const {
@@ -747,7 +754,7 @@ NodeId ASTDiff::Impl::findCandidate(const Mapping &M, NodeId Id1) const {
continue;
if (M.hasDst(Id2))
continue;
- double Similarity = getSimilarity(M, Id1, Id2);
+ double Similarity = getJaccardSimilarity(M, Id1, Id2);
if (Similarity >= Options.MinSimilarity && Similarity > HighestSimilarity) {
HighestSimilarity = Similarity;
Candidate = Id2;
@@ -767,8 +774,8 @@ void ASTDiff::Impl::matchBottomUp(Mapping &M) const {
}
break;
}
- const Node &N1 = T1.getNode(Id1);
bool Matched = M.hasSrc(Id1);
+ const Node &N1 = T1.getNode(Id1);
bool MatchedChildren =
std::any_of(N1.Children.begin(), N1.Children.end(),
[&](NodeId Child) { return M.hasSrc(Child); });
@@ -836,6 +843,8 @@ ASTDiff::Impl::Impl(SyntaxTree::Impl &T1, SyntaxTree::Impl &T2,
void ASTDiff::Impl::computeMapping() {
TheMapping = matchTopDown();
+ if (Options.StopAfterTopDown)
+ return;
matchBottomUp(TheMapping);
}
OpenPOWER on IntegriCloud