Skip to content

Commit

Permalink
Merge pull request #2008 from lf-lang/target-properties
Browse files Browse the repository at this point in the history
Refactoring of target properties and their validation
  • Loading branch information
lhstrh authored Nov 3, 2023
2 parents ca4f7f2 + a9f60c3 commit f92b6d9
Show file tree
Hide file tree
Showing 183 changed files with 5,544 additions and 3,963 deletions.
4 changes: 2 additions & 2 deletions .github/scripts/run-zephyr-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ num_successes=0
num_failures=0
failed_tests=""

# Skip
skip=("FileReader" "FilePkgReader" "Tracing" "ThreadedThreaded")
# Skip tests doing file IO and tracing
skip=("FileReader" "FilePkgReader" "Tracing" "ThreadedThreaded" "CountTest" "AsyncCallback")

find_kconfig_folders() {
if [ -f "$folder/CMakeLists.txt" ]; then
Expand Down
156 changes: 78 additions & 78 deletions cli/base/src/main/java/org/lflang/cli/CliBase.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.lflang.cli;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
Expand All @@ -17,8 +16,6 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
Expand Down Expand Up @@ -62,22 +59,21 @@ static class MutuallyExclusive {
protected List<Path> files;

@Option(names = "--json", description = "JSON object containing CLI arguments.")
private String jsonString;
String jsonString;

@Option(names = "--json-file", description = "JSON file containing CLI arguments.")
private Path jsonFile;
Path jsonFile;

@Option(names = "--stdin", description = "Read paths to Lingua Franca programs from stdin.")
private boolean stdin;
}

@ArgGroup(exclusive = true, multiplicity = "1")
@ArgGroup(multiplicity = "1")
MutuallyExclusive topLevelArg;

@Option(
names = {"-o", "--output-path"},
defaultValue = "",
fallbackValue = "",
description = "Specify the root output directory.")
private Path outputPath;

Expand All @@ -99,6 +95,8 @@ static class MutuallyExclusive {
/** Injected resource validator. */
@Inject private IResourceValidator validator;

private JsonObject jsonObject;

protected static void cliMain(
String toolName, Class<? extends CliBase> toolClass, Io io, String[] args) {
// Injector used to obtain Main instance.
Expand All @@ -123,27 +121,7 @@ public void doExecute(Io io, String[] args) {
* the Runnable interface, is instantiated.
*/
public void run() {
// If args are given in a json file, store its contents in jsonString.
if (topLevelArg.jsonFile != null) {
try {
topLevelArg.jsonString =
new String(Files.readAllBytes(io.getWd().resolve(topLevelArg.jsonFile)));
} catch (IOException e) {
reporter.printFatalErrorAndExit("No such file: " + topLevelArg.jsonFile);
}
}
// If args are given in a json string, unpack them and re-run
// picocli argument validation.
if (topLevelArg.jsonString != null) {
// Unpack args from json string.
String[] args = jsonStringToArgs(topLevelArg.jsonString);
// Execute application on unpacked args.
CommandLine cmd = spec.commandLine();
cmd.execute(args);
// If args are already unpacked, invoke tool-specific logic.
} else {
doRun();
}
doRun();
}

/*
Expand Down Expand Up @@ -183,6 +161,24 @@ protected List<Path> getInputPaths() {
}
if (line == null) return List.of();
return List.of(Path.of(line));
} else if (topLevelArg.jsonFile != null || topLevelArg.jsonString != null) {
paths = new ArrayList<>();
var filesObj = getJsonObject().get("src");
if (filesObj != null) {
if (filesObj.isJsonPrimitive()) {
paths = List.of(Path.of(filesObj.getAsString()));
} else if (filesObj.isJsonArray()) {
paths =
filesObj.getAsJsonArray().asList().stream()
.map(e -> Path.of(e.getAsString()))
.toList();
} else {
reporter.printFatalErrorAndExit(
"JSON Parse Exception: field \"src\" must be a string or an array of strings.");
}
} else {
reporter.printFatalErrorAndExit("JSON Parse Exception: field \"src\" not found.");
}
} else {
paths = topLevelArg.files.stream().map(io.getWd()::resolve).collect(Collectors.toList());
}
Expand All @@ -196,6 +192,29 @@ protected List<Path> getInputPaths() {
return paths;
}

protected final JsonObject getJsonObject() {
if (jsonObject != null) {
return jsonObject;
}
var jsonString = topLevelArg.jsonString;
// If args are given in a json file, store its contents in jsonString.
if (topLevelArg.jsonFile != null) {
try {
jsonString = new String(Files.readAllBytes(io.getWd().resolve(topLevelArg.jsonFile)));
} catch (IOException e) {
reporter.printFatalErrorAndExit("No such file: " + topLevelArg.jsonFile);
}
}
if (jsonString != null) {
try {
jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
} catch (JsonParseException e) {
messageReporter.nowhere().error(String.format("Invalid JSON string:%n %s", jsonString));
}
}
return jsonObject;
}

protected final boolean stdinMode() {
return topLevelArg.stdin;
}
Expand All @@ -207,23 +226,39 @@ protected final boolean stdinMode() {
*/
protected Path getOutputRoot() {
Path root = null;
Path path = null;

if (!outputPath.toString().isEmpty()) {
path = outputPath;
} else {
var json = getJsonObject();
if (json != null) {
var obj = json.get("out");
if (obj != null) {
path = Path.of(obj.getAsString());
}
}
}

if (path != null) {
root = io.getWd().resolve(outputPath).normalize();
if (!Files.exists(root)) { // FIXME: Create it instead?
if (!Files.exists(root)) {
reporter.printFatalErrorAndExit(root + ": Output location does not exist.");
}
if (!Files.isDirectory(root)) {
reporter.printFatalErrorAndExit(root + ": Output location is not a directory.");
}
}

return root;
}

/** If some errors were collected, print them and abort execution. Otherwise, return. */
protected void exitIfCollectedErrors() {
if (issueCollector.getErrorsOccurred()) {
// if there are errors, don't print warnings.

// Print warnings if there are any.
printWarningsIfAny();

List<LfIssue> errors = printErrorsIfAny();
String cause = errors.size() + " previous error";
if (errors.size() > 1) {
Expand All @@ -234,7 +269,18 @@ protected void exitIfCollectedErrors() {
}

/**
* If any errors were collected, print them, then return them.
* If any warnings were collected, print them, then return them.
*
* @return A list of collected warnings.
*/
public List<LfIssue> printWarningsIfAny() {
List<LfIssue> errors = issueCollector.getWarnings();
errors.forEach(reporter::printIssue);
return errors;
}

/**
* If any warnings were collected, print them, then return them.
*
* @return A list of collected errors.
*/
Expand Down Expand Up @@ -293,50 +339,4 @@ public Resource getResource(Path path) {
return null;
}
}

private String[] jsonStringToArgs(String jsonString) {
ArrayList<String> argsList = new ArrayList<>();
JsonObject jsonObject = new JsonObject();

// Parse JSON string and get top-level JSON object.
try {
jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
} catch (JsonParseException e) {
reporter.printFatalErrorAndExit(String.format("Invalid JSON string:%n %s", jsonString));
}
// Append input paths.
JsonElement src = jsonObject.get("src");
if (src == null) {
reporter.printFatalErrorAndExit("JSON Parse Exception: field \"src\" not found.");
}
assert src != null;
argsList.add(src.getAsString());
// Append output path if given.
JsonElement out = jsonObject.get("out");
if (out != null) {
argsList.add("--output-path");
argsList.add(out.getAsString());
}

// If there are no other properties, return args array.
JsonElement properties = jsonObject.get("properties");
if (properties != null) {
// Get the remaining properties.
Set<Entry<String, JsonElement>> entrySet = properties.getAsJsonObject().entrySet();
// Append the remaining properties to the args array.
for (Entry<String, JsonElement> entry : entrySet) {
String property = entry.getKey();
String value = entry.getValue().getAsString();

// Append option.
argsList.add("--" + property);
// Append argument for non-boolean options.
if (!value.equals("true") || property.equals("threading")) {
argsList.add(value);
}
}
}

return argsList.toArray(new String[0]);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.google.inject.Inject;
import java.nio.file.Path;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.lsp4j.DiagnosticSeverity;
import org.eclipse.xtext.diagnostics.Severity;
import org.lflang.MessageReporterBase;
Expand All @@ -52,8 +53,9 @@ static Severity convertSeverity(DiagnosticSeverity severity) {
}

@Override
protected void reportOnNode(EObject node, DiagnosticSeverity severity, String message) {
issueAcceptor.accept(convertSeverity(severity), message, node, null, 0, null);
protected void reportOnNode(
EObject node, EStructuralFeature feature, DiagnosticSeverity severity, String message) {
issueAcceptor.accept(convertSeverity(severity), message, node, feature, 0, null);
}

@Override
Expand Down
10 changes: 7 additions & 3 deletions cli/base/src/main/kotlin/org/lflang/cli/ReportingUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -176,17 +176,21 @@ data class LfIssue(
@Singleton // one instance per injector
class IssueCollector {
private val map = mutableMapOf<Severity, MutableSet<LfIssue>>()
/** Whether any errors occurred.*/
/** Whether any errors occurred. */
val errorsOccurred: Boolean get() = map[Severity.ERROR]?.isNotEmpty() == true

fun accept(issue: LfIssue) {
val set = map.computeIfAbsent(issue.severity) { mutableSetOf() }
set += issue
}

/** Sorted list of all errors.*/
/** Sorted list of all errors. */
val errors: List<LfIssue> get() = map[Severity.ERROR].orEmpty().sorted()
/** Sorted list of all issues.*/

/** Sorted list of all warnings. */
val warnings: List<LfIssue> get() = map[Severity.WARNING].orEmpty().sorted()

/** Sorted list of all issues. */
val allIssues: List<LfIssue> get() = map.values.flatten().sorted()
}

Expand Down
Loading

0 comments on commit f92b6d9

Please sign in to comment.