aboutsummaryrefslogtreecommitdiffstats
path: root/yql/essentials/public/fastcheck/linter.cpp
blob: a32814e3ec348e8c411b17ba903d6f106f961a4b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "linter.h"
#include "check_runner.h"

#include <yql/essentials/ast/yql_ast.h>
#include <yql/essentials/ast/yql_expr.h>

#include <util/string/split.h>

#include <functional>

namespace NYql {
namespace NFastCheck {

namespace {

class TCheckRunnerFactory : public ICheckRunnerFactory {
public:
    using TRunnerFactoryFunction = std::function<std::unique_ptr<ICheckRunner>()>;

    TCheckRunnerFactory() {
        Registry_.emplace("lexer", MakeLexerRunner);
        Registry_.emplace("parser", MakeParserRunner);
        Registry_.emplace("format", MakeFormatRunner);
        Registry_.emplace("translator", MakeTranslatorRunner);
        for (const auto& x : Registry_) {
            CheckNames_.emplace(x.first);
        }
    }

    const TSet<TString>& ListChecks() const {
        return CheckNames_;
    }

    std::unique_ptr<ICheckRunner> MakeRunner(const TString& checkName) const final {
        auto ptr = Registry_.FindPtr(checkName);
        if (!ptr) {
            return {};
        }

        return (*ptr)();
    }

private:
    THashMap<TString, TRunnerFactoryFunction> Registry_;
    TSet<TString> CheckNames_;
};

TSet<TString> GetEnabledChecks(const TSet<TString>& allChecks, const TMaybe<TVector<TCheckFilter>>& filters) {
    auto usedFilters = filters.GetOrElse(TVector<TCheckFilter>(1, TCheckFilter{.Include = true, .CheckNameGlob = "*"}));
    TSet<TString> enabledChecks;
    for (const auto& f : usedFilters) {
        if (f.CheckNameGlob == "*") {
            if (f.Include) {
                enabledChecks = allChecks;
            } else {
                enabledChecks.clear();
            }
        } else {
            // TODO full support of glob (* and ?)
            Y_ENSURE(f.CheckNameGlob.find('*') == TString::npos);
            Y_ENSURE(f.CheckNameGlob.find('?') == TString::npos);
            if (f.Include) {
                if (allChecks.contains(f.CheckNameGlob)) {
                    enabledChecks.insert(f.CheckNameGlob);
                }
            } else {
                enabledChecks.erase(f.CheckNameGlob);
            }
        }
    }

    return enabledChecks;
}

TCheckRunnerFactory& GetCheckRunnerFactory() {
    return *Singleton<TCheckRunnerFactory>();
};

}

TVector<TCheckFilter> ParseChecks(const TString& checks) {
    TVector<TCheckFilter> res;
    for (TStringBuf one: StringSplitter(checks).SplitByString(",")) {
        TCheckFilter f;
        TStringBuf afterPrefix = one;
        if (one.AfterPrefix("-", afterPrefix)) {
            f.Include = false;
        }

        f.CheckNameGlob = afterPrefix;
        res.push_back(f);
    }

    return res;
}

TSet<TString> ListChecks(const TMaybe<TVector<TCheckFilter>>& filters) {
    return GetEnabledChecks(GetCheckRunnerFactory().ListChecks(), filters);
}

TChecksResponse RunChecks(const TChecksRequest& request) {
    auto enabledChecks = GetEnabledChecks(GetCheckRunnerFactory().ListChecks(), request.Filters);
    TChecksResponse res;
    for (const auto& c : enabledChecks) {
        auto checkRunner = GetCheckRunnerFactory().MakeRunner(c);
        if (checkRunner) {
            res.Checks.push_back(checkRunner->Run(request));
        }
    }

    return res;
}

}
}