Browse Source

Added SHORT_NAME to each language frontend. Removed not needed dependencies from JPlag.

Dominik Fuchß 4 years ago
parent
commit
f2927bd6df

+ 42 - 0
jplag.cli/pom.xml

@@ -12,6 +12,48 @@
             <groupId>de.jplag</groupId>
             <groupId>de.jplag</groupId>
             <artifactId>jplag</artifactId>
             <artifactId>jplag</artifactId>
         </dependency>
         </dependency>
+        <!-- Languages -->
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>frontend-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>text</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>python-3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>csharp-6</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>cpp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>rlang</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>kotlin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>scheme</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>de.jplag</groupId>
+            <artifactId>chars</artifactId>
+        </dependency>
+        <!-- CLI -->
         <dependency>
         <dependency>
             <groupId>net.sourceforge.argparse4j</groupId>
             <groupId>net.sourceforge.argparse4j</groupId>
             <artifactId>argparse4j</artifactId>
             <artifactId>argparse4j</artifactId>

+ 3 - 10
jplag.cli/src/main/java/de/jplag/CommandLineArgument.java

@@ -2,9 +2,7 @@ package de.jplag;
 
 
 import static de.jplag.CLI.CLUSTERING_GROUP_NAME;
 import static de.jplag.CLI.CLUSTERING_GROUP_NAME;
 import static de.jplag.CLI.CLUSTERING_PREPROCESSING_GROUP_NAME;
 import static de.jplag.CLI.CLUSTERING_PREPROCESSING_GROUP_NAME;
-import static de.jplag.options.JPlagOptions.DEFAULT_COMPARISON_MODE;
-import static de.jplag.options.JPlagOptions.DEFAULT_SHOWN_COMPARISONS;
-import static de.jplag.options.JPlagOptions.DEFAULT_SIMILARITY_THRESHOLD;
+import static de.jplag.options.JPlagOptions.*;
 import static net.sourceforge.argparse4j.impl.Arguments.append;
 import static net.sourceforge.argparse4j.impl.Arguments.append;
 import static net.sourceforge.argparse4j.impl.Arguments.storeTrue;
 import static net.sourceforge.argparse4j.impl.Arguments.storeTrue;
 
 
@@ -13,16 +11,11 @@ import java.util.List;
 import java.util.Optional;
 import java.util.Optional;
 
 
 import net.sourceforge.argparse4j.impl.Arguments;
 import net.sourceforge.argparse4j.impl.Arguments;
-import net.sourceforge.argparse4j.inf.Argument;
-import net.sourceforge.argparse4j.inf.ArgumentAction;
-import net.sourceforge.argparse4j.inf.ArgumentContainer;
-import net.sourceforge.argparse4j.inf.ArgumentParser;
-import net.sourceforge.argparse4j.inf.Namespace;
+import net.sourceforge.argparse4j.inf.*;
 
 
 import de.jplag.clustering.ClusteringAlgorithm;
 import de.jplag.clustering.ClusteringAlgorithm;
 import de.jplag.clustering.ClusteringOptions;
 import de.jplag.clustering.ClusteringOptions;
 import de.jplag.clustering.algorithm.InterClusterSimilarity;
 import de.jplag.clustering.algorithm.InterClusterSimilarity;
-import de.jplag.options.JPlagOptions;
 import de.jplag.options.SimilarityMetric;
 import de.jplag.options.SimilarityMetric;
 import de.jplag.strategy.ComparisonMode;
 import de.jplag.strategy.ComparisonMode;
 
 
@@ -34,7 +27,7 @@ public enum CommandLineArgument {
     ROOT_DIRECTORY(new Builder("rootDir", String.class).nargs(NumberOfArgumentValues.ZERO_OR_MORE_VALUES)),
     ROOT_DIRECTORY(new Builder("rootDir", String.class).nargs(NumberOfArgumentValues.ZERO_OR_MORE_VALUES)),
     NEW_DIRECTORY(new Builder("-new", String.class).nargs(NumberOfArgumentValues.ONE_OR_MORE_VALUES)),
     NEW_DIRECTORY(new Builder("-new", String.class).nargs(NumberOfArgumentValues.ONE_OR_MORE_VALUES)),
     OLD_DIRECTORY(new Builder("-old", String.class).nargs(NumberOfArgumentValues.ONE_OR_MORE_VALUES)),
     OLD_DIRECTORY(new Builder("-old", String.class).nargs(NumberOfArgumentValues.ONE_OR_MORE_VALUES)),
-    LANGUAGE(new Builder("-l", String.class).defaultsTo(JPlagOptions.DEFAULT_LANGUAGE).choices(LanguageLoader.getAllLanguageNames())),
+    LANGUAGE(new Builder("-l", String.class).defaultsTo(de.jplag.java.Language.SHORT_NAME).choices(LanguageLoader.getAllLanguageNames())),
     BASE_CODE("-bc", String.class),
     BASE_CODE("-bc", String.class),
     VERBOSITY(new Builder("-v", String.class).defaultsTo("quiet").choices(List.of("quiet", "long"))), // TODO SH: Replace verbosity when integrating a
     VERBOSITY(new Builder("-v", String.class).defaultsTo("quiet").choices(List.of("quiet", "long"))), // TODO SH: Replace verbosity when integrating a
                                                                                                       // real logging library
                                                                                                       // real logging library

+ 8 - 2
jplag.cli/src/test/java/de/jplag/cli/LanguageTest.java

@@ -3,19 +3,19 @@ package de.jplag.cli;
 import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit;
 import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Test;
 
 
 import de.jplag.CommandLineArgument;
 import de.jplag.CommandLineArgument;
 import de.jplag.Language;
 import de.jplag.Language;
 import de.jplag.LanguageLoader;
 import de.jplag.LanguageLoader;
-import de.jplag.options.JPlagOptions;
 
 
 class LanguageTest extends CommandLineInterfaceTest {
 class LanguageTest extends CommandLineInterfaceTest {
 
 
     @Test
     @Test
     void testDefaultLanguage() {
     void testDefaultLanguage() {
         buildOptionsFromCLI(CURRENT_DIRECTORY);
         buildOptionsFromCLI(CURRENT_DIRECTORY);
-        assertEquals(JPlagOptions.DEFAULT_LANGUAGE, options.getLanguageShortName());
+        assertEquals(de.jplag.java.Language.SHORT_NAME, options.getLanguageShortName());
     }
     }
 
 
     @Test
     @Test
@@ -25,6 +25,12 @@ class LanguageTest extends CommandLineInterfaceTest {
         assertEquals(1, statusCode);
         assertEquals(1, statusCode);
     }
     }
 
 
+    @Test
+    void testLoading() {
+        var languages = LanguageLoader.loadLanguages();
+        Assertions.assertEquals(9, languages.size());
+    }
+
     @Test
     @Test
     void testValidLanguages() {
     void testValidLanguages() {
         for (Language language : LanguageLoader.loadLanguages()) {
         for (Language language : LanguageLoader.loadLanguages()) {

+ 22 - 2
jplag.frontend-utils/src/main/java/de/jplag/LanguageLoader.java

@@ -12,6 +12,8 @@ import org.slf4j.LoggerFactory;
 public final class LanguageLoader {
 public final class LanguageLoader {
     private static final Logger logger = LoggerFactory.getLogger(LanguageLoader.class);
     private static final Logger logger = LoggerFactory.getLogger(LanguageLoader.class);
 
 
+    private static List<Language> loaded = null;
+
     private LanguageLoader() {
     private LanguageLoader() {
         throw new IllegalAccessError();
         throw new IllegalAccessError();
     }
     }
@@ -22,17 +24,28 @@ public final class LanguageLoader {
      * method does only return prototypes.
      * method does only return prototypes.
      * @return the languages
      * @return the languages
      */
      */
-    public static List<Language> loadLanguages() {
+    public static synchronized List<Language> loadLanguages() {
+        if (loaded != null)
+            return loaded;
+
+        Set<String> loadedShortNames = new HashSet<>();
         List<Language> languages = new ArrayList<>();
         List<Language> languages = new ArrayList<>();
 
 
         for (Language notInitializedLanguage : ServiceLoader.load(Language.class)) {
         for (Language notInitializedLanguage : ServiceLoader.load(Language.class)) {
+            String shortName = notInitializedLanguage.getShortName();
+            if (!loadedShortNames.add(shortName)) {
+                logger.error("Multiple implementations for a language '{}' are present in the classpath! Skipping ..", shortName);
+                languages.removeIf(l -> Objects.equals(shortName, l.getShortName()));
+                continue;
+            }
             logger.info("Loading Language Frontend '{}'", notInitializedLanguage.getName());
             logger.info("Loading Language Frontend '{}'", notInitializedLanguage.getName());
             languages.add(notInitializedLanguage);
             languages.add(notInitializedLanguage);
         }
         }
 
 
         languages.sort(Comparator.comparing(Language::getShortName));
         languages.sort(Comparator.comparing(Language::getShortName));
 
 
-        return languages;
+        loaded = Collections.unmodifiableList(languages);
+        return loaded;
     }
     }
 
 
     /**
     /**
@@ -56,4 +69,11 @@ public final class LanguageLoader {
     public static List<String> getAllLanguageNames() {
     public static List<String> getAllLanguageNames() {
         return loadLanguages().stream().map(Language::getShortName).toList();
         return loadLanguages().stream().map(Language::getShortName).toList();
     }
     }
+
+    /**
+     * Resets the internal cache of all loaded languages
+     */
+    public static synchronized void reload() {
+        loaded = null;
+    }
 }
 }

+ 2 - 1
jplag.frontend.chars/src/main/java/de/jplag/chars/Language.java

@@ -13,6 +13,7 @@ import de.jplag.TokenList;
 @MetaInfServices(de.jplag.Language.class)
 @MetaInfServices(de.jplag.Language.class)
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
 
 
+    public static final String SHORT_NAME = "char";
     private final Parser parser;
     private final Parser parser;
 
 
     /**
     /**
@@ -43,7 +44,7 @@ public class Language implements de.jplag.Language {
 
 
     @Override
     @Override
     public String getShortName() {
     public String getShortName() {
-        return "char";
+        return SHORT_NAME;
     }
     }
 
 
     @Override
     @Override

+ 3 - 1
jplag.frontend.cpp/src/main/java/de/jplag/cpp/Language.java

@@ -9,6 +9,8 @@ import de.jplag.TokenList;
 
 
 @MetaInfServices(de.jplag.Language.class)
 @MetaInfServices(de.jplag.Language.class)
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
+    public static final String SHORT_NAME = "cpp";
+
     private final Scanner scanner; // cpp code is scanned not parsed
     private final Scanner scanner; // cpp code is scanned not parsed
 
 
     /**
     /**
@@ -39,7 +41,7 @@ public class Language implements de.jplag.Language {
 
 
     @Override
     @Override
     public String getShortName() {
     public String getShortName() {
-        return "cpp";
+        return SHORT_NAME;
     }
     }
 
 
     @Override
     @Override

+ 3 - 1
jplag.frontend.java/src/main/java/de/jplag/java/Language.java

@@ -12,6 +12,8 @@ import de.jplag.TokenList;
  */
  */
 @MetaInfServices(de.jplag.Language.class)
 @MetaInfServices(de.jplag.Language.class)
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
+    public static final String SHORT_NAME = "java";
+
     private final Parser parser;
     private final Parser parser;
 
 
     /**
     /**
@@ -42,7 +44,7 @@ public class Language implements de.jplag.Language {
 
 
     @Override
     @Override
     public String getShortName() {
     public String getShortName() {
-        return "java";
+        return SHORT_NAME;
     }
     }
 
 
     @Override
     @Override

+ 1 - 1
jplag.frontend.kotlin/src/main/java/de/jplag/kotlin/Language.java

@@ -14,7 +14,7 @@ import de.jplag.TokenList;
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
 
 
     private static final String NAME = "Kotlin Parser";
     private static final String NAME = "Kotlin Parser";
-    private static final String SHORT_NAME = "kotlin";
+    public static final String SHORT_NAME = "kotlin";
     private static final int DEFAULT_MIN_TOKEN_MATCH = 8;
     private static final int DEFAULT_MIN_TOKEN_MATCH = 8;
     private static final String[] FILE_EXTENSIONS = {".kt"};
     private static final String[] FILE_EXTENSIONS = {".kt"};
     private final KotlinParserAdapter parserAdapter;
     private final KotlinParserAdapter parserAdapter;

+ 3 - 1
jplag.frontend.python-3/src/main/java/de/jplag/python3/Language.java

@@ -10,6 +10,8 @@ import de.jplag.TokenList;
 @MetaInfServices(de.jplag.Language.class)
 @MetaInfServices(de.jplag.Language.class)
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
 
 
+    public static final String SHORT_NAME = "python3";
+
     private final Parser parser;
     private final Parser parser;
 
 
     /**
     /**
@@ -40,7 +42,7 @@ public class Language implements de.jplag.Language {
 
 
     @Override
     @Override
     public String getShortName() {
     public String getShortName() {
-        return "python3";
+        return SHORT_NAME;
     }
     }
 
 
     @Override
     @Override

+ 1 - 1
jplag.frontend.rlang/src/main/java/de/jplag/rlang/Language.java

@@ -14,7 +14,7 @@ import de.jplag.TokenList;
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
 
 
     private static final String NAME = "R Parser";
     private static final String NAME = "R Parser";
-    private static final String SHORT_NAME = "rlang";
+    public static final String SHORT_NAME = "rlang";
     private static final int DEFAULT_MIN_TOKEN_MATCH = 8;
     private static final int DEFAULT_MIN_TOKEN_MATCH = 8;
     private static final String[] FILE_EXTENSION = {".R", ".r"};
     private static final String[] FILE_EXTENSION = {".R", ".r"};
     private final RParserAdapter parserAdapter;
     private final RParserAdapter parserAdapter;

+ 3 - 1
jplag.frontend.scheme/src/main/java/de/jplag/scheme/Language.java

@@ -9,6 +9,8 @@ import de.jplag.TokenList;
 
 
 @MetaInfServices(de.jplag.Language.class)
 @MetaInfServices(de.jplag.Language.class)
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
+
+    public static final String SHORT_NAME = "scheme";
     private final de.jplag.scheme.Parser parser;
     private final de.jplag.scheme.Parser parser;
 
 
     /**
     /**
@@ -39,7 +41,7 @@ public class Language implements de.jplag.Language {
 
 
     @Override
     @Override
     public String getShortName() {
     public String getShortName() {
-        return "scheme";
+        return SHORT_NAME;
     }
     }
 
 
     @Override
     @Override

+ 2 - 1
jplag.frontend.text/src/main/java/de/jplag/text/Language.java

@@ -11,6 +11,7 @@ import de.jplag.TokenList;
 @MetaInfServices(de.jplag.Language.class)
 @MetaInfServices(de.jplag.Language.class)
 public class Language implements de.jplag.Language {
 public class Language implements de.jplag.Language {
 
 
+    public static final String SHORT_NAME = "text";
     private final Parser parser;
     private final Parser parser;
 
 
     /**
     /**
@@ -41,7 +42,7 @@ public class Language implements de.jplag.Language {
 
 
     @Override
     @Override
     public String getShortName() {
     public String getShortName() {
-        return "text";
+        return SHORT_NAME;
     }
     }
 
 
     @Override
     @Override

+ 4 - 20
jplag/pom.xml

@@ -25,41 +25,25 @@
             <groupId>de.jplag</groupId>
             <groupId>de.jplag</groupId>
             <artifactId>frontend-utils</artifactId>
             <artifactId>frontend-utils</artifactId>
         </dependency>
         </dependency>
-        <dependency>
-            <groupId>de.jplag</groupId>
-            <artifactId>text</artifactId>
-        </dependency>
         <dependency>
         <dependency>
             <groupId>de.jplag</groupId>
             <groupId>de.jplag</groupId>
             <artifactId>java</artifactId>
             <artifactId>java</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>de.jplag</groupId>
-            <artifactId>python-3</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>de.jplag</groupId>
-            <artifactId>csharp-6</artifactId>
+            <scope>test</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>de.jplag</groupId>
             <groupId>de.jplag</groupId>
             <artifactId>cpp</artifactId>
             <artifactId>cpp</artifactId>
+            <scope>test</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>de.jplag</groupId>
             <groupId>de.jplag</groupId>
             <artifactId>rlang</artifactId>
             <artifactId>rlang</artifactId>
+            <scope>test</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>de.jplag</groupId>
             <groupId>de.jplag</groupId>
             <artifactId>kotlin</artifactId>
             <artifactId>kotlin</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>de.jplag</groupId>
-            <artifactId>scheme</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>de.jplag</groupId>
-            <artifactId>chars</artifactId>
+            <scope>test</scope>
         </dependency>
         </dependency>
     </dependencies>
     </dependencies>
 </project>
 </project>

+ 0 - 3
jplag/src/main/java/de/jplag/options/JPlagOptions.java

@@ -20,9 +20,6 @@ import de.jplag.strategy.ComparisonMode;
 public class JPlagOptions {
 public class JPlagOptions {
 
 
     private static final Logger logger = LoggerFactory.getLogger("JPlag");
     private static final Logger logger = LoggerFactory.getLogger("JPlag");
-
-    public static final String DEFAULT_LANGUAGE = "java";
-
     public static final ComparisonMode DEFAULT_COMPARISON_MODE = NORMAL;
     public static final ComparisonMode DEFAULT_COMPARISON_MODE = NORMAL;
     public static final float DEFAULT_SIMILARITY_THRESHOLD = 0;
     public static final float DEFAULT_SIMILARITY_THRESHOLD = 0;
     public static final int DEFAULT_SHOWN_COMPARISONS = 30;
     public static final int DEFAULT_SHOWN_COMPARISONS = 30;

+ 0 - 16
jplag/src/test/java/de/jplag/LanguageTest.java

@@ -1,16 +0,0 @@
-package de.jplag;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-/**
- * This class contains integration tests for {@link Language} and {@link LanguageLoader}.
- * @author Dominik Fuchss
- */
-class LanguageTest {
-    @Test
-    void testLoading() {
-        var languages = LanguageLoader.loadLanguages();
-        Assertions.assertEquals(9, languages.size());
-    }
-}

+ 2 - 1
jplag/src/test/java/de/jplag/TestBase.java

@@ -6,6 +6,7 @@ import java.util.List;
 import java.util.function.Consumer;
 import java.util.function.Consumer;
 
 
 import de.jplag.exceptions.ExitException;
 import de.jplag.exceptions.ExitException;
+import de.jplag.java.Language;
 import de.jplag.options.JPlagOptions;
 import de.jplag.options.JPlagOptions;
 import de.jplag.options.Verbosity;
 import de.jplag.options.Verbosity;
 
 
@@ -45,7 +46,7 @@ public abstract class TestBase {
     }
     }
 
 
     protected JPlagResult runJPlag(List<String> newPaths, List<String> oldPaths, Consumer<JPlagOptions> customization) throws ExitException {
     protected JPlagResult runJPlag(List<String> newPaths, List<String> oldPaths, Consumer<JPlagOptions> customization) throws ExitException {
-        JPlagOptions options = new JPlagOptions(newPaths, oldPaths, JPlagOptions.DEFAULT_LANGUAGE);
+        JPlagOptions options = new JPlagOptions(newPaths, oldPaths, Language.SHORT_NAME);
         options.setVerbosity(Verbosity.LONG);
         options.setVerbosity(Verbosity.LONG);
         customization.accept(options);
         customization.accept(options);
         JPlag jplag = new JPlag(options);
         JPlag jplag = new JPlag(options);

+ 4 - 4
jplag/src/test/java/de/jplag/special/TokenPrinterTest.java

@@ -15,6 +15,7 @@ import de.jplag.options.JPlagOptions;
  * Special test case the does not really test anything but prints the tokens and the corresponding line of code.
  * Special test case the does not really test anything but prints the tokens and the corresponding line of code.
  * @author Timur Saglam
  * @author Timur Saglam
  */
  */
+// TODO DF: We could move some tests to their language frontends.
 public class TokenPrinterTest extends TestBase {
 public class TokenPrinterTest extends TestBase {
     private static final String LARGE_SPACE = "   ";
     private static final String LARGE_SPACE = "   ";
     private static final String LINE = "------------------";
     private static final String LINE = "------------------";
@@ -22,10 +23,9 @@ public class TokenPrinterTest extends TestBase {
     private static final int MIN_TOKEN_MATCH = 5;
     private static final int MIN_TOKEN_MATCH = 5;
     private static final String PRINTER_FOLDER = "PRINTER"; // in the folder 'jplag/src/test/resources/samples'
     private static final String PRINTER_FOLDER = "PRINTER"; // in the folder 'jplag/src/test/resources/samples'
 
 
-    private static final String LANGUAGE_CPP = "cpp";
-    private static final String LANGUAGE_R = "rlang";
-
-    private static final String LANGUAGE_KOTLIN = "kotlin";
+    private static final String LANGUAGE_CPP = de.jplag.cpp.Language.SHORT_NAME;
+    private static final String LANGUAGE_R = de.jplag.rlang.Language.SHORT_NAME;
+    private static final String LANGUAGE_KOTLIN = de.jplag.kotlin.Language.SHORT_NAME;
 
 
     @Disabled
     @Disabled
     @Test
     @Test