50 res.insertTextFormat = InsertTextFormat::Snippet;
52 res.insertText = qualifier.
data();
53 *
res.insertText +=
'.';
54 *
res.insertText += insertText.data();
56 res.insertText = insertText.data();
58 res.kind = int(CompletionItemKind::Snippet);
59 res.insertTextMode = InsertTextMode::AdjustIndentation;
89 const QQmlLSCompletionPosition &positionInfo,
95 if (!(
left.end() <= positionInfo.offset()))
101 return positionInfo.offset() <=
right.begin();
109 const QQmlLSCompletionPosition &positionInfo)
const
118bool QQmlLSCompletion::beforeLocation(
const QQmlLSCompletionPosition &
ctx,
121 if (!
right.isValid())
131bool QQmlLSCompletion::ctxBeforeStatement(
const QQmlLSCompletionPosition &positionInfo,
132 const DomItem &parentForContext,
136 const bool result = beforeLocation(positionInfo, regions[firstRegion]);
141QQmlLSCompletion::suggestBindingCompletion(
const DomItem &itemAtPosition, BackInsertIterator
it)
const
143 suggestReachableTypes(itemAtPosition, LocalSymbolsType::AttachedType, CompletionItemKind::Class,
148 return itemAtPosition.qmlObject().semanticScope();
150 const DomItem owner = itemAtPosition.directParent().field(Fields::left);
159 propertyCompletion(scope,
nullptr,
it);
160 signalHandlerCompletion(scope,
nullptr,
it);
163void QQmlLSCompletion::insideImportCompletionHelper(
const DomItem &
file,
164 const QQmlLSCompletionPosition &positionInfo,
165 BackInsertIterator
it)
const
172 qsizetype effectiveLength = linePieces.size()
173 + ((!ctx.preLine().isEmpty() && ctx.preLine().last().isSpace()) ? 1 : 0);
174 if (effectiveLength < 2) {
176 comp.label =
"import";
177 comp.kind = int(CompletionItemKind::Keyword);
180 if (linePieces.isEmpty() || linePieces.first() != u
"import")
182 if (effectiveLength == 2) {
185 }
else if (effectiveLength == 3) {
186 if (linePieces.last() != u
"as") {
190 comp.kind = int(CompletionItemKind::Keyword);
196 if (std::shared_ptr<DomEnvironment> envPtr = env.ownerAs<
DomEnvironment>()) {
197 switch (importCompletionType) {
201 QDuplicateTracker<QString> modulesSeen;
202 for (
const QString &uri : envPtr->moduleIndexUris(env)) {
204 if (uri.startsWith(
base)) {
210 if (!modulesSeen.hasSeen(
label)) {
213 comp.kind = int(CompletionItemKind::Module);
221 if (
ctx.base().isEmpty()) {
223 envPtr->moduleIndexMajorVersions(env, linePieces.
at(1).
toString())) {
226 comp.kind = int(CompletionItemKind::Constant);
230 bool hasMajorVersion =
ctx.base().endsWith(u
'.');
233 majorV =
ctx.base().mid(0,
ctx.base().size() - 1).toInt(&hasMajorVersion);
234 if (!hasMajorVersion)
236 if (std::shared_ptr<ModuleIndex> mIndex =
237 envPtr->moduleIndexWithUri(env, linePieces.at(1).toString(), majorV)) {
238 for (
int minorV : mIndex->minorVersions()) {
241 comp.kind = int(CompletionItemKind::Constant);
251void QQmlLSCompletion::idsCompletions(
const DomItem &
component, BackInsertIterator
it)
const
253 qCDebug(QQmlLSCompletionLog) <<
"adding ids completions";
256 comp.label = k.toUtf8();
257 comp.kind = int(CompletionItemKind::Value);
263 CompletionItemKind kind)
265 const bool currentIsSingleton = scope->
isSingleton();
267 if ((options & LocalSymbolsType::Singleton) && currentIsSingleton) {
270 if ((options & LocalSymbolsType::AttachedType) && currentIsAttached) {
274 if (options & LocalSymbolsType::ObjectType && !currentIsSingleton && isObjectType) {
275 return kind != CompletionItemKind::Constructor || scope->
isCreatable();
277 if (options & LocalSymbolsType::ValueType && !currentIsSingleton && !isObjectType) {
287void QQmlLSCompletion::suggestReachableTypes(
const DomItem &
el, LocalSymbolsTypes options,
288 CompletionItemKind kind, BackInsertIterator
it)
const
293 auto resolver =
file->typeResolver();
298 const auto keyValueRange = resolver->importedTypes().asKeyValueRange();
299 for (
const auto &
type : keyValueRange) {
301 const bool isMarkerType =
type.first.contains(u
"$internal$.")
302 ||
type.first.contains(u
"$anonymous$.") ||
type.first.contains(u
"$module$.");
303 if (isMarkerType || !
type.first.startsWith(requiredQualifiers))
306 auto &scope =
type.second.scope;
315 completion.kind = int(kind);
321 QDuplicateTracker<QString> *usedNames,
322 BackInsertIterator
it)
const
324 for (
const auto &[
name, jsIdentifier] : scope->ownJSIdentifiers().asKeyValueRange()) {
326 if (usedNames && usedNames->hasSeen(
name)) {
329 completion.label =
name.toUtf8();
330 completion.kind = int(CompletionItemKind::Variable);
332 if (jsIdentifier.typeName) {
333 if (jsIdentifier.isConst) {
336 detail.append(*jsIdentifier.typeName);
338 detail.append(jsIdentifier.isConst ? u
"const"_s : u
"var"_s);
340 completion.detail =
detail.toUtf8();
346 QDuplicateTracker<QString> *usedNames,
347 BackInsertIterator
it)
const
353 if (usedNames && usedNames->hasSeen(
name)) {
357 completion.label =
name.toUtf8();
358 completion.kind = int(CompletionItemKind::Method);
366 QDuplicateTracker<QString> *usedNames,
367 BackInsertIterator
it)
const
370 if (usedNames && usedNames->hasSeen(
name)) {
374 completion.label =
name.toUtf8();
375 completion.kind = int(CompletionItemKind::Property);
378 detail.append(u
"readonly "_s);
380 completion.detail =
detail.toUtf8();
386 QDuplicateTracker<QString> *usedNames,
387 BackInsertIterator
it)
const
390 if (usedNames && usedNames->hasSeen(enumerator.name())) {
394 completion.label = enumerator.name().toUtf8();
395 completion.kind =
static_cast<int>(CompletionItemKind::Enum);
400void QQmlLSCompletion::enumerationValueCompletionHelper(
const QStringList &enumeratorKeys,
401 BackInsertIterator
it)
const
403 for (
const QString &enumeratorKey : enumeratorKeys) {
405 completion.label = enumeratorKey.toUtf8();
406 completion.kind =
static_cast<int>(CompletionItemKind::EnumMember);
433 BackInsertIterator
result)
const
435 auto enumerator = scope->
enumeration(enumeratorName);
436 if (enumerator.isValid()) {
437 enumerationValueCompletionHelper(enumerator.keys(),
result);
442 enumerationValueCompletionHelper(enumerator.keys(),
result);
478void QQmlLSCompletion::suggestJSExpressionCompletion(
const DomItem &scriptIdentifier,
479 BackInsertIterator
result)
const
481 QDuplicateTracker<QString> usedNames;
488 const bool hasQualifier =
494 completion.label =
view.data();
495 completion.kind = int(CompletionItemKind::Value);
498 idsCompletions(scriptIdentifier.component(),
result);
499 suggestReachableTypes(scriptIdentifier,
500 LocalSymbolsType::Singleton | LocalSymbolsType::AttachedType,
501 CompletionItemKind::Class,
result);
503 auto scope = scriptIdentifier.nearestSemanticScope();
506 nearestScope = scope;
508 enumerationCompletion(nearestScope, &usedNames,
result);
511 (askForCompletionOnDot ? scriptIdentifier : scriptIdentifier.directParent())
512 .field(Fields::left);
515 if (!expressionType || !expressionType->semanticScope)
517 nearestScope = expressionType->semanticScope;
521 nearestScope = owner.rootQmlObject(GoTo::MostLikely).semanticScope();
522 if (expressionType->name) {
524 enumerationValueCompletion(nearestScope, *expressionType->name,
result);
527 if (
auto enumerator = nearestScope->enumeration(*expressionType->name);
528 !enumerator.isValid()) {
529 enumerationCompletion(nearestScope, &usedNames,
result);
539 methodCompletion(nearestScope, &usedNames,
result);
540 propertyCompletion(nearestScope, &usedNames,
result);
546 jsIdentifierCompletion(scope, &usedNames,
result);
551 methodCompletion(scope, &usedNames,
result);
556 propertyCompletion(scope, &usedNames,
result);
560 auto file = scriptIdentifier.containingFile().as<
QmlFile>();
563 auto resolver =
file->typeResolver();
567 const auto globals = resolver->jsGlobalObject();
568 methodCompletion(globals, &usedNames,
result);
569 propertyCompletion(globals, &usedNames,
result);
577 if (
auto propertyType =
property.type().get()) {
578 current = propertyType;
587bool QQmlLSCompletion::cursorInFrontOfItem(
const DomItem &parentForContext,
588 const QQmlLSCompletionPosition &positionInfo)
591 return positionInfo.offset() <= fileLocations.offset;
594bool QQmlLSCompletion::cursorAfterColon(
const DomItem ¤tItem,
595 const QQmlLSCompletionPosition &positionInfo)
600 if (region ==
location.regions.constEnd())
603 if (region.value().isValid() && region.value().offset < positionInfo.offset()) {
621 { u
"ComponentBehavior"_s, { u
"Unbound"_s, u
"Bound"_s } },
622 { u
"NativeMethodBehavior"_s, { u
"AcceptThisObject"_s, u
"RejectThisObject"_s } },
623 { u
"ListPropertyAssignBehavior"_s, { u
"Append"_s, u
"Replace"_s, u
"ReplaceIfNotDefault"_s } },
624 { u
"Singleton"_s, {} },
625 { u
"ValueTypeBehavior"_s, { u
"Addressable"_s, u
"Inaddressable"_s } },
629 const QQmlLSCompletionPosition &positionInfo,
630 BackInsertIterator
result)
const
632 if (cursorAfterColon(currentItem, positionInfo)) {
640 comp.label =
value.toUtf8();
641 comp.kind =
static_cast<int>(CompletionItemKind::Value);
649 comp.label = pragma.first.toUtf8();
650 if (!pragma.second.isEmpty()) {
653 comp.kind =
static_cast<int>(CompletionItemKind::Value);
658void QQmlLSCompletion::insideQmlObjectCompletion(
const DomItem &parentForContext,
659 const QQmlLSCompletionPosition &positionInfo,
660 BackInsertIterator
result)
const
668 if (beforeLocation(positionInfo, leftBrace)) {
669 LocalSymbolsTypes options;
670 options.setFlag(LocalSymbolsType::ObjectType);
671 suggestReachableTypes(positionInfo.itemAtPosition, options, CompletionItemKind::Constructor,
673 suggestSnippetsForLeftHandSideOfBinding(positionInfo.itemAtPosition,
result);
697 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
702 if (betweenLocations(leftBrace, positionInfo, rightBrace)) {
706 "required default ",
"required " }) {
730 "function ${1:name}($2): ${3:returnType} {\n\t$0\n}");
733 result =
makeSnippet(
"enum name { Values...}",
"enum ${1:name} {\n\t${0:values}\n}");
737 "component ${1:name}: ${2:baseType} {\n\t$0\n}");
740 const DomItem containingObject = parentForContext.qmlObject();
741 suggestBindingCompletion(containingObject,
result);
744 const DomItem containingFile = parentForContext.containingFile();
745 suggestReachableTypes(containingFile, LocalSymbolsType::ObjectType,
746 CompletionItemKind::Constructor,
result);
747 suggestSnippetsForLeftHandSideOfBinding(positionInfo.itemAtPosition,
result);
752void QQmlLSCompletion::insidePropertyDefinitionCompletion(
753 const DomItem ¤tItem,
const QQmlLSCompletionPosition &positionInfo,
754 BackInsertIterator
result)
const
760 if (positionInfo.offset() < propertyKeyword.offset + propertyKeyword.length) {
765 bool completeReadonly =
true;
766 bool completeRequired =
true;
767 bool completeDefault =
true;
770 if (readonlyKeyword.isValid() && readonlyKeyword.offset < positionInfo.offset()) {
771 completeReadonly =
false;
773 completeRequired =
false;
777 if (requiredKeyword.isValid() && requiredKeyword.offset < positionInfo.offset()) {
778 completeRequired =
false;
780 completeReadonly =
false;
784 if (defaultKeyword.isValid() && defaultKeyword.offset < positionInfo.offset()) {
785 completeDefault =
false;
792 item.kind = int(CompletionItemKind::Keyword);
795 addCompletionKeyword(u8
"readonly", completeReadonly);
796 addCompletionKeyword(u8
"required", completeRequired);
797 addCompletionKeyword(u8
"default", completeDefault);
798 addCompletionKeyword(u8
"property",
true);
804 if (propertyKeyword.end() <= positionInfo.offset()
805 && positionInfo.offset() < propertyIdentifier.offset) {
806 suggestReachableTypes(currentItem,
807 LocalSymbolsType::ObjectType | LocalSymbolsType::ValueType,
808 CompletionItemKind::Class,
result);
814void QQmlLSCompletion::insideBindingCompletion(
const DomItem ¤tItem,
815 const QQmlLSCompletionPosition &positionInfo,
816 BackInsertIterator
result)
const
818 const DomItem containingBinding = currentItem.filterUp(
820 FilterUpOptions::ReturnOuter);
823 if (cursorAfterColon(containingBinding, positionInfo)) {
824 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
827 const QStringList names = currentItem.field(Fields::name).toString().split(u
'.');
831 LocalSymbolsTypes options;
832 options.setFlag(LocalSymbolsType::ObjectType);
833 suggestReachableTypes(positionInfo.itemAtPosition, options,
834 CompletionItemKind::Constructor,
result);
835 suggestSnippetsForRightHandSideOfBinding(positionInfo.itemAtPosition,
result);
842 if (cursorInFrontOfItem(containingBinding, positionInfo)) {
843 insideQmlObjectCompletion(currentItem.containingObject(), positionInfo,
result);
847 const DomItem containingObject = currentItem.qmlObject();
849 suggestBindingCompletion(positionInfo.itemAtPosition,
result);
852 suggestReachableTypes(positionInfo.itemAtPosition, LocalSymbolsType::ObjectType,
853 CompletionItemKind::Constructor,
result);
854 suggestSnippetsForLeftHandSideOfBinding(positionInfo.itemAtPosition,
result);
857void QQmlLSCompletion::insideImportCompletion(
const DomItem ¤tItem,
858 const QQmlLSCompletionPosition &positionInfo,
859 BackInsertIterator
result)
const
861 const DomItem containingFile = currentItem.containingFile();
862 insideImportCompletionHelper(containingFile, positionInfo,
result);
865 if (cursorInFrontOfItem(currentItem, positionInfo)) {
866 suggestReachableTypes(containingFile, LocalSymbolsType::ObjectType,
867 CompletionItemKind::Constructor,
result);
871void QQmlLSCompletion::insideQmlFileCompletion(
const DomItem ¤tItem,
872 const QQmlLSCompletionPosition &positionInfo,
873 BackInsertIterator
result)
const
875 const DomItem containingFile = currentItem.containingFile();
878 if (positionInfo.cursorPosition.atLineStart()) {
879 if (positionInfo.cursorPosition.base().isEmpty()) {
882 comp.label =
s.toUtf8();
883 comp.kind = int(CompletionItemKind::Keyword);
889 suggestReachableTypes(containingFile, LocalSymbolsType::ObjectType,
890 CompletionItemKind::Constructor,
result);
897void QQmlLSCompletion::suggestVariableDeclarationStatementCompletion(
905 snippet.insertText->append(
";");
906 snippet.label.append(
";");
916void QQmlLSCompletion::suggestCaseAndDefaultStatementCompletion(BackInsertIterator
result)
const
921 result =
makeSnippet(
"case value: { statements... }",
"case ${1:value}: {\n\t$0\n}");
938void QQmlLSCompletion::suggestContinueAndBreakStatementIfNeeded(
const DomItem &itemAtPosition,
939 BackInsertIterator
result)
const
941 bool alreadyInLabel =
false;
942 bool alreadyInSwitch =
false;
943 for (
DomItem current = itemAtPosition; current; current = current.directParent()) {
944 switch (current.internalKind()) {
945 case DomType::ScriptExpression:
949 case DomType::ScriptForStatement:
950 case DomType::ScriptForEachStatement:
951 case DomType::ScriptWhileStatement:
952 case DomType::ScriptDoWhileStatement: {
954 continueKeyword.label =
"continue";
955 continueKeyword.kind = int(CompletionItemKind::Keyword);
959 if (!alreadyInSwitch && !alreadyInLabel) {
961 breakKeyword.label =
"break";
962 breakKeyword.kind = int(CompletionItemKind::Keyword);
968 case DomType::ScriptSwitchStatement: {
970 if (alreadyInSwitch || alreadyInLabel)
972 alreadyInSwitch =
true;
975 breakKeyword.label =
"break";
976 breakKeyword.kind = int(CompletionItemKind::Keyword);
980 case DomType::ScriptLabelledStatement: {
982 if (alreadyInSwitch || alreadyInLabel)
984 alreadyInLabel =
true;
987 breakKeyword.label =
"break";
988 breakKeyword.kind = int(CompletionItemKind::Keyword);
1014void QQmlLSCompletion::suggestJSStatementCompletion(
const DomItem &itemAtPosition,
1015 BackInsertIterator
result)
const
1017 suggestJSExpressionCompletion(itemAtPosition,
result);
1023 suggestVariableDeclarationStatementCompletion(
result);
1031 result =
makeSnippet(
"do { statements } while (condition);",
"do {\n\t$1\n} while ($0);");
1034 result =
makeSnippet(
"while (condition) { statements...}",
"while ($1) {\n\t$0\n}");
1037 result =
makeSnippet(
"for (initializer; condition; increment) { statements... }",
1038 "for ($1;$2;$3) {\n\t$0\n}");
1041 result =
makeSnippet(
"for (property in object) { statements... }",
"for ($1 in $2) {\n\t$0\n}");
1044 result =
makeSnippet(
"for (element of array) { statements... }",
"for ($1 of $2) {\n\t$0\n}");
1048 "try {\n\t$1\n} catch($2) {\n\t$0\n}");
1052 "try {\n\t$1\n} finally {\n\t$0\n}");
1056 "try { statements... } catch(error) { statements... } finally { statements... }",
1057 "try {\n\t$1\n} catch($2) {\n\t$3\n} finally {\n\t$0\n}");
1060 for (
auto &&
view : {
"return"_ba,
"throw"_ba }) {
1063 item.kind = int(CompletionItemKind::Keyword);
1081 const DomType currentKind = itemAtPosition.internalKind();
1082 const DomType parentKind = itemAtPosition.directParent().internalKind();
1083 if (currentKind == DomType::ScriptCaseBlock || currentKind == DomType::ScriptCaseClause
1084 || currentKind == DomType::ScriptDefaultClause
1085 || (currentKind == DomType::List
1086 && (parentKind == DomType::ScriptCaseClause
1087 || parentKind == DomType::ScriptDefaultClause))) {
1088 suggestCaseAndDefaultStatementCompletion(
result);
1090 suggestContinueAndBreakStatementIfNeeded(itemAtPosition,
result);
1093void QQmlLSCompletion::insideForStatementCompletion(
const DomItem &parentForContext,
1094 const QQmlLSCompletionPosition &positionInfo,
1095 BackInsertIterator
result)
const
1104 if (betweenLocations(leftParenthesis, positionInfo, firstSemicolon)) {
1105 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1106 suggestVariableDeclarationStatementCompletion(
result,
1110 if (betweenLocations(firstSemicolon, positionInfo, secondSemicolon)
1111 || betweenLocations(secondSemicolon, positionInfo, rightParenthesis)) {
1112 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1116 if (afterLocation(rightParenthesis, positionInfo)) {
1117 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1122void QQmlLSCompletion::insideScriptLiteralCompletion(
const DomItem ¤tItem,
1123 const QQmlLSCompletionPosition &positionInfo,
1124 BackInsertIterator
result)
const
1127 if (positionInfo.cursorPosition.base().isEmpty()) {
1128 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1133void QQmlLSCompletion::insideCallExpression(
const DomItem ¤tItem,
1134 const QQmlLSCompletionPosition &positionInfo,
1135 BackInsertIterator
result)
const
1140 if (beforeLocation(positionInfo, leftParenthesis)) {
1141 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1144 if (betweenLocations(leftParenthesis, positionInfo, rightParenthesis)) {
1145 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1150void QQmlLSCompletion::insideIfStatement(
const DomItem ¤tItem,
1151 const QQmlLSCompletionPosition &positionInfo,
1152 BackInsertIterator
result)
const
1159 if (betweenLocations(leftParenthesis, positionInfo, rightParenthesis)) {
1160 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1163 if (betweenLocations(rightParenthesis, positionInfo, elseKeyword)) {
1164 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1167 if (afterLocation(elseKeyword, positionInfo)) {
1168 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1173void QQmlLSCompletion::insideReturnStatement(
const DomItem ¤tItem,
1174 const QQmlLSCompletionPosition &positionInfo,
1175 BackInsertIterator
result)
const
1180 if (afterLocation(returnKeyword, positionInfo)) {
1181 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1186void QQmlLSCompletion::insideWhileStatement(
const DomItem ¤tItem,
1187 const QQmlLSCompletionPosition &positionInfo,
1188 BackInsertIterator
result)
const
1194 if (betweenLocations(leftParenthesis, positionInfo, rightParenthesis)) {
1195 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1198 if (afterLocation(rightParenthesis, positionInfo)) {
1199 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1204void QQmlLSCompletion::insideDoWhileStatement(
const DomItem &parentForContext,
1205 const QQmlLSCompletionPosition &positionInfo,
1206 BackInsertIterator
result)
const
1214 if (betweenLocations(doKeyword, positionInfo, whileKeyword)) {
1215 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1218 if (betweenLocations(leftParenthesis, positionInfo, rightParenthesis)) {
1219 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1224void QQmlLSCompletion::insideForEachStatement(
const DomItem &parentForContext,
1225 const QQmlLSCompletionPosition &positionInfo,
1226 BackInsertIterator
result)
const
1234 if (betweenLocations(leftParenthesis, positionInfo, inOf)) {
1235 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1236 suggestVariableDeclarationStatementCompletion(
result);
1239 if (betweenLocations(inOf, positionInfo, rightParenthesis)) {
1240 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1244 if (afterLocation(rightParenthesis, positionInfo)) {
1245 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1250void QQmlLSCompletion::insideSwitchStatement(
const DomItem &parentForContext,
1251 const QQmlLSCompletionPosition positionInfo,
1252 BackInsertIterator
result)
const
1259 if (betweenLocations(leftParenthesis, positionInfo, rightParenthesis)) {
1260 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1265void QQmlLSCompletion::insideCaseClause(
const DomItem &parentForContext,
1266 const QQmlLSCompletionPosition &positionInfo,
1267 BackInsertIterator
result)
const
1274 if (betweenLocations(caseKeyword, positionInfo, colonToken)) {
1275 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1278 if (afterLocation(colonToken, positionInfo)) {
1279 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1289bool QQmlLSCompletion::isCaseOrDefaultBeforeCtx(
const DomItem ¤tClause,
1290 const QQmlLSCompletionPosition &positionInfo,
1300 if (afterLocation(
token, positionInfo))
1315QQmlLSCompletion::previousCaseOfCaseBlock(
const DomItem &parentForContext,
1316 const QQmlLSCompletionPosition &positionInfo)
const
1318 const DomItem caseClauses = parentForContext.field(Fields::caseClauses);
1319 for (
int i = 0;
i < caseClauses.indexes(); ++
i) {
1320 const DomItem currentClause = caseClauses.index(
i);
1322 return currentClause;
1326 const DomItem defaultClause = parentForContext.field(Fields::defaultClause);
1328 return parentForContext.field(Fields::defaultClause);
1330 const DomItem moreCaseClauses = parentForContext.field(Fields::moreCaseClauses);
1331 for (
int i = 0;
i < moreCaseClauses.indexes(); ++
i) {
1332 const DomItem currentClause = moreCaseClauses.index(
i);
1334 return currentClause;
1341void QQmlLSCompletion::insideCaseBlock(
const DomItem &parentForContext,
1342 const QQmlLSCompletionPosition &positionInfo,
1343 BackInsertIterator
result)
const
1350 if (!betweenLocations(leftBrace, positionInfo, rightBrace))
1355 if (
const auto previousCase = previousCaseOfCaseBlock(parentForContext, positionInfo)) {
1356 suggestJSStatementCompletion(previousCase,
result);
1361 suggestCaseAndDefaultStatementCompletion(
result);
1364void QQmlLSCompletion::insideDefaultClause(
const DomItem &parentForContext,
1365 const QQmlLSCompletionPosition &positionInfo,
1366 BackInsertIterator
result)
const
1372 if (afterLocation(colonToken, positionInfo)) {
1373 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1378void QQmlLSCompletion::insideBinaryExpressionCompletion(
1379 const DomItem &parentForContext,
const QQmlLSCompletionPosition &positionInfo,
1380 BackInsertIterator
result)
const
1386 if (beforeLocation(positionInfo, operatorLocation)) {
1387 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1390 if (afterLocation(operatorLocation, positionInfo)) {
1391 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1436void QQmlLSCompletion::insideScriptPattern(
const DomItem &parentForContext,
1437 const QQmlLSCompletionPosition &positionInfo,
1438 BackInsertIterator
result)
const
1444 if (!afterLocation(
equal, positionInfo))
1448 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1455void QQmlLSCompletion::insideVariableDeclarationEntry(
const DomItem &parentForContext,
1456 const QQmlLSCompletionPosition &positionInfo,
1457 BackInsertIterator
result)
const
1459 insideScriptPattern(parentForContext, positionInfo,
result);
1462void QQmlLSCompletion::insideThrowStatement(
const DomItem &parentForContext,
1463 const QQmlLSCompletionPosition &positionInfo,
1464 BackInsertIterator
result)
const
1470 if (afterLocation(throwKeyword, positionInfo)) {
1471 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1476void QQmlLSCompletion::insideLabelledStatement(
const DomItem &parentForContext,
1477 const QQmlLSCompletionPosition &positionInfo,
1478 BackInsertIterator
result)
const
1484 if (afterLocation(colon, positionInfo)) {
1485 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1501 for (
DomItem current =
context; current; current = current.directParent()) {
1502 if (current.internalKind() == DomType::ScriptLabelledStatement) {
1503 const QString label = current.field(Fields::label).value().toString();
1504 if (
label.isEmpty())
1506 CompletionItem
item;
1508 item.kind = int(CompletionItemKind::Value);
1511 }
else if (current.internalKind() == DomType::ScriptExpression) {
1519void QQmlLSCompletion::insideContinueStatement(
const DomItem &parentForContext,
1520 const QQmlLSCompletionPosition &positionInfo,
1521 BackInsertIterator
result)
const
1527 if (afterLocation(continueKeyword, positionInfo)) {
1533void QQmlLSCompletion::insideBreakStatement(
const DomItem &parentForContext,
1534 const QQmlLSCompletionPosition &positionInfo,
1535 BackInsertIterator
result)
const
1541 if (afterLocation(breakKeyword, positionInfo)) {
1547void QQmlLSCompletion::insideConditionalExpression(
const DomItem &parentForContext,
1548 const QQmlLSCompletionPosition &positionInfo,
1549 BackInsertIterator
result)
const
1556 if (beforeLocation(positionInfo, questionMark)) {
1557 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1560 if (betweenLocations(questionMark, positionInfo, colon)) {
1561 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1564 if (afterLocation(colon, positionInfo)) {
1565 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1570void QQmlLSCompletion::insideUnaryExpression(
const DomItem &parentForContext,
1571 const QQmlLSCompletionPosition &positionInfo,
1572 BackInsertIterator
result)
const
1578 if (afterLocation(operatorToken, positionInfo)) {
1579 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1584void QQmlLSCompletion::insidePostExpression(
const DomItem &parentForContext,
1585 const QQmlLSCompletionPosition &positionInfo,
1586 BackInsertIterator
result)
const
1592 if (beforeLocation(positionInfo, operatorToken)) {
1593 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1598void QQmlLSCompletion::insideParenthesizedExpression(
const DomItem &parentForContext,
1599 const QQmlLSCompletionPosition &positionInfo,
1600 BackInsertIterator
result)
const
1607 if (betweenLocations(leftParenthesis, positionInfo, rightParenthesis)) {
1608 suggestJSExpressionCompletion(positionInfo.itemAtPosition,
result);
1614 QDuplicateTracker<QString> *usedNames,
1615 BackInsertIterator
result)
const
1617 const auto keyValues = scope->
methods().asKeyValueRange();
1618 for (
const auto &[
name,
method] : keyValues) {
1620 ||
method.methodType() != QQmlJSMetaMethodType::Signal) {
1623 if (usedNames && usedNames->hasSeen(
name)) {
1629 completion.kind = int(CompletionItemKind::Method);
1638QList<CompletionItem>
1642 QList<CompletionItem>
result;
1643 collectCompletions(currentItem, contextStrings, std::back_inserter(
result));
1647void QQmlLSCompletion::collectCompletions(
const DomItem ¤tItem,
1649 BackInsertIterator
result)
const
1672 const QQmlLSCompletionPosition positionInfo{ currentItem, contextStrings };
1673 for (
DomItem currentParent = currentItem; currentParent;
1674 currentParent = currentParent.directParent()) {
1675 const DomType currentType = currentParent.internalKind();
1677 switch (currentType) {
1681 case DomType::Pragma:
1682 insidePragmaCompletion(currentParent, positionInfo,
result);
1684 case DomType::ScriptType: {
1685 if (currentParent.directParent().internalKind() == DomType::QmlObject) {
1686 insideQmlObjectCompletion(currentParent.directParent(), positionInfo,
result);
1690 LocalSymbolsTypes options;
1691 options.setFlag(LocalSymbolsType::ObjectType);
1692 options.setFlag(LocalSymbolsType::ValueType);
1693 suggestReachableTypes(currentItem, options, CompletionItemKind::Class,
result);
1696 case DomType::ScriptFormalParameter:
1699 case DomType::Binding:
1700 insideBindingCompletion(currentParent, positionInfo,
result);
1702 case DomType::Import:
1703 insideImportCompletion(currentParent, positionInfo,
result);
1705 case DomType::ScriptForStatement:
1706 insideForStatementCompletion(currentParent, positionInfo,
result);
1708 case DomType::ScriptBlockStatement:
1709 suggestJSStatementCompletion(positionInfo.itemAtPosition,
result);
1711 case DomType::QmlFile:
1712 insideQmlFileCompletion(currentParent, positionInfo,
result);
1714 case DomType::QmlObject:
1715 insideQmlObjectCompletion(currentParent, positionInfo,
result);
1717 case DomType::MethodInfo:
1720 case DomType::PropertyDefinition:
1721 insidePropertyDefinitionCompletion(currentParent, positionInfo,
result);
1723 case DomType::ScriptBinaryExpression:
1727 insideBinaryExpressionCompletion(currentParent, positionInfo,
result);
1729 case DomType::ScriptLiteral:
1730 insideScriptLiteralCompletion(currentParent, positionInfo,
result);
1732 case DomType::ScriptCallExpression:
1733 insideCallExpression(currentParent, positionInfo,
result);
1735 case DomType::ScriptIfStatement:
1736 insideIfStatement(currentParent, positionInfo,
result);
1738 case DomType::ScriptReturnStatement:
1739 insideReturnStatement(currentParent, positionInfo,
result);
1741 case DomType::ScriptWhileStatement:
1742 insideWhileStatement(currentParent, positionInfo,
result);
1744 case DomType::ScriptDoWhileStatement:
1745 insideDoWhileStatement(currentParent, positionInfo,
result);
1747 case DomType::ScriptForEachStatement:
1748 insideForEachStatement(currentParent, positionInfo,
result);
1750 case DomType::ScriptTryCatchStatement:
1770 case DomType::ScriptSwitchStatement:
1771 insideSwitchStatement(currentParent, positionInfo,
result);
1773 case DomType::ScriptCaseClause:
1774 insideCaseClause(currentParent, positionInfo,
result);
1776 case DomType::ScriptDefaultClause:
1779 insideDefaultClause(currentParent, positionInfo,
result);
1781 case DomType::ScriptCaseBlock:
1782 insideCaseBlock(currentParent, positionInfo,
result);
1784 case DomType::ScriptVariableDeclaration:
1789 case DomType::ScriptVariableDeclarationEntry:
1790 insideVariableDeclarationEntry(currentParent, positionInfo,
result);
1792 case DomType::ScriptProperty:
1795 case DomType::ScriptPattern:
1796 insideScriptPattern(currentParent, positionInfo,
result);
1798 case DomType::ScriptThrowStatement:
1799 insideThrowStatement(currentParent, positionInfo,
result);
1801 case DomType::ScriptLabelledStatement:
1802 insideLabelledStatement(currentParent, positionInfo,
result);
1804 case DomType::ScriptContinueStatement:
1805 insideContinueStatement(currentParent, positionInfo,
result);
1807 case DomType::ScriptBreakStatement:
1808 insideBreakStatement(currentParent, positionInfo,
result);
1810 case DomType::ScriptConditionalExpression:
1811 insideConditionalExpression(currentParent, positionInfo,
result);
1813 case DomType::ScriptUnaryExpression:
1814 insideUnaryExpression(currentParent, positionInfo,
result);
1816 case DomType::ScriptPostExpression:
1817 insidePostExpression(currentParent, positionInfo,
result);
1819 case DomType::ScriptParenthesizedExpression:
1820 insideParenthesizedExpression(currentParent, positionInfo,
result);
1825 case DomType::ScriptArray:
1826 case DomType::ScriptObject:
1827 case DomType::ScriptElision:
1828 case DomType::ScriptArrayEntry:
1838 qCDebug(QQmlLSUtilsLog) <<
"No completion was found for current request.";
1844 const auto keys = pluginLoader.metaDataKeys();
1846 auto instance = std::unique_ptr<QQmlLSPlugin>(
1847 qobject_cast<QQmlLSPlugin *>(pluginLoader.instance(
i)));
1850 if (
auto completionInstance = instance->createCompletionPlugin())
1851 m_plugins.push_back(std::move(completionInstance));
1860 BackInsertIterator
result)
const
1862 for (
const auto &plugin : m_plugins) {
1868void QQmlLSCompletion::suggestSnippetsForLeftHandSideOfBinding(
const DomItem &itemAtPosition,
1869 BackInsertIterator
result)
const
1873 p->suggestSnippetsForLeftHandSideOfBinding(itemAtPosition,
result);
1878void QQmlLSCompletion::suggestSnippetsForRightHandSideOfBinding(
const DomItem &itemAtPosition,
1879 BackInsertIterator
result)
const
1883 p->suggestSnippetsForRightHandSideOfBinding(itemAtPosition,
result);
static JNINativeMethod methods[]
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString toString(const QString &defaultValue={}) const
Returns the string value stored in this QCborValue, if it is of the string type.
Tracks the types for the QmlCompiler.
QHash< QString, QQmlJSMetaMethod > methods() const
Returns all methods visible from this scope including those of base types and extensions.
QQmlJSScope::Ptr parentScope()
bool isReferenceType() const
AccessSemantics accessSemantics() const
QQmlJSMetaEnum enumeration(const QString &name) const
QQmlJSScope::ConstPtr attachedType() const
QQmlJSMetaProperty property(const QString &name) const
Represents a consistent set of types organized in modules, it is the top level of the DOM.
DomItem field(QStringView name) const
static FileLocations::Tree treeOf(const DomItem &)
A QmlFile, when loaded in a DomEnvironment that has the DomCreationOption::WithSemanticAnalysis,...
QQmlLSCompletion provides completions for all kinds of QML and JS constructs.
QLspSpecification::CompletionItem CompletionItem
QList< CompletionItem > completions(const DomItem ¤tItem, const CompletionContextStrings &ctx) const
static CompletionItem makeSnippet(QUtf8StringView qualifier, QUtf8StringView label, QUtf8StringView insertText)
QQmlLSCompletion(const QFactoryLoader &pluginLoader)
std::back_insert_iterator< QList< CompletionItem > > BackInsertIterator
static std::optional< QQmlLSUtilsExpressionType > resolveExpressionType(const DomItem &item, QQmlLSUtilsResolveOptions)
static QString qualifiersFrom(const DomItem &el)
static bool isFieldMemberExpression(const DomItem &item)
static bool isFieldMemberAccess(const DomItem &item)
static QString signalNameToHandlerName(QAnyStringView signal)
\inmodule QtCore \reentrant
constexpr QStringView sliced(qsizetype pos) const noexcept
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
QString first(qsizetype n) const &
QChar * data()
Returns a pointer to the data stored in the QString.
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & append(QChar c)
QByteArray toUtf8() const &
QSet< QString >::iterator it
@ FirstSemicolonTokenRegion
@ QuestionMarkTokenRegion
Combined button and popup list for selecting options.
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLenum GLsizei GLsizei GLint * values
[15]
GLenum GLenum GLsizei const GLuint * ids
GLuint GLsizei const GLchar * label
[43]
static qreal component(const QPointF &point, unsigned int i)
void collectFromAllJavaScriptParents(const F &&f, const QQmlJSScope::ConstPtr &scope)
static const QQmlJSScope * resolve(const QQmlJSScope *current, const QStringList &names)
static void collectLabels(const DomItem &context, QQmlLSCompletion::BackInsertIterator result)
static bool testScopeSymbol(const QQmlJSScope::ConstPtr &scope, LocalSymbolsTypes options, CompletionItemKind kind)
static const QMap< QString, QList< QString > > valuesForPragmas
Mapping from pragma names to allowed pragma values.
@ ResolveActualTypeForFieldMemberExpression
QBasicUtf8StringView< false > QUtf8StringView
static bool equal(const QChar *a, int l, const char *b)
char * toString(const MyType &t)
[31]