void MethodStatement::addTraitMethodToScope(AnalysisResultConstPtr ar, ClassScopePtr classScope) { FunctionScopeRawPtr funcScope = getFunctionScope(); classScope->addFunction(ar, funcScope); setSpecialMethod(classScope); FunctionScope::RecordFunctionInfo(m_name, funcScope); }
void MethodStatement::onParse(AnalysisResultPtr ar, BlockScopePtr scope) { ClassScopePtr classScope = dynamic_pointer_cast<ClassScope>(scope); FunctionScopePtr fs = getFunctionScope(); fs->setParamCounts(ar, -1, -1); classScope->addFunction(ar, fs); if (m_name == "__construct") { classScope->setAttribute(ClassScope::HasConstructor); } else if (m_name == "__destruct") { classScope->setAttribute(ClassScope::HasDestructor); } if (m_name == "__call") { classScope->setAttribute(ClassScope::HasUnknownMethodHandler); } else if (m_name == "__get") { classScope->setAttribute(ClassScope::HasUnknownPropGetter); } else if (m_name == "__set") { classScope->setAttribute(ClassScope::HasUnknownPropSetter); } else if (m_name == "__call") { classScope->setAttribute(ClassScope::HasUnknownMethodHandler); } else if (m_name == "__callstatic") { classScope->setAttribute(ClassScope::HasUnknownStaticMethodHandler); } m_className = classScope->getName(); m_originalClassName = classScope->getOriginalName(); }
void MethodStatement::onParse(AnalysisResultPtr ar) { ClassScopePtr classScope = dynamic_pointer_cast<ClassScope>(ar->getScope()); classScope->addFunction(ar, onParseImpl(ar)); if (m_name == "__construct") { classScope->setAttribute(ClassScope::HasConstructor); } else if (m_name == "__destruct") { classScope->setAttribute(ClassScope::HasDestructor); } if (m_name == "__call") { classScope->setAttribute(ClassScope::HasUnknownMethodHandler); } else if (m_name == "__get") { classScope->setAttribute(ClassScope::HasUnknownPropHandler); } m_className = classScope->getName(); }
void MethodStatement::onParseRecur(AnalysisResultConstRawPtr ar, FileScopeRawPtr fileScope, ClassScopePtr classScope) { checkParameters(fileScope); FunctionScopeRawPtr funcScope = getFunctionScope(); funcScope->setOuterScope(classScope); const bool isNative = funcScope->isNative(); if (m_modifiers) { if ((m_modifiers->isExplicitlyPublic() + m_modifiers->isProtected() + m_modifiers->isPrivate()) > 1) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, Strings::PICK_ACCESS_MODIFIER ); } if (m_modifiers->hasDuplicates()) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, Strings::PICK_ACCESS_MODIFIER); } if (classScope->isInterface()) { if (m_modifiers->isProtected() || m_modifiers->isPrivate() || m_modifiers->isAbstract() || m_modifiers->isFinal() || isNative) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, "Access type for interface method %s::%s() must be omitted", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (m_modifiers->isAsync()) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, Strings::ASYNC_WITHOUT_BODY, "interface", classScope->getOriginalName().c_str(), getOriginalName().c_str() ); } if (getStmts()) { getStmts()->parseTimeFatal( fileScope, Compiler::InvalidMethodDefinition, "Interface method %s::%s() cannot contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } } if (m_modifiers->isAbstract()) { if (!Option::WholeProgram && funcScope->userAttributes().count("__Memoize")) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, "Abstract method %s::%s cannot be memoized", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (m_modifiers->isPrivate() || m_modifiers->isFinal() || isNative) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, "Cannot declare abstract method %s::%s() %s", classScope->getOriginalName().c_str(), getOriginalName().c_str(), m_modifiers->isPrivate() ? "private" : (m_modifiers->isFinal() ? "final" : "native")); } if (!classScope->isInterface() && !classScope->isAbstract()) { /* note that classScope->isAbstract() returns true for traits */ m_modifiers->parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Class %s contains abstract method %s and " "must therefore be declared abstract", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (getStmts()) { parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Abstract method %s::%s() cannot contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (m_modifiers->isAsync()) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, Strings::ASYNC_WITHOUT_BODY, "abstract", classScope->getOriginalName().c_str(), getOriginalName().c_str() ); } } if (!m_modifiers->isStatic() && classScope->isStaticUtil()) { m_modifiers->parseTimeFatal( fileScope, Compiler::InvalidAttribute, "Class %s contains non-static method %s and " "therefore cannot be declared 'abstract final'", classScope->getOriginalName().c_str(), getOriginalName().c_str() ); } if (isNative) { if (getStmts()) { parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Native method %s::%s() cannot contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } auto is_ctordtor = isNamed("__construct") || isNamed("__destruct"); if (!m_retTypeAnnotation && !is_ctordtor) { parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Native method %s::%s() must have a return type hint", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } else if (m_retTypeAnnotation && is_ctordtor && (m_retTypeAnnotation->dataType() != KindOfNull)) { parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Native method %s::%s() must return void", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } } } if ((!m_modifiers || !m_modifiers->isAbstract()) && !getStmts() && !classScope->isInterface() && !isNative) { parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Non-abstract method %s::%s() must contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } classScope->addFunction(ar, fileScope, funcScope); setSpecialMethod(fileScope, classScope); if (RuntimeOption::DynamicInvokeFunctions.count(getOriginalFullName())) { funcScope->setDynamicInvoke(); } if (m_params) { auto nParams = m_params->getCount(); for (int i = 0; i < nParams; i++) { auto param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); param->parseHandler(fileScope, classScope); // Variadic capture params don't need types because they'll // be treated as Arrays as far as HNI is concerned. if (isNative && !param->hasUserType() && !param->isVariadic()) { parseTimeFatal(fileScope, Compiler::InvalidAttribute, "Native method calls must have type hints on all args"); } } } FunctionScope::RecordFunctionInfo(m_originalName, funcScope); }
void MethodStatement::onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr classScope) { if (m_modifiers) { if (classScope->isInterface()) { if (m_modifiers->isProtected() || m_modifiers->isPrivate() || m_modifiers->isAbstract() || m_modifiers->isFinal()) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, "Access type for interface method %s::%s() must be omitted", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } } if (m_modifiers->isAbstract()) { if (m_modifiers->isPrivate() || m_modifiers->isFinal()) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, "Cannot declare abstract method %s::%s() %s", classScope->getOriginalName().c_str(), getOriginalName().c_str(), m_modifiers->isPrivate() ? "private" : "final"); } if (!classScope->isInterface() && !classScope->isAbstract()) { /* note that classScope->isAbstract() returns true for traits */ m_modifiers->parseTimeFatal(Compiler::InvalidAttribute, "Class %s contains abstract method %s and " "must therefore be declared abstract", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (getStmts()) { parseTimeFatal(Compiler::InvalidAttribute, "Abstract method %s::%s() cannot contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } } } if ((!m_modifiers || !m_modifiers->isAbstract()) && !getStmts() && !classScope->isInterface()) { parseTimeFatal(Compiler::InvalidAttribute, "Non-abstract method %s::%s() must contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } FunctionScopeRawPtr fs = getFunctionScope(); classScope->addFunction(ar, fs); m_className = classScope->getName(); m_originalClassName = classScope->getOriginalName(); setSpecialMethod(classScope); if (Option::DynamicInvokeFunctions.find(getFullName()) != Option::DynamicInvokeFunctions.end()) { fs->setDynamicInvoke(); } if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); param->parseHandler(classScope); } } FunctionScope::RecordFunctionInfo(m_name, fs); }
void MethodStatement::onParseRecur(AnalysisResultConstPtr ar, ClassScopePtr classScope) { FunctionScopeRawPtr fs = getFunctionScope(); const bool isNative = fs->isNative(); if (m_modifiers) { if ((m_modifiers->isExplicitlyPublic() + m_modifiers->isProtected() + m_modifiers->isPrivate()) > 1) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, "%s: method %s::%s()", Strings::PICK_ACCESS_MODIFIER, classScope->getOriginalName().c_str(), getOriginalName().c_str() ); } if (classScope->isInterface()) { if (m_modifiers->isProtected() || m_modifiers->isPrivate() || m_modifiers->isAbstract() || m_modifiers->isFinal() || isNative) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, "Access type for interface method %s::%s() must be omitted", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (m_modifiers->isAsync()) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, Strings::ASYNC_WITHOUT_BODY, "interface", classScope->getOriginalName().c_str(), getOriginalName().c_str() ); } } if (m_modifiers->isAbstract()) { if (m_modifiers->isPrivate() || m_modifiers->isFinal() || isNative) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, "Cannot declare abstract method %s::%s() %s", classScope->getOriginalName().c_str(), getOriginalName().c_str(), m_modifiers->isPrivate() ? "private" : (m_modifiers->isFinal() ? "final" : "native")); } if (!classScope->isInterface() && !classScope->isAbstract()) { /* note that classScope->isAbstract() returns true for traits */ m_modifiers->parseTimeFatal(Compiler::InvalidAttribute, "Class %s contains abstract method %s and " "must therefore be declared abstract", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (getStmts()) { parseTimeFatal(Compiler::InvalidAttribute, "Abstract method %s::%s() cannot contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (m_modifiers->isAsync()) { m_modifiers->parseTimeFatal( Compiler::InvalidAttribute, Strings::ASYNC_WITHOUT_BODY, "abstract", classScope->getOriginalName().c_str(), getOriginalName().c_str() ); } } if (isNative) { if (getStmts()) { parseTimeFatal(Compiler::InvalidAttribute, "Native method %s::%s() cannot contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } if (!m_retTypeAnnotation) { parseTimeFatal(Compiler::InvalidAttribute, "Native method %s::%s() must have a return type hint", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } } } if ((!m_modifiers || !m_modifiers->isAbstract()) && !getStmts() && !classScope->isInterface() && !isNative) { parseTimeFatal(Compiler::InvalidAttribute, "Non-abstract method %s::%s() must contain body", classScope->getOriginalName().c_str(), getOriginalName().c_str()); } classScope->addFunction(ar, fs); m_className = classScope->getName(); m_originalClassName = classScope->getOriginalName(); setSpecialMethod(classScope); if (Option::DynamicInvokeFunctions.find(getFullName()) != Option::DynamicInvokeFunctions.end()) { fs->setDynamicInvoke(); } if (m_params) { for (int i = 0; i < m_params->getCount(); i++) { ParameterExpressionPtr param = dynamic_pointer_cast<ParameterExpression>((*m_params)[i]); param->parseHandler(classScope); if (isNative && !param->hasUserType()) { parseTimeFatal(Compiler::InvalidAttribute, "Native method calls must have type hints on all args"); } } } FunctionScope::RecordFunctionInfo(m_name, fs); }