Arquivos
hhvm/hphp/runtime/base/class_info.h
T
2013-03-18 16:05:53 -07:00

506 linhas
17 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef __HPHP_CLASS_INFO_H__
#define __HPHP_CLASS_INFO_H__
#include <runtime/base/types.h>
#include <runtime/base/complex_types.h>
#include <util/mutex.h>
#include <util/case_insensitive.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
class ClassInfoHook;
/**
* Though called "ClassInfo", we consider global scope as a virtual "class".
* Therefore, this is the place we store meta information of both global
* functions and class methods and properties.
*/
class ClassInfo {
public:
enum Attribute { // class prop func method param
IsOverride = (1 << 0), // x
IsRedeclared = (1 << 1), // x x
IsVolatile = (1 << 2), // x x
IsInterface = (1 << 3), // x
IsClosure = (1 << 3), // x x
IsAbstract = (1 << 4), // x x
IsFinal = (1 << 5), // x x
IsPublic = (1 << 6), // x x
IsProtected = (1 << 7), // x x
IsPrivate = (1 << 8), // x x
IsStatic = (1 << 9), // x x
// FIXME (#2163116): IsCppAbstract = (1 << 10) in idl/base.php
IsInherited = (1 << 10), // x
HasCall = IsPublic, // x
HasCallStatic = IsProtected,// x
IgnoreRedefinition = IsPrivate, // x
IsReference = (1 << 11), // x x x
IsConstructor = (1 << 12), // x
// need a non-zero number for const char * maps
IsNothing = (1 << 13),
HasDocComment = (1 << 14), // x x
IsLazyInit = (1 << 15), // x
HasGeneratorAsBody = (1 << 15), // x x
HipHopSpecific = (1 << 16), // x x
VariableArguments = (1 << 17), // x x
RefVariableArguments = (1 << 18), // x x
MixedVariableArguments = (1 << 19), // x x
FunctionIsFoldable = (1 << 20), // x
NoEffect = (1 << 21), // x
NoInjection = (1 << 22), // x x
HasOptFunction = (1 << 23), // x
AllowIntercept = (1 << 24), // x x
NoProfile = (1 << 25), // x x
ContextSensitive = (1 << 26), // x
NoDefaultSweep = (1 << 27), // x
IsSystem = (1 << 28), // x x
IsTrait = (1 << 29), // x
UsesTraits = (1 << 30), // x
HasAliasedMethods = (1u << 31),// x
NeedsActRec = (1u << 31),// x x
};
enum GetArrayKind {
GetArrayNone = 0,
GetArrayPrivate = 1,
GetArrayPublic = 2,
GetArrayAll = GetArrayPrivate|GetArrayPublic
};
class ConstantInfo {
public:
ConstantInfo();
String name;
unsigned int valueLen;
const char *valueText;
const void* callback;
Variant getValue() const;
void setValue(CVarRef value);
void setStaticValue(CVarRef value);
private:
bool deferred;
Variant value;
std::string svalue; // serialized, only used by eval
};
class UserAttributeInfo {
public:
UserAttributeInfo();
String name;
Variant getValue() const;
void setStaticValue(CVarRef value);
private:
Variant value;
};
struct ParameterInfo {
~ParameterInfo();
Attribute attribute;
DataType argType; // hinted arg type
const char *name;
const char *type; // hinted type string
const char *value; // serialized default value
const char *valueText; // original PHP code
std::vector<const UserAttributeInfo *> userAttrs;
};
struct MethodInfo {
MethodInfo() : docComment(nullptr) {}
MethodInfo(const char **&p);
~MethodInfo();
MethodInfo *getDeclared();
Attribute attribute;
int volatile_redec_offset;
String name;
std::vector<const ParameterInfo *> parameters;
std::vector<const ConstantInfo *> staticVariables;
std::vector<const UserAttributeInfo *> userAttrs;
const char *docComment;
const char *file;
int line1;
int line2;
DataType returnType;
};
class PropertyInfo {
public:
PropertyInfo() : docComment(nullptr) {}
Attribute attribute;
String name;
const char *docComment;
const ClassInfo *owner;
bool isVisible(const ClassInfo *context) const;
};
typedef StringIMap<ClassInfo *> ClassMap;
typedef std::vector<String> ClassVec;
typedef StringISet InterfaceSet;
typedef std::vector<String> InterfaceVec;
typedef StringISet TraitSet;
typedef std::vector<String> TraitVec;
typedef StringIMap<MethodInfo *> MethodMap;
typedef std::vector<MethodInfo *> MethodVec;
typedef StringMap<PropertyInfo *> PropertyMap;
typedef std::vector<PropertyInfo *> PropertyVec;
typedef StringMap<ConstantInfo *> ConstantMap;
typedef std::vector<ConstantInfo *> ConstantVec;
typedef std::vector<UserAttributeInfo *> UserAttributeVec;
typedef std::vector<std::pair<String, String> > TraitAliasVec;
public:
/**
* Load everything.
*/
static void Load();
/**
* Return a list of PHP library functions.
*/
static Array GetSystemFunctions();
/**
* Return a list of user defined functions.
*/
static Array GetUserFunctions();
/**
* Locate one function.
*/
static const MethodInfo *FindSystemFunction(CStrRef name);
static const MethodInfo *FindFunction(CStrRef name);
/**
* Return a list of declared classes.
*/
static Array GetClasses() { return GetClassLike(IsInterface|IsTrait, 0); }
static bool HasClassInterfaceOrTrait(CStrRef name) {
return FindClassInterfaceOrTrait(name);
}
/**
* Locate one class.
*/
static const ClassInfo *FindClass(CStrRef name);
/**
* Locate one system class.
*/
static const ClassInfo *FindSystemClass(CStrRef name);
/**
* Return a list of declared interfaces.
*/
static Array GetInterfaces() { return GetClassLike(IsInterface, IsInterface); }
/**
* Return a list of declared traits.
*/
static Array GetTraits() { return GetClassLike(IsTrait, IsTrait); }
/**
* Locate one interface.
*/
static const ClassInfo *FindInterface(CStrRef name);
/**
* Locate one system interface.
*/
static const ClassInfo *FindSystemInterface(CStrRef name);
/**
* Locate one trait.
*/
static const ClassInfo *FindTrait(CStrRef name);
/**
* Locate one system trait.
*/
static const ClassInfo *FindSystemTrait(CStrRef name);
/**
* Locate either a class, interface, or trait.
*/
static const ClassInfo *FindClassInterfaceOrTrait(CStrRef name);
/**
* Locate either a system class, system interface, or system trait.
*/
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
*/
static Array GetConstants();
/**
* Get all statically known system constants
*/
static Array GetSystemConstants();
/**
* Return all methods a class has, including the ones on base classes and
* interfaces.
* type: 0: unknown; 1: class; 2: interface
*/
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.
*/
static void ReadUserAttributes(const char **&p,
std::vector<const UserAttributeInfo*> &attrs);
/**
* Return lists of names for auto-complete purposes.
*/
static void GetClassSymbolNames(CArrRef names, bool interface, bool trait,
std::vector<String> &classes,
std::vector<String> *clsMethods,
std::vector<String> *clsProperties,
std::vector<String> *clsConstants);
static void GetSymbolNames(std::vector<String> &classes,
std::vector<String> &functions,
std::vector<String> &constants,
std::vector<String> *clsMethods,
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) {
switch (type) {
case KindOfBoolean:
return *(bool*)addr;
case KindOfInt64:
return *(int64_t*)addr;
case KindOfDouble:
return *(double*)addr;
case KindOfString:
return *(String*)addr;
case KindOfArray:
return *(Array*)addr;
case KindOfObject:
return *(Object*)addr;
default:
assert(false);
return uninit_null();
}
}
public:
ClassInfo() : m_cdec_offset(0), m_docComment(nullptr) {}
virtual ~ClassInfo() {}
inline const ClassInfo *checkCurrent() const {
assert(!(m_attribute & IsRedeclared));
return this;
}
Attribute getAttribute() const { return checkCurrent()->m_attribute;}
const char *getFile() const { return checkCurrent()->m_file;}
int getLine1() const { return checkCurrent()->m_line1;}
int getLine2() const { return checkCurrent()->m_line2;}
virtual const ClassInfo* getCurrentOrNull() const { return this; }
virtual CStrRef getName() const { return m_name;}
const char *getDocComment() const { return m_docComment; }
virtual void postInit();
/**
* Parents of this class.
*/
virtual CStrRef getParentClass() const = 0;
const ClassInfo *getParentClassInfo() const;
virtual const InterfaceSet &getInterfaces() const = 0;
virtual const InterfaceVec &getInterfacesVec() const = 0;
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.
*/
virtual const MethodMap &getMethods() const = 0; // non-recursively
virtual const MethodVec &getMethodsVec() const = 0; // non-recursively
MethodInfo *getMethodInfo(CStrRef name) const;
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);
const char *getConstructor() const;
/**
* 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;
protected:
static bool s_loaded; // whether class map is loaded
static ClassInfo *s_systemFuncs; // all system functions
static ClassInfoHook *s_hook;
Attribute m_attribute;
int m_cdec_offset;
String m_name;
const char *m_file;
int m_line1;
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);
const ClassInfo *getDeclared() const;
};
/**
* Stores info about a class that appears once in the codebase.
*/
class ClassInfoUnique : public ClassInfo {
public:
/**
* Read one class's information from specified map pointer and move it.
*/
ClassInfoUnique(const char **&p);
virtual ~ClassInfoUnique();
// implementing ClassInfo
CStrRef getParentClass() const { return m_parent;}
const ClassInfo *getParentClassInfo() const;
const InterfaceSet &getInterfaces() const { return m_interfaces;}
const InterfaceVec &getInterfacesVec() const { return m_interfacesVec;}
const TraitSet &getTraits() const { return m_traits;}
const TraitVec &getTraitsVec() const { return m_traitsVec;}
const TraitAliasVec &getTraitAliasesVec() const { return m_traitAliasesVec;}
const MethodMap &getMethods() const { return m_methods;}
const MethodVec &getMethodsVec() const { return m_methodsVec;}
const PropertyMap &getProperties() const { return m_properties;}
const PropertyVec &getPropertiesVec() const { return m_propertiesVec;}
const ConstantMap &getConstants() const { return m_constants;}
const ConstantVec &getConstantsVec() const { return m_constantsVec;}
const UserAttributeVec &getUserAttributeVec() const { return m_userAttrVec;}
virtual void postInit();
private:
String m_parent; // parent class name
const ClassInfo *m_parentInfo; // parent class info (or null)
InterfaceSet m_interfaces; // all interfaces
InterfaceVec m_interfacesVec; // all interfaces in declaration order
TraitSet m_traits; // all used traits
TraitVec m_traitsVec; // all used traits
TraitAliasVec m_traitAliasesVec; // all trait aliases
MethodMap m_methods; // all methods
MethodVec m_methodsVec; // all methods in declaration order
PropertyMap m_properties; // all properties
PropertyVec m_propertiesVec; // all properties in declaration order
ConstantMap m_constants; // all constants
ConstantVec m_constantsVec; // all constants in declaration order
UserAttributeVec m_userAttrVec;
};
/**
* Interface for a hook into class info for eval. This way I can avoid
* a dependency on eval.
*/
class ClassInfoHook {
public:
virtual ~ClassInfoHook() {};
virtual Array getUserFunctions() const = 0;
virtual Array getClasses() const = 0;
virtual Array getInterfaces() const = 0;
virtual Array getTraits() const = 0;
virtual Array getConstants() const = 0;
virtual const ClassInfo::MethodInfo *findFunction(CStrRef name) const = 0;
virtual const ClassInfo *findClassLike(CStrRef name) const = 0;
virtual const ClassInfo::ConstantInfo *findConstant(CStrRef name) const = 0;
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // __HPHP_CLASS_INFO_H__