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);
21QQmlPrivate::AOTLookupValidation::Type QQmlJSLookupSignaturesRecorder::type(
22 const QQmlJSScope::ConstPtr &type)
24 using namespace QQmlPrivate::AOTLookupValidation;
26 QQmlPrivate::AOTLookupValidation::Type res;
27 if (!type->isComposite()) {
28 if (type->accessSemantics() == QQmlSA::AccessSemantics::Value && type->isSelfExtension()) {
29 res.name = type->internalName();
30 res.icNameOrExtensionTypeName = type->extensionTypeName();
32 res.name = type->internalName();
38 res.isComposite = IsComposite::Yes;
39 if (isUnnamedCompositeType(type)) {
44 Q_ASSERT(type->baseType());
45 return QQmlJSLookupSignaturesRecorder::type(type->baseType());
48 QQmlJSScope::ConstPtr root = type;
49 while (!root->isFileRootComponent())
50 root = root->parentScope();
52 bool isFileBeingCompiled = root->filePath() == m_typeResolver->logger()->filePath();
54 Q_ASSERT(!root->internalName().isEmpty());
55 res.module = isFileBeingCompiled ? s_thisCuModule : root->moduleName();
56 res.name = isFileBeingCompiled ? s_thisCuType : root->internalName();
58 if (type->isInlineComponent()) {
59 res.isInlineComponent = IsIC::Yes;
60 res.icNameOrExtensionTypeName = *type->inlineComponentName();
67bool QQmlJSLookupSignaturesRecorder::cantDesync(
const QQmlJSScope::ConstPtr &type)
const
69 Q_ASSERT(!m_typeResolver->logger()->filePath().isEmpty());
71 return type->filePath() == m_typeResolver->logger()->filePath();
74bool QQmlJSLookupSignaturesRecorder::safeBase(
const QQmlJSScope::ConstPtr &base)
const
76 return base == m_typeResolver->varType() || base == m_typeResolver->jsValueType()
77 || base->inherits(m_typeResolver->qmlPropertyMapType());
80bool QQmlJSLookupSignaturesRecorder::isUnnamedCompositeType(
const QQmlJSScope::ConstPtr &type)
const
82 return type->isComposite() && !type->isFileRootComponent() && !type->isInlineComponent();
87 return m.otherMethodIndex() == QQmlJSMetaMethod::RelativeFunctionIndex::Invalid
88 ? m.methodIndex() : m.otherMethodIndex();
94 const auto &ms = type->ownMethods();
95 return std::count_if(ms.cbegin(), ms.cend(), [&](
const QQmlJSMetaMethod &m) {
96 Q_ASSERT(m.isConstructor() || methodIndex(m) != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
97 return m.methodType() != QQmlSA::MethodType::Signal && !m.isConstructor()
98 &&
int(methodIndex(m)) < index;
105 const auto &ms = type->ownMethods();
106 return std::count_if(ms.cbegin(), ms.cend(), [&](
const QQmlJSMetaMethod &m) {
107 Q_ASSERT(m.isConstructor() || methodIndex(m) != QQmlJSMetaMethod::RelativeFunctionIndex::Invalid);
108 return m.methodType() == QQmlSA::MethodType::Signal &&
int(methodIndex(m)) > index;
115 const auto &ps = type->ownProperties();
116 return std::count_if(ps.cbegin(), ps.cend(), [&](
const auto &p) {
117 return p.isAlias() && p.index() < index;
124 const auto &ps = type->ownProperties();
125 return std::count_if(ps.cbegin(), ps.cend(), [&](
const auto &p) {
126 return !p.isAlias() && p.index() > index;
130void QQmlJSLookupSignaturesRecorder::recordPropertyLookup(
const QQmlJSScope::ConstPtr &base,
131 const QQmlJSMetaProperty &property)
133 using namespace QQmlPrivate::AOTLookupValidation;
135 const QString &name = property.propertyName();
136 const auto [owner, extensionSpecifier] = QQmlJSScope::ownerOfProperty(base, name);
137 if (base->isScript() || safeBase(base) || cantDesync(owner))
148 if (isUnnamedCompositeType(base) && owner == base)
151 PropertySignature propertySignature;
152 propertySignature.type = type(property.type());
155 propertySignature.relativeIndex = property.isAlias()
156 ? property.index() + ownRegularPropertyCountAfterIndex(owner, property.index())
157 : property.index() - ownAliasCountBeforeIndex(owner, property.index());
160 lookup.base = type(base);
161 lookup.member = name;
163 m_signatures.insert(lookup, propertySignature);
166void QQmlJSLookupSignaturesRecorder::recordMethodLookup(
const QQmlJSScope::ConstPtr &base,
167 const QQmlJSMetaMethod &method)
169 using namespace QQmlPrivate::AOTLookupValidation;
171 const QString &name = method.methodName();
172 const auto [owner, extensionSpecifier] = QQmlJSScope::ownerOfMethod(base, name);
173 if (base->isScript() || safeBase(base) || cantDesync(owner))
177 if (isUnnamedCompositeType(base) && owner == base)
181 if (name == QStringLiteral(
"destroy") || name == QStringLiteral(
"toString"))
184 MethodSignature methodSignature;
186 if (method.methodType() == QQmlSA::MethodType::Signal) {
187 methodSignature.isSignal = IsSignal::Yes;
188 int index =
int(methodIndex(method));
189 methodSignature.relativeIndex = index - ownRegularMethodCountBeforeIndex(owner, index);
191 methodSignature.isSignal = IsSignal::No;
192 int index =
int(methodIndex(method));
193 methodSignature.relativeIndex = index + ownSignalCountAfterIndex(owner, index);
196 methodSignature.types.push_back(type(method.returnType()));
197 for (
const auto ¶m : method.parameters()) {
198 methodSignature.paramNames.push_back(param.name());
199 methodSignature.types.push_back(type(param.type()));
203 lookup.base = type(base);
204 lookup.member = name;
206 m_signatures.insert(lookup, methodSignature);
209void QQmlJSLookupSignaturesRecorder::recordEnumKeyLookup(
const QQmlJSScope::ConstPtr &base,
210 const QQmlJSMetaEnum &metaEnum,
211 const QString &keyName)
213 using namespace QQmlPrivate::AOTLookupValidation;
215 const auto [owner, extensionSpecifier] = QQmlJSScope::ownerOfEnum(base, metaEnum.name());
216 if (base->isScript() || safeBase(base) || cantDesync(owner))
219 EnumKeySignature enumSignature;
221 enumSignature.value = quint64(metaEnum.value(keyName));
222 if (metaEnum.isFlag())
223 enumSignature.isFlag = IsFlag::Yes;
226 lookup.base = type(base);
227 lookup.member = keyName;
228 lookup.enumName = metaEnum.name();
229 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)
static QQmlJSMetaMethod::RelativeFunctionIndex methodIndex(const QQmlJSMetaMethod &m)
static int ownSignalCountAfterIndex(const QQmlJSScope::ConstPtr &type, int index)