-
Notifications
You must be signed in to change notification settings - Fork 217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
line length rule: add a parameter to check comments #972
base: master
Are you sure you want to change the base?
Changes from all commits
360d2b8
793a9be
cc4cfdc
3bd46d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -70,16 +70,21 @@ const LintRuleDescriptor& LineLengthRule::GetDescriptor() { | |||||
.desc = | ||||||
"Checks that all lines do not exceed the maximum allowed " | ||||||
"length. ", | ||||||
.param = {{"length", absl::StrCat(kDefaultLineLength), | ||||||
"Desired line length"}}, | ||||||
.param = | ||||||
{ | ||||||
{"length", absl::StrCat(kDefaultLineLength), | ||||||
"Desired line length"}, | ||||||
{"check_comments", "true", "Check comments."}, | ||||||
}, | ||||||
}; | ||||||
return d; | ||||||
} | ||||||
|
||||||
// Returns true if line is an exceptional case that should allow excessive | ||||||
// length. | ||||||
static bool AllowLongLineException(TokenSequence::const_iterator token_begin, | ||||||
TokenSequence::const_iterator token_end) { | ||||||
bool LineLengthRule::AllowLongLineException( | ||||||
TokenSequence::const_iterator token_begin, | ||||||
TokenSequence::const_iterator token_end) { | ||||||
// There may be no tokens on this line if the lexer skipped them. | ||||||
// TODO(b/134180314): Preserve all text in lexer. | ||||||
if (token_begin == token_end) return true; // Conservatively ignore. | ||||||
|
@@ -111,7 +116,7 @@ static bool AllowLongLineException(TokenSequence::const_iterator token_begin, | |||||
// remain as atomic tokens, so fixing comment indentation may cause | ||||||
// line-length violations. The compromise for now is to forgive | ||||||
// this case (no matter what the length). | ||||||
return true; | ||||||
return !check_comments_; | ||||||
|
||||||
// Once comment-reflowing is implemented, re-enable the following: | ||||||
// If comment consist of more than one token, it should be split. | ||||||
|
@@ -122,6 +127,8 @@ static bool AllowLongLineException(TokenSequence::const_iterator token_begin, | |||||
// TODO(fangism): examine "long string literals" | ||||||
// TODO(fangism): case TK_COMMENT_BLOCK: | ||||||
// Multi-line comments need deeper inspection. | ||||||
case TK_COMMENT_BLOCK: | ||||||
return !check_comments_; | ||||||
default: | ||||||
return true; | ||||||
} | ||||||
|
@@ -165,15 +172,75 @@ static bool AllowLongLineException(TokenSequence::const_iterator token_begin, | |||||
return false; | ||||||
} | ||||||
|
||||||
static verible::TokenRange StripNewlineTokens(verible::TokenRange token_range) { | ||||||
// truncate newline tokens and return a new, possibly shrinked range | ||||||
auto reversed = reversed_view(token_range); | ||||||
auto last_non_newline = | ||||||
std::find_if(reversed.begin(), reversed.end(), [](const TokenInfo& t) { | ||||||
return t.token_enum() != TK_NEWLINE; | ||||||
}).base(); | ||||||
|
||||||
return make_range(token_range.begin(), last_non_newline); | ||||||
} | ||||||
|
||||||
static verible::TokenRange SeekLastNonNewlineToken( | ||||||
verible::TokenRange token_range, TokenSequence::const_iterator text_begin) { | ||||||
// Extend token_range backwards to find non-newline tokens. | ||||||
// text_begin is the frontal limiter that shall not be overrun. | ||||||
// If such a token isn't found, the input range is returned | ||||||
auto found_it = std::find_if( | ||||||
std::reverse_iterator<TokenSequence::const_iterator>(token_range.begin()), | ||||||
std::reverse_iterator<TokenSequence::const_iterator>(text_begin), | ||||||
[](const TokenInfo& t) { return t.token_enum() != TK_NEWLINE; }); | ||||||
|
||||||
if (found_it != | ||||||
std::reverse_iterator<TokenSequence::const_iterator>(text_begin)) { | ||||||
// Use the last non-newline token as a new beginning. | ||||||
auto new_begin = found_it.base() - 1; | ||||||
// We move the front backwards, so now it's possible that there are | ||||||
// unneeded tokens in the back. | ||||||
token_range = make_range(new_begin, token_range.end()); | ||||||
} | ||||||
return token_range; | ||||||
} | ||||||
|
||||||
verible::TokenRange& CheckTokenRangeForTrailingNewlines( | ||||||
verible::TokenRange* orig_range, | ||||||
TokenSequence::const_iterator text_structure) { | ||||||
// Recall that token_range is *unfiltered* and may contain non-essential | ||||||
// whitespace 'tokens'. | ||||||
// This shrinks the range if there are leading newline tokens | ||||||
*orig_range = StripNewlineTokens(*orig_range); | ||||||
if (orig_range->begin() == orig_range->end()) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Maybe something like this? Then just return There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does not implement enough methods to call either |
||||||
// No tokens, even though the line exceeds the limit. | ||||||
// The range doesn't contain tokens that start in the preceeding lines | ||||||
// and continue in this line. | ||||||
// A token that spans accross multiple lines is in this line | ||||||
// and exceeds the limit. | ||||||
// Find the last non-newline token in the preceeding lines. | ||||||
*orig_range = SeekLastNonNewlineToken(*orig_range, text_structure); | ||||||
// Yet again after moving the `begin` backwards, `end` may point | ||||||
// behind newline tokens, depending on how many lines backwards | ||||||
// the range was extended. | ||||||
// Also, AllowLongLineException function assumes the length of the range | ||||||
// to be 1 if there is 1 meaningful token. | ||||||
*orig_range = StripNewlineTokens(*orig_range); | ||||||
} | ||||||
return *orig_range; | ||||||
} | ||||||
|
||||||
void LineLengthRule::Lint(const TextStructureView& text_structure, | ||||||
absl::string_view) { | ||||||
size_t lineno = 0; | ||||||
const auto text_begin = text_structure.TokenRangeOnLine(lineno).begin(); | ||||||
|
||||||
for (const auto& line : text_structure.Lines()) { | ||||||
const int observed_line_length = verible::utf8_len(line); | ||||||
if (observed_line_length > line_length_limit_) { | ||||||
const auto token_range = text_structure.TokenRangeOnLine(lineno); | ||||||
// Recall that token_range is *unfiltered* and may contain non-essential | ||||||
// whitespace 'tokens'. | ||||||
// range of tokens that *begin* in this line. | ||||||
auto token_range = text_structure.TokenRangeOnLine(lineno); | ||||||
token_range = | ||||||
CheckTokenRangeForTrailingNewlines(&token_range, text_begin); | ||||||
if (!AllowLongLineException(token_range.begin(), token_range.end())) { | ||||||
// Fake a token that marks the offending range of text. | ||||||
TokenInfo token(TK_OTHER, line.substr(line_length_limit_)); | ||||||
|
@@ -187,10 +254,12 @@ void LineLengthRule::Lint(const TextStructureView& text_structure, | |||||
} | ||||||
|
||||||
absl::Status LineLengthRule::Configure(absl::string_view configuration) { | ||||||
using verible::config::SetBool; | ||||||
using verible::config::SetInt; | ||||||
return verible::ParseNameValues( | ||||||
configuration, {{"length", SetInt(&line_length_limit_, kMinimumLineLength, | ||||||
kMaximumLineLength)}}); | ||||||
kMaximumLineLength)}, | ||||||
{"check_comments", SetBool(&check_comments_)}}); | ||||||
} | ||||||
|
||||||
LintRuleStatus LineLengthRule::Report() const { | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need explicit params for the
reverse_iterator
s here? (possibly usecbegin()
if you're running into some fun template errors)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cbegin
is not implemented and not having parameters has caused problems (and warnings in a compilation with-Werror
set) with parameter deduction in Clang: