aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2021-05-27 14:32:43 +0200
committerMaximilian Goldstein <max.goldstein@qt.io>2021-06-03 08:54:57 +0200
commit9f389ee75dfcbf8ad56fa4ceac0f28d2a81194e1 (patch)
tree3218652b643cc54a989960c15a59f16ba19f578c /tools
parent609a21eac694f15c74c9f53b49473cd08588ef40 (diff)
qmllint: Add ability to ignore individual warnings
Allows users to ignore individual warnings by adding a "// qmllint disable" comment in the line that triggers the warning. This feature is especially useful for use in pre-commit / CI tests as it allows to add exceptions for individual warnings that cannot be fixed immediately. [ChangeLog][qmllint][New Feature] You can now ignore individual warnings by adding "// qmllint disable" in the line causing it. You may also specify one or more warning type to ignore ("// qmllint disable warningtype1 warningtype2...") which is preferable. This can also be done for entire blocks of code by using "// qmllint disable" in an empty line and ending it with "// qmllint enable" Change-Id: Iea6c29132d6b51ecfb5e5d8a19a43446a7286c24 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tools')
-rw-r--r--tools/qmllint/findwarnings.cpp83
-rw-r--r--tools/qmllint/findwarnings.h8
-rw-r--r--tools/qmllint/main.cpp3
3 files changed, 87 insertions, 7 deletions
diff --git a/tools/qmllint/findwarnings.cpp b/tools/qmllint/findwarnings.cpp
index bc228fa8e1..31ecb9a03a 100644
--- a/tools/qmllint/findwarnings.cpp
+++ b/tools/qmllint/findwarnings.cpp
@@ -421,9 +421,9 @@ bool FindWarningVisitor::visit(QQmlJS::AST::IdentifierExpression *idexp)
return true;
}
-FindWarningVisitor::FindWarningVisitor(
- QQmlJSImporter *importer, QStringList qmltypesFiles, QString code, QString fileName,
- bool silent)
+FindWarningVisitor::FindWarningVisitor(QQmlJSImporter *importer, QStringList qmltypesFiles,
+ QString code, QList<QQmlJS::SourceLocation> comments,
+ QString fileName, bool silent)
: QQmlJSImportVisitor(importer,
implicitImportDirectory(fileName, importer->resourceFileMapper()),
qmltypesFiles, fileName, code, silent),
@@ -457,6 +457,83 @@ FindWarningVisitor::FindWarningVisitor(
}
for (const auto& jsGlobVar: jsGlobVars)
m_currentScope->insertJSIdentifier(jsGlobVar, globalJavaScript);
+
+ parseComments(comments);
+}
+
+void FindWarningVisitor::parseComments(const QList<QQmlJS::SourceLocation> &comments)
+{
+ QHash<int, QSet<QQmlJSLoggerCategory>> disablesPerLine;
+ QHash<int, QSet<QQmlJSLoggerCategory>> enablesPerLine;
+ QHash<int, QSet<QQmlJSLoggerCategory>> oneLineDisablesPerLine;
+
+ const QStringList lines = m_code.split(u'\n');
+
+ for (const auto &loc : comments) {
+ const QString comment = m_code.mid(loc.offset, loc.length);
+ if (!comment.startsWith(u" qmllint ") && !comment.startsWith(u"qmllint "))
+ continue;
+
+ QStringList words = comment.split(u' ');
+ if (words.constFirst().isEmpty())
+ words.removeFirst();
+
+ const QString command = words.at(1);
+
+ QSet<QQmlJSLoggerCategory> categories;
+ for (qsizetype i = 2; i < words.size(); i++) {
+ const QString category = words.at(i);
+ const auto option = m_logger.options().constFind(category);
+ if (option != m_logger.options().constEnd())
+ categories << option->m_category;
+ else
+ m_logger.log(u"qmllint directive on unknown category \"%1\""_qs.arg(category),
+ Log_Syntax, loc);
+ }
+
+ if (categories.isEmpty()) {
+ for (const auto &option : m_logger.options())
+ categories << option.m_category;
+ }
+
+ if (command == u"disable"_qs) {
+ const QString line = lines[loc.startLine - 1];
+ const QString preComment = line.left(line.indexOf(comment) - 2);
+
+ bool lineHasContent = false;
+ for (qsizetype i = 0; i < preComment.size(); i++) {
+ if (!preComment[i].isSpace()) {
+ lineHasContent = true;
+ break;
+ }
+ }
+
+ if (lineHasContent)
+ oneLineDisablesPerLine[loc.startLine] |= categories;
+ else
+ disablesPerLine[loc.startLine] |= categories;
+ } else if (command == u"enable"_qs) {
+ enablesPerLine[loc.startLine + 1] |= categories;
+ } else {
+ m_logger.log(u"Invalid qmllint directive \"%1\" provided"_qs.arg(command), Log_Syntax,
+ loc);
+ }
+ }
+
+ if (disablesPerLine.isEmpty() && oneLineDisablesPerLine.isEmpty())
+ return;
+
+ QSet<QQmlJSLoggerCategory> currentlyDisabled;
+ for (qsizetype i = 1; i <= lines.length(); i++) {
+ currentlyDisabled.unite(disablesPerLine[i]).subtract(enablesPerLine[i]);
+
+ currentlyDisabled.unite(oneLineDisablesPerLine[i]);
+
+ if (!currentlyDisabled.isEmpty())
+ m_logger.ignoreWarnings(i, currentlyDisabled);
+
+ currentlyDisabled.subtract(oneLineDisablesPerLine[i]);
+ }
}
bool FindWarningVisitor::check()
diff --git a/tools/qmllint/findwarnings.h b/tools/qmllint/findwarnings.h
index b6c5f19c76..e2538fe5b8 100644
--- a/tools/qmllint/findwarnings.h
+++ b/tools/qmllint/findwarnings.h
@@ -57,9 +57,9 @@ class FindWarningVisitor : public QQmlJSImportVisitor
{
Q_DISABLE_COPY_MOVE(FindWarningVisitor)
public:
- explicit FindWarningVisitor(
- QQmlJSImporter *importer, QStringList qmltypesFiles, QString code, QString fileName,
- bool silent);
+ explicit FindWarningVisitor(QQmlJSImporter *importer, QStringList qmltypesFiles, QString code,
+ QList<QQmlJS::SourceLocation> comments, QString fileName,
+ bool silent);
~FindWarningVisitor() override = default;
bool check();
@@ -88,6 +88,8 @@ private:
// correctness, the scope that defines the default property acts as a key
QHash<const QQmlJSScope *, bool> m_scopeHasDefaultPropertyAssignment;
+ void parseComments(const QList<QQmlJS::SourceLocation> &comments);
+
void checkInheritanceCycle(QQmlJSScope::ConstPtr scope);
void checkGroupedAndAttachedScopes(QQmlJSScope::ConstPtr scope);
void flushPendingSignalParameters();
diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp
index 7e3962fe0b..7f4c63439f 100644
--- a/tools/qmllint/main.cpp
+++ b/tools/qmllint/main.cpp
@@ -168,7 +168,8 @@ static bool lint_file(const QString &filename, const bool silent, QJsonArray *js
importer.setResourceFileMapper(mapper);
- FindWarningVisitor v { &importer, qmltypesFiles, code, filename, silent || json };
+ FindWarningVisitor v { &importer, qmltypesFiles, code,
+ engine.comments(), filename, silent || json };
for (auto it = options.cbegin(); it != options.cend(); ++it) {
v.logger().setCategoryDisabled(it.value().m_category, it.value().m_disabled);