Remove more ClassInfo goo
Remove more uses of ClassInfo in favor of VM::Class, VM::Func, etc.
Esse commit está contido em:
@@ -7076,7 +7076,7 @@ static Unit* emitHHBCNativeClassUnit(const HhbcExtClassInfo* builtinClasses,
|
||||
Entry e;
|
||||
e.name = const_cast<StringData*>(it->first);
|
||||
e.info = it->second;
|
||||
e.ci = ClassInfo::FindClassInterfaceOrTrait(e.name);
|
||||
e.ci = ClassInfo::FindSystemClassInterfaceOrTrait(e.name);
|
||||
assert(e.ci);
|
||||
StringData* parentName
|
||||
= StringData::GetStaticString(e.ci->getParentClass().get());
|
||||
|
||||
@@ -193,19 +193,6 @@ Array ClassInfo::GetClassLike(unsigned mask, unsigned value) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ClassInfo::ConstantInfo *ClassInfo::FindConstant(CStrRef name) {
|
||||
assert(!name.isNull());
|
||||
assert(s_loaded);
|
||||
const ConstantInfo *info;
|
||||
info = s_systemFuncs->getConstantInfo(name);
|
||||
if (info) return info;
|
||||
if (s_hook) {
|
||||
info = s_hook->findConstant(name);
|
||||
if (info) return info;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClassInfo::ConstantInfo::ConstantInfo() :
|
||||
valueLen(0), callback(nullptr), deferred(true) {
|
||||
}
|
||||
@@ -354,24 +341,6 @@ bool ClassInfo::GetClassMethods(MethodVec &ret, const ClassInfo *classInfo) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClassInfo::GetClassProperties(PropertyMap &props, CStrRef classname) {
|
||||
if (!classname.empty()) {
|
||||
const ClassInfo *classInfo = FindClass(classname);
|
||||
if (classInfo) {
|
||||
classInfo->getAllProperties(props);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassInfo::GetClassProperties(PropertyVec &props, CStrRef classname) {
|
||||
if (!classname.empty()) {
|
||||
const ClassInfo *classInfo = FindClass(classname);
|
||||
if (classInfo) {
|
||||
classInfo->getAllProperties(props);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassInfo::GetClassSymbolNames(CArrRef names, bool interface, bool trait,
|
||||
std::vector<String> &classes,
|
||||
std::vector<String> *clsMethods,
|
||||
@@ -497,70 +466,6 @@ const ClassInfo *ClassInfo::getParentClassInfo() const {
|
||||
return FindClass(parentName);
|
||||
}
|
||||
|
||||
void ClassInfo::getAllParentsVec(ClassVec &parents) const {
|
||||
CStrRef parent = getParentClass();
|
||||
if (!parent.empty()) {
|
||||
parents.push_back(parent);
|
||||
const ClassInfo *info = FindClass(parent);
|
||||
if (info) info->getAllParentsVec(parents);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassInfo::getAllInterfacesVec(InterfaceVec &interfaces) const {
|
||||
CStrRef parent = getParentClass();
|
||||
if (!parent.empty()) {
|
||||
const ClassInfo *info = FindClass(parent);
|
||||
if (info) info->getAllInterfacesVec(interfaces);
|
||||
}
|
||||
|
||||
const InterfaceVec &ifs = getInterfacesVec();
|
||||
for (unsigned int i = 0; i < ifs.size(); i++) {
|
||||
CStrRef intf = ifs[i];
|
||||
interfaces.push_back(intf);
|
||||
const ClassInfo *info = FindInterface(intf);
|
||||
if (info) info->getAllInterfacesVec(interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
bool ClassInfo::derivesFrom(CStrRef name, bool considerInterface) const {
|
||||
assert(!name.isNull());
|
||||
return derivesFromImpl(name, considerInterface);
|
||||
}
|
||||
|
||||
bool ClassInfo::derivesFromImpl(CStrRef name, bool considerInterface) const {
|
||||
if (name->isame(getParentClass().get())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const ClassInfo *parent = getParentClassInfo();
|
||||
if (parent && parent->derivesFromImpl(name, considerInterface)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (considerInterface) {
|
||||
const InterfaceSet &interfaces = getInterfaces();
|
||||
for (InterfaceSet::const_iterator iter = interfaces.begin();
|
||||
iter != interfaces.end(); ++iter) {
|
||||
if (name->isame(iter->get())) {
|
||||
return true;
|
||||
}
|
||||
const ClassInfo *parent = FindInterface(*iter);
|
||||
if (parent && parent->derivesFromImpl(name, considerInterface)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClassInfo::IsSubClass(CStrRef className1, CStrRef className2,
|
||||
bool considerInterface) {
|
||||
const ClassInfo *clsInfo1 = ClassInfo::FindClass(className1);
|
||||
if (!clsInfo1) return false;
|
||||
|
||||
return clsInfo1->derivesFrom(className2, considerInterface);
|
||||
}
|
||||
|
||||
ClassInfo::MethodInfo *ClassInfo::getMethodInfo(CStrRef name) const {
|
||||
assert(!name.isNull());
|
||||
|
||||
@@ -603,133 +508,6 @@ const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// internal function className::methodName or callObject->methodName
|
||||
bool ClassInfo::HasAccess(CStrRef className, CStrRef methodName,
|
||||
bool staticCall, bool hasCallObject) {
|
||||
// It has to be either a static call or a call with an object.
|
||||
assert(staticCall || hasCallObject);
|
||||
const ClassInfo *clsInfo = ClassInfo::FindClass(className);
|
||||
if (!clsInfo) return false;
|
||||
ClassInfo *defClass;
|
||||
ClassInfo::MethodInfo *methodInfo =
|
||||
clsInfo->hasMethod(methodName, defClass);
|
||||
if (!methodInfo) return false;
|
||||
if (methodInfo->attribute & ClassInfo::IsPublic) return true;
|
||||
VM::Class* ctx = g_vmContext->getContextClass();
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
const ClassInfo *ctxClass = ClassInfo::FindClass(ctx->nameRef());
|
||||
bool hasObject = hasCallObject || g_vmContext->getThis();
|
||||
if (ctxClass) {
|
||||
return ctxClass->checkAccess(defClass, methodInfo, staticCall, hasObject);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClassInfo::checkAccess(ClassInfo *defClass,
|
||||
MethodInfo *methodInfo,
|
||||
bool staticCall,
|
||||
bool hasObject) const {
|
||||
assert(defClass && methodInfo);
|
||||
if ((m_name->isame(defClass->m_name.get()))) {
|
||||
if (methodInfo->attribute & ClassInfo::IsStatic) return true;
|
||||
return hasObject;
|
||||
}
|
||||
|
||||
if (methodInfo->attribute & ClassInfo::IsStatic) {
|
||||
if (methodInfo->attribute & ClassInfo::IsPublic) return true;
|
||||
if (methodInfo->attribute & ClassInfo::IsProtected) {
|
||||
return derivesFrom(defClass->m_name, false) ||
|
||||
defClass->derivesFrom(m_name, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!hasObject && !staticCall) return false;
|
||||
if (methodInfo->attribute & ClassInfo::IsPublic) return true;
|
||||
if (methodInfo->attribute & ClassInfo::IsProtected) {
|
||||
return derivesFrom(defClass->m_name, false) ||
|
||||
defClass->derivesFrom(m_name, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ClassInfo::getAllProperties(PropertyMap &props) const {
|
||||
const PropertyMap &properties = getProperties();
|
||||
props.insert(properties.begin(), properties.end());
|
||||
|
||||
CStrRef parentClass = getParentClass();
|
||||
if (!parentClass.empty()) {
|
||||
GetClassProperties(props, parentClass);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassInfo::getAllProperties(PropertyVec &props) const {
|
||||
const PropertyVec &properties = getPropertiesVec();
|
||||
props.insert(props.end(), properties.begin(), properties.end());
|
||||
|
||||
CStrRef parentClass = getParentClass();
|
||||
if (!parentClass.empty()) {
|
||||
GetClassProperties(props, parentClass);
|
||||
}
|
||||
}
|
||||
|
||||
void ClassInfo::filterProperties(Array &props, Attribute toRemove) const {
|
||||
const PropertyVec &properties = getPropertiesVec();
|
||||
for (unsigned i = 0; i < properties.size(); i++) {
|
||||
if (properties[i]->attribute & toRemove) {
|
||||
props.remove(properties[i]->name, true);
|
||||
}
|
||||
}
|
||||
const ClassInfo *parent = getParentClassInfo();
|
||||
if (parent) {
|
||||
parent->filterProperties(props, toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
ClassInfo::PropertyInfo *ClassInfo::getPropertyInfo(CStrRef name) const {
|
||||
assert(!name.isNull());
|
||||
const PropertyMap &properties = getProperties();
|
||||
PropertyMap::const_iterator iter = properties.find(name);
|
||||
if (iter != properties.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ClassInfo::hasProperty(CStrRef name) const {
|
||||
assert(!name.isNull());
|
||||
const PropertyMap &properties = getProperties();
|
||||
return properties.find(name) != properties.end();
|
||||
}
|
||||
|
||||
ClassInfo::ConstantInfo *ClassInfo::getConstantInfo(CStrRef name) const {
|
||||
assert(!name.isNull());
|
||||
const ConstantMap &constants = getConstants();
|
||||
ConstantMap::const_iterator iter = constants.find(name);
|
||||
if (iter != constants.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool ClassInfo::hasConstant(CStrRef name) const {
|
||||
assert(!name.isNull());
|
||||
const ConstantMap &constants = getConstants();
|
||||
return constants.find(name) != constants.end();
|
||||
}
|
||||
|
||||
bool ClassInfo::PropertyInfo::isVisible(const ClassInfo *context) const {
|
||||
if ((attribute & ClassInfo::IsPublic) || context == owner) return true;
|
||||
if (!context) return false;
|
||||
if (attribute & ClassInfo::IsProtected) {
|
||||
return owner->derivesFrom(context->getName(), false) ||
|
||||
context->derivesFrom(owner->getName(), false);
|
||||
}
|
||||
assert(attribute & ClassInfo::IsPrivate);
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// load functions
|
||||
|
||||
@@ -1042,14 +820,5 @@ ClassInfo::MethodInfo::~MethodInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
void ClassInfo::GetArray(const ObjectData *obj,
|
||||
Array &props, GetArrayKind kind) {
|
||||
obj->o_getArray(props, !(kind & GetArrayPrivate));
|
||||
}
|
||||
|
||||
void ClassInfo::SetArray(ObjectData *obj, CArrRef props) {
|
||||
obj->o_setArray(props);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
@@ -84,13 +84,6 @@ public:
|
||||
NeedsActRec = (1u << 31),// x x
|
||||
};
|
||||
|
||||
enum GetArrayKind {
|
||||
GetArrayNone = 0,
|
||||
GetArrayPrivate = 1,
|
||||
GetArrayPublic = 2,
|
||||
GetArrayAll = GetArrayPrivate|GetArrayPublic
|
||||
};
|
||||
|
||||
class ConstantInfo {
|
||||
public:
|
||||
ConstantInfo();
|
||||
@@ -170,7 +163,6 @@ public:
|
||||
DataType type;
|
||||
const char *docComment;
|
||||
const ClassInfo *owner;
|
||||
bool isVisible(const ClassInfo *context) const;
|
||||
};
|
||||
|
||||
typedef StringIMap<ClassInfo *> ClassMap;
|
||||
@@ -215,10 +207,6 @@ public:
|
||||
*/
|
||||
static Array GetClasses() { return GetClassLike(IsInterface|IsTrait, 0); }
|
||||
|
||||
static bool HasClassInterfaceOrTrait(CStrRef name) {
|
||||
return FindClassInterfaceOrTrait(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate one class.
|
||||
*/
|
||||
@@ -269,11 +257,6 @@ public:
|
||||
*/
|
||||
static const ClassInfo *FindSystemClassInterfaceOrTrait(CStrRef name);
|
||||
|
||||
/**
|
||||
* Locate one constant (excluding dynamic and redeclared constants)
|
||||
*/
|
||||
static const ConstantInfo *FindConstant(CStrRef name);
|
||||
|
||||
/**
|
||||
* Get all statically known constants
|
||||
*/
|
||||
@@ -293,13 +276,6 @@ public:
|
||||
static bool GetClassMethods(MethodVec &ret, CStrRef classname, int type = 0);
|
||||
static bool GetClassMethods(MethodVec &ret, const ClassInfo *classInfo);
|
||||
|
||||
/**
|
||||
* Return all properties a class has, including the ones on base classes and
|
||||
* the ones that were implicitly defined.
|
||||
*/
|
||||
static void GetClassProperties(PropertyMap &props, CStrRef classname);
|
||||
static void GetClassProperties(PropertyVec &props, CStrRef classname);
|
||||
|
||||
/**
|
||||
* Read user attributes in from the class map.
|
||||
*/
|
||||
@@ -321,13 +297,6 @@ public:
|
||||
std::vector<String> *clsProperties,
|
||||
std::vector<String> *clsConstants);
|
||||
|
||||
static void GetArray(const ObjectData *obj,
|
||||
Array &props, GetArrayKind kind);
|
||||
static void GetArray(const ObjectData *obj,
|
||||
Array &props, bool pubOnly) {
|
||||
GetArray(obj, props, pubOnly ? GetArrayPublic : GetArrayAll);
|
||||
}
|
||||
static void SetArray(ObjectData *obj, CArrRef props);
|
||||
static void SetHook(ClassInfoHook *hook) { s_hook = hook; }
|
||||
|
||||
static Variant GetVariant(DataType type, const void *addr) {
|
||||
@@ -379,10 +348,6 @@ public:
|
||||
virtual const TraitSet &getTraits() const = 0;
|
||||
virtual const TraitVec &getTraitsVec() const = 0;
|
||||
virtual const TraitAliasVec &getTraitAliasesVec() const = 0;
|
||||
bool derivesFrom(CStrRef name, bool considerInterface) const;
|
||||
|
||||
void getAllParentsVec(ClassVec &parents) const; // recursive
|
||||
void getAllInterfacesVec(InterfaceVec &interfaces) const; // recursive
|
||||
|
||||
/**
|
||||
* Method functions.
|
||||
@@ -393,30 +358,18 @@ public:
|
||||
MethodInfo *hasMethod(CStrRef name,
|
||||
ClassInfo *&classInfo,
|
||||
bool interfaces = false) const;
|
||||
static bool HasAccess(CStrRef className, CStrRef methodName,
|
||||
bool staticCall, bool hasCallObject);
|
||||
static bool IsSubClass(CStrRef className1, CStrRef className2,
|
||||
bool considerInterface);
|
||||
|
||||
/**
|
||||
* Property functions.
|
||||
*/
|
||||
virtual const PropertyMap &getProperties() const = 0; // non-recursively
|
||||
virtual const PropertyVec &getPropertiesVec() const = 0; // non-recursively
|
||||
void getAllProperties(PropertyMap &props) const; // recursively
|
||||
void getAllProperties(PropertyVec &props) const; // recursively
|
||||
// Remove properties with the given attribute from the array, recursively.
|
||||
void filterProperties(Array &props, Attribute toRemove) const;
|
||||
PropertyInfo *getPropertyInfo(CStrRef name) const;
|
||||
bool hasProperty(CStrRef name) const;
|
||||
|
||||
/**
|
||||
* Constant functions.
|
||||
*/
|
||||
virtual const ConstantMap &getConstants() const = 0;
|
||||
virtual const ConstantVec &getConstantsVec() const = 0;
|
||||
ConstantInfo *getConstantInfo(CStrRef name) const;
|
||||
bool hasConstant(CStrRef name) const;
|
||||
|
||||
virtual const UserAttributeVec &getUserAttributeVec() const = 0;
|
||||
|
||||
@@ -437,10 +390,6 @@ protected:
|
||||
int m_line2;
|
||||
const char *m_docComment;
|
||||
|
||||
bool derivesFromImpl(CStrRef name, bool considerInterface) const;
|
||||
bool checkAccess(ClassInfo *defClass, MethodInfo *methodInfo,
|
||||
bool staticCall, bool hasObject) const;
|
||||
|
||||
private:
|
||||
static ClassMap s_class_like; // all classes, interfaces and traits
|
||||
static Array GetClassLike(unsigned mask, unsigned value);
|
||||
|
||||
@@ -386,7 +386,7 @@ Object ObjectData::FromArray(ArrayData *properties) {
|
||||
|
||||
Array ObjectData::o_toArray() const {
|
||||
Array ret(ArrayData::Create());
|
||||
ClassInfo::GetArray(this, ret, ClassInfo::GetArrayAll);
|
||||
o_getArray(ret, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ ImmutableObj::ImmutableObj(ObjectData *obj) {
|
||||
assert(!obj->instanceof(SystemLib::s_SerializableClass));
|
||||
m_cls = obj->o_getClassName()->copy(true);
|
||||
Array props;
|
||||
ClassInfo::GetArray(obj, props, ClassInfo::GetArrayAll);
|
||||
obj->o_getArray(props, false);
|
||||
m_propCount = 0;
|
||||
if (props.empty()) {
|
||||
m_props = nullptr;
|
||||
@@ -73,7 +73,7 @@ Object ImmutableObj::getObject() {
|
||||
true);
|
||||
}
|
||||
Array v = ai.create();
|
||||
ClassInfo::SetArray(obj.get(), v);
|
||||
obj->o_setArray(v);
|
||||
obj->t___wakeup();
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ void VariableSerializer::write(CObjRef v) {
|
||||
collectionSerialize(v.get(), this);
|
||||
} else {
|
||||
Array props(ArrayData::Create());
|
||||
ClassInfo::GetArray(v.get(), props, ClassInfo::GetArrayPublic);
|
||||
v->o_getArray(props, true);
|
||||
setObjectInfo(v->o_getClassName(), v->o_getId(), 'O');
|
||||
props.serialize(this);
|
||||
}
|
||||
|
||||
@@ -1589,7 +1589,7 @@ Variant f_mysql_fetch_object(CVarRef result,
|
||||
Variant properties = php_mysql_fetch_hash(result, MYSQL_ASSOC);
|
||||
if (!same(properties, false)) {
|
||||
Object obj = create_object(class_name, params);
|
||||
ClassInfo::SetArray(obj.get(), properties);
|
||||
obj->o_setArray(properties);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -140,82 +140,64 @@ Variant f_hphp_get_this() {
|
||||
}
|
||||
|
||||
Variant f_class_implements(CVarRef obj, bool autoload /* = true */) {
|
||||
String clsname;
|
||||
VM::Class* cls;
|
||||
if (obj.isString()) {
|
||||
clsname = obj.toString();
|
||||
cls = VM::Unit::getClass(obj.getStringData(), autoload);
|
||||
if (!cls) {
|
||||
return false;
|
||||
}
|
||||
} else if (obj.isObject()) {
|
||||
clsname = obj.toObject()->o_getClassName();
|
||||
cls = obj.getObjectData()->getVMClass();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname);
|
||||
if (info == NULL) {
|
||||
if (!autoload) return false;
|
||||
AutoloadHandler::s_instance->invokeHandler(clsname);
|
||||
return f_class_implements(clsname, false);
|
||||
}
|
||||
|
||||
Array ret(Array::Create());
|
||||
ClassInfo::InterfaceVec ifs;
|
||||
info->getAllInterfacesVec(ifs);
|
||||
for (unsigned int i = 0; i < ifs.size(); i++) {
|
||||
ret.set(ifs[i], ifs[i]);
|
||||
for (auto& elem : cls->allInterfaces()) {
|
||||
// For the case where cls is an interface, we don't want to
|
||||
// include cls in the array we return
|
||||
if (elem == cls) continue;
|
||||
ret.set(elem->nameRef(), elem->nameRef());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Variant f_class_parents(CVarRef obj, bool autoload /* = true */) {
|
||||
String clsname;
|
||||
VM::Class* cls;
|
||||
if (obj.isString()) {
|
||||
clsname = obj.toString();
|
||||
cls = VM::Unit::getClass(obj.getStringData(), autoload);
|
||||
if (!cls) {
|
||||
return false;
|
||||
}
|
||||
} else if (obj.isObject()) {
|
||||
clsname = obj.toObject()->o_getClassName();
|
||||
cls = obj.getObjectData()->getVMClass();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname);
|
||||
if (info == NULL) {
|
||||
if (!autoload) return false;
|
||||
AutoloadHandler::s_instance->invokeHandler(clsname);
|
||||
return f_class_parents(clsname, false);
|
||||
}
|
||||
|
||||
Array ret(Array::Create());
|
||||
ClassInfo::ClassVec parents;
|
||||
info->getAllParentsVec(parents);
|
||||
for (unsigned int i = 0; i < parents.size(); i++) {
|
||||
ret.set(parents[i], parents[i]);
|
||||
for (cls = cls->parent(); cls; cls = cls->parent()) {
|
||||
auto& clsName = cls->nameRef();
|
||||
ret.set(clsName, clsName);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Variant f_class_uses(CVarRef obj, bool autoload /* = true */) {
|
||||
String clsname;
|
||||
VM::Class* cls;
|
||||
if (obj.isString()) {
|
||||
clsname = obj.toString();
|
||||
cls = VM::Unit::getClass(obj.getStringData(), autoload);
|
||||
if (!cls) {
|
||||
return false;
|
||||
}
|
||||
} else if (obj.isObject()) {
|
||||
clsname = obj.toObject()->o_getClassName();
|
||||
cls = obj.getObjectData()->getVMClass();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ClassInfo *info = ClassInfo::FindClassInterfaceOrTrait(clsname);
|
||||
if (!info) {
|
||||
if (!autoload) return false;
|
||||
AutoloadHandler::s_instance->invokeHandler(clsname);
|
||||
return f_class_uses(clsname, false);
|
||||
}
|
||||
|
||||
Array ret(Array::Create());
|
||||
const ClassInfo::TraitVec &traits = info->getTraitsVec();
|
||||
for (unsigned int i = 0; i < traits.size(); i++) {
|
||||
ret.set(traits[i], traits[i]);
|
||||
for (auto& elem : cls->usedTraits()) {
|
||||
auto& traitName = elem.get()->nameRef();
|
||||
ret.set(traitName, traitName);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ private:
|
||||
bool rename(const StringData* old, const StringData* n3w);
|
||||
bool isFunctionRenameable(const StringData* name);
|
||||
void addRenameableFunctions(ArrayData* arr);
|
||||
|
||||
//Array getUserFunctions();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário