void InterfaceStatement::checkArgumentsToPromote( FileScopeRawPtr scope, ExpressionListPtr promotedParams, int type) { if (!m_stmt) { return; } for (int i = 0; i < m_stmt->getCount(); i++) { MethodStatementPtr meth = dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]); if (meth && meth->isNamed("__construct")) { ExpressionListPtr params = meth->getParams(); if (params) { for (int i = 0; i < params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*params)[i]); if (param->getModifier() != 0) { if (type == T_TRAIT || type == T_INTERFACE) { param->parseTimeFatal(scope, Compiler::InvalidAttribute, "Constructor parameter promotion " "not allowed on traits or interfaces"); } if (promotedParams) { promotedParams->addElement(param); } } } } return; // nothing else to look at } } }
void ClassStatement::onParse(AnalysisResultConstPtr ar, FileScopePtr fs) { ClassScope::KindOf kindOf = ClassScope::KindOf::ObjectClass; switch (m_type) { case T_CLASS: kindOf = ClassScope::KindOf::ObjectClass; break; case T_ABSTRACT: kindOf = ClassScope::KindOf::AbstractClass; break; case T_STATIC: // Slight hack: see comments in hphp.y kindOf = ClassScope::KindOf::UtilClass; break; case T_FINAL: kindOf = ClassScope::KindOf::FinalClass; break; case T_TRAIT: kindOf = ClassScope::KindOf::Trait; break; case T_ENUM: kindOf = ClassScope::KindOf::Enum; break; default: assert(false); } std::vector<std::string> bases; if (!m_originalParent.empty()) { bases.push_back(m_originalParent); } if (m_base) m_base->getStrings(bases); for (auto &b : bases) { ar->parseOnDemandByClass(b); } std::vector<UserAttributePtr> attrs; if (m_attrList) { for (int i = 0; i < m_attrList->getCount(); ++i) { UserAttributePtr a = dynamic_pointer_cast<UserAttribute>((*m_attrList)[i]); attrs.push_back(a); } } StatementPtr stmt = dynamic_pointer_cast<Statement>(shared_from_this()); auto classScope = std::make_shared<ClassScope>( fs, kindOf, m_originalName, m_originalParent, bases, m_docComment, stmt, attrs); setBlockScope(classScope); if (!fs->addClass(ar, classScope)) { m_ignored = true; return; } classScope->setPersistent(false); if (m_stmt) { MethodStatementPtr constructor = nullptr; MethodStatementPtr destructor = nullptr; MethodStatementPtr clone = nullptr; // flatten continuation StatementList into MethodStatements for (int i = 0; i < m_stmt->getCount(); i++) { StatementListPtr stmts = dynamic_pointer_cast<StatementList>((*m_stmt)[i]); if (stmts) { m_stmt->removeElement(i); for (int j = 0; j < stmts->getCount(); j++) { m_stmt->insertElement((*stmts)[j], i + j); } } } for (int i = 0; i < m_stmt->getCount(); i++) { MethodStatementPtr meth = dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]); if (meth) { if (meth->isNamed("__construct")) { constructor = meth; continue; } if (meth->isNamed("__destruct")) { destructor = meth; continue; } if (meth->isNamed("__clone")) { clone = meth; continue; } } if (constructor && destructor && clone) { break; } } for (int i = 0; i < m_stmt->getCount(); i++) { if (!constructor) { MethodStatementPtr meth = dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]); if (meth && meth->isNamed(classScope->getOriginalName()) && !classScope->isTrait()) { // class-name constructor constructor = meth; classScope->setAttribute(ClassScope::ClassNameConstructor); } } IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>((*m_stmt)[i]); ph->onParseRecur(ar, fs, classScope); } if (constructor && constructor->getModifiers()->isStatic()) { constructor->parseTimeFatal(fs, Compiler::InvalidAttribute, "Constructor %s::%s() cannot be static", classScope->getOriginalName().c_str(), constructor->getOriginalName().c_str()); } if (destructor && destructor->getModifiers()->isStatic()) { destructor->parseTimeFatal(fs, Compiler::InvalidAttribute, "Destructor %s::%s() cannot be static", classScope->getOriginalName().c_str(), destructor->getOriginalName().c_str()); } if (clone && clone->getModifiers()->isStatic()) { clone->parseTimeFatal(fs, Compiler::InvalidAttribute, "Clone method %s::%s() cannot be static", classScope->getOriginalName().c_str(), clone->getOriginalName().c_str()); } } }