Skip to content

Commit b640858

Browse files
committed
cli: Add lint subcommand
1 parent c40b98c commit b640858

5 files changed

Lines changed: 104 additions & 7 deletions

File tree

cli/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ set(PLCLI_SOURCES
1313
source/subcommands/run.cpp
1414
source/subcommands/docs.cpp
1515
source/subcommands/info.cpp
16+
source/subcommands/lint.cpp
1617
)
1718

1819
if (LIBPL_BUILD_CLI_AS_EXECUTABLE)

cli/include/pl/cli/helpers/utils.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@
77

88
namespace pl::cli {
99

10+
void configureRuntime(
11+
PatternLanguage &runtime,
12+
const std::vector<std::fs::path> &includePaths,
13+
const std::vector<std::string> &defines,
14+
bool allowDangerousFunctions);
15+
1016
void executePattern(
1117
PatternLanguage &runtime,
1218
wolv::io::File &inputFilePath,
@@ -15,4 +21,5 @@ namespace pl::cli {
1521
const std::vector<std::string> &defines,
1622
bool allowDangerousFunctions,
1723
u64 baseAddress);
18-
}
24+
25+
}

cli/source/helpers/utils.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,11 @@ namespace pl::cli {
2626
return result;
2727
}
2828

29-
void executePattern(
29+
void configureRuntime(
3030
PatternLanguage &runtime,
31-
wolv::io::File &inputFile,
32-
wolv::io::File &patternFile,
3331
const std::vector<std::fs::path> &includePaths,
3432
const std::vector<std::string> &defines,
35-
bool allowDangerousFunctions,
36-
u64 baseAddress) {
33+
bool allowDangerousFunctions) {
3734

3835
runtime.setDangerousFunctionCallHandler([&]() {
3936
return allowDangerousFunctions;
@@ -43,6 +40,18 @@ namespace pl::cli {
4340

4441
for (const auto &define : defines)
4542
runtime.addDefine(define);
43+
}
44+
45+
void executePattern(
46+
PatternLanguage &runtime,
47+
wolv::io::File &inputFile,
48+
wolv::io::File &patternFile,
49+
const std::vector<std::fs::path> &includePaths,
50+
const std::vector<std::string> &defines,
51+
bool allowDangerousFunctions,
52+
u64 baseAddress) {
53+
54+
configureRuntime(runtime, includePaths, defines, allowDangerousFunctions);
4655

4756
if (inputFile.isValid()) {
4857
// Include baseAddress as a copy to prevent it from going out of scope in the lambda

cli/source/main.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace pl::cli {
1616
void addRunSubcommand(CLI::App *app);
1717
void addDocsSubcommand(CLI::App *app);
1818
void addInfoSubcommand(CLI::App *app);
19+
void addLintSubcommand(CLI::App *app);
1920

2021
}
2122

@@ -30,6 +31,7 @@ namespace pl::cli {
3031
sub::addRunSubcommand(&app);
3132
sub::addDocsSubcommand(&app);
3233
sub::addInfoSubcommand(&app);
34+
sub::addLintSubcommand(&app);
3335

3436
// Print help message if not enough arguments were provided
3537
if (args.size() == 0) {
@@ -76,4 +78,4 @@ namespace pl::cli {
7678

7779
return pl::cli::executeCommandLineInterface(args);
7880
}
79-
#endif
81+
#endif

cli/source/subcommands/lint.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <pl/pattern_language.hpp>
2+
#include <pl/formatters.hpp>
3+
#include <wolv/io/file.hpp>
4+
5+
#include <pl/cli/helpers/utils.hpp>
6+
7+
#include <CLI/CLI.hpp>
8+
#include <CLI/App.hpp>
9+
#include <fmt/format.h>
10+
11+
#include <nlohmann/json.hpp>
12+
13+
namespace pl::cli::sub {
14+
15+
void addLintSubcommand(CLI::App *app) {
16+
static std::fs::path patternFilePath;
17+
static std::vector<std::fs::path> includePaths;
18+
static std::vector<std::string> defines;
19+
20+
static bool allowDangerousFunctions = false;
21+
static bool outputJson = false;
22+
23+
auto subcommand = app->add_subcommand("lint", "Compiles the given pattern");
24+
25+
// Add command line arguments
26+
subcommand->add_option("-p,--pattern,PATTERN_FILE", patternFilePath, "Pattern file")->required()->check(CLI::ExistingFile);
27+
subcommand->add_option("-I,--includes", includePaths, "Include file paths")->take_all()->check(CLI::ExistingDirectory);
28+
subcommand->add_option("-D,--define", defines, "Define a preprocessor macro")->take_all();
29+
subcommand->add_flag("-d,--dangerous", allowDangerousFunctions, "Allow dangerous functions")->default_val(false);
30+
subcommand->add_flag("-j,--json", outputJson, "Output JSON instead of text")->default_val(false);
31+
32+
subcommand->callback([] {
33+
// Open pattern file
34+
wolv::io::File patternFile(patternFilePath, wolv::io::File::Mode::Read);
35+
if (!patternFile.isValid()) {
36+
::fmt::print("Failed to open file '{}'\n", patternFilePath.string());
37+
std::exit(EXIT_FAILURE);
38+
}
39+
40+
// Create and configure Pattern Language runtime
41+
pl::PatternLanguage runtime;
42+
43+
pl::cli::configureRuntime(runtime, includePaths, defines, allowDangerousFunctions);
44+
45+
const auto code = patternFile.readString();
46+
const auto source = wolv::util::toUTF8String(patternFile.getPath());
47+
auto _ = runtime.parseString(code, source);
48+
49+
auto compileErrors = runtime.getCompileErrors();
50+
::nlohmann::json errors = ::nlohmann::json::array();
51+
if (compileErrors.size() > 0) {
52+
for (const auto &error : compileErrors) {
53+
if (outputJson) {
54+
::nlohmann::json obj;
55+
obj["message"] = error.getMessage();
56+
obj["description"] = error.getDescription();
57+
58+
::nlohmann::json loc;
59+
const auto &location = error.getLocation();
60+
loc["line"] = location.line;
61+
loc["column"] = location.column;
62+
loc["source"] = location.source->source;
63+
obj["location"] = loc;
64+
65+
errors.emplace_back(obj);
66+
} else {
67+
::fmt::print("{}\n", error.format());
68+
}
69+
}
70+
}
71+
72+
if(outputJson) {
73+
::fmt::print("{}\n", errors.dump());
74+
}
75+
});
76+
}
77+
78+
}

0 commit comments

Comments
 (0)