kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/indexer/proto/source_tree.h (about)

     1  /*
     2   * Copyright 2018 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  #ifndef KYTHE_CXX_INDEXER_PROTO_SOURCE_TREE_H_
    18  #define KYTHE_CXX_INDEXER_PROTO_SOURCE_TREE_H_
    19  
    20  #include <string>
    21  #include <vector>
    22  
    23  #include "absl/container/flat_hash_map.h"
    24  #include "google/protobuf/compiler/importer.h"
    25  #include "google/protobuf/io/zero_copy_stream.h"
    26  
    27  namespace kythe {
    28  
    29  // An implementation of SourceTree that
    30  //  - provides only pre-loaded files and
    31  //  - understands the path substitutions (generalizing search paths) used by
    32  //    the Proto compiler (e.g., for import statements).
    33  // Needed because Proto files will import "foo/bar.proto" and not want to care
    34  // whether the path is actually "bazel-out/long/path/foo/genprotos/bar.proto".
    35  // A ProtoFileParser passes exactly the argument of import statements, leaving
    36  // details like this to some other party (in this case the FileReader).
    37  //
    38  // Takes a sequence of substitutions (s, t) such that paths beginning with s
    39  // (and where the end of s is the end of a path component) can be treated as
    40  // though they instead began with t for purposes of file lookup. This is the
    41  // same as what protoc gets from "-I" and "--proto_path arguments".
    42  // (Often either s is empty, in which case t is essentially a search path, or
    43  // s and t completely specify virtual and actual filenames.)
    44  //
    45  // Substitutions are attempted one at a time (not composed) in the order they
    46  // appear, which should match the order they were specified on the protoc
    47  // command line. If no applicable substitution finds a valid file, the
    48  // filename is considered one more time with no substitution before failing.
    49  class PreloadedProtoFileTree : public google::protobuf::compiler::SourceTree {
    50   public:
    51    PreloadedProtoFileTree(
    52        const std::vector<std::pair<std::string, std::string>>* substitutions,
    53        absl::flat_hash_map<std::string, std::string>* file_mapping_cache)
    54        : substitutions_(substitutions),
    55          file_mapping_cache_(file_mapping_cache) {}
    56  
    57    // disallow copy and assign
    58    PreloadedProtoFileTree(const PreloadedProtoFileTree&) = delete;
    59    void operator=(const PreloadedProtoFileTree&) = delete;
    60  
    61    // Add a file's full name (i.e., what any substitutions will map the name(s)
    62    // by which it is included onto) to the FileReader.
    63    // Returns false if `filename` was already added.
    64    bool AddFile(const std::string& filename, const std::string& contents);
    65  
    66    // Load the full contents of `filename` into `contents`, if possible, and
    67    // return whether this was successful.
    68    // Note that ProtoFileParser passes the literal argument to import statements
    69    // as `filename`, leaving FileReaders to do any elaboration (e.g., in this
    70    // case, applying path substitutions).
    71    google::protobuf::io::ZeroCopyInputStream* Open(
    72        absl::string_view filename) override;
    73  
    74    // If Open() returns nullptr, calling this method immediately will return a
    75    // description of the error.
    76    std::string GetLastErrorMessage() override { return last_error_; }
    77  
    78    // A wrapper around Open(), that reads the proto file contents into a buffer.
    79    bool Read(absl::string_view file_path, std::string* out);
    80  
    81   private:
    82    // All path prefix substitutions to consider.
    83    const std::vector<std::pair<std::string, std::string>>* const substitutions_;
    84  
    85    // A map of pre-substitution to post-substitution names for all files that
    86    // have been successfully read via this reader.
    87    absl::flat_hash_map<std::string, std::string>* file_mapping_cache_;
    88  
    89    // Path (post-substitution) -> file contents.
    90    absl::flat_hash_map<std::string, std::string> file_map_;
    91  
    92    // A description of the error from the last call to Open() (if any).
    93    std::string last_error_;
    94  };
    95  
    96  }  // namespace kythe
    97  
    98  #endif  // KYTHE_CXX_INDEXER_PROTO_SOURCE_TREE_H_