#include "AST.h" #include "MethodDecl.h" #include "code-util.h" #include "errors.h" #include "is-main.h" #include "string-utils.h" MethodSet mainMethods; extern string *mainclass; //////////////////////////////////////////////////////////////////////// bool MethodDeclNode::isMain() const { return decl()->isMain(); } bool MethodDecl::isMain() { if ((modifiers() & Common::Static) && (modifiers() & Common::Public) && *name() == "main") { assert( methodType()->kind() == Common::MethodKind ); if (!methodType()->isMain()) return false; /* wrong signature */ string fullclassname = container()->fullName(); if (mainclass) /* explicitly selected by class name */ return fullclassname == *mainclass; else /* any matching non-library main method */ return !isInLibrary(container()); } else return false; /* wrong signature */ } bool MethodTypeNode::isMain() const { if (returnType()->kind() == VoidKind && paramTypes()->arity() == 1) { const TypeNode ¶m = *paramTypes()->child( 0 ); if (param.isJavaArrayType() && !param.isLocal()) { const TypeNode &element = *param.elementType(); if (element.isStringType() && !element.isLocal()) return true; } } return false; } //////////////////////////////////////////////////////////////////////// void TreeNode::lookForMain() const { undefined( "lookForMain" ); } void CompileUnitNode::lookForMain() const { foriter (type, types()->allChildren(), TreeNode::ChildIter) (*type)->lookForMain(); } void TemplateDeclNode::lookForMain() const { } void ClassDeclNode::lookForMain() const { if (decl()->category() == Decl::Class) foriter (member, members()->allChildren(), TreeNode::ChildIter) (*member)->lookForMain(); } void MethodDeclNode::lookForMain() const { if (isMain()) mainMethods.insert( decl() ); } void InterfaceDeclNode::lookForMain() const { } void FieldDeclNode::lookForMain() const { } void StaticInitNode::lookForMain() const { } void InstanceInitNode::lookForMain() const { } void ConstructorDeclNode::lookForMain() const { } void MethodSignatureNode::lookForMain() const { } void OmittedNode::lookForMain() const { } //////////////////////////////////////////////////////////////////////// void checkOnlyOneMain() { switch (mainMethods.size()) { case 0: { string classes = (mainclass?*mainclass:string("any class")); Error() << "no suitable main() method found in " << classes << endl; break; } case 1: break; default: Error() << "too many main() methods found. Use \'-main classname\' to choose one." << endl; for (MethodSet::const_iterator method = mainMethods.begin(); method != mainMethods.end(); ++method) (*method)->source()->message() << "candidate " << (*method)->errorName() << "()" << endl; } }