const EnumCache::EnumValues* EnumCache::loadEnumValues(const Class* klass, bool recurse) { auto const numConstants = klass->numConstants(); size_t foundOnClass = 0; Array values; Array names; auto const consts = klass->constants(); for (size_t i = 0; i < numConstants; i++) { if (consts[i].isAbstract() || consts[i].isType()) { continue; } if (consts[i].m_class == klass) foundOnClass++; else if (!recurse) continue; Cell value = consts[i].m_val; // Handle dynamically set constants if (value.m_type == KindOfUninit) { value = klass->clsCnsGet(consts[i].m_name); } assert(value.m_type != KindOfUninit); if (UNLIKELY(!(isIntType(value.m_type) || (tvIsString(&value) && value.m_data.pstr->isStatic())))) { // only int and string values allowed for enums. Moreover the strings // must be static std::string msg; msg += klass->name()->data(); msg += " enum can only contain static string and int values"; EnumCache::failLookup(msg); } values.set(StrNR(consts[i].m_name), cellAsCVarRef(value)); names.set(cellAsCVarRef(value), VarNR(consts[i].m_name)); } if (UNLIKELY(foundOnClass == 0)) { std::string msg; msg += klass->name()->data(); msg += " enum must contain values"; EnumCache::failLookup(msg); } { std::unique_ptr<EnumCache::EnumValues> enums(new EnumCache::EnumValues()); enums->values = ArrayData::GetScalarArray(values.get()); enums->names = ArrayData::GetScalarArray(names.get()); intptr_t key = getKey(klass, recurse); EnumValuesMap::accessor acc; if (!m_enumValuesMap.insert(acc, key)) { return acc->second; } // add to the map the newly created values acc->second = enums.release(); return acc->second; } }
const EnumValues* EnumCache::cachePersistentEnumValues( const Class* klass, bool recurse, Array&& names, Array&& values) { std::unique_ptr<EnumValues> enums(new EnumValues()); enums->values = ArrayData::GetScalarArray(values.get()); enums->names = ArrayData::GetScalarArray(names.get()); if (!recurse) { return const_cast<Class*>(klass)->setEnumValues(enums.release()); } intptr_t key = getKey(klass, recurse); EnumValuesMap::accessor acc; if (!m_enumValuesMap.insert(acc, key)) { return acc->second; } // add to the map the newly created values acc->second = enums.release(); return acc->second; }
QList<Section> QsCodeMarker::sections( const InnerNode *inner, SynopsisStyle style, Status status ) { QList<Section> sections; if (inner->type() != Node::Class) return sections; const ClassNode *classe = static_cast<const ClassNode *>(inner); if ( style == Summary ) { FastSection enums(classe, "Enums", "", "enum", "enums"); FastSection functions(classe, "Functions", "", "function", "functions"); FastSection readOnlyProperties(classe, "", "Read-Only Properties", "property", "properties"); FastSection signalz(classe, "Signals", "", "signal", "signals"); FastSection writableProperties(classe, "", "Writable Properties", "property", "properties"); QStack<const ClassNode *> stack; stack.push( classe ); while ( !stack.isEmpty() ) { const ClassNode *ancestorClass = stack.pop(); NodeList::ConstIterator c = ancestorClass->childNodes().begin(); while ( c != ancestorClass->childNodes().end() ) { if ( (*c)->access() == Node::Public ) { if ( (*c)->type() == Node::Enum ) { insert( enums, *c, style, status ); } else if ( (*c)->type() == Node::Function ) { const FunctionNode *func = (const FunctionNode *) *c; if ( func->metaness() == FunctionNode::Signal ) { insert( signalz, *c, style, status ); } else { insert( functions, *c, style, status ); } } else if ( (*c)->type() == Node::Property ) { const PropertyNode *property = (const PropertyNode *) *c; if ( property->setters().isEmpty() ) { insert( readOnlyProperties, *c, style, status ); } else { insert( writableProperties, *c, style, status ); } } } ++c; } QList<RelatedClass>::ConstIterator r = ancestorClass->baseClasses().begin(); while ( r != ancestorClass->baseClasses().end() ) { stack.prepend( (*r).node ); ++r; } } append( sections, enums ); append( sections, writableProperties ); append( sections, readOnlyProperties ); append( sections, functions ); append( sections, signalz ); } else if ( style == Detailed ) { FastSection enums( classe, "Enum Documentation", "", "member", "members"); FastSection functionsAndSignals( classe, "Function and Signal Documentation", "", "member", "members"); FastSection properties( classe, "Property Documentation", "", "member", "members"); NodeList::ConstIterator c = classe->childNodes().begin(); while ( c != classe->childNodes().end() ) { if ( (*c)->access() == Node::Public ) { if ( (*c)->type() == Node::Enum ) { insert( enums, *c, style, status ); } else if ( (*c)->type() == Node::Function ) { insert( functionsAndSignals, *c, style, status ); } else if ( (*c)->type() == Node::Property ) { insert( properties, *c, style, status ); } } ++c; } append( sections, enums ); append( sections, properties ); append( sections, functionsAndSignals ); } else { // ( style == SeparateList ) FastSection all(classe, "", "", "member", "members"); QStack<const ClassNode *> stack; stack.push( classe ); while ( !stack.isEmpty() ) { const ClassNode *ancestorClass = stack.pop(); NodeList::ConstIterator c = ancestorClass->childNodes().begin(); while ( c != ancestorClass->childNodes().end() ) { if ( (*c)->access() == Node::Public ) insert( all, *c, style, status ); ++c; } QList<RelatedClass>::ConstIterator r = ancestorClass->baseClasses().begin(); while ( r != ancestorClass->baseClasses().end() ) { stack.prepend( (*r).node ); ++r; } } append( sections, all ); } return sections; }