Skip to content

Commit 36241d9

Browse files
committed
Merge branch 'master' of github.com:AnetteTaivere/GobPie_
2 parents b042082 + 1cd6399 commit 36241d9

27 files changed

+1499
-105
lines changed

gobpie-0.0.4.vsix:Zone.Identifier

Whitespace-only changes.

pom.xml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,54 @@
77
<version>0.0.4-SNAPSHOT</version>
88
<dependencies>
99

10+
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
11+
<dependency>
12+
<groupId>ch.qos.logback</groupId>
13+
<artifactId>logback-classic</artifactId>
14+
<version>1.3.14</version>
15+
<scope>test</scope>
16+
</dependency>
17+
18+
<!-- https://mvnrepository.com/artifact/io.github.hakky54/logcaptor -->
19+
<dependency>
20+
<groupId>io.github.hakky54</groupId>
21+
<artifactId>logcaptor</artifactId>
22+
<version>2.9.2</version>
23+
<scope>test</scope>
24+
</dependency>
25+
26+
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
27+
<dependency>
28+
<groupId>org.mockito</groupId>
29+
<artifactId>mockito-core</artifactId>
30+
<version>5.8.0</version>
31+
<scope>test</scope>
32+
</dependency>
33+
34+
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
35+
<dependency>
36+
<groupId>org.junit.jupiter</groupId>
37+
<artifactId>junit-jupiter-api</artifactId>
38+
<version>5.10.2</version>
39+
<scope>test</scope>
40+
</dependency>
41+
42+
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
43+
<dependency>
44+
<groupId>org.junit.jupiter</groupId>
45+
<artifactId>junit-jupiter-engine</artifactId>
46+
<version>5.10.0</version>
47+
<scope>test</scope>
48+
</dependency>
49+
50+
<!-- https://mvnrepository.com/artifact/uk.org.webcompere/system-stubs-jupiter -->
51+
<dependency>
52+
<groupId>uk.org.webcompere</groupId>
53+
<artifactId>system-stubs-jupiter</artifactId>
54+
<version>2.1.6</version>
55+
<scope>test</scope>
56+
</dependency>
57+
1058
<!-- lsp4j DAP -->
1159
<dependency>
1260
<groupId>org.eclipse.lsp4j</groupId>
@@ -132,6 +180,19 @@
132180
</execution>
133181
</executions>
134182
</plugin>
183+
184+
<plugin>
185+
<groupId>org.apache.maven.plugins</groupId>
186+
<artifactId>maven-surefire-plugin</artifactId>
187+
<version>3.2.5</version>
188+
<dependencies>
189+
<dependency>
190+
<groupId>org.junit.jupiter</groupId>
191+
<artifactId>junit-jupiter-engine</artifactId>
192+
<version>5.10.0</version>
193+
</dependency>
194+
</dependencies>
195+
</plugin>
135196
</plugins>
136197
</build>
137198
</project>

src/main/java/Main.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import api.GoblintService;
77
import api.GoblintServiceLauncher;
88
import api.messages.params.Params;
9+
import goblintserver.GoblintConfWatcher;
910
import goblintserver.GoblintServer;
1011
import gobpie.GobPieConfReader;
1112
import gobpie.GobPieConfiguration;
@@ -17,7 +18,10 @@
1718
import org.eclipse.lsp4j.MessageParams;
1819
import org.eclipse.lsp4j.MessageType;
1920
import org.eclipse.lsp4j.jsonrpc.messages.Either;
21+
import util.FileWatcher;
22+
2023
import java.io.File;
24+
import java.nio.file.Path;
2125

2226
public class Main {
2327

@@ -40,8 +44,11 @@ public static void main(String... args) {
4044
// Connect GoblintService and read configuration
4145
GoblintService goblintService = connectGoblintService(magpieServer, gobpieConfiguration, goblintServer);
4246

47+
// Create file watcher for Goblint configuration
48+
GoblintConfWatcher goblintConfWatcher = getGoblintConfWatcher(magpieServer, goblintService, gobpieConfiguration);
49+
4350
// Add analysis
44-
addAnalysis(magpieServer, gobpieConfiguration, goblintServer, goblintService);
51+
addAnalysis(magpieServer, gobpieConfiguration, goblintServer, goblintService, goblintConfWatcher);
4552

4653
// Launch magpieServer
4754
magpieServer.configurationDone();
@@ -123,19 +130,24 @@ private static GoblintService connectGoblintService(MagpieServer magpieServer, G
123130
return goblintService;
124131
}
125132

133+
private static GoblintConfWatcher getGoblintConfWatcher(GoblintMagpieServer magpieServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration) {
134+
FileWatcher fileWatcher = new FileWatcher(Path.of(gobpieConfiguration.getGoblintConf()));
135+
return new GoblintConfWatcher(magpieServer, goblintService, gobpieConfiguration, fileWatcher);
136+
}
137+
126138

127139
/**
128140
* Method for creating and adding Goblint analysis to MagpieBridge server.
129141
* <p>
130142
* Creates the GoblintAnalysis classes.
131143
*/
132144
private static void addAnalysis(MagpieServer magpieServer, GobPieConfiguration gobpieConfiguration,
133-
GoblintServer goblintServer, GoblintService goblintService) {
145+
GoblintServer goblintServer, GoblintService goblintService, GoblintConfWatcher goblintConfWatcher) {
134146
// define language
135147
String language = "c";
136148

137149
// add analysis to the MagpieServer
138-
ServerAnalysis serverAnalysis = new GoblintAnalysis(magpieServer, goblintServer, goblintService, gobpieConfiguration);
150+
ServerAnalysis serverAnalysis = new GoblintAnalysis(magpieServer, goblintServer, goblintService, gobpieConfiguration, goblintConfWatcher);
139151
magpieServer.addAnalysis(Either.forLeft(serverAnalysis), language);
140152

141153
// add HTTP server for showing CFGs, only if the option is specified in the configuration

src/main/java/analysis/GoblintAnalysis.java

Lines changed: 19 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import api.messages.params.AnalyzeParams;
66
import api.messages.params.Params;
77
import com.ibm.wala.classLoader.Module;
8+
import goblintserver.GoblintConfWatcher;
89
import goblintserver.GoblintServer;
910
import gobpie.GobPieConfiguration;
1011
import gobpie.GobPieException;
@@ -20,12 +21,9 @@
2021
import org.zeroturnaround.exec.InvalidExitValueException;
2122
import org.zeroturnaround.exec.ProcessExecutor;
2223
import org.zeroturnaround.exec.ProcessResult;
23-
import org.zeroturnaround.process.UnixProcess;
24-
import util.FileWatcher;
2524

2625
import java.io.File;
2726
import java.io.IOException;
28-
import java.nio.file.Path;
2927
import java.util.ArrayList;
3028
import java.util.Arrays;
3129
import java.util.Collection;
@@ -51,26 +49,24 @@
5149

5250
public class GoblintAnalysis implements ServerAnalysis {
5351

54-
private final static int SIGINT = 2;
55-
5652
private final MagpieServer magpieServer;
5753
private final GoblintServer goblintServer;
5854
private final GoblintService goblintService;
5955
private final GobPieConfiguration gobpieConfiguration;
60-
private final FileWatcher goblintConfWatcher;
61-
62-
private static boolean configValid = false;
56+
private final GoblintConfWatcher goblintConfWatcher;
6357
private static Future<?> lastAnalysisTask = null;
6458

65-
private final Logger log = LogManager.getLogger(GoblintAnalysis.class);
59+
//private final Logger log = LogManager.getLogger(GoblintAnalysis.class);
60+
private Logger log = LogManager.getLogger(GoblintAnalysis.class);
6661

6762

68-
public GoblintAnalysis(MagpieServer magpieServer, GoblintServer goblintServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration) {
63+
64+
public GoblintAnalysis(MagpieServer magpieServer, GoblintServer goblintServer, GoblintService goblintService, GobPieConfiguration gobpieConfiguration, GoblintConfWatcher goblintConfWatcher) {
6965
this.magpieServer = magpieServer;
7066
this.goblintServer = goblintServer;
7167
this.goblintService = goblintService;
7268
this.gobpieConfiguration = gobpieConfiguration;
73-
this.goblintConfWatcher = new FileWatcher(Path.of(gobpieConfiguration.getGoblintConf()));
69+
this.goblintConfWatcher = goblintConfWatcher;
7470
}
7571

7672

@@ -100,7 +96,7 @@ public void analyze(Collection<? extends Module> files, AnalysisConsumer consume
10096
return;
10197
}
10298

103-
if (!goblintServer.getGoblintRunProcess().getProcess().isAlive()) {
99+
if (!goblintServer.isAlive()) {
104100
// Goblint server has crashed. Exit GobPie because without the server no analysis is possible.
105101
magpieServer.exit();
106102
return;
@@ -109,29 +105,31 @@ public void analyze(Collection<? extends Module> files, AnalysisConsumer consume
109105
if (lastAnalysisTask != null && !lastAnalysisTask.isDone()) {
110106
lastAnalysisTask.cancel(true);
111107
try {
112-
abortAnalysis();
108+
goblintServer.abortAnalysis();
113109
log.info("--------------- This analysis has been aborted -------------");
114110
} catch (IOException e) {
115111
log.error("Aborting analysis failed.");
116112
}
117113
}
118114

119-
refreshGoblintConfig();
120-
121-
if (!configValid) {
115+
if (!goblintConfWatcher.refreshGoblintConfig()) {
122116
return;
123117
}
124118

125119
magpieServer.forwardMessageToClient(new MessageParams(MessageType.Info, source() + " started analyzing the code."));
126-
127-
preAnalyse();
128-
120+
goblintServer.preAnalyse();
129121
log.info("---------------------- Analysis started ----------------------");
122+
130123
lastAnalysisTask = reanalyse().thenAccept(response -> {
124+
for (AnalysisResult analysisResult : response) {
125+
System.out.println(analysisResult.toString());
126+
}
131127
consumer.consume(new ArrayList<>(response), source());
128+
132129
log.info("--------------------- Analysis finished ----------------------");
133130
magpieServer.forwardMessageToClient(new MessageParams(MessageType.Info, source() + " finished analyzing the code."));
134131
}).exceptionally(ex -> {
132+
135133
Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
136134
// TODO: handle closed socket exceptions:
137135
// org.eclipse.lsp4j.jsonrpc.JsonRpcException: java.net.SocketException: Broken pipe; errno=32
@@ -144,59 +142,6 @@ public void analyze(Collection<? extends Module> files, AnalysisConsumer consume
144142
}
145143

146144

147-
/**
148-
* Aborts the previous running analysis by sending a SIGINT signal to Goblint.
149-
*/
150-
private void abortAnalysis() throws IOException {
151-
Process goblintProcess = goblintServer.getGoblintRunProcess().getProcess();
152-
int pid = Math.toIntExact(goblintProcess.pid());
153-
UnixProcess unixProcess = new UnixProcess(pid);
154-
unixProcess.kill(SIGINT);
155-
}
156-
157-
158-
/**
159-
* Reloads Goblint config if it has been changed or is currently invalid.
160-
*/
161-
private void refreshGoblintConfig() {
162-
if (goblintConfWatcher.checkModified() || !configValid) {
163-
configValid = goblintService.reset_config()
164-
.thenCompose(_res ->
165-
goblintService.read_config(new Params(new File(gobpieConfiguration.getGoblintConf()).getAbsolutePath())))
166-
.handle((_res, ex) -> {
167-
if (ex != null) {
168-
Throwable cause = ex instanceof CompletionException ? ex.getCause() : ex;
169-
String msg = "Goblint was unable to successfully read the new configuration: " + cause.getMessage();
170-
magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, msg));
171-
log.error(msg);
172-
return false;
173-
}
174-
return true;
175-
})
176-
.join();
177-
}
178-
}
179-
180-
181-
/**
182-
* The method that is triggered before each analysis.
183-
* <p>
184-
* preAnalyzeCommand is read from the GobPie configuration file.
185-
* Can be used for automating the compilation database generation.
186-
*/
187-
private void preAnalyse() {
188-
String[] preAnalyzeCommand = gobpieConfiguration.getPreAnalyzeCommand();
189-
if (preAnalyzeCommand != null) {
190-
try {
191-
log.info("Preanalyze command ran: \"" + Arrays.toString(preAnalyzeCommand) + "\"");
192-
runCommand(new File(System.getProperty("user.dir")), preAnalyzeCommand);
193-
log.info("Preanalyze command finished.");
194-
} catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) {
195-
this.magpieServer.forwardMessageToClient(
196-
new MessageParams(MessageType.Warning, "Running preanalysis command failed. " + e.getMessage()));
197-
}
198-
}
199-
}
200145

201146
/**
202147
* Sends the requests to Goblint server and gets their results.
@@ -207,7 +152,8 @@ private void preAnalyse() {
207152
* @return a CompletableFuture of a collection of warning messages and cfg code lenses if request was successful.
208153
* @throws GobPieException in case the analysis was aborted or returned a VerifyError.
209154
*/
210-
private CompletableFuture<Collection<AnalysisResult>> reanalyse() {
155+
public CompletableFuture<Collection<AnalysisResult>> reanalyse() {
156+
//return goblintService.analyze(new AnalyzeParams(true))
211157
return goblintService.analyze(new AnalyzeParams(!gobpieConfiguration.useIncrementalAnalysis()))
212158
.thenCompose(this::getComposedAnalysisResults);
213159
}

src/main/java/analysis/GoblintCFGAnalysisResult.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import java.util.ArrayList;
1111
import java.util.Collections;
12+
import java.util.Objects;
1213

1314
/**
1415
* The Class GoblintCFGAnalysisResult.
@@ -72,4 +73,28 @@ public Pair<Position, String> repair() {
7273
public String code() {
7374
return null;
7475
}
76+
77+
78+
@Override
79+
public boolean equals(Object o) {
80+
if (this == o) return true;
81+
if (o == null || getClass() != o.getClass()) return false;
82+
GoblintCFGAnalysisResult that = (GoblintCFGAnalysisResult) o;
83+
return Objects.equals(pos, that.pos) && Objects.equals(title, that.title) && Objects.equals(funName, that.funName) && Objects.equals(related, that.related);
84+
}
85+
86+
@Override
87+
public int hashCode() {
88+
return Objects.hash(pos, title, funName, related);
89+
}
90+
91+
@Override
92+
public String toString() {
93+
return "GoblintCFGAnalysisResult{" +
94+
"pos=" + pos +
95+
", title='" + title + '\'' +
96+
", funName='" + funName + '\'' +
97+
", related=" + related +
98+
'}';
99+
}
75100
}

src/main/java/analysis/GoblintMessagesAnalysisResult.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.eclipse.lsp4j.DiagnosticSeverity;
99

1010
import java.util.ArrayList;
11+
import java.util.Objects;
1112

1213
/**
1314
* The Class GoblintMessagesAnalysisResult.
@@ -108,4 +109,27 @@ public String code() {
108109
return null;
109110
}
110111

112+
@Override
113+
public boolean equals(Object o) {
114+
if (this == o) return true;
115+
if (o == null || getClass() != o.getClass()) return false;
116+
GoblintMessagesAnalysisResult that = (GoblintMessagesAnalysisResult) o;
117+
return Objects.equals(group_text, that.group_text) && Objects.equals(text, that.text) && Objects.equals(pos, that.pos) && Objects.equals(severity, that.severity) && Objects.equals(related, that.related);
118+
}
119+
120+
@Override
121+
public int hashCode() {
122+
return Objects.hash(group_text, text, pos, severity, related);
123+
}
124+
125+
@Override
126+
public String toString() {
127+
return "GoblintMessagesAnalysisResult{" +
128+
"group_text='" + group_text + '\'' +
129+
", text='" + text + '\'' +
130+
", pos=" + pos.toString() +
131+
", severity='" + severity + '\'' +
132+
", related=" + related +
133+
'}';
134+
}
111135
}

0 commit comments

Comments
 (0)