Browse Source

migrate language frontend api to use Set<File> instead of String[]

Jan Wittler 4 years ago
parent
commit
094190af0a
40 changed files with 200 additions and 203 deletions
  1. 2 21
      core/src/main/java/de/jplag/Submission.java
  2. 4 5
      language-api/src/main/java/de/jplag/Language.java
  3. 3 2
      languages/cpp/src/main/java/de/jplag/cpp/Language.java
  4. 5 4
      languages/cpp/src/main/java/de/jplag/cpp/Scanner.java
  5. 5 5
      languages/cpp/src/main/javacc/CPP.jj
  6. 10 11
      languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java
  7. 3 3
      languages/csharp/src/main/java/de/jplag/csharp/Language.java
  8. 2 2
      languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java
  9. 3 1
      languages/emf-metamodel-dynamic/src/test/java/de/jplag/emf/dynamic/MinimalDynamicMetamodelTest.java
  10. 3 3
      languages/emf-metamodel/src/main/java/de/jplag/emf/Language.java
  11. 11 12
      languages/emf-metamodel/src/main/java/de/jplag/emf/parser/EcoreParser.java
  12. 4 5
      languages/emf-metamodel/src/main/java/de/jplag/emf/util/EMFUtil.java
  13. 5 5
      languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java
  14. 3 1
      languages/emf-metamodel/src/test/java/de/jplag/emf/MinimalMetamodelTest.java
  15. 8 8
      languages/golang/src/main/java/de/jplag/golang/GoParserAdapter.java
  16. 3 2
      languages/golang/src/main/java/de/jplag/golang/Language.java
  17. 2 1
      languages/golang/src/test/java/de/jplag/golang/GoLanguageTest.java
  18. 16 10
      languages/java/src/main/java/de/jplag/java/JavacAdapter.java
  19. 3 2
      languages/java/src/main/java/de/jplag/java/Language.java
  20. 3 4
      languages/java/src/main/java/de/jplag/java/Parser.java
  21. 10 11
      languages/kotlin/src/main/java/de/jplag/kotlin/KotlinParserAdapter.java
  22. 3 2
      languages/kotlin/src/main/java/de/jplag/kotlin/Language.java
  23. 2 1
      languages/kotlin/src/test/java/de/jplag/kotlin/KotlinLanguageTest.java
  24. 3 2
      languages/python-3/src/main/java/de/jplag/python3/Language.java
  25. 9 8
      languages/python-3/src/main/java/de/jplag/python3/Parser.java
  26. 3 2
      languages/rlang/src/main/java/de/jplag/rlang/Language.java
  27. 10 11
      languages/rlang/src/main/java/de/jplag/rlang/RParserAdapter.java
  28. 2 1
      languages/rlang/src/test/java/de/jplag/rlang/RLanguageTest.java
  29. 3 2
      languages/rust/src/main/java/de/jplag/rust/Language.java
  30. 10 11
      languages/rust/src/main/java/de/jplag/rust/RustParserAdapter.java
  31. 2 1
      languages/rust/src/test/java/de/jplag/rust/RustLanguageTest.java
  32. 3 2
      languages/scala/src/main/scala/de/jplag/scala/Language.scala
  33. 4 6
      languages/scala/src/main/scala/de/jplag/scala/Parser.scala
  34. 2 1
      languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java
  35. 3 2
      languages/scheme/src/main/java/de/jplag/scheme/Language.java
  36. 6 5
      languages/scheme/src/main/java/de/jplag/scheme/Parser.java
  37. 5 6
      languages/scheme/src/main/javacc/Scheme.jj
  38. 3 2
      languages/text/src/main/java/de/jplag/text/Language.java
  39. 11 12
      languages/text/src/main/java/de/jplag/text/ParserAdapter.java
  40. 8 8
      languages/text/src/test/java/jplag/text/TextLanguageTest.java

+ 2 - 21
core/src/main/java/de/jplag/Submission.java

@@ -3,9 +3,9 @@ package de.jplag;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
 
@@ -232,23 +232,6 @@ public class Submission implements Comparable<Submission> {
         return subdirectory;
     }
 
-    /**
-     * Map all files of this submission to their path relative to the submission directory.
-     * <p>
-     * This method is required to stay compatible with `language.parse(...)` as it requires the given file paths to be
-     * relative to the submission directory.
-     * <p>
-     * In a future update, `language.parse(...)` should probably just take a list of files.
-     * @param baseFile - File to base all relative file paths on.
-     * @param files - List of files to map.
-     * @return an array of file paths relative to the submission directory.
-     */
-    private String[] getRelativeFilePaths(File baseFile, Collection<File> files) {
-        Path baseFilePath = baseFile.toPath();
-
-        return files.stream().map(File::toPath).map(baseFilePath::relativize).map(Path::toString).toArray(String[]::new);
-    }
-
     /* package-private */ void markAsErroneous() {
         hasErrors = true;
     }
@@ -265,9 +248,7 @@ public class Submission implements Comparable<Submission> {
             return false;
         }
 
-        String[] relativeFilePaths = getRelativeFilePaths(submissionRootFile, files);
-
-        tokenList = language.parse(submissionRootFile, relativeFilePaths);
+        tokenList = language.parse(new HashSet<>(files));
         if (!language.hasErrors()) {
             if (tokenList.size() < 3) {
                 logger.error("Submission \"{}\" is too short!", name);

+ 4 - 5
language-api/src/main/java/de/jplag/Language.java

@@ -2,6 +2,7 @@ package de.jplag;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Common interface for all languages. Each language-front end must provide a concrete language implementation.
@@ -29,12 +30,11 @@ public interface Language {
     int minimumTokenMatch();
 
     /**
-     * Parses a set files in a directory.
-     * @param directory is the directory where the files are located.
-     * @param files are the names of the files to parse.
+     * Parses a set of files.
+     * @param files are the files to parse.
      * @return the list of parsed JPlag tokens.
      */
-    List<Token> parse(File directory, String[] files);
+    List<Token> parse(Set<File> files);
 
     /**
      * Whether errors were found during the last {@link #parse}.
@@ -62,5 +62,4 @@ public interface Language {
     default String viewFileSuffix() {
         return "";
     }
-
 }

+ 3 - 2
languages/cpp/src/main/java/de/jplag/cpp/Language.java

@@ -2,6 +2,7 @@ package de.jplag.cpp;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -38,8 +39,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File dir, String[] files) {
-        return this.scanner.scan(dir, files);
+    public List<Token> parse(Set<File> files) {
+        return this.scanner.scan(files);
     }
 
     @Override

+ 5 - 4
languages/cpp/src/main/java/de/jplag/cpp/Scanner.java

@@ -3,6 +3,7 @@ package de.jplag.cpp;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import de.jplag.AbstractParser;
 import de.jplag.Token;
@@ -19,13 +20,13 @@ public class Scanner extends AbstractParser {
         super();
     }
 
-    public List<Token> scan(File directory, String[] files) {
+    public List<Token> scan(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String currentFile : files) {
-            this.currentFile = currentFile;
+        for (File file : files) {
+            this.currentFile = file.getName();
             logger.trace("Scanning file {}", currentFile);
-            if (!CPPScanner.scanFile(directory, currentFile, this)) {
+            if (!CPPScanner.scanFile(file, this)) {
                 errors++;
             }
             tokens.add(Token.fileEnd(currentFile));

+ 5 - 5
languages/cpp/src/main/javacc/CPP.jj

@@ -24,22 +24,22 @@ import static de.jplag.cpp.CPPTokenType.*;
 public class CPPScanner {
     private Scanner delegatingScanner;
 
-    public static boolean scanFile(File dir, String fileName, Scanner delegatingScanner) {
+    public static boolean scanFile(File file, Scanner delegatingScanner) {
         CPPScanner scanner;
-        try(InputStream input = new NewlineStream(new FileInputStream(new File(dir, fileName)))) {
+        try(InputStream input = new NewlineStream(new FileInputStream(file))) {
             scanner = new CPPScanner(input, "UTF-8");
             scanner.delegatingScanner = delegatingScanner;
         } catch (IOException e) {
-            System.out.println("C/C++ Scanner: File " + fileName + " not found.");
+            System.out.println("C/C++ Scanner: File " + file.getName() + " not found.");
             return false;
         }
         try {
             scanner.scan();
         } catch (ParseException e) {
-            delegatingScanner.logger.error("Parsing Error in '" + fileName + "': " + e.getMessage());
+            delegatingScanner.logger.error("Parsing Error in '" + file.getName() + "': " + e.getMessage());
             return false;
         } catch (TokenMgrException e) {
-            delegatingScanner.logger.error("Scanning Error in '" + fileName + "': " + e.getMessage());
+            delegatingScanner.logger.error("Scanning Error in '" + file.getName() + "': " + e.getMessage());
             return false;
         }
         return true;

+ 10 - 11
languages/csharp/src/main/java/de/jplag/csharp/CSharpParserAdapter.java

@@ -5,6 +5,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -35,27 +36,25 @@ public class CSharpParserAdapter extends AbstractParser {
     }
 
     /**
-     * Parses all tokens form a list of files.
-     * @param directory is the base directory.
-     * @param fileNames is the list of file names.
+     * Parses all tokens from a set of files.
+     * @param files is the set of files.
      * @return the list of parsed tokens.
      */
-    public List<Token> parse(File directory, List<String> fileNames) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String fileName : fileNames) {
-            if (!parseFile(directory, fileName)) {
+        for (File file : files) {
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(fileName));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String fileName) {
-        File file = new File(directory, fileName);
+    private boolean parseFile(File file) {
         try (FileInputStream inputStream = new FileInputStream(file)) {
-            currentFile = fileName;
+            currentFile = file.getName();
 
             // create a lexer, a parser and a buffer between them.
             CSharpLexer lexer = new CSharpLexer(CharStreams.fromStream(inputStream));
@@ -72,7 +71,7 @@ public class CSharpParserAdapter extends AbstractParser {
                 treeWalker.walk(new CSharpListener(this), parseTree);
             }
         } catch (IOException exception) {
-            logger.error("Parsing Error in '" + fileName + "':" + File.separator + exception, exception);
+            logger.error("Parsing Error in '" + file.getName() + "':" + File.separator + exception, exception);
             return false;
         }
         return true;

+ 3 - 3
languages/csharp/src/main/java/de/jplag/csharp/Language.java

@@ -1,8 +1,8 @@
 package de.jplag.csharp;
 
 import java.io.File;
-import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -46,8 +46,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File dir, String[] files) {
-        return parser.parse(dir, Arrays.asList(files));
+    public List<Token> parse(Set<File> files) {
+        return parser.parse(files);
     }
 
     @Override

+ 2 - 2
languages/csharp/src/test/java/de/jplag/csharp/MinimalCSharpTest.java

@@ -26,6 +26,7 @@ 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.junit.jupiter.api.Test;
@@ -61,8 +62,7 @@ class MinimalCSharpTest {
                 ACCESSOR_END, ACCESSORS_END, CLASS_END, SharedTokenType.FILE_END);
 
         // Parse test input
-        String[] input = new String[] {TEST_SUBJECT};
-        List<Token> result = language.parse(baseDirectory, input);
+        List<Token> result = language.parse(Set.of(new File(baseDirectory, TEST_SUBJECT)));
         logger.info(TokenPrinter.printTokens(result, baseDirectory));
 
         // Compare parsed tokens:

+ 3 - 1
languages/emf-metamodel-dynamic/src/test/java/de/jplag/emf/dynamic/MinimalDynamicMetamodelTest.java

@@ -6,9 +6,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
 import java.nio.file.Path;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -40,7 +42,7 @@ class MinimalDynamicMetamodelTest {
 
     @Test
     void testBookstoreMetamodels() {
-        List<Token> result = language.parse(baseDirectory, TEST_SUBJECTS);
+        List<Token> result = language.parse(Arrays.stream(TEST_SUBJECTS).map(path -> new File(BASE_PATH.toFile(), path)).collect(Collectors.toSet()));
         List<TokenType> tokenTypes = result.stream().map(Token::getType).toList();
         logger.debug(TokenPrinter.printTokens(result, baseDirectory, Optional.of(Language.VIEW_FILE_SUFFIX)));
         logger.info("parsed token types: " + tokenTypes.stream().map(TokenType::getDescription).toList().toString());

+ 3 - 3
languages/emf-metamodel/src/main/java/de/jplag/emf/Language.java

@@ -1,8 +1,8 @@
 package de.jplag.emf;
 
 import java.io.File;
-import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 
 import org.eclipse.emf.ecore.EcorePackage;
 import org.kohsuke.MetaInfServices;
@@ -54,8 +54,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File dir, String[] files) {
-        return parser.parse(dir, Arrays.asList(files));
+    public List<Token> parse(Set<File> files) {
+        return parser.parse(files);
     }
 
     @Override

+ 11 - 12
languages/emf-metamodel/src/main/java/de/jplag/emf/parser/EcoreParser.java

@@ -3,6 +3,7 @@ package de.jplag.emf.parser;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.eclipse.emf.ecore.EObject;
 
@@ -33,29 +34,27 @@ public class EcoreParser extends AbstractParser {
     }
 
     /**
-     * Parses all tokens form a list of files.
-     * @param directory is the base directory.
-     * @param fileNames is the list of file names.
+     * Parses all tokens from a set of files.
+     * @param files is the set of files.
      * @return the list of parsed tokens.
      */
-    public List<Token> parse(File directory, List<String> fileNames) {
+    public List<Token> parse(Set<File> files) {
         errors = 0;
         tokens = new ArrayList<>();
-        for (String fileName : fileNames) {
-            currentFile = fileName;
-            String filePath = fileName.isEmpty() ? directory.toString() : directory.toString() + File.separator + fileName;
-            parseModelFile(filePath);
+        for (File file : files) {
+            currentFile = file.getName();
+            parseModelFile(file);
         }
         return tokens;
     }
 
     /**
      * Loads a metamodel from a file and parses it.
-     * @param filePath is the path to the metamodel file.
+     * @param file is the metamodel file.
      */
-    protected void parseModelFile(String filePath) {
-        treeView = new MetamodelTreeView(filePath);
-        List<EObject> model = EMFUtil.loadModel(filePath);
+    protected void parseModelFile(File file) {
+        treeView = new MetamodelTreeView(file);
+        List<EObject> model = EMFUtil.loadModel(file);
         if (model == null) {
             errors++;
         } else {

+ 4 - 5
languages/emf-metamodel/src/main/java/de/jplag/emf/util/EMFUtil.java

@@ -57,17 +57,16 @@ public final class EMFUtil {
 
     /**
      * Loads a model or metamodel from a absolute file path.
-     * @param filePath is the absolute path to the (meta)model.
+     * @param file is file to the (meta)model.
      * @return the content of the loaded (meta)model resource or null if it could not be loaded.
      */
-    public static List<EObject> loadModel(String filePath) {
+    public static List<EObject> loadModel(File file) {
         final ResourceSet resourceSet = new ResourceSetImpl();
         try {
-            final Resource resource = resourceSet.getResource(URI.createFileURI(filePath), true);
+            final Resource resource = resourceSet.getResource(URI.createFileURI(file.getAbsolutePath()), true);
             return resource.getContents();
         } catch (WrappedException exception) {
-            String name = new File(filePath).getName();
-            logger.error("Could not load " + name + ": " + exception.getCause().getMessage());
+            logger.error("Could not load " + file.getName() + ": " + exception.getCause().getMessage());
         }
         return null;
     }

+ 5 - 5
languages/emf-metamodel/src/main/java/de/jplag/emf/util/MetamodelTreeView.java

@@ -19,7 +19,7 @@ import de.jplag.emf.MetamodelToken;
  * @author Timur Saglam
  */
 public class MetamodelTreeView {
-    private final String filePath;
+    private final File file;
     private int lineIndex;
     private int columnIndex;
     private final StringBuilder viewBuilder;
@@ -28,10 +28,10 @@ public class MetamodelTreeView {
 
     /**
      * Creates a tree view for a metamodel.
-     * @param filePath is the path to the file where the metamodel is persisted.
+     * @param file is the file where the metamodel is persisted.
      */
-    public MetamodelTreeView(String filePath) {
-        this.filePath = filePath;
+    public MetamodelTreeView(File file) {
+        this.file = file;
         logger = LoggerFactory.getLogger(this.getClass());
         viewBuilder = new StringBuilder();
     }
@@ -85,7 +85,7 @@ public class MetamodelTreeView {
      * @param suffix is the suffix of the file to be written.
      */
     public void writeToFile(String suffix) {
-        File treeViewFile = new File(filePath + suffix);
+        File treeViewFile = new File(file, suffix);
         try (BufferedWriter writer = new BufferedWriter(new FileWriter(treeViewFile));) {
             if (!treeViewFile.createNewFile()) {
                 logger.warn("Overwriting tree view file: {}", treeViewFile);

+ 3 - 1
languages/emf-metamodel/src/test/java/de/jplag/emf/MinimalMetamodelTest.java

@@ -6,9 +6,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.File;
 import java.nio.file.Path;
+import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -40,7 +42,7 @@ class MinimalMetamodelTest {
 
     @Test
     void testBookstoreMetamodels() {
-        List<Token> result = language.parse(baseDirectory, TEST_SUBJECTS);
+        List<Token> result = language.parse(Arrays.stream(TEST_SUBJECTS).map(path -> new File(BASE_PATH.toFile(), path)).collect(Collectors.toSet()));
 
         logger.debug(TokenPrinter.printTokens(result, baseDirectory, Optional.of(Language.VIEW_FILE_SUFFIX)));
         List<TokenType> tokenTypes = result.stream().map(Token::getType).toList();

+ 8 - 8
languages/golang/src/main/java/de/jplag/golang/GoParserAdapter.java

@@ -5,6 +5,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -22,21 +23,20 @@ public class GoParserAdapter extends AbstractParser {
     private String currentFile;
     private List<Token> tokens;
 
-    public List<Token> parse(File directory, String[] fileNames) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
-        for (String file : fileNames) {
-            if (!parseFile(directory, file)) {
+        for (File file : files) {
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(file));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String fileName) {
-        File file = new File(directory, fileName);
+    private boolean parseFile(File file) {
         try (FileInputStream inputStream = new FileInputStream(file)) {
-            currentFile = fileName;
+            currentFile = file.getName();
 
             GoLexer lexer = new GoLexer(CharStreams.fromStream(inputStream));
             CommonTokenStream tokenStream = new CommonTokenStream(lexer);
@@ -51,7 +51,7 @@ public class GoParserAdapter extends AbstractParser {
                 treeWalker.walk(listener, parseTree);
             }
         } catch (IOException exception) {
-            logger.error("Parsing Error in '%s':".formatted(fileName), exception);
+            logger.error("Parsing Error in '%s':".formatted(file.getName()), exception);
             return false;
         }
         return true;

+ 3 - 2
languages/golang/src/main/java/de/jplag/golang/Language.java

@@ -2,6 +2,7 @@ package de.jplag.golang;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -41,8 +42,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File directory, String[] files) {
-        return parserAdapter.parse(directory, files);
+    public List<Token> parse(Set<File> files) {
+        return parserAdapter.parse(files);
     }
 
     @Override

+ 2 - 1
languages/golang/src/test/java/de/jplag/golang/GoLanguageTest.java

@@ -12,6 +12,7 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 import java.util.OptionalInt;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -58,7 +59,7 @@ class GoLanguageTest {
     @Test
     void parseTestFiles() {
         for (String fileName : testFiles) {
-            List<Token> tokens = language.parse(testFileLocation, new String[] {fileName});
+            List<Token> tokens = language.parse(Set.of(new File(testFileLocation, fileName)));
             String output = TokenPrinter.printTokens(tokens, testFileLocation);
             logger.info(output);
 

+ 16 - 10
languages/java/src/main/java/de/jplag/java/JavacAdapter.java

@@ -3,9 +3,9 @@ package de.jplag.java;
 import java.io.File;
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
-import java.nio.file.Paths;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 
 import javax.tools.Diagnostic;
 import javax.tools.DiagnosticCollector;
@@ -28,11 +28,11 @@ public class JavacAdapter {
 
     private static final JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
 
-    public int parseFiles(File directory, Iterable<File> pathedFiles, final Parser parser) {
+    public int parseFiles(Set<File> files, final Parser parser) {
         var listener = new DiagnosticCollector<>();
 
         try (final StandardJavaFileManager fileManager = javac.getStandardFileManager(listener, null, StandardCharsets.UTF_8)) {
-            var javaFiles = fileManager.getJavaFileObjectsFromFiles(pathedFiles);
+            var javaFiles = fileManager.getJavaFileObjectsFromFiles(files);
 
             // We need to disable annotation processing, see
             // https://stackoverflow.com/questions/72737445/system-java-compiler-behaves-different-depending-on-dependencies-defined-in-mave
@@ -40,7 +40,7 @@ public class JavacAdapter {
             final Trees trees = Trees.instance(task);
             final SourcePositions positions = trees.getSourcePositions();
             for (final CompilationUnitTree ast : executeCompilationTask(task, parser.logger)) {
-                final String filename = fileNameOf(directory, ast);
+                final String filename = relativeFileName(ast, files);
                 final LineMap map = ast.getLineMap();
                 ast.accept(new TokenGeneratingTreeScanner(filename, parser, map, positions, ast), null);
                 parser.add(Token.fileEnd(filename));
@@ -61,12 +61,18 @@ public class JavacAdapter {
         return abstractSyntaxTrees;
     }
 
-    private String fileNameOf(File directory, final CompilationUnitTree ast) {
-        if (directory == null)
-            return ast.getSourceFile().getName();
-        else {
-            return Paths.get(directory.toURI()).relativize(Paths.get(ast.getSourceFile().toUri())).toString();
-        }
+    private String relativeFileName(final CompilationUnitTree ast, Set<File> files) {
+        String fullFilePath = ast.getSourceFile().toUri().toString();
+        var matchingFile = files.stream().filter(file -> {
+            try {
+                if (file.getCanonicalPath().contains(fullFilePath)) {
+                    return true;
+                }
+            } catch (IOException e) {
+            }
+            return false;
+        }).map(File::getName).findFirst();
+        return matchingFile.orElse(ast.getSourceFile().getName());
     }
 
     private int processErrors(Logger logger, DiagnosticCollector<Object> listener) {

+ 3 - 2
languages/java/src/main/java/de/jplag/java/Language.java

@@ -2,6 +2,7 @@ package de.jplag.java;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -41,8 +42,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File directory, String[] files) {
-        return this.parser.parse(directory, files);
+    public List<Token> parse(Set<File> files) {
+        return this.parser.parse(files);
     }
 
     @Override

+ 3 - 4
languages/java/src/main/java/de/jplag/java/Parser.java

@@ -2,8 +2,8 @@ package de.jplag.java;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 
 import de.jplag.AbstractParser;
 import de.jplag.Token;
@@ -19,11 +19,10 @@ public class Parser extends AbstractParser {
         super();
     }
 
-    public List<Token> parse(File directory, String[] files) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        var pathedFiles = Arrays.stream(files).map(it -> new File(directory, it)).toList();
-        errors += new JavacAdapter().parseFiles(directory, pathedFiles, this);
+        errors += new JavacAdapter().parseFiles(files, this);
         return tokens;
     }
 

+ 10 - 11
languages/kotlin/src/main/java/de/jplag/kotlin/KotlinParserAdapter.java

@@ -5,6 +5,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -29,26 +30,24 @@ public class KotlinParserAdapter extends AbstractParser {
     }
 
     /**
-     * Parsers a list of files into a single list of {@link Token}s.
-     * @param directory the directory of the files.
-     * @param fileNames the file names of the files.
+     * Parsers a set of files into a single list of {@link Token}s.
+     * @param files the set of files.
      * @return a list containing all tokens of all files.
      */
-    public List<Token> parse(File directory, String[] fileNames) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
-        for (String file : fileNames) {
-            if (!parseFile(directory, file)) {
+        for (File file : files) {
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(file));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String fileName) {
-        File file = new File(directory, fileName);
+    private boolean parseFile(File file) {
         try (FileInputStream inputStream = new FileInputStream(file)) {
-            currentFile = fileName;
+            currentFile = file.getName();
 
             KotlinLexer lexer = new KotlinLexer(CharStreams.fromStream(inputStream));
             CommonTokenStream tokenStream = new CommonTokenStream(lexer);
@@ -63,7 +62,7 @@ public class KotlinParserAdapter extends AbstractParser {
                 treeWalker.walk(listener, parseTree);
             }
         } catch (IOException exception) {
-            logger.error("Parsing Error in '{}': {}{}", fileName, File.separator, exception);
+            logger.error("Parsing Error in '{}': {}{}", file.getName(), File.separator, exception);
             return false;
         }
         return true;

+ 3 - 2
languages/kotlin/src/main/java/de/jplag/kotlin/Language.java

@@ -2,6 +2,7 @@ package de.jplag.kotlin;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -44,8 +45,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File directory, String[] files) {
-        return parserAdapter.parse(directory, files);
+    public List<Token> parse(Set<File> files) {
+        return parserAdapter.parse(files);
     }
 
     @Override

+ 2 - 1
languages/kotlin/src/test/java/de/jplag/kotlin/KotlinLanguageTest.java

@@ -10,6 +10,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -57,7 +58,7 @@ class KotlinLanguageTest {
     @Test
     void parseTestFiles() {
         for (String fileName : testFiles) {
-            List<Token> tokens = language.parse(testFileLocation, new String[] {fileName});
+            List<Token> tokens = language.parse(Set.of(new File(testFileLocation, fileName)));
             String output = TokenPrinter.printTokens(tokens, testFileLocation);
             logger.info(output);
 

+ 3 - 2
languages/python-3/src/main/java/de/jplag/python3/Language.java

@@ -2,6 +2,7 @@ package de.jplag.python3;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -39,8 +40,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File dir, String[] files) {
-        return this.parser.parse(dir, files);
+    public List<Token> parse(Set<File> files) {
+        return this.parser.parse(files);
     }
 
     @Override

+ 9 - 8
languages/python-3/src/main/java/de/jplag/python3/Parser.java

@@ -6,6 +6,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.CharStreams;
@@ -32,26 +33,26 @@ public class Parser extends AbstractParser {
         super();
     }
 
-    public List<Token> parse(File directory, String[] files) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String file : files) {
-            logger.trace("Parsing file {}", file);
-            if (!parseFile(directory, file)) {
+        for (File file : files) {
+            logger.trace("Parsing file {}", file.getName());
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(file));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String file) {
+    private boolean parseFile(File file) {
         BufferedInputStream inputStream;
 
         CharStream input;
         try {
-            inputStream = new BufferedInputStream(new FileInputStream(new File(directory, file)));
-            currentFile = file;
+            inputStream = new BufferedInputStream(new FileInputStream(file));
+            currentFile = file.getName();
             input = CharStreams.fromStream(inputStream);
 
             // create a lexer that feeds off of input CharStream

+ 3 - 2
languages/rlang/src/main/java/de/jplag/rlang/Language.java

@@ -2,6 +2,7 @@ package de.jplag.rlang;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -44,8 +45,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File directory, String[] files) {
-        return parserAdapter.parse(directory, files);
+    public List<Token> parse(Set<File> files) {
+        return parserAdapter.parse(files);
     }
 
     @Override

+ 10 - 11
languages/rlang/src/main/java/de/jplag/rlang/RParserAdapter.java

@@ -5,6 +5,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -36,27 +37,25 @@ public class RParserAdapter extends AbstractParser {
     }
 
     /**
-     * Parsers a list of files into a single token list of {@link Token}s.
-     * @param directory the directory of the files.
-     * @param fileNames the file names of the files.
+     * Parsers a set of files into a single token list of {@link Token}s.
+     * @param files the set of files.
      * @return a list containing all tokens of all files.
      */
-    public List<Token> parse(File directory, String[] fileNames) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String fileName : fileNames) {
-            if (!parseFile(directory, fileName)) {
+        for (File file : files) {
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(fileName));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String fileName) {
-        File file = new File(directory, fileName);
+    private boolean parseFile(File file) {
         try (FileInputStream inputStream = new FileInputStream(file)) {
-            currentFile = fileName;
+            currentFile = file.getName();
 
             // create a lexer, a parser and a buffer between them.
             RLexer lexer = new RLexer(CharStreams.fromStream(inputStream));
@@ -78,7 +77,7 @@ public class RParserAdapter extends AbstractParser {
                 treeWalker.walk(new JPlagRListener(this), parseTree);
             }
         } catch (IOException exception) {
-            logger.error("Parsing Error in '" + fileName + "': " + File.separator + exception.getMessage(), exception);
+            logger.error("Parsing Error in '" + file.getName() + "': " + File.separator + exception.getMessage(), exception);
             return false;
         }
         return true;

+ 2 - 1
languages/rlang/src/test/java/de/jplag/rlang/RLanguageTest.java

@@ -10,6 +10,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -47,7 +48,7 @@ class RLanguageTest {
     @Test
     void parseTestFiles() {
         for (String fileName : testFiles) {
-            List<Token> tokens = language.parse(testFileLocation, new String[] {fileName});
+            List<Token> tokens = language.parse(Set.of(new File(testFileLocation, fileName)));
             String output = TokenPrinter.printTokens(tokens, testFileLocation);
             logger.info(output);
 

+ 3 - 2
languages/rust/src/main/java/de/jplag/rust/Language.java

@@ -2,6 +2,7 @@ package de.jplag.rust;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import de.jplag.Token;
 
@@ -39,8 +40,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File directory, String[] files) {
-        return parserAdapter.parse(directory, files);
+    public List<Token> parse(Set<File> files) {
+        return parserAdapter.parse(files);
     }
 
     @Override

+ 10 - 11
languages/rust/src/main/java/de/jplag/rust/RustParserAdapter.java

@@ -5,6 +5,7 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import org.antlr.v4.runtime.CharStreams;
 import org.antlr.v4.runtime.CommonTokenStream;
@@ -23,27 +24,25 @@ public class RustParserAdapter extends AbstractParser {
     private List<Token> tokens;
 
     /**
-     * Parsers a list of files into a single list of {@link Token}s.
-     * @param directory the directory of the files.
-     * @param fileNames the file names of the files.
+     * Parsers a set of files into a single list of {@link Token}s.
+     * @param files the set of files.
      * @return a list containing all tokens of all files.
      */
-    public List<Token> parse(File directory, String[] fileNames) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String fileName : fileNames) {
-            if (!parseFile(directory, fileName)) {
+        for (File file : files) {
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(fileName));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String fileName) {
-        File file = new File(directory, fileName);
+    private boolean parseFile(File file) {
         try (FileInputStream inputStream = new FileInputStream(file)) {
-            currentFile = fileName;
+            currentFile = file.getName();
 
             // create a lexer, a parser and a buffer between them.
             RustLexer lexer = new RustLexer(CharStreams.fromStream(inputStream));
@@ -61,7 +60,7 @@ public class RustParserAdapter extends AbstractParser {
                 treeWalker.walk(new JPlagRustListener(this), parseTree);
             }
         } catch (IOException exception) {
-            logger.error("Parsing Error in '" + fileName + "':" + File.separator, exception);
+            logger.error("Parsing Error in '" + file.getName() + "':" + File.separator, exception);
             return false;
         }
         return true;

+ 2 - 1
languages/rust/src/test/java/de/jplag/rust/RustLanguageTest.java

@@ -9,6 +9,7 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -51,7 +52,7 @@ class RustLanguageTest {
     @Test
     void parseTestFiles() {
         for (String fileName : testFiles) {
-            List<Token> tokens = language.parse(testFileLocation, new String[] {fileName});
+            List<Token> tokens = language.parse(Set.of(new File(testFileLocation, fileName)));
             String output = TokenPrinter.printTokens(tokens, testFileLocation);
             logger.info(output);
 

+ 3 - 2
languages/scala/src/main/scala/de/jplag/scala/Language.scala

@@ -5,7 +5,8 @@ import de.jplag.Token
 import java.io.File
 import org.kohsuke.MetaInfServices
 
-import scala.jdk.CollectionConverters.SeqHasAsJava
+import java.util
+import scala.jdk.CollectionConverters.{SeqHasAsJava, SetHasAsScala}
 
 class Language extends de.jplag.Language {
   private val parser = new Parser
@@ -19,7 +20,7 @@ class Language extends de.jplag.Language {
 
   override def minimumTokenMatch = 8
 
-  override def parse(dir: File, files: Array[String]): java.util.List[Token] = this.parser.parse(dir, files).asJava
+  override def parse(files: util.Set[File]): java.util.List[Token] = this.parser.parse(files.asScala.toSet).asJava
 
   override def hasErrors: Boolean = this.parser.hasErrors
 

+ 4 - 6
languages/scala/src/main/scala/de/jplag/scala/Parser.scala

@@ -330,13 +330,12 @@ class Parser extends AbstractParser {
         }
     }
 
-    def parse(directory: File, files: Array[String]): List[Token] = {
+    def parse(files: Set[File]): List[Token] = {
         tokens = ListBuffer()
         errors = 0
 
         for (file <- files) {
-            currentFile = file
-            if (!parseFile(directory, file)) {
+            if (!parseFile(file)) {
                 errors += 1
             }
             System.gc()
@@ -345,11 +344,10 @@ class Parser extends AbstractParser {
         tokens.toList
     }
 
-    private def parseFile(directory: File, fileName: String): Boolean = {
-        currentFile = fileName
+    private def parseFile(file: File): Boolean = {
+        currentFile = file.getName
 
         try {
-            val file = new File(directory, fileName)
             val bytes = java.nio.file.Files.readAllBytes(file.toPath)
             val text = new String(bytes, "UTF-8")
             val input = Input.VirtualFile(file.getPath, text)

+ 2 - 1
languages/scala/src/test/java/de/jplag/scala/ScalaLanguageTest.java

@@ -10,6 +10,7 @@ import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
@@ -58,7 +59,7 @@ class ScalaLanguageTest {
     @Test
     void parseTestFiles() {
         for (String fileName : testFiles) {
-            List<Token> tokens = language.parse(testFileLocation, new String[] {fileName});
+            List<Token> tokens = language.parse(Set.of(new File(testFileLocation, fileName)));
             String output = TokenPrinter.printTokens(tokens, testFileLocation);
             logger.info(output);
 

+ 3 - 2
languages/scheme/src/main/java/de/jplag/scheme/Language.java

@@ -2,6 +2,7 @@ package de.jplag.scheme;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -38,8 +39,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File dir, String[] files) {
-        return this.parser.parse(dir, files);
+    public List<Token> parse(Set<File> files) {
+        return this.parser.parse(files);
     }
 
     @Override

+ 6 - 5
languages/scheme/src/main/java/de/jplag/scheme/Parser.java

@@ -3,6 +3,7 @@ package de.jplag.scheme;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 import de.jplag.AbstractParser;
 import de.jplag.Token;
@@ -20,13 +21,13 @@ public class Parser extends AbstractParser {
         super();
     }
 
-    public List<Token> parse(File directory, String[] files) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String file : files) {
-            currentFile = file;
-            logger.trace("Parsing file {}", file);
-            if (!SchemeParser.parseFile(directory, file, null, this)) {
+        for (File file : files) {
+            currentFile = file.getName();
+            logger.trace("Parsing file {}", file.getName());
+            if (!SchemeParser.parseFile(file, null, this)) {
                 errors++;
             }
             tokens.add(Token.fileEnd(currentFile));

+ 5 - 6
languages/scheme/src/main/javacc/Scheme.jj

@@ -63,10 +63,9 @@ public class SchemeParser {
     private static int templateParam;
     private Parser parser2;
 
-    public static boolean parseFile(File dir, String fileName, SchemeParser parser, Parser parserX) {
-        File file = null;
+    public static boolean parseFile(File file, SchemeParser parser, Parser parserX) {
         try {
-            FileInputStream in = new FileInputStream(file = new File(dir, fileName));
+            FileInputStream in = new FileInputStream(file);
             if (parser == null) {
                 parser = new SchemeParser(in, "UTF-8");
             } else {
@@ -74,16 +73,16 @@ public class SchemeParser {
             }
             parser.parser2 = parserX;
         } catch (FileNotFoundException e) {
-            System.out.println("Scheme Parser R4RS:  File " + fileName + " not found.");
+            System.out.println("Scheme Parser R4RS:  File " + file.getName() + " not found.");
             return false;
         }
         try {
             parser.Program();
         } catch (ParseException e) {
-            parserX.logger.error("Parsing Error in '" + fileName + "': " + e.getMessage());
+            parserX.logger.error("Parsing Error in '" + file.getName() + "': " + e.getMessage());
             return false;
         } catch (TokenMgrException e) {
-            parserX.logger.error("Scanning Error in '" + fileName + "': " + e.getMessage());
+            parserX.logger.error("Scanning Error in '" + file.getName() + "': " + e.getMessage());
             return false;
         }
         return true;

+ 3 - 2
languages/text/src/main/java/de/jplag/text/Language.java

@@ -2,6 +2,7 @@ package de.jplag.text;
 
 import java.io.File;
 import java.util.List;
+import java.util.Set;
 
 import org.kohsuke.MetaInfServices;
 
@@ -43,8 +44,8 @@ public class Language implements de.jplag.Language {
     }
 
     @Override
-    public List<Token> parse(File dir, String[] files) {
-        return parserAdapter.parse(dir, files);
+    public List<Token> parse(Set<File> files) {
+        return parserAdapter.parse(files);
     }
 
     @Override

+ 11 - 12
languages/text/src/main/java/de/jplag/text/ParserAdapter.java

@@ -3,10 +3,10 @@ package de.jplag.text;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
-import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
+import java.util.Set;
 
 import de.jplag.AbstractParser;
 import de.jplag.Token;
@@ -37,25 +37,24 @@ public class ParserAdapter extends AbstractParser {
         this.pipeline = new StanfordCoreNLP(properties);
     }
 
-    public List<Token> parse(File directory, String[] files) {
+    public List<Token> parse(Set<File> files) {
         tokens = new ArrayList<>();
         errors = 0;
-        for (String file : files) {
+        for (File file : files) {
             logger.trace("Parsing file {}", file);
-            if (!parseFile(directory, file)) {
+            if (!parseFile(file)) {
                 errors++;
             }
-            tokens.add(Token.fileEnd(file));
+            tokens.add(Token.fileEnd(file.getName()));
         }
         return tokens;
     }
 
-    private boolean parseFile(File directory, String file) {
-        this.currentFile = file;
+    private boolean parseFile(File file) {
+        this.currentFile = file.getName();
         this.currentLine = 1; // lines start at 1
         this.currentLineBreakIndex = 0;
-        Path filePath = directory.toPath().resolve(file);
-        String content = readFile(filePath);
+        String content = readFile(file);
         if (content == null) {
             return false;
         }
@@ -105,11 +104,11 @@ public class ParserAdapter extends AbstractParser {
         tokens.add(new Token(new TextTokenType(text), currentFile, currentLine, column, length));
     }
 
-    private String readFile(Path filePath) {
+    private String readFile(File file) {
         try {
-            return Files.readString(filePath);
+            return Files.readString(file.toPath());
         } catch (IOException e) {
-            logger.error("Error reading from file {}", filePath, e);
+            logger.error("Error reading from file {}", file.getName(), e);
             return null;
         }
     }

+ 8 - 8
languages/text/src/test/java/jplag/text/TextLanguageTest.java

@@ -9,6 +9,7 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -42,8 +43,7 @@ class TextLanguageTest {
     @Test
     void testParsingJavaDoc() {
         // Parse test input
-        String[] input = new String[] {TEST_SUBJECT};
-        List<Token> result = language.parse(baseDirectory, input);
+        List<Token> result = language.parse(Set.of(new File(BASE_PATH.toFile(), TEST_SUBJECT)));
         logger.info(TokenPrinter.printTokens(result, baseDirectory));
 
         List<TokenType> tokenTypes = result.stream().map(Token::getType).toList();
@@ -54,18 +54,18 @@ class TextLanguageTest {
     @ParameterizedTest
     @ValueSource(strings = {"\n", "\r", "\r\n",})
     void testLineBreakInputs(String input, @TempDir Path tempDir) throws IOException {
-        Path file = tempDir.resolve("input.txt");
-        Files.writeString(file, input);
-        List<Token> result = language.parse(tempDir.toFile(), new String[] {"input.txt"});
+        Path filePath = tempDir.resolve("input.txt");
+        Files.writeString(filePath, input);
+        List<Token> result = language.parse(Set.of(filePath.toFile()));
         assertEquals(1, result.size());
     }
 
     @ParameterizedTest
     @ValueSource(strings = {"\ntoken", "\rtoken", "\r\ntoken",})
     void testTokenAfterLineBreak(String input, @TempDir Path tempDir) throws IOException {
-        Path file = tempDir.resolve("input.txt");
-        Files.writeString(file, input);
-        List<Token> result = language.parse(tempDir.toFile(), new String[] {"input.txt"});
+        Path filePath = tempDir.resolve("input.txt");
+        Files.writeString(filePath, input);
+        List<Token> result = language.parse(Set.of(filePath.toFile()));
         assertEquals(2, result.get(0).getLine());
     }