7#include <private/qqmljstyperesolver_p.h>
9using namespace Qt::StringLiterals;
13QQmlJSLookupSignaturesRecorder::QQmlJSLookupSignaturesRecorder(
14 const QString ¤tFilePath,
const QQmlJSTypeResolver *typeResolver)
15 : m_currentFilePath(currentFilePath), m_typeResolver(typeResolver)
17 Q_ASSERT(!m_currentFilePath.isEmpty());
18 Q_ASSERT(m_typeResolver);
21#define CHECKED_OPT_ASSIGN(var, expr)
23 const auto opt = expr;
29std::optional<QQmlPrivate::AOTLookupValidation::Type>
30QQmlJSLookupSignaturesRecorder::type(
const QQmlJSScope::ConstPtr &type)
32 using namespace QQmlPrivate::AOTLookupValidation;
34 QQmlPrivate::AOTLookupValidation::Type res;
35 if (!type->isComposite()) {
36 if (type->accessSemantics() == QQmlSA::AccessSemantics::Value && type->isSelfExtension()) {
37 res.name = type->internalName();
38 res.icNameOrExtensionTypeName = type->extensionTypeName();
40 res.name = type->internalName();
46 res.isComposite = IsComposite::Yes;
47 if (isUnnamedCompositeType(type)) {
52 if (!type->baseType()) {
53 const QString msg =
"unknown base type for composite object at %1:%2"_L1;
54 m_rejectMessage = msg.arg(type->filePath(), QString::number(type->lineNumber()));
57 return QQmlJSLookupSignaturesRecorder::type(type->baseType());
60 QQmlJSScope::ConstPtr root = type;
61 while (!root->isFileRootComponent())
62 root = root->parentScope();
64 bool isFileBeingCompiled = root->filePath() == m_typeResolver->logger()->filePath();
66 Q_ASSERT(!root->internalName().isEmpty());
67 res.module = isFileBeingCompiled ? s_thisCuModule : root->moduleName();
68 res.name = isFileBeingCompiled ? s_thisCuType : root->internalName();
70 if (type->isInlineComponent()) {
71 res.isInlineComponent = IsIC::Yes;
72 res.icNameOrExtensionTypeName = *type->inlineComponentName();
79bool QQmlJSLookupSignaturesRecorder::cantDesync(
const QQmlJSScope::ConstPtr &type)
const
81 Q_ASSERT(!m_typeResolver->logger()->filePath().isEmpty());
83 return type->filePath() == m_typeResolver->logger()->filePath();
86bool QQmlJSLookupSignaturesRecorder::safeBase(
const QQmlJSScope::ConstPtr &base)
const
88 return base == m_typeResolver->varType() || base == m_typeResolver->jsValueType()
89 || base->inherits(m_typeResolver->qmlPropertyMapType());
92bool QQmlJSLookupSignaturesRecorder::isUnnamedCompositeType(
const QQmlJSScope::ConstPtr &type)
const
94 return type->isComposite() && !type->isFileRootComponent() && !type->isInlineComponent();
99 return m.otherMethodIndex() == QQmlJSMetaMethod::RelativeFunctionIndex::Invalid
100 ? m.methodIndex() : m.otherMethodIndex();
106 const auto &ms = type->ownMethods();
107 return std::count_if(ms.cbegin(), ms.cend(), [&](
const QQmlJSMetaMethod &m) {
108 Q_ASSERT(m.isConstructor() || methodIndex(m) != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
109 return m.methodType() != QQmlSA::MethodType::Signal && !m.isConstructor()
110 &&
int(methodIndex(m)) < index;
117 const auto &ms = type->ownMethods();
118 return std::count_if(ms.cbegin(), ms.cend(), [&](
const QQmlJSMetaMethod &m) {
119 Q_ASSERT(m.isConstructor() || methodIndex(m) != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
120 return m.methodType() == QQmlSA::MethodType::Signal &&
int(methodIndex(m)) > index;
127 const auto &ps = type->ownProperties();
128 return std::count_if(ps.cbegin(), ps.cend(), [&](
const auto &p) {
129 return p.isAlias() && p.index() < index;
136 const auto &ps = type->ownProperties();
137 return std::count_if(ps.cbegin(), ps.cend(), [&](
const auto &p) {
138 return !p.isAlias() && p.index() > index;
142bool QQmlJSLookupSignaturesRecorder::recordPropertyLookup(
const QQmlJSScope::ConstPtr &base,
143 const QQmlJSMetaProperty &property)
145 using namespace QQmlPrivate::AOTLookupValidation;
147 const QString &name = property.propertyName();
148 const auto [owner, extensionSpecifier] = QQmlJSScope::ownerOfProperty(base, name);
149 if (base->isScript() || safeBase(base) || cantDesync(owner))
160 if (isUnnamedCompositeType(base) && owner == base)
163 PropertySignature propertySignature;
167 propertySignature.relativeIndex = property.isAlias()
168 ? property.index() + ownRegularPropertyCountAfterIndex(owner, property.index())
169 : property.index() - ownAliasCountBeforeIndex(owner, property.index());
173 lookup.member = name;
175 m_signatures.insert(lookup, propertySignature);
179bool QQmlJSLookupSignaturesRecorder::recordMethodLookup(
const QQmlJSScope::ConstPtr &base,
180 const QQmlJSMetaMethod &method)
182 using namespace QQmlPrivate::AOTLookupValidation;
184 const QString &name = method.methodName();
185 const auto [owner, extensionSpecifier] = QQmlJSScope::ownerOfMethod(base, name);
186 if (base->isScript() || safeBase(base) || cantDesync(owner))
190 if (isUnnamedCompositeType(base) && owner == base)
194 if (name == QStringLiteral(
"destroy") || name == QStringLiteral(
"toString"))
197 MethodSignature methodSignature;
199 if (method.methodType() == QQmlSA::MethodType::Signal) {
200 methodSignature.isSignal = IsSignal::Yes;
201 int index =
int(methodIndex(method));
202 methodSignature.relativeIndex = index - ownRegularMethodCountBeforeIndex(owner, index);
204 methodSignature.isSignal = IsSignal::No;
205 int index =
int(methodIndex(method));
206 methodSignature.relativeIndex = index + ownSignalCountAfterIndex(owner, index);
209 methodSignature.types.push_back({});
211 for (
const auto ¶m : method.parameters()) {
212 methodSignature.paramNames.push_back(param.name());
213 methodSignature.types.push_back({});
219 lookup.member = name;
221 m_signatures.insert(lookup, methodSignature);
225bool QQmlJSLookupSignaturesRecorder::recordEnumKeyLookup(
const QQmlJSScope::ConstPtr &base,
226 const QQmlJSMetaEnum &metaEnum,
227 const QString &keyName)
229 using namespace QQmlPrivate::AOTLookupValidation;
231 const auto [owner, extensionSpecifier] = QQmlJSScope::ownerOfEnum(base, metaEnum.name());
232 if (base->isScript() || safeBase(base) || cantDesync(owner))
235 EnumKeySignature enumSignature;
237 enumSignature.value = quint64(metaEnum.value(keyName));
238 if (metaEnum.isFlag())
239 enumSignature.isFlag = IsFlag::Yes;
243 lookup.member = keyName;
244 lookup.enumName = metaEnum.name();
245 m_signatures.insert(lookup, enumSignature);
static int ownAliasCountBeforeIndex(const QQmlJSScope::ConstPtr &type, int index)
static int ownRegularMethodCountBeforeIndex(const QQmlJSScope::ConstPtr &type, int index)
static int ownRegularPropertyCountAfterIndex(const QQmlJSScope::ConstPtr &type, int index)
#define CHECKED_OPT_ASSIGN(var, expr)
static QQmlJSMetaMethod::RelativeFunctionIndex methodIndex(const QQmlJSMetaMethod &m)
static int ownSignalCountAfterIndex(const QQmlJSScope::ConstPtr &type, int index)