libexpr: Warn on incorrect string usage
The indentation stripping semantics of strings are fairly bad and have a few gotchas where they behave unintuitively. But the good news is, that these cases are easy to catch and can be avoided. This commit adds a warning in the parser when such strings are detected. Unfortunately Nixpkgs uses this kind of a lot, so we won't be able to actually enable this warning for a while to come. Co-authored-by: Commentator2.0 <lix@crystal-cavern.systems> Change-Id: I3b3b68c2eee4cd70959d3f4ca643cb6caf3a2217
This commit is contained in:
co-authored by
Commentator2.0
parent
4e1c216fd3
commit
f1fbd1d095
@@ -656,9 +656,20 @@ template<> struct BuildAST<grammar::v1::string> : change_head<StringState> {
|
||||
struct IndStringState : SubexprState {
|
||||
using SubexprState::SubexprState;
|
||||
|
||||
// If the first line (after the '') is empty it gets completely removed.
|
||||
// We track that in the grammar because no need to process it any further,
|
||||
// but we still require the information to know the actual number of lines
|
||||
// in the string.
|
||||
bool firstLineStripped = false;
|
||||
std::vector<IndStringLine> lines;
|
||||
};
|
||||
|
||||
template<> struct BuildAST<grammar::v1::ind_string::strip_first_line> {
|
||||
static void apply(const auto & in, IndStringState & s, State & ps) {
|
||||
s.firstLineStripped = true;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct BuildAST<grammar::v1::ind_string::line_start> {
|
||||
static void apply(const auto & in, IndStringState & s, State & ps) {
|
||||
s.lines.push_back(IndStringLine { in.string_view(), ps.at(in) });
|
||||
@@ -717,6 +728,16 @@ template<> struct BuildAST<grammar::v1::ind_string::nul> {
|
||||
|
||||
template<> struct BuildAST<grammar::v1::ind_string> : change_head<IndStringState> {
|
||||
static void success(const auto & in, IndStringState & s, ExprState & e, State & ps) {
|
||||
if (!ps.featureSettings.isEnabled(Dep::BrokenStringIndent)) {
|
||||
/* Check for semantically incorrect code: Single-line string with indentation */
|
||||
if (s.lines.size() == 1 && !s.firstLineStripped && s.lines.front().indentation.size() > 0) {
|
||||
ps.badSingleLineIndStringFound(ps.at(in));
|
||||
}
|
||||
/* Check for semantically incorrect code: Multi-line string with text on the first line */
|
||||
if (s.lines.size() > 1 && !s.firstLineStripped) {
|
||||
ps.badFirstLineIndStringFound(ps.at(in));
|
||||
}
|
||||
}
|
||||
e.pushExpr(noPos, ps.stripIndentation(ps.at(in), std::move(s.lines)));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user