static fbstring genDocComment(const PhpFunc& func, const fbstring& classname) { fbstring ret(genDocCommentPreamble(func.getPhpName(), func.getDesc(), func.flags(), classname)); for (auto ¶m : func.params()) { ret += "@" + param.name() + " " + param.getPhpType() + " "; if (param.isRef()) { ret += "(output) "; } ret += param.getDesc() + "\n"; } if (func.numParams() > 0) { ret += "\n"; } auto rko = func.returnKindOf(); if ((rko != KindOfNull) && (rko != KindOfInvalid)) { ret += "@return " + func.returnPhpType() + " "; if (func.isReturnRef()) { ret += "(output) "; } ret += func.returnDesc() + "\n"; } return formatDocComment(ret); }
static void writeFunction(std::ostream& out, const PhpFunc& func) { auto flags = (func.flags() & FUNC_FLAG_MASK) | IsSystem | IsNothing; if (flags & RefVariableArguments) { flags |= VariableArguments; } if (flags & MixedVariableArguments) { flags |= RefVariableArguments | VariableArguments; } if (!func.isMethod() || !(flags & VISIBILITY_MASK)) { flags |= IsPublic; } if (func.isReturnRef()) { flags |= IsReference; } out << " " << castLong(flags, true) << ", \"" << escapeCpp(func.getPhpName()) << "\", " << "\"\", " << castLong(0) << ", " << castLong(0) << ",\n"; out << " \"" << escapeCpp(genDocComment(func, func.className())) << "\",\n"; DataType rko = func.returnKindOf(); if (rko == KindOfAny) { // ClassInfo::MethodInfo expects this for Any/Variant // TODO: Fix that broken assumption rko = KindOfInvalid; } out << " " << castLong(rko, true) << ",\n"; for (auto &p : func.params()) { long attr = IsNothing; DataType ko = p.kindOf(); if (p.isRef()) { // We don't declare param type as KindOfRef // as then the caller will try to cast it as such attr |= IsReference; ko = KindOfAny; } if (ko == KindOfAny) { // TODO: See above ko = KindOfInvalid; } out << " " << castLong(attr, true) << ", " << "\"" << escapeCpp(p.name()) << "\", \"\", " << castLong(ko, true) << ",\n"; auto ser = p.getDefaultSerialized(); auto val = p.getDefaultPhp(); out << " " << "\"" << escapeCpp(ser) << "\", " << castLong(ser.size()) << ", " << "\"" << escapeCpp(val) << "\", " << castLong(val.size()) << ", " << "NULL,\n"; } out << " NULL,\n" << " NULL,\n" << " NULL,\n"; }
PhpFunc PhpFunc::fromDynamic(const folly::dynamic& d, const fbstring& className) { // Better at least have a name auto name = d["name"].asString(); auto args = d.find("args"); auto flags = d.find("flags"); auto ret = d.find("return"); if (args == d.items().end() || !args->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'args'", name).str() ); } if (flags == d.items().end() || !flags->second.isArray()) { throw std::logic_error( folly::format("'{0}' must have an array field 'flags'", name).str() ); } if (ret == d.items().end() || !ret->second.isObject() || ret->second.find("type") == ret->second.items().end()) { throw std::logic_error( folly::format("'{0}' must have an array field 'return', which must have " "a string field 'type'", name).str() ); } auto areVarargs = [](const fbstring& str) { return (str == "VariableArguments" || str == "RefVariableArguments" || str == "MixedVariableArguments"); }; fbvector<PhpParam> params; try { params = std::move(folly::convertTo<fbvector<PhpParam>>(args->second)); } catch (const std::exception& exc) { throw std::logic_error( folly::format("'{0}' has an arg with either 'name' or 'type' field " "missing", name).str() ); } if (name == "__get" || name == "__set" || name == "__isset" || name == "__unset" || name == "__call") { for (auto& param : params) { param.cppType = "HPHP::Variant"; } } auto refIt = d.find("ref"); bool ref = (refIt != d.items().end() && refIt->second.asString() == "true"); PhpFunc retval; retval.name = name; retval.className = className; retval.returnCppType = typeString(ret->second["type"], true); retval.returnByRef = ref; retval.params = params; retval.isVarargs = anyFlags(areVarargs, flags->second); retval.isStatic = false; if (!className.empty()) { auto areStatic = [](const fbstring& str) { return str == "IsStatic"; }; retval.isStatic = anyFlags(areStatic, flags->second); } retval.initComputedProps(); return retval; }