yql_linter.cpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <yql/essentials/public/fastcheck/linter.h>
  2. #include <yql/essentials/utils/tty.h>
  3. #include <library/cpp/getopt/last_getopt.h>
  4. #include <google/protobuf/arena.h>
  5. #include <library/cpp/colorizer/output.h>
  6. #include <util/generic/serialized_enum.h>
  7. #include <util/stream/file.h>
  8. int Run(int argc, char* argv[]) {
  9. NLastGetopt::TOpts opts = NLastGetopt::TOpts::Default();
  10. TString inFileName;
  11. TString queryString;
  12. TString checks;
  13. THashMap<TString, TString> clusterMapping;
  14. TString modeStr = "Default";
  15. TString syntaxStr = "YQL";
  16. opts.AddLongOption('i', "input", "input file").RequiredArgument("input").StoreResult(&inFileName);
  17. opts.AddLongOption('v', "verbose", "show lint issues").NoArgument();
  18. opts.AddLongOption("list-checks", "list all enabled checks and exit").NoArgument();
  19. opts.AddLongOption("checks", "comma-separated list of globs with optional '-' prefix").StoreResult(&checks);
  20. opts.AddLongOption('C', "cluster", "cluster to service mapping").RequiredArgument("name@service")
  21. .KVHandler([&](TString cluster, TString provider) {
  22. if (cluster.empty() || provider.empty()) {
  23. throw yexception() << "Incorrect service mapping, expected form cluster@provider, e.g. plato@yt";
  24. }
  25. clusterMapping[cluster] = provider;
  26. }, '@');
  27. opts.AddLongOption('m', "mode", "query mode, allowed values: " + GetEnumAllNames<NYql::NFastCheck::EMode>()).StoreResult(&modeStr);
  28. opts.AddLongOption('s', "syntax", "query syntax, allowed values: " + GetEnumAllNames<NYql::NFastCheck::ESyntax>()).StoreResult(&syntaxStr);
  29. opts.AddLongOption("ansi-lexer", "use ansi lexer").NoArgument();
  30. opts.AddLongOption("no-colors", "disable colors for output").NoArgument();
  31. opts.SetFreeArgsNum(0);
  32. opts.AddHelpOption();
  33. NLastGetopt::TOptsParseResult res(&opts, argc, argv);
  34. const bool colorize = !res.Has("no-colors") && IsTty(NYql::EStdStream::Out);
  35. NYql::NFastCheck::TChecksRequest checkReq;
  36. if (res.Has("checks")) {
  37. checkReq.Filters = NYql::NFastCheck::ParseChecks(checks);
  38. }
  39. if (res.Has("list-checks")) {
  40. for (const auto& c : NYql::NFastCheck::ListChecks(checkReq.Filters)) {
  41. if (colorize) {
  42. Cout << NColorizer::LightCyan();
  43. }
  44. Cout << c;
  45. if (colorize) {
  46. Cout << NColorizer::Old();
  47. }
  48. Cout << '\n';
  49. }
  50. return 0;
  51. }
  52. THolder<TUnbufferedFileInput> inFile;
  53. if (!inFileName.empty()) {
  54. inFile.Reset(new TUnbufferedFileInput(inFileName));
  55. }
  56. IInputStream& in = inFile ? *inFile.Get() : Cin;
  57. queryString = in.ReadAll();
  58. int errors = 0;
  59. TString queryFile("query");
  60. checkReq.IsAnsiLexer = res.Has("ansi-lexer");
  61. checkReq.Program = queryString;
  62. checkReq.Syntax = NYql::NFastCheck::ESyntax::YQL;
  63. checkReq.ClusterMapping = clusterMapping;
  64. checkReq.Mode = FromString<NYql::NFastCheck::EMode>(modeStr);
  65. checkReq.Syntax = FromString<NYql::NFastCheck::ESyntax>(syntaxStr);
  66. auto checkResp = NYql::NFastCheck::RunChecks(checkReq);
  67. for (const auto& c : checkResp.Checks) {
  68. if (!c.Success) {
  69. errors = 1;
  70. }
  71. if (colorize) {
  72. Cout << NColorizer::LightCyan();
  73. }
  74. Cout << c.CheckName << " ";
  75. if (colorize) {
  76. Cout << (c.Success ? NColorizer::Green() : NColorizer::LightRed());
  77. }
  78. Cout << (c.Success ? "PASSED" : "FAIL");
  79. if (colorize) {
  80. Cout << NColorizer::Old();
  81. }
  82. Cout << "\n";
  83. if (res.Has("verbose")) {
  84. c.Issues.PrintWithProgramTo(Cout, inFileName, queryString, colorize);
  85. }
  86. }
  87. return errors;
  88. }
  89. int main(int argc, char* argv[]) {
  90. try {
  91. return Run(argc, argv);
  92. } catch (const yexception& e) {
  93. Cerr << "Caught exception:" << e.what() << Endl;
  94. return 1;
  95. } catch (...) {
  96. Cerr << CurrentExceptionMessage() << Endl;
  97. return 1;
  98. }
  99. return 0;
  100. }