Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmllsquickplugin.cpp
Go to the documentation of this file.
1// Copyright (C) 2024 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant reason:default
4
6#include <QtQmlLS/private/qqmllsutils_p.h>
7#include <QtQmlLS/private/qqmllscompletion_p.h>
8
9using namespace QLspSpecification;
10using namespace QQmlJS::Dom;
11
12QT_BEGIN_NAMESPACE
13
14std::unique_ptr<QQmlLSCompletionPlugin> QQmlLSQuickPlugin::createCompletionPlugin() const
15{
16 return std::make_unique<QQmlLSQuickCompletionPlugin>();
17}
18
19void QQmlLSQuickCompletionPlugin::suggestSnippetsForLeftHandSideOfBinding(
20 const DomItem &itemAtPosition, BackInsertIterator result) const
21{
22 auto file = itemAtPosition.containingFile().as<QmlFile>();
23 if (!file)
24 return;
25
26 // check if QtQuick has been imported
27 const auto &imports = file->imports();
28 auto it = std::find_if(imports.constBegin(), imports.constEnd(), [](const Import &import) {
29 return import.uri.moduleUri() == u"QtQuick";
30 });
31 if (it == imports.constEnd()) {
32 return;
33 }
34
35 // for default bindings:
36 suggestSnippetsForRightHandSideOfBinding(itemAtPosition, result);
37
38 // check if the user already typed some qualifier, remove its dot and compare it to QtQuick's
39 // qualified name
40 const QString userTypedQualifier = QQmlLSUtils::qualifiersFrom(itemAtPosition);
41 if (!userTypedQualifier.isEmpty()
42 && !it->importId.startsWith(QStringView(userTypedQualifier).chopped(1))) {
43 return;
44 }
45
46 const QByteArray prefixForSnippet =
47 userTypedQualifier.isEmpty() ? it->importId.toUtf8() : QByteArray();
48 const QByteArray prefixWithDotForSnippet =
49 it->importId.isEmpty() ? QByteArray() : it->importId.toUtf8().append(u'.');
50
51 auto resolver = file->typeResolver();
52 if (!resolver)
53 return;
54 const auto qquickItemScope = resolver->typeForName(prefixWithDotForSnippet + u"Item"_s);
55 const QQmlJSScope::ConstPtr ownerScope = itemAtPosition.qmlObject().semanticScope();
56 if (!ownerScope || !qquickItemScope)
57 return;
58
59 if (ownerScope->inherits(qquickItemScope)) {
60 result = QQmlLSCompletion::makeSnippet(
61 "states binding with PropertyChanges in State",
62 "states: [\n"
63 "\t"_ba.append(prefixWithDotForSnippet)
64 .append("State {\n"
65 "\t\tname: \"${1:name}\"\n"
66 "\t\t"_ba.append(prefixWithDotForSnippet)
67 .append("PropertyChanges {\n"
68 "\t\t\ttarget: ${2:object}\n"
69 "\t\t}\n"
70 "\t}\n"
71 "]")));
72 result = QQmlLSCompletion::makeSnippet("transitions binding with Transition",
73 "transitions: [\n"
74 "\t"_ba.append(prefixWithDotForSnippet)
75 .append("Transition {\n"
76 "\t\tfrom: \"${1:fromState}\"\n"
77 "\t\tto: \"${2:fromState}\"\n"
78 "\t}\n"
79 "]"));
80 }
81}
82
83void QQmlLSQuickCompletionPlugin::suggestSnippetsForRightHandSideOfBinding(
84 const DomItem &itemAtPosition, BackInsertIterator result) const
85{
86 auto file = itemAtPosition.containingFile().as<QmlFile>();
87 if (!file)
88 return;
89
90 // check if QtQuick has been imported
91 const auto &imports = file->imports();
92 auto it = std::find_if(imports.constBegin(), imports.constEnd(), [](const Import &import) {
93 return import.uri.moduleUri() == u"QtQuick";
94 });
95 if (it == imports.constEnd()) {
96 return;
97 }
98
99 // check if the user already typed some qualifier, remove its dot and compare it to QtQuick's
100 // qualified name
101 const QString userTypedQualifier = QQmlLSUtils::qualifiersFrom(itemAtPosition);
102 if (!userTypedQualifier.isEmpty()
103 && !it->importId.startsWith(QStringView(userTypedQualifier).chopped(1))) {
104 return;
105 }
106
107 const QByteArray prefixForSnippet =
108 userTypedQualifier.isEmpty() ? it->importId.toUtf8() : QByteArray();
109 const QByteArray prefixWithDotForSnippet =
110 it->importId.isEmpty() ? QByteArray() : it->importId.toUtf8().append(u'.');
111
112 // Quick completions from Qt Creator's code model
113 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "BorderImage snippet",
114 "BorderImage {\n"
115 "\tid: ${1:name}\n"
116 "\tsource: \"${2:file}\"\n"
117 "\twidth: ${3:100}; height: ${4:100}\n"
118 "\tborder.left: ${5: 5}; border.top: ${5}\n"
119 "\tborder.right: ${5}; border.bottom: ${5}\n"
120 "}");
121 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "ColorAnimation snippet",
122 "ColorAnimation {\n"
123 "\tfrom: \"${1:white}\"\n"
124 "\tto: \"${2:black}\"\n"
125 "\tduration: ${3:200}\n"
126 "}");
127 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Image snippet",
128 "Image {\n"
129 "\tid: ${1:name}\n"
130 "\tsource: \"${2:file}\"\n"
131 "}");
132 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Item snippet",
133 "Item {\n"
134 "\tid: ${1:name}\n"
135 "}");
136 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "NumberAnimation snippet",
137 "NumberAnimation {\n"
138 "\ttarget: ${1:object}\n"
139 "\tproperty: \"${2:name}\"\n"
140 "\tduration: ${3:200}\n"
141 "\teasing.type: "_ba.append(prefixWithDotForSnippet)
142 .append("Easing.${4:InOutQuad}\n"
143 "}"));
144 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "NumberAnimation with targets snippet",
145 "NumberAnimation {\n"
146 "\ttargets: [${1:object}]\n"
147 "\tproperties: \"${2:name}\"\n"
148 "\tduration: ${3:200}\n"
149 "}");
150 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PauseAnimation snippet",
151 "PauseAnimation {\n"
152 "\tduration: ${1:200}\n"
153 "}");
154 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PropertyAction snippet",
155 "PropertyAction {\n"
156 "\ttarget: ${1:object}\n"
157 "\tproperty: \"${2:name}\"\n"
158 "}");
159 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PropertyAction with targets snippet",
160 "PropertyAction {\n"
161 "\ttargets: [${1:object}]\n"
162 "\tproperties: \"${2:name}\"\n"
163 "}");
164 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PropertyChanges snippet",
165 "PropertyChanges {\n"
166 "\ttarget: ${1:object}\n"
167 "}");
168 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "State snippet",
169 "State {\n"
170 "\tname: ${1:name}\n"
171 "\t"_ba.append(prefixWithDotForSnippet)
172 .append("PropertyChanges {\n"
173 "\t\ttarget: ${2:object}\n"
174 "\t}\n"
175 "}"));
176 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Text snippet",
177 "Text {\n"
178 "\tid: ${1:name}\n"
179 "\ttext: qsTr(\"${2:text}\")\n"
180 "}");
181 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Transition snippet",
182 "Transition {\n"
183 "\tfrom: \"${1:fromState}\"\n"
184 "\tto: \"${2:toState}\"\n"
185 "}");
186}
187
188QT_END_NAMESPACE