Skip to content

Commit e6696ef

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

3 files changed

Lines changed: 83 additions & 1 deletion

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/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: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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 outputJson = false;
21+
22+
auto subcommand = app->add_subcommand("lint", "Compiles the given pattern");
23+
24+
// Add command line arguments
25+
subcommand->add_option("-p,--pattern,PATTERN_FILE", patternFilePath, "Pattern file")->required()->check(CLI::ExistingFile);
26+
subcommand->add_option("-I,--includes", includePaths, "Include file paths")->take_all()->check(CLI::ExistingDirectory);
27+
subcommand->add_option("-D,--define", defines, "Define a preprocessor macro")->take_all();
28+
subcommand->add_flag("-j,--json", outputJson, "Output JSON instead of text")->default_val(false);
29+
30+
subcommand->callback([] {
31+
// Open pattern file
32+
wolv::io::File patternFile(patternFilePath, wolv::io::File::Mode::Read);
33+
if (!patternFile.isValid()) {
34+
::fmt::print("Failed to open file '{}'\n", patternFilePath.string());
35+
std::exit(EXIT_FAILURE);
36+
}
37+
38+
// Create and configure Pattern Language runtime
39+
pl::PatternLanguage runtime;
40+
41+
runtime.setIncludePaths(includePaths);
42+
43+
for (const auto &define : defines)
44+
runtime.addDefine(define);
45+
46+
const auto code = patternFile.readString();
47+
const auto source = wolv::util::toUTF8String(patternFile.getPath());
48+
auto _ = runtime.parseString(code, source);
49+
50+
auto compileErrors = runtime.getCompileErrors();
51+
::nlohmann::json errors = ::nlohmann::json::array();
52+
if (compileErrors.size() > 0) {
53+
for (const auto &error : compileErrors) {
54+
if (outputJson) {
55+
::nlohmann::json obj;
56+
obj["message"] = error.getMessage();
57+
obj["description"] = error.getDescription();
58+
59+
::nlohmann::json loc;
60+
const auto &location = error.getLocation();
61+
loc["line"] = location.line;
62+
loc["column"] = location.column;
63+
loc["source"] = location.source->source;
64+
obj["location"] = loc;
65+
66+
errors.emplace_back(obj);
67+
} else {
68+
::fmt::print("{}\n", error.format());
69+
}
70+
}
71+
}
72+
73+
if(outputJson) {
74+
::fmt::print("{}\n", errors.dump());
75+
}
76+
});
77+
}
78+
79+
}

0 commit comments

Comments
 (0)