|
3 | 3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | 4 | // |
5 | 5 |
|
6 | | -package com.adacore.lkql_jit.drivers; |
| 6 | +package com.adacore.lkql_jit; |
7 | 7 |
|
8 | | -import com.adacore.lkql_jit.options.JsonUtils; |
9 | | -import com.adacore.lkql_jit.options.RuleInstance; |
10 | 8 | import java.io.File; |
11 | 9 | import java.io.IOException; |
12 | 10 | import java.nio.file.Files; |
13 | 11 | import java.nio.file.Paths; |
14 | 12 | import java.util.*; |
15 | 13 | import java.util.concurrent.Callable; |
| 14 | +import java.util.stream.Collectors; |
16 | 15 | import org.graalvm.launcher.AbstractLanguageLauncher; |
17 | 16 | import org.graalvm.options.OptionCategory; |
18 | 17 | import org.graalvm.polyglot.Context; |
19 | 18 | import org.graalvm.polyglot.Engine; |
20 | 19 | import org.graalvm.polyglot.Source; |
21 | 20 | import org.graalvm.polyglot.Value; |
| 21 | +import org.json.JSONObject; |
22 | 22 | import picocli.CommandLine; |
23 | 23 |
|
24 | 24 | /** |
@@ -168,106 +168,67 @@ protected void launch(Context.Builder contextBuilder) { |
168 | 168 | * @return The exit code of the script. |
169 | 169 | */ |
170 | 170 | protected int executeScript(Context.Builder contextBuilder) { |
171 | | - // Set the builder common options |
172 | | - contextBuilder.allowIO(true); |
173 | | - contextBuilder.option("lkql.diagnosticOutputMode", "GNATCHECK"); |
174 | | - |
175 | | - // If no rules are provided, don't do anything |
176 | | - contextBuilder.option("lkql.fallbackToAllRules", "false"); |
| 171 | + // Create the LKQL options object builder |
| 172 | + final var optionsBuilder = new LKQLOptions.Builder(); |
177 | 173 |
|
178 | | - // Do not stop the worker's execution when a source file is missing |
179 | | - contextBuilder.option("lkql.keepGoingOnMissingFile", "true"); |
| 174 | + // Set the common configuration |
| 175 | + contextBuilder.allowIO(true); |
| 176 | + contextBuilder.engine( |
| 177 | + Engine.newBuilder() |
| 178 | + .allowExperimentalOptions(true) |
| 179 | + .option("engine.Compilation", "false") |
| 180 | + .build()); |
| 181 | + optionsBuilder |
| 182 | + .diagnosticOutputMode(LKQLOptions.DiagnosticOutputMode.GNATCHECK) |
| 183 | + .fallbackToAllRules(false) |
| 184 | + .keepGoingOnMissingFile(true); |
180 | 185 |
|
181 | 186 | // If a LKQL rule config file has been provided, parse it and display the result |
182 | 187 | if (this.args.lkqlConfigFile != null) { |
183 | 188 | System.out.println( |
184 | | - JsonUtils.serializeInstances(parseLKQLRuleFile(this.args.lkqlConfigFile))); |
| 189 | + new JSONObject( |
| 190 | + parseLKQLRuleFile(this.args.lkqlConfigFile).entrySet().stream() |
| 191 | + .map(e -> Map.entry(e.getKey(), e.getValue().toJson())) |
| 192 | + .collect( |
| 193 | + Collectors.toMap( |
| 194 | + Map.Entry::getKey, Map.Entry::getValue)))); |
185 | 195 | return 0; |
186 | 196 | } |
187 | 197 |
|
188 | | - // Set the context options |
189 | | - if (this.args.verbose) { |
190 | | - contextBuilder.option("lkql.verbose", "true"); |
191 | | - } |
192 | | - |
193 | | - // Set the project file |
194 | | - if (this.args.project != null) { |
195 | | - contextBuilder.option("lkql.projectFile", this.args.project); |
196 | | - } |
197 | | - |
198 | | - if (this.args.subProject != null) { |
199 | | - contextBuilder.option("lkql.subprojectFile", this.args.subProject); |
200 | | - } |
201 | | - |
202 | | - if (this.args.debug) { |
203 | | - contextBuilder.option("lkql.checkerDebug", "true"); |
204 | | - } |
205 | | - |
206 | | - if (!this.args.scenarioVariables.isEmpty()) { |
207 | | - StringBuilder scenarioVars = new StringBuilder(); |
208 | | - Base64.Encoder encoder = Base64.getEncoder(); |
209 | | - this.args.scenarioVariables.forEach( |
210 | | - (key, val) -> { |
211 | | - scenarioVars.append( |
212 | | - new String(encoder.encode((key + "=" + val).getBytes()))); |
213 | | - scenarioVars.append(";"); |
214 | | - }); |
215 | | - contextBuilder.option("lkql.scenarioVars", scenarioVars.toString()); |
216 | | - } |
217 | | - |
218 | | - if (this.args.target != null) { |
219 | | - contextBuilder.option("lkql.target", this.args.target); |
220 | | - } |
221 | | - |
222 | | - if (this.args.RTS != null) { |
223 | | - contextBuilder.option("lkql.runtime", this.args.RTS); |
224 | | - } |
225 | | - |
226 | | - if (this.args.configFile != null) { |
227 | | - contextBuilder.option("lkql.configFile", this.args.configFile); |
228 | | - } |
229 | | - |
230 | | - // Set the files |
| 198 | + // Forward the command line options to the options object builder |
| 199 | + optionsBuilder |
| 200 | + .verbose(this.args.verbose) |
| 201 | + .projectFile(this.args.project) |
| 202 | + .subprojectFile(this.args.subProject) |
| 203 | + .scenarioVariables(this.args.scenarioVariables) |
| 204 | + .target(this.args.target) |
| 205 | + .runtime(this.args.RTS) |
| 206 | + .configFile(this.args.configFile) |
| 207 | + .charset(this.args.charset) |
| 208 | + .rulesDir(this.args.rulesDirs) |
| 209 | + .showInstantiationChain(this.args.showInstantiationChain) |
| 210 | + .checkerDebug(this.args.debug); |
| 211 | + |
| 212 | + // Read the list of sources to analyze provided by GNATcheck driver |
231 | 213 | if (this.args.filesFrom != null) { |
232 | 214 | try { |
233 | | - final List<String> lines = Files.readAllLines(Paths.get(this.args.filesFrom)); |
234 | | - final String files = String.join(File.pathSeparator, lines); |
235 | | - contextBuilder.option("lkql.files", files); |
| 215 | + optionsBuilder.files(Files.readAllLines(Paths.get(this.args.filesFrom))); |
236 | 216 | } catch (IOException e) { |
237 | 217 | System.err.println("Could not read file: " + this.args.filesFrom); |
238 | 218 | } |
239 | 219 | } |
240 | 220 |
|
241 | | - // Set the charset |
242 | | - if (this.args.charset != null) { |
243 | | - contextBuilder.option("lkql.charset", this.args.charset); |
244 | | - } |
245 | | - |
246 | | - // Set the rule directories |
247 | | - if (!this.args.rulesDirs.isEmpty()) { |
248 | | - contextBuilder.option( |
249 | | - "lkql.rulesDirs", String.join(File.pathSeparator, this.args.rulesDirs)); |
250 | | - } |
251 | | - |
252 | | - // Set the generic instantiation displaying parameter |
253 | | - if (this.args.showInstantiationChain) { |
254 | | - contextBuilder.option("lkql.showInstantiationChain", "true"); |
255 | | - } |
256 | | - |
257 | | - // Set the rule instances |
| 221 | + // Parse the rule instances provided by the GNATcheck driver |
258 | 222 | final Map<String, RuleInstance> instances = new HashMap<>(); |
259 | 223 | for (var rulesFrom : this.args.rulesFroms) { |
260 | 224 | if (!rulesFrom.isEmpty()) { |
261 | 225 | instances.putAll(parseLKQLRuleFile(rulesFrom)); |
262 | 226 | } |
263 | 227 | } |
264 | | - contextBuilder.option("lkql.ruleInstances", JsonUtils.serializeInstances(instances)); |
| 228 | + optionsBuilder.ruleInstances(instances); |
265 | 229 |
|
266 | | - contextBuilder.engine( |
267 | | - Engine.newBuilder() |
268 | | - .allowExperimentalOptions(true) |
269 | | - .option("engine.Compilation", "false") |
270 | | - .build()); |
| 230 | + // Finally, pass the options to the LKQL engine |
| 231 | + contextBuilder.option("lkql.options", optionsBuilder.build().toJson().toString()); |
271 | 232 |
|
272 | 233 | // Create the context and run the script in it |
273 | 234 | try (Context context = contextBuilder.build()) { |
@@ -307,7 +268,14 @@ private static Map<String, RuleInstance> parseLKQLRuleFile(final String lkqlRule |
307 | 268 | final Map<String, RuleInstance> res = new HashMap<>(); |
308 | 269 | try (Context context = |
309 | 270 | Context.newBuilder() |
310 | | - .option("lkql.diagnosticOutputMode", "GNATCHECK") |
| 271 | + .option( |
| 272 | + "lkql.options", |
| 273 | + new LKQLOptions.Builder() |
| 274 | + .diagnosticOutputMode( |
| 275 | + LKQLOptions.DiagnosticOutputMode.GNATCHECK) |
| 276 | + .build() |
| 277 | + .toJson() |
| 278 | + .toString()) |
311 | 279 | .allowIO(true) |
312 | 280 | .build()) { |
313 | 281 | // Parse the LKQL rule configuration file with a polyglot context |
|
0 commit comments