diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 1999a37..183d790 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -11,10 +11,10 @@ jobs:
steps:
- uses: actions/checkout@v2
- - name: Set up JDK 11
+ - name: Set up JDK 17
uses: actions/setup-java@v2
with:
- java-version: '11' # TODO: what version do we want?
+ java-version: '17' # TODO: what version do we want?
distribution: 'adopt'
cache: maven
@@ -42,4 +42,4 @@ jobs:
uses: actions/upload-artifact@v2.2.4
with:
name: plugin
- path: ./vscode/goblintanalyzer-*.vsix
+ path: ./vscode/gobpie-*.vsix
diff --git a/Readme.md b/Readme.md
index d0dfab5..4d07a9f 100644
--- a/Readme.md
+++ b/Readme.md
@@ -30,7 +30,7 @@ Example configuration file `gobpie.json`:
{
"goblintConf" : "goblint.json",
"files" : ["./build"],
- "preAnalyzeCommand" : ["cmake", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "build"]
+ "preAnalyzeCommand" : ["cmake", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-B", "build"]
}
```
diff --git a/pom.xml b/pom.xml
index 2758bf8..f1cf394 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,81 +1,86 @@
- 4.0.0
- magpiebridge
- goblintanalyzer
- 0.0.1-SNAPSHOT
-
-
- com.github.magpiebridge
- magpiebridge
- 0.1.3
-
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+ goblint
+ gobpie
+ 0.0.2-SNAPSHOT
+
-
-
- com.google.code.gson
- gson
- 2.8.6
-
+
+
+ com.github.magpiebridge
+ magpiebridge
+ 0.1.3
+
-
- org.zeroturnaround
- zt-exec
- 1.12
-
+
+
+ com.google.code.gson
+ gson
+ 2.8.6
+
-
- org.apache.logging.log4j
- log4j-api
- 2.15.0
-
-
- org.apache.logging.log4j
- log4j-core
- 2.15.0
-
-
-
- 1.8
- 1.8
-
-
-
-
-
- org.apache.maven.plugins
- maven-shade-plugin
- 2.3
-
-
-
- package
-
- shade
-
-
-
-
-
- Main
-
-
-
-
- *:*
-
- META-INF/*.SF
- META-INF/*.DSA
- META-INF/*.RSA
-
-
-
-
-
-
-
-
-
+
+
+ org.zeroturnaround
+ zt-exec
+ 1.12
+
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ 2.15.0
+
+
+ org.apache.logging.log4j
+ log4j-core
+ 2.15.0
+
+
+
+
+ 17
+ 17
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ 2.3
+
+
+
+ package
+
+ shade
+
+
+
+
+
+ Main
+
+
+
+
+ *:*
+
+ META-INF/*.SF
+ META-INF/*.DSA
+ META-INF/*.RSA
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/GoblintAnalysis.java b/src/main/java/GoblintAnalysis.java
deleted file mode 100644
index 6b4d44f..0000000
--- a/src/main/java/GoblintAnalysis.java
+++ /dev/null
@@ -1,187 +0,0 @@
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.*;
-import java.util.concurrent.TimeoutException;
-import java.util.stream.Stream;
-
-import com.ibm.wala.classLoader.Module;
-
-import magpiebridge.core.AnalysisConsumer;
-import magpiebridge.core.ServerAnalysis;
-import magpiebridge.core.MagpieServer;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonSyntaxException;
-
-import org.eclipse.lsp4j.MessageParams;
-import org.eclipse.lsp4j.MessageType;
-import org.zeroturnaround.exec.InvalidExitValueException;
-import org.zeroturnaround.exec.ProcessExecutor;
-import org.zeroturnaround.exec.ProcessResult;
-
-
-public class GoblintAnalysis implements ServerAnalysis {
-
- private final MagpieServer magpieServer;
- private File jsonResult = new File("analysisResults.json");
- private File gobPieConf = new File("gobpie.json");
- private String pathToGoblintConf;
- private String[] filesToAnalyze;
- private String[] preAnalyzeCommand;
- private String[] goblintRunCommand;
- // private List projectFiles; // for future use
-
- private final Logger log;
-
- public GoblintAnalysis(MagpieServer server) {
- this.magpieServer = server;
- this.log = LogManager.getLogger(GoblintAnalysis.class);
- }
-
- /**
- * The source of this analysis, usually the name of the analysis.
- *
- * @return the string
- */
- public String source() {
- return "GoblintAnalysis";
- }
-
-
- /**
- * The files to be analyzed.
- *
- * @param files the files that have been opened in the editor (not using due to using the compilation database).
- * @param consumer the server which consumes the analysis results.
- * @param rerun tells if the analysis should be reran.
- */
- @Override
- public void analyze(Collection extends Module> files, AnalysisConsumer consumer, boolean rerun) {
- if (rerun) {
- if (consumer instanceof MagpieServer) {
- boolean gobpieconf = readGobPieConfiguration();
- if (!gobpieconf) return;
- if (preAnalyzeCommand != null && preAnalyzeCommand.length > 0) {
- try {
- runCommand(new File(System.getProperty("user.dir")), preAnalyzeCommand);
- } catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) {
- this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Warning, "Building compilation database failed. " + e.getMessage()));
- }
- }
- log.info("New analysis started");
- MagpieServer server = (MagpieServer) consumer;
- if (generateJson()) server.consume(new ArrayList<>(readResultsFromJson()), source());
- }
- }
- }
-
-
- public ProcessResult runCommand(File dirPath, String[] command) throws IOException, InvalidExitValueException, InterruptedException, TimeoutException {
- log.debug("Waiting for Goblint to run...");
- System.err.println("---------------------- Goblint's dump start ----------------------");
- ProcessResult process = new ProcessExecutor()
- .directory(dirPath)
- .command(command)
- .redirectOutput(System.err)
- .redirectError(System.err)
- .execute();
- System.err.println("----------------------- Goblint's dump end -----------------------");
- return process;
- }
-
- /**
- * Runs the command in the project root directory
- * to let goblint generate the json file with analysis results.
- *
- * @param file the file on which to run the analysis.
- * @return returns true if goblint finished the analysis and json was generated sucessfully, false otherwise
- */
- private boolean generateJson() {
- // construct command to run
- this.goblintRunCommand = Stream.concat(
- Arrays.stream(new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", jsonResult.getAbsolutePath()}),
- Arrays.stream(filesToAnalyze))
- .toArray(String[]::new);
-
- try {
- // run command
- log.info("Goblint run with command: " + String.join(" ", goblintRunCommand));
- ProcessResult commandRunProcess = runCommand(new File(System.getProperty("user.dir")), goblintRunCommand);
- if (commandRunProcess.getExitValue() != 0) {
- magpieServer.forwardMessageToClient(
- new MessageParams(MessageType.Error,
- "Goblint exited with an error."));
- log.error("Goblint exited with an error.");
- return false;
- }
- log.info("Goblint finished analyzing.");
- return true;
- } catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) {
- this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Running Goblint failed. " + e.getMessage()));
- return false;
- }
- }
-
- /**
- * Deserializes json to GoblintResult objects and then converts the information
- * into GoblintAnalysisResult objects, which Magpie uses to generate IDE
- * messages.
- *
- * @return A collection of GoblintAnalysisResult objects.
- */
- private Collection readResultsFromJson() {
- try {
- log.debug("Reading analysis results from json");
- // Read json objects as an array
- JsonObject json = JsonParser.parseReader(new FileReader(jsonResult)).getAsJsonObject();
- GsonBuilder builder = new GsonBuilder();
- // Add deserializer for tags
- builder.registerTypeAdapter(GoblintResult.Message.tag.class, new TagInterfaceAdapter());
- Gson gson = builder.create();
- GoblintResult goblintResult = gson.fromJson(json, GoblintResult.class);
- Collection results = goblintResult.convert();
- // this.projectFiles = goblintResult.getFiles();
- log.debug("Analysis results read from json");
- return results;
- } catch (JsonIOException | JsonSyntaxException | FileNotFoundException | MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
-
- private boolean readGobPieConfiguration() {
- try {
- log.debug("Reading GobPie configuration from json");
- Gson gson = new GsonBuilder().create();
- // Read json object
- JsonObject jsonObject = JsonParser.parseReader(new FileReader(gobPieConf)).getAsJsonObject();
- // Convert json object to GobPieConfiguration object
- GobPieConfiguration gobpieConfiguration = gson.fromJson(jsonObject, GobPieConfiguration.class);
- this.pathToGoblintConf = new File(gobpieConfiguration.getGoblintConf()).getAbsolutePath().toString();
- this.filesToAnalyze = gobpieConfiguration.getFiles();
- this.preAnalyzeCommand = gobpieConfiguration.getPreAnalyzeCommand();
- if (gobpieConfiguration.getGoblintConf().equals("") || gobpieConfiguration.getFiles() == null || gobpieConfiguration.getFiles().length < 1) {
- log.debug("Configuration parameters missing from GobPie configuration file");
- magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Configuration parameters missing from GobPie configuration file."));
- return false;
- }
- log.debug("GobPie configuration read from json");
- } catch (JsonIOException | JsonSyntaxException e) {
- throw new RuntimeException(e);
- } catch (FileNotFoundException e) {
- this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Could not locate GobPie configuration file. " + e.getMessage()));
- return false;
- }
- return true;
- }
-
-}
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
index 433de63..737e93d 100644
--- a/src/main/java/Main.java
+++ b/src/main/java/Main.java
@@ -1,6 +1,3 @@
-
-import org.eclipse.lsp4j.jsonrpc.messages.Either;
-
import java.io.File;
import magpiebridge.core.MagpieServer;
@@ -8,6 +5,12 @@
import magpiebridge.core.ServerConfiguration;
import magpiebridge.core.ToolAnalysis;
+import analysis.GoblintAnalysis;
+import goblintserver.GoblintClient;
+import goblintserver.GoblintServer;
+
+import org.eclipse.lsp4j.jsonrpc.messages.Either;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -16,27 +19,49 @@ public class Main {
private static final Logger log = LogManager.getLogger(Main.class);
public static void main(String... args) {
- // create server
- MagpieServer server = createServer();
- log.info("Server created");
- // launch the server only if there is a goblint conf file present
+
+ // launch the server only if there is a GobPie conf file present
if (new File(System.getProperty("user.dir") + "/" + "gobpie.json").exists()) {
- server.launchOnStdio();
- log.info("Server launched");
+
+ MagpieServer magpieServer = createMagpieServer();
+
+ if (magpieServer == null) {
+ log.info("Unable to launch MagpieBridge.");
+ } else {
+ magpieServer.launchOnStdio();
+ log.info("MagpieBridge server launched.");
+ magpieServer.doAnalysis("c", true);
+ }
}
}
- private static MagpieServer createServer() {
+
+ private static MagpieServer createMagpieServer() {
+
// set up configuration for MagpieServer
ServerConfiguration serverConfig = new ServerConfiguration();
- MagpieServer server = new MagpieServer(serverConfig);
+ serverConfig.setDoAnalysisByFirstOpen(false);
+ MagpieServer magpieServer = new MagpieServer(serverConfig);
+
// define language
String language = "c";
+
+ // start GoblintServer
+ GoblintServer goblintServer = new GoblintServer(magpieServer);
+ boolean gobServerStarted = goblintServer.startGoblintServer();
+ if (!gobServerStarted) return null;
+
+ // connect GoblintClient
+ GoblintClient goblintClient = new GoblintClient(magpieServer);
+ boolean goblintClientConnected = goblintClient.connectGoblitClient();
+ if (!goblintClientConnected) return null;
+
// add analysis to the MagpieServer
- ServerAnalysis serverAnalysis = new GoblintAnalysis(server);
+ ServerAnalysis serverAnalysis = new GoblintAnalysis(magpieServer, goblintServer, goblintClient);
Either analysis = Either.forLeft(serverAnalysis);
- server.addAnalysis(analysis, language);
+ magpieServer.addAnalysis(analysis, language);
- return server;
+ return magpieServer;
}
+
}
diff --git a/src/main/java/analysis/GoblintAnalysis.java b/src/main/java/analysis/GoblintAnalysis.java
new file mode 100644
index 0000000..f533d4f
--- /dev/null
+++ b/src/main/java/analysis/GoblintAnalysis.java
@@ -0,0 +1,195 @@
+package analysis;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.*;
+import java.util.concurrent.TimeoutException;
+
+import com.ibm.wala.classLoader.Module;
+
+import magpiebridge.core.AnalysisConsumer;
+import magpiebridge.core.ServerAnalysis;
+import magpiebridge.core.MagpieServer;
+
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import com.google.gson.*;
+
+import org.eclipse.lsp4j.MessageParams;
+import org.eclipse.lsp4j.MessageType;
+
+import org.zeroturnaround.exec.InvalidExitValueException;
+import org.zeroturnaround.exec.ProcessExecutor;
+import org.zeroturnaround.exec.ProcessResult;
+
+import goblintserver.GoblintClient;
+import goblintserver.GoblintServer;
+import goblintserver.Request;
+
+
+public class GoblintAnalysis implements ServerAnalysis {
+
+ private final MagpieServer magpieServer;
+ private final GoblintServer goblintServer;
+ private final GoblintClient goblintClient;
+
+ private final Logger log = LogManager.getLogger(GoblintAnalysis.class);
+
+
+ public GoblintAnalysis(MagpieServer magpieServer, GoblintServer goblintServer, GoblintClient goblintClient) {
+ this.magpieServer = magpieServer;
+ this.goblintServer = goblintServer;
+ this.goblintClient = goblintClient;
+ }
+
+
+ /**
+ * The source of this analysis, usually the name of the analysis.
+ *
+ * @return the string
+ */
+
+ public String source() {
+ return "GobPie";
+ }
+
+
+ /**
+ * The method that is triggered to start a new analysis.
+ *
+ * @param files the files that have been opened in the editor (not using due to using the compilation database).
+ * @param consumer the server which consumes the analysis results.
+ * @param rerun tells if the analysis should be reran.
+ */
+
+ @Override
+ public void analyze(Collection extends Module> files, AnalysisConsumer consumer, boolean rerun) {
+ if (rerun) {
+ if (consumer instanceof MagpieServer) {
+
+ preAnalyse();
+
+ System.err.println("\n---------------------- Analysis started ----------------------");
+ MagpieServer server = (MagpieServer) consumer;
+ Collection response = reanalyse();
+ if (response != null) server.consume(new ArrayList<>(response), source());
+ System.err.println("--------------------- Analysis finished ----------------------\n");
+
+ }
+ }
+ }
+
+
+ /**
+ * The method that is triggered before each analysis.
+ *
+ * preAnalyzeCommand is read from the GobPie configuration file.
+ * Can be used for automating the compilation database generation.
+ */
+
+ private void preAnalyse() {
+ String[] preAnalyzeCommand = goblintServer.getPreAnalyzeCommand();
+ if (preAnalyzeCommand != null) {
+ try {
+ log.info("Preanalyze command ran: \"" + Arrays.toString(preAnalyzeCommand) + "\"");
+ runCommand(new File(System.getProperty("user.dir")), preAnalyzeCommand);
+ log.info("Preanalyze command finished.");
+ } catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) {
+ this.magpieServer.forwardMessageToClient(
+ new MessageParams(MessageType.Warning, "Running preanalysis command failed. " + e.getMessage()));
+ }
+ }
+ }
+
+
+ /**
+ * Sends the request to Goblint server to reanalyse and reads the result.
+ *
+ * @return returns true if the request was sucessful, false otherwise
+ */
+
+ private Collection reanalyse() {
+
+ // {"jsonrpc":"2.0","id":0,"method":"analyze","params":{}}
+ String analyzeRequest = new GsonBuilder().create().toJson(new Request("analyze")) + "\n";
+ String messagesRequest = new GsonBuilder().create().toJson(new Request("messages")) + "\n";
+
+ try {
+ goblintClient.writeRequestToSocket(analyzeRequest);
+ goblintClient.readResponseFromSocket();
+ goblintClient.writeRequestToSocket(messagesRequest);
+ JsonObject response = goblintClient.readResponseFromSocket();
+ Collection results = convertResultsFromJson(response);
+ return results;
+ } catch (IOException e) {
+ log.info("Sending the request to or receiving result from the server failed: " + e);
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+
+ /**
+ * Method for running a command.
+ *
+ * @param dirPath The directory in which the command will run.
+ * @param command The command to run.
+ * @return Exit value and output of a finished process.
+ */
+
+ public ProcessResult runCommand(File dirPath, String[] command) throws IOException, InvalidExitValueException, InterruptedException, TimeoutException {
+ log.debug("Waiting for command: " + command.toString() + " to run...");
+ ProcessResult process = new ProcessExecutor()
+ .directory(dirPath)
+ .command(command)
+ .redirectOutput(System.err)
+ .redirectError(System.err)
+ .execute();
+ return process;
+ }
+
+
+ /**
+ * Deserializes json to GoblintResult objects and then converts the information
+ * into GoblintAnalysisResult objects, which Magpie uses to generate IDE
+ * messages.
+ *
+ * @return A collection of GoblintAnalysisResult objects.
+ */
+
+ private Collection convertResultsFromJson(JsonObject response) {
+
+ Collection results = new ArrayList<>();
+
+ try {
+ log.debug("Reading analysis results from json.");
+ // Read json objects as an array
+ JsonArray messagesArray = response.get("result").getAsJsonArray();
+ if (messagesArray != null && !messagesArray.isJsonArray()) {
+ log.error("Reading analysis results failed.");
+ this.magpieServer.forwardMessageToClient(
+ new MessageParams(MessageType.Error, "Reading analysis results failed."));
+ return null;
+ }
+ GsonBuilder builder = new GsonBuilder();
+ // Add deserializer for tags
+ builder.registerTypeAdapter(GoblintMessages.tag.class, new TagInterfaceAdapter());
+ Gson gson = builder.create();
+
+ for (JsonElement msg : messagesArray) {
+ GoblintMessages goblintResult = gson.fromJson(msg, GoblintMessages.class);
+ results.addAll(goblintResult.convert());
+ }
+
+ log.debug("Analysis results read from json");
+
+ return results;
+ } catch (JsonIOException | JsonSyntaxException | MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+}
diff --git a/src/main/java/GoblintAnalysisResult.java b/src/main/java/analysis/GoblintAnalysisResult.java
similarity index 99%
rename from src/main/java/GoblintAnalysisResult.java
rename to src/main/java/analysis/GoblintAnalysisResult.java
index 8664daa..d050820 100644
--- a/src/main/java/GoblintAnalysisResult.java
+++ b/src/main/java/analysis/GoblintAnalysisResult.java
@@ -1,3 +1,5 @@
+package analysis;
+
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
diff --git a/src/main/java/GoblintResult.java b/src/main/java/analysis/GoblintMessages.java
similarity index 69%
rename from src/main/java/GoblintResult.java
rename to src/main/java/analysis/GoblintMessages.java
index 4b05259..9b14fab 100644
--- a/src/main/java/GoblintResult.java
+++ b/src/main/java/analysis/GoblintMessages.java
@@ -1,23 +1,16 @@
+package analysis;
+
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.util.collections.Pair;
import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
import java.util.stream.Collectors;
-public class GoblintResult {
-
- private Map> files;
- private List messages = new ArrayList<>();
-
- static class Message {
+public class GoblintMessages {
private List tags = new ArrayList<>();
private String severity;
@@ -78,26 +71,25 @@ static class loc {
private int endColumn;
}
}
- }
}
+
public List convert() throws MalformedURLException {
List results = new ArrayList<>();
- for (Message message : messages) {
- if (message.multipiece.group_text == null) {
- String msg = message.tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " " + message.multipiece.text;
- GoblintPosition pos = new GoblintPosition(message.multipiece.loc.line, message.multipiece.loc.endLine, message.multipiece.loc.column - 1, message.multipiece.loc.endColumn - 1, new File(message.multipiece.loc.file).toURI().toURL());
- GoblintAnalysisResult result = new GoblintAnalysisResult(pos, msg, message.severity);
+ if (multipiece.group_text == null) {
+ String msg = tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " " + multipiece.text;
+ GoblintPosition pos = new GoblintPosition(multipiece.loc.line, multipiece.loc.endLine, multipiece.loc.column - 1, multipiece.loc.endColumn - 1, new File(multipiece.loc.file).toURI().toURL());
+ GoblintAnalysisResult result = new GoblintAnalysisResult(pos, msg, severity);
results.add(result);
} else {
List intermresults = new ArrayList<>();
- List pieces = message.multipiece.pieces;
- for (Message.multipiece.pieces piece : pieces) {
+ List pieces = multipiece.pieces;
+ for (multipiece.pieces piece : pieces) {
GoblintPosition pos = new GoblintPosition(piece.loc.line, piece.loc.endLine, piece.loc.column - 1, piece.loc.endColumn - 1, new File(piece.loc.file).toURI().toURL());
GoblintAnalysisResult result = new GoblintAnalysisResult(pos,
- message.tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " Group: " + message.multipiece.group_text,
- piece.text, message.severity);
+ tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " Group: " + multipiece.group_text,
+ piece.text, severity);
intermresults.add(result);
}
// Add related warnings to all the group elements
@@ -113,19 +105,18 @@ public List convert() throws MalformedURLException {
res1.severityStr(), related));
}
results.addAll(addedRelated);
- }
}
return results;
}
- public List getFiles() {
- Set allFiles = new HashSet<>();
- for (Entry> entry : files.entrySet()) {
- allFiles.add(entry.getKey());
- allFiles.addAll(entry.getValue());
- }
- return new ArrayList<>(allFiles);
- }
+ // public List getFiles() {
+ // Set allFiles = new HashSet<>();
+ // for (Entry> entry : files.entrySet()) {
+ // allFiles.add(entry.getKey());
+ // allFiles.addAll(entry.getValue());
+ // }
+ // return new ArrayList<>(allFiles);
+ // }
}
diff --git a/src/main/java/GoblintPosition.java b/src/main/java/analysis/GoblintPosition.java
similarity index 98%
rename from src/main/java/GoblintPosition.java
rename to src/main/java/analysis/GoblintPosition.java
index 09e2f8f..e70baf5 100644
--- a/src/main/java/GoblintPosition.java
+++ b/src/main/java/analysis/GoblintPosition.java
@@ -1,3 +1,5 @@
+package analysis;
+
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.classLoader.IMethod;
diff --git a/src/main/java/TagInterfaceAdapter.java b/src/main/java/analysis/TagInterfaceAdapter.java
similarity index 88%
rename from src/main/java/TagInterfaceAdapter.java
rename to src/main/java/analysis/TagInterfaceAdapter.java
index c5a59d1..4de8b71 100644
--- a/src/main/java/TagInterfaceAdapter.java
+++ b/src/main/java/analysis/TagInterfaceAdapter.java
@@ -1,3 +1,5 @@
+package analysis;
+
import java.lang.reflect.Type;
import com.google.gson.JsonDeserializationContext;
@@ -12,9 +14,9 @@ public class TagInterfaceAdapter implements JsonDeserializer