示例#1
0
void IncludeExpression::analyzeInclude(AnalysisResultPtr ar,
                                       const std::string &include) {
  ASSERT(ar->getPhase() == AnalysisResult::AnalyzeInclude);
  ConstructPtr self = shared_from_this();
  FileScopePtr file = ar->findFileScope(include, true);
  if (!file) {
    ar->getCodeError()->record(self, CodeError::PHPIncludeFileNotFound, self);
    return;
  }
  if (include.find("compiler/") != 0 ||
      include.find("/compiler/") == string::npos) {
    ar->getCodeError()->record(self, CodeError::PHPIncludeFileNotInLib,
                               self, ConstructPtr(),
                               include.c_str());
  }

  if (!isFileLevel()) { // Not unsupported but potentially bad
    ar->getCodeError()->record(self, CodeError::UseDynamicInclude, self);
  }

  ar->getDependencyGraph()->add
    (DependencyGraph::KindOfProgramMaxInclude,
     ar->getName(), file->getName(), StatementPtr());
  ar->getDependencyGraph()->addParent
    (DependencyGraph::KindOfProgramMinInclude,
     ar->getName(), file->getName(), StatementPtr());
  FunctionScopePtr func = ar->getFunctionScope();
  ar->getFileScope()->addIncludeDependency(ar, m_include,
                                           func && func->isInlined());
}
示例#2
0
int CodeGenerator::createNewId(AnalysisResultPtr ar) {
  FileScopePtr fs = ar->getFileScope();
  if (fs) {
    return createNewId(fs->getName());
  }
  return createNewId("");
}
示例#3
0
void AnalysisResult::addFileScope(FileScopePtr fileScope) {
  assert(fileScope);
  FileScopePtr &res = m_files[fileScope->getName()];
  assert(!res);
  res = fileScope;
  m_fileScopes.push_back(fileScope);
}
示例#4
0
int CodeGenerator::createNewId(ConstructPtr cs) {
  FileScopePtr fs = cs->getFileScope();
  if (fs) {
    return createNewId(fs->getName());
  }
  return createNewId("");
}
示例#5
0
std::string IncludeExpression::CheckInclude(ConstructPtr includeExp,
                                            FileScopePtr scope,
                                            ExpressionPtr fileExp,
                                            bool &documentRoot) {
  auto const& container = scope->getName();
  std::string var, lit;
  parse_string_arg(fileExp, var, lit);
  if (lit.empty()) return lit;

  if (var == "__DIR__") {
    var = "";
    // get_include_file_path will check relative to the current file's dir
    // as long as the first char isn't a /
    if (lit[0] == '/') {
      lit = lit.substr(1);
    }
  }

  auto included = get_include_file_path(container, var, lit, documentRoot);
  if (!included.empty()) {
    if (included == container) {
      Compiler::Error(Compiler::BadPHPIncludeFile, includeExp);
    }
    included = FileUtil::canonicalize(included).toCppString();
    if (!var.empty()) documentRoot = true;
  }
  return included;
}
void FunctionStatement::onParse(AnalysisResultPtr ar, BlockScopePtr scope) {
  // note it's important to add to file scope, not a pushed FunctionContainer,
  // as a function may be declared inside a class's method, yet this function
  // is a global function, not a class method.
  FileScopePtr fileScope = dynamic_pointer_cast<FileScope>(scope);
  if (!fileScope->addFunction(ar, onInitialParse(ar, fileScope, false))) {
    m_ignored = true;
    return;
  }
  ar->recordFunctionSource(m_name, m_loc, fileScope->getName());
}
示例#7
0
void FunctionStatement::onParse(AnalysisResultPtr ar) {
   // note it's important to add to file scope, not a pushed FunctionContainer,
  // as a function may be declared inside a class's method, yet this function
  // is a global function, not a class method.
  FileScopePtr fileScope = ar->getFileScope();
  if (!fileScope->addFunction(ar, onParseImpl(ar))) {
    m_ignored = true;
    return;
  }
  ar->recordFunctionSource(m_name, m_loc, fileScope->getName());
}
示例#8
0
int CodeGenerator::createNewLocalId(AnalysisResultPtr ar) {
  FunctionScopePtr func = ar->getFunctionScope();
  if (func) {
    return func->nextInlineIndex();
  }
  FileScopePtr fs = ar->getFileScope();
  if (fs) {
    return createNewId(fs->getName());
  }
  return createNewId("");
}
void ClassStatement::onParse(AnalysisResultPtr ar, BlockScopePtr scope) {
  ClassScope::KindOf kindOf = ClassScope::KindOfObjectClass;
  switch (m_type) {
  case T_CLASS:     kindOf = ClassScope::KindOfObjectClass;   break;
  case T_ABSTRACT:  kindOf = ClassScope::KindOfAbstractClass; break;
  case T_FINAL:     kindOf = ClassScope::KindOfFinalClass;    break;
  default:
    ASSERT(false);
  }

  FileScopePtr fs = dynamic_pointer_cast<FileScope>(scope);
  vector<string> bases;
  if (!m_parent.empty()) {
    bases.push_back(m_parent);
    ar->addNonFinal(m_parent);
  }
  if (m_base) m_base->getStrings(bases);
  StatementPtr stmt = dynamic_pointer_cast<Statement>(shared_from_this());
  ClassScopePtr classScope(new ClassScope(kindOf, m_originalName, m_parent,
                                          bases, m_docComment,
                                          stmt));
  setBlockScope(classScope);
  if (!fs->addClass(ar, classScope)) {
    m_ignored = true;
    return;
  }
  ar->recordClassSource(m_name, m_loc, fs->getName());

  if (m_stmt) {
    bool seenConstruct = false;
    for (int i = 0; i < m_stmt->getCount(); i++) {
      MethodStatementPtr meth =
        dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
      if (meth && meth->getName() == "__construct") {
        seenConstruct = true;
        break;
      }
    }
    for (int i = 0; i < m_stmt->getCount(); i++) {
      if (!seenConstruct) {
        MethodStatementPtr meth =
          dynamic_pointer_cast<MethodStatement>((*m_stmt)[i]);
        if (meth && classScope && meth->getName() == classScope->getName()
         && !meth->getModifiers()->isStatic()) {
          // class-name constructor
          classScope->setAttribute(ClassScope::ClassNameConstructor);
        }
      }
      IParseHandlerPtr ph = dynamic_pointer_cast<IParseHandler>((*m_stmt)[i]);
      ph->onParse(ar, classScope);
    }
  }
}
示例#10
0
int CodeGenerator::createNewLocalId(ConstructPtr ar) {
  if (m_wrappedExpression[m_curStream]) {
    return m_localId[m_curStream]++;
  }
  FunctionScopePtr func = ar->getFunctionScope();
  if (func) {
    return func->nextInlineIndex();
  }
  FileScopePtr fs = ar->getFileScope();
  if (fs) {
    return createNewId(fs->getName());
  }
  return createNewId("");
}
示例#11
0
void QueryExpression::doRewrites(AnalysisResultPtr ar,
                                 FileScopePtr fileScope) {
  // Clone the query expression for client rewriting later on.
  auto csqe = static_pointer_cast<QueryExpression>(this->clone());

  // Find expressions that capture client state and turn them into
  // query parameter expression. The original expressions end up in m_queryargs.
  CaptureExtractor ce;
  auto qe = static_pointer_cast<QueryExpression>(
    ce.rewrite(static_pointer_cast<Expression>(shared_from_this())));

  // Expose the argument (capture) expressions to static analysis rather than
  // the original clause list (it is still available in m_originalExpressions).
  m_expressions = static_pointer_cast<ExpressionList>(m_expressions->clone());
  m_expressions->clearElements();
  auto queryArgs = static_pointer_cast<ExpressionList>(m_expressions->clone());
  for (auto e : ce.getCapturedExpressions()) {
    queryArgs->addElement(e);
  }
  assert(queryArgs->getCount() > 0); //syntax requires an initial from clause
  m_expressions->addElement(queryArgs);

  // Rewrite select clauses so that they become tuples of columns when
  // sent to the query provider.
  ServerSideSelectRewriter se;
  se.rewriteQuery(qe);

  // Serialize the rewritten query expression so that it can be sent to
  // the query provider as a string which it can unserialize and turn
  // into a query (unless already cached).
  std::ostringstream serialized;
  CodeGenerator cg(&serialized, CodeGenerator::Output::CodeModel,
                   &fileScope->getName());
  cg.setAstClassPrefix("Code");
  qe->outputCodeModel(cg);
  std::string s(serialized.str().c_str(), serialized.str().length());
  m_querystr = makeStaticString(s);

  // start again with the clone of the original query (not the one
  // that was rewritten for use by the query provider) and rewrite
  // it into a closure expression that is used by the query provider
  // to execute code in the context to the client, not the server.
  auto selectClosure = csqe->clientSideRewrite(ar, fileScope);
  if (selectClosure != nullptr) {
    m_expressions->addElement(selectClosure);
  }
}
示例#12
0
static bool by_filename(const FileScopePtr &f1, const FileScopePtr &f2) {
  return f1->getName() < f2->getName();
}