Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix two minor issues with the Java language module token extraction #940

Merged
merged 10 commits into from
Feb 24, 2023
12 changes: 6 additions & 6 deletions core/src/test/java/de/jplag/BasicFunctionalityTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,17 @@ void testPartialPlagiarism() throws ExitException {
.forEach(comparison -> assertEquals(0, comparison.similarity(), DELTA));

// Hard coded assertions on selected comparisons
assertEquals(0.238, getSelectedPercent(result, "A", "B"), DELTA);
assertEquals(0.237, getSelectedPercent(result, "A", "B"), DELTA);
assertEquals(0.996, getSelectedPercent(result, "A", "C"), DELTA);
assertEquals(0.748, getSelectedPercent(result, "A", "D"), DELTA);
assertEquals(0.238, getSelectedPercent(result, "B", "C"), DELTA);
assertEquals(0.283, getSelectedPercent(result, "B", "D"), DELTA);
assertEquals(0.748, getSelectedPercent(result, "C", "D"), DELTA);
assertEquals(0.751, getSelectedPercent(result, "A", "D"), DELTA);
assertEquals(0.237, getSelectedPercent(result, "B", "C"), DELTA);
assertEquals(0.281, getSelectedPercent(result, "B", "D"), DELTA);
assertEquals(0.751, getSelectedPercent(result, "C", "D"), DELTA);

// More detailed assertions for the plagiarism in A-D
var biggestMatch = getSelectedComparison(result, "A", "D");
assertEquals(0.946, biggestMatch.get().maximalSimilarity(), DELTA);
assertEquals(0.619, biggestMatch.get().minimalSimilarity(), DELTA);
assertEquals(0.622, biggestMatch.get().minimalSimilarity(), DELTA);
assertEquals(11, biggestMatch.get().matches().size());
}

Expand Down
7 changes: 3 additions & 4 deletions languages/java/src/main/java/de/jplag/java/JavaTokenType.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ public enum JavaTokenType implements TokenType {
J_SWITCH_END("}SWITCH"), // check
J_CASE("CASE"), // check
J_TRY_BEGIN("TRY{"), // check
J_TRY_END("}TRY"), // check
J_CATCH_BEGIN("CATCH{"), // check
J_CATCH_END("}CATCH"), // check
J_FINALLY("FINALLY"), // check
J_FINALLY_BEGIN("FINALLY{"), // check
J_FINALLY_END("}FINALLY"), // check
J_IF_BEGIN("IF{"), // check
J_ELSE("ELSE"), // check
J_IF_END("}IF"), // check
Expand Down Expand Up @@ -62,9 +64,6 @@ public enum JavaTokenType implements TokenType {
J_ANNO_C_BEGIN("ANNO_C{"), // ??
J_ANNO_C_END("}ANNO_C"), // ??

// new in 1.7
J_TRY_WITH_RESOURCE("TRY_RES"), // check

// new in 1.9
J_REQUIRES("REQUIRES"), // check
J_PROVIDES("PROVIDES"), // check
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,18 +226,19 @@ public Object visitCase(CaseTree node, Object p) {
@Override
public Object visitTry(TryTree node, Object p) {
long start = positions.getStartPosition(ast, node);
if (node.getResources().isEmpty())
addToken(JavaTokenType.J_TRY_BEGIN, start, 3);
else
addToken(JavaTokenType.J_TRY_WITH_RESOURCE, start, 3);
addToken(JavaTokenType.J_TRY_BEGIN, start, 3);
scan(node.getResources(), p);
scan(node.getBlock(), p);
long end = positions.getEndPosition(ast, node);
addToken(JavaTokenType.J_TRY_END, end, 1);
scan(node.getCatches(), p);
if (node.getFinallyBlock() != null) {
start = positions.getStartPosition(ast, node.getFinallyBlock());
addToken(JavaTokenType.J_FINALLY, start, 3);
addToken(JavaTokenType.J_FINALLY_BEGIN, start, 3);
scan(node.getFinallyBlock(), p);
end = positions.getEndPosition(ast, node.getFinallyBlock());
addToken(JavaTokenType.J_FINALLY_END, end, 1);
}
scan(node.getFinallyBlock(), p);
return null; // return value isn't used
}

Expand Down Expand Up @@ -308,7 +309,7 @@ public Object visitNewClass(NewClassTree node, Object p) {
@Override
public Object visitTypeParameter(TypeParameterTree node, Object p) {
long start = positions.getStartPosition(ast, node);
// This is odd, but also done like this in Java17
// This is odd, but also done like this in Java 1.7
addToken(JavaTokenType.J_GENERIC, start, 1);
return super.visitTypeParameter(node, p);
}
Expand Down Expand Up @@ -368,6 +369,7 @@ public Object visitAssert(AssertTree node, Object p) {
public Object visitVariable(VariableTree node, Object p) {
long start = positions.getStartPosition(ast, node);
addToken(JavaTokenType.J_VARDEF, start, node.toString().length());

return super.visitVariable(node, p);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package de.jplag.java;

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

import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;

import org.junit.jupiter.api.BeforeEach;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.ParsingException;
import de.jplag.Token;
import de.jplag.TokenPrinter;
import de.jplag.TokenType;

/**
* Basic test class for testing the Java language module.
*/
public abstract class AbstractJavaLanguageTest {

private static final Path BASE_PATH = Path.of("src", "test", "resources", "java");
private static final String LOG_MESSAGE = "Tokens of {}: {}";
private final Logger logger = LoggerFactory.getLogger(JavaBlockTest.class);
private de.jplag.Language language;
protected File baseDirectory;

/**
* Sets up the base directory and the language module.
*/
@BeforeEach
void setUp() {
language = new Language();
baseDirectory = BASE_PATH.toFile();
assertTrue(baseDirectory.exists(), "Could not find base directory!");
}

/**
* Parses a java file in the {@link AbstractJavaLanguageTest.baseDirectory} and returns the list of token types.
* @param fileName is the name of the file to parse.
* @return the token types.
* @throws ParsingException if parsing fails.
*/
protected List<TokenType> parseJavaFile(String fileName) throws ParsingException {
List<Token> parsedTokens = language.parse(Set.of(new File(baseDirectory, fileName)));
List<TokenType> tokenTypes = parsedTokens.stream().map(Token::getType).toList();
logger.info(LOG_MESSAGE, fileName, tokenTypes);
logger.info(TokenPrinter.printTokens(parsedTokens, BASE_PATH.toAbsolutePath().toFile()));
return tokenTypes;
}

}
34 changes: 1 addition & 33 deletions languages/java/src/test/java/de/jplag/java/JavaBlockTest.java
Original file line number Diff line number Diff line change
@@ -1,59 +1,27 @@
package de.jplag.java;

import static org.junit.jupiter.api.Assertions.assertIterableEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.jplag.ParsingException;
import de.jplag.Token;
import de.jplag.TokenType;

/**
* Test cases regarding the extraction from implicit vs. explicit blocks in Java code.
*/
class JavaBlockTest {
private static final Path BASE_PATH = Path.of("src", "test", "resources", "java");
private static final String LOG_MESSAGE = "Tokens of {}: {}";

private final Logger logger = LoggerFactory.getLogger(JavaBlockTest.class);

private de.jplag.Language language;
private File baseDirectory;

@BeforeEach
public void setUp() {
language = new Language();
baseDirectory = BASE_PATH.toFile();
assertTrue(baseDirectory.exists(), "Could not find base directory!");
}

class JavaBlockTest extends AbstractJavaLanguageTest {
@ParameterizedTest
@MethodSource("provideClassPairs")
@DisplayName("Test pairs of classes with explicit vs. implicit blocks.")
void testJavaClassPair(String fileName1, String fileName2) throws ParsingException {
assertIterableEquals(parseJavaFile(fileName1), parseJavaFile(fileName2));
}

private List<TokenType> parseJavaFile(String fileName) throws ParsingException {
List<Token> parsedTokens = language.parse(Set.of(new File(baseDirectory, fileName)));
List<TokenType> tokenTypes = parsedTokens.stream().map(Token::getType).toList();
logger.info(LOG_MESSAGE, fileName, tokenTypes);
return tokenTypes;
}

/**
* Argument source for the test case {@link testJavaClassPair(String, String)).
*/
Expand Down
20 changes: 20 additions & 0 deletions languages/java/src/test/java/de/jplag/java/JavaTryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

package de.jplag.java;

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

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import de.jplag.ParsingException;

/**
* Test cases regarding the extraction from try vs. try with resource.
*/
class JavaTryTest extends AbstractJavaLanguageTest {
@Test
@DisplayName("Test difference between try block and try-with-resource block.")
void testJavaClassPair() throws ParsingException {
assertIterableEquals(parseJavaFile("Try.java"), parseJavaFile("TryWithResource.java"));
}
}
28 changes: 28 additions & 0 deletions languages/java/src/test/resources/java/Try.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package de.jplag.java;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class Try {
public static void main(String[] args) {
new Try().load("DoesNotExist.txt");
}

public void load(String path) {
Scanner scanner = null;
try {
Scanner other; // This is just here to keep the tokens similar.
scanner = new Scanner(new File(path));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
}
}
26 changes: 26 additions & 0 deletions languages/java/src/test/resources/java/TryWithResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package de.jplag.java;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

public class TryWithResource {
public static void main(String[] args) {
new TryWithResource().load("DoesNotExist.txt");
}

public void load(String path) {
Scanner other = null; // This is just here to keep the tokens similar.
try (Scanner scanner = other = new Scanner(new File(path))) { // same for = other =
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} finally {
if (other != null) { // This as well...
other.close(); // This as well...
}
}
}
}