aboutsummaryrefslogtreecommitdiffstats
path: root/examples/qmlcompiler/tutorials/helloworld
diff options
context:
space:
mode:
Diffstat (limited to 'examples/qmlcompiler/tutorials/helloworld')
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt22
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp19
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h21
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter1/plugin.json13
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml24
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt22
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp56
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h21
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter2/plugin.json13
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml24
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter3/CMakeLists.txt22
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.cpp64
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter3/helloplugin.h21
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter3/plugin.json13
-rw-r--r--examples/qmlcompiler/tutorials/helloworld/chapter3/test.qml26
15 files changed, 381 insertions, 0 deletions
diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt b/examples/qmlcompiler/tutorials/helloworld/chapter1/CMakeLists.txt
new file mode 100644
index 0000000000..b9466b61b3
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/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/chapter1/helloplugin.cpp b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp
new file mode 100644
index 0000000000..ad36e64fae
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.cpp
@@ -0,0 +1,19 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include "helloplugin.h"
+#include <QDebug>
+
+using namespace Qt::StringLiterals;
+
+static constexpr QQmlSA::LoggerWarningId helloWorld { "Plugin.HelloWorld.hello-world" };
+
+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
+ // here we will later register our passes
+}
+
+#include "moc_helloplugin.cpp"
diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h b/examples/qmlcompiler/tutorials/helloworld/chapter1/helloplugin.h
new file mode 100644
index 0000000000..6666c78be0
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/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 <QtCore/qobject.h>
+#include <QtQmlCompiler/qqmlsa.h>
+
+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/chapter1/plugin.json b/examples/qmlcompiler/tutorials/helloworld/chapter1/plugin.json
new file mode 100644
index 0000000000..3d8c1ff206
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/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/chapter1/test.qml b/examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml
new file mode 100644
index 0000000000..99af71ad7d
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter1/test.qml
@@ -0,0 +1,24 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+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!" }
+ }
+}
diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt b/examples/qmlcompiler/tutorials/helloworld/chapter2/CMakeLists.txt
new file mode 100644
index 0000000000..b9466b61b3
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/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/chapter2/helloplugin.cpp b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp
new file mode 100644
index 0000000000..431ad97f16
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.cpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include "helloplugin.h"
+#include <QDebug>
+
+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;
+ if (textBinding.stringValue() != u"Hello world!"_s)
+ emitWarning("Incorrect greeting", helloWorld, textBinding.sourceLocation());
+ }
+}
+
+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<HelloWorldElementPass>(manager));
+}
+
+#include "moc_helloplugin.cpp"
diff --git a/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h b/examples/qmlcompiler/tutorials/helloworld/chapter2/helloplugin.h
new file mode 100644
index 0000000000..6666c78be0
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/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 <QtCore/qobject.h>
+#include <QtQmlCompiler/qqmlsa.h>
+
+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/chapter2/plugin.json b/examples/qmlcompiler/tutorials/helloworld/chapter2/plugin.json
new file mode 100644
index 0000000000..3d8c1ff206
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/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/chapter2/test.qml b/examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml
new file mode 100644
index 0000000000..99af71ad7d
--- /dev/null
+++ b/examples/qmlcompiler/tutorials/helloworld/chapter2/test.qml
@@ -0,0 +1,24 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+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!" }
+ }
+}
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 <QDebug>
+
+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<HelloWorldElementPass>(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 <QtCore/qobject.h>
+#include <QtQmlCompiler/qqmlsa.h>
+
+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]