10#include <private/qv4compilerscanfunctions_p.h>
12#include <QtQmlCompiler/private/qqmlsasourcelocation_p.h>
34 :
QQmlJSCompilePass(unitGenerator, typeResolver, logger, basicBlocks, annotations),
35 m_passManager(passManager)
48 if (m_state.needsMorePasses)
51 m_prevStateAnnotations = m_state.annotations;
52 m_state = PassState();
62 }
while (m_state.needsMorePasses);
64 return { std::move(
m_basicBlocks), std::move(m_state.annotations) };
67#define INSTR_PROLOGUE_NOT_IMPLEMENTED() \
68 setError(u"Instruction \"%1\" not implemented"_s.arg(QString::fromUtf8(__func__))); \
71#define INSTR_PROLOGUE_NOT_IMPLEMENTED_IGNORE() \
72 m_logger->log(u"Instruction \"%1\" not implemented"_s.arg(QString::fromUtf8(__func__)), \
73 qmlCompiler, QQmlJS::SourceLocation()); \
76void QQmlJSTypePropagator::generate_ret_SAcheck()
85 getCurrentBindingSourceLocation()));
89 if (m_passManager !=
nullptr)
90 generate_ret_SAcheck();
98 setError(u
"function without return type annotation returns %1. This may prevent proper "_s
103 m_logger->
log(u
"Function without return type annotation returns %1"_s.arg(
108 }
else if (!canConvertFromTo(m_state.
accumulatorIn(), m_returnType)) {
109 setError(u
"cannot convert from %1 to %2"_s
113 m_logger->
log(u
"Cannot assign binding of type %1 to %2"_s.arg(
125 addReadAccumulator(m_returnType);
129 m_state.skipInstructionsUntilNextJumpTarget =
true;
292 return combine(entries.constFirst().location, entries.constLast().location);
295void QQmlJSTypePropagator::handleUnqualifiedAccess(
const QString &
name,
bool isMethod)
const
297 auto location = getCurrentSourceLocation();
313 std::optional<QQmlJSFixSuggestion> suggestion;
317 auto &scope = childScopes[
i];
318 if (
location.offset > scope->sourceLocation().offset) {
319 if (
i + 1 < childScopes.size()
320 && childScopes.at(
i + 1)->sourceLocation().offset <
location.offset)
322 if (scope->childScopes().size() == 0)
325 const auto jsId = scope->childScopes().first()->jsIdentifier(
name);
332 fixLocation.length = 0;
336 QString fixString = handler.isMultiline ? u
"function("_s : u
"("_s;
337 const auto parameters = handler.signalParameters;
338 for (
int numParams = parameters.size(); numParams > 0; --numParams) {
339 fixString += parameters.
at(parameters.size() - numParams);
341 fixString += u
", "_s;
344 fixString += handler.isMultiline ? u
") "_s : u
") => "_s;
347 name + u
" is accessible in this scope because you are handling a signal"
348 " at %1:%2. Use a function instead.\n"_s
364 if (
name == u
"model" ||
name == u
"index") {
366 const auto bindings = parent->ownPropertyBindings(u
"delegate"_s);
368 for (
auto it = bindings.first;
it != bindings.second;
it++) {
369 if (!
it->hasObject())
373 name +
" is implicitly injected into this delegate."
374 " Add a required property instead."_L1,
384 if (!suggestion.has_value()) {
386 scope = scope->parentScope()) {
387 if (scope->hasProperty(
name)) {
394 +
" is a member of a parent element.\n You can qualify the access "
395 "with its id to avoid this warning.\n"_L1,
396 fixLocation, (
id.isEmpty() ? u
"<id>."_s : (
id + u
'.'))
400 suggestion->
setHint(
"You first have to give the element an id"_L1);
402 suggestion->setAutoApplicable();
409 const QLatin1String replacement =
"pragma ComponentBehavior: Bound"_L1;
411 "Set \"%1\" in order to use IDs from outer components in nested components."_L1
414 replacement +
'\n'_L1
416 bindComponents.setAutoApplicable();
417 suggestion = bindComponents;
420 if (!suggestion.has_value()) {
421 if (
auto didYouMean =
426 didYouMean.has_value()) {
427 suggestion = didYouMean;
440 if (qmlScope.isNull())
443 QList<QQmlJSAnnotation> annotations;
448 const QVector<QQmlJSMetaMethod>
methods = qmlScope->methods(
name);
452 annotations =
method.annotations();
457 annotations =
property.annotations();
460 auto deprecationAnn = std::find_if(
461 annotations.constBegin(), annotations.constEnd(),
462 [](
const QQmlJSAnnotation &annotation) { return annotation.isDeprecation(); });
464 if (deprecationAnn == annotations.constEnd())
471 descriptor += u
'(' +
method.parameterNames().join(u
", "_s) + u
')';
474 .arg(isMethod ? u
"Method"_s : u
"Property"_s)
484QQmlJSTypePropagator::PropertyResolution QQmlJSTypePropagator::propertyResolution(
487 auto property = scope->
property(propertyName);
489 return PropertyMissing;
493 errorType = u
"found"_s;
494 else if (!
property.type()->isFullyResolved())
495 errorType = u
"fully resolved"_s;
497 return PropertyFullyResolved;
502 u
"Type \"%1\" of property \"%2\" not %3. This is likely due to a missing dependency entry or a type not being exposed declaratively."_s
503 .
arg(
property.typeName(), propertyName, errorType),
506 return PropertyTypeUnresolved;
515 QString propertyType = u
"Property"_s;
521 errorType = u
"shadowed by a property."_s;
522 switch (
methods.first().methodType()) {
523 case QQmlJSMetaMethodType::Signal:
524 propertyType = u
"Signal"_s;
526 case QQmlJSMetaMethodType::Slot:
527 propertyType = u
"Slot"_s;
529 case QQmlJSMetaMethodType::Method:
530 propertyType = u
"Method"_s;
537 u
"a variant property. It may or may not be a method. Use a regular function instead."_s;
540 u
"a QJSValue property. It may or may not be a method. Use a regular Q_INVOKABLE instead."_s;
542 errorType = u
"not a method"_s;
546 getCurrentSourceLocation(),
true,
true, {});
552void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup_SAcheck(
const QString &
name)
558 getCurrentBindingSourceLocation()));
584 handleUnqualifiedAccess(
name,
false);
591 if (outStored.isNull()) {
594 setError(u
"Cannot determine generic type for "_s +
name);
599 && !outStored->isReferenceType()) {
600 setError(u
"Cannot retrieve a non-object type by ID: "_s +
name);
604 if (m_passManager !=
nullptr)
605 generate_LoadQmlContextPropertyLookup_SAcheck(
name);
618 getCurrentBindingSourceLocation()));
638 if (!
type.isValid()) {
639 handleUnqualifiedAccess(
name,
false);
644 if (!
type.isProperty()) {
646 : u
"Cannot assign to non-property %1"_s;
650 getCurrentSourceLocation());
655 if (!
type.isWritable()) {
656 setError(u
"Can't assign to read-only property %1"_s.arg(
name));
659 getCurrentSourceLocation());
664 if (!canConvertFromTo(
in,
type)) {
665 setError(u
"cannot convert from %1 to %2"_s
666 .
arg(
in.descriptiveName(),
type.descriptiveName()));
669 if (m_passManager !=
nullptr)
670 generate_StoreNameCommon_SAcheck(
in,
name);
677 addReadAccumulator(
in);
679 addReadAccumulator(
type);
698 if (
base.isEnumeration()) {
699 const auto metaEn =
base.enumeration();
700 if (!metaEn.hasKey(propertyName)) {
702 getCurrentSourceLocation());
703 const QString error = u
"\"%1\" is not an entry of enum \"%2\"."_s
704 .arg(propertyName, metaEn.name());
713 if (metaEn.isValid() && !metaEn.isScoped() && !metaEn.isQml()) {
715 = u
"You cannot access unscoped enum \"%1\" from here."_s.arg(propertyName);
727 const auto fallback = [&]() {
729 addReadAccumulator(jsValue);
730 addReadRegister(
base, jsValue);
731 setAccumulator(jsValue);
735 if (!baseRegister.isList()
740 addReadRegister(
base, baseRegister);
769 if (!baseRegister.isList()
772 addReadAccumulator(jsValue);
773 addReadRegister(
base, jsValue);
774 addReadRegister(
index, jsValue);
790 addReadRegister(
base, baseRegister);
801void QQmlJSTypePropagator::propagatePropertyLookup_SAcheck(
const QString &propertyName)
803 const bool isAttached =
812 QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(
813 getCurrentBindingSourceLocation()));
816void QQmlJSTypePropagator::propagatePropertyLookup(
const QString &propertyName,
int lookupIndex)
823 + u
'.' + propertyName
824 : propertyName, lookupIndex));
839 getCurrentSourceLocation());
843 u
"Cannot access singleton as a property of an object. Did you want to access an attached object?"_s,
866 setError(u
"Cannot load property %1 from %2."_s
879 if (propertyResolution(baseType, propertyName) != PropertyMissing)
882 if (baseType->isScript())
885 std::optional<QQmlJSFixSuggestion> fixSuggestion;
888 getCurrentSourceLocation());
889 suggestion.has_value()) {
890 fixSuggestion = suggestion;
893 if (!fixSuggestion.has_value()
897 m_state.accumulatorIn().scopeType()->enumerations())
898 enumKeys << metaEnum.
keys();
900 if (
auto suggestion =
902 suggestion.has_value()) {
903 fixSuggestion = suggestion;
913 setError(u
"Cannot determine overloaded method on loadProperty"_s);
936 setError(u
"Type %1 does not have a property %2 for reading"_s
948 if (m_passManager !=
nullptr)
949 propagatePropertyLookup_SAcheck(propertyName);
989 saveRegisterStateForJump(
offset);
1004 QQmlSA::SourceLocationPrivate::createQQmlSASourceLocation(
1005 getCurrentBindingSourceLocation()));
1015 setError(u
"Type %1 does not have a property %2 for writing"_s
1016 .
arg(callBase.descriptiveName(), propertyName));
1020 if (
property.storedType().isNull()) {
1021 setError(u
"Cannot determine type for property %1 of type %2"_s.arg(
1022 propertyName, callBase.descriptiveName()));
1027 setError(u
"Can't assign to read-only property %1"_s.arg(propertyName));
1029 m_logger->
log(u
"Cannot assign to read-only property %1"_s.arg(propertyName),
1036 setError(u
"cannot convert from %1 to %2"_s
1041 if (m_passManager !=
nullptr)
1042 generate_StoreProperty_SAcheck(propertyName, callBase);
1055 ?
property.storedIn(varType).castTo(varType)
1057 addReadAccumulator(readType);
1058 addReadRegister(
base, callBase);
1115 return consoleMethod == u
"log" || consoleMethod == u
"debug" || consoleMethod == u
"info"
1116 || consoleMethod == u
"warn" || consoleMethod == u
"error";
1119void QQmlJSTypePropagator::generate_CallProperty_SCMath(
int base,
int argc,
int argv)
1132 for (
int i = 0;
i < argc; ++
i)
1133 addReadRegister(argv +
i, realType);
1134 setAccumulator(realType);
1137void QQmlJSTypePropagator::generate_CallProperty_SCconsole(
int base,
int argc,
int argv)
1143 addReadRegister(
base, voidType);
1151 switch (firstArg->accessSemantics()) {
1152 case QQmlJSScope::AccessSemantics::Reference:
1158 case QQmlJSScope::AccessSemantics::Sequence:
1159 addReadRegister(argv, firstContent);
1162 addReadRegister(argv, stringType);
1167 for (
int i = 1;
i < argc; ++
i) {
1172 arg->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1190 getCurrentBindingSourceLocation()));
1200 generate_CallProperty_SCMath(
base, argc, argv);
1205 generate_CallProperty_SCconsole(
base, argc, argv);
1212 if (!member.isMethod()) {
1216 addReadRegister(
base, jsValueType);
1217 for (
int i = 0;
i < argc; ++
i)
1218 addReadRegister(argv +
i, jsValueType);
1226 setError(u
"Type %1 does not have a property %2 for calling"_s
1227 .
arg(callBase.descriptiveName(), propertyName));
1229 if (callBase.isType() && isCallingProperty(callBase.type(), propertyName))
1235 std::optional<QQmlJSFixSuggestion> fixSuggestion;
1238 getCurrentSourceLocation());
1239 suggestion.has_value()) {
1240 fixSuggestion = suggestion;
1243 m_logger->
log(u
"Member \"%1\" not found on type \"%2\""_s.arg(
1249 checkDeprecated(baseType, propertyName,
true);
1251 if (m_passManager !=
nullptr)
1252 generate_callProperty_SAcheck(propertyName, baseType);
1254 addReadRegister(
base, callBase);
1257 if (propertyName == u
"arg"_s && argc == 1) {
1258 propagateStringArgCall(argv);
1263 if (baseType->
accessSemantics() == QQmlJSScope::AccessSemantics::Sequence
1265 && propagateArrayMethod(propertyName, argc, argv, callBase)) {
1269 propagateCall(member.method(), argc, argv, member.scopeType());
1277 bool hasMultipleCandidates =
false;
1282 if (
method.isJavaScriptFunction() && !javascriptFunction.isValid())
1283 javascriptFunction =
method;
1285 if (
method.returnType().isNull() && !
method.returnTypeName().isEmpty()) {
1286 errors->append(u
"return type %1 cannot be resolved"_s
1294 u
"Function expects %1 arguments, but %2 were provided"_s.arg(
arguments.
size())
1299 bool fuzzyMatch =
true;
1300 bool exactMatch =
true;
1301 for (
int i = 0;
i < argc; ++
i) {
1305 u
"type %1 for argument %2 cannot be resolved"_s.arg(
arguments[
i].typeName())
1312 const auto content = m_state.
registers[argv +
i].content;
1328 u
"argument %1 contains %2 but is expected to contain the type %3"_s.arg(
i).arg(
1329 content.descriptiveName(),
arguments[
i].typeName()));
1336 }
else if (fuzzyMatch) {
1340 hasMultipleCandidates =
true;
1344 if (hasMultipleCandidates)
1347 return candidate.
isValid() ? candidate : javascriptFunction;
1359 if (
it != m_prevStateAnnotations.
end()) {
1370void QQmlJSTypePropagator::mergeRegister(
1376 if (!merged.isConversion()) {
1385 if (
it == m_prevStateAnnotations.
end())
1388 auto conversion =
it->second.typeConversions.
find(
index);
1389 if (conversion ==
it->second.typeConversions.
end())
1392 const VirtualRegister &lastTry = conversion.value();
1394 Q_ASSERT(lastTry.content.isValid());
1395 if (!lastTry.content.isConversion())
1399 || lastTry.content.conversionOrigins() != merged.conversionOrigins()) {
1409 if (!tryPrevStateConversion(
index, merged)) {
1423void QQmlJSTypePropagator::propagateCall(
1424 const QList<QQmlJSMetaMethod> &
methods,
int argc,
int argv,
1430 if (!
match.isValid()) {
1435 }
else if (errors.size() <
methods.size()) {
1436 setError(u
"Multiple matching overrides found. Cannot determine the right one."_s);
1438 setError(u
"No matching override found. Candidates:\n"_s + errors.join(u
'\n'));
1443 const auto returnType =
match.isJavaScriptFunction()
1448 match.isJavaScriptFunction()
1453 setError(u
"Cannot store return type of method %1()."_s.arg(
match.methodName()));
1456 for (
int i = 0;
i < argc; ++
i) {
1461 if (!
type.isNull()) {
1471bool QQmlJSTypePropagator::propagateTranslationMethod(
1472 const QList<QQmlJSMetaMethod> &
methods,
int argc,
int argv)
1487 if (
method.methodName() == u
"qsTranslate"_s) {
1490 addReadRegister(argv + 3, intType);
1493 addReadRegister(argv + 2, stringType);
1496 addReadRegister(argv + 1, stringType);
1497 addReadRegister(argv, stringType);
1498 setAccumulator(returnType);
1505 if (
method.methodName() == u
"QT_TRANSLATE_NOOP"_s) {
1508 addReadRegister(argv + 2, stringType);
1511 addReadRegister(argv + 1, stringType);
1512 addReadRegister(argv, stringType);
1513 setAccumulator(returnType);
1520 if (
method.methodName() == u
"qsTr"_s) {
1523 addReadRegister(argv + 2, intType);
1526 addReadRegister(argv + 1, stringType);
1529 addReadRegister(argv, stringType);
1530 setAccumulator(returnType);
1537 if (
method.methodName() == u
"QT_TR_NOOP"_s) {
1540 addReadRegister(argv + 1, stringType);
1543 addReadRegister(argv, stringType);
1544 setAccumulator(returnType);
1551 if (
method.methodName() == u
"qsTrId"_s) {
1554 addReadRegister(argv + 1, intType);
1557 addReadRegister(argv, stringType);
1558 setAccumulator(returnType);
1565 if (
method.methodName() == u
"QT_TRID_NOOP"_s) {
1568 addReadRegister(argv, stringType);
1569 setAccumulator(returnType);
1579void QQmlJSTypePropagator::propagateStringArgCall(
int argv)
1612bool QQmlJSTypePropagator::propagateArrayMethod(
1625 const auto valueContained = baseContained->
valueType();
1629 || baseContained->isListProperty()
1637 if (
name == u
"copyWithin" && argc > 0 && argc < 4) {
1638 for (
int i = 0;
i < argc; ++
i) {
1639 if (!canConvertFromTo(m_state.
registers[argv +
i].content, intType))
1643 for (
int i = 0;
i < argc; ++
i)
1644 addReadRegister(argv +
i, intType);
1647 setReturnType(baseContained);
1651 if (
name == u
"fill" && argc > 0 && argc < 4) {
1652 if (!canConvertFromTo(m_state.
registers[argv].content, valueType))
1655 for (
int i = 1;
i < argc; ++
i) {
1656 if (!canConvertFromTo(m_state.
registers[argv +
i].content, intType))
1660 addReadRegister(argv, valueType);
1662 for (
int i = 1;
i < argc; ++
i)
1663 addReadRegister(argv +
i, intType);
1666 setReturnType(baseContained);
1670 if (
name == u
"includes" && argc > 0 && argc < 3) {
1671 if (!canConvertFromTo(m_state.
registers[argv].content, valueType))
1675 if (!canConvertFromTo(m_state.
registers[argv + 1].content, intType))
1677 addReadRegister(argv + 1, intType);
1680 addReadRegister(argv, valueType);
1685 if (
name == u
"toString" || (
name == u
"join" && argc < 2)) {
1687 if (!canConvertFromTo(m_state.
registers[argv].content, stringType))
1689 addReadRegister(argv, stringType);
1696 if ((
name == u
"pop" ||
name == u
"shift") && argc == 0) {
1698 setReturnType(valueContained);
1702 if (
name == u
"push" ||
name == u
"unshift") {
1703 for (
int i = 0;
i < argc; ++
i) {
1704 if (!canConvertFromTo(m_state.
registers[argv +
i].content, valueType))
1708 for (
int i = 0;
i < argc; ++
i)
1709 addReadRegister(argv +
i, valueType);
1716 if (
name == u
"reverse" && argc == 0) {
1718 setReturnType(baseContained);
1722 if (
name == u
"slice" && argc < 3) {
1723 for (
int i = 0;
i < argc; ++
i) {
1724 if (!canConvertFromTo(m_state.
registers[argv +
i].content, intType))
1728 for (
int i = 0;
i < argc; ++
i)
1729 addReadRegister(argv +
i, intType);
1737 if (
name == u
"splice" && argc > 0) {
1738 for (
int i = 0;
i < 2; ++
i) {
1739 if (!canConvertFromTo(m_state.
registers[argv +
i].content, intType))
1743 for (
int i = 2;
i < argc; ++
i) {
1744 if (!canConvertFromTo(m_state.
registers[argv +
i].content, valueType))
1748 for (
int i = 0;
i < 2; ++
i)
1749 addReadRegister(argv +
i, intType);
1751 for (
int i = 2;
i < argc; ++
i)
1752 addReadRegister(argv +
i, valueType);
1755 setReturnType(baseContained);
1759 if ((
name == u
"indexOf" ||
name == u
"lastIndexOf") && argc > 0 && argc < 3) {
1760 if (!canConvertFromTo(m_state.
registers[argv].content, valueType))
1764 if (!canConvertFromTo(m_state.
registers[argv + 1].content, intType))
1766 addReadRegister(argv + 1, intType);
1769 addReadRegister(argv, valueType);
1796void QQmlJSTypePropagator::propagateScopeLookupCall(
const QString &functionName,
int argc,
int argv)
1800 if (resolvedContent.isMethod()) {
1801 const auto methods = resolvedContent.method();
1803 if (propagateTranslationMethod(
methods, argc, argv))
1808 propagateCall(
methods, argc, argv, resolvedContent.scopeType());
1813 setError(u
"method %1 cannot be resolved."_s.arg(functionName));
1816 setError(u
"Cannot find function '%1'"_s.arg(functionName));
1818 handleUnqualifiedAccess(functionName,
true);
1829 propagateScopeLookupCall(
name, argc, argv);
1853void QQmlJSTypePropagator::generate_Construct_SCDate(
int argc,
int argv)
1875 constexpr int maxArgc = 7;
1876 for (
int i = 0;
i < std::min(argc, maxArgc); ++
i) {
1883void QQmlJSTypePropagator::generate_Construct_SCArray(
int argc,
int argv)
1899 if (!
type.isMethod()) {
1906 generate_Construct_SCDate(argc, argv);
1911 generate_Construct_SCArray(argc, argv);
1952 const auto fail = [
this,
name]() {
1953 setError(u
"Cannot statically assert the dead temporal zone check for %1"_s.arg(
1958 if (
in.isConversion()) {
1974 m_state.skipInstructionsUntilNextJumpTarget =
true;
2041 if (!listType.
isList()) {
2043 addReadAccumulator(jsValue);
2044 setAccumulator(jsValue);
2048 addReadAccumulator(listType);
2056 addReadAccumulator(iteratorType);
2060 saveRegisterStateForJump(
offset);
2120 for (
int i = 0;
i < argc; ++
i)
2121 addReadRegister(
args +
i, elementType);
2130 for (
int i = 0;
i < classSize; ++
i) {
2136 for (
int i = classSize;
i < argc;
i += 3) {
2197 saveRegisterStateForJump(
offset);
2198 m_state.skipInstructionsUntilNextJumpTarget =
true;
2206 setError(u
"cannot convert from %1 to boolean"_s
2210 saveRegisterStateForJump(
offset);
2219 setError(u
"cannot convert from %1 to boolean"_s
2223 saveRegisterStateForJump(
offset);
2230 saveRegisterStateForJump(
offset);
2245void QQmlJSTypePropagator::recordEqualsNullType()
2255void QQmlJSTypePropagator::recordEqualsIntType()
2266void QQmlJSTypePropagator::recordEqualsType(
int lhs)
2273 const auto lhsRegister = m_state.
registers[lhs].content;
2279 || (isNumericOrEnum(accumulatorIn) && isNumericOrEnum(lhsRegister))
2281 addReadRegister(lhs, lhsRegister);
2282 addReadAccumulator(accumulatorIn);
2299 addReadRegister(lhs, lhsRegister);
2300 addReadAccumulator(accumulatorIn);
2308 addReadRegister(lhs, jsval);
2309 addReadAccumulator(jsval);
2312void QQmlJSTypePropagator::recordCompareType(
int lhs)
2321 addReadRegister(lhs,
read);
2322 addReadAccumulator(
read);
2327 recordEqualsNullType();
2333 recordEqualsNullType();
2339 recordEqualsIntType();
2348 recordEqualsIntType();
2357 recordEqualsType(lhs);
2363 recordEqualsType(lhs);
2369 recordCompareType(lhs);
2375 recordCompareType(lhs);
2381 recordCompareType(lhs);
2387 recordCompareType(lhs);
2393 recordEqualsType(lhs);
2399 recordEqualsType(lhs);
2434 if (outContained->isComposite())
2444 if (outContained->accessSemantics() == QQmlJSScope::AccessSemantics::Reference) {
2453 setError(u
"invalid cast from %1 to %2. You can only cast object types."_s
2469 addReadRegister(lhs,
input);
2473void QQmlJSTypePropagator::checkConversion(
2476 if (!canConvertFromTo(from, to)) {
2477 setError(u
"cannot convert from %1 to %2"_s
2487 addReadAccumulator(
type);
2488 setAccumulator(
type);
2521void QQmlJSTypePropagator::generateBinaryArithmeticOperation(
QSOperator::Op op,
int lhs)
2525 checkConversion(checkedInputRegister(lhs),
type);
2526 addReadRegister(lhs,
type);
2529 addReadAccumulator(
type);
2532void QQmlJSTypePropagator::generateBinaryConstArithmeticOperation(
QSOperator::Op op)
2539 addReadAccumulator(
type);
2540 setAccumulator(
type);
2641 for (
int reg = firstReg,
end = firstReg +
count; reg <
end; ++reg)
2663 if (m_state.skipInstructionsUntilNextJumpTarget) {
2666 m_state.skipInstructionsUntilNextJumpTarget =
false;
2668 }
else if (m_state.skipInstructionsUntilNextJumpTarget
2685 for (
auto originRegisterStateIt =
2686 m_jumpOriginRegisterStateByTargetInstructionOffset.
constFind(currentOffset);
2687 originRegisterStateIt != m_jumpOriginRegisterStateByTargetInstructionOffset.
constEnd()
2688 && originRegisterStateIt.key() == currentOffset;
2689 ++originRegisterStateIt) {
2690 auto stateToMerge = *originRegisterStateIt;
2691 for (
auto registerIt = stateToMerge.registers.constBegin(),
2692 end = stateToMerge.registers.constEnd();
2693 registerIt !=
end; ++registerIt) {
2694 const int registerIndex = registerIt.key();
2696 auto newType = registerIt.value().content;
2697 if (!newType.isValid()) {
2698 setError(u
"When reached from offset %1, %2 is undefined"_s
2699 .
arg(stateToMerge.originatingOffset)
2700 .arg(registerName(registerIndex)));
2704 auto currentRegister = m_state.
registers.
find(registerIndex);
2706 mergeRegister(registerIndex, newType, currentRegister.value().content);
2708 mergeRegister(registerIndex, newType, newType);
2722 currentInstruction.isRename = m_state.
isRename();
2726 case QV4::Moth::Instr::Type::Ret:
2727 case QV4::Moth::Instr::Type::Jump:
2728 case QV4::Moth::Instr::Type::JumpFalse:
2729 case QV4::Moth::Instr::Type::JumpTrue:
2730 case QV4::Moth::Instr::Type::StoreReg:
2731 case QV4::Moth::Instr::Type::StoreElement:
2732 case QV4::Moth::Instr::Type::StoreNameSloppy:
2733 case QV4::Moth::Instr::Type::StoreProperty:
2734 case QV4::Moth::Instr::Type::SetLookup:
2735 case QV4::Moth::Instr::Type::MoveConst:
2736 case QV4::Moth::Instr::Type::MoveReg:
2737 case QV4::Moth::Instr::Type::CheckException:
2738 case QV4::Moth::Instr::Type::CreateCallContext:
2739 case QV4::Moth::Instr::Type::PopContext:
2740 case QV4::Moth::Instr::Type::JumpNoException:
2741 case QV4::Moth::Instr::Type::ThrowException:
2742 case QV4::Moth::Instr::Type::SetUnwindHandler:
2743 case QV4::Moth::Instr::Type::PushCatchContext:
2744 case QV4::Moth::Instr::Type::UnwindDispatch:
2745 case QV4::Moth::Instr::Type::InitializeBlockDeadTemporalZone:
2746 case QV4::Moth::Instr::Type::ConvertThisToObject:
2747 case QV4::Moth::Instr::Type::DeadTemporalZoneCheck:
2748 case QV4::Moth::Instr::Type::IteratorNext:
2749 case QV4::Moth::Instr::Type::IteratorNextForYieldStar:
2751 setError(u
"Instruction is not expected to populate the accumulator"_s);
2760 setError(u
"Instruction is expected to populate the accumulator"_s);
2766 && instr != QV4::Moth::Instr::Type::DeadTemporalZoneCheck) {
2777 r.affectedBySideEffects = m_state.
isRename()
2789 auto lhsRegister = checkedInputRegister(lhs);
2790 if (!lhsRegister.isValid())
2796 setAccumulator(
type);
2806void QQmlJSTypePropagator::saveRegisterStateForJump(
int offset)
2809 ExpectedRegisterState
state;
2812 m_state.jumpTargets.
insert(jumpToOffset);
2816 const auto registerStates =
2817 m_jumpOriginRegisterStateByTargetInstructionOffset.
equal_range(jumpToOffset);
2818 for (
auto it = registerStates.first;
it != registerStates.second; ++
it) {
2819 if (
it->registers.keys() ==
state.registers.keys()
2826 m_state.needsMorePasses =
true;
2828 m_jumpOriginRegisterStateByTargetInstructionOffset.
insert(jumpToOffset,
state);
2831QString QQmlJSTypePropagator::registerName(
int registerIndex)
const
2834 return u
"accumulator"_s;
2836 && registerIndex < FirstArgument + m_function->argumentTypes.size()) {
2840 return u
"temporary register %1"_s.
arg(
2851 setError(u
"Type error: could not infer the type of an expression"_s);
2854 return regIt.value().content;
static JNINativeMethod methods[]
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
bool contains(const Key &key) const
iterator find(const Key &key)
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
qsizetype size() const noexcept
std::pair< iterator, iterator > equal_range(const Key &key)
const_iterator constEnd() const noexcept
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the ...
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
const_iterator constFind(const Key &key) const noexcept
const QV4::Compiler::JSUnitGenerator * m_jsUnitGenerator
bool isArgument(int registerIndex) const
static bool instructionManipulatesContext(QV4::Moth::Instr::Type type)
const Function * m_function
const QQmlJSTypeResolver * m_typeResolver
QQmlJS::DiagnosticMessage * m_error
InstructionAnnotations m_annotations
State initialState(const Function *function)
QFlatMap< int, VirtualRegister > VirtualRegisters
BasicBlocks m_basicBlocks
void setError(const QString &message, int instructionOffset)
QQmlJSRegisterContent argumentType(int registerIndex) const
void setHint(const QString &hint)
void setAutoApplicable(bool autoApply=true)
void log(const QString &message, QQmlJS::LoggerWarningId id, const QQmlJS::SourceLocation &srcLocation, bool showContext=true, bool showFileName=true, const std::optional< QQmlJSFixSuggestion > &suggestion={}, const QString overrideFileName=QString())
QString descriptiveName() const
QQmlJSMetaProperty property() const
QQmlJSScope::ConstPtr scopeType() const
uint importNamespace() const
bool isConversion() const
bool isImportNamespace() const
ContentVariant variant() const
QQmlJSScope::ConstPtr storedType() const
static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &storedType, const QQmlJSScope::ConstPtr &type, int resultLookupIndex, ContentVariant variant, const QQmlJSScope::ConstPtr &scope={})
int resultLookupIndex() const
bool isEnumeration() const
QList< QQmlJSMetaMethod > method() const
QHash< QString, QQmlJSMetaProperty > properties() const
Returns all properties visible from this scope including those of base types and extensions.
QHash< QString, QQmlJSMetaMethod > methods() const
Returns all methods visible from this scope including those of base types and extensions.
bool isInCustomParserParent() const
QQmlJSScope::Ptr parentScope()
QString internalName() const
bool isReferenceType() const
AccessSemantics accessSemantics() const
static QQmlSA::Element createQQmlSAElement(const ConstPtr &)
QVector< QQmlJSScope::Ptr > childScopes()
bool isListProperty() const
QDeferredSharedPointer< const QQmlJSScope > ConstPtr
QQmlJSMetaProperty property(const QString &name) const
QQmlJSScope::ConstPtr baseType() const
static QQmlJSScope::ConstPtr findCurrentQMLScope(const QQmlJSScope::ConstPtr &scope)
QQmlJS::SourceLocation sourceLocation() const
QQmlJSScope::ConstPtr valueType() const
bool componentsAreBound() const
bool existsAnywhereInDocument(const QString &id) const
QString id(const QQmlJSScope::ConstPtr &scope, const QQmlJSScope::ConstPtr &referrer, QQmlJSScopesByIdOptions options=Default) const
bool equals(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const
QQmlJSScope::ConstPtr functionType() const
QQmlJSRegisterContent merge(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) const
QQmlJSScope::ConstPtr dateTimeType() const
QQmlJSScope::ConstPtr stringType() const
const QHash< QQmlJS::SourceLocation, QQmlJSMetaSignalHandler > & signalHandlers() const
QQmlJSRegisterContent cast(const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const
QQmlJSScope::ConstPtr nullType() const
QQmlJSScope::ConstPtr timeType() const
QQmlJSRegisterContent tracked(const QQmlJSRegisterContent &type) const
QQmlJSScope::ConstPtr mathObject() const
QQmlJSScope::ConstPtr genericType(const QQmlJSScope::ConstPtr &type, ComponentIsGeneric allowComponent=ComponentIsGeneric::No) const
QQmlJSScope::ConstPtr emptyType() const
bool registerIsStoredIn(const QQmlJSRegisterContent ®, const QQmlJSScope::ConstPtr &type) const
QQmlJSScope::ConstPtr containedType(const QQmlJSRegisterContent &container) const
QQmlJSScope::ConstPtr jsPrimitiveType() const
QQmlJSRegisterContent typeForArithmeticUnaryOperation(UnaryOperator op, const QQmlJSRegisterContent &operand) const
bool isNumeric(const QQmlJSRegisterContent &type) const
QQmlJSScope::ConstPtr consoleObject() const
QQmlJSScope::ConstPtr arrayPrototype() const
QQmlJSScope::ConstPtr boolType() const
QQmlJSScope::ConstPtr qObjectListType() const
QQmlJSScope::ConstPtr jsGlobalObject() const
bool registerContains(const QQmlJSRegisterContent ®, const QQmlJSScope::ConstPtr &type) const
bool inherits(const QQmlJSScope::ConstPtr &derived, const QQmlJSScope::ConstPtr &base) const
bool isIntegral(const QQmlJSRegisterContent &type) const
bool isPrimitive(const QQmlJSRegisterContent &type) const
QQmlJSRegisterContent builtinType(const QQmlJSScope::ConstPtr &type) const
QQmlJSRegisterContent returnType(const QQmlJSScope::ConstPtr &type, QQmlJSRegisterContent::ContentVariant variant, const QQmlJSScope::ConstPtr &scope) const
bool canConvertFromTo(const QQmlJSScope::ConstPtr &from, const QQmlJSScope::ConstPtr &to) const
bool isPrefix(const QString &name) const
QString containedTypeName(const QQmlJSRegisterContent &container, bool useFancyName=false) const
QQmlJSScope::ConstPtr jsValueType() const
QQmlJSRegisterContent globalType(const QQmlJSScope::ConstPtr &type) const
QQmlJSRegisterContent convert(const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const
bool canHoldUndefined(const QQmlJSRegisterContent &content) const
QQmlJSScope::ConstPtr sizeType() const
QQmlJSRegisterContent valueType(const QQmlJSRegisterContent &list) const
QQmlJSScope::ConstPtr uint32Type() const
QQmlJSScope::ConstPtr extractNonVoidFromOptionalType(const QQmlJSRegisterContent &content) const
QQmlJSScope::ConstPtr int32Type() const
QQmlJSScope::ConstPtr variantListType() const
QQmlJSRegisterContent memberType(const QQmlJSRegisterContent &type, const QString &name, int lookupIndex=QQmlJSRegisterContent::InvalidLookupIndex) const
QQmlJSScope::ConstPtr voidType() const
QQmlJSRegisterContent iteratorPointer(const QQmlJSRegisterContent &listType, QQmlJS::AST::ForEachType type, int lookupIndex) const
QQmlJSScope::ConstPtr metaObjectType() const
QQmlJSScope::ConstPtr realType() const
bool isOptionalType(const QQmlJSRegisterContent &content) const
bool isUnsignedInteger(const QQmlJSScope::ConstPtr &type) const
QQmlJSScope::ConstPtr dateType() const
QQmlJSScope::ConstPtr typeForConst(QV4::ReturnedValue rv) const
bool canAddressValueTypes() const
bool isSignedInteger(const QQmlJSScope::ConstPtr &type) const
QQmlJSRegisterContent scopedType(const QQmlJSScope::ConstPtr &scope, const QString &name, int lookupIndex=QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSScopesByIdOptions options=Default) const
QQmlJSScope::ConstPtr qObjectType() const
QQmlJSScope::ConstPtr varType() const
QQmlJSRegisterContent typeForBinaryOperation(QSOperator::Op oper, const QQmlJSRegisterContent &left, const QQmlJSRegisterContent &right) const
QQmlJSScope::ConstPtr variantMapType() const
static PassManagerPrivate * get(PassManager *manager)
static QQmlSA::SourceLocation createQQmlSASourceLocation(const QQmlJS::SourceLocation &jsLocation)
QList< T > values() const
iterator find(const T &value)
bool contains(const T &value) const
iterator insert(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
QString arg(qlonglong a, int fieldwidth=0, int base=10, QChar fillChar=u' ') const
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
int currentInstructionOffset() const
int nextInstructionOffset() const
QSet< QString >::iterator it
QList< QVariant > arguments
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
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
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLboolean GLboolean GLboolean b
GLenum GLuint GLint level
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum GLenum * types
GLenum GLenum GLsizei count
GLuint GLsizei const GLchar * message
GLenum GLuint GLintptr offset
GLenum GLenum GLenum input
const QQmlSA::LoggerWarningId qmlRestrictedType
const QQmlSA::LoggerWarningId qmlReadOnlyProperty
const QQmlSA::LoggerWarningId qmlUseProperFunction
const QQmlSA::LoggerWarningId qmlMissingProperty
const QQmlSA::LoggerWarningId qmlUnqualified
const QQmlSA::LoggerWarningId qmlMissingEnumEntry
const QQmlSA::LoggerWarningId qmlAccessSingleton
const QQmlSA::LoggerWarningId qmlUnresolvedType
const QQmlSA::LoggerWarningId qmlMissingType
const QQmlSA::LoggerWarningId qmlIncompatibleType
const QQmlSA::LoggerWarningId qmlDeprecated
#define INSTR_PROLOGUE_NOT_IMPLEMENTED()
#define INSTR_PROLOGUE_NOT_IMPLEMENTED_IGNORE()
static bool isLoggingMethod(const QString &consoleMethod)
bool canStrictlyCompareWithVar(const QQmlJSTypeResolver *typeResolver, const QQmlJSScope::ConstPtr &lhsType, const QQmlJSScope::ConstPtr &rhsType)
bool canCompareWithQObject(const QQmlJSTypeResolver *typeResolver, const QQmlJSScope::ConstPtr &lhsType, const QQmlJSScope::ConstPtr &rhsType)
bool canCompareWithQUrl(const QQmlJSTypeResolver *typeResolver, const QQmlJSScope::ConstPtr &lhsType, const QQmlJSScope::ConstPtr &rhsType)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
static bool match(const uchar *found, uint foundLen, const char *target, uint targetLen)
ReturnedValue read(const char *data)
QT_BEGIN_NAMESPACE typedef uchar * output
QList< QQmlJSRegisterContent > argumentTypes
QQmlJSScopesById addressableScopes
QQmlJSScope::ConstPtr qmlScope
const SourceLocationTable * sourceLocations
QQmlJSRegisterContent returnType
int renameSourceRegisterIndex() const
const QQmlJSRegisterContent & accumulatorIn() const
The accumulatorIn is the input register of the current instruction.
VirtualRegisters registers
void addReadAccumulator(const QQmlJSRegisterContent ®)
void clearChangedRegister()
int changedRegisterIndex() const
VirtualRegisters takeReadRegisters() const
bool isRegisterAffectedBySideEffects(int registerIndex) const
void setReadRegisters(VirtualRegisters readReagisters)
const QQmlJSRegisterContent & changedRegister() const
void setIsRename(bool isRename)
bool hasSideEffects() const
void setRegister(int registerIndex, QQmlJSRegisterContent content)
void addReadRegister(int registerIndex, const QQmlJSRegisterContent ®)
void setHasSideEffects(bool hasSideEffects)
const QQmlJSRegisterContent & accumulatorOut() const
The accumulatorOut is the output register of the current instruction.
void generate_CmpEqInt(int lhsConst) override
void generate_GetLookup(int index) override
void generate_Decrement() override
void generate_CallPropertyLookup(int lookupIndex, int base, int argc, int argv) override
void generate_StoreNameStrict(int name) override
void generate_StoreElement(int base, int index) override
bool checkForEnumProblems(const QQmlJSRegisterContent &base, const QString &propertyName)
void generate_ConvertThisToObject() override
void generate_CloneBlockContext() override
void generate_LoadConst(int index) override
void generate_LoadLocal(int index) override
void generate_CreateUnmappedArgumentsObject() override
void generate_StoreSuperProperty(int property) override
void generate_DeleteName(int name) override
void generate_CreateCallContext() override
void generate_PopScriptContext() override
void generate_MoveRegExp(int regExpId, int destReg) override
void generate_PushWithContext() override
void generate_TypeofName(int name) override
void generate_CallQmlContextPropertyLookup(int index, int argc, int argv) override
void generate_BitXorConst(int rhsConst) override
void generate_InitializeBlockDeadTemporalZone(int firstReg, int count) override
void generate_LoadName(int nameIndex) override
void generate_StoreNameCommon(int nameIndex)
void generate_DeclareVar(int varName, int isDeletable) override
void generate_StoreProperty(int name, int base) override
void generate_GetException() override
void generate_LoadReg(int reg) override
void generate_CallGlobalLookup(int index, int argc, int argv) override
void generate_LoadTrue() override
void generate_IteratorClose() override
void generate_SetLookup(int index, int base) override
void generate_UShrConst(int rhsConst) override
void endInstruction(QV4::Moth::Instr::Type instr) override
void generate_LoadImport(int index) override
void generate_PushBlockContext(int index) override
void generate_CmpGe(int lhs) override
void generate_CmpLt(int lhs) override
void generate_ToObject() override
void generate_LoadClosure(int value) override
void generate_Mul(int lhs) override
void generate_UnwindToLabel(int level, int offset) override
void generate_StoreScopedLocal(int scope, int index) override
void generate_LoadNull() override
void generate_CmpInstanceOf(int lhs) override
void generate_DestructureRestElement() override
void generate_YieldStar() override
void generate_CmpNeNull() override
void generate_JumpNoException(int offset) override
void generate_ThrowException() override
void generate_GetOptionalLookup(int index, int offset) override
void generate_Resume(int) override
void generate_BitAndConst(int rhsConst) override
void generate_LoadElement(int base) override
void generate_MoveReg(int srcReg, int destReg) override
void generate_LoadProperty(int nameIndex) override
void generate_Yield() override
void generate_CmpNe(int lhs) override
void generate_Construct(int func, int argc, int argv) override
void generate_LoadFalse() override
void generate_Ret() override
void generate_CallProperty(int name, int base, int argc, int argv) override
void generate_CmpNeInt(int lhs) override
void generate_JumpFalse(int offset) override
void generate_ConstructWithSpread(int func, int argc, int argv) override
void generate_StoreReg(int reg) override
void generate_GetIterator(int iterator) override
void generate_ShlConst(int rhs) override
void generate_BitAnd(int lhs) override
void generate_SetException() override
void generate_UMinus() override
void generate_CmpStrictNotEqual(int lhs) override
void generate_CmpStrictEqual(int lhs) override
void generate_LoadScopedLocal(int scope, int index) override
void generate_Shl(int lhs) override
void generate_UPlus() override
void generate_Debug() override
void generate_CmpEqNull() override
void generate_LoadRuntimeString(int stringId) override
void generate_Shr(int lhs) override
void generate_DefineArray(int argc, int args) override
void generate_UCompl() override
void generate_JumpNotUndefined(int offset) override
void generate_CallWithReceiver(int name, int thisObject, int argc, int argv) override
void generate_CallWithSpread(int func, int thisObject, int argc, int argv) override
void generate_GetTemplateObject(int index) override
void generate_DefineObjectLiteral(int internalClassId, int argc, int args) override
void generate_CreateRestParameter(int argIndex) override
void generate_CheckException() override
void generate_CallValue(int name, int argc, int argv) override
void generate_Mod(int lhs) override
void generate_BitOr(int lhs) override
void generate_CmpLe(int lhs) override
void generate_StoreLocal(int index) override
void generate_SetUnwindHandler(int offset) override
void generate_LoadUndefined() override
void generate_MoveConst(int constIndex, int destTemp) override
void generate_TailCall(int func, int thisObject, int argc, int argv) override
void generate_DeleteProperty(int base, int index) override
void generate_BitOrConst(int rhsConst) override
void generate_StoreNameSloppy(int nameIndex) override
void generate_BitXor(int lhs) override
void generate_Exp(int lhs) override
void generate_Div(int lhs) override
void generate_LoadSuperProperty(int property) override
void generate_CreateClass(int classIndex, int heritage, int computedNames) override
void generate_TypeofValue() override
void generate_UShr(int lhs) override
void generate_PushScriptContext(int index) override
void generate_CallName(int name, int argc, int argv) override
void generate_Jump(int offset) override
void generate_CmpEq(int lhs) override
void generate_As(int lhs) override
void generate_LoadOptionalProperty(int name, int offset) override
void generate_Sub(int lhs) override
void generate_LoadZero() override
void generate_LoadGlobalLookup(int index) override
void generate_UnwindDispatch() override
void generate_LoadInt(int value) override
void generate_ShrConst(int rhs) override
void generate_CallPossiblyDirectEval(int argc, int argv) override
void generate_CmpIn(int lhs) override
void generate_JumpTrue(int offset) override
void generate_UNot() override
void generate_LoadQmlContextPropertyLookup(int index) override
void generate_PopContext() override
BlocksAndAnnotations run(const Function *m_function, QQmlJS::DiagnosticMessage *error)
void generate_IteratorNextForYieldStar(int iterator, int object, int offset) override
Verdict startInstruction(QV4::Moth::Instr::Type instr) override
void generate_PushCatchContext(int index, int name) override
void generate_CmpGt(int lhs) override
QQmlJSTypePropagator(const QV4::Compiler::JSUnitGenerator *unitGenerator, const QQmlJSTypeResolver *typeResolver, QQmlJSLogger *logger, BasicBlocks basicBlocks={}, InstructionAnnotations annotations={}, QQmlSA::PassManager *passManager=nullptr)
void generate_IteratorNext(int value, int offset) override
void generate_Add(int lhs) override
void generate_LoadSuperConstructor() override
void generate_CreateMappedArgumentsObject() override
void generate_ThrowOnNullOrUndefined() override
void generate_Increment() override
void generate_DeadTemporalZoneCheck(int name) override
static std::optional< QQmlJSFixSuggestion > didYouMean(const QString &userInput, QStringList candidates, QQmlJS::SourceLocation location)
QString lookupName(int index) const
ReturnedValue constant(int idx) const
int lookupNameIndex(int index) const
int getStringId(const QString &string) const
QString stringForIndex(int index) const
int jsClassSize(int jsClassId) const