From f4c13d1b738d25c563d00c0bc25e720775d985a3 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 1 Sep 2023 17:57:19 +0200 Subject: QQmlSA: Add initial fixit section FixSuggestion unfortunately still lacks class documentation, and we probably need to rework the API before moving the module out of TP. However, we should still show the basic usage of the module, including fixit suggestions. Consequently, add a small example on how to write FixSuggestions, and add a warning note that they should only be marked as auto-applicable if the resulting code is still valid. Pick-to: 6.6 Change-Id: I260021163e3afe2cda97fd82a9bf4e9c26a910e2 Reviewed-by: Ulf Hermann --- .../tutorials/helloworld/chapter3/CMakeLists.txt | 22 ++++++++ .../tutorials/helloworld/chapter3/helloplugin.cpp | 64 ++++++++++++++++++++++ .../tutorials/helloworld/chapter3/helloplugin.h | 21 +++++++ .../tutorials/helloworld/chapter3/plugin.json | 13 +++++ .../tutorials/helloworld/chapter3/test.qml | 26 +++++++++ 5 files changed, 146 insertions(+) create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json create mode 100644 examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml (limited to 'examples/qmlcompiler/tutorials/helloworld') diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt b/examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt new file mode 100644 index 0000000000..b9466b61b3 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.21) + +project(hello_world_plugin VERSION 1.0.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 REQUIRED COMPONENTS QmlCompiler) + +qt_standard_project_setup( + REQUIRES 6.6 +) + +qt_add_plugin(HelloWorldPlugin) + +target_sources(HelloWorldPlugin + PRIVATE + helloplugin.h + helloplugin.cpp +) + +target_link_libraries(HelloWorldPlugin PRIVATE Qt::QmlCompiler) diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp new file mode 100644 index 0000000000..93ee6d80c4 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include "helloplugin.h" +#include + +using namespace Qt::StringLiterals; + +static constexpr QQmlSA::LoggerWarningId helloWorld { "Plugin.HelloWorld.hello-world" }; + +class HelloWorldElementPass : public QQmlSA::ElementPass +{ +public: + HelloWorldElementPass(QQmlSA::PassManager *manager); + bool shouldRun(const QQmlSA::Element &element) override; + void run(const QQmlSA::Element &element) override; +private: + QQmlSA::Element m_textType; +}; + +HelloWorldElementPass::HelloWorldElementPass(QQmlSA::PassManager *manager) + : QQmlSA::ElementPass(manager) +{ + m_textType = resolveType("QtQuick", "Text"); +} + +bool HelloWorldElementPass::shouldRun(const QQmlSA::Element &element) +{ + if (!element.inherits(m_textType)) + return false; + if (!element.hasOwnPropertyBindings(u"text"_s)) + return false; + return true; +} + +void HelloWorldElementPass::run(const QQmlSA::Element &element) +{ + auto textBindings = element.ownPropertyBindings(u"text"_s); + for (const auto &textBinding: textBindings) { + if (textBinding.bindingType() != QQmlSA::BindingType::StringLiteral) + continue; + QString currentBinding = textBinding.stringValue(); + if (currentBinding == u"Hello world!"_s) + continue; + if (currentBinding == u"Goodbye world!"_s) { + QQmlSA::FixSuggestion suggestion(u"Replace 'Goodbye' with 'Hello'"_s, + textBinding.sourceLocation(), u"\"Hello world!\""_s); + suggestion.setAutoApplicable(true); + emitWarning("Incorrect greeting", helloWorld, textBinding.sourceLocation(), suggestion); + } + } +} + + +void HelloWorldPlugin::registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) +{ + const bool pluginIsEnabled = manager->isCategoryEnabled(helloWorld); + qDebug() << "Hello World plugin is" << (pluginIsEnabled ? "enabled" : "disabled"); + if (!pluginIsEnabled) + return; // skip registration if the plugin is disabled anyway + manager->registerElementPass(std::make_unique(manager)); +} + +#include "moc_helloplugin.cpp" diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h new file mode 100644 index 0000000000..6666c78be0 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h @@ -0,0 +1,21 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef HELLO_PLUGIN_H +#define HELLO_PLUGIN_H + +#include +#include + +class HelloWorldPlugin : public QObject, public QQmlSA::LintPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QmlLintPluginInterface_iid FILE "plugin.json") + Q_INTERFACES(QQmlSA::LintPlugin) + +public: + void registerPasses(QQmlSA::PassManager *manager, const QQmlSA::Element &rootElement) override; +}; + +#endif + diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json b/examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json new file mode 100644 index 0000000000..3d8c1ff206 --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json @@ -0,0 +1,13 @@ +{ + "name": "HelloWorld", + "author": "Qt Example", + "description": "Demonstrates how to write a qmllint plugin", + "version": "1.0", + "loggingCategories": [ + { + "name": "hello-world", + "settingsName": "HelloWorld", + "description": "Used to create test messages" + } + ] +} diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml b/examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml new file mode 100644 index 0000000000..42fbaa108f --- /dev/null +++ b/examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml @@ -0,0 +1,26 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +// [0] +import QtQuick + +Item { + id: root + + property string greeting: "Hello" + + component MyText : Text {} + + component NotText : Item { + property string text + } + + Text { text: "Hello world!" } + Text { text: root.greeting } + Text { text: "Goodbye world!" } + NotText { + text: "Does not trigger" + MyText { text: "Goodbye world!" } + } +} +// [0] -- cgit v1.2.3