kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/cxx/indexer/proto/marked_source.cc (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  #include "kythe/cxx/indexer/proto/marked_source.h"
    18  
    19  #include <optional>
    20  
    21  #include "absl/strings/str_split.h"
    22  #include "google/protobuf/descriptor.h"
    23  #include "kythe/cxx/common/indexing/KytheOutputStream.h"
    24  #include "kythe/cxx/common/kythe_uri.h"
    25  #include "kythe/cxx/indexer/proto/proto_graph_builder.h"
    26  #include "kythe/proto/common.pb.h"
    27  
    28  namespace kythe {
    29  bool GenerateMarkedSourceForDottedName(absl::string_view name,
    30                                         MarkedSource* root,
    31                                         std::optional<proto::VName> vname) {
    32    std::vector<absl::string_view> tokens = absl::StrSplit(name, '.');
    33    if (tokens.empty()) {
    34      return false;
    35    }
    36    if (tokens.size() == 1) {
    37      root->set_kind(MarkedSource::IDENTIFIER);
    38      root->set_pre_text(std::string(tokens[0]));
    39      if (vname) {
    40        root->add_link()->add_definition(URI(*vname).ToString());
    41      }
    42    } else {
    43      auto* context = root->add_child();
    44      auto* ident = root->add_child();
    45      ident->set_kind(MarkedSource::IDENTIFIER);
    46      ident->set_pre_text(std::string(tokens.back()));
    47      if (vname) {
    48        ident->add_link()->add_definition(URI(*vname).ToString());
    49      }
    50      tokens.pop_back();
    51      context->set_kind(MarkedSource::CONTEXT);
    52      context->set_post_child_text(".");
    53      context->set_add_final_list_token(true);
    54      for (const auto& token : tokens) {
    55        auto* node = context->add_child();
    56        node->set_kind(MarkedSource::IDENTIFIER);
    57        node->set_pre_text(std::string(token));
    58      }
    59    }
    60    return true;
    61  }
    62  
    63  template <typename T>
    64  static std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
    65      absl::string_view kind, const T* descriptor, ProtoGraphBuilder* builder) {
    66    MarkedSource ms;
    67    auto* mod = ms.add_child();
    68    mod->set_kind(MarkedSource::MODIFIER);
    69    mod->set_pre_text(kind);
    70    mod->set_post_text(" ");
    71    std::optional<proto::VName> vname;
    72    if (builder) {
    73      vname = builder->VNameForDescriptor(descriptor);
    74    }
    75    if (GenerateMarkedSourceForDottedName(descriptor->full_name(), ms.add_child(),
    76                                          vname)) {
    77      return ms;
    78    }
    79    return std::nullopt;
    80  }
    81  
    82  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
    83      const google::protobuf::Descriptor* descriptor,
    84      ProtoGraphBuilder* builder) {
    85    return GenerateMarkedSourceForDescriptor("message", descriptor, builder);
    86  }
    87  
    88  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
    89      const google::protobuf::EnumDescriptor* descriptor,
    90      ProtoGraphBuilder* builder) {
    91    return GenerateMarkedSourceForDescriptor("enum", descriptor, builder);
    92  }
    93  
    94  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
    95      const google::protobuf::EnumValueDescriptor* descriptor,
    96      ProtoGraphBuilder* builder) {
    97    // EnumValueDescriptor::full_name leaves off the parent enum's name.
    98    std::string full_name =
    99        descriptor->type()->full_name() + "." + descriptor->name();
   100    MarkedSource ms;
   101    if (GenerateMarkedSourceForDottedName(
   102            full_name, &ms, builder->VNameForDescriptor(descriptor))) {
   103      return ms;
   104    }
   105    return std::nullopt;
   106  }
   107  
   108  static std::optional<MarkedSource> GenerateMarkedSourceForType(
   109      const google::protobuf::FieldDescriptor* descriptor,
   110      ProtoGraphBuilder* builder) {
   111    MarkedSource type;
   112    type.set_kind(MarkedSource::TYPE);
   113    switch (descriptor->type()) {
   114      case google::protobuf::FieldDescriptor::TYPE_MESSAGE:
   115        if (descriptor->is_map()) {
   116          type.set_pre_text("map<");
   117          type.set_post_child_text(", ");
   118          type.set_post_text(">");
   119  
   120          auto key = GenerateMarkedSourceForType(
   121              descriptor->message_type()->map_key(), builder);
   122          auto val = GenerateMarkedSourceForType(
   123              descriptor->message_type()->map_value(), builder);
   124          if (!key || !val) {
   125            return std::nullopt;
   126          }
   127  
   128          *type.add_child() = *key;
   129          *type.add_child() = *val;
   130        } else if (!GenerateMarkedSourceForDottedName(
   131                       descriptor->message_type()->full_name(), type.add_child(),
   132                       builder->VNameForDescriptor(descriptor->message_type()))) {
   133          return std::nullopt;
   134        }
   135        break;
   136      case google::protobuf::FieldDescriptor::TYPE_ENUM:
   137        if (!GenerateMarkedSourceForDottedName(
   138                descriptor->enum_type()->full_name(), type.add_child(),
   139                builder->VNameForDescriptor(descriptor->enum_type()))) {
   140          return std::nullopt;
   141        }
   142        break;
   143      default:
   144        type.set_pre_text(descriptor->type_name());
   145        break;
   146    }
   147    return type;
   148  }
   149  
   150  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
   151      const google::protobuf::FieldDescriptor* descriptor,
   152      ProtoGraphBuilder* builder) {
   153    std::string full_name;
   154    if (const google::protobuf::OneofDescriptor* oneof =
   155            descriptor->real_containing_oneof()) {
   156      full_name = oneof->full_name() + "." + descriptor->name();
   157    } else {
   158      full_name = descriptor->full_name();
   159    }
   160    MarkedSource ms;
   161    ms.set_post_child_text(" ");
   162    if (!descriptor->real_containing_oneof() && !descriptor->is_map() &&
   163        (descriptor->has_presence() || descriptor->is_repeated())) {
   164      auto* mod = ms.add_child();
   165      mod->set_kind(MarkedSource::MODIFIER);
   166      switch (descriptor->label()) {
   167        case google::protobuf::FieldDescriptor::Label::LABEL_OPTIONAL:
   168          mod->set_pre_text("optional");
   169          break;
   170        case google::protobuf::FieldDescriptor::Label::LABEL_REQUIRED:
   171          mod->set_pre_text("required");
   172          break;
   173        case google::protobuf::FieldDescriptor::Label::LABEL_REPEATED:
   174          mod->set_pre_text("repeated");
   175          break;
   176      }
   177    }
   178    if (const std::optional<MarkedSource> t =
   179            GenerateMarkedSourceForType(descriptor, builder)) {
   180      *ms.add_child() = *t;
   181    }
   182    if (GenerateMarkedSourceForDottedName(
   183            full_name, ms.add_child(), builder->VNameForDescriptor(descriptor))) {
   184      return ms;
   185    }
   186    return std::nullopt;
   187  }
   188  
   189  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
   190      const google::protobuf::ServiceDescriptor* descriptor,
   191      ProtoGraphBuilder* builder) {
   192    return GenerateMarkedSourceForDescriptor("service", descriptor, builder);
   193  }
   194  
   195  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
   196      const google::protobuf::MethodDescriptor* descriptor,
   197      ProtoGraphBuilder* builder) {
   198    return GenerateMarkedSourceForDescriptor("rpc", descriptor, builder);
   199  }
   200  
   201  std::optional<MarkedSource> GenerateMarkedSourceForDescriptor(
   202      const google::protobuf::OneofDescriptor* descriptor,
   203      ProtoGraphBuilder* builder) {
   204    MarkedSource ms;
   205    if (GenerateMarkedSourceForDottedName(
   206            descriptor->full_name(), &ms,
   207            builder->VNameForDescriptor(descriptor))) {
   208      return ms;
   209    }
   210    return std::nullopt;
   211  }
   212  
   213  }  // namespace kythe