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()); }
int CodeGenerator::createNewId(AnalysisResultPtr ar) { FileScopePtr fs = ar->getFileScope(); if (fs) { return createNewId(fs->getName()); } return createNewId(""); }
void AnalysisResult::addFileScope(FileScopePtr fileScope) { assert(fileScope); FileScopePtr &res = m_files[fileScope->getName()]; assert(!res); res = fileScope; m_fileScopes.push_back(fileScope); }
int CodeGenerator::createNewId(ConstructPtr cs) { FileScopePtr fs = cs->getFileScope(); if (fs) { return createNewId(fs->getName()); } return createNewId(""); }
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()); }
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()); }
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); } } }
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(""); }
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); } }
static bool by_filename(const FileScopePtr &f1, const FileScopePtr &f2) { return f1->getName() < f2->getName(); }