Skip to content

Commit

Permalink
libnixf: introduce nixf-tidy, perform analysis, lints and emit json (
Browse files Browse the repository at this point in the history
…#446)

Let's bring nix world automatic linting in the CI.
  • Loading branch information
inclyc authored Apr 23, 2024
1 parent dc0164e commit 25ef401
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 1 deletion.
2 changes: 2 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
, nix
, nixpkgs-fmt
, pkg-config
, nlohmann_json
}:

stdenv.mkDerivation {
Expand Down Expand Up @@ -43,6 +44,7 @@ stdenv.mkDerivation {
boost182
llvmPackages.llvm
fmt
nlohmann_json
];

env.CXXFLAGS = "-include ${nix.dev}/include/nix/config.h";
Expand Down
32 changes: 32 additions & 0 deletions libnixf/include/nixf/Basic/JSONDiagnostic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/// \file
/// \brief Provide jsonified diagnostic, for other languages/structured output.

#include "Diagnostic.h"
#include "nixf/Basic/Range.h"

#include <nlohmann/json.hpp>

namespace nixf {

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const LexerCursor &LC);

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const LexerCursorRange &LCR);

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const PartialDiagnostic &D);

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const Diagnostic &D);

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const Note &N);

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const TextEdit &D);

void to_json // NOLINT(readability-identifier-naming)
(nlohmann::json &R, const Fix &F);

} // namespace nixf
9 changes: 8 additions & 1 deletion libnixf/meson.build
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
libnixf_deps = [ boost, libnixbc ]
libnixf_deps = [ boost, libnixbc, nlohmann_json ]

libnixf_inc = include_directories('include')

libnixf = library(
'nixf',
'src/Basic/Nodes.cpp',
'src/Basic/JSONDiagnostic.cpp',
'src/Basic/Diagnostic.cpp',
'src/Bytecode/Write.cpp',
'src/Parse/Lexer.cpp',
Expand Down Expand Up @@ -77,4 +78,10 @@ test('unit/libnixf/Sema',

subdir('tools')

nixf_tidy = executable('nixf-tidy',
'tools/nixf-tidy.cpp',
dependencies: [ nixf ],
install: true
)

install_subdir('include/nixf', install_dir: 'include')
60 changes: 60 additions & 0 deletions libnixf/src/Basic/JSONDiagnostic.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "nixf/Basic/JSONDiagnostic.h"
#include "nixf/Basic/Diagnostic.h"
#include "nixf/Basic/Range.h"

using namespace nixf;
using nlohmann::json;

void nixf::to_json(json &R, const LexerCursor &LC) {
R = json{
{"line", LC.line()},
{"column", LC.column()},
{"offset", LC.offset()},
};
}

void nixf::to_json(json &R, const LexerCursorRange &LCR) {
R = json{
{"lCur", LCR.lCur()},
{"rCur", LCR.rCur()},
};
}

void nixf::to_json(json &R, const PartialDiagnostic &PD) {
R = json{
{"args", PD.args()},
{"tag", PD.tags()},
{"range", PD.range()},
};
}

void nixf::to_json(json &R, const Diagnostic &D) {
to_json(R, static_cast<const PartialDiagnostic &>(D));
R["kind"] = D.kind();
R["severity"] = Diagnostic::severity(D.kind());
R["message"] = D.message();
R["sname"] = D.sname();
R["notes"] = D.notes();
R["fixes"] = D.fixes();
}

void nixf::to_json(json &R, const Note &N) {
to_json(R, static_cast<const PartialDiagnostic &>(N));
R["kind"] = N.kind();
R["sname"] = N.sname();
R["message"] = N.message();
}

void nixf::to_json(json &R, const Fix &F) {
R = json{
{"edits", F.edits()},
{"message", F.message()},
};
}

void nixf::to_json(json &R, const TextEdit &D) {
R = json{
{"range", D.oldRange()},
{"newText", D.newText()},
};
}
55 changes: 55 additions & 0 deletions libnixf/tools/nixf-tidy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/// \file
/// \brief nixf-tidy, provide linting based on libnixf.

#include "nixf/Basic/JSONDiagnostic.h"
#include "nixf/Basic/Nodes/Basic.h"
#include "nixf/Parse/Parser.h"
#include "nixf/Sema/VariableLookup.h"

#include <iostream>
#include <sstream>

using namespace nixf;

namespace {

/// Pretty print the output.
bool PrettyPrint = false;

/// Enable variable lookup warnings.
bool VLA;

void parseArgs(int Argc, const char *Argv[]) {
for (int I = 0; I < Argc; I++) {
if (std::string_view(Argv[I]) == "--pretty-print")
PrettyPrint = true;
else if (std::string_view(Argv[I]) == "--variable-lookup")
VLA = true;
}
}

} // namespace

int main(int Argc, const char *Argv[]) {
parseArgs(Argc, Argv);
std::ostringstream Inputs;
Inputs << std::cin.rdbuf();
std::string Src = Inputs.str();

std::vector<nixf::Diagnostic> Diags;
std::shared_ptr<nixf::Node> AST = nixf::parse(Src, Diags);

if (VLA) {
VariableLookupAnalysis V(Diags);
if (AST)
V.runOnAST(*AST);
}

nlohmann::json V;
to_json(V, Diags);

if (PrettyPrint)
std::cout << std::setw(4);
std::cout << V << "\n";
return 0;
}
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ gtest_main = dependency('gtest_main')
llvm = dependency('llvm')
boost = dependency('boost')
fmt = dependency('fmt')
nlohmann_json = dependency('nlohmann_json')

backtrace = cpp.find_library('backtrace')
lit = find_program('lit', required: false)
Expand Down

0 comments on commit 25ef401

Please sign in to comment.