diff options
author | Maximilian Goldstein <max.goldstein@qt.io> | 2021-05-27 14:32:43 +0200 |
---|---|---|
committer | Maximilian Goldstein <max.goldstein@qt.io> | 2021-06-03 08:54:57 +0200 |
commit | 9f389ee75dfcbf8ad56fa4ceac0f28d2a81194e1 (patch) | |
tree | 3218652b643cc54a989960c15a59f16ba19f578c /tools/qmllint | |
parent | 609a21eac694f15c74c9f53b49473cd08588ef40 (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/qmllint')
-rw-r--r-- | tools/qmllint/findwarnings.cpp | 83 | ||||
-rw-r--r-- | tools/qmllint/findwarnings.h | 8 | ||||
-rw-r--r-- | tools/qmllint/main.cpp | 3 |
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); |