private boolean isEquivalent(IMethod method, IMethod otherMethod, Optional<IProgressMonitor> monitor) throws JavaModelException { monitor.ifPresent(m -> m.beginTask("Checking method equivalence ...", 2)); MethodDeclaration methodDeclaration = this.getMethodDeclaration(method, monitor.map(m -> new SubProgressMonitor(m, 1))); MethodDeclaration otherMethodDeclaration = this.getMethodDeclaration(otherMethod, monitor.map(m -> new SubProgressMonitor(m, 1))); monitor.ifPresent(IProgressMonitor::done); Block methodDeclarationBody = methodDeclaration.getBody(); Block otherMethodDeclarationBody = otherMethodDeclaration.getBody(); boolean match = methodDeclarationBody.subtreeMatch(new ASTMatcher(), otherMethodDeclarationBody); return match; }
public StableNodeBasedRegionUpdater(ReplaceEdit originalEdit, ReferenceUpdater referenceUpdater, N originalNode, ASTMatcher matcher) throws RefactoringException { super(originalEdit, referenceUpdater); this.originalNode = originalNode; this.matcher = matcher; // Look for a stable node StableBindingResolver stableBindingResolver = new StableBindingResolver( originalNode); if (stableBindingResolver.resolve()) { // Found one! isCompilationUnitTheStableNode = false; originalStableNode = stableBindingResolver.getStableNode(); originalStableBindingKey = stableBindingResolver.getStableBinding().getKey(); } else { // In some cases (like an import declaration), there isn't a stable // binding // node we can use, so instead we use the compilation unit isCompilationUnitTheStableNode = true; originalStableNode = originalNode.getRoot(); originalStableBindingKey = null; } }
/** * Creates a new region updater for the given text edit contained within the * given node. * * @param originalEdit the text edit * @param node the most-specific node that contains the text edit * @param referenceUpdater an reference updater knowledgeable about the * refactoring that is taking place * @param matcher an AST matcher knowledgeable about refactoring that is * taking place * @return a region updater instance for the given text edit * @throws RefactoringException if there was an error creating a region * updater */ public static RegionUpdater newRegionUpdater(ReplaceEdit originalEdit, ASTNode node, ReferenceUpdater referenceUpdater, ASTMatcher matcher) throws RefactoringException { if (node instanceof Name) { return new NameRegionUpdater(originalEdit, referenceUpdater, (Name) node, matcher); } else if (node instanceof TextElement) { return new TextElementRegionUpdater(originalEdit, referenceUpdater, (TextElement) node, matcher); } throw new RefactoringException("This AST node type is not supported"); }
/** * Determines if given method exists in a given list * * @param list list of method to search through * @param method method to find * @return declaration of method from the list that has the same name and parameter types, or * null if not found */ protected BodyDeclaration findMethodToReplace(final List<BodyDeclaration> list, MethodDeclaration method) { for (final Iterator<BodyDeclaration> iterator= list.iterator(); iterator.hasNext();) { final BodyDeclaration bodyDecl= iterator.next(); if (bodyDecl instanceof MethodDeclaration) { final MethodDeclaration method2= (MethodDeclaration)bodyDecl; if (method2.getName().getIdentifier().equals(method.getName().getIdentifier()) && method2.parameters().size() == method.parameters().size()) { Iterator<SingleVariableDeclaration> iterator1= method.parameters().iterator(); Iterator<SingleVariableDeclaration> iterator2= method2.parameters().iterator(); boolean ok= true; while (iterator1.hasNext()) { if (!iterator1.next().getType().subtreeMatch(new ASTMatcher(), iterator2.next().getType())) { ok= false; break; } } if (ok) return method2; } } } return null; }
private static String getArgumentName(List<Expression> arguments, int index) { String def= String.valueOf(index + 1); ASTNode expr= arguments.get(index); if (expr.getLength() > 18) { return def; } ASTMatcher matcher= new ASTMatcher(); for (int i= 0; i < arguments.size(); i++) { if (i != index && matcher.safeSubtreeMatch(expr, arguments.get(i))) { return def; } } return '\'' + BasicElementLabels.getJavaElementName(ASTNodes.asString(expr)) + '\''; }
private static String getArgumentName(List<Expression> arguments, int index) { String def = String.valueOf(index + 1); ASTNode expr = arguments.get(index); if (expr.getLength() > 18) { return def; } ASTMatcher matcher = new ASTMatcher(); for (int i = 0; i < arguments.size(); i++) { if (i != index && matcher.safeSubtreeMatch(expr, arguments.get(i))) { return def; } } return '\'' + BasicElementLabels.getJavaElementName(ASTNodes.asString(expr)) + '\''; }
/** * Calculates the edit distance between two argument lists. */ public static int editDistance(List<SingleVariableDeclaration> params, List<SingleVariableDeclaration> peerParams) { ASTMatcher matcher = new ASTMatcher(); // Classic DP implementation int[][] dp = new int[params.size() + 1][peerParams.size() + 1]; for (int i = 0; i <= params.size(); i++) { dp[i][0] = i; } for (int j = 0; j <= peerParams.size(); j++) { dp[0][j] = j; } for (int i = 1; i <= params.size(); i++) { for (int j = 1; j <= peerParams.size(); j++) { int distance = dp[i - 1][j - 1]; if (!params.get(i - 1).subtreeMatch(matcher, peerParams.get(j - 1))) { distance += 1; } if (dp[i - 1][j] + 1 < distance) { distance = dp[i - 1][j] + 1; } if (dp[i][j - 1] + 1 < distance) { distance = dp[i][j - 1] + 1; } dp[i][j] = distance; } } return dp[params.size()][peerParams.size()]; }
public EquivalentNodeFinder(ASTNode node, ASTNode ancestorNode, ASTNode newAncestorNode, ASTMatcher matcher) { this.originalNode = node; this.ancestorNode = ancestorNode; this.newAncestorNode = newAncestorNode; this.matcher = matcher; }
private boolean treesMatch(ASTNode node, ASTNode otherNode, ASTNode topmostAncestorNode, ASTNode topmostNewAncestorNode, ASTMatcher matcher) { while (true) { if ((node == topmostAncestorNode) != (otherNode == topmostNewAncestorNode)) { // One has reached the end and the other has not return false; } if (node == topmostAncestorNode) { // They have both reached an end, and everything went smoothly return true; } if (!node.subtreeMatch(matcher, otherNode)) { // Subtrees do not match return false; } if (!indexMatches(node, otherNode)) { // The index of each does not match return false; } node = node.getParent(); otherNode = otherNode.getParent(); } }
private boolean methodThrowsException(MethodDeclaration method, Name exception) { ASTMatcher matcher = new ASTMatcher(); for (Iterator<Name> iter = method.thrownExceptions().iterator(); iter.hasNext();) { Name thrown = iter.next(); if (exception.subtreeMatch(matcher, thrown)) return true; } return false; }
private boolean isIn(MethodDeclaration md, List<MethodDeclaration> list) { for (int i = 0; i < list.size(); i++) { MethodDeclaration md2 = list.get(i); if (!md.getName().subtreeMatch(new ASTMatcher(), md2.getName())) { continue; } List<SingleVariableDeclaration> varDeclars = md.parameters(); List<SingleVariableDeclaration> varDeclars2 = md2.parameters(); if (varDeclars.size() != varDeclars2.size()) { continue; } boolean identical = true; for (int j = 0; j < varDeclars.size(); j++) { Type type = varDeclars.get(j).getType(); if (type.isParameterizedType()) { type = ((ParameterizedType)type).getType(); } Type type2 = varDeclars2.get(j).getType(); if (type2.isParameterizedType()) { type2 = ((ParameterizedType)type2).getType(); } if (!type.subtreeMatch(new ASTMatcher(), type2)) { identical = false; break; } } if (identical) { return true; } } return false; }
/** * Determines if the node is in the list by subtreeMatch() method. */ private boolean isIn(List<? extends ASTNode> list, ASTNode node) { boolean found = false; for (int i = 0; i < list.size(); i++) { if (list.get(i).subtreeMatch(new ASTMatcher(), node)) { found = true; break; } } return found; }
public NameRegionUpdater(ReplaceEdit originalEdit, ReferenceUpdater referenceUpdater, Name originalNode, ASTMatcher matcher) throws RefactoringException { super(originalEdit, referenceUpdater, originalNode, matcher); }
public TextElementRegionUpdater(ReplaceEdit originalEdit, ReferenceUpdater referenceUpdater, TextElement originalNode, ASTMatcher matcher) throws RefactoringException { super(originalEdit, referenceUpdater, originalNode, matcher); }
/** * Determines if nodes are equal. */ private boolean areEqual(ASTNode node1, ASTNode node2) { return node1.subtreeMatch(new ASTMatcher(), node2); }
/** * Creates the visitor. * * @param astMatcher a relaxed matcher that is knowledgeable about the * refactoring (for example, it matches two nodes even if the names * don't match -- given the new node has the new name and the old * node has the old name) * @param referenceUpdater a reference updater that can update references from * the old matcher to the new */ public RegionUpdaterChangeWeavingVisitor(ASTMatcher astMatcher, ReferenceUpdater referenceUpdater) { this.astMatcher = astMatcher; this.referenceUpdater = referenceUpdater; }