📄 moc.cpp
字号:
funcDef.arguments.removeLast(); def->slotList += funcDef; } }}void Moc::parseSignals(ClassDef *def){ next(COLON); while (inClass(def) && hasNext()) { switch (next()) { case PUBLIC: case PROTECTED: case PRIVATE: case Q_SIGNALS_TOKEN: case Q_SLOTS_TOKEN: prev(); return; case SEMIC: continue; case FRIEND: until(SEMIC); continue; case USING: error("'using' directive not supported in 'signals' section"); default: prev(); } FunctionDef funcDef; funcDef.access = FunctionDef::Protected; parseFunction(&funcDef); if (funcDef.isVirtual) error("Signals cannot be declared virtual"); if (funcDef.inlineCode) error("Not a signal declaration"); def->signalList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def->signalList += funcDef; } }}void Moc::parseProperty(ClassDef *def){ next(LPAREN); PropertyDef propDef; QByteArray type = parseType().name; if (type.isEmpty()) error(); propDef.designable = propDef.scriptable = propDef.stored = "true"; propDef.user = "false"; /* The Q_PROPERTY construct cannot contain any commas, since commas separate macro arguments. We therefore expect users to type "QMap" instead of "QMap<QString, QVariant>". For coherence, we also expect the same for QValueList<QVariant>, the other template class supported by QVariant. */ type = normalizeType(type); if (type == "QMap") type = "QMap<QString,QVariant>"; else if (type == "QValueList") type = "QValueList<QVariant>"; else if (type == "LongLong") type = "qlonglong"; else if (type == "ULongLong") type = "qulonglong"; propDef.type = type; next(); propDef.name = lexem(); while (test(IDENTIFIER)) { QByteArray l = lexem(); QByteArray v, v2; if (test(LPAREN)) { v = lexemUntil(RPAREN); } else { next(IDENTIFIER); v = lexem(); if (test(LPAREN)) v2 = lexemUntil(RPAREN); else if (v != "true" && v != "false") v2 = "()"; } switch (l[0]) { case 'R': if (l == "READ") propDef.read = v; else if (l == "RESET") propDef.reset = v + v2; else error(2); break; case 'S': if (l == "SCRIPTABLE") propDef.scriptable = v + v2; else if (l == "STORED") propDef.stored = v + v2; else error(2); break; case 'W': if (l != "WRITE") error(2); propDef.write = v; break; case 'D': if (l != "DESIGNABLE") error(2); propDef.designable = v + v2; break; case 'E': if (l != "EDITABLE") error(2); propDef.editable = v + v2; break; case 'N': if (l != "NOTIFY") error(2); break; case 'U': if (l != "USER") error(2); propDef.user = v + v2; break; default: error(2); } } next(RPAREN); def->propertyList += propDef;}void Moc::parseEnumOrFlag(ClassDef *def, bool isFlag){ next(LPAREN); QByteArray identifier; while (test(IDENTIFIER)) { identifier = lexem(); while (test(SCOPE) && test(IDENTIFIER)) { identifier += "::"; identifier += lexem(); } def->enumDeclarations[identifier] = isFlag; } next(RPAREN);}void Moc::parseFlag(ClassDef *def){ next(LPAREN); QByteArray flagName, enumName; while (test(IDENTIFIER)) { flagName = lexem(); while (test(SCOPE) && test(IDENTIFIER)) { flagName += "::"; flagName += lexem(); } } next(COMMA); while (test(IDENTIFIER)) { enumName = lexem(); while (test(SCOPE) && test(IDENTIFIER)) { enumName += "::"; enumName += lexem(); } } def->flagAliases.insert(enumName, flagName); next(RPAREN);}void Moc::parseClassInfo(ClassDef *def){ next(LPAREN); ClassInfoDef infoDef; next(STRING_LITERAL); infoDef.name = symbol().unquotedLexem(); next(COMMA); if (test(STRING_LITERAL)) { infoDef.value = symbol().unquotedLexem(); } else { // support Q_CLASSINFO("help", QT_TR_NOOP("blah")) next(IDENTIFIER); next(LPAREN); next(STRING_LITERAL); infoDef.value = symbol().unquotedLexem(); next(RPAREN); } next(RPAREN); def->classInfoList += infoDef;}void Moc::parseInterfaces(ClassDef *def){ next(LPAREN); while (test(IDENTIFIER)) { QList<ClassDef::Interface> iface; iface += ClassDef::Interface(lexem()); while (test(SCOPE)) { iface.last().className += lexem(); next(IDENTIFIER); iface.last().className += lexem(); } while (test(COLON)) { next(IDENTIFIER); iface += ClassDef::Interface(lexem()); while (test(SCOPE)) { iface.last().className += lexem(); next(IDENTIFIER); iface.last().className += lexem(); } } // resolve from classnames to interface ids for (int i = 0; i < iface.count(); ++i) { const QByteArray iid = interface2IdMap.value(iface.at(i).className); if (iid.isEmpty()) error("Undefined interface"); iface[i].interfaceId = iid; } def->interfaceList += iface; } next(RPAREN);}void Moc::parseDeclareInterface(){ next(LPAREN); QByteArray interface; next(IDENTIFIER); interface += lexem(); while (test(SCOPE)) { interface += lexem(); next(IDENTIFIER); interface += lexem(); } next(COMMA); QByteArray iid; if (test(STRING_LITERAL)) { iid = lexem(); } else { next(IDENTIFIER); iid = lexem(); } interface2IdMap.insert(interface, iid); next(RPAREN);}void Moc::parseDeclareMetatype(){ next(LPAREN); QByteArray typeName = lexemUntil(RPAREN); typeName.remove(0, 1); typeName.chop(1); metaTypes.append(typeName);}void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access){ next(LPAREN); FunctionDef funcDef; next(IDENTIFIER); funcDef.inPrivateClass = lexem(); // also allow void functions if (test(LPAREN)) { next(RPAREN); funcDef.inPrivateClass += "()"; } next(COMMA); funcDef.access = access; parseFunction(&funcDef, true); def->slotList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; funcDef.arguments.removeLast(); def->slotList += funcDef; }}QByteArray Moc::lexemUntil(Token target){ int from = index; until(target); QByteArray s; while (from <= index) { QByteArray n = symbols.at(from++-1).lexem(); if (s.size() && n.size() && is_ident_char(s.at(s.size()-1)) && is_ident_char(n.at(0))) s += ' '; s += n; } return s;}bool Moc::until(Token target) { int braceCount = 0; int brackCount = 0; int parenCount = 0; int angleCount = 0; if (index) { switch(symbols.at(index-1).token) { case LBRACE: ++braceCount; break; case LBRACK: ++brackCount; break; case LPAREN: ++parenCount; break; case LANGLE: ++angleCount; break; default: break; } } while (index < symbols.size()) { Token t = symbols.at(index++).token; switch (t) { case LBRACE: ++braceCount; break; case RBRACE: --braceCount; break; case LBRACK: ++brackCount; break; case RBRACK: --brackCount; break; case LPAREN: ++parenCount; break; case RPAREN: --parenCount; break; case LANGLE: ++angleCount; break; case RANGLE: --angleCount; break; case GTGT: angleCount -= 2; t = RANGLE; break; default: break; } if (t == target && braceCount <= 0 && brackCount <= 0 && parenCount <= 0 && (target != RANGLE || angleCount <= 0)) return true; if (braceCount < 0 || brackCount < 0 || parenCount < 0 || (target == RANGLE && angleCount < 0)) { --index; break; } } return false;}void Moc::checkSuperClasses(ClassDef *def){ const QByteArray firstSuperclass = def->superclassList.value(0).first; if (!knownQObjectClasses.contains(firstSuperclass)) { // enable once we /require/ include paths#if 0 QByteArray msg; msg += "Class "; msg += def->className; msg += " contains the Q_OBJECT macro and inherits from "; msg += def->superclassList.value(0); msg += " but that is not a known QObject subclass. You may get compilation errors."; warning(msg.constData()); return;#endif } for (int i = 1; i < def->superclassList.count(); ++i) { const QByteArray superClass = def->superclassList.at(i).first; if (knownQObjectClasses.contains(superClass)) { QByteArray msg; msg += "Class "; msg += def->classname; msg += " inherits from two QObject subclasses "; msg += firstSuperclass; msg += " and "; msg += superClass; msg += ". This is not supported!"; warning(msg.constData()); } if (interface2IdMap.contains(superClass)) { bool registeredInterface = false; for (int i = 0; i < def->interfaceList.count(); ++i) if (def->interfaceList.at(i).first().className == superClass) { registeredInterface = true; break; } if (!registeredInterface) { QByteArray msg; msg += "Class "; msg += def->classname; msg += " implements the interface "; msg += superClass; msg += " but does not list it in Q_INTERFACES. qobject_cast to "; msg += superClass; msg += " will not work!"; warning(msg.constData()); } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -