00001 #include "PhysicsTools/Utilities/src/findMethod.h"
00002 #include "PhysicsTools/Utilities/src/ErrorCodes.h"
00003 #include "PhysicsTools/Utilities/interface/Exception.h"
00004 #include "Reflex/Base.h"
00005 #include "Reflex/TypeTemplate.h"
00006
00007 using namespace ROOT::Reflex;
00008 using namespace std;
00009 using reco::parser::AnyMethodArgument;
00010
00011
00012 static bool fatalErrorCondition(int iError)
00013 {
00014 return (reco::parser::kIsNotPublic==iError ||
00015 reco::parser::kIsStatic==iError ||
00016 reco::parser::kIsFunctionAddedByROOT==iError ||
00017 reco::parser::kIsConstructor==iError ||
00018 reco::parser::kIsDestructor==iError ||
00019 reco::parser::kIsOperator==iError);
00020
00021 }
00022 namespace reco {
00023 int checkMethod(const ROOT::Reflex::Member & mem,
00024 const ROOT::Reflex::Type & type,
00025 const std::vector<AnyMethodArgument> &args, std::vector<AnyMethodArgument> &fixuppedArgs) {
00026 int casts = 0;
00027 if (mem.IsConstructor()) return -1*parser::kIsConstructor;
00028 if (mem.IsDestructor()) return -1*parser::kIsDestructor;
00029 if (mem.IsOperator()) return -1*parser::kIsOperator;
00030 if (! mem.IsPublic()) return -1*parser::kIsNotPublic;
00031 if (mem.IsStatic()) return -1*parser::kIsStatic;
00032 if ( ! mem.TypeOf().IsConst() ) return -1*parser::kIsNotConst;
00033 if (mem.Name().substr(0, 2) == "__") return -1*parser::kIsFunctionAddedByROOT;
00034 if (mem.DeclaringType().Id() != type.Id()) {
00035
00036
00037
00038 return -1*parser::kOverloaded;
00039 }
00040 size_t minArgs = mem.FunctionParameterSize(true), maxArgs = mem.FunctionParameterSize(false);
00041 if ((args.size() < minArgs) || (args.size() > maxArgs)) return -1*parser::kWrongNumberOfArguments;
00042
00043
00044
00045 if (!args.empty()) {
00046 Type t = mem.TypeOf();
00047 std::vector<AnyMethodArgument> tmpFixups;
00048 for (size_t i = 0; i < args.size(); ++i) {
00049 std::pair<AnyMethodArgument,int> fixup = boost::apply_visitor( reco::parser::AnyMethodArgumentFixup(t.FunctionParameterAt(i)), args[i] );
00050
00051 if (fixup.second >= 0) {
00052 tmpFixups.push_back(fixup.first);
00053 casts += fixup.second;
00054 } else {
00055 return -1*parser::kWrongArgumentType;
00056 }
00057 }
00058 fixuppedArgs.swap(tmpFixups);
00059 }
00060
00061
00062
00063 return casts;
00064 }
00065
00066 pair<Member, bool> findMethod(const Type & t,
00067 const string & name,
00068 const std::vector<AnyMethodArgument> &args,
00069 std::vector<AnyMethodArgument> &fixuppedArgs,
00070 const char* iIterator,
00071 int& oError) {
00072 oError = parser::kNameDoesNotExist;
00073 Type type = t;
00074 if (! type)
00075 throw parser::Exception(iIterator)
00076 << "No dictionary for class \"" << type.Name() << "\".";
00077 while(type.IsPointer() || type.IsTypedef()) type = type.ToType();
00078 type = Type(type,0);
00079
00080 pair<Member, bool> mem; mem.second = false;
00081
00082
00083 vector<pair<int,Member> > oks;
00084
00085
00086 for(Member_Iterator m = type.FunctionMember_Begin(); m != type.FunctionMember_End(); ++m ) {
00087 if(m->Name()==name) {
00088 int casts = checkMethod(*m, type, args, fixuppedArgs);
00089 if (casts > -1) {
00090 oks.push_back( make_pair(casts,*m) );
00091 } else {
00092 oError = -1*casts;
00093
00094 if(fatalErrorCondition(oError)) {
00095 return mem;
00096 }
00097 }
00098 }
00099 }
00100
00101
00102 if (!oks.empty()) {
00103 if (oks.size() > 1) {
00104
00105 sort(oks.begin(), oks.end());
00106
00107 if (oks[0].first == oks[1].first) {
00108 throw parser::Exception(iIterator)
00109 << "Can't resolve method \"" << name << "\" for class \"" << type.Name() << "\", the two candidates "
00110 << oks[0].second.Name() << " and " << oks[1].second.Name()
00111 << " require the same number of integer->real conversions (" << oks[0].first << ").";
00112 }
00113
00114
00115 fixuppedArgs.clear();
00116 checkMethod(oks.front().second, type, args, fixuppedArgs);
00117 }
00118 mem.first = oks.front().second;
00119 }
00120
00121
00122 int baseError=parser::kNameDoesNotExist;
00123 if(! mem.first) {
00124 for(Base_Iterator b = type.Base_Begin(); b != type.Base_End(); ++ b) {
00125 if((mem = findMethod(b->ToType(), name, args, fixuppedArgs,iIterator,baseError)).first) break;
00126 if(fatalErrorCondition(baseError)) {
00127 oError = baseError;
00128 return mem;
00129 }
00130 }
00131 }
00132
00133
00134 if(!mem.first) {
00135
00136
00137 if(type.IsTemplateInstance()) {
00138 TypeTemplate templ = type.TemplateFamily();
00139 std::string name = templ.Name();
00140 if(name.compare("Ref") == 0 ||
00141 name.compare("RefToBase") == 0 ||
00142 name.compare("Ptr") == 0) {
00143
00144 std::vector<AnyMethodArgument> empty, empty2;
00145 int error;
00146 mem = findMethod(type, "get", empty, empty2,iIterator,error);
00147 if(!mem.first) {
00148 throw parser::Exception(iIterator)
00149 << "No member \"get\" in reference of type \"" << type.Name() << "\".";
00150 }
00151 mem.second = true;
00152 }
00153 }
00154 }
00155
00156
00157
00158
00159
00160
00161 if(mem.first) {
00162 oError = parser::kNoError;
00163 } else {
00164
00165 if(oError == parser::kNameDoesNotExist) {
00166 oError = baseError;
00167 }
00168 }
00169 return mem;
00170 }
00171 }