Make write_props be callable from policied code
[hiphop-php.git] / hphp / compiler / analysis / analysis_result.cpp
blob3906e04fcc7c17d0a1a9b2ac817f21ae20fc6a5f
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/compiler/analysis/analysis_result.h"
19 #include <folly/Conv.h>
20 #include <folly/portability/SysStat.h>
22 #include <algorithm>
23 #include <fstream>
24 #include <iomanip>
25 #include <map>
26 #include <string>
27 #include <utility>
28 #include <vector>
30 #include "hphp/compiler/builtin_symbols.h"
31 #include "hphp/compiler/option.h"
32 #include "hphp/compiler/package.h"
33 #include "hphp/runtime/base/program-functions.h"
34 #include "hphp/runtime/vm/unit-emitter.h"
35 #include "hphp/runtime/vm/treadmill.h"
36 #include "hphp/util/hash.h"
37 #include "hphp/util/job-queue.h"
38 #include "hphp/util/logger.h"
39 #include "hphp/util/timer.h"
41 using namespace HPHP;
43 ///////////////////////////////////////////////////////////////////////////////
44 // initialization
46 AnalysisResult::AnalysisResult()
47 : m_package(nullptr), m_parseOnDemand(false) {
48 if (RuntimeOption::EvalUseHHBBC) {
49 m_program = HHBBC::make_program();
53 AnalysisResult::~AnalysisResult() {
54 always_assert(!m_finish);
57 void AnalysisResult::finish() {
58 if (m_finish) {
59 // std::move leaves a std::function in a valid, but
60 // unspecified state. Don't try to replace this with a std::move
61 decltype(m_finish) f;
62 f.swap(m_finish);
63 f(shared_from_this());
67 ///////////////////////////////////////////////////////////////////////////////
68 // general functions
70 void AnalysisResult::addHhasFile(std::unique_ptr<UnitEmitter>&& ue) {
71 Lock lock(getMutex());
72 m_hhasFiles.emplace_back(std::move(ue));
75 std::vector<std::unique_ptr<UnitEmitter>> AnalysisResult::getHhasFiles() {
76 return std::move(m_hhasFiles);
79 bool AnalysisResult::inParseOnDemandDirs(const std::string& filename) const {
80 for (auto const& dir : m_parseOnDemandDirs) {
81 if (filename.find(dir) == 0) return true;
83 return false;
86 void AnalysisResult::parseOnDemand(const std::string& name) const {
87 if (m_package) {
88 auto const& root = m_package->getRoot();
89 auto rname = name;
90 if (rname.compare(0, root.length(), root) == 0) {
91 rname = rname.substr(root.length());
93 if ((m_parseOnDemand || inParseOnDemandDirs(rname)) &&
94 Option::PackageExcludeFiles.find(rname) ==
95 Option::PackageExcludeFiles.end() &&
96 !Option::IsFileExcluded(rname, Option::PackageExcludePatterns)) {
97 m_package->addSourceFile(rname);
102 template <class Map>
103 void AnalysisResult::parseOnDemandBy(const CompactVector<std::string>& syms,
104 const Map& amap) const {
105 if (m_package) {
106 for (auto const& name : syms) {
107 auto it = amap.find(name);
108 if (it != amap.end()) {
109 parseOnDemand(Option::AutoloadRoot + it->second);
115 void AnalysisResult::parseOnDemandBy(
116 SymbolRef kind, const CompactVector<std::string>& syms) const {
117 switch (kind) {
118 case SymbolRef::Include:
119 for (auto const& name : syms) parseOnDemand(name);
120 return;
122 case SymbolRef::Class:
123 return parseOnDemandBy(syms, Option::AutoloadClassMap);
125 case SymbolRef::Function:
126 return parseOnDemandBy(syms, Option::AutoloadFuncMap);
128 case SymbolRef::Constant:
129 return parseOnDemandBy(syms, Option::AutoloadConstMap);
131 not_reached();
134 ///////////////////////////////////////////////////////////////////////////////
135 // code generation functions
137 std::string AnalysisResult::prepareFile(const char *root,
138 const std::string &fileName,
139 bool chop,
140 bool stripPath /* = true */) {
141 std::string fullPath = root;
142 if (!fullPath.empty() &&
143 !FileUtil::isDirSeparator(fullPath[fullPath.size() - 1])) {
144 fullPath += FileUtil::getDirSeparator();
147 auto file = fileName;
148 if (stripPath) {
149 size_t npos = file.rfind('/');
150 if (npos != std::string::npos) {
151 file = file.substr(npos + 1);
155 if (chop && file.size() > 4 && file.substr(file.length() - 4) == ".php") {
156 fullPath += file.substr(0, file.length() - 4);
157 } else {
158 fullPath += file;
160 for (size_t pos = strlen(root); pos < fullPath.size(); pos++) {
161 if (FileUtil::isDirSeparator(fullPath[pos])) {
162 mkdir(fullPath.substr(0, pos).c_str(), 0777);
165 return fullPath;