mirror of
https://github.com/dlang-community/D-Scanner.git
synced 2025-04-26 13:20:07 +03:00
support // @nolint(...) comments as well
This commit is contained in:
parent
8612841365
commit
640c757299
4 changed files with 123 additions and 41 deletions
|
@ -378,6 +378,29 @@ struct BaseAnalyzerArguments
|
||||||
const Scope* sc;
|
const Scope* sc;
|
||||||
bool skipTests = false;
|
bool skipTests = false;
|
||||||
|
|
||||||
|
// auto-generated members:
|
||||||
|
size_t[typeof(Token.line)] lineEndTokenIndices;
|
||||||
|
size_t[typeof(Token.line)] lineStartTokenIndices;
|
||||||
|
|
||||||
|
void preprocess()
|
||||||
|
{
|
||||||
|
if (!tokens.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
typeof(Token.line) line = -1;
|
||||||
|
foreach (i, t; tokens)
|
||||||
|
{
|
||||||
|
if (t.line != line)
|
||||||
|
{
|
||||||
|
lineStartTokenIndices[t.line] = i;
|
||||||
|
if (i != 0)
|
||||||
|
lineEndTokenIndices[tokens[i - 1].line] = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lineEndTokenIndices[tokens[$ - 1].line] = tokens.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
BaseAnalyzerArguments setSkipTests(bool v)
|
BaseAnalyzerArguments setSkipTests(bool v)
|
||||||
{
|
{
|
||||||
auto ret = this;
|
auto ret = this;
|
||||||
|
@ -406,6 +429,8 @@ public:
|
||||||
this.tokens = args.tokens;
|
this.tokens = args.tokens;
|
||||||
this.fileName = args.fileName;
|
this.fileName = args.fileName;
|
||||||
this.skipTests = args.skipTests;
|
this.skipTests = args.skipTests;
|
||||||
|
this.lineEndTokenIndices = args.lineEndTokenIndices;
|
||||||
|
this.lineStartTokenIndices = args.lineStartTokenIndices;
|
||||||
_messages = new MessageSet;
|
_messages = new MessageSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,6 +506,8 @@ protected:
|
||||||
bool inAggregate;
|
bool inAggregate;
|
||||||
bool skipTests;
|
bool skipTests;
|
||||||
const(Token)[] tokens;
|
const(Token)[] tokens;
|
||||||
|
size_t[typeof(Token.line)] lineEndTokenIndices;
|
||||||
|
size_t[typeof(Token.line)] lineStartTokenIndices;
|
||||||
NoLint noLint;
|
NoLint noLint;
|
||||||
|
|
||||||
template visitTemplate(T)
|
template visitTemplate(T)
|
||||||
|
@ -496,42 +523,42 @@ protected:
|
||||||
deprecated("Use the overload taking start and end locations or a Node instead")
|
deprecated("Use the overload taking start and end locations or a Node instead")
|
||||||
void addErrorMessage(size_t line, size_t column, string key, string message)
|
void addErrorMessage(size_t line, size_t column, string key, string message)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, [findToken(line, column)]))
|
||||||
return;
|
return;
|
||||||
_messages.insert(Message(fileName, line, column, key, message, getName()));
|
_messages.insert(Message(fileName, line, column, key, message, getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addErrorMessage(const BaseNode node, string key, string message, AutoFix[] autofixes = null)
|
void addErrorMessage(const BaseNode node, string key, string message, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, node.tokens))
|
||||||
return;
|
return;
|
||||||
addErrorMessage(Message.Diagnostic.from(fileName, node, message), key, autofixes);
|
addErrorMessage(Message.Diagnostic.from(fileName, node, message), key, autofixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addErrorMessage(const Token token, string key, string message, AutoFix[] autofixes = null)
|
void addErrorMessage(const Token token, string key, string message, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, [token]))
|
||||||
return;
|
return;
|
||||||
addErrorMessage(Message.Diagnostic.from(fileName, token, message), key, autofixes);
|
addErrorMessage(Message.Diagnostic.from(fileName, token, message), key, autofixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addErrorMessage(const Token[] tokens, string key, string message, AutoFix[] autofixes = null)
|
void addErrorMessage(const Token[] tokens, string key, string message, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, tokens))
|
||||||
return;
|
return;
|
||||||
addErrorMessage(Message.Diagnostic.from(fileName, tokens, message), key, autofixes);
|
addErrorMessage(Message.Diagnostic.from(fileName, tokens, message), key, autofixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addErrorMessage(size_t[2] index, size_t line, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
|
void addErrorMessage(size_t[2] index, size_t line, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, [findToken(index[0]), findToken(index[1])]))
|
||||||
return;
|
return;
|
||||||
addErrorMessage(index, [line, line], columns, key, message, autofixes);
|
addErrorMessage(index, [line, line], columns, key, message, autofixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addErrorMessage(size_t[2] index, size_t[2] lines, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
|
void addErrorMessage(size_t[2] index, size_t[2] lines, size_t[2] columns, string key, string message, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, [findToken(index[0]), findToken(index[1])]))
|
||||||
return;
|
return;
|
||||||
auto d = Message.Diagnostic.from(fileName, index, lines, columns, message);
|
auto d = Message.Diagnostic.from(fileName, index, lines, columns, message);
|
||||||
_messages.insert(Message(d, key, getName(), autofixes));
|
_messages.insert(Message(d, key, getName(), autofixes));
|
||||||
|
@ -539,14 +566,14 @@ protected:
|
||||||
|
|
||||||
void addErrorMessage(Message.Diagnostic diagnostic, string key, AutoFix[] autofixes = null)
|
void addErrorMessage(Message.Diagnostic diagnostic, string key, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, null)) // TODO
|
||||||
return;
|
return;
|
||||||
_messages.insert(Message(diagnostic, key, getName(), autofixes));
|
_messages.insert(Message(diagnostic, key, getName(), autofixes));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addErrorMessage(Message.Diagnostic diagnostic, Message.Diagnostic[] supplemental, string key, AutoFix[] autofixes = null)
|
void addErrorMessage(Message.Diagnostic diagnostic, Message.Diagnostic[] supplemental, string key, AutoFix[] autofixes = null)
|
||||||
{
|
{
|
||||||
if (noLint.containsCheck(key))
|
if (checkNoLint(key, null)) // TODO
|
||||||
return;
|
return;
|
||||||
_messages.insert(Message(diagnostic, supplemental, key, getName(), autofixes));
|
_messages.insert(Message(diagnostic, supplemental, key, getName(), autofixes));
|
||||||
}
|
}
|
||||||
|
@ -559,6 +586,59 @@ protected:
|
||||||
const(Scope)* sc;
|
const(Scope)* sc;
|
||||||
|
|
||||||
MessageSet _messages;
|
MessageSet _messages;
|
||||||
|
|
||||||
|
private const Token findToken(typeof(Token.index) index)
|
||||||
|
{
|
||||||
|
return Token.init; // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
private const Token findToken(typeof(Token.line) line, typeof(Token.column) column)
|
||||||
|
{
|
||||||
|
return Token.init; // todo
|
||||||
|
}
|
||||||
|
|
||||||
|
private const Token getLastLineToken(typeof(Token.line) line)
|
||||||
|
{
|
||||||
|
if (auto pi = line in lineEndTokenIndices)
|
||||||
|
return tokens[*pi];
|
||||||
|
return Token.init;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool checkNoLint(string key, const(Token)[] tokens)
|
||||||
|
{
|
||||||
|
if (noLint.containsCheck(key))
|
||||||
|
return true;
|
||||||
|
if (!tokens.length)
|
||||||
|
return false;
|
||||||
|
auto first = tokens[0].leadingTrivia;
|
||||||
|
auto last = tokens[$ - 1].trailingTrivia;
|
||||||
|
auto line = getLastLineToken(tokens[$ - 1].line).trailingTrivia;
|
||||||
|
|
||||||
|
bool checkComments(typeof(Token.leadingTrivia) tokens)
|
||||||
|
{
|
||||||
|
foreach (token; tokens)
|
||||||
|
{
|
||||||
|
if (token.type == tok!"comment"
|
||||||
|
&& token.text.startsWith(
|
||||||
|
"// @nolint",
|
||||||
|
"// @suppress")) // in use in some projects since this was introduced in code-d
|
||||||
|
{
|
||||||
|
auto nolintUDA = token.text[3 .. $];
|
||||||
|
auto n = NoLintFactory.fromString(nolintUDA);
|
||||||
|
if (!n.isNull && n.get.containsCheck(key))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkComments(getLastLineToken(tokens[$ - 1].line).trailingTrivia)
|
||||||
|
|| checkComments(tokens[$ - 1].trailingTrivia)
|
||||||
|
|| checkComments(tokens[0].leadingTrivia))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the token with the given type, otherwise returns the whole range or a user-specified fallback, if set.
|
/// Find the token with the given type, otherwise returns the whole range or a user-specified fallback, if set.
|
||||||
|
|
|
@ -116,6 +116,38 @@ struct NoLintFactory
|
||||||
return noLint.nullable;
|
return noLint.nullable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform a string with form "nolint(abc, efg)"
|
||||||
|
// into a NoLint struct
|
||||||
|
static Nullable!NoLint fromString(in string str)
|
||||||
|
{
|
||||||
|
static immutable re = regex(`[\w-_.]+`, "g");
|
||||||
|
auto matches = matchAll(str, re);
|
||||||
|
|
||||||
|
if (!matches)
|
||||||
|
return nullNoLint;
|
||||||
|
|
||||||
|
const udaName = matches.hit;
|
||||||
|
if (udaName != "nolint")
|
||||||
|
return nullNoLint;
|
||||||
|
|
||||||
|
matches.popFront;
|
||||||
|
|
||||||
|
NoLint noLint;
|
||||||
|
|
||||||
|
while (matches)
|
||||||
|
{
|
||||||
|
noLint.pushCheck(matches.hit);
|
||||||
|
matches.popFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!noLint.getDisabledChecks.length)
|
||||||
|
return nullNoLint;
|
||||||
|
|
||||||
|
return noLint.nullable;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nullNoLint = Nullable!NoLint.init;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Nullable!NoLint fromAttribute(const(Attribute) attribute)
|
static Nullable!NoLint fromAttribute(const(Attribute) attribute)
|
||||||
{
|
{
|
||||||
|
@ -205,38 +237,6 @@ private:
|
||||||
return noLint.nullable;
|
return noLint.nullable;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform a string with form "nolint(abc, efg)"
|
|
||||||
// into a NoLint struct
|
|
||||||
static Nullable!NoLint fromString(in string str)
|
|
||||||
{
|
|
||||||
static immutable re = regex(`[\w-_.]+`, "g");
|
|
||||||
auto matches = matchAll(str, re);
|
|
||||||
|
|
||||||
if (!matches)
|
|
||||||
return nullNoLint;
|
|
||||||
|
|
||||||
const udaName = matches.hit;
|
|
||||||
if (udaName != "nolint")
|
|
||||||
return nullNoLint;
|
|
||||||
|
|
||||||
matches.popFront;
|
|
||||||
|
|
||||||
NoLint noLint;
|
|
||||||
|
|
||||||
while (matches)
|
|
||||||
{
|
|
||||||
noLint.pushCheck(matches.hit);
|
|
||||||
matches.popFront;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!noLint.getDisabledChecks.length)
|
|
||||||
return nullNoLint;
|
|
||||||
|
|
||||||
return noLint.nullable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static nullNoLint = Nullable!NoLint.init;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unittest
|
unittest
|
||||||
|
|
|
@ -754,6 +754,7 @@ private BaseAnalyzer[] getAnalyzersForModuleAndConfig(string fileName,
|
||||||
tokens,
|
tokens,
|
||||||
moduleScope
|
moduleScope
|
||||||
);
|
);
|
||||||
|
args.preprocess();
|
||||||
|
|
||||||
if (moduleName.shouldRun!AsmStyleCheck(analysisConfig))
|
if (moduleName.shouldRun!AsmStyleCheck(analysisConfig))
|
||||||
checks ~= new AsmStyleCheck(args.setSkipTests(
|
checks ~= new AsmStyleCheck(args.setSkipTests(
|
||||||
|
|
|
@ -369,7 +369,8 @@ public:
|
||||||
assertAnalyzerWarnings(q{
|
assertAnalyzerWarnings(q{
|
||||||
@("nolint(dscanner.useless-initializer)")
|
@("nolint(dscanner.useless-initializer)")
|
||||||
int a = 0;
|
int a = 0;
|
||||||
int a = 0; /+
|
int a = 0; // @nolint(dscanner.useless-initializer)
|
||||||
|
int a = 0; /+
|
||||||
^ [warn]: X +/
|
^ [warn]: X +/
|
||||||
|
|
||||||
@("nolint(dscanner.useless-initializer)")
|
@("nolint(dscanner.useless-initializer)")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue