Compare commits
2 Commits
87ad5dca5b
...
656eaec1f5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
656eaec1f5 | ||
|
|
4ed31be23c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
gen/
|
gen/
|
||||||
sample#/
|
sample#/
|
||||||
|
target/
|
||||||
*.dot
|
*.dot
|
||||||
*.svg
|
*.svg
|
||||||
*.gefx
|
*.gefx
|
||||||
|
|||||||
6
.idea/copilot.data.migration.agent.xml
generated
Normal file
6
.idea/copilot.data.migration.agent.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AgentMigrationStateService">
|
||||||
|
<option name="migrationStatus" value="COMPLETED" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -34,5 +34,5 @@
|
|||||||
</list>
|
</list>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" default="true" project-jdk-name="homebrew-23" project-jdk-type="JavaSDK" />
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_X" default="true" project-jdk-name="homebrew-23" project-jdk-type="JavaSDK" />
|
||||||
</project>
|
</project>
|
||||||
41
README.md
Normal file
41
README.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
This is a first working state of the plugin. It has not been tested thoroughly. It has not been tested on windows at all.
|
||||||
|
|
||||||
|
This allows you to mix .java and .jav files in a single project. However, circular dependencies between .java and .jav files are not allowed as both compilers can read .class files but neither is aware of the other source files.
|
||||||
|
|
||||||
|
In theory, this should not be a problem as JavaTX is supposed to be a superset of Java. In practice however, there are features missing in JavaTX that Java supports (e.g. Arrays)
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
To install run
|
||||||
|
```mvn install```
|
||||||
|
in the root of this directory. This will install the plugin to your local maven repository.
|
||||||
|
|
||||||
|
Then you can use it as a plugin in your maven project by adding the plugin to your project's pom.xml. Make sure to change the javaTXCompilerLocation configuration variable to the correct location.
|
||||||
|
It needs to point to a jar file.
|
||||||
|
```
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>de.dhbwstuttgart</groupId>
|
||||||
|
<artifactId>javatx-compiler-plugin</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<configuration>
|
||||||
|
<javaTXCompilerLocation>path-to-your-java-tx-compiler-location</javaTXCompilerLocation>
|
||||||
|
</configuration>
|
||||||
|
<!-- Currently this is the way to override the mvn:compile lifecycle step with this plugin instead of the standard one -->
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>custom-compile</id>
|
||||||
|
<phase>compile</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>compile-javatx-project</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
... additional plugins
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can use the typical `mvn:compile` to compile the project.
|
||||||
@@ -3,6 +3,8 @@
|
|||||||
<component name="AdditionalModuleElements">
|
<component name="AdditionalModuleElements">
|
||||||
<content url="file://$MODULE_DIR$" dumb="true">
|
<content url="file://$MODULE_DIR$" dumb="true">
|
||||||
<sourceFolder url="file://$MODULE_DIR$/target/generated-sources/antlr4" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/target/generated-sources/antlr4" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/gen" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/sample#" />
|
||||||
</content>
|
</content>
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
5
pom.xml
5
pom.xml
@@ -9,8 +9,7 @@
|
|||||||
<packaging>maven-plugin</packaging>
|
<packaging>maven-plugin</packaging>
|
||||||
|
|
||||||
<name>javatx-compiler-plugin</name>
|
<name>javatx-compiler-plugin</name>
|
||||||
<!-- FIXME change it to the project's website -->
|
<url>https://dhbw-stuttgart.de/horb</url>
|
||||||
<url>http://www.example.com</url>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
@@ -122,7 +121,7 @@
|
|||||||
<artifactId>maven-plugin-plugin</artifactId>
|
<artifactId>maven-plugin-plugin</artifactId>
|
||||||
<version>3.13.1</version>
|
<version>3.13.1</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<goalPrefix>javatx-compiler</goalPrefix>
|
<goalPrefix>javatx-compiler-plugin</goalPrefix>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
package de.dhbwstuttgart;
|
|
||||||
|
|
||||||
import de.dhbwstuttgart.parser.JavaTXDependencyObtainer;
|
|
||||||
import org.antlr.v4.runtime.CharStream;
|
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTree;
|
|
||||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hello world!
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
public class App {
|
|
||||||
public static void main(String[] args) throws IOException {
|
|
||||||
CharStream input = CharStreams.fromStream(System.in);
|
|
||||||
|
|
||||||
JavaTXLexer lexer = new JavaTXLexer(input);
|
|
||||||
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
|
||||||
|
|
||||||
JavaTXParser parser = new JavaTXParser(tokens);
|
|
||||||
ParseTree tree = parser.sourceFile();
|
|
||||||
|
|
||||||
JavaTXDependencyObtainer dependencyObtainer = new JavaTXDependencyObtainer();
|
|
||||||
ParseTreeWalker walker = new ParseTreeWalker();
|
|
||||||
walker.walk(dependencyObtainer, tree);
|
|
||||||
|
|
||||||
System.out.println("Package: " + dependencyObtainer.getPackageDecl());
|
|
||||||
System.out.println("Imports: " + dependencyObtainer.getImports());
|
|
||||||
System.out.println("Classes: " + dependencyObtainer.getClasses());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@@ -46,10 +46,6 @@ public class JavaDependencyResolver {
|
|||||||
.setSymbolResolver(new JavaSymbolSolver(solver))
|
.setSymbolResolver(new JavaSymbolSolver(solver))
|
||||||
.setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_21);
|
.setLanguageLevel(ParserConfiguration.LanguageLevel.JAVA_21);
|
||||||
|
|
||||||
if (file.getName().equals("StatementToTargetExpression.java")){
|
|
||||||
System.out.println();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse a source file
|
// Parse a source file
|
||||||
JavaParser parser = new JavaParser(config);
|
JavaParser parser = new JavaParser(config);
|
||||||
|
|
||||||
@@ -152,7 +148,7 @@ public class JavaDependencyResolver {
|
|||||||
ResolvedType type = param.getType().resolve();
|
ResolvedType type = param.getType().resolve();
|
||||||
dependencies.addAll(getAllInnerTypes(type));
|
dependencies.addAll(getAllInnerTypes(type));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("Unresolved Parameter: " + param);
|
//System.out.println("Unresolved Parameter: " + param);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return dependencies;
|
return dependencies;
|
||||||
@@ -289,7 +285,6 @@ public class JavaDependencyResolver {
|
|||||||
else{
|
else{
|
||||||
return null; // Unsupported type declaration
|
return null; // Unsupported type declaration
|
||||||
}
|
}
|
||||||
System.out.println("generating dependency for type: " + typeDecl.getName() + " at path: " + path.toAbsolutePath());
|
|
||||||
if(isJavaTXFile) return new Dependency(packagePath, new JavaTXSourceFile(path.toAbsolutePath().toFile()), true);
|
if(isJavaTXFile) return new Dependency(packagePath, new JavaTXSourceFile(path.toAbsolutePath().toFile()), true);
|
||||||
else return new Dependency(packagePath, new JavaSourceFile(path.toAbsolutePath().toFile()), false);
|
else return new Dependency(packagePath, new JavaSourceFile(path.toAbsolutePath().toFile()), false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package de.dhbwstuttgart.javatxanalyzer;
|
package de.dhbwstuttgart.javatxanalyzer;
|
||||||
|
|
||||||
import com.github.javaparser.ast.type.ReferenceType;
|
|
||||||
import com.github.javaparser.resolution.types.ResolvedType;
|
|
||||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
|
||||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
|
||||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
|
||||||
@@ -11,6 +9,8 @@ import de.dhbwstuttgart.javaanalyzer.JavaTXTypeSolver;
|
|||||||
import de.dhbwstuttgart.parser.JavaTXDependencyObtainer;
|
import de.dhbwstuttgart.parser.JavaTXDependencyObtainer;
|
||||||
import de.dhbwstuttgart.parser.antlr.JavaTXLexer;
|
import de.dhbwstuttgart.parser.antlr.JavaTXLexer;
|
||||||
import de.dhbwstuttgart.parser.antlr.JavaTXParser;
|
import de.dhbwstuttgart.parser.antlr.JavaTXParser;
|
||||||
|
import de.dhbwstuttgart.structure.JavaSourceFile;
|
||||||
|
import de.dhbwstuttgart.structure.JavaTXSourceFile;
|
||||||
import org.antlr.v4.runtime.CharStream;
|
import org.antlr.v4.runtime.CharStream;
|
||||||
import org.antlr.v4.runtime.CharStreams;
|
import org.antlr.v4.runtime.CharStreams;
|
||||||
import org.antlr.v4.runtime.CommonTokenStream;
|
import org.antlr.v4.runtime.CommonTokenStream;
|
||||||
@@ -20,15 +20,13 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.Array;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class JavaTXDependencyResolver {
|
public class JavaTXDependencyResolver {
|
||||||
|
|
||||||
public static Set<Dependency> getDependenciesForJavaTXFile(File sourceFile, List<File> javaFilesPaths, List<File> javFilesPaths) throws IOException {
|
public static Set<Dependency> getDependenciesForJavaTXFile(File sourceFile, List<JavaSourceFile> javaFilesPaths, List<JavaTXSourceFile> javFilesPaths, List<File> srcDirs) throws IOException {
|
||||||
CharStream input = CharStreams.fromStream(new FileInputStream(sourceFile));
|
CharStream input = CharStreams.fromStream(new FileInputStream(sourceFile));
|
||||||
|
|
||||||
JavaTXLexer lexer = new JavaTXLexer(input);
|
JavaTXLexer lexer = new JavaTXLexer(input);
|
||||||
@@ -45,11 +43,11 @@ public class JavaTXDependencyResolver {
|
|||||||
|
|
||||||
CombinedTypeSolver solver = new CombinedTypeSolver();
|
CombinedTypeSolver solver = new CombinedTypeSolver();
|
||||||
solver.add(new ReflectionTypeSolver()); // JDK classes
|
solver.add(new ReflectionTypeSolver()); // JDK classes
|
||||||
for (var file : javaFilesPaths) {
|
for (var dir : srcDirs) {
|
||||||
solver.add(new JavaParserTypeSolver(file)); // Java Files
|
solver.add(new JavaParserTypeSolver(dir)); // Java Files
|
||||||
}
|
}
|
||||||
for (var file : javFilesPaths) {
|
for (var dir : srcDirs) {
|
||||||
solver.add(new JavaTXTypeSolver(file)); // Jav Files
|
solver.add(new JavaTXTypeSolver(dir)); // Jav Files
|
||||||
}
|
}
|
||||||
|
|
||||||
for(var dep : dependencyObtainer.getImports()){
|
for(var dep : dependencyObtainer.getImports()){
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package de.dhbwstuttgart.mojos;
|
package de.dhbwstuttgart.mojos;
|
||||||
|
|
||||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
|
||||||
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
|
||||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
|
||||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
|
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
|
||||||
import de.dhbwstuttgart.javaanalyzer.*;
|
import de.dhbwstuttgart.javaanalyzer.*;
|
||||||
import de.dhbwstuttgart.javatxanalyzer.JavaTXDependencyResolver;
|
import de.dhbwstuttgart.javatxanalyzer.JavaTXDependencyResolver;
|
||||||
import de.dhbwstuttgart.structure.*;
|
import de.dhbwstuttgart.structure.*;
|
||||||
import de.dhbwstuttgart.utils.CompilationHelper;
|
import de.dhbwstuttgart.utils.*;
|
||||||
import de.dhbwstuttgart.utils.Utils;
|
|
||||||
import org.apache.maven.artifact.Artifact;
|
import org.apache.maven.artifact.Artifact;
|
||||||
import org.apache.maven.plugin.AbstractMojo;
|
import org.apache.maven.plugin.AbstractMojo;
|
||||||
import org.apache.maven.plugin.MojoExecutionException;
|
import org.apache.maven.plugin.MojoExecutionException;
|
||||||
@@ -15,13 +15,15 @@ import org.apache.maven.plugin.MojoFailureException;
|
|||||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||||
import org.apache.maven.plugins.annotations.Mojo;
|
import org.apache.maven.plugins.annotations.Mojo;
|
||||||
import org.apache.maven.plugins.annotations.Parameter;
|
import org.apache.maven.plugins.annotations.Parameter;
|
||||||
|
import org.apache.maven.plugins.annotations.ResolutionScope;
|
||||||
import org.apache.maven.project.MavenProject;
|
import org.apache.maven.project.MavenProject;
|
||||||
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Mojo(name="compile javatx project", defaultPhase= LifecyclePhase.COMPILE)
|
@Mojo(name="compile-javatx", defaultPhase= LifecyclePhase.COMPILE, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
|
||||||
public class CompilerMojo extends AbstractMojo {
|
public class CompilerMojo extends AbstractMojo {
|
||||||
|
|
||||||
@Parameter(property = "JavaTXCompilerLocation", required = true)
|
@Parameter(property = "JavaTXCompilerLocation", required = true)
|
||||||
@@ -30,36 +32,83 @@ public class CompilerMojo extends AbstractMojo {
|
|||||||
@Parameter(defaultValue = "${project}", required = true, readonly = true)
|
@Parameter(defaultValue = "${project}", required = true, readonly = true)
|
||||||
private MavenProject project;
|
private MavenProject project;
|
||||||
|
|
||||||
|
// public static void main(String[] args) throws IOException {
|
||||||
|
// // List<File> compileSourceRoots = List.of(new File("/Users/julianschmidt/dhbw/javatx/JavaCompilerCoreInJavaTXMavenPlugin/src/main/java"), new File("/Users/julianschmidt/dhbw/javatx/JavaCompilerCoreInJavaTXMavenPlugin/target/generated-sources/antlr4"));
|
||||||
|
//// List<File> dependencies = List.of(
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/antlr/antlr4/4.13.2/antlr4-4.13.2.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/antlr/antlr4-runtime/4.13.2/antlr4-runtime-4.13.2.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/antlr/antlr-runtime/3.5.3/antlr-runtime-3.5.3.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/antlr/ST4/4.3.4/ST4-4.3.4.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/abego/treelayout/org.abego.treelayout.core/1.0.3/org.abego.treelayout.core-1.0.3.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/com/ibm/icu/icu4j/72.1/icu4j-72.1.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/commons-io/commons-io/2.19.0/commons-io-2.19.0.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/io/github/classgraph/classgraph/4.8.180/classgraph-4.8.180.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/com/google/guava/guava/33.4.8-jre/guava-33.4.8-jre.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/com/google/guava/failureaccess/1.0.3/failureaccess-1.0.3.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/com/google/errorprone/error_prone_annotations/2.36.0/error_prone_annotations-2.36.0.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/com/google/j2objc/j2objc-annotations/3.0.0/j2objc-annotations-3.0.0.jar"),
|
||||||
|
//// new File("/Users/julianschmidt/.m2/repository/org/ow2/asm/asm/9.8/asm-9.8.jar"));
|
||||||
|
//
|
||||||
|
//// File outputDir = new File("/Users/julianschmidt/dhbw/javatx/JavaCompilerCoreInJavaTXMavenPlugin/target/classes");
|
||||||
|
//// File compilerLocation = new File("/Users/julianschmidt/dhbw/javatx/JavaCompilerCore/target/JavaTXcompiler-0.1-jar-with-dependencies.jar");
|
||||||
|
// //compile(compileSourceRoots, dependencies, outputDir, compilerLocation);
|
||||||
|
// List<File> compileSourceRoots = List.of(new File("/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/sample#"));
|
||||||
|
// File outputDir = new File("/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/target/classes");
|
||||||
|
// File compilerLocation = new File("/Users/julianschmidt/dhbw/javatx/JavaCompilerCore/target/JavaTXcompiler-0.1-jar-with-dependencies.jar");
|
||||||
|
// compile(compileSourceRoots, List.of(), outputDir, compilerLocation);
|
||||||
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() throws MojoExecutionException, MojoFailureException {
|
public void execute() throws MojoExecutionException, MojoFailureException {
|
||||||
try {
|
|
||||||
List<?> dir = project.getCompileSourceRoots();
|
List<?> dir = project.getCompileSourceRoots();
|
||||||
List<File> compileSourceRoots = new ArrayList<>();
|
List<File> compileSourceRoots = new ArrayList<>();
|
||||||
for(var d : dir){
|
for (var d : dir) {
|
||||||
if (d instanceof String path) {
|
if (d instanceof String path) {
|
||||||
compileSourceRoots.add(new File(path));
|
compileSourceRoots.add(new File(path));
|
||||||
}
|
}
|
||||||
getLog().info("Compile Source Root: " + d);
|
getLog().info("Compile Source Root: " + d);
|
||||||
}
|
}
|
||||||
var files = CompilerMojo.getAllJavaFiles(compileSourceRoots.getFirst());
|
|
||||||
var javFiles = CompilerMojo.getAllJavaTXFiles(compileSourceRoots.getFirst());
|
List<File> mavenDependencies = new ArrayList<>();
|
||||||
Set<?> artifacts = project.getArtifacts();
|
|
||||||
|
|
||||||
for (var artifact : project.getArtifacts()) {
|
for (var artifact : project.getArtifacts()) {
|
||||||
if (artifact instanceof Artifact a){
|
if (artifact instanceof Artifact a) {
|
||||||
File file = a.getFile();
|
File file = a.getFile();
|
||||||
if (file != null) {
|
if (file != null) {
|
||||||
getLog().info("Dependency: " + a.getArtifactId() + " at " + file.getAbsolutePath());
|
mavenDependencies.add(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File outputDir = new File(project.getBuild().getOutputDirectory());
|
||||||
|
if (!outputDir.exists()) {
|
||||||
|
outputDir.mkdirs();
|
||||||
|
}
|
||||||
|
File javaTXCompilerPath = new File(javaTXCompilerLocation);
|
||||||
|
if(!javaTXCompilerPath.isFile()){
|
||||||
|
throw new MojoExecutionException("The Java-TX Compiler Path is not correct");
|
||||||
|
}
|
||||||
|
|
||||||
getLog().info("Project Path:" + dir);
|
try {
|
||||||
|
compile(compileSourceRoots, mavenDependencies, outputDir, javaTXCompilerPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compile(List<File> compileSourceRoots, List<File> dependencies, File outputDir, File javaTXCompilerLocation) throws IOException {
|
||||||
|
try {
|
||||||
|
var javaFiles = CompilerMojo.getAllJavaFiles(compileSourceRoots);
|
||||||
|
var javFiles = CompilerMojo.getAllJavaTXFiles(compileSourceRoots);
|
||||||
|
|
||||||
|
|
||||||
|
System.out.println(dependencies);
|
||||||
|
|
||||||
Map<File, Set<Dependency>> javDependenciesMap = new HashMap<>();
|
Map<File, Set<Dependency>> javDependenciesMap = new HashMap<>();
|
||||||
|
|
||||||
for (File file : javFiles) {
|
for (File file : javFiles) {
|
||||||
var a = JavaTXDependencyResolver.getDependenciesForJavaTXFile(file, compileSourceRoots, compileSourceRoots);
|
var a = JavaTXDependencyResolver.getDependenciesForJavaTXFile(file, javaFiles, javFiles, compileSourceRoots);
|
||||||
javDependenciesMap.put(new JavaTXSourceFile(file.getAbsoluteFile()), a);
|
javDependenciesMap.put(new JavaTXSourceFile(file.getAbsoluteFile()), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,11 +116,13 @@ public class CompilerMojo extends AbstractMojo {
|
|||||||
solver.add(new ReflectionTypeSolver()); // JDK classes
|
solver.add(new ReflectionTypeSolver()); // JDK classes
|
||||||
solver.add(new JavaParserTypeSolver(compileSourceRoots.getFirst())); //Java Files
|
solver.add(new JavaParserTypeSolver(compileSourceRoots.getFirst())); //Java Files
|
||||||
solver.add(new JavaTXTypeSolver(compileSourceRoots.getFirst())); //Jav Files
|
solver.add(new JavaTXTypeSolver(compileSourceRoots.getFirst())); //Jav Files
|
||||||
|
for (var dep : dependencies) {
|
||||||
|
solver.add(new JarTypeSolver(dep)); //add maven dependencies
|
||||||
|
}
|
||||||
|
|
||||||
Map<File, Set<Dependency>> dependenciesMap = new HashMap<>();
|
Map<File, Set<Dependency>> dependenciesMap = new HashMap<>();
|
||||||
|
|
||||||
for (File file: files){
|
for (File file : javaFiles) {
|
||||||
dependenciesMap.put(new JavaSourceFile(file.getAbsoluteFile()), JavaDependencyResolver.getAllDependenciesForJavaFile(file, solver));
|
dependenciesMap.put(new JavaSourceFile(file.getAbsoluteFile()), JavaDependencyResolver.getAllDependenciesForJavaFile(file, solver));
|
||||||
}
|
}
|
||||||
dependenciesMap.putAll(javDependenciesMap);
|
dependenciesMap.putAll(javDependenciesMap);
|
||||||
@@ -79,51 +130,104 @@ public class CompilerMojo extends AbstractMojo {
|
|||||||
|
|
||||||
var graph = Utils.buildDependencyGraph(dependenciesMap);
|
var graph = Utils.buildDependencyGraph(dependenciesMap);
|
||||||
|
|
||||||
var compilationSteps = Utils.generateCompilationStepsFromDependencyGraph(graph);
|
System.out.println(Utils.exportGraphToDot(graph));
|
||||||
|
|
||||||
for(CompilationStep step : compilationSteps) {
|
TarjanSCC tarjan = new TarjanSCC(graph);
|
||||||
if (step instanceof JavacCompilationStep(Set<File> toCompile, List<File> classpath)) {
|
var sccs = tarjan.run();
|
||||||
getLog().info("compiling: " + toCompile + " ...");
|
for (Set<File> scc : sccs) {
|
||||||
List<File> cp = List.of(
|
System.out.println("SCC: " + scc);
|
||||||
new File(project.getBuild().getOutputDirectory()));
|
}
|
||||||
CompilationHelper.compileJavaSources(toCompile.stream().toList(),
|
|
||||||
new File(project.getBuild().getOutputDirectory()),
|
if(!Utils.checkForCycles(sccs)){
|
||||||
cp);
|
System.exit(1);
|
||||||
} else if (step instanceof JavaTXCompilationStep(Set<File> toCompile, List<File> classpath)) {
|
}
|
||||||
getLog().info("compiling: " + toCompile + " ...");
|
|
||||||
List<File> cp = List.of(
|
Map<File, Integer> sccIndex = new HashMap<>();
|
||||||
new File(project.getBuild().getOutputDirectory()));
|
for (int i = 0; i < sccs.size(); i++) {
|
||||||
CompilationHelper.compileJavaTXSources(new File(javaTXCompilerLocation),
|
for (File f : sccs.get(i)) {
|
||||||
toCompile.stream().toList(),
|
sccIndex.put(f, i);
|
||||||
new File(project.getBuild().getOutputDirectory()),
|
|
||||||
cp, getLog());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getLog().info(compilationSteps.toString());
|
Map<Integer, Set<Integer>> sccGraph = new HashMap<>();
|
||||||
|
|
||||||
} catch (IOException e) {
|
for (int i = 0; i < sccs.size(); i++) {
|
||||||
throw new RuntimeException(e);
|
sccGraph.put(i, new HashSet<>());
|
||||||
} catch (InterruptedException e) {
|
}
|
||||||
throw new RuntimeException(e);
|
|
||||||
|
for (File u : graph.vertexSet()) {
|
||||||
|
int uScc = sccIndex.get(u);
|
||||||
|
|
||||||
|
for (LabeledEdge e : graph.outgoingEdgesOf(u)) {
|
||||||
|
File v = graph.getEdgeTarget(e);
|
||||||
|
int vScc = sccIndex.get(v);
|
||||||
|
|
||||||
|
if (uScc != vScc) {
|
||||||
|
// Reverse the edge for compilation DAG:
|
||||||
|
// dependency -> dependent
|
||||||
|
sccGraph.get(vScc).add(uScc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var a = Utils.convertSccGraphToJGraphT(sccGraph);
|
||||||
|
|
||||||
|
System.out.println(Utils.exportSccGraphWithFileLabels(a, sccs));
|
||||||
|
|
||||||
|
List<Integer> topoOrder = Utils.topoSort(sccGraph);
|
||||||
|
|
||||||
|
List<List<File>> compilationOrder = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int sccId : topoOrder) {
|
||||||
|
compilationOrder.add(new ArrayList<>(sccs.get(sccId)));
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(compilationOrder);
|
||||||
|
|
||||||
|
List<? extends CompilationStep> compilationSteps = compilationOrder.stream().map(x -> x.getFirst() instanceof JavaTXSourceFile ? new JavaTXCompilationStep(new HashSet<>(x), null) : new JavacCompilationStep(new HashSet<>(x), null)).toList();
|
||||||
|
|
||||||
|
for(CompilationStep step : compilationSteps) {
|
||||||
|
if (step instanceof JavacCompilationStep(Set<File> toCompile, List<File> _)) {
|
||||||
|
CompilationHelper.compileJavaSources(toCompile.stream().toList(),
|
||||||
|
outputDir,
|
||||||
|
dependencies);
|
||||||
|
} else if (step instanceof JavaTXCompilationStep(Set<File> toCompile, List<File> _)) {
|
||||||
|
CompilationHelper.compileJavaTXSources(javaTXCompilerLocation,
|
||||||
|
toCompile.stream().toList(),
|
||||||
|
outputDir,
|
||||||
|
dependencies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static List<JavaTXSourceFile> getAllJavaTXFiles(File rootDir){
|
public static List<JavaTXSourceFile> getAllJavaTXFiles(List<File> rootDirs){
|
||||||
String[] javaFilePaths = Utils.getFilePathsInDirectory(rootDir, new String[] { "**/*.jav" }, new String[] { });
|
List<JavaTXSourceFile> javatxSourceFiles = new ArrayList<>();
|
||||||
return Arrays.stream(javaFilePaths)
|
for(var dir : rootDirs){
|
||||||
.map(f -> new JavaTXSourceFile(rootDir, f))
|
String[] javaFilePaths = Utils.getFilePathsInDirectory(dir, new String[] { "**/*.jav" }, new String[] { });
|
||||||
.toList();
|
javatxSourceFiles.addAll(Arrays.stream(javaFilePaths)
|
||||||
|
.map(f -> new JavaTXSourceFile(dir, f))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
return javatxSourceFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<JavaSourceFile> getAllJavaFiles(File rootDir){
|
public static List<JavaSourceFile> getAllJavaFiles(List<File> rootDirs){
|
||||||
String[] javaFilePaths = Utils.getFilePathsInDirectory(rootDir, new String[] { "**/*.java" }, new String[] { });
|
List<JavaSourceFile> javaSourceFiles = new ArrayList<>();
|
||||||
return Arrays.stream(javaFilePaths)
|
for(var dir : rootDirs){
|
||||||
.map(f -> new JavaSourceFile(rootDir, f))
|
String[] javaFilePaths = Utils.getFilePathsInDirectory(dir, new String[] { "**/*.java" }, new String[] { });
|
||||||
.toList();
|
javaSourceFiles.addAll(Arrays.stream(javaFilePaths)
|
||||||
|
.map(f -> new JavaSourceFile(dir, f))
|
||||||
|
.toList());
|
||||||
|
}
|
||||||
|
return javaSourceFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// public void buildDependencyGraph(List<File> baseDirs) throws IOException {
|
// public void buildDependencyGraph(List<File> baseDirs) throws IOException {
|
||||||
//
|
//
|
||||||
// //currently only supports one base dir
|
// //currently only supports one base dir
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class CompilationHelper {
|
public class CompilationHelper {
|
||||||
public static void compileJavaSources(List<File> sourceFiles, File outputDir, List<File> classpathFiles) throws IOException {
|
public static void compileJavaSources(List<File> sourceFiles, File outputDir, List<File> classpathFiles) throws IOException {
|
||||||
@@ -29,15 +30,13 @@ public class CompilationHelper {
|
|||||||
|
|
||||||
// Build classpath string from File objects
|
// Build classpath string from File objects
|
||||||
if (classpathFiles != null && !classpathFiles.isEmpty()) {
|
if (classpathFiles != null && !classpathFiles.isEmpty()) {
|
||||||
StringBuilder cp = new StringBuilder();
|
|
||||||
for (int i = 0; i < classpathFiles.size(); i++) {
|
String classpath = classpathFiles.stream()
|
||||||
cp.append(classpathFiles.get(i).getAbsolutePath());
|
.map(File::getAbsolutePath)
|
||||||
if (i < classpathFiles.size() - 1) {
|
.collect(Collectors.joining(File.pathSeparator));
|
||||||
cp.append(File.pathSeparator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
options.add("-classpath");
|
options.add("-classpath");
|
||||||
options.add(cp.toString());
|
options.add(classpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaCompiler.CompilationTask task = compiler.getTask(
|
JavaCompiler.CompilationTask task = compiler.getTask(
|
||||||
@@ -55,7 +54,7 @@ public class CompilationHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void compileJavaTXSources(File compilerLocation, List<File> sourceFiles, File outputDir, List<File> classpathFiles, Log log) throws IOException, InterruptedException {
|
public static void compileJavaTXSources(File compilerLocation, List<File> sourceFiles, File outputDir, List<File> classpathFiles) throws IOException, InterruptedException {
|
||||||
// JavaTX compilation logic can be similar to Java compilation
|
// JavaTX compilation logic can be similar to Java compilation
|
||||||
List<String> command = new java.util.ArrayList<>();
|
List<String> command = new java.util.ArrayList<>();
|
||||||
command.add("java");
|
command.add("java");
|
||||||
@@ -64,14 +63,17 @@ public static void compileJavaTXSources(File compilerLocation, List<File> source
|
|||||||
for(File sourceFile : sourceFiles) {
|
for(File sourceFile : sourceFiles) {
|
||||||
command.add(sourceFile.getAbsolutePath());
|
command.add(sourceFile.getAbsolutePath());
|
||||||
}
|
}
|
||||||
command.add("-cp");
|
if(!classpathFiles.isEmpty()) {
|
||||||
for (var file : classpathFiles) {
|
command.add("-cp");
|
||||||
command.add(file.getAbsolutePath());
|
String classpath = classpathFiles.stream()
|
||||||
|
.map(File::getAbsolutePath)
|
||||||
|
.collect(Collectors.joining(File.pathSeparator));
|
||||||
|
command.add(classpath);
|
||||||
}
|
}
|
||||||
command.add("-d");
|
command.add("-d");
|
||||||
command.add(outputDir.getAbsolutePath());
|
command.add(outputDir.getAbsolutePath());
|
||||||
|
|
||||||
log.info("Compiling JavaTX sources with command: " + String.join(" ", command));
|
System.out.println("Compiling JavaTX sources with command: " + String.join(" ", command));
|
||||||
|
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||||
processBuilder.inheritIO();
|
processBuilder.inheritIO();
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package de.dhbwstuttgart.utils;
|
||||||
|
|
||||||
|
public class CyclicDependencyException extends RuntimeException {
|
||||||
|
public CyclicDependencyException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/main/java/de/dhbwstuttgart/utils/TarjanSCC.java
Normal file
73
src/main/java/de/dhbwstuttgart/utils/TarjanSCC.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package de.dhbwstuttgart.utils;
|
||||||
|
|
||||||
|
import org.jgrapht.Graph;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class TarjanSCC {
|
||||||
|
|
||||||
|
private final Graph<File, LabeledEdge> graph;
|
||||||
|
|
||||||
|
private Map<File, Integer> indexMap = new HashMap<>();
|
||||||
|
private Map<File, Integer> lowlinkMap = new HashMap<>();
|
||||||
|
private Deque<File> stack = new ArrayDeque<>();
|
||||||
|
private Set<File> onStack = new HashSet<>();
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
|
private final List<Set<File>> stronglyConnectedComponents = new ArrayList<>();
|
||||||
|
|
||||||
|
public TarjanSCC(Graph<File, LabeledEdge> graph) {
|
||||||
|
this.graph = graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Run the algorithm */
|
||||||
|
public List<Set<File>> run() {
|
||||||
|
for (File v : graph.vertexSet()) {
|
||||||
|
if (!indexMap.containsKey(v)) {
|
||||||
|
strongConnect(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
return stronglyConnectedComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Recursive Tarjan DFS step */
|
||||||
|
private void strongConnect(File v) {
|
||||||
|
|
||||||
|
indexMap.put(v, index);
|
||||||
|
lowlinkMap.put(v, index);
|
||||||
|
index++;
|
||||||
|
stack.push(v);
|
||||||
|
onStack.add(v);
|
||||||
|
|
||||||
|
// Consider successors
|
||||||
|
for (LabeledEdge e : graph.outgoingEdgesOf(v)) {
|
||||||
|
File w = graph.getEdgeTarget(e);
|
||||||
|
|
||||||
|
if (!indexMap.containsKey(w)) {
|
||||||
|
// Successor w not yet visited
|
||||||
|
strongConnect(w);
|
||||||
|
lowlinkMap.put(v, Math.min(lowlinkMap.get(v), lowlinkMap.get(w)));
|
||||||
|
}
|
||||||
|
else if (onStack.contains(w)) {
|
||||||
|
// Successor w is in the stack -> part of current SCC
|
||||||
|
lowlinkMap.put(v, Math.min(lowlinkMap.get(v), indexMap.get(w)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If v is the root of an SCC
|
||||||
|
if (Objects.equals(lowlinkMap.get(v), indexMap.get(v))) {
|
||||||
|
Set<File> scc = new HashSet<>();
|
||||||
|
File w;
|
||||||
|
do {
|
||||||
|
w = stack.pop();
|
||||||
|
onStack.remove(w);
|
||||||
|
scc.add(w);
|
||||||
|
} while (!w.equals(v));
|
||||||
|
|
||||||
|
stronglyConnectedComponents.add(scc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,14 +10,13 @@ import org.codehaus.plexus.util.DirectoryScanner;
|
|||||||
import org.jgrapht.Graph;
|
import org.jgrapht.Graph;
|
||||||
import org.jgrapht.alg.util.Pair;
|
import org.jgrapht.alg.util.Pair;
|
||||||
import org.jgrapht.graph.AbstractBaseGraph;
|
import org.jgrapht.graph.AbstractBaseGraph;
|
||||||
|
import org.jgrapht.graph.DefaultDirectedGraph;
|
||||||
|
import org.jgrapht.graph.DefaultEdge;
|
||||||
import org.jgrapht.graph.DirectedMultigraph;
|
import org.jgrapht.graph.DirectedMultigraph;
|
||||||
import org.jgrapht.nio.DefaultAttribute;
|
import org.jgrapht.nio.DefaultAttribute;
|
||||||
import org.jgrapht.nio.dot.DOTExporter;
|
import org.jgrapht.nio.dot.DOTExporter;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -45,34 +44,74 @@ public class Utils {
|
|||||||
if (!graph.containsVertex(dependency.location())) {
|
if (!graph.containsVertex(dependency.location())) {
|
||||||
graph.addVertex(dependency.location());
|
graph.addVertex(dependency.location());
|
||||||
}
|
}
|
||||||
System.out.println(dependency.clazzPath().getPackagePathAsString());
|
|
||||||
System.out.println(dependency.clazzPath().getAbsoluteName());
|
|
||||||
try{
|
try{
|
||||||
graph.addEdge(file, dependency.location(), new LabeledEdge(dependency.clazzPath().getAbsoluteName()));
|
graph.addEdge(file, dependency.location(), new LabeledEdge(dependency.clazzPath().getAbsoluteName()));
|
||||||
}
|
}
|
||||||
catch(Exception e){
|
catch(Exception e){
|
||||||
System.out.println();
|
System.err.println("Error adding edge from " + file.getAbsolutePath() + " to " + dependency.location().getAbsolutePath() + ": " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void exportGraphToDotFile(Graph<File, LabeledEdge> graph, File outputFile) throws IOException {
|
public static <E> String exportGraphToDot(Graph<File, E> graph) {
|
||||||
DOTExporter<File, LabeledEdge> exporter = new DOTExporter<>();
|
|
||||||
exporter.setVertexIdProvider(file -> "\"" + file.getName() + "\"");
|
DOTExporter<File, E> exporter = new DOTExporter<>(
|
||||||
exporter.setEdgeAttributeProvider(e -> Map.of("label", DefaultAttribute.createAttribute(e.getLabel())));
|
file -> file.getName().replaceAll("[^A-Za-z0-9_]", "_") // DOT-safe ID
|
||||||
|
);
|
||||||
|
|
||||||
exporter.setVertexAttributeProvider(file -> Map.of(
|
exporter.setVertexAttributeProvider(file -> Map.of(
|
||||||
"label", DefaultAttribute.createAttribute(file.getName())
|
"label", DefaultAttribute.createAttribute(file.getName())
|
||||||
));
|
));
|
||||||
|
|
||||||
try (Writer writer = new FileWriter(outputFile)) {
|
StringWriter writer = new StringWriter();
|
||||||
exporter.exportGraph(graph, writer);
|
exporter.exportGraph(graph, writer);
|
||||||
}
|
return writer.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<CompilationStep> simplify(List<CompilationStep> steps){
|
||||||
|
List<CompilationStep> simplifiedSteps = new ArrayList<>();
|
||||||
|
CompilationStep previousStep = null;
|
||||||
|
boolean addedTwo = false;
|
||||||
|
for(int idx = 0; idx < steps.size(); idx++){
|
||||||
|
//first step
|
||||||
|
if (previousStep == null){
|
||||||
|
previousStep = steps.get(idx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
public static List<CompilationStep> generateCompilationStepsFromDependencyGraph(Graph<File, LabeledEdge> originalGraph) throws IOException {
|
CompilationStep thisStep = steps.get(idx);
|
||||||
|
|
||||||
|
if (previousStep instanceof JavaTXCompilationStep prev && thisStep instanceof JavaTXCompilationStep thiz){
|
||||||
|
Set<File> combined = new HashSet<>(prev.toCompile());
|
||||||
|
combined.addAll(thiz.toCompile());
|
||||||
|
|
||||||
|
simplifiedSteps.removeLast(); //remove previous step and combine the two
|
||||||
|
thisStep = new JavaTXCompilationStep(combined, null);
|
||||||
|
simplifiedSteps.add(thisStep);
|
||||||
|
}
|
||||||
|
else if(previousStep instanceof JavacCompilationStep prev && thisStep instanceof JavacCompilationStep thiz){
|
||||||
|
Set<File> combined = new HashSet<>(prev.toCompile());
|
||||||
|
combined.addAll(thiz.toCompile());
|
||||||
|
|
||||||
|
simplifiedSteps.removeLast(); //remove previous step and combine the two
|
||||||
|
thisStep = new JavacCompilationStep(combined, null);
|
||||||
|
simplifiedSteps.add(thisStep);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
simplifiedSteps.add(previousStep);
|
||||||
|
if(idx == steps.size() - 1){
|
||||||
|
simplifiedSteps.add(thisStep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previousStep = thisStep;
|
||||||
|
|
||||||
|
}
|
||||||
|
return simplifiedSteps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<CompilationStep> generateCompilationStepsFromDependencyGraph(Graph<File, LabeledEdge> originalGraph) throws IOException, CyclicDependencyException {
|
||||||
Graph<File, LabeledEdge> graph = (Graph<File, LabeledEdge>) ((AbstractBaseGraph<File, LabeledEdge>) originalGraph).clone();
|
Graph<File, LabeledEdge> graph = (Graph<File, LabeledEdge>) ((AbstractBaseGraph<File, LabeledEdge>) originalGraph).clone();
|
||||||
List<CompilationStep> steps = new ArrayList<>();
|
List<CompilationStep> steps = new ArrayList<>();
|
||||||
while (!graph.vertexSet().isEmpty()) {
|
while (!graph.vertexSet().isEmpty()) {
|
||||||
@@ -93,14 +132,62 @@ public class Utils {
|
|||||||
|
|
||||||
if (amoutOfVertices == graph.vertexSet().size()) {
|
if (amoutOfVertices == graph.vertexSet().size()) {
|
||||||
// cannot remove any more vertices, so we probably have a cyclic dependency
|
// cannot remove any more vertices, so we probably have a cyclic dependency
|
||||||
System.out.println("Cyclic dependency detected, stopping compilation steps generation.");
|
throw new CyclicDependencyException("Cyclic dependency between Java and Java-TX files detected, stopping compilation steps generation.");
|
||||||
Utils.exportGraphToDotFile(graph, new File("cyclic_dependency_graph.dot"));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return steps;
|
|
||||||
|
|
||||||
|
return simplify(steps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Graph<Integer,DefaultEdge> convertSccGraphToJGraphT(
|
||||||
|
Map<Integer, Set<Integer>> sccGraph
|
||||||
|
) {
|
||||||
|
// Create a directed graph with default edges
|
||||||
|
Graph<Integer,DefaultEdge> g = new DefaultDirectedGraph<>(DefaultEdge.class);
|
||||||
|
|
||||||
|
// Add vertices
|
||||||
|
for (Integer sccId : sccGraph.keySet()) {
|
||||||
|
g.addVertex(sccId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add edges
|
||||||
|
for (Map.Entry<Integer, Set<Integer>> entry : sccGraph.entrySet()) {
|
||||||
|
Integer src = entry.getKey();
|
||||||
|
for (Integer dst : entry.getValue()) {
|
||||||
|
g.addEdge(src, dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String exportSccGraphWithFileLabels(
|
||||||
|
Graph<Integer, DefaultEdge> sccGraph,
|
||||||
|
List<Set<File>> sccs
|
||||||
|
) {
|
||||||
|
DOTExporter<Integer, DefaultEdge> exporter = new DOTExporter<>(Object::toString);
|
||||||
|
|
||||||
|
// Label each vertex with the files in the SCC
|
||||||
|
exporter.setVertexAttributeProvider(sccId -> {
|
||||||
|
Set<File> files = sccs.get(sccId);
|
||||||
|
String label = files.stream()
|
||||||
|
.map(File::getName)
|
||||||
|
.collect(Collectors.joining("\\n")); // newline in DOT
|
||||||
|
return Map.of("label", DefaultAttribute.createAttribute(label));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Optional: label edges
|
||||||
|
exporter.setEdgeAttributeProvider(e -> Map.of(
|
||||||
|
"label", DefaultAttribute.createAttribute(e.toString())
|
||||||
|
));
|
||||||
|
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
exporter.exportGraph(sccGraph, writer);
|
||||||
|
return writer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static <T extends File> Set<File> getTransitiveDependentFilesOfType(Class<T> type, Graph<File, LabeledEdge> graph, Set<File> potentialVerticesInThisStep, Set<File> potentialFilesInCycle) {
|
public static <T extends File> Set<File> getTransitiveDependentFilesOfType(Class<T> type, Graph<File, LabeledEdge> graph, Set<File> potentialVerticesInThisStep, Set<File> potentialFilesInCycle) {
|
||||||
|
|
||||||
//initial call
|
//initial call
|
||||||
@@ -171,4 +258,45 @@ public class Utils {
|
|||||||
.map(graph::getEdgeTarget)
|
.map(graph::getEdgeTarget)
|
||||||
.allMatch(type::isInstance);
|
.allMatch(type::isInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean checkForCycles(List<Set<File>> sccs) {
|
||||||
|
for(var scc : sccs){
|
||||||
|
boolean allSameType = scc.stream().map(Object::getClass).distinct().count() <= 1;
|
||||||
|
if (!allSameType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> topoSort(Map<Integer, Set<Integer>> graph) {
|
||||||
|
Set<Integer> visited = new HashSet<>();
|
||||||
|
Set<Integer> temp = new HashSet<>();
|
||||||
|
List<Integer> order = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int node : graph.keySet()) {
|
||||||
|
if (!visited.contains(node)) {
|
||||||
|
dfs(node, graph, visited, temp, order);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collections.reverse(order);
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dfs(int u, Map<Integer, Set<Integer>> graph,
|
||||||
|
Set<Integer> visited, Set<Integer> temp, List<Integer> order) {
|
||||||
|
|
||||||
|
if (temp.contains(u))
|
||||||
|
throw new IllegalStateException("Graph is not a DAG (should not happen after SCCs)");
|
||||||
|
|
||||||
|
if (!visited.contains(u)) {
|
||||||
|
temp.add(u);
|
||||||
|
for (int v : graph.get(u)) {
|
||||||
|
dfs(v, graph, visited, temp, order);
|
||||||
|
}
|
||||||
|
temp.remove(u);
|
||||||
|
visited.add(u);
|
||||||
|
order.add(u);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/main/resources/META-INF/maven/lifecycle.xml
Normal file
13
src/main/resources/META-INF/maven/lifecycle.xml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<lifecycles>
|
||||||
|
<lifecycle>
|
||||||
|
<id>default</id>
|
||||||
|
<phases>
|
||||||
|
<phase>
|
||||||
|
<id>compile</id>
|
||||||
|
<goal>
|
||||||
|
<plugin>de.dhbwstuttgart:javatx-compiler-plugin:compile-javatx</plugin>
|
||||||
|
</goal>
|
||||||
|
</phase>
|
||||||
|
</phases>
|
||||||
|
</lifecycle>
|
||||||
|
</lifecycles>
|
||||||
@@ -8,10 +8,11 @@
|
|||||||
<groupId>de.dhbwstuttgart</groupId>
|
<groupId>de.dhbwstuttgart</groupId>
|
||||||
<artifactId>javatx-compiler-plugin</artifactId>
|
<artifactId>javatx-compiler-plugin</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<goalPrefix>javatx-compiler</goalPrefix>
|
<goalPrefix>javatx-compiler-plugin</goalPrefix>
|
||||||
<mojos>
|
<mojos>
|
||||||
<mojo>
|
<mojo>
|
||||||
<goal>compile javatx project</goal>
|
<goal>compile-javatx</goal>
|
||||||
|
<requiresDependencyResolution>compile+runtime</requiresDependencyResolution>
|
||||||
<requiresDirectInvocation>false</requiresDirectInvocation>
|
<requiresDirectInvocation>false</requiresDirectInvocation>
|
||||||
<requiresProject>true</requiresProject>
|
<requiresProject>true</requiresProject>
|
||||||
<requiresReports>false</requiresReports>
|
<requiresReports>false</requiresReports>
|
||||||
|
|||||||
@@ -8,14 +8,15 @@
|
|||||||
<groupId>de.dhbwstuttgart</groupId>
|
<groupId>de.dhbwstuttgart</groupId>
|
||||||
<artifactId>javatx-compiler-plugin</artifactId>
|
<artifactId>javatx-compiler-plugin</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<goalPrefix>javatx-compiler</goalPrefix>
|
<goalPrefix>javatx-compiler-plugin</goalPrefix>
|
||||||
<isolatedRealm>false</isolatedRealm>
|
<isolatedRealm>false</isolatedRealm>
|
||||||
<inheritedByDefault>true</inheritedByDefault>
|
<inheritedByDefault>true</inheritedByDefault>
|
||||||
<requiredJavaVersion>23</requiredJavaVersion>
|
<requiredJavaVersion>23</requiredJavaVersion>
|
||||||
<requiredMavenVersion>3.9.9</requiredMavenVersion>
|
<requiredMavenVersion>3.9.9</requiredMavenVersion>
|
||||||
<mojos>
|
<mojos>
|
||||||
<mojo>
|
<mojo>
|
||||||
<goal>compile javatx project</goal>
|
<goal>compile-javatx</goal>
|
||||||
|
<requiresDependencyResolution>compile+runtime</requiresDependencyResolution>
|
||||||
<requiresDirectInvocation>false</requiresDirectInvocation>
|
<requiresDirectInvocation>false</requiresDirectInvocation>
|
||||||
<requiresProject>true</requiresProject>
|
<requiresProject>true</requiresProject>
|
||||||
<requiresReports>false</requiresReports>
|
<requiresReports>false</requiresReports>
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -306,6 +306,7 @@ de/dhbwstuttgart/parser/antlr/JavaTXParser$BitwiseorexpressionContext.class
|
|||||||
de/dhbwstuttgart/parser/antlr/JavaParser$NonWildcardTypeArgumentsContext.class
|
de/dhbwstuttgart/parser/antlr/JavaParser$NonWildcardTypeArgumentsContext.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaParser$MethodBodyContext.class
|
de/dhbwstuttgart/parser/antlr/JavaParser$MethodBodyContext.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaParser$ExplicitGenericInvocationSuffixContext.class
|
de/dhbwstuttgart/parser/antlr/JavaParser$ExplicitGenericInvocationSuffixContext.class
|
||||||
|
de/dhbwstuttgart/utils/CyclicDependencyException.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaParser$ElementValuePairsContext.class
|
de/dhbwstuttgart/parser/antlr/JavaParser$ElementValuePairsContext.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaTXParser$SwitchExpression2Context.class
|
de/dhbwstuttgart/parser/antlr/JavaTXParser$SwitchExpression2Context.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaTXParser$BoolLiteralContext.class
|
de/dhbwstuttgart/parser/antlr/JavaTXParser$BoolLiteralContext.class
|
||||||
@@ -348,6 +349,7 @@ de/dhbwstuttgart/parser/antlr/JavaTXParser$ConditionalstmtContext.class
|
|||||||
de/dhbwstuttgart/parser/JavaTXDependencyObtainer.class
|
de/dhbwstuttgart/parser/JavaTXDependencyObtainer.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaParser$ConstantDeclaratorContext.class
|
de/dhbwstuttgart/parser/antlr/JavaParser$ConstantDeclaratorContext.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaParser$InterfaceBodyDeclarationContext.class
|
de/dhbwstuttgart/parser/antlr/JavaParser$InterfaceBodyDeclarationContext.class
|
||||||
|
de/dhbwstuttgart/utils/TarjanSCC.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaTXParserBaseVisitor.class
|
de/dhbwstuttgart/parser/antlr/JavaTXParserBaseVisitor.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaTXParser$AnnotationTypeBodyContext.class
|
de/dhbwstuttgart/parser/antlr/JavaTXParser$AnnotationTypeBodyContext.class
|
||||||
de/dhbwstuttgart/parser/antlr/JavaTXParser$RefTypeContext.class
|
de/dhbwstuttgart/parser/antlr/JavaTXParser$RefTypeContext.class
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/App.java
|
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/javaanalyzer/CompilationStep.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/javaanalyzer/CompilationStep.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/javaanalyzer/Dependency.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/javaanalyzer/Dependency.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/javaanalyzer/JavaDependencyResolver.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/javaanalyzer/JavaDependencyResolver.java
|
||||||
@@ -16,7 +15,9 @@
|
|||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/structure/JavaSourceFile.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/structure/JavaSourceFile.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/structure/JavaTXSourceFile.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/structure/JavaTXSourceFile.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/CompilationHelper.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/CompilationHelper.java
|
||||||
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/CyclicDependencyException.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/LabeledEdge.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/LabeledEdge.java
|
||||||
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/TarjanSCC.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/Utils.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/src/main/java/de/dhbwstuttgart/utils/Utils.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/target/generated-sources/antlr4/de/dhbwstuttgart/parser/antlr/JavaLexer.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/target/generated-sources/antlr4/de/dhbwstuttgart/parser/antlr/JavaLexer.java
|
||||||
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/target/generated-sources/antlr4/de/dhbwstuttgart/parser/antlr/JavaParser.java
|
/Users/julianschmidt/dhbw/javatx/JavaTX-Maven-Plugin/javatx-compiler-plugin/target/generated-sources/antlr4/de/dhbwstuttgart/parser/antlr/JavaParser.java
|
||||||
|
|||||||
@@ -8,14 +8,15 @@
|
|||||||
<groupId>de.dhbwstuttgart</groupId>
|
<groupId>de.dhbwstuttgart</groupId>
|
||||||
<artifactId>javatx-compiler-plugin</artifactId>
|
<artifactId>javatx-compiler-plugin</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<goalPrefix>javatx-compiler</goalPrefix>
|
<goalPrefix>javatx-compiler-plugin</goalPrefix>
|
||||||
<isolatedRealm>false</isolatedRealm>
|
<isolatedRealm>false</isolatedRealm>
|
||||||
<inheritedByDefault>true</inheritedByDefault>
|
<inheritedByDefault>true</inheritedByDefault>
|
||||||
<requiredJavaVersion>23</requiredJavaVersion>
|
<requiredJavaVersion>23</requiredJavaVersion>
|
||||||
<requiredMavenVersion>3.9.9</requiredMavenVersion>
|
<requiredMavenVersion>3.9.9</requiredMavenVersion>
|
||||||
<mojos>
|
<mojos>
|
||||||
<mojo>
|
<mojo>
|
||||||
<goal>compile javatx project</goal>
|
<goal>compile-javatx</goal>
|
||||||
|
<requiresDependencyResolution>compile+runtime</requiresDependencyResolution>
|
||||||
<requiresDirectInvocation>false</requiresDirectInvocation>
|
<requiresDirectInvocation>false</requiresDirectInvocation>
|
||||||
<requiresProject>true</requiresProject>
|
<requiresProject>true</requiresProject>
|
||||||
<requiresReports>false</requiresReports>
|
<requiresReports>false</requiresReports>
|
||||||
|
|||||||
Reference in New Issue
Block a user