| 1 | // Copyright (C) 2024 The Qt Company Ltd. | 
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
| 3 |  | 
| 4 | #ifndef QQMLLSCOMPLETION_H | 
| 5 | #define QQMLLSCOMPLETION_H | 
| 6 |  | 
| 7 | // | 
| 8 | //  W A R N I N G | 
| 9 | //  ------------- | 
| 10 | // | 
| 11 | // This file is not part of the Qt API.  It exists purely as an | 
| 12 | // implementation detail.  This header file may change from version to | 
| 13 | // version without notice, or even be removed. | 
| 14 | // | 
| 15 | // We mean it. | 
| 16 | // | 
| 17 |  | 
| 18 | #include "qqmlcompletioncontextstrings_p.h" | 
| 19 | #include "qqmllsutils_p.h" | 
| 20 | #include "qqmllsplugin_p.h" | 
| 21 |  | 
| 22 | #include <QtLanguageServer/private/qlanguageserverspectypes_p.h> | 
| 23 | #include <QtQmlDom/private/qqmldomexternalitems_p.h> | 
| 24 | #include <QtQmlDom/private/qqmldomtop_p.h> | 
| 25 | #include <QtCore/private/qduplicatetracker_p.h> | 
| 26 | #include <QtCore/private/qfactoryloader_p.h> | 
| 27 | #include <QtCore/qpluginloader.h> | 
| 28 | #include <QtCore/qxpfunctional.h> | 
| 29 |  | 
| 30 | QT_BEGIN_NAMESPACE | 
| 31 |  | 
| 32 | Q_DECLARE_LOGGING_CATEGORY(QQmlLSCompletionLog) | 
| 33 |  | 
| 34 |  | 
| 35 | class QQmlLSCompletion | 
| 36 | { | 
| 37 |     using DomItem = QQmlJS::Dom::DomItem; | 
| 38 | public: | 
| 39 |     enum class ImportCompletionType { None, Module, Version }; | 
| 40 |     enum AppendOption { AppendSemicolon, AppendNothing }; | 
| 41 |  | 
| 42 |     QQmlLSCompletion(const QFactoryLoader &pluginLoader); | 
| 43 |  | 
| 44 |     using CompletionItem = QLspSpecification::CompletionItem; | 
| 45 |     using BackInsertIterator = std::back_insert_iterator<QList<CompletionItem>>; | 
| 46 |     QList<CompletionItem> completions(const DomItem ¤tItem, | 
| 47 |                                       const CompletionContextStrings &ctx) const; | 
| 48 |  | 
| 49 |     static CompletionItem makeSnippet(QUtf8StringView qualifier, QUtf8StringView label, | 
| 50 |                                       QUtf8StringView insertText); | 
| 51 |  | 
| 52 |     static CompletionItem makeSnippet(QUtf8StringView label, QUtf8StringView insertText); | 
| 53 |  | 
| 54 | private: | 
| 55 |     struct QQmlLSCompletionPosition | 
| 56 |     { | 
| 57 |         DomItem itemAtPosition; | 
| 58 |         CompletionContextStrings cursorPosition; | 
| 59 |         qsizetype offset() const { return cursorPosition.offset(); } | 
| 60 |     }; | 
| 61 |  | 
| 62 |     void collectCompletions(const DomItem ¤tItem, const CompletionContextStrings &ctx, | 
| 63 |                             BackInsertIterator result) const; | 
| 64 |  | 
| 65 |     bool betweenLocations(QQmlJS::SourceLocation left, const QQmlLSCompletionPosition &positionInfo, | 
| 66 |                           QQmlJS::SourceLocation right) const; | 
| 67 |     bool afterLocation(QQmlJS::SourceLocation left, | 
| 68 |                        const QQmlLSCompletionPosition &positionInfo) const; | 
| 69 |     bool beforeLocation(const QQmlLSCompletionPosition &ctx, QQmlJS::SourceLocation right) const; | 
| 70 |     bool ctxBeforeStatement(const QQmlLSCompletionPosition &positionInfo, | 
| 71 |                             const DomItem &parentForContext, | 
| 72 |                             QQmlJS::Dom::FileLocationRegion firstRegion) const; | 
| 73 |     bool isCaseOrDefaultBeforeCtx(const DomItem ¤tClause, | 
| 74 |                                   const QQmlLSCompletionPosition &positionInfo, | 
| 75 |                                   QQmlJS::Dom::FileLocationRegion keywordRegion) const; | 
| 76 |     DomItem previousCaseOfCaseBlock(const DomItem &parentForContext, | 
| 77 |                                     const QQmlLSCompletionPosition &positionInfo) const; | 
| 78 |  | 
| 79 |     void idsCompletions(const DomItem &component, BackInsertIterator it) const; | 
| 80 |  | 
| 81 |     void suggestReachableTypes(const DomItem &context, | 
| 82 |                                QQmlJS::Dom::LocalSymbolsTypes typeCompletionType, | 
| 83 |                                QLspSpecification::CompletionItemKind kind, | 
| 84 |                                BackInsertIterator it) const; | 
| 85 |  | 
| 86 |     void suggestJSStatementCompletion(const DomItem ¤tItem, BackInsertIterator it) const; | 
| 87 |     void suggestCaseAndDefaultStatementCompletion(BackInsertIterator it) const; | 
| 88 |     void suggestVariableDeclarationStatementCompletion( | 
| 89 |             BackInsertIterator it, AppendOption option = AppendSemicolon) const; | 
| 90 |  | 
| 91 |     void suggestEnumerationsAndEnumerationValues(const QQmlJSScope::ConstPtr &scope, | 
| 92 |                                                  const QString &enumName, | 
| 93 |                                                  QDuplicateTracker<QString> &usedNames, | 
| 94 |                                                  BackInsertIterator result) const; | 
| 95 |     DomItem ownerOfQualifiedExpression(const DomItem &qualifiedExpression) const; | 
| 96 |     void suggestJSExpressionCompletion(const DomItem &context, BackInsertIterator it) const; | 
| 97 |  | 
| 98 |     void suggestBindingCompletion(const DomItem &itemAtPosition, BackInsertIterator it) const; | 
| 99 |  | 
| 100 |     void insideImportCompletionHelper(const DomItem &file, | 
| 101 |                                       const QQmlLSCompletionPosition &positionInfo, | 
| 102 |                                       BackInsertIterator it) const; | 
| 103 |  | 
| 104 |     void jsIdentifierCompletion(const QQmlJSScope::ConstPtr &scope, | 
| 105 |                                 QDuplicateTracker<QString> *usedNames, BackInsertIterator it) const; | 
| 106 |  | 
| 107 |     void methodCompletion(const QQmlJSScope::ConstPtr &scope, QDuplicateTracker<QString> *usedNames, | 
| 108 |                           BackInsertIterator it) const; | 
| 109 |     void propertyCompletion(const QQmlJSScope::ConstPtr &scope, | 
| 110 |                             QDuplicateTracker<QString> *usedNames, BackInsertIterator it) const; | 
| 111 |     void enumerationCompletion(const QQmlJSScope::ConstPtr &scope, | 
| 112 |                                QDuplicateTracker<QString> *usedNames, BackInsertIterator it) const; | 
| 113 |     void enumerationValueCompletionHelper(const QStringList &enumeratorKeys, | 
| 114 |                                           BackInsertIterator it) const; | 
| 115 |  | 
| 116 |     void enumerationValueCompletion(const QQmlJSScope::ConstPtr &scope, | 
| 117 |                                     const QString &enumeratorName, BackInsertIterator it) const; | 
| 118 |  | 
| 119 |     static bool cursorInFrontOfItem(const DomItem &parentForContext, | 
| 120 |                                     const QQmlLSCompletionPosition &positionInfo); | 
| 121 |     static bool cursorAfterColon(const DomItem ¤tItem, | 
| 122 |                                  const QQmlLSCompletionPosition &positionInfo); | 
| 123 |     void insidePragmaCompletion(QQmlJS::Dom::DomItem currentItem, | 
| 124 |                                 const QQmlLSCompletionPosition &positionInfo, | 
| 125 |                                 BackInsertIterator it) const; | 
| 126 |     void insideQmlObjectCompletion(const DomItem &parentForContext, | 
| 127 |                                    const QQmlLSCompletionPosition &positionInfo, | 
| 128 |                                    BackInsertIterator it) const; | 
| 129 |     void insidePropertyDefinitionCompletion(const DomItem ¤tItem, | 
| 130 |                                             const QQmlLSCompletionPosition &positionInfo, | 
| 131 |                                             BackInsertIterator it) const; | 
| 132 |     void insideBindingCompletion(const DomItem ¤tItem, | 
| 133 |                                  const QQmlLSCompletionPosition &positionInfo, | 
| 134 |                                  BackInsertIterator it) const; | 
| 135 |     void insideImportCompletion(const DomItem ¤tItem, | 
| 136 |                                 const QQmlLSCompletionPosition &positionInfo, | 
| 137 |                                 BackInsertIterator it) const; | 
| 138 |     void insideQmlFileCompletion(const DomItem ¤tItem, | 
| 139 |                                  const QQmlLSCompletionPosition &positionInfo, | 
| 140 |                                  BackInsertIterator it) const; | 
| 141 |     void suggestContinueAndBreakStatementIfNeeded(const DomItem &itemAtPosition, | 
| 142 |                                                   BackInsertIterator it) const; | 
| 143 |     void insideScriptLiteralCompletion(const DomItem ¤tItem, | 
| 144 |                                        const QQmlLSCompletionPosition &positionInfo, | 
| 145 |                                        BackInsertIterator it) const; | 
| 146 |     void insideCallExpression(const DomItem ¤tItem, | 
| 147 |                               const QQmlLSCompletionPosition &positionInfo, | 
| 148 |                               BackInsertIterator it) const; | 
| 149 |     void insideIfStatement(const DomItem ¤tItem, const QQmlLSCompletionPosition &positionInfo, | 
| 150 |                            BackInsertIterator it) const; | 
| 151 |     void insideReturnStatement(const DomItem ¤tItem, | 
| 152 |                                const QQmlLSCompletionPosition &positionInfo, | 
| 153 |                                BackInsertIterator it) const; | 
| 154 |     void insideWhileStatement(const DomItem ¤tItem, | 
| 155 |                               const QQmlLSCompletionPosition &positionInfo, | 
| 156 |                               BackInsertIterator it) const; | 
| 157 |     void insideDoWhileStatement(const DomItem &parentForContext, | 
| 158 |                                 const QQmlLSCompletionPosition &positionInfo, | 
| 159 |                                 BackInsertIterator it) const; | 
| 160 |     void insideForStatementCompletion(const DomItem &parentForContext, | 
| 161 |                                       const QQmlLSCompletionPosition &positionInfo, | 
| 162 |                                       BackInsertIterator it) const; | 
| 163 |     void insideForEachStatement(const DomItem &parentForContext, | 
| 164 |                                 const QQmlLSCompletionPosition &positionInfo, | 
| 165 |                                 BackInsertIterator it) const; | 
| 166 |     void insideSwitchStatement(const DomItem &parentForContext, | 
| 167 |                                const QQmlLSCompletionPosition positionInfo, | 
| 168 |                                BackInsertIterator it) const; | 
| 169 |     void insideCaseClause(const DomItem &parentForContext, | 
| 170 |                           const QQmlLSCompletionPosition &positionInfo, | 
| 171 |                           BackInsertIterator it) const; | 
| 172 |     void insideCaseBlock(const DomItem &parentForContext, | 
| 173 |                          const QQmlLSCompletionPosition &positionInfo, BackInsertIterator it) const; | 
| 174 |     void insideDefaultClause(const DomItem &parentForContext, | 
| 175 |                              const QQmlLSCompletionPosition &positionInfo, | 
| 176 |                              BackInsertIterator it) const; | 
| 177 |     void insideBinaryExpressionCompletion(const DomItem &parentForContext, | 
| 178 |                                           const QQmlLSCompletionPosition &positionInfo, | 
| 179 |                                           BackInsertIterator it) const; | 
| 180 |     void insideScriptPattern(const DomItem &parentForContext, | 
| 181 |                              const QQmlLSCompletionPosition &positionInfo, | 
| 182 |                              BackInsertIterator it) const; | 
| 183 |     void insideVariableDeclarationEntry(const DomItem &parentForContext, | 
| 184 |                                         const QQmlLSCompletionPosition &positionInfo, | 
| 185 |                                         BackInsertIterator it) const; | 
| 186 |     void insideThrowStatement(const DomItem &parentForContext, | 
| 187 |                               const QQmlLSCompletionPosition &positionInfo, | 
| 188 |                               BackInsertIterator it) const; | 
| 189 |     void insideLabelledStatement(const DomItem &parentForContext, | 
| 190 |                                  const QQmlLSCompletionPosition &positionInfo, | 
| 191 |                                  BackInsertIterator it) const; | 
| 192 |     void insideContinueStatement(const DomItem &parentForContext, | 
| 193 |                                  const QQmlLSCompletionPosition &positionInfo, | 
| 194 |                                  BackInsertIterator it) const; | 
| 195 |     void insideBreakStatement(const DomItem &parentForContext, | 
| 196 |                               const QQmlLSCompletionPosition &positionInfo, | 
| 197 |                               BackInsertIterator it) const; | 
| 198 |     void insideConditionalExpression(const DomItem &parentForContext, | 
| 199 |                                      const QQmlLSCompletionPosition &positionInfo, | 
| 200 |                                      BackInsertIterator it) const; | 
| 201 |     void insideUnaryExpression(const DomItem &parentForContext, | 
| 202 |                                const QQmlLSCompletionPosition &positionInfo, | 
| 203 |                                BackInsertIterator it) const; | 
| 204 |     void insidePostExpression(const DomItem &parentForContext, | 
| 205 |                               const QQmlLSCompletionPosition &positionInfo, | 
| 206 |                               BackInsertIterator it) const; | 
| 207 |     void insideParenthesizedExpression(const DomItem &parentForContext, | 
| 208 |                                        const QQmlLSCompletionPosition &positionInfo, | 
| 209 |                                        BackInsertIterator it) const; | 
| 210 |     void insideTemplateLiteral(const DomItem &parentForContext, | 
| 211 |                                const QQmlLSCompletionPosition &positionInfo, | 
| 212 |                                BackInsertIterator it) const; | 
| 213 |     void insideNewExpression(const DomItem &parentForContext, | 
| 214 |                              const QQmlLSCompletionPosition &positionInfo, | 
| 215 |                              BackInsertIterator it) const; | 
| 216 |     void insideNewMemberExpression(const DomItem &parentForContext, | 
| 217 |                                    const QQmlLSCompletionPosition &positionInfo, | 
| 218 |                                    BackInsertIterator it) const; | 
| 219 |     void signalHandlerCompletion(const QQmlJSScope::ConstPtr &scope, | 
| 220 |                                  QDuplicateTracker<QString> *usedNames, | 
| 221 |                                  BackInsertIterator it) const; | 
| 222 |  | 
| 223 |     void suggestSnippetsForLeftHandSideOfBinding(const DomItem &items, | 
| 224 |                                                  BackInsertIterator result) const; | 
| 225 |  | 
| 226 |     void suggestSnippetsForRightHandSideOfBinding(const DomItem &items, | 
| 227 |                                                   BackInsertIterator result) const; | 
| 228 |  | 
| 229 | private: | 
| 230 |     using CompletionFromPluginFunction = void(QQmlLSCompletionPlugin *plugin, | 
| 231 |                                               BackInsertIterator result); | 
| 232 |     void collectFromPlugins(const qxp::function_ref<CompletionFromPluginFunction> f, | 
| 233 |                             BackInsertIterator result) const; | 
| 234 |  | 
| 235 |     QStringList m_loadPaths; | 
| 236 |  | 
| 237 |     std::vector<std::unique_ptr<QQmlLSCompletionPlugin>> m_plugins; | 
| 238 | }; | 
| 239 |  | 
| 240 | QT_END_NAMESPACE | 
| 241 |  | 
| 242 | #endif // QQMLLSCOMPLETION_H | 
| 243 |  |