kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/indexer/proto/proto_graph_builder.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  // Wrappers for adding nodes/edges to the Kythe graph.
    18  
    19  #ifndef KYTHE_CXX_INDEXER_PROTO_PROTO_GRAPH_BUILDER_H_
    20  #define KYTHE_CXX_INDEXER_PROTO_PROTO_GRAPH_BUILDER_H_
    21  
    22  #include <functional>
    23  #include <string>
    24  #include <utility>
    25  #include <vector>
    26  
    27  #include "absl/log/log.h"
    28  #include "google/protobuf/io/printer.h"
    29  #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
    30  #include "kythe/cxx/common/indexing/KytheGraphRecorder.h"
    31  #include "kythe/cxx/common/indexing/KytheOutputStream.h"
    32  #include "kythe/cxx/common/kythe_metadata_file.h"
    33  #include "kythe/cxx/common/kythe_uri.h"
    34  #include "kythe/cxx/indexer/proto/vname_util.h"
    35  #include "kythe/proto/common.pb.h"
    36  #include "kythe/proto/storage.pb.h"
    37  #include "kythe/proto/xref.pb.h"
    38  
    39  namespace kythe {
    40  
    41  // The canonical name for the protobuf language in Kythe
    42  static const char kLanguageName[] = "protobuf";
    43  
    44  // A simple structure for the offsets we need to make anchor nodes, because
    45  // Descriptors omit these and kythe::proto::Location is seriously overkill.
    46  struct Location {
    47    proto::VName file;
    48    size_t begin;
    49    size_t end;
    50  };
    51  
    52  // Contains the hooks for emitting the correct Kythe artifacts based at
    53  // relevant points in a proto file's source tree.
    54  class ProtoGraphBuilder {
    55   public:
    56    // Constructs a graph builder using the given graph recorder. Ownership
    57    // of the graph recorder is not transferred, and it must outlive this
    58    // object. `vname_for_rel_path` should return a VName for the given
    59    // relative (to the file under analysis) path.
    60    ProtoGraphBuilder(
    61        KytheGraphRecorder* recorder,
    62        std::function<proto::VName(const std::string&)> vname_for_rel_path);
    63  
    64    // disallow copy and assign
    65    ProtoGraphBuilder(const ProtoGraphBuilder&) = delete;
    66    void operator=(const ProtoGraphBuilder&) = delete;
    67  
    68    // Returns a VName for the given protobuf descriptor. Descriptors share
    69    // various member names but do not participate in any sort of inheritance
    70    // hierarchy, so we're stuck with a template.
    71    template <typename SomeDescriptor>
    72    proto::VName VNameForDescriptor(const SomeDescriptor* descriptor) {
    73      return ::kythe::lang_proto::VNameForDescriptor(descriptor,
    74                                                     vname_for_rel_path_);
    75    }
    76  
    77    // Sets the metadata for this file.
    78    void SetMetadata(std::unique_ptr<MetadataFile> meta) {
    79      meta_ = std::move(meta);
    80    }
    81  
    82    // Sets the source text for this file.
    83    void SetText(const proto::VName& node_name, const std::string& content);
    84  
    85    // Records a node with the given VName and kind in the graph.
    86    void AddNode(const proto::VName& node_name, NodeKindID node_kind);
    87  
    88    // Maybe add a generated file edge
    89    void MaybeAddMetadataFileRules(const proto::VName& file);
    90  
    91    // Records an edge of the given kind between the named nodes in the graph.
    92    void AddEdge(const proto::VName& start, const proto::VName& end,
    93                 EdgeKindID start_to_end_kind);
    94  
    95    // Records an edge of the given kind between the named nodes in the graph.
    96    void AddEdge(const proto::VName& start, const proto::VName& end,
    97                 EdgeKindID start_to_end_kind, int ordinal);
    98  
    99    // Creates and add to the graph a proto language-specific declaration node.
   100    proto::VName CreateAndAddAnchorNode(const Location& location);
   101  
   102    // Creates and adds a documentation node for `element` to the graph. The
   103    // `location` is used to derive the location of the documentation text.
   104    proto::VName CreateAndAddDocNode(const Location& location,
   105                                     const proto::VName& element);
   106  
   107    // Adds an import for the file.
   108    void AddImport(const std::string& import, const Location& location);
   109  
   110    // Adds a namespace for the file.  Generally the first call.
   111    void AddNamespace(const proto::VName& package, const Location& location);
   112  
   113    // Adds a value field to an already-added enum declaration.
   114    void AddValueToEnum(const proto::VName& enum_type, const proto::VName& value,
   115                        const Location& location);
   116  
   117    // Adds a field to an already-added protocol buffer message.
   118    // `parent` refers to the context where the field is defined,
   119    // and `message` refers to the message this field is a part of.
   120    // These only differ when processing extensions.
   121    void AddFieldToMessage(const proto::VName* parent,
   122                           const proto::VName& message, const proto::VName* oneof,
   123                           const proto::VName& field, const Location& location);
   124  
   125    // Adds a oneof to an already-added protocol buffer message.
   126    void AddOneofToMessage(const proto::VName& message, const proto::VName& oneof,
   127                           const Location& location);
   128  
   129    // Adds a stubby method to an already-added RPC service.
   130    void AddMethodToService(const proto::VName& service,
   131                            const proto::VName& method, const Location& location);
   132  
   133    // Adds an enum.
   134    void AddEnumType(const proto::VName* parent, const proto::VName& enum_type,
   135                     const Location& location);
   136  
   137    // Adds a message.
   138    void AddMessageType(const proto::VName* parent, const proto::VName& message,
   139                        const Location& location);
   140  
   141    // Adds an argument with type given by type at the specified location to an
   142    // already-added stubby service method.
   143    void AddArgumentToMethod(const proto::VName& method, const proto::VName& type,
   144                             const Location& location) {
   145      AddReference(type, location);
   146    }
   147  
   148    // Adds typed edges for the given RPC method.
   149    void AddMethodType(const proto::VName& method, const proto::VName& input,
   150                       const proto::VName& output);
   151  
   152    // Adds an anchor for location and a Ref edge to referent
   153    void AddReference(const proto::VName& referent, const Location& location);
   154  
   155    // Adds an edge indicating that `term` has type `type`.
   156    void AddTyping(const proto::VName& term, const proto::VName& type);
   157  
   158    // Adds a stubby service to the file or optionally provided namespace scope.
   159    // Nested fields/declarations/etc must be added separately.
   160    void AddService(const proto::VName* parent, const proto::VName& service,
   161                    const Location& location);
   162  
   163    // Adds an edge associating the comment at a location with an element.
   164    void AddDocComment(const proto::VName& element, const Location& location);
   165  
   166    // Adds a code fact to the element.
   167    void AddCodeFact(const proto::VName& element, const MarkedSource& code);
   168  
   169    // Marks the given node as deprecated.
   170    void SetDeprecated(const proto::VName& node_name);
   171  
   172   private:
   173    // Adds an edge from the metadata if metadata exists and a rule is found for
   174    // location.
   175    void MaybeAddEdgeFromMetadata(const Location& location,
   176                                  const proto::VName& target);
   177    // Where we output nodes, edges, etc..
   178    KytheGraphRecorder* recorder_;
   179  
   180    // The metadata file for generated protos.
   181    std::unique_ptr<MetadataFile> meta_;
   182  
   183    // A function to resolve relative paths to VNames.
   184    std::function<proto::VName(const std::string&)> vname_for_rel_path_;
   185  
   186    // The text of the current file being analyzed.
   187    std::string current_file_contents_;
   188  
   189    // Whether the builtin rpc type node has been emitted.
   190    bool builtin_rpc_type_emitted_ = false;
   191  
   192    proto::VName builtin_rpc_type_constructor_;
   193  };
   194  
   195  }  // namespace kythe
   196  
   197  #endif  // KYTHE_CXX_INDEXER_PROTO_PROTO_GRAPH_BUILDER_H_