Imported Upstream version 3.8.0
[platform/upstream/protobuf.git] / src / google / protobuf / compiler / importer.cc
index c3831e7..715d999 100644 (file)
 #else
 #include <unistd.h>
 #endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include <algorithm>
 #include <memory>
 #include <google/protobuf/compiler/importer.h>
 
 #include <google/protobuf/compiler/parser.h>
+#include <google/protobuf/io/io_win32.h>
 #include <google/protobuf/io/tokenizer.h>
 #include <google/protobuf/io/zero_copy_stream_impl.h>
 #include <google/protobuf/stubs/strutil.h>
 
 
-#include <google/protobuf/stubs/io_win32.h>
 
 #ifdef _WIN32
 #include <ctype.h>
@@ -66,19 +66,17 @@ namespace compiler {
 #ifdef _WIN32
 // DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
 // them like we do below.
-using google::protobuf::internal::win32::access;
-using google::protobuf::internal::win32::open;
+using google::protobuf::io::win32::access;
+using google::protobuf::io::win32::open;
 #endif
 
 // Returns true if the text looks like a Windows-style absolute path, starting
 // with a drive letter.  Example:  "C:\foo".  TODO(kenton):  Share this with
 // copy in command_line_interface.cc?
-static bool IsWindowsAbsolutePath(const string& text) {
+static bool IsWindowsAbsolutePath(const std::string& text) {
 #if defined(_WIN32) || defined(__CYGWIN__)
-  return text.size() >= 3 && text[1] == ':' &&
-         isalpha(text[0]) &&
-         (text[2] == '/' || text[2] == '\\') &&
-         text.find_last_of(':') == 1;
+  return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) &&
+         (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1;
 #else
   return false;
 #endif
@@ -93,17 +91,17 @@ MultiFileErrorCollector::~MultiFileErrorCollector() {}
 class SourceTreeDescriptorDatabase::SingleFileErrorCollector
     : public io::ErrorCollector {
  public:
-  SingleFileErrorCollector(const string& filename,
+  SingleFileErrorCollector(const std::string& filename,
                            MultiFileErrorCollector* multi_file_error_collector)
-    : filename_(filename),
-      multi_file_error_collector_(multi_file_error_collector),
-      had_errors_(false) {}
+      : filename_(filename),
+        multi_file_error_collector_(multi_file_error_collector),
+        had_errors_(false) {}
   ~SingleFileErrorCollector() {}
 
   bool had_errors() { return had_errors_; }
 
   // implements ErrorCollector ---------------------------------------
-  void AddError(int line, int column, const string& message) {
+  void AddError(int line, int column, const std::string& message) override {
     if (multi_file_error_collector_ != NULL) {
       multi_file_error_collector_->AddError(filename_, line, column, message);
     }
@@ -111,7 +109,7 @@ class SourceTreeDescriptorDatabase::SingleFileErrorCollector
   }
 
  private:
-  string filename_;
+  std::string filename_;
   MultiFileErrorCollector* multi_file_error_collector_;
   bool had_errors_;
 };
@@ -120,17 +118,30 @@ class SourceTreeDescriptorDatabase::SingleFileErrorCollector
 
 SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase(
     SourceTree* source_tree)
-  : source_tree_(source_tree),
-    error_collector_(NULL),
-    using_validation_error_collector_(false),
-    validation_error_collector_(this) {}
+    : source_tree_(source_tree),
+      fallback_database_(nullptr),
+      error_collector_(nullptr),
+      using_validation_error_collector_(false),
+      validation_error_collector_(this) {}
+
+SourceTreeDescriptorDatabase::SourceTreeDescriptorDatabase(
+    SourceTree* source_tree, DescriptorDatabase* fallback_database)
+    : source_tree_(source_tree),
+      fallback_database_(fallback_database),
+      error_collector_(nullptr),
+      using_validation_error_collector_(false),
+      validation_error_collector_(this) {}
 
 SourceTreeDescriptorDatabase::~SourceTreeDescriptorDatabase() {}
 
-bool SourceTreeDescriptorDatabase::FindFileByName(
-    const string& filename, FileDescriptorProto* output) {
+bool SourceTreeDescriptorDatabase::FindFileByName(const std::string& filename,
+                                                  FileDescriptorProto* output) {
   std::unique_ptr<io::ZeroCopyInputStream> input(source_tree_->Open(filename));
   if (input == NULL) {
+    if (fallback_database_ != nullptr &&
+        fallback_database_->FindFileByName(filename, output)) {
+      return true;
+    }
     if (error_collector_ != NULL) {
       error_collector_->AddError(filename, -1, 0,
                                  source_tree_->GetLastErrorMessage());
@@ -152,17 +163,16 @@ bool SourceTreeDescriptorDatabase::FindFileByName(
 
   // Parse it.
   output->set_name(filename);
-  return parser.Parse(&tokenizer, output) &&
-         !file_error_collector.had_errors();
+  return parser.Parse(&tokenizer, output) && !file_error_collector.had_errors();
 }
 
 bool SourceTreeDescriptorDatabase::FindFileContainingSymbol(
-    const string& symbol_name, FileDescriptorProto* output) {
+    const std::string& symbol_name, FileDescriptorProto* output) {
   return false;
 }
 
 bool SourceTreeDescriptorDatabase::FindFileContainingExtension(
-    const string& containing_type, int field_number,
+    const std::string& containing_type, int field_number,
     FileDescriptorProto* output) {
   return false;
 }
@@ -170,35 +180,41 @@ bool SourceTreeDescriptorDatabase::FindFileContainingExtension(
 // -------------------------------------------------------------------
 
 SourceTreeDescriptorDatabase::ValidationErrorCollector::
-ValidationErrorCollector(SourceTreeDescriptorDatabase* owner)
-  : owner_(owner) {}
+    ValidationErrorCollector(SourceTreeDescriptorDatabase* owner)
+    : owner_(owner) {}
 
 SourceTreeDescriptorDatabase::ValidationErrorCollector::
-~ValidationErrorCollector() {}
+    ~ValidationErrorCollector() {}
 
 void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddError(
-    const string& filename,
-    const string& element_name,
-    const Message* descriptor,
-    ErrorLocation location,
-    const string& message) {
+    const std::string& filename, const std::string& element_name,
+    const Message* descriptor, ErrorLocation location,
+    const std::string& message) {
   if (owner_->error_collector_ == NULL) return;
 
   int line, column;
-  owner_->source_locations_.Find(descriptor, location, &line, &column);
+  if (location == DescriptorPool::ErrorCollector::IMPORT) {
+    owner_->source_locations_.FindImport(descriptor, element_name, &line,
+                                         &column);
+  } else {
+    owner_->source_locations_.Find(descriptor, location, &line, &column);
+  }
   owner_->error_collector_->AddError(filename, line, column, message);
 }
 
 void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning(
-    const string& filename,
-    const string& element_name,
-    const Message* descriptor,
-    ErrorLocation location,
-    const string& message) {
+    const std::string& filename, const std::string& element_name,
+    const Message* descriptor, ErrorLocation location,
+    const std::string& message) {
   if (owner_->error_collector_ == NULL) return;
 
   int line, column;
-  owner_->source_locations_.Find(descriptor, location, &line, &column);
+  if (location == DescriptorPool::ErrorCollector::IMPORT) {
+    owner_->source_locations_.FindImport(descriptor, element_name, &line,
+                                         &column);
+  } else {
+    owner_->source_locations_.Find(descriptor, location, &line, &column);
+  }
   owner_->error_collector_->AddWarning(filename, line, column, message);
 }
 
@@ -206,19 +222,19 @@ void SourceTreeDescriptorDatabase::ValidationErrorCollector::AddWarning(
 
 Importer::Importer(SourceTree* source_tree,
                    MultiFileErrorCollector* error_collector)
-  : database_(source_tree),
-    pool_(&database_, database_.GetValidationErrorCollector()) {
+    : database_(source_tree),
+      pool_(&database_, database_.GetValidationErrorCollector()) {
   pool_.EnforceWeakDependencies(true);
   database_.RecordErrorsTo(error_collector);
 }
 
 Importer::~Importer() {}
 
-const FileDescriptor* Importer::Import(const string& filename) {
+const FileDescriptor* Importer::Import(const std::string& filename) {
   return pool_.FindFileByName(filename);
 }
 
-void Importer::AddUnusedImportTrackFile(const string& file_name) {
+void Importer::AddUnusedImportTrackFile(const std::string& file_name) {
   pool_.AddUnusedImportTrackFile(file_name);
 }
 
@@ -231,15 +247,13 @@ void Importer::ClearUnusedImportTrackFiles() {
 
 SourceTree::~SourceTree() {}
 
-string SourceTree::GetLastErrorMessage() {
-  return "File not found.";
-}
+std::string SourceTree::GetLastErrorMessage() { return "File not found."; }
 
 DiskSourceTree::DiskSourceTree() {}
 
 DiskSourceTree::~DiskSourceTree() {}
 
-static inline char LastChar(const string& str) {
+static inline char LastChar(const std::string& str) {
   return str[str.size() - 1];
 }
 
@@ -262,7 +276,7 @@ static inline char LastChar(const string& str) {
 //   then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize
 //   to a path which does not appear to be under foo, and thus the compiler
 //   will complain that baz.proto is not inside the --proto_path.
-static string CanonicalizePath(string path) {
+static std::string CanonicalizePath(std::string path) {
 #ifdef _WIN32
   // The Win32 API accepts forward slashes as a path delimiter even though
   // backslashes are standard.  Let's avoid confusion and use only forward
@@ -275,8 +289,8 @@ static string CanonicalizePath(string path) {
   }
 #endif
 
-  std::vector<string> canonical_parts;
-  std::vector<string> parts = Split(
+  std::vector<std::string> canonical_parts;
+  std::vector<std::string> parts = Split(
       path, "/", true);  // Note:  Removes empty parts.
   for (int i = 0; i < parts.size(); i++) {
     if (parts[i] == ".") {
@@ -285,20 +299,20 @@ static string CanonicalizePath(string path) {
       canonical_parts.push_back(parts[i]);
     }
   }
-  string result = Join(canonical_parts, "/");
+  std::string result = Join(canonical_parts, "/");
   if (!path.empty() && path[0] == '/') {
     // Restore leading slash.
     result = '/' + result;
   }
-  if (!path.empty() && LastChar(path) == '/' &&
-      !result.empty() && LastChar(result) != '/') {
+  if (!path.empty() && LastChar(path) == '/' && !result.empty() &&
+      LastChar(result) != '/') {
     // Restore trailing slash.
     result += '/';
   }
   return result;
 }
 
-static inline bool ContainsParentReference(const string& path) {
+static inline bool ContainsParentReference(const std::string& path) {
   return path == ".." || HasPrefixString(path, "../") ||
          HasSuffixString(path, "/..") || path.find("/../") != string::npos;
 }
@@ -320,10 +334,9 @@ static inline bool ContainsParentReference(const string& path) {
 //   assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
 //   assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
 //   assert(!ApplyMapping("foobar", "foo", "baz", &result));
-static bool ApplyMapping(const string& filename,
-                         const string& old_prefix,
-                         const string& new_prefix,
-                         string* result) {
+static bool ApplyMapping(const std::string& filename,
+                         const std::string& old_prefix,
+                         const std::string& new_prefix, std::string* result) {
   if (old_prefix.empty()) {
     // old_prefix matches any relative path.
     if (ContainsParentReference(filename)) {
@@ -359,7 +372,7 @@ static bool ApplyMapping(const string& filename,
       if (after_prefix_start != -1) {
         // Yep.  So the prefixes are directories and the filename is a file
         // inside them.
-        string after_prefix = filename.substr(after_prefix_start);
+        std::string after_prefix = filename.substr(after_prefix_start);
         if (ContainsParentReference(after_prefix)) {
           // We do not allow the file name to use "..".
           return false;
@@ -375,18 +388,17 @@ static bool ApplyMapping(const string& filename,
   return false;
 }
 
-void DiskSourceTree::MapPath(const string& virtual_path,
-                             const string& disk_path) {
+void DiskSourceTree::MapPath(const std::string& virtual_path,
+                             const std::string& disk_path) {
   mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path)));
 }
 
 DiskSourceTree::DiskFileToVirtualFileResult
-DiskSourceTree::DiskFileToVirtualFile(
-    const string& disk_file,
-    string* virtual_file,
-    string* shadowing_disk_file) {
+DiskSourceTree::DiskFileToVirtualFile(const std::string& disk_file,
+                                      std::string* virtual_file,
+                                      std::string* shadowing_disk_file) {
   int mapping_index = -1;
-  string canonical_disk_file = CanonicalizePath(disk_file);
+  std::string canonical_disk_file = CanonicalizePath(disk_file);
 
   for (int i = 0; i < mappings_.size(); i++) {
     // Apply the mapping in reverse.
@@ -426,36 +438,36 @@ DiskSourceTree::DiskFileToVirtualFile(
   return SUCCESS;
 }
 
-bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file,
-                                           string* disk_file) {
+bool DiskSourceTree::VirtualFileToDiskFile(const std::string& virtual_file,
+                                           std::string* disk_file) {
   std::unique_ptr<io::ZeroCopyInputStream> stream(
       OpenVirtualFile(virtual_file, disk_file));
   return stream != NULL;
 }
 
-io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) {
+io::ZeroCopyInputStream* DiskSourceTree::Open(const std::string& filename) {
   return OpenVirtualFile(filename, NULL);
 }
 
-string DiskSourceTree::GetLastErrorMessage() {
+std::string DiskSourceTree::GetLastErrorMessage() {
   return last_error_message_;
 }
 
 io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
-    const string& virtual_file,
-    string* disk_file) {
+    const std::string& virtual_file, std::string* disk_file) {
   if (virtual_file != CanonicalizePath(virtual_file) ||
       ContainsParentReference(virtual_file)) {
     // We do not allow importing of paths containing things like ".." or
     // consecutive slashes since the compiler expects files to be uniquely
     // identified by file name.
-    last_error_message_ = "Backslashes, consecutive slashes, \".\", or \"..\" "
-                          "are not allowed in the virtual path";
+    last_error_message_ =
+        "Backslashes, consecutive slashes, \".\", or \"..\" "
+        "are not allowed in the virtual path";
     return NULL;
   }
 
   for (int i = 0; i < mappings_.size(); i++) {
-    string temp_disk_file;
+    std::string temp_disk_file;
     if (ApplyMapping(virtual_file, mappings_[i].virtual_path,
                      mappings_[i].disk_path, &temp_disk_file)) {
       io::ZeroCopyInputStream* stream = OpenDiskFile(temp_disk_file);
@@ -468,8 +480,8 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
 
       if (errno == EACCES) {
         // The file exists but is not readable.
-        last_error_message_ = "Read access is denied for file: " +
-                              temp_disk_file;
+        last_error_message_ =
+            "Read access is denied for file: " + temp_disk_file;
         return NULL;
       }
     }
@@ -479,7 +491,7 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
 }
 
 io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile(
-    const string& filename) {
+    const std::string& filename) {
   int file_descriptor;
   do {
     file_descriptor = open(filename.c_str(), O_RDONLY);