|
16 | 16 |
|
17 | 17 | #include <cstddef> |
18 | 18 | #include <string> |
| 19 | +#include <string_view> |
19 | 20 | #include <utility> |
20 | 21 | #include <vector> |
21 | 22 |
|
@@ -102,13 +103,87 @@ bool SignaturesOverlap(const OverloadDecl& lhs, const OverloadDecl& rhs) { |
102 | 103 | return args_overlap; |
103 | 104 | } |
104 | 105 |
|
| 106 | +// Recursively appends a string representation of the given `type` to `result`. |
| 107 | +// Type parameters are enclosed in angle brackets and separated by commas. |
| 108 | +void AppendTypeToOverloadId(std::string* result, const Type& type) { |
| 109 | + const auto& parameters = type.GetParameters(); |
| 110 | + if (parameters.empty()) { |
| 111 | + absl::StrAppend(result, type.name()); |
| 112 | + } else { |
| 113 | + absl::StrAppend(result, type.name(), "<"); |
| 114 | + for (size_t i = 0; i < parameters.size(); ++i) { |
| 115 | + AppendTypeToOverloadId(result, parameters[i]); |
| 116 | + if (i < parameters.size() - 1) { |
| 117 | + absl::StrAppend(result, ","); |
| 118 | + } |
| 119 | + } |
| 120 | + absl::StrAppend(result, ">"); |
| 121 | + } |
| 122 | +} |
| 123 | + |
| 124 | +// Generates an identifier for the overload based on the function name and |
| 125 | +// the types of the arguments. If `member` is true, the first argument type |
| 126 | +// is used as the receiver and is prepended to the function name, followed by |
| 127 | +// a dot. |
| 128 | +// |
| 129 | +// Examples: |
| 130 | +// |
| 131 | +// - `foo()` |
| 132 | +// - `foo(int)` |
| 133 | +// - `bar.foo(int)` |
| 134 | +// - `foo(int,string)` |
| 135 | +// - `foo(list<int>,list<string>)` |
| 136 | +// - `bar.foo(list<int>, list<opaque<A>>)` |
| 137 | +// |
| 138 | +std::string GenereateOverloadId(std::string_view function_name, |
| 139 | + const std::vector<Type>& args, bool member) { |
| 140 | + std::string result; |
| 141 | + result.reserve(function_name.size() + 3 + args.size() * 8); |
| 142 | + |
| 143 | + if (member) { |
| 144 | + if (!args.empty()) { |
| 145 | + AppendTypeToOverloadId(&result, args[0]); |
| 146 | + } |
| 147 | + absl::StrAppend(&result, ".", function_name, "("); |
| 148 | + for (size_t i = 1; i < args.size(); ++i) { |
| 149 | + AppendTypeToOverloadId(&result, args[i]); |
| 150 | + if (i < args.size() - 1) { |
| 151 | + absl::StrAppend(&result, ","); |
| 152 | + } |
| 153 | + } |
| 154 | + absl::StrAppend(&result, ")"); |
| 155 | + } else { |
| 156 | + absl::StrAppend(&result, function_name, "("); |
| 157 | + for (size_t i = 0; i < args.size(); ++i) { |
| 158 | + AppendTypeToOverloadId(&result, args[i]); |
| 159 | + if (i < args.size() - 1) { |
| 160 | + absl::StrAppend(&result, ","); |
| 161 | + } |
| 162 | + } |
| 163 | + absl::StrAppend(&result, ")"); |
| 164 | + } |
| 165 | + |
| 166 | + return result; |
| 167 | +} |
| 168 | + |
105 | 169 | template <typename Overload> |
106 | | -void AddOverloadInternal(std::vector<OverloadDecl>& insertion_order, |
| 170 | +void AddOverloadInternal(std::string_view function_name, |
| 171 | + std::vector<OverloadDecl>& insertion_order, |
107 | 172 | OverloadDeclHashSet& overloads, Overload&& overload, |
108 | 173 | absl::Status& status) { |
109 | 174 | if (!status.ok()) { |
110 | 175 | return; |
111 | 176 | } |
| 177 | + |
| 178 | + if (overload.id().empty()) { |
| 179 | + OverloadDecl overload_decl = overload; |
| 180 | + overload_decl.set_id(GenereateOverloadId( |
| 181 | + function_name, overload_decl.args(), overload_decl.member())); |
| 182 | + AddOverloadInternal(function_name, insertion_order, overloads, |
| 183 | + std::move(overload_decl), status); |
| 184 | + return; |
| 185 | + } |
| 186 | + |
112 | 187 | if (auto it = overloads.find(overload.id()); it != overloads.end()) { |
113 | 188 | status = absl::AlreadyExistsError( |
114 | 189 | absl::StrCat("overload already exists: ", overload.id())); |
@@ -174,13 +249,13 @@ absl::flat_hash_set<std::string> OverloadDecl::GetTypeParams() const { |
174 | 249 |
|
175 | 250 | void FunctionDecl::AddOverloadImpl(const OverloadDecl& overload, |
176 | 251 | absl::Status& status) { |
177 | | - AddOverloadInternal(overloads_.insertion_order, overloads_.set, overload, |
178 | | - status); |
| 252 | + AddOverloadInternal(name_, overloads_.insertion_order, overloads_.set, |
| 253 | + overload, status); |
179 | 254 | } |
180 | 255 |
|
181 | 256 | void FunctionDecl::AddOverloadImpl(OverloadDecl&& overload, |
182 | 257 | absl::Status& status) { |
183 | | - AddOverloadInternal(overloads_.insertion_order, overloads_.set, |
| 258 | + AddOverloadInternal(name_, overloads_.insertion_order, overloads_.set, |
184 | 259 | std::move(overload), status); |
185 | 260 | } |
186 | 261 |
|
|
0 commit comments