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