diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2c8f143960..03bac27982 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -73,7 +73,6 @@ add_subdirectory(plugins) if(QT_FEATURE_qml_devtools) add_subdirectory(qmlcompiler) - add_subdirectory(qmllint) add_subdirectory(qmldom) # Build qmlcachegen now, so that we can use it in src/imports. diff --git a/src/qmlcompiler/CMakeLists.txt b/src/qmlcompiler/CMakeLists.txt index 110c625b00..25a0d130a6 100644 --- a/src/qmlcompiler/CMakeLists.txt +++ b/src/qmlcompiler/CMakeLists.txt @@ -31,6 +31,8 @@ qt_internal_add_module(QmlCompilerPrivate qqmljstyperesolver.cpp qqmljstyperesolver_p.h qresourcerelocater.cpp qresourcerelocater_p.h qqmljsutils_p.h qqmljsutils.cpp + qqmljslinter_p.h qqmljslinter.cpp + qqmljslintercodegen_p.h qqmljslintercodegen.cpp PUBLIC_LIBRARIES Qt::CorePrivate Qt::QmlPrivate diff --git a/src/qmllint/qqmllinter.cpp b/src/qmlcompiler/qqmljslinter.cpp similarity index 83% rename from src/qmllint/qqmllinter.cpp rename to src/qmlcompiler/qqmljslinter.cpp index d4089ccc6f..c50740750e 100644 --- a/src/qmllint/qqmllinter.cpp +++ b/src/qmlcompiler/qqmljslinter.cpp @@ -26,10 +26,9 @@ ** ****************************************************************************/ -#include "qqmllinter_p.h" +#include "qqmljslinter_p.h" -#include "codegen_p.h" -#include "codegenwarninginterface_p.h" +#include "qqmljslintercodegen_p.h" #include #include @@ -47,12 +46,35 @@ QT_BEGIN_NAMESPACE -QQmlLinter::QQmlLinter(const QStringList &importPaths, bool useAbsolutePath) +class CodegenWarningInterface final : public QV4::Compiler::CodegenWarningInterface +{ +public: + CodegenWarningInterface(QQmlJSLogger *logger) : m_logger(logger) { } + + void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName, + QQmlJS::SourceLocation declarationLocation, + QQmlJS::SourceLocation accessLocation) override + { + Q_UNUSED(fileName) + m_logger->logWarning( + u"Variable \"%1\" is used here before its declaration. The declaration is at %2:%3."_qs + .arg(name) + .arg(declarationLocation.startLine) + .arg(declarationLocation.startColumn), + Log_Type, accessLocation); + } + +private: + QQmlJSLogger *m_logger; +}; + +QQmlJSLinter::QQmlJSLinter(const QStringList &importPaths, bool useAbsolutePath) : m_useAbsolutePath(useAbsolutePath), m_importer(importPaths, nullptr) { } -void QQmlLinter::parseComments(QQmlJSLogger *logger, const QList &comments) +void QQmlJSLinter::parseComments(QQmlJSLogger *logger, + const QList &comments) { QHash> disablesPerLine; QHash> enablesPerLine; @@ -128,10 +150,10 @@ void QQmlLinter::parseComments(QQmlJSLogger *logger, const QList &options) +bool QQmlJSLinter::lintFile(const QString &filename, const QString *fileContents, const bool silent, + QJsonArray *json, const QStringList &qmlImportPaths, + const QStringList &qmldirFiles, const QStringList &resourceFiles, + const QMap &options) { // Make sure that we don't expose an old logger if we return before a new one is created. m_logger.reset(); @@ -213,11 +235,10 @@ bool QQmlLinter::lintFile(const QString &filename, const QString *fileContents, QFile file(filename); if (!file.open(QFile::ReadOnly)) { if (json) { - addJsonWarning(QQmlJS::DiagnosticMessage { - QStringLiteral("Failed to open file %1: %2").arg(filename, file.errorString()), - QtCriticalMsg, - QQmlJS::SourceLocation() - }); + addJsonWarning( + QQmlJS::DiagnosticMessage { QStringLiteral("Failed to open file %1: %2") + .arg(filename, file.errorString()), + QtCriticalMsg, QQmlJS::SourceLocation() }); success = false; } else if (!silent) { qWarning() << "Failed to open file" << filename << file.error(); @@ -299,11 +320,11 @@ bool QQmlLinter::lintFile(const QString &filename, const QString *fileContents, QQmlJSTypeResolver typeResolver(&m_importer); - // Type resolving is using document parent mode here so that it produces fewer false positives - // on the "parent" property of QQuickItem. It does produce a few false negatives this way - // because items can be reparented. Furthermore, even if items are not reparented, the document - // parent may indeed not be their visual parent. See QTBUG-95530. Eventually, we'll need - // cleverer logic to deal with this. + // Type resolving is using document parent mode here so that it produces fewer false + // positives on the "parent" property of QQuickItem. It does produce a few false + // negatives this way because items can be reparented. Furthermore, even if items are + // not reparented, the document parent may indeed not be their visual parent. See + // QTBUG-95530. Eventually, we'll need cleverer logic to deal with this. typeResolver.setParentMode(QQmlJSTypeResolver::UseDocumentParent); typeResolver.init(&v, parser.rootNode()); @@ -319,11 +340,11 @@ bool QQmlLinter::lintFile(const QString &filename, const QString *fileContents, const QStringList resourcePaths = mapper ? mapper->resourcePaths(QQmlJSResourceFileMapper::localFileFilter(filename)) : QStringList(); - const QString resolvedPath = (resourcePaths.size() == 1) - ? u':' + resourcePaths.first() - : filename; + const QString resolvedPath = + (resourcePaths.size() == 1) ? u':' + resourcePaths.first() : filename; - Codegen codegen { &m_importer, resolvedPath, qmldirFiles, m_logger.get(), &typeInfo }; + QQmlJSLinterCodegen codegen { &m_importer, resolvedPath, qmldirFiles, m_logger.get(), + &typeInfo }; codegen.setTypeResolver(std::move(typeResolver)); QQmlJSSaveFunction saveFunction = [](const QV4::CompiledData::SaveableUnitPointer &, const QQmlJSAotFunctionMap &, diff --git a/src/qmllint/qqmllinter_p.h b/src/qmlcompiler/qqmljslinter_p.h similarity index 93% rename from src/qmllint/qqmllinter_p.h rename to src/qmlcompiler/qqmljslinter_p.h index 6d0ea35054..6dccfad5eb 100644 --- a/src/qmllint/qqmllinter_p.h +++ b/src/qmlcompiler/qqmljslinter_p.h @@ -26,8 +26,8 @@ ** ****************************************************************************/ -#ifndef QMLLINT_P_H -#define QMLLINT_P_H +#ifndef QMLJSLINTER_P_H +#define QMLJSLINTER_P_H // // W A R N I N G @@ -51,10 +51,10 @@ QT_BEGIN_NAMESPACE -class QQmlLinter +class QQmlJSLinter { public: - QQmlLinter(const QStringList &importPaths, bool useAbsolutePath = false); + QQmlJSLinter(const QStringList &importPaths, bool useAbsolutePath = false); bool lintFile(const QString &filename, const QString *fileContents, const bool silent, QJsonArray *json, const QStringList &qmlImportPaths, @@ -73,4 +73,4 @@ private: QT_END_NAMESPACE -#endif // QMLLINT_P_H +#endif // QMLJSLINTER_P_H diff --git a/src/qmllint/codegen.cpp b/src/qmlcompiler/qqmljslintercodegen.cpp similarity index 77% rename from src/qmllint/codegen.cpp rename to src/qmlcompiler/qqmljslintercodegen.cpp index ecc991b6ef..db9b94a253 100644 --- a/src/qmllint/codegen.cpp +++ b/src/qmlcompiler/qqmljslintercodegen.cpp @@ -26,7 +26,7 @@ ** ****************************************************************************/ -#include "codegen_p.h" +#include "qqmljslintercodegen_p.h" #include #include @@ -38,14 +38,15 @@ QT_BEGIN_NAMESPACE -Codegen::Codegen(QQmlJSImporter *importer, const QString &fileName, - const QStringList &qmldirFiles, QQmlJSLogger *logger, QQmlJSTypeInfo *typeInfo) - : QQmlJSAotCompiler(importer, fileName, qmldirFiles, logger) - , m_typeInfo(typeInfo) +QQmlJSLinterCodegen::QQmlJSLinterCodegen(QQmlJSImporter *importer, const QString &fileName, + const QStringList &qmldirFiles, QQmlJSLogger *logger, + QQmlJSTypeInfo *typeInfo) + : QQmlJSAotCompiler(importer, fileName, qmldirFiles, logger), m_typeInfo(typeInfo) { } -void Codegen::setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document *document) +void QQmlJSLinterCodegen::setDocument(const QmlIR::JSCodeGen *codegen, + const QmlIR::Document *document) { Q_UNUSED(codegen); m_document = document; @@ -54,14 +55,15 @@ void Codegen::setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document } std::variant -Codegen::compileBinding(const QV4::Compiler::Context *context, const QmlIR::Binding &irBinding) +QQmlJSLinterCodegen::compileBinding(const QV4::Compiler::Context *context, + const QmlIR::Binding &irBinding) { QQmlJSFunctionInitializer initializer(&m_typeResolver, m_currentObject, m_currentScope); QQmlJS::DiagnosticMessage initializationError; const QString name = m_document->stringAt(irBinding.propertyNameIndex); - QQmlJSCompilePass::Function function = initializer.run( - context, name, irBinding, &initializationError); + QQmlJSCompilePass::Function function = + initializer.run(context, name, irBinding, &initializationError); if (initializationError.isValid()) diagnose(initializationError.message, initializationError.type, initializationError.loc); @@ -80,13 +82,14 @@ Codegen::compileBinding(const QV4::Compiler::Context *context, const QmlIR::Bind } std::variant -Codegen::compileFunction(const QV4::Compiler::Context *context, const QmlIR::Function &irFunction) +QQmlJSLinterCodegen::compileFunction(const QV4::Compiler::Context *context, + const QmlIR::Function &irFunction) { QQmlJS::DiagnosticMessage initializationError; QQmlJSFunctionInitializer initializer(&m_typeResolver, m_currentObject, m_currentScope); const QString name = m_document->stringAt(irFunction.nameIndex); - QQmlJSCompilePass::Function function = initializer.run( - context, name, irFunction, &initializationError); + QQmlJSCompilePass::Function function = + initializer.run(context, name, irFunction, &initializationError); if (initializationError.isValid()) diagnose(initializationError.message, initializationError.type, initializationError.loc); @@ -99,10 +102,9 @@ Codegen::compileFunction(const QV4::Compiler::Context *context, const QmlIR::Fun return QQmlJSAotFunction {}; } -bool Codegen::analyzeFunction( - const QV4::Compiler::Context *context, - QQmlJSCompilePass::Function *function, - QQmlJS::DiagnosticMessage *error) +bool QQmlJSLinterCodegen::analyzeFunction(const QV4::Compiler::Context *context, + QQmlJSCompilePass::Function *function, + QQmlJS::DiagnosticMessage *error) { QQmlJSTypePropagator propagator(m_unitGenerator, &m_typeResolver, m_logger, m_typeInfo); QQmlJSCompilePass::InstructionAnnotations annotations = propagator.run(function, error); diff --git a/src/qmllint/codegen_p.h b/src/qmlcompiler/qqmljslintercodegen_p.h similarity index 86% rename from src/qmllint/codegen_p.h rename to src/qmlcompiler/qqmljslintercodegen_p.h index ddf7cc3c4a..3423605334 100644 --- a/src/qmllint/codegen_p.h +++ b/src/qmlcompiler/qqmljslintercodegen_p.h @@ -26,8 +26,8 @@ ** ****************************************************************************/ -#ifndef CODEGEN_P_H -#define CODEGEN_P_H +#ifndef QQMLJSLINTERCODEGEN_P_H +#define QQMLJSLINTERCODEGEN_P_H // // W A R N I N G @@ -56,11 +56,12 @@ QT_BEGIN_NAMESPACE -class Codegen : public QQmlJSAotCompiler +class QQmlJSLinterCodegen : public QQmlJSAotCompiler { public: - Codegen(QQmlJSImporter *importer, const QString &fileName, const QStringList &qmldirFiles, - QQmlJSLogger *logger, QQmlJSTypeInfo *typeInfo); + QQmlJSLinterCodegen(QQmlJSImporter *importer, const QString &fileName, + const QStringList &qmldirFiles, QQmlJSLogger *logger, + QQmlJSTypeInfo *typeInfo); void setDocument(const QmlIR::JSCodeGen *codegen, const QmlIR::Document *document) override; std::variant @@ -78,8 +79,7 @@ private: QQmlJSTypeInfo *m_typeInfo; bool analyzeFunction(const QV4::Compiler::Context *context, - QQmlJSCompilePass::Function *function, - QQmlJS::DiagnosticMessage *error); + QQmlJSCompilePass::Function *function, QQmlJS::DiagnosticMessage *error); }; QT_END_NAMESPACE diff --git a/src/qmllint/CMakeLists.txt b/src/qmllint/CMakeLists.txt deleted file mode 100644 index d73e132de1..0000000000 --- a/src/qmllint/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -qt_internal_add_module(QmlLintPrivate - STATIC - INTERNAL_MODULE - SOURCES - codegen_p.h codegen.cpp - codegenwarninginterface_p.h codegenwarninginterface.cpp - qqmllinter_p.h qqmllinter.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::QmlPrivate - Qt::QmlCompilerPrivate -) diff --git a/src/qmllint/codegenwarninginterface.cpp b/src/qmllint/codegenwarninginterface.cpp deleted file mode 100644 index c06571d1bf..0000000000 --- a/src/qmllint/codegenwarninginterface.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "codegenwarninginterface_p.h" - -#include - -QT_BEGIN_NAMESPACE - -void CodegenWarningInterface::reportVarUsedBeforeDeclaration( - const QString &name, const QString &fileName, QQmlJS::SourceLocation declarationLocation, - QQmlJS::SourceLocation accessLocation) -{ - Q_UNUSED(fileName) - m_logger->logWarning( - u"Variable \"%1\" is used here before its declaration. The declaration is at %2:%3."_qs - .arg(name) - .arg(declarationLocation.startLine) - .arg(declarationLocation.startColumn), - Log_Type, accessLocation); -} - -QT_END_NAMESPACE diff --git a/src/qmllint/codegenwarninginterface_p.h b/src/qmllint/codegenwarninginterface_p.h deleted file mode 100644 index fb9c5ca862..0000000000 --- a/src/qmllint/codegenwarninginterface_p.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the tools applications of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CODEGENWARNINGINTERFACE_P_H -#define CODEGENWARNINGINTERFACE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. - -#include - -QT_BEGIN_NAMESPACE - -class QQmlJSLogger; -class CodegenWarningInterface final : public QV4::Compiler::CodegenWarningInterface -{ -public: - CodegenWarningInterface(QQmlJSLogger *logger) : m_logger(logger) { } - - void reportVarUsedBeforeDeclaration(const QString &name, const QString &fileName, - QQmlJS::SourceLocation declarationLocation, - QQmlJS::SourceLocation accessLocation) override; - -private: - QQmlJSLogger *m_logger; -}; - -QT_END_NAMESPACE - -#endif // CODEGENWARNINGINTERFACE_P_H diff --git a/tests/auto/qml/qmllint/CMakeLists.txt b/tests/auto/qml/qmllint/CMakeLists.txt index d7f1c6e833..61cc2d4281 100644 --- a/tests/auto/qml/qmllint/CMakeLists.txt +++ b/tests/auto/qml/qmllint/CMakeLists.txt @@ -16,7 +16,7 @@ qt_internal_add_test(tst_qmllint PUBLIC_LIBRARIES Qt::Gui Qt::QuickTestUtilsPrivate - Qt::QmlLintPrivate + Qt::QmlCompilerPrivate TESTDATA ${test_data} ) diff --git a/tests/auto/qml/qmllint/tst_qmllint.cpp b/tests/auto/qml/qmllint/tst_qmllint.cpp index 4801d4ccbc..a7c19468c5 100644 --- a/tests/auto/qml/qmllint/tst_qmllint.cpp +++ b/tests/auto/qml/qmllint/tst_qmllint.cpp @@ -31,7 +31,7 @@ #include #include #include -#include +#include class TestQmllint: public QQmlDataTest { @@ -115,7 +115,7 @@ private: QString m_qmltyperegistrarPath; QStringList m_defaultImportPaths; - QQmlLinter m_linter; + QQmlJSLinter m_linter; }; TestQmllint::TestQmllint() @@ -1374,7 +1374,7 @@ void TestQmllint::missingBuiltinsNoCrash() { // We cannot use the normal linter here since the other tests might have cached the builtins // alread - QQmlLinter linter(m_defaultImportPaths); + QQmlJSLinter linter(m_defaultImportPaths); QJsonArray jsonOutput; QJsonArray warnings; @@ -1396,7 +1396,7 @@ void TestQmllint::absolutePath() { // We cannot use the normal linter here since we need to set a different parameter in the // constructor - QQmlLinter linter(m_defaultImportPaths, true); + QQmlJSLinter linter(m_defaultImportPaths, true); const QString absolutePath = QFileInfo(testFile("memberNotFound.qml")).absoluteFilePath(); diff --git a/tests/auto/qml/qmltc/data/CMakeLists.txt b/tests/auto/qml/qmltc/data/CMakeLists.txt index 59b302f241..816164022e 100644 --- a/tests/auto/qml/qmltc/data/CMakeLists.txt +++ b/tests/auto/qml/qmltc/data/CMakeLists.txt @@ -72,7 +72,7 @@ set(qml_sources LocallyImported.qml LocalWithOnCompleted.qml LocallyImported_context.qml -# SingletonThing.qml +# SingletonThing.qml ) set(js_sources diff --git a/tests/auto/quickcontrols2/sanity/CMakeLists.txt b/tests/auto/quickcontrols2/sanity/CMakeLists.txt index b94b1bfe31..cd838b332c 100644 --- a/tests/auto/quickcontrols2/sanity/CMakeLists.txt +++ b/tests/auto/quickcontrols2/sanity/CMakeLists.txt @@ -23,7 +23,7 @@ qt_internal_add_test(tst_sanity Qt::QuickTest Qt::QuickTestUtilsPrivate Qt::TestPrivate - Qt::QmlLintPrivate + Qt::QmlCompilerPrivate ) #### Keys ignored in scope 1:.:.:sanity.pro:: diff --git a/tests/auto/quickcontrols2/sanity/tst_sanity.cpp b/tests/auto/quickcontrols2/sanity/tst_sanity.cpp index 5fcf594ed9..69d27cf5dc 100644 --- a/tests/auto/quickcontrols2/sanity/tst_sanity.cpp +++ b/tests/auto/quickcontrols2/sanity/tst_sanity.cpp @@ -40,7 +40,7 @@ #include #include #include -#include +#include using namespace QQuickVisualTestUtils; using namespace QQuickControlsTestUtils; @@ -63,7 +63,7 @@ private: QMap installedQmlFiles; QStringList m_importPaths; - QQmlLinter m_linter; + QQmlJSLinter m_linter; QMap m_options; }; diff --git a/tools/qmllint/CMakeLists.txt b/tools/qmllint/CMakeLists.txt index f9127acaa3..d54ab2d43f 100644 --- a/tools/qmllint/CMakeLists.txt +++ b/tools/qmllint/CMakeLists.txt @@ -15,7 +15,6 @@ qt_internal_add_tool(${target_name} PUBLIC_LIBRARIES Qt::CorePrivate Qt::QmlCompilerPrivate - Qt::QmlLintPrivate ) qt_internal_return_unless_building_tools() diff --git a/tools/qmllint/main.cpp b/tools/qmllint/main.cpp index eb744b3c19..484b6f4a63 100644 --- a/tools/qmllint/main.cpp +++ b/tools/qmllint/main.cpp @@ -28,10 +28,9 @@ #include "../shared/qqmltoolingsettings.h" -#include - #include #include +#include #include #include @@ -224,7 +223,7 @@ All warnings can be set to three levels: QStringList resourceFiles = defaultResourceFiles; bool success = true; - QQmlLinter linter(qmlImportPaths, useAbsolutePath); + QQmlJSLinter linter(qmlImportPaths, useAbsolutePath); QJsonArray jsonFiles; diff --git a/tools/qmlls/CMakeLists.txt b/tools/qmlls/CMakeLists.txt index ac42d239de..7e74677e29 100644 --- a/tools/qmlls/CMakeLists.txt +++ b/tools/qmlls/CMakeLists.txt @@ -24,6 +24,6 @@ qt_internal_add_tool(${target_name} Qt::CorePrivate Qt::QmlDomPrivate Qt::LanguageServerPrivate - Qt::QmlLintPrivate + Qt::QmlCompilerPrivate ) qt_internal_return_unless_building_tools() diff --git a/tools/qmlls/qmllintsuggestions.cpp b/tools/qmlls/qmllintsuggestions.cpp index 6a9dee5f44..efa83e499d 100644 --- a/tools/qmlls/qmllintsuggestions.cpp +++ b/tools/qmlls/qmllintsuggestions.cpp @@ -27,7 +27,7 @@ ****************************************************************************/ #include "qmllintsuggestions.h" #include -#include +#include #include #include #include @@ -135,7 +135,7 @@ void QmlLintSuggestions::diagnose(const QByteArray &uri) QStringList resourceFiles; QMap options; - QQmlLinter linter(imports, useAbsolutePath); + QQmlJSLinter linter(imports, useAbsolutePath); linter.lintFile(filename, &fileContents, silent, &json, imports, qmltypesFiles, resourceFiles, options);