Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-12-17 23:35:56

0001 #include "CommonTools/Utils/interface/MethodSetter.h"
0002 
0003 #include "CommonTools/Utils/interface/Exception.h"
0004 #include "CommonTools/Utils/src/ErrorCodes.h"
0005 #include "CommonTools/Utils/interface/MethodInvoker.h"
0006 #include "CommonTools/Utils/src/findDataMember.h"
0007 #include "CommonTools/Utils/src/findMethod.h"
0008 #include "CommonTools/Utils/interface/returnType.h"
0009 
0010 #include <string>
0011 
0012 using namespace reco::parser;
0013 using namespace std;
0014 
0015 void MethodSetter::operator()(const char* begin, const char* end) const {
0016   string name(begin, end);
0017   string::size_type parenthesis = name.find_first_of('(');
0018   if ((*begin == '[') || (*begin == '(')) {
0019     name.insert(0, "operator..");     // operator..[arg];
0020     parenthesis = 10;                 //           ^--- idx = 10
0021     name[8] = *begin;                 // operator[.[arg];
0022     name[9] = name[name.size() - 1];  // operator[][arg];
0023     name[10] = '(';                   // operator[](arg];
0024     name[name.size() - 1] = ')';      // operator[](arg);
0025     // we don't actually need the last two, but just for extra care
0026     //std::cout << "Transformed {" << string(begin,end) << "} into
0027     //  {"<< name <<"}" << std::endl;
0028   }
0029   std::vector<AnyMethodArgument> args;
0030   if (parenthesis != string::npos) {
0031     name.erase(parenthesis, name.size());
0032     if (intStack_.empty()) {
0033       throw Exception(begin) << "expected method argument, but non given.";
0034     }
0035     for (vector<AnyMethodArgument>::const_iterator i = intStack_.begin(); i != intStack_.end(); ++i) {
0036       args.push_back(*i);
0037     }
0038     intStack_.clear();
0039   }
0040   string::size_type endOfExpr = name.find_last_of(' ');
0041   if (endOfExpr != string::npos) {
0042     name.erase(endOfExpr, name.size());
0043   }
0044   //std::cerr << "Pushing [" << name << "] with " << args.size()
0045   //  << " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl;
0046   if (lazy_) {
0047     // for lazy parsing we just push method name and arguments
0048     lazyMethStack_.push_back(LazyInvoker(name, args));
0049   } else {
0050     // otherwise we really have to resolve the method
0051     push(name, args, begin);
0052   }
0053   //std::cerr << "Pushed [" << name << "] with " << args.size() <<
0054   //  " args " << (lazy_ ? "(lazy)" : "(immediate)") << std::endl;
0055 }
0056 
0057 bool MethodSetter::push(const string& name, const vector<AnyMethodArgument>& args, const char* begin, bool deep) const {
0058   edm::TypeWithDict type = typeStack_.back();
0059   vector<AnyMethodArgument> fixups;
0060   int error = 0;
0061   pair<edm::FunctionWithDict, bool> mem = reco::findMethod(type, name, args, fixups, begin, error);
0062   if (bool(mem.first)) {
0063     // We found the method.
0064     edm::TypeWithDict retType = reco::returnType(mem.first);
0065     if (!bool(retType)) {
0066       // Invalid return type, fatal error, throw.
0067       throw Exception(begin) << "member \"" << mem.first.name() << "\" return type is invalid:\n"
0068                              << "  return type: \"" << mem.first.typeName() << "\"\n";
0069     }
0070     typeStack_.push_back(retType);
0071     // check for edm::Ref, edm::RefToBase, edm::Ptr
0072     if (mem.second) {
0073       // Without fixups.
0074       //std::cout << "Mem.second, so book " << mem.first.name() <<
0075       //  " without fixups." << std::endl;
0076       methStack_.push_back(MethodInvoker(mem.first));
0077       if (!deep) {
0078         return false;
0079       }
0080       // note: we have not found the method, so we have not
0081       // fixupped the arguments
0082       push(name, args, begin);
0083     } else {
0084       // With fixups.
0085       //std::cout << "Not mem.second, so book " << mem.first.name()
0086       //  << " with #args = " << fixups.size() << std::endl;
0087       methStack_.push_back(MethodInvoker(mem.first, fixups));
0088     }
0089     return true;
0090   }
0091   if (error != reco::parser::kNameDoesNotExist) {
0092     // Fatal error, throw.
0093     switch (error) {
0094       case reco::parser::kIsNotPublic:
0095         throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
0096                                << "\" is not publically accessible.";
0097         break;
0098       case reco::parser::kIsStatic:
0099         throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name() << "\" is static.";
0100         break;
0101       case reco::parser::kIsNotConst:
0102         throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name() << "\" is not const.";
0103         break;
0104       case reco::parser::kWrongNumberOfArguments:
0105         throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
0106                                << "\" was passed the wrong number of arguments.";
0107         break;
0108       case reco::parser::kWrongArgumentType:
0109         throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
0110                                << "\" was passed the wrong types of arguments.";
0111         break;
0112       default:
0113         throw Exception(begin) << "method named \"" << name << "\" for type \"" << type.name()
0114                                << "\" is not usable in this context.";
0115     }
0116   }
0117   // Not a method, check for a data member.
0118   error = 0;
0119   edm::MemberWithDict member(reco::findDataMember(type, name, error));
0120   if (!bool(member)) {
0121     // Not a data member either, fatal error, throw.
0122     switch (error) {
0123       case reco::parser::kNameDoesNotExist: {
0124         Exception ex(begin);
0125         ex << "no method or data member named \"" << name << "\" found for type \"" << type.name() << "\"\n";
0126         // The following information is for temporary debugging only, intended to be removed later
0127         ex << "It has the following methods\n";
0128         edm::TypeFunctionMembers functions(type);
0129         for (auto const& f : functions) {
0130           ex << " " << f->GetName() << "\n";
0131         }
0132         ex << "and the following data members\n";
0133         edm::TypeDataMembers members(type);
0134         for (auto const& m : members) {
0135           ex << " " << m->GetName() << "\n";
0136         }
0137         throw ex;
0138       } break;
0139       case reco::parser::kIsNotPublic:
0140         throw Exception(begin) << "data member named \"" << name << "\" for type \"" << type.name()
0141                                << "\" is not publically accessible.";
0142         break;
0143       default:
0144         throw Exception(begin) << "data member named \"" << name << "\" for type \"" << type.name()
0145                                << "\" is not usable in this context.";
0146         break;
0147     }
0148   }
0149   // Ok, it was a data member.
0150   typeStack_.push_back(member.typeOf());
0151   methStack_.push_back(MethodInvoker(member));
0152   return true;
0153 }