|
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