Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
5#include <QtQmlLS/private/qqmllsutils_p.h>
6#include <QtQmlLS/private/qqmllscompletion_p.h>
7
8using namespace QLspSpecification;
9using namespace QQmlJS::Dom;
10
12
13std::unique_ptr<QQmlLSCompletionPlugin> QQmlLSQuickPlugin::createCompletionPlugin() const
14{
15 return std::make_unique<QQmlLSQuickCompletionPlugin>();
16}
17
19 const DomItem &itemAtPosition, BackInsertIterator result) const
20{
21 auto file = itemAtPosition.containingFile().as<QmlFile>();
22 if (!file)
23 return;
24
25 // check if QtQuick has been imported
26 const auto &imports = file->imports();
27 auto it = std::find_if(imports.constBegin(), imports.constEnd(), [](const Import &import) {
28 return import.uri.moduleUri() == u"QtQuick";
29 });
30 if (it == imports.constEnd()) {
31 return;
32 }
33
34 // for default bindings:
36
37 // check if the user already typed some qualifier, remove its dot and compare it to QtQuick's
38 // qualified name
39 const QString userTypedQualifier = QQmlLSUtils::qualifiersFrom(itemAtPosition);
40 if (!userTypedQualifier.isEmpty()
41 && !it->importId.startsWith(QStringView(userTypedQualifier).chopped(1))) {
42 return;
43 }
44
45 const QByteArray prefixForSnippet =
46 userTypedQualifier.isEmpty() ? it->importId.toUtf8() : QByteArray();
47 const QByteArray prefixWithDotForSnippet =
48 prefixForSnippet.isEmpty() ? QByteArray() : QByteArray(prefixForSnippet).append(u'.');
49
50 auto resolver = file->typeResolver();
51 if (!resolver)
52 return;
53 const auto qquickItemScope = resolver->typeForName(prefixWithDotForSnippet + u"Item"_s);
54 const QQmlJSScope::ConstPtr ownerScope = itemAtPosition.qmlObject().semanticScope();
55 if (!ownerScope || !qquickItemScope)
56 return;
57
58 if (ownerScope->inherits(qquickItemScope)) {
60 "states binding with PropertyChanges in State",
61 "states: [\n"
62 "\t"_ba.append(prefixWithDotForSnippet)
63 .append("State {\n"
64 "\t\tname: \"${1:name}\"\n"
65 "\t\t"_ba.append(prefixWithDotForSnippet)
66 .append("PropertyChanges {\n"
67 "\t\t\ttarget: ${2:object}\n"
68 "\t\t}\n"
69 "\t}\n"
70 "]")));
71 result = QQmlLSCompletion::makeSnippet("transitions binding with Transition",
72 "transitions: [\n"
73 "\t"_ba.append(prefixWithDotForSnippet)
74 .append("Transition {\n"
75 "\t\tfrom: \"${1:fromState}\"\n"
76 "\t\tto: \"${2:fromState}\"\n"
77 "\t}\n"
78 "]"));
79 }
80}
81
83 const DomItem &itemAtPosition, BackInsertIterator result) const
84{
85 auto file = itemAtPosition.containingFile().as<QmlFile>();
86 if (!file)
87 return;
88
89 // check if QtQuick has been imported
90 const auto &imports = file->imports();
91 auto it = std::find_if(imports.constBegin(), imports.constEnd(), [](const Import &import) {
92 return import.uri.moduleUri() == u"QtQuick";
93 });
94 if (it == imports.constEnd()) {
95 return;
96 }
97
98 // check if the user already typed some qualifier, remove its dot and compare it to QtQuick's
99 // qualified name
100 const QString userTypedQualifier = QQmlLSUtils::qualifiersFrom(itemAtPosition);
101 if (!userTypedQualifier.isEmpty()
102 && !it->importId.startsWith(QStringView(userTypedQualifier).chopped(1))) {
103 return;
104 }
105
106 const QByteArray prefixForSnippet =
107 userTypedQualifier.isEmpty() ? it->importId.toUtf8() : QByteArray();
108 const QByteArray prefixWithDotForSnippet =
109 prefixForSnippet.isEmpty() ? QByteArray() : QByteArray(prefixForSnippet).append(u'.');
110
111 // Quick completions from Qt Creator's code model
112 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "BorderImage snippet",
113 "BorderImage {\n"
114 "\tid: ${1:name}\n"
115 "\tsource: \"${2:file}\"\n"
116 "\twidth: ${3:100}; height: ${4:100}\n"
117 "\tborder.left: ${5: 5}; border.top: ${5}\n"
118 "\tborder.right: ${5}; border.bottom: ${5}\n"
119 "}");
120 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "ColorAnimation snippet",
121 "ColorAnimation {\n"
122 "\tfrom: \"${1:white}\"\n"
123 "\tto: \"${2:black}\"\n"
124 "\tduration: ${3:200}\n"
125 "}");
126 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Image snippet",
127 "Image {\n"
128 "\tid: ${1:name}\n"
129 "\tsource: \"${2:file}\"\n"
130 "}");
131 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Item snippet",
132 "Item {\n"
133 "\tid: ${1:name}\n"
134 "}");
135 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "NumberAnimation snippet",
136 "NumberAnimation {\n"
137 "\ttarget: ${1:object}\n"
138 "\tproperty: \"${2:name}\"\n"
139 "\tduration: ${3:200}\n"
140 "\teasing.type: "_ba.append(prefixWithDotForSnippet)
141 .append("Easing.${4:InOutQuad}\n"
142 "}"));
143 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "NumberAnimation with targets snippet",
144 "NumberAnimation {\n"
145 "\ttargets: [${1:object}]\n"
146 "\tproperties: \"${2:name}\"\n"
147 "\tduration: ${3:200}\n"
148 "}");
149 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PauseAnimation snippet",
150 "PauseAnimation {\n"
151 "\tduration: ${1:200}\n"
152 "}");
153 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PropertyAction snippet",
154 "PropertyAction {\n"
155 "\ttarget: ${1:object}\n"
156 "\tproperty: \"${2:name}\"\n"
157 "}");
158 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PropertyAction with targets snippet",
159 "PropertyAction {\n"
160 "\ttargets: [${1:object}]\n"
161 "\tproperties: \"${2:name}\"\n"
162 "}");
163 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "PropertyChanges snippet",
164 "PropertyChanges {\n"
165 "\ttarget: ${1:object}\n"
166 "}");
167 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "State snippet",
168 "State {\n"
169 "\tname: ${1:name}\n"
170 "\t"_ba.append(prefixWithDotForSnippet)
171 .append("PropertyChanges {\n"
172 "\t\ttarget: ${2:object}\n"
173 "\t}\n"
174 "}"));
175 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Text snippet",
176 "Text {\n"
177 "\tid: ${1:name}\n"
178 "\ttext: qsTr(\"${2:text}\")\n"
179 "}");
180 result = QQmlLSCompletion::makeSnippet(prefixForSnippet, "Transition snippet",
181 "Transition {\n"
182 "\tfrom: \"${1:fromState}\"\n"
183 "\tto: \"${2:toState}\"\n"
184 "}");
185}
186
\inmodule QtCore
Definition qbytearray.h:57
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
T const * as() const
DomItem containingFile() const
DomItem qmlObject(GoTo option=GoTo::Strict, FilterUpOptions options=FilterUpOptions::ReturnOuter) const
QQmlJSScope::ConstPtr semanticScope() const
A QmlFile, when loaded in a DomEnvironment that has the DomCreationOption::WithSemanticAnalysis,...
std::back_insert_iterator< QList< QLspSpecification::CompletionItem > > BackInsertIterator
static CompletionItem makeSnippet(QUtf8StringView qualifier, QUtf8StringView label, QUtf8StringView insertText)
void suggestSnippetsForLeftHandSideOfBinding(const QQmlJS::Dom::DomItem &items, BackInsertIterator result) const override
void suggestSnippetsForRightHandSideOfBinding(const QQmlJS::Dom::DomItem &items, BackInsertIterator result) const override
std::unique_ptr< QQmlLSCompletionPlugin > createCompletionPlugin() const override
static QString qualifiersFrom(const DomItem &el)
const_iterator constEnd() const noexcept
Definition qset.h:143
\inmodule QtCore
Definition qstringview.h:78
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QSet< QString >::iterator it
Combined button and popup list for selecting options.
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
GLuint64EXT * result
[6]
QFile file
[0]