Skip to content

Commit

Permalink
Added reduction or equals and hashcode
Browse files Browse the repository at this point in the history
  • Loading branch information
timo-a committed Apr 4, 2021
1 parent 81686e8 commit 5e087a1
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 1 deletion.
4 changes: 3 additions & 1 deletion app/src/main/java/de/lomboker/app/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
*/
package de.lomboker.app;

import de.lomboker.lib.FuzzyEqualsAndHashCode;
import picocli.CommandLine;
import picocli.CommandLine.Command;

@Command(name = "lomboker",
subcommands = {
CounterApp.class,
Reduce.class,
Mark.class
Mark.class,
FuzzyEqualsAndHashCode.class
})
public class App implements Runnable {
public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package de.lomboker.app.equalsAndHashCode;

import picocli.CommandLine;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

import static de.lomboker.lib.FuzzyEqualsAndHashCode.reduceFuzzyEqualsAndHashCode;

@CommandLine.Command(name = "equalsAndHashCode", description = "reduce equals and hash code")
public class ReduceFuzzyEaH implements Runnable {

@CommandLine.Parameters(index = "0")
File file;

public static void main(String[] args) {
int exitCode = new CommandLine(new ReduceFuzzyEaH()).execute(args);
System.exit(exitCode);
}

@Override
public void run() {
try {
String code = Files.readString(file.toPath());
String converted = reduceFuzzyEqualsAndHashCode(code);
Files.writeString(file.toPath(), converted);
} catch (IOException e) {
e.printStackTrace();
}

}

}
93 changes: 93 additions & 0 deletions lib/src/main/java/de/lomboker/lib/FuzzyEqualsAndHashCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package de.lomboker.lib;

import com.github.javaparser.ast.AccessSpecifier;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.expr.AnnotationExpr;
import com.github.javaparser.printer.lexicalpreservation.LexicalPreservingPrinter;

import java.util.Optional;

public class FuzzyEqualsAndHashCode {

public static String reduceFuzzyEqualsAndHashCode(String code) {
ClassWrapper wrapper = new ClassWrapper(code);

CompilationUnit cu = wrapper.cu;
LexicalPreservingPrinter.setup(cu);

//the equals method, if it exists
Optional<MethodDeclaration> equals = wrapper.methods
.stream()
.filter(FuzzyEqualsAndHashCode::isEquals)
.findAny();

//the hashCode method, if it exists
Optional<MethodDeclaration> hashCode = wrapper.methods
.stream()
.filter(FuzzyEqualsAndHashCode::isHashCode)
.findAny();

if (equals.isPresent() && hashCode.isPresent()) {
cu.addImport("lombok.EqualsAndHashCode");

cu.findAll(ClassOrInterfaceDeclaration.class);

//add annotation
Optional<ClassOrInterfaceDeclaration> oFirstClass = cu.findFirst(ClassOrInterfaceDeclaration.class);
if(oFirstClass.isEmpty()) {
System.out.println("Error! no class found");
return LexicalPreservingPrinter.print(cu);
}

ClassOrInterfaceDeclaration firstClass = oFirstClass.get();

NodeList<AnnotationExpr> as = firstClass.getAnnotations();
firstClass.addMarkerAnnotation("EqualsAndHashCode");

//remove equals, hashCode
equals.get().removeJavaDocComment();
equals.get().remove();
hashCode.get().removeJavaDocComment();
hashCode.get().remove();
}

return LexicalPreservingPrinter.print(cu);

}

static boolean isEquals(MethodDeclaration md) {
boolean isPublic = AccessSpecifier.PUBLIC.equals(md.getAccessSpecifier());
boolean isBoolean = "boolean".equals(md.getTypeAsString());
boolean oneParameter = md.getParameters().size() == 1;

return isPublic
&& isBoolean
&& oneParameter
&& paramIsObject(md);
}

static boolean paramIsObject(MethodDeclaration md) {
var op = md.getParameters().getFirst();
if(op.isEmpty()) {
return false;
}

Parameter p = op.get();
return "Object".equals(p.getTypeAsString());
}

static boolean isHashCode(MethodDeclaration md) {
boolean isPublic = AccessSpecifier.PUBLIC.equals(md.getAccessSpecifier());
boolean isInt = "int".equals(md.getTypeAsString());
boolean noParameter = md.getParameters().isEmpty();

return isPublic
&& isInt
&& noParameter;
}

}
25 changes: 25 additions & 0 deletions lib/src/test/java/de/lomboker/lib/FuzzyEaHTests.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.lomboker.lib;

import org.junit.jupiter.api.Test;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.util.StringJoiner;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class FuzzyEaHTests extends FileTest {

@Test
public void testFuzzyEaH() throws IOException {
String fileName = "Fuzzy/EqualsAndHashCode/EaH.java";
String fileNameRef = "Fuzzy/EqualsAndHashCode/EaH.reduced.java";
String input = readFile(fileName);
String expected = readFile(fileNameRef);

assertEquals(expected, FuzzyEqualsAndHashCode.reduceFuzzyEqualsAndHashCode(input));
}

}
13 changes: 13 additions & 0 deletions lib/src/test/resources/Fuzzy/EqualsAndHashCode/EaH.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class A {

private int number = 5;

public boolean equals(Object o) {
return false;
}

public int hashCode() {
return 0;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import lombok.EqualsAndHashCode;

@EqualsAndHashCode
class A {

private int number = 5;

}

0 comments on commit 5e087a1

Please sign in to comment.