All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openrewrite.java.search.SemanticallyEqual Maven / Gradle / Ivy

There is a newer version: 8.40.2
Show newest version
/*
 * Copyright 2020 the original author or authors.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* https://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.openrewrite.java.search; import org.jspecify.annotations.Nullable; import org.openrewrite.Incubating; import org.openrewrite.Tree; import org.openrewrite.java.JavaIsoVisitor; import org.openrewrite.java.tree.*; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; /** * Recursively checks the equality of each element of two ASTs to determine if two trees are semantically equal. *

* Bug fixes related to semantic equality should be applied to `CombineSemanticallyEqualCatchBlocks$CommentVisitor` too. */ @Incubating(since = "7.24.0") public class SemanticallyEqual { protected SemanticallyEqual() { } public static boolean areEqual(J firstElem, J secondElem) { SemanticallyEqualVisitor semanticallyEqualVisitor = new SemanticallyEqualVisitor(true); semanticallyEqualVisitor.visit(firstElem, secondElem); return semanticallyEqualVisitor.isEqual(); } /** * Compares method invocations and new class constructors based on the `JavaType.Method` instead of checking * each types of each parameter. * I.E. void foo(Object obj) {} invoked with `java.lang.String` or `java.lang.Integer` will return true. */ public static boolean areSemanticallyEqual(J firstElem, J secondElem) { SemanticallyEqualVisitor semanticallyEqualVisitor = new SemanticallyEqualVisitor(false); semanticallyEqualVisitor.visit(firstElem, secondElem); return semanticallyEqualVisitor.isEqual.get(); } @SuppressWarnings("ConstantConditions") protected static class SemanticallyEqualVisitor extends JavaIsoVisitor { private final boolean compareMethodArguments; protected final AtomicBoolean isEqual = new AtomicBoolean(true); private final Deque> variableScope = new ArrayDeque<>(); private final Set seen = new HashSet<>(); public SemanticallyEqualVisitor(boolean compareMethodArguments) { this.compareMethodArguments = compareMethodArguments; } public boolean isEqual() { return isEqual.get(); } protected boolean nullMissMatch(Object obj1, Object obj2) { return (obj1 == null && obj2 != null || obj1 != null && obj2 == null); } protected boolean nullListSizeMissMatch(List list1, List list2) { return nullMissMatch(list1, list2) || list1 != null && list2 != null && list1.size() != list2.size(); } protected boolean modifierListMissMatch(List list1, List list2) { if (list1.size() != list2.size()) { return true; } EnumSet modifiers1 = EnumSet.noneOf(J.Modifier.Type.class); EnumSet modifiers2 = EnumSet.noneOf(J.Modifier.Type.class); for (int i = 0; i < list1.size(); i++) { modifiers1.add(list1.get(i).getType()); modifiers2.add(list2.get(i).getType()); } return !modifiers1.equals(modifiers2); } protected void visitList(@Nullable List list1, @Nullable List list2) { if (!isEqual.get() || nullListSizeMissMatch(list1, list2)) { isEqual.set(false); return; } if (list1 != null) { for (int i = 0; i < list1.size(); i++) { visit(list1.get(i), list2.get(i)); if (!isEqual.get()) { return; } } } } @Override public @Nullable J visit(@Nullable Tree tree, J j) { return super.visit(unwrap(tree), unwrap(j)); } private static @Nullable J unwrap(@Nullable Tree tree) { if (tree instanceof Expression) { tree = ((Expression) tree).unwrap(); } if (tree instanceof J.ControlParentheses) { tree = unwrap(((J.ControlParentheses) tree).getTree()); } return (J) tree; } @Override public @Nullable J preVisit(J tree, J j) { if (declaresVariableScope(tree)) { variableScope.push(new HashMap<>()); } return tree; } @Override public @Nullable J postVisit(J tree, J j) { if (declaresVariableScope(tree)) { variableScope.pop(); } return tree; } protected boolean declaresVariableScope(J tree) { if (tree instanceof J.Lambda) { return true; } return false; } @Override public Expression visitExpression(Expression expression, J j) { if (isEqual.get()) { if (!TypeUtils.isOfType(expression.getType(), ((Expression) j).getType())) { isEqual.set(false); } } return expression; } @Override public J.Annotation visitAnnotation(J.Annotation annotation, J j) { if (isEqual.get()) { if (!(j instanceof J.Annotation)) { isEqual.set(false); return annotation; } J.Annotation compareTo = (J.Annotation) j; if (!TypeUtils.isOfType(annotation.getType(), compareTo.getType()) || nullListSizeMissMatch(annotation.getArguments(), compareTo.getArguments())) { isEqual.set(false); return annotation; } this.visitTypeName(annotation.getAnnotationType(), compareTo.getAnnotationType()); this.visitList(annotation.getArguments(), compareTo.getArguments()); } return annotation; } @Override public J.AnnotatedType visitAnnotatedType(J.AnnotatedType annotatedType, J j) { if (isEqual.get()) { if (!(j instanceof J.AnnotatedType)) { isEqual.set(false); return annotatedType; } J.AnnotatedType compareTo = (J.AnnotatedType) j; if (!TypeUtils.isOfType(annotatedType.getType(), compareTo.getType()) || annotatedType.getAnnotations().size() != compareTo.getAnnotations().size()) { isEqual.set(false); return annotatedType; } this.visitTypeName(annotatedType.getTypeExpression(), compareTo.getTypeExpression()); this.visitList(annotatedType.getAnnotations(), compareTo.getAnnotations()); } return annotatedType; } @Override public J.ArrayAccess visitArrayAccess(J.ArrayAccess arrayAccess, J j) { if (isEqual.get()) { if (!(j instanceof J.ArrayAccess)) { isEqual.set(false); return arrayAccess; } J.ArrayAccess compareTo = (J.ArrayAccess) j; if (!TypeUtils.isOfType(arrayAccess.getType(), compareTo.getType())) { isEqual.set(false); return arrayAccess; } visit(arrayAccess.getIndexed(), compareTo.getIndexed()); visit(arrayAccess.getDimension(), compareTo.getDimension()); } return arrayAccess; } @Override public J.ArrayDimension visitArrayDimension(J.ArrayDimension arrayDimension, J j) { if (isEqual.get()) { if (!(j instanceof J.ArrayDimension)) { isEqual.set(false); return arrayDimension; } J.ArrayDimension compareTo = (J.ArrayDimension) j; visit(arrayDimension.getIndex(), compareTo.getIndex()); } return arrayDimension; } @Override public J.ArrayType visitArrayType(J.ArrayType arrayType, J j) { if (isEqual.get()) { if (!(j instanceof J.ArrayType)) { isEqual.set(false); return arrayType; } J.ArrayType compareTo = (J.ArrayType) j; if (!TypeUtils.isOfType(arrayType.getType(), compareTo.getType())) { isEqual.set(false); return arrayType; } this.visitTypeName(arrayType.getElementType(), compareTo.getElementType()); } return arrayType; } @Override public J.Assert visitAssert(J.Assert _assert, J j) { if (isEqual.get()) { if (!(j instanceof J.Assert)) { isEqual.set(false); return _assert; } J.Assert compareTo = (J.Assert) j; if (nullMissMatch(_assert.getDetail(), compareTo.getDetail())) { isEqual.set(false); return _assert; } visit(_assert.getCondition(), compareTo.getCondition()); if (_assert.getDetail() != null && compareTo.getDetail() != null) { visit(_assert.getDetail().getElement(), compareTo.getDetail().getElement()); } } return _assert; } @Override public J.Assignment visitAssignment(J.Assignment assignment, J j) { if (isEqual.get()) { if (!(j instanceof J.Assignment)) { isEqual.set(false); return assignment; } J.Assignment compareTo = (J.Assignment) j; if (!TypeUtils.isOfType(assignment.getType(), compareTo.getType())) { isEqual.set(false); return assignment; } visit(assignment.getAssignment(), compareTo.getAssignment()); visit(assignment.getVariable(), compareTo.getVariable()); } return assignment; } @Override public J.AssignmentOperation visitAssignmentOperation(J.AssignmentOperation assignOp, J j) { if (isEqual.get()) { if (!(j instanceof J.AssignmentOperation)) { isEqual.set(false); return assignOp; } J.AssignmentOperation compareTo = (J.AssignmentOperation) j; if (!TypeUtils.isOfType(assignOp.getType(), compareTo.getType())) { isEqual.set(false); return assignOp; } visit(assignOp.getAssignment(), compareTo.getAssignment()); visit(assignOp.getVariable(), compareTo.getVariable()); } return assignOp; } @Override public J.Binary visitBinary(J.Binary binary, J j) { if (isEqual.get()) { if (!(j instanceof J.Binary)) { isEqual.set(false); return binary; } J.Binary compareTo = (J.Binary) j; if (binary.getOperator() != compareTo.getOperator() || !TypeUtils.isOfType(binary.getType(), compareTo.getType())) { isEqual.set(false); return binary; } visit(binary.getLeft(), compareTo.getLeft()); visit(binary.getRight(), compareTo.getRight()); } return binary; } @Override public J.Block visitBlock(J.Block block, J j) { if (isEqual.get()) { if (!(j instanceof J.Block)) { isEqual.set(false); return block; } J.Block compareTo = (J.Block) j; if (block.getStatements().size() != compareTo.getStatements().size()) { isEqual.set(false); return block; } this.visitList(block.getStatements(), compareTo.getStatements()); } return block; } @Override public J.Break visitBreak(J.Break breakStatement, J j) { if (isEqual.get()) { if (!(j instanceof J.Break)) { isEqual.set(false); return breakStatement; } J.Break compareTo = (J.Break) j; if (nullMissMatch(breakStatement.getLabel(), compareTo.getLabel())) { isEqual.set(false); return breakStatement; } if (breakStatement.getLabel() != null && compareTo.getLabel() != null) { visit(breakStatement.getLabel(), compareTo.getLabel()); } } return breakStatement; } @Override public J.Case visitCase(J.Case _case, J j) { if (isEqual.get()) { if (!(j instanceof J.Case)) { isEqual.set(false); return _case; } J.Case compareTo = (J.Case) j; this.visitList(_case.getStatements(), compareTo.getStatements()); visit(_case.getBody(), compareTo.getBody()); this.visitList(_case.getExpressions(), compareTo.getExpressions()); } return _case; } @Override public J.Try.Catch visitCatch(J.Try.Catch _catch, J j) { if (isEqual.get()) { if (!(j instanceof J.Try.Catch)) { isEqual.set(false); return _catch; } J.Try.Catch compareTo = (J.Try.Catch) j; visit(_catch.getParameter(), compareTo.getParameter()); visit(_catch.getBody(), compareTo.getBody()); } return _catch; } @Override public J.ClassDeclaration visitClassDeclaration(J.ClassDeclaration classDecl, J j) { if (isEqual.get()) { if (!(j instanceof J.ClassDeclaration)) { isEqual.set(false); return classDecl; } J.ClassDeclaration compareTo = (J.ClassDeclaration) j; if (!classDecl.getSimpleName().equals(compareTo.getSimpleName()) || !TypeUtils.isOfType(classDecl.getType(), compareTo.getType()) || modifierListMissMatch(classDecl.getModifiers(), compareTo.getModifiers()) || classDecl.getKind() != compareTo.getKind() || nullListSizeMissMatch(classDecl.getPermits(), compareTo.getPermits()) || nullListSizeMissMatch(classDecl.getLeadingAnnotations(), compareTo.getLeadingAnnotations()) || nullMissMatch(classDecl.getExtends(), compareTo.getExtends()) || nullListSizeMissMatch(classDecl.getTypeParameters(), compareTo.getTypeParameters()) || nullListSizeMissMatch(classDecl.getImplements(), compareTo.getImplements())) { isEqual.set(false); return classDecl; } this.visitList(classDecl.getPermits(), compareTo.getPermits()); this.visitList(classDecl.getLeadingAnnotations(), compareTo.getLeadingAnnotations()); if (classDecl.getExtends() != null && compareTo.getExtends() != null) { visit(classDecl.getExtends(), compareTo.getExtends()); } this.visitList(classDecl.getTypeParameters(), compareTo.getTypeParameters()); this.visitList(classDecl.getImplements(), compareTo.getImplements()); visit(classDecl.getBody(), compareTo.getBody()); } return classDecl; } @Override public J.CompilationUnit visitCompilationUnit(J.CompilationUnit cu, J j) { if (isEqual.get()) { if (!(j instanceof J.CompilationUnit)) { isEqual.set(false); return cu; } J.CompilationUnit compareTo = (J.CompilationUnit) j; if (nullMissMatch(cu.getPackageDeclaration(), compareTo.getPackageDeclaration()) || cu.getClasses().size() != compareTo.getClasses().size()) { isEqual.set(false); return cu; } if (cu.getPackageDeclaration() != null && compareTo.getPackageDeclaration() != null) { visit(cu.getPackageDeclaration(), compareTo.getPackageDeclaration()); } // NOTE: no checking of imports, as that is just syntax sugar in a type-attributed LST this.visitList(cu.getClasses(), compareTo.getClasses()); } return cu; } @SuppressWarnings("unchecked") @Override public J.ControlParentheses visitControlParentheses(J.ControlParentheses controlParens, J j) { if (isEqual.get()) { if (j instanceof J.ControlParentheses) { J.ControlParentheses compareTo = (J.ControlParentheses) j; if (!TypeUtils.isOfType(controlParens.getType(), compareTo.getType())) { isEqual.set(false); return controlParens; } visit(controlParens.getTree(), compareTo.getTree()); } else if (j instanceof J.Parentheses) { J.Parentheses compareTo = (J.Parentheses) j; visit(controlParens.getTree(), compareTo.getTree()); } else { isEqual.set(false); return controlParens; } } return controlParens; } @Override public J.Continue visitContinue(J.Continue continueStatement, J j) { if (isEqual.get()) { if (!(j instanceof J.Continue)) { isEqual.set(false); return continueStatement; } J.Continue compareTo = (J.Continue) j; if (nullMissMatch(continueStatement.getLabel(), compareTo.getLabel())) { isEqual.set(false); return continueStatement; } if (continueStatement.getLabel() != null && compareTo.getLabel() != null) { visit(continueStatement.getLabel(), compareTo.getLabel()); } } return continueStatement; } @Override public J.DoWhileLoop visitDoWhileLoop(J.DoWhileLoop doWhileLoop, J j) { if (isEqual.get()) { if (!(j instanceof J.DoWhileLoop)) { isEqual.set(false); return doWhileLoop; } J.DoWhileLoop compareTo = (J.DoWhileLoop) j; visit(doWhileLoop.getWhileCondition(), compareTo.getWhileCondition()); visit(doWhileLoop.getBody(), compareTo.getBody()); } return doWhileLoop; } @Override public J.If.Else visitElse(J.If.Else else_, J j) { if (isEqual.get()) { if (!(j instanceof J.If.Else)) { isEqual.set(false); return else_; } J.If.Else compareTo = (J.If.Else) j; visit(else_.getBody(), compareTo.getBody()); } return else_; } @Override public J.Empty visitEmpty(J.Empty empty, J j) { if (isEqual.get()) { if (!(j instanceof J.Empty)) { isEqual.set(false); return empty; } J.Empty compareTo = (J.Empty) j; if (nullMissMatch(empty.getType(), compareTo.getType())) { isEqual.set(false); return empty; } } return empty; } @Override public J.EnumValue visitEnumValue(J.EnumValue _enum, J j) { if (isEqual.get()) { if (!(j instanceof J.EnumValue)) { isEqual.set(false); return _enum; } J.EnumValue compareTo = (J.EnumValue) j; if (!_enum.getName().getSimpleName().equals(compareTo.getName().getSimpleName()) || !TypeUtils.isOfType(_enum.getName().getType(), compareTo.getName().getType()) || nullListSizeMissMatch(_enum.getAnnotations(), compareTo.getAnnotations()) || nullMissMatch(_enum.getInitializer(), compareTo.getInitializer())) { isEqual.set(false); return _enum; } this.visitList(_enum.getAnnotations(), compareTo.getAnnotations()); if (_enum.getInitializer() != null && compareTo.getInitializer() != null) { visit(_enum.getInitializer(), compareTo.getInitializer()); } } return _enum; } @Override public J.EnumValueSet visitEnumValueSet(J.EnumValueSet enums, J j) { if (isEqual.get()) { if (!(j instanceof J.EnumValueSet)) { isEqual.set(false); return enums; } J.EnumValueSet compareTo = (J.EnumValueSet) j; this.visitList(enums.getEnums(), compareTo.getEnums()); } return enums; } @Override public J.FieldAccess visitFieldAccess(J.FieldAccess fieldAccess, J j) { if (isEqual.get()) { JavaType.Variable fieldType = fieldAccess.getName().getFieldType(); if (!(j instanceof J.FieldAccess)) { if (!(j instanceof J.Identifier) || !TypeUtils.isOfType(fieldType, ((J.Identifier) j).getFieldType()) || !fieldAccess.getSimpleName().equals(((J.Identifier) j).getSimpleName())) { isEqual.set(false); } else { if (fieldType != null && !fieldType.hasFlags(Flag.Static)) { isEqual.set(false); } } return fieldAccess; } J.FieldAccess compareTo = (J.FieldAccess) j; if (fieldAccess.getType() instanceof JavaType.Unknown && compareTo.getType() instanceof JavaType.Unknown) { if (!fieldAccess.getSimpleName().equals(compareTo.getSimpleName())) { isEqual.set(false); return fieldAccess; } } else if (!TypeUtils.isOfType(fieldAccess.getType(), compareTo.getType()) || !TypeUtils.isOfType(fieldType, compareTo.getName().getFieldType())) { isEqual.set(false); return fieldAccess; } visit(fieldAccess.getTarget(), compareTo.getTarget()); } return fieldAccess; } @Override public J.ForEachLoop visitForEachLoop(J.ForEachLoop forLoop, J j) { if (isEqual.get()) { if (!(j instanceof J.ForEachLoop)) { isEqual.set(false); return forLoop; } J.ForEachLoop compareTo = (J.ForEachLoop) j; visit(forLoop.getControl(), compareTo.getControl()); visit(forLoop.getBody(), compareTo.getBody()); } return forLoop; } @Override public J.ForEachLoop.Control visitForEachControl(J.ForEachLoop.Control control, J j) { if (isEqual.get()) { if (!(j instanceof J.ForEachLoop.Control)) { isEqual.set(false); return control; } J.ForEachLoop.Control compareTo = (J.ForEachLoop.Control) j; visit(control.getVariable(), compareTo.getVariable()); visit(control.getIterable(), compareTo.getIterable()); } return control; } @Override public J.ForLoop visitForLoop(J.ForLoop forLoop, J j) { if (isEqual.get()) { if (!(j instanceof J.ForLoop)) { isEqual.set(false); return forLoop; } J.ForLoop compareTo = (J.ForLoop) j; visit(forLoop.getControl(), compareTo.getControl()); visit(forLoop.getBody(), compareTo.getBody()); } return forLoop; } @Override public J.ForLoop.Control visitForControl(J.ForLoop.Control control, J j) { if (isEqual.get()) { if (!(j instanceof J.ForLoop.Control)) { isEqual.set(false); return control; } J.ForLoop.Control compareTo = (J.ForLoop.Control) j; if (control.getInit().size() != compareTo.getInit().size() || control.getUpdate().size() != compareTo.getUpdate().size()) { isEqual.set(false); return control; } visit(control.getCondition(), compareTo.getCondition()); this.visitList(control.getInit(), compareTo.getInit()); this.visitList(control.getUpdate(), compareTo.getUpdate()); } return control; } @Override public J.Identifier visitIdentifier(J.Identifier identifier, J j) { if (isEqual.get()) { if (!(j instanceof J.Identifier)) { if (!(j instanceof J.FieldAccess) || !TypeUtils.isOfType(identifier.getFieldType(), ((J.FieldAccess) j).getName().getFieldType())) { isEqual.set(false); } else if (identifier.getFieldType() != null && !identifier.getFieldType().hasFlags(Flag.Static)) { isEqual.set(false); } return identifier; } J.Identifier compareTo = (J.Identifier) j; if (identifier.getFieldType() != null) { Map scope = variableScope.peek(); if (scope != null && scope.containsKey(identifier.getSimpleName()) && scope.get(identifier.getSimpleName()).equals(compareTo.getSimpleName())) { return identifier; } } if (!identifier.getSimpleName().equals(compareTo.getSimpleName())) { isEqual.set(false); return identifier; } } return identifier; } @Override public J.If visitIf(J.If iff, J j) { if (isEqual.get()) { if (!(j instanceof J.If)) { isEqual.set(false); return iff; } J.If compareTo = (J.If) j; if (nullMissMatch(iff.getElsePart(), compareTo.getElsePart())) { isEqual.set(false); return iff; } visit(iff.getIfCondition(), compareTo.getIfCondition()); visit(iff.getThenPart(), compareTo.getThenPart()); if (iff.getElsePart() != null && compareTo.getElsePart() != null) { visit(iff.getElsePart(), compareTo.getElsePart()); } } return iff; } @Override public J.Import visitImport(J.Import _import, J j) { if (isEqual.get()) { if (!(j instanceof J.Import)) { isEqual.set(false); return _import; } J.Import compareTo = (J.Import) j; if (_import.isStatic() != compareTo.isStatic() || !_import.getPackageName().equals(compareTo.getPackageName()) || !_import.getClassName().equals(compareTo.getClassName()) || !TypeUtils.isOfType(_import.getQualid().getType(), compareTo.getQualid().getType())) { isEqual.set(false); return _import; } } return _import; } @Override public J.InstanceOf visitInstanceOf(J.InstanceOf instanceOf, J j) { if (isEqual.get()) { if (!(j instanceof J.InstanceOf)) { isEqual.set(false); return instanceOf; } J.InstanceOf compareTo = (J.InstanceOf) j; if (!TypeUtils.isOfType(instanceOf.getType(), compareTo.getType())) { isEqual.set(false); return instanceOf; } visit(instanceOf.getClazz(), compareTo.getClazz()); visit(instanceOf.getExpression(), compareTo.getExpression()); } return instanceOf; } @Override public J.Label visitLabel(J.Label label, J j) { if (isEqual.get()) { if (!(j instanceof J.Label)) { isEqual.set(false); return label; } J.Label compareTo = (J.Label) j; if (!label.getLabel().getSimpleName().equals(compareTo.getLabel().getSimpleName()) || !TypeUtils.isOfType(label.getLabel().getType(), compareTo.getLabel().getType())) { isEqual.set(false); return label; } visit(label.getStatement(), compareTo.getStatement()); } return label; } @Override public J.Lambda visitLambda(J.Lambda lambda, J j) { if (isEqual.get()) { if (!(j instanceof J.Lambda)) { isEqual.set(false); return lambda; } J.Lambda compareTo = (J.Lambda) j; if (lambda.getParameters().getParameters().size() != compareTo.getParameters().getParameters().size()) { isEqual.set(false); return lambda; } visitList(lambda.getParameters().getParameters(), compareTo.getParameters().getParameters()); visit(lambda.getBody(), compareTo.getBody()); } return lambda; } @Override public J.Literal visitLiteral(J.Literal literal, J j) { if (isEqual.get()) { if (!(j instanceof J.Literal)) { isEqual.set(false); return literal; } J.Literal compareTo = (J.Literal) j; if (!TypeUtils.isOfType(literal.getType(), compareTo.getType()) || !Objects.equals(literal.getValue(), compareTo.getValue())) { isEqual.set(false); return literal; } } return literal; } @Override public J.MemberReference visitMemberReference(J.MemberReference memberRef, J j) { if (isEqual.get()) { if (!(j instanceof J.MemberReference)) { isEqual.set(false); return memberRef; } J.MemberReference compareTo = (J.MemberReference) j; if (!memberRef.getReference().getSimpleName().equals(compareTo.getReference().getSimpleName()) || !TypeUtils.isOfType(memberRef.getReference().getType(), compareTo.getReference().getType()) || !TypeUtils.isOfType(memberRef.getType(), compareTo.getType()) || !TypeUtils.isOfType(memberRef.getVariableType(), compareTo.getVariableType()) || !TypeUtils.isOfType(memberRef.getMethodType(), compareTo.getMethodType()) || nullListSizeMissMatch(memberRef.getTypeParameters(), compareTo.getTypeParameters())) { isEqual.set(false); return memberRef; } visit(memberRef.getContaining(), compareTo.getContaining()); this.visitList(memberRef.getTypeParameters(), compareTo.getTypeParameters()); } return memberRef; } @Override public J.MethodDeclaration visitMethodDeclaration(J.MethodDeclaration method, J j) { if (isEqual.get()) { if (!(j instanceof J.MethodDeclaration)) { isEqual.set(false); return method; } J.MethodDeclaration compareTo = (J.MethodDeclaration) j; if (!method.getSimpleName().equals(compareTo.getSimpleName()) || !TypeUtils.isOfType(method.getMethodType(), compareTo.getMethodType()) || modifierListMissMatch(method.getModifiers(), compareTo.getModifiers()) || method.getLeadingAnnotations().size() != compareTo.getLeadingAnnotations().size() || method.getParameters().size() != compareTo.getParameters().size() || nullMissMatch(method.getReturnTypeExpression(), compareTo.getReturnTypeExpression()) || nullListSizeMissMatch(method.getTypeParameters(), compareTo.getTypeParameters()) || nullListSizeMissMatch(method.getThrows(), compareTo.getThrows()) || nullMissMatch(method.getBody(), compareTo.getBody()) || method.getBody() != null && compareTo.getBody() != null && nullListSizeMissMatch(method.getBody().getStatements(), compareTo.getBody().getStatements())) { isEqual.set(false); return method; } this.visitList(method.getLeadingAnnotations(), compareTo.getLeadingAnnotations()); this.visitList(method.getParameters(), compareTo.getParameters()); if (method.getReturnTypeExpression() != null && compareTo.getReturnTypeExpression() != null) { this.visitTypeName(method.getReturnTypeExpression(), compareTo.getReturnTypeExpression()); } this.visitList(method.getTypeParameters(), compareTo.getTypeParameters()); this.visitList(method.getThrows(), compareTo.getThrows()); if (method.getBody() != null && compareTo.getBody() != null) { visit(method.getBody(), compareTo.getBody()); } } return method; } @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, J j) { if (isEqual.get()) { if (!(j instanceof J.MethodInvocation)) { isEqual.set(false); return method; } boolean static_ = method.getMethodType() != null && method.getMethodType().hasFlags(Flag.Static); J.MethodInvocation compareTo = (J.MethodInvocation) j; if (!method.getSimpleName().equals(compareTo.getSimpleName()) || method.getArguments().size() != compareTo.getArguments().size() || !(static_ == (compareTo.getMethodType() != null && compareTo.getMethodType().hasFlags(Flag.Static)) || !nullMissMatch(method.getSelect(), compareTo.getSelect())) || method.getMethodType() == null || compareTo.getMethodType() == null || !TypeUtils.isAssignableTo(method.getMethodType().getReturnType(), compareTo.getMethodType().getReturnType()) || nullListSizeMissMatch(method.getTypeParameters(), compareTo.getTypeParameters())) { isEqual.set(false); return method; } if (!static_) { if (nullMissMatch(method.getSelect(), compareTo.getSelect())) { isEqual.set(false); return method; } visit(method.getSelect(), compareTo.getSelect()); } else { JavaType.FullyQualified methodDeclaringType = method.getMethodType().getDeclaringType(); JavaType.FullyQualified compareToDeclaringType = compareTo.getMethodType().getDeclaringType(); if (!TypeUtils.isAssignableTo(methodDeclaringType instanceof JavaType.Parameterized ? ((JavaType.Parameterized) methodDeclaringType).getType() : methodDeclaringType, compareToDeclaringType instanceof JavaType.Parameterized ? ((JavaType.Parameterized) compareToDeclaringType).getType() : compareToDeclaringType)) { isEqual.set(false); return method; } } boolean containsLiteral = false; if (!compareMethodArguments) { for (int i = 0; i < method.getArguments().size(); i++) { if (method.getArguments().get(i) instanceof J.Literal || compareTo.getArguments().get(i) instanceof J.Literal) { containsLiteral = true; break; } } if (!containsLiteral) { if (nullMissMatch(method.getMethodType(), compareTo.getMethodType()) || !TypeUtils.isOfType(method.getMethodType(), compareTo.getMethodType())) { isEqual.set(false); return method; } } } if (compareMethodArguments || containsLiteral) { this.visitList(method.getArguments(), compareTo.getArguments()); } this.visitList(method.getTypeParameters(), compareTo.getTypeParameters()); } return method; } @Override public J.MultiCatch visitMultiCatch(J.MultiCatch multiCatch, J j) { if (isEqual.get()) { if (!(j instanceof J.MultiCatch)) { isEqual.set(false); return multiCatch; } J.MultiCatch compareTo = (J.MultiCatch) j; if (!(multiCatch.getType() instanceof JavaType.MultiCatch) || !(compareTo.getType() instanceof JavaType.MultiCatch) || ((JavaType.MultiCatch) multiCatch.getType()).getThrowableTypes().size() != ((JavaType.MultiCatch) compareTo.getType()).getThrowableTypes().size() || multiCatch.getAlternatives().size() != compareTo.getAlternatives().size()) { isEqual.set(false); return multiCatch; } for (int i = 0; i < ((JavaType.MultiCatch) multiCatch.getType()).getThrowableTypes().size(); i++) { JavaType first = ((JavaType.MultiCatch) multiCatch.getType()).getThrowableTypes().get(i); JavaType second = ((JavaType.MultiCatch) compareTo.getType()).getThrowableTypes().get(i); if (!TypeUtils.isOfType(first, second)) { isEqual.set(false); return multiCatch; } } this.visitList(multiCatch.getAlternatives(), compareTo.getAlternatives()); } return multiCatch; } @Override public J.NewArray visitNewArray(J.NewArray newArray, J j) { if (isEqual.get()) { if (!(j instanceof J.NewArray)) { isEqual.set(false); return newArray; } J.NewArray compareTo = (J.NewArray) j; if (!TypeUtils.isOfType(newArray.getType(), compareTo.getType()) || newArray.getDimensions().size() != compareTo.getDimensions().size() || nullMissMatch(newArray.getTypeExpression(), compareTo.getTypeExpression()) || nullListSizeMissMatch(newArray.getInitializer(), compareTo.getInitializer())) { isEqual.set(false); return newArray; } this.visitList(newArray.getDimensions(), compareTo.getDimensions()); if (newArray.getTypeExpression() != null && compareTo.getTypeExpression() != null) { visit(newArray.getTypeExpression(), compareTo.getTypeExpression()); } this.visitList(newArray.getInitializer(), compareTo.getInitializer()); } return newArray; } @Override public J.NewClass visitNewClass(J.NewClass newClass, J j) { if (isEqual.get()) { if (!(j instanceof J.NewClass)) { isEqual.set(false); return newClass; } J.NewClass compareTo = (J.NewClass) j; if (!TypeUtils.isOfType(newClass.getType(), compareTo.getType()) || !TypeUtils.isOfType(newClass.getConstructorType(), compareTo.getConstructorType()) || nullMissMatch(newClass.getEnclosing(), compareTo.getEnclosing()) || nullMissMatch(newClass.getClazz(), compareTo.getClazz()) || nullMissMatch(newClass.getConstructorType(), compareTo.getConstructorType()) || nullMissMatch(newClass.getBody(), compareTo.getBody()) || nullListSizeMissMatch(newClass.getArguments(), compareTo.getArguments())) { isEqual.set(false); return newClass; } if (newClass.getEnclosing() != null && compareTo.getEnclosing() != null) { visit(newClass.getEnclosing(), compareTo.getEnclosing()); } if (newClass.getClazz() != null && compareTo.getClazz() != null) { visit(newClass.getClazz(), compareTo.getClazz()); } if (newClass.getBody() != null && compareTo.getBody() != null) { visit(newClass.getBody(), compareTo.getBody()); } if (newClass.getArguments() != null && compareTo.getArguments() != null) { boolean containsLiteral = false; if (!compareMethodArguments) { for (int i = 0; i < newClass.getArguments().size(); i++) { if (newClass.getArguments().get(i) instanceof J.Literal || compareTo.getArguments().get(i) instanceof J.Literal) { containsLiteral = true; break; } } if (!containsLiteral) { if (nullMissMatch(newClass.getConstructorType(), compareTo.getConstructorType()) || newClass.getConstructorType() != null && compareTo.getConstructorType() != null && !TypeUtils.isOfType(newClass.getConstructorType(), compareTo.getConstructorType())) { isEqual.set(false); return newClass; } } } if (compareMethodArguments || containsLiteral) { this.visitList(newClass.getArguments(), compareTo.getArguments()); } } } return newClass; } @Override public J.Package visitPackage(J.Package pkg, J j) { if (isEqual.get()) { if (!(j instanceof J.Package)) { isEqual.set(false); return pkg; } J.Package compareTo = (J.Package) j; if (pkg.getAnnotations().size() != compareTo.getAnnotations().size() || !pkg.getExpression().toString().equals(compareTo.getExpression().toString())) { isEqual.set(false); return pkg; } this.visitList(pkg.getAnnotations(), compareTo.getAnnotations()); } return pkg; } @Override public J.ParameterizedType visitParameterizedType(J.ParameterizedType type, J j) { if (isEqual.get()) { if (!(j instanceof J.ParameterizedType)) { isEqual.set(false); return type; } J.ParameterizedType compareTo = (J.ParameterizedType) j; if (!TypeUtils.isOfType(type.getType(), compareTo.getType()) || nullListSizeMissMatch(type.getTypeParameters(), compareTo.getTypeParameters())) { isEqual.set(false); return type; } if (!(type.getTypeParameters().get(0) instanceof J.Empty || compareTo.getTypeParameters().get(0) instanceof J.Empty)) { this.visitList(type.getTypeParameters(), compareTo.getTypeParameters()); } } return type; } @Override public J.Parentheses visitParentheses(J.Parentheses parens, J j) { if (isEqual.get()) { if (j instanceof Expression) { visit(parens.getTree(), ((Expression) j).unwrap()); } else { isEqual.set(false); return parens; } } return parens; } @Override public J.Primitive visitPrimitive(J.Primitive primitive, J j) { if (isEqual.get()) { if (!(j instanceof J.Primitive)) { isEqual.set(false); return primitive; } J.Primitive compareTo = (J.Primitive) j; if (!TypeUtils.isOfType(primitive.getType(), compareTo.getType())) { isEqual.set(false); return primitive; } } return primitive; } @Override public J.Return visitReturn(J.Return _return, J j) { if (isEqual.get()) { if (!(j instanceof J.Return)) { isEqual.set(false); return _return; } J.Return compareTo = (J.Return) j; if (nullMissMatch(_return.getExpression(), compareTo.getExpression())) { isEqual.set(false); return _return; } if (_return.getExpression() != null && compareTo.getExpression() != null) { visit(_return.getExpression(), compareTo.getExpression()); } } return _return; } @Override public J.Switch visitSwitch(J.Switch _switch, J j) { if (isEqual.get()) { if (!(j instanceof J.Switch)) { isEqual.set(false); return _switch; } J.Switch compareTo = (J.Switch) j; visit(_switch.getCases(), compareTo.getCases()); } return _switch; } @Override public J.SwitchExpression visitSwitchExpression(J.SwitchExpression _switch, J j) { if (isEqual.get()) { if (!(j instanceof J.SwitchExpression)) { isEqual.set(false); return _switch; } J.SwitchExpression compareTo = (J.SwitchExpression) j; visit(_switch.getSelector(), compareTo.getSelector()); visit(_switch.getCases(), compareTo.getCases()); } return _switch; } @Override public J.Synchronized visitSynchronized(J.Synchronized _sync, J j) { if (isEqual.get()) { if (!(j instanceof J.Synchronized)) { isEqual.set(false); return _sync; } J.Synchronized compareTo = (J.Synchronized) j; visit(_sync.getLock(), compareTo.getLock()); visit(_sync.getBody(), compareTo.getBody()); } return _sync; } @Override public J.Ternary visitTernary(J.Ternary ternary, J j) { if (isEqual.get()) { if (!(j instanceof J.Ternary)) { isEqual.set(false); return ternary; } J.Ternary compareTo = (J.Ternary) j; if (!TypeUtils.isOfType(ternary.getType(), compareTo.getType())) { isEqual.set(false); return ternary; } visit(ternary.getCondition(), compareTo.getCondition()); visit(ternary.getTruePart(), compareTo.getTruePart()); visit(ternary.getFalsePart(), compareTo.getFalsePart()); } return ternary; } @Override public J.Throw visitThrow(J.Throw thrown, J j) { if (isEqual.get()) { if (!(j instanceof J.Throw)) { isEqual.set(false); return thrown; } J.Throw compareTo = (J.Throw) j; visit(thrown.getException(), compareTo.getException()); } return thrown; } @Override public J.Try visitTry(J.Try _try, J j) { if (isEqual.get()) { if (!(j instanceof J.Try)) { isEqual.set(false); return _try; } J.Try compareTo = (J.Try) j; if (_try.getCatches().size() != compareTo.getCatches().size() || nullMissMatch(_try.getFinally(), compareTo.getFinally()) || nullListSizeMissMatch(_try.getResources(), compareTo.getResources())) { isEqual.set(false); return _try; } visit(_try.getBody(), compareTo.getBody()); this.visitList(_try.getCatches(), compareTo.getCatches()); this.visitList(_try.getResources(), compareTo.getResources()); if (_try.getFinally() != null && compareTo.getFinally() != null) { visit(_try.getFinally(), compareTo.getFinally()); } } return _try; } @Override public J.Try.Resource visitTryResource(J.Try.Resource tryResource, J j) { if (isEqual.get()) { if (!(j instanceof J.Try.Resource)) { isEqual.set(false); return tryResource; } J.Try.Resource compareTo = (J.Try.Resource) j; visit(tryResource.getVariableDeclarations(), compareTo.getVariableDeclarations()); } return tryResource; } @Override public J.TypeCast visitTypeCast(J.TypeCast typeCast, J j) { if (isEqual.get()) { if (!(j instanceof Expression)) { isEqual.set(false); return typeCast; } Expression compareTo = (Expression) j; if (!TypeUtils.isOfType(typeCast.getType(), compareTo.getType())) { isEqual.set(false); } else { if (compareTo instanceof J.TypeCast) { visit(typeCast.getExpression(), ((J.TypeCast) compareTo).getExpression()); } else { visit(typeCast.getExpression(), compareTo); } } } return typeCast; } @Override public J.TypeParameter visitTypeParameter(J.TypeParameter typeParam, J j) { if (isEqual.get()) { if (!(j instanceof J.TypeParameter)) { isEqual.set(false); return typeParam; } J.TypeParameter compareTo = (J.TypeParameter) j; if (typeParam.getAnnotations().size() != compareTo.getAnnotations().size() || nullListSizeMissMatch(typeParam.getBounds(), compareTo.getBounds())) { isEqual.set(false); return typeParam; } visit(typeParam.getName(), compareTo.getName()); this.visitList(typeParam.getAnnotations(), compareTo.getAnnotations()); this.visitList(typeParam.getBounds(), compareTo.getBounds()); } return typeParam; } @Override public J.Unary visitUnary(J.Unary unary, J j) { if (isEqual.get()) { if (!(j instanceof J.Unary)) { isEqual.set(false); return unary; } J.Unary compareTo = (J.Unary) j; if (unary.getOperator() != compareTo.getOperator() || !TypeUtils.isOfType(unary.getType(), compareTo.getType())) { isEqual.set(false); return unary; } visit(unary.getExpression(), compareTo.getExpression()); } return unary; } @Override public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, J j) { if (isEqual.get()) { if (!(j instanceof J.VariableDeclarations)) { isEqual.set(false); return multiVariable; } J.VariableDeclarations compareTo = (J.VariableDeclarations) j; if (!TypeUtils.isOfType(multiVariable.getType(), compareTo.getType()) || nullMissMatch(multiVariable.getTypeExpression(), compareTo.getTypeExpression()) || multiVariable.getVariables().size() != compareTo.getVariables().size() || multiVariable.getLeadingAnnotations().size() != compareTo.getLeadingAnnotations().size()) { isEqual.set(false); return multiVariable; } if (multiVariable.getTypeExpression() != null && compareTo.getTypeExpression() != null) { this.visitTypeName(multiVariable.getTypeExpression(), compareTo.getTypeExpression()); } this.visitList(multiVariable.getLeadingAnnotations(), compareTo.getLeadingAnnotations()); this.visitList(multiVariable.getVariables(), compareTo.getVariables()); } return multiVariable; } @Override public J.VariableDeclarations.NamedVariable visitVariable(J.VariableDeclarations.NamedVariable variable, J j) { if (isEqual.get()) { if (!(j instanceof J.VariableDeclarations.NamedVariable)) { isEqual.set(false); return variable; } J.VariableDeclarations.NamedVariable compareTo = (J.VariableDeclarations.NamedVariable) j; Map scope = variableScope.peek(); if (scope != null) { scope.put(variable.getSimpleName(), compareTo.getSimpleName()); } else if (!variable.getSimpleName().equals(compareTo.getSimpleName())) { isEqual.set(false); return variable; } if (!TypeUtils.isOfType(variable.getType(), compareTo.getType()) || nullMissMatch(variable.getInitializer(), compareTo.getInitializer())) { isEqual.set(false); return variable; } if (variable.getInitializer() != null && compareTo.getInitializer() != null) { visit(variable.getInitializer(), compareTo.getInitializer()); } } return variable; } @Override public J.WhileLoop visitWhileLoop(J.WhileLoop whileLoop, J j) { if (isEqual.get()) { if (!(j instanceof J.WhileLoop)) { isEqual.set(false); return whileLoop; } J.WhileLoop compareTo = (J.WhileLoop) j; visit(whileLoop.getBody(), compareTo.getBody()); visit(whileLoop.getCondition(), compareTo.getCondition()); } return whileLoop; } @Override public J.Wildcard visitWildcard(J.Wildcard wildcard, J j) { if (isEqual.get()) { if (!(j instanceof J.Wildcard)) { isEqual.set(false); return wildcard; } J.Wildcard compareTo = (J.Wildcard) j; if (wildcard.getBound() != compareTo.getBound() || nullMissMatch(wildcard.getBoundedType(), compareTo.getBoundedType())) { isEqual.set(false); return wildcard; } if (wildcard.getBoundedType() != null && compareTo.getBoundedType() != null) { this.visitTypeName(wildcard.getBoundedType(), compareTo.getBoundedType()); } } return wildcard; } @Override public N visitTypeName(N firstTypeName, J j) { if (isEqual.get()) { if (!(j instanceof NameTree) && !TypeUtils.isOfType(firstTypeName.getType(), ((NameTree) j).getType())) { isEqual.set(false); return firstTypeName; } } return firstTypeName; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy