Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 10:12:02

0001 // Protocol Buffers - Google's data interchange format
0002 // Copyright 2024 Google LLC.  All rights reserved.
0003 //
0004 // Use of this source code is governed by a BSD-style
0005 // license that can be found in the LICENSE file or at
0006 // https://developers.google.com/open-source/licenses/bsd
0007 
0008 // Author: kenton@google.com (Kenton Varda)
0009 //  Based on original Protocol Buffers design by
0010 //  Sanjay Ghemawat, Jeff Dean, and others.
0011 //
0012 // Utility class for writing text to a ZeroCopyOutputStream.
0013 
0014 #ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
0015 #define GOOGLE_PROTOBUF_IO_PRINTER_H__
0016 
0017 #include <cstddef>
0018 #include <functional>
0019 #include <initializer_list>
0020 #include <string>
0021 #include <type_traits>
0022 #include <utility>
0023 #include <vector>
0024 
0025 #include "absl/cleanup/cleanup.h"
0026 #include "absl/container/flat_hash_map.h"
0027 #include "absl/functional/any_invocable.h"
0028 #include "absl/functional/function_ref.h"
0029 #include "absl/log/absl_check.h"
0030 #include "absl/meta/type_traits.h"
0031 #include "absl/strings/str_cat.h"
0032 #include "absl/strings/str_format.h"
0033 #include "absl/strings/string_view.h"
0034 #include "absl/types/optional.h"
0035 #include "absl/types/variant.h"
0036 #include "google/protobuf/io/zero_copy_sink.h"
0037 
0038 
0039 // Must be included last.
0040 #include "google/protobuf/port_def.inc"
0041 
0042 namespace google {
0043 namespace protobuf {
0044 namespace io {
0045 
0046 // Records annotations about a Printer's output.
0047 class PROTOBUF_EXPORT AnnotationCollector {
0048  public:
0049   // Annotation is a offset range and a payload pair. This payload's layout is
0050   // specific to derived types of AnnotationCollector.
0051   using Annotation = std::pair<std::pair<size_t, size_t>, std::string>;
0052 
0053   // The semantic meaning of an annotation. This enum mirrors
0054   // google.protobuf.GeneratedCodeInfo.Annotation.Semantic, and the enumerator values
0055   // should match it.
0056   enum Semantic {
0057     kNone = 0,
0058     kSet = 1,
0059     kAlias = 2,
0060   };
0061 
0062   virtual ~AnnotationCollector() = default;
0063 
0064   // Records that the bytes in file_path beginning with begin_offset and ending
0065   // before end_offset are associated with the SourceCodeInfo-style path.
0066   virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
0067                              const std::string& file_path,
0068                              const std::vector<int>& path) = 0;
0069 
0070   virtual void AddAnnotation(size_t begin_offset, size_t end_offset,
0071                              const std::string& file_path,
0072                              const std::vector<int>& path,
0073                              absl::optional<Semantic> semantic) {
0074     AddAnnotation(begin_offset, end_offset, file_path, path);
0075   }
0076 
0077   // TODO I don't see why we need virtuals here. Just a vector of
0078   // range, payload pairs stored in a context should suffice.
0079   virtual void AddAnnotationNew(Annotation&) {}
0080 };
0081 
0082 // Records annotations about a Printer's output to a Protobuf message,
0083 // assuming that it has a repeated submessage field named `annotation` with
0084 // fields matching
0085 //
0086 // message ??? {
0087 //   repeated int32 path = 1;
0088 //   optional string source_file = 2;
0089 //   optional int32 begin = 3;
0090 //   optional int32 end = 4;
0091 //   optional int32 semantic = 5;
0092 // }
0093 template <typename AnnotationProto>
0094 class AnnotationProtoCollector : public AnnotationCollector {
0095  private:
0096   // Some users of this type use it with a proto that does not have a
0097   // "semantic" field. Therefore, we need to detect it with SFINAE.
0098 
0099   // go/ranked-overloads
0100   struct Rank0 {};
0101   struct Rank1 : Rank0 {};
0102 
0103   template <typename Proto>
0104   static auto SetSemantic(Proto* p, int semantic, Rank1)
0105       -> decltype(p->set_semantic(
0106           static_cast<typename Proto::Semantic>(semantic))) {
0107     return p->set_semantic(static_cast<typename Proto::Semantic>(semantic));
0108   }
0109 
0110   template <typename Proto>
0111   static void SetSemantic(Proto*, int, Rank0) {}
0112 
0113  public:
0114   explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
0115       : annotation_proto_(annotation_proto) {}
0116 
0117   void AddAnnotation(size_t begin_offset, size_t end_offset,
0118                      const std::string& file_path,
0119                      const std::vector<int>& path) override {
0120     AddAnnotation(begin_offset, end_offset, file_path, path, absl::nullopt);
0121   }
0122 
0123   void AddAnnotation(size_t begin_offset, size_t end_offset,
0124                      const std::string& file_path, const std::vector<int>& path,
0125                      absl::optional<Semantic> semantic) override {
0126     auto* annotation = annotation_proto_->add_annotation();
0127     for (int i = 0; i < path.size(); ++i) {
0128       annotation->add_path(path[i]);
0129     }
0130     annotation->set_source_file(file_path);
0131     annotation->set_begin(begin_offset);
0132     annotation->set_end(end_offset);
0133 
0134     if (semantic.has_value()) {
0135       SetSemantic(annotation, *semantic, Rank1{});
0136     }
0137   }
0138 
0139   void AddAnnotationNew(Annotation& a) override {
0140     auto* annotation = annotation_proto_->add_annotation();
0141     annotation->ParseFromString(a.second);
0142     annotation->set_begin(a.first.first);
0143     annotation->set_end(a.first.second);
0144   }
0145 
0146  private:
0147   AnnotationProto* annotation_proto_;
0148 };
0149 
0150 // A source code printer for assisting in code generation.
0151 //
0152 // This type implements a simple templating language for substituting variables
0153 // into static, user-provided strings, and also tracks indentation
0154 // automatically.
0155 //
0156 // The main entry-point for this type is the Emit function, which can be used
0157 // as thus:
0158 //
0159 //   Printer p(output);
0160 //   p.Emit({{"class", my_class_name}}, R"cc(
0161 //     class $class$ {
0162 //      public:
0163 //       $class$(int x) : x_(x) {}
0164 //      private:
0165 //       int x_;
0166 //     };
0167 //   )cc");
0168 //
0169 // Substitutions are of the form $var$, which is looked up in the map passed in
0170 // as the first argument. The variable delimiter character, $, can be chosen to
0171 // be something convenient for the target language. For example, in PHP, which
0172 // makes heavy use of $, it can be made into something like # instead.
0173 //
0174 // A literal $ can be emitted by writing $$.
0175 //
0176 // Substitutions may contain spaces around the name of the variable, which will
0177 // be ignored for the purposes of looking up the variable to substitute in, but
0178 // which will be reproduced in the output:
0179 //
0180 //   p.Emit({{"foo", "bar"}}, "$ foo $");
0181 //
0182 // emits the string " bar ". If the substituted-in variable is the empty string,
0183 // then the surrounding spaces are *not* printed:
0184 //
0185 //   p.Emit({{"xyz", xyz}}, "$xyz $Thing");
0186 //
0187 // If xyz is "Foo", this will become "Foo Thing", but if it is "", this becomes
0188 // "Thing", rather than " Thing". This helps minimize awkward whitespace in the
0189 // output.
0190 //
0191 // The value may be any type that can be stringified with `absl::StrCat`:
0192 //
0193 //   p.Emit({{"num", 5}}, "x = $num$;");
0194 //
0195 // If a variable that is referenced in the format string is missing, the program
0196 // will crash. Callers must statically know that every variable reference is
0197 // valid, and MUST NOT pass user-provided strings directly into Emit().
0198 //
0199 // In practice, this means the first member of io::Printer::Sub here:
0200 //
0201 //   p.Emit({{"num", 5}}, "x = $num$;");
0202 //            ^
0203 // must always be a string literal.
0204 //
0205 // Substitutions can be configured to "chomp" a single character after them, to
0206 // help make indentation work out. This can be configured by passing a
0207 // io::Printer::Sub().WithSuffix() into Emit's substitution map:
0208 //   p.Emit({io::Printer::Sub("var", var_decl).WithSuffix(";")}, R"cc(
0209 //     class $class$ {
0210 //      public:
0211 //       $var$;
0212 //     };
0213 //   )cc");
0214 //
0215 // This will delete the ; after $var$, regardless of whether it was an empty
0216 // declaration or not. It will also intelligently attempt to clean up
0217 // empty lines that follow, if it was on an empty line; this promotes cleaner
0218 // formatting of the output.
0219 //
0220 // You can configure a large set of skippable characters, but when chomping,
0221 // only one character will actually be skipped at a time. For example, callback
0222 // substitutions (see below) use ";," by default as their "chomping set".
0223 //
0224 //   p.Emit({io::Printer::Sub("var", 123).WithSuffix(";,")}, R"cc(
0225 //       $var$,;
0226 //   )cc");
0227 //
0228 // will produce "123,".
0229 //
0230 // # Callback Substitution
0231 //
0232 // Instead of passing a string into Emit(), it is possible to pass in a callback
0233 // as a variable mapping. This will take indentation into account, which allows
0234 // factoring out parts of a formatting string while ensuring braces are
0235 // balanced:
0236 //
0237 //   p.Emit(
0238 //     {{"methods", [&] {
0239 //       p.Emit(R"cc(
0240 //         int Bar() {
0241 //            return 42;
0242 //         }
0243 //       )cc");
0244 //     }}},
0245 //     R"cc(
0246 //       class Foo {
0247 //        public:
0248 //         $methods$;
0249 //       };
0250 //     )cc"
0251 //   );
0252 //
0253 // This emits
0254 //
0255 //   class Foo {
0256 //    public:
0257 //     int Bar() {
0258 //       return 42;
0259 //     }
0260 //   };
0261 //
0262 // # Comments
0263 //
0264 // It may be desirable to place comments in a raw string that are stripped out
0265 // before printing. The prefix for Printer-ignored comments can be configured
0266 // in Options. By default, this is `//~`.
0267 //
0268 //   p.Emit(R"cc(
0269 //     // Will be printed in the output.
0270 //     //~ Won't be.
0271 //   )cc");
0272 //
0273 // # Lookup Frames
0274 //
0275 // If many calls to Emit() use the same set of variables, they can be stored
0276 // in a *variable lookup frame*, like so:
0277 //
0278 //   auto vars = p.WithVars({{"class_name", my_class_name}});
0279 //   p.Emit(R"cc(
0280 //     class $class_name$ {
0281 //      public:
0282 //       $class_name$(int x);
0283 //       // Etc.
0284 //     };
0285 //   )cc");
0286 //
0287 // WithVars() returns an RAII object that will "pop" the lookup frame on scope
0288 // exit, ensuring that the variables remain local. There are a few different
0289 // overloads of WithVars(); it accepts a map type, like absl::flat_hash_map,
0290 // either by-value (which will cause the Printer to store a copy), or by
0291 // pointer (which will cause the Printer to store a pointer, potentially
0292 // avoiding a copy.)
0293 //
0294 // p.Emit(vars, "..."); is effectively syntax sugar for
0295 //
0296 //  { auto v = p.WithVars(vars); p.Emit("..."); }
0297 //
0298 // NOTE: callbacks are *not* allowed with WithVars; callbacks should be local
0299 // to a specific Emit() call.
0300 //
0301 // # Annotations
0302 //
0303 // If Printer is given an AnnotationCollector, it will use it to record which
0304 // spans of generated code correspond to user-indicated descriptors. There are
0305 // a few different ways of indicating when to emit annotations.
0306 //
0307 // The WithAnnotations() function is like WithVars(), but accepts maps with
0308 // string keys and descriptor values. It adds an annotation variable frame and
0309 // returns an RAII object that pops the frame.
0310 //
0311 // There are two different ways to annotate code. In the first, when
0312 // substituting a variable, if there is an annotation with the same name, then
0313 // the resulting expanded value's span will be annotated with that annotation.
0314 // For example:
0315 //
0316 //   auto v = p.WithVars({{"class_name", my_class_name}});
0317 //   auto a = p.WithAnnotations({{"class_name", message_descriptor}});
0318 //   p.Emit(R"cc(
0319 //     class $class_name$ {
0320 //      public:
0321 //       $class_name$(int x);
0322 //       // Etc.
0323 //     };
0324 //   )cc");
0325 //
0326 // The span corresponding to whatever $class_name$ expands to will be annotated
0327 // as having come from message_descriptor.
0328 //
0329 // For convenience, this can be done with a single WithVars(), using the special
0330 // three-argument form:
0331 //
0332 //   auto v = p.WithVars({{"class_name", my_class_name, message_descriptor}});
0333 //   p.Emit(R"cc(
0334 //     class $class_name$ {
0335 //      public:
0336 //       $class_name$(int x);
0337 //       // Etc.
0338 //     };
0339 //   )cc");
0340 //
0341 //
0342 // Alternatively, a range may be given explicitly:
0343 //
0344 //   auto a = p.WithAnnotations({{"my_desc", message_descriptor}});
0345 //   p.Emit(R"cc(
0346 //     $_start$my_desc$
0347 //     class Foo {
0348 //       // Etc.
0349 //     };
0350 //     $_end$my_desc$
0351 //   )cc");
0352 //
0353 // The special $_start$ and $_end$ variables indicate the start and end of an
0354 // annotated span, which is annotated with the variable that follows. This
0355 // form can produce somewhat unreadable format strings and is not recommended.
0356 //
0357 // Note that whitespace after a $_start$ and before an $_end$ is not printed.
0358 //
0359 // # Indentation
0360 //
0361 // Printer tracks an indentation amount to add to each new line, independent
0362 // from indentation in an Emit() call's literal. The amount of indentation to
0363 // add is controlled by the WithIndent() function:
0364 //
0365 //   p.Emit("class $class_name$ {");
0366 //   {
0367 //     auto indent = p.WithIndent();
0368 //     p.Emit(R"cc(
0369 //       public:
0370 //        $class_name$(int x);
0371 //     )cc");
0372 //   }
0373 //   p.Emit("};");
0374 //
0375 // This will automatically add one level of indentation to all code in scope of
0376 // `indent`, which is an RAII object much like the return value of `WithVars()`.
0377 //
0378 // # Old API
0379 // TODO: Delete this documentation.
0380 //
0381 // Printer supports an older-style API that is in the process of being
0382 // re-written. The old documentation is reproduced here until all use-cases are
0383 // handled.
0384 //
0385 // This simple utility class assists in code generation.  It basically
0386 // allows the caller to define a set of variables and then output some
0387 // text with variable substitutions.  Example usage:
0388 //
0389 //   Printer printer(output, '$');
0390 //   map<string, string> vars;
0391 //   vars["name"] = "Bob";
0392 //   printer.Print(vars, "My name is $name$.");
0393 //
0394 // The above writes "My name is Bob." to the output stream.
0395 //
0396 // Printer aggressively enforces correct usage, crashing (with assert failures)
0397 // in the case of undefined variables in debug builds. This helps greatly in
0398 // debugging code which uses it.
0399 //
0400 // If a Printer is constructed with an AnnotationCollector, it will provide it
0401 // with annotations that connect the Printer's output to paths that can identify
0402 // various descriptors.  In the above example, if person_ is a descriptor that
0403 // identifies Bob, we can associate the output string "My name is Bob." with
0404 // a source path pointing to that descriptor with:
0405 //
0406 //   printer.Annotate("name", person_);
0407 //
0408 // The AnnotationCollector will be sent an annotation linking the output range
0409 // covering "Bob" to the logical path provided by person_.  Tools may use
0410 // this association to (for example) link "Bob" in the output back to the
0411 // source file that defined the person_ descriptor identifying Bob.
0412 //
0413 // Annotate can only examine variables substituted during the last call to
0414 // Print.  It is invalid to refer to a variable that was used multiple times
0415 // in a single Print call.
0416 //
0417 // In full generality, one may specify a range of output text using a beginning
0418 // substitution variable and an ending variable.  The resulting annotation will
0419 // span from the first character of the substituted value for the beginning
0420 // variable to the last character of the substituted value for the ending
0421 // variable.  For example, the Annotate call above is equivalent to this one:
0422 //
0423 //   printer.Annotate("name", "name", person_);
0424 //
0425 // This is useful if multiple variables combine to form a single span of output
0426 // that should be annotated with the same source path.  For example:
0427 //
0428 //   Printer printer(output, '$');
0429 //   map<string, string> vars;
0430 //   vars["first"] = "Alice";
0431 //   vars["last"] = "Smith";
0432 //   printer.Print(vars, "My name is $first$ $last$.");
0433 //   printer.Annotate("first", "last", person_);
0434 //
0435 // This code would associate the span covering "Alice Smith" in the output with
0436 // the person_ descriptor.
0437 //
0438 // Note that the beginning variable must come before (or overlap with, in the
0439 // case of zero-sized substitution values) the ending variable.
0440 //
0441 // It is also sometimes useful to use variables with zero-sized values as
0442 // markers.  This avoids issues with multiple references to the same variable
0443 // and also allows annotation ranges to span literal text from the Print
0444 // templates:
0445 //
0446 //   Printer printer(output, '$');
0447 //   map<string, string> vars;
0448 //   vars["foo"] = "bar";
0449 //   vars["function"] = "call";
0450 //   vars["mark"] = "";
0451 //   printer.Print(vars, "$function$($foo$,$foo$)$mark$");
0452 //   printer.Annotate("function", "mark", call_);
0453 //
0454 // This code associates the span covering "call(bar,bar)" in the output with the
0455 // call_ descriptor.
0456 class PROTOBUF_EXPORT Printer {
0457  private:
0458   struct AnnotationRecord;
0459 
0460  public:
0461   // This type exists to work around an absl type that has not yet been
0462   // released.
0463   struct SourceLocation {
0464     static SourceLocation current() { return {}; }
0465     absl::string_view file_name() const { return "<unknown>"; }
0466     int line() const { return 0; }
0467   };
0468 
0469   static constexpr char kDefaultVariableDelimiter = '$';
0470   static constexpr absl::string_view kProtocCodegenTrace =
0471       "PROTOC_CODEGEN_TRACE";
0472 
0473   // Sink type for constructing substitutions to pass to WithVars() and Emit().
0474   class Sub;
0475 
0476   // Options for controlling how the output of a Printer is formatted.
0477   struct Options {
0478     Options() = default;
0479     Options(const Options&) = default;
0480     Options(Options&&) = default;
0481     Options(char variable_delimiter, AnnotationCollector* annotation_collector)
0482         : variable_delimiter(variable_delimiter),
0483           annotation_collector(annotation_collector) {}
0484 
0485     // The delimiter for variable substitutions, e.g. $foo$.
0486     char variable_delimiter = kDefaultVariableDelimiter;
0487     // An optional listener the Printer calls whenever it emits a source
0488     // annotation; may be null.
0489     AnnotationCollector* annotation_collector = nullptr;
0490     // The "comment start" token for the language being generated. This is used
0491     // to allow the Printer to emit debugging annotations in the source code
0492     // output.
0493     absl::string_view comment_start = "//";
0494     // The token for beginning comments that are discarded by Printer's internal
0495     // formatter.
0496     absl::string_view ignored_comment_start = "//~";
0497     // The number of spaces that a single level of indentation adds by default;
0498     // this is the amount that WithIndent() increases indentation by.
0499     size_t spaces_per_indent = 2;
0500     // Whether to emit a "codegen trace" for calls to Emit(). If true, each call
0501     // to Emit() will print a comment indicating where in the source of the
0502     // compiler the Emit() call occurred.
0503     //
0504     // If disengaged, defaults to whether or not the environment variable
0505     // `PROTOC_CODEGEN_TRACE` is set.
0506     absl::optional<bool> enable_codegen_trace = absl::nullopt;
0507   };
0508 
0509   // Constructs a new Printer with the default options to output to
0510   // `output`.
0511   explicit Printer(ZeroCopyOutputStream* output);
0512 
0513   // Constructs a new printer with the given set of options to output to
0514   // `output`.
0515   Printer(ZeroCopyOutputStream* output, Options options);
0516 
0517   // Old-style constructor. Avoid in preference to the two constructors above.
0518   //
0519   // Will eventually be marked as deprecated.
0520   Printer(ZeroCopyOutputStream* output, char variable_delimiter,
0521           AnnotationCollector* annotation_collector = nullptr);
0522 
0523   Printer(const Printer&) = delete;
0524   Printer& operator=(const Printer&) = delete;
0525 
0526   // Pushes a new variable lookup frame that stores `vars` by reference.
0527   //
0528   // Returns an RAII object that pops the lookup frame.
0529   template <typename Map>
0530   auto WithVars(const Map* vars);
0531 
0532   // Pushes a new variable lookup frame that stores `vars` by value.
0533   //
0534   // Returns an RAII object that pops the lookup frame.
0535   template <typename Map = absl::flat_hash_map<std::string, std::string>,
0536             typename = std::enable_if_t<!std::is_pointer<Map>::value>,
0537             // Prefer the more specific span impl if this could be turned into
0538             // a span.
0539             typename = std::enable_if_t<
0540                 !std::is_convertible<Map, absl::Span<const Sub>>::value>>
0541   auto WithVars(Map&& vars);
0542 
0543   // Pushes a new variable lookup frame that stores `vars` by value.
0544   //
0545   // Returns an RAII object that pops the lookup frame.
0546   auto WithVars(absl::Span<const Sub> vars);
0547 
0548   // Looks up a variable set with WithVars().
0549   //
0550   // Will crash if:
0551   // - `var` is not present in the lookup frame table.
0552   // - `var` is a callback, rather than a string.
0553   absl::string_view LookupVar(absl::string_view var);
0554 
0555   // Pushes a new annotation lookup frame that stores `vars` by reference.
0556   //
0557   // Returns an RAII object that pops the lookup frame.
0558   template <typename Map>
0559   auto WithAnnotations(const Map* vars);
0560 
0561   // Pushes a new variable lookup frame that stores `vars` by value.
0562   //
0563   // When writing `WithAnnotations({...})`, this is the overload that will be
0564   // called, and it will synthesize an `absl::flat_hash_map`.
0565   //
0566   // Returns an RAII object that pops the lookup frame.
0567   template <typename Map = absl::flat_hash_map<std::string, AnnotationRecord>>
0568   auto WithAnnotations(Map&& vars);
0569 
0570   // Increases the indentation by `indent` spaces; when nullopt, increments
0571   // indentation by the configured default spaces_per_indent.
0572   //
0573   // Returns an RAII object that removes this indentation.
0574   auto WithIndent(absl::optional<size_t> indent = absl::nullopt) {
0575     size_t delta = indent.value_or(options_.spaces_per_indent);
0576     indent_ += delta;
0577     return absl::MakeCleanup([this, delta] { indent_ -= delta; });
0578   }
0579 
0580   // Emits formatted source code to the underlying output. See the class
0581   // documentation for more details.
0582   //
0583   // `format` MUST be a string constant.
0584   void Emit(absl::string_view format,
0585             SourceLocation loc = SourceLocation::current());
0586 
0587   // Emits formatted source code to the underlying output, injecting
0588   // additional variables as a lookup frame for just this call. See the class
0589   // documentation for more details.
0590   //
0591   // `format` MUST be a string constant.
0592   void Emit(absl::Span<const Sub> vars, absl::string_view format,
0593             SourceLocation loc = SourceLocation::current());
0594 
0595   // Write a string directly to the underlying output, performing no formatting
0596   // of any sort.
0597   void PrintRaw(absl::string_view data) { WriteRaw(data.data(), data.size()); }
0598 
0599   // Write a string directly to the underlying output, performing no formatting
0600   // of any sort.
0601   void WriteRaw(const char* data, size_t size);
0602 
0603   // True if any write to the underlying stream failed.  (We don't just
0604   // crash in this case because this is an I/O failure, not a programming
0605   // error.)
0606   bool failed() const { return failed_; }
0607 
0608   // -- Old-style API below; to be deprecated and removed. --
0609   // TODO: Deprecate these APIs.
0610 
0611   template <typename Map = absl::flat_hash_map<std::string, std::string>>
0612   void Print(const Map& vars, absl::string_view text);
0613 
0614   template <typename... Args>
0615   void Print(absl::string_view text, const Args&... args);
0616 
0617   // Link a substitution variable emitted by the last call to Print to the
0618   // object described by descriptor.
0619   template <typename SomeDescriptor>
0620   void Annotate(
0621       absl::string_view varname, const SomeDescriptor* descriptor,
0622       absl::optional<AnnotationCollector::Semantic> semantic = absl::nullopt) {
0623     Annotate(varname, varname, descriptor, semantic);
0624   }
0625 
0626   // Link the output range defined by the substitution variables as emitted by
0627   // the last call to Print to the object described by descriptor. The range
0628   // begins at begin_varname's value and ends after the last character of the
0629   // value substituted for end_varname.
0630   template <typename Desc>
0631   void Annotate(
0632       absl::string_view begin_varname, absl::string_view end_varname,
0633       const Desc* descriptor,
0634       absl::optional<AnnotationCollector::Semantic> semantic = absl::nullopt);
0635 
0636   // Link a substitution variable emitted by the last call to Print to the file
0637   // with path file_name.
0638   void Annotate(
0639       absl::string_view varname, absl::string_view file_name,
0640       absl::optional<AnnotationCollector::Semantic> semantic = absl::nullopt) {
0641     Annotate(varname, varname, file_name, semantic);
0642   }
0643 
0644   // Link the output range defined by the substitution variables as emitted by
0645   // the last call to Print to the file with path file_name. The range begins
0646   // at begin_varname's value and ends after the last character of the value
0647   // substituted for end_varname.
0648   void Annotate(
0649       absl::string_view begin_varname, absl::string_view end_varname,
0650       absl::string_view file_name,
0651       absl::optional<AnnotationCollector::Semantic> semantic = absl::nullopt) {
0652     if (options_.annotation_collector == nullptr) {
0653       return;
0654     }
0655 
0656     Annotate(begin_varname, end_varname, file_name, {}, semantic);
0657   }
0658 
0659   // Indent text by `options.spaces_per_indent`; undone by Outdent().
0660   void Indent() { indent_ += options_.spaces_per_indent; }
0661 
0662   // Undoes a call to Indent().
0663   void Outdent();
0664 
0665   // FormatInternal is a helper function not meant to use directly, use
0666   // compiler::cpp::Formatter instead.
0667   template <typename Map = absl::flat_hash_map<std::string, std::string>>
0668   void FormatInternal(absl::Span<const std::string> args, const Map& vars,
0669                       absl::string_view format);
0670 
0671   // Injects a substitution listener for the lifetime of the RAII object
0672   // returned.
0673   // While the listener is active it will receive a callback on each
0674   // substitution label found.
0675   // This can be used to add basic verification on top of emit routines.
0676   auto WithSubstitutionListener(
0677       absl::AnyInvocable<void(absl::string_view, SourceLocation)> listener) {
0678     ABSL_CHECK(substitution_listener_ == nullptr);
0679     substitution_listener_ = std::move(listener);
0680     return absl::MakeCleanup([this] { substitution_listener_ = nullptr; });
0681   }
0682 
0683  private:
0684   struct PrintOptions;
0685   struct Format;
0686 
0687   // Helper type for wrapping a variable substitution expansion result.
0688   template <bool owned>
0689   struct ValueImpl;
0690 
0691   using ValueView = ValueImpl</*owned=*/false>;
0692   using Value = ValueImpl</*owned=*/true>;
0693 
0694   // Provide a helper to use heterogeneous lookup when it's available.
0695   template <typename...>
0696   using Void = void;
0697 
0698   template <typename Map, typename = void>
0699   struct HasHeteroLookup : std::false_type {};
0700   template <typename Map>
0701   struct HasHeteroLookup<Map, Void<decltype(std::declval<Map>().find(
0702                                   std::declval<absl::string_view>()))>>
0703       : std::true_type {};
0704 
0705   template <typename Map,
0706             typename = std::enable_if_t<HasHeteroLookup<Map>::value>>
0707   static absl::string_view ToStringKey(absl::string_view x) {
0708     return x;
0709   }
0710 
0711   template <typename Map,
0712             typename = std::enable_if_t<!HasHeteroLookup<Map>::value>>
0713   static std::string ToStringKey(absl::string_view x) {
0714     return std::string(x);
0715   }
0716 
0717   Format TokenizeFormat(absl::string_view format_string,
0718                         const PrintOptions& options);
0719 
0720   // Emit an annotation for the range defined by the given substitution
0721   // variables, as set by the most recent call to PrintImpl() that set
0722   // `use_substitution_map` to true.
0723   //
0724   // The range begins at the start of `begin_varname`'s value and ends after the
0725   // last byte of `end_varname`'s value.
0726   //
0727   // `begin_varname` and `end_varname may` refer to the same variable.
0728   void Annotate(absl::string_view begin_varname, absl::string_view end_varname,
0729                 absl::string_view file_path, const std::vector<int>& path,
0730                 absl::optional<AnnotationCollector::Semantic> semantic);
0731 
0732   // The core printing implementation. There are three public entry points,
0733   // which enable different slices of functionality that are controlled by the
0734   // `opts` argument.
0735   void PrintImpl(absl::string_view format, absl::Span<const std::string> args,
0736                  PrintOptions opts);
0737 
0738   // This is a private function only so that it can see PrintOptions.
0739   static bool Validate(bool cond, PrintOptions opts,
0740                        absl::FunctionRef<std::string()> message);
0741   static bool Validate(bool cond, PrintOptions opts, absl::string_view message);
0742 
0743   // Performs calls to `Validate()` to check that `index < current_arg_index`
0744   // and `index < args_len`, producing appropriate log lines if the checks fail,
0745   // and crashing if necessary.
0746   bool ValidateIndexLookupInBounds(size_t index, size_t current_arg_index,
0747                                    size_t args_len, PrintOptions opts);
0748 
0749   // Prints indentation if `at_start_of_line_` is true.
0750   void IndentIfAtStart();
0751 
0752   // Prints a codegen trace, for the given location in the compiler's source.
0753   void PrintCodegenTrace(absl::optional<SourceLocation> loc);
0754 
0755   // The core implementation for "fully-elaborated" variable definitions.
0756   auto WithDefs(absl::Span<const Sub> vars, bool allow_callbacks);
0757 
0758   // Returns the start and end of the value that was substituted in place of
0759   // the variable `varname` in the last call to PrintImpl() (with
0760   // `use_substitution_map` set), if such a variable was substituted exactly
0761   // once.
0762   absl::optional<std::pair<size_t, size_t>> GetSubstitutionRange(
0763       absl::string_view varname, PrintOptions opts);
0764 
0765   google::protobuf::io::zc_sink_internal::ZeroCopyStreamByteSink sink_;
0766   Options options_;
0767   size_t indent_ = 0;
0768   bool at_start_of_line_ = true;
0769   bool failed_ = false;
0770 
0771   size_t paren_depth_ = 0;
0772   std::vector<size_t> paren_depth_to_omit_;
0773 
0774   std::vector<std::function<absl::optional<ValueView>(absl::string_view)>>
0775       var_lookups_;
0776 
0777   std::vector<
0778       std::function<absl::optional<AnnotationRecord>(absl::string_view)>>
0779       annotation_lookups_;
0780 
0781   // If set, we invoke this when we do a label substitution. This can be used to
0782   // verify consistency of the generated code while we generate it.
0783   absl::AnyInvocable<void(absl::string_view, SourceLocation)>
0784       substitution_listener_;
0785 
0786   // A map from variable name to [start, end) offsets in the output buffer.
0787   //
0788   // This stores the data looked up by GetSubstitutionRange().
0789   absl::flat_hash_map<std::string, std::pair<size_t, size_t>> substitutions_;
0790   // Keeps track of the keys in `substitutions_` that need to be updated when
0791   // indents are inserted. These are keys that refer to the beginning of the
0792   // current line.
0793   std::vector<std::string> line_start_variables_;
0794 };
0795 
0796 // Options for PrintImpl().
0797 struct Printer::PrintOptions {
0798   // The callsite of the public entry-point. Only Emit() sets this.
0799   absl::optional<SourceLocation> loc;
0800   // If set, Validate() calls will not crash the program.
0801   bool checks_are_debug_only = false;
0802   // If set, the `substitutions_` map will be populated as variables are
0803   // substituted.
0804   bool use_substitution_map = false;
0805   // If set, the ${1$ and $}$ forms will be substituted. These are used for
0806   // a slightly janky annotation-insertion mechanism in FormatInternal, that
0807   // requires that passed-in substitution variables be serialized protos.
0808   bool use_curly_brace_substitutions = false;
0809   // If set, the $n$ forms will be substituted, pulling from the `args`
0810   // argument to PrintImpl().
0811   bool allow_digit_substitutions = true;
0812   // If set, when a variable substitution with spaces in it, such as $ var$,
0813   // is encountered, the spaces are stripped, so that it is as if it was
0814   // $var$. If $var$ substitutes to a non-empty string, the removed spaces are
0815   // printed around the substituted value.
0816   //
0817   // See the class documentation for more information on this behavior.
0818   bool strip_spaces_around_vars = true;
0819   // If set, leading whitespace will be stripped from the format string to
0820   // determine the "extraneous indentation" that is produced when the format
0821   // string is a C++ raw string. This is used to remove leading spaces from
0822   // a raw string that would otherwise result in erratic indentation in the
0823   // output.
0824   bool strip_raw_string_indentation = false;
0825   // If set, the annotation lookup frames are searched, per the annotation
0826   // semantics of Emit() described in the class documentation.
0827   bool use_annotation_frames = true;
0828 };
0829 
0830 // Helper type for wrapping a variable substitution expansion result.
0831 template <bool owned>
0832 struct Printer::ValueImpl {
0833  private:
0834   template <typename T>
0835   struct IsSubImpl : std::false_type {};
0836   template <bool a>
0837   struct IsSubImpl<ValueImpl<a>> : std::true_type {};
0838 
0839  public:
0840   using StringType = std::conditional_t<owned, std::string, absl::string_view>;
0841   // These callbacks return false if this is a recursive call.
0842   using Callback = std::function<bool()>;
0843   using StringOrCallback = absl::variant<StringType, Callback>;
0844 
0845   ValueImpl() = default;
0846 
0847   // This is a template to avoid colliding with the copy constructor below.
0848   template <typename Value,
0849             typename = std::enable_if_t<
0850                 !IsSubImpl<absl::remove_cvref_t<Value>>::value>>
0851   ValueImpl(Value&& value)  // NOLINT
0852       : value(ToStringOrCallback(std::forward<Value>(value), Rank2{})) {
0853     if (absl::holds_alternative<Callback>(this->value)) {
0854       consume_after = ";,";
0855     }
0856   }
0857 
0858   // Copy ctor/assign allow interconversion of the two template parameters.
0859   template <bool that_owned>
0860   ValueImpl(const ValueImpl<that_owned>& that) {  // NOLINT
0861     *this = that;
0862   }
0863 
0864   template <bool that_owned>
0865   ValueImpl& operator=(const ValueImpl<that_owned>& that);
0866 
0867   const StringType* AsString() const {
0868     return absl::get_if<StringType>(&value);
0869   }
0870 
0871   const Callback* AsCallback() const { return absl::get_if<Callback>(&value); }
0872 
0873   StringOrCallback value;
0874   std::string consume_after;
0875   bool consume_parens_if_empty = false;
0876 
0877  private:
0878   // go/ranked-overloads
0879   struct Rank0 {};
0880   struct Rank1 : Rank0 {};
0881   struct Rank2 : Rank1 {};
0882 
0883   // Dummy template for delayed instantiation, which is required for the
0884   // static assert below to kick in only when this function is called when it
0885   // shouldn't.
0886   //
0887   // This is done to produce a better error message than the "candidate does
0888   // not match" SFINAE errors.
0889   template <typename Cb, typename = decltype(std::declval<Cb&&>()())>
0890   StringOrCallback ToStringOrCallback(Cb&& cb, Rank2);
0891 
0892   // Separate from the AlphaNum overload to avoid copies when taking strings
0893   // by value when in `owned` mode.
0894   StringOrCallback ToStringOrCallback(StringType s, Rank1) { return s; }
0895 
0896   StringOrCallback ToStringOrCallback(const absl::AlphaNum& s, Rank0) {
0897     return StringType(s.Piece());
0898   }
0899 };
0900 
0901 template <bool owned>
0902 template <bool that_owned>
0903 Printer::ValueImpl<owned>& Printer::ValueImpl<owned>::operator=(
0904     const ValueImpl<that_owned>& that) {
0905   // Cast to void* is required, since this and that may potentially be of
0906   // different types (due to the `that_owned` parameter).
0907   if (static_cast<const void*>(this) == static_cast<const void*>(&that)) {
0908     return *this;
0909   }
0910 
0911   using ThatStringType = typename ValueImpl<that_owned>::StringType;
0912 
0913   if (auto* str = absl::get_if<ThatStringType>(&that.value)) {
0914     value = StringType(*str);
0915   } else {
0916     value = absl::get<Callback>(that.value);
0917   }
0918 
0919   consume_after = that.consume_after;
0920   consume_parens_if_empty = that.consume_parens_if_empty;
0921   return *this;
0922 }
0923 
0924 template <bool owned>
0925 template <typename Cb, typename /*Sfinae*/>
0926 auto Printer::ValueImpl<owned>::ToStringOrCallback(Cb&& cb, Rank2)
0927     -> StringOrCallback {
0928   return Callback(
0929       [cb = std::forward<Cb>(cb), is_called = false]() mutable -> bool {
0930         if (is_called) {
0931           // Catch whether or not this function is being called recursively.
0932           return false;
0933         }
0934         is_called = true;
0935         cb();
0936         is_called = false;
0937         return true;
0938       });
0939 }
0940 
0941 struct Printer::AnnotationRecord {
0942   std::vector<int> path;
0943   std::string file_path;
0944   absl::optional<AnnotationCollector::Semantic> semantic;
0945 
0946   // AnnotationRecord's constructors are *not* marked as explicit,
0947   // specifically so that it is possible to construct a
0948   // map<string, AnnotationRecord> by writing
0949   //
0950   // {{"foo", my_cool_descriptor}, {"bar", "file.proto"}}
0951 
0952   template <
0953       typename String,
0954       std::enable_if_t<std::is_convertible<const String&, std::string>::value,
0955                        int> = 0>
0956   AnnotationRecord(  // NOLINT(google-explicit-constructor)
0957       const String& file_path,
0958       absl::optional<AnnotationCollector::Semantic> semantic = absl::nullopt)
0959       : file_path(file_path), semantic(semantic) {}
0960 
0961   template <typename Desc,
0962             // This SFINAE clause excludes char* from matching this
0963             // constructor.
0964             std::enable_if_t<std::is_class<Desc>::value, int> = 0>
0965   AnnotationRecord(  // NOLINT(google-explicit-constructor)
0966       const Desc* desc,
0967       absl::optional<AnnotationCollector::Semantic> semantic = absl::nullopt)
0968       : file_path(desc->file()->name()), semantic(semantic) {
0969     desc->GetLocationPath(&path);
0970   }
0971 };
0972 
0973 class Printer::Sub {
0974  public:
0975   template <typename Value>
0976   Sub(std::string key, Value&& value)
0977       : key_(std::move(key)),
0978         value_(std::forward<Value>(value)),
0979         annotation_(absl::nullopt) {}
0980 
0981   Sub AnnotatedAs(AnnotationRecord annotation) && {
0982     annotation_ = std::move(annotation);
0983     return std::move(*this);
0984   }
0985 
0986   Sub WithSuffix(std::string sub_suffix) && {
0987     value_.consume_after = std::move(sub_suffix);
0988     return std::move(*this);
0989   }
0990 
0991   Sub ConditionalFunctionCall() && {
0992     value_.consume_parens_if_empty = true;
0993     return std::move(*this);
0994   }
0995 
0996   absl::string_view key() const { return key_; }
0997 
0998   absl::string_view value() const {
0999     const auto* str = value_.AsString();
1000     ABSL_CHECK(str != nullptr)
1001         << "could not find " << key() << "; found callback instead";
1002     return *str;
1003   }
1004 
1005  private:
1006   friend class Printer;
1007 
1008   std::string key_;
1009   Value value_;
1010   absl::optional<AnnotationRecord> annotation_;
1011 };
1012 
1013 template <typename Map>
1014 auto Printer::WithVars(const Map* vars) {
1015   var_lookups_.emplace_back(
1016       [vars](absl::string_view var) -> absl::optional<ValueView> {
1017         auto it = vars->find(ToStringKey<Map>(var));
1018         if (it == vars->end()) {
1019           return absl::nullopt;
1020         }
1021         return ValueView(it->second);
1022       });
1023   return absl::MakeCleanup([this] { var_lookups_.pop_back(); });
1024 }
1025 
1026 template <typename Map, typename, typename /*Sfinae*/>
1027 auto Printer::WithVars(Map&& vars) {
1028   var_lookups_.emplace_back(
1029       [vars = std::forward<Map>(vars)](
1030           absl::string_view var) -> absl::optional<ValueView> {
1031         auto it = vars.find(ToStringKey<Map>(var));
1032         if (it == vars.end()) {
1033           return absl::nullopt;
1034         }
1035         return ValueView(it->second);
1036       });
1037   return absl::MakeCleanup([this] { var_lookups_.pop_back(); });
1038 }
1039 
1040 template <typename Map>
1041 auto Printer::WithAnnotations(const Map* vars) {
1042   annotation_lookups_.emplace_back(
1043       [vars](absl::string_view var) -> absl::optional<AnnotationRecord> {
1044         auto it = vars->find(ToStringKey<Map>(var));
1045         if (it == vars->end()) {
1046           return absl::nullopt;
1047         }
1048         return AnnotationRecord(it->second);
1049       });
1050   return absl::MakeCleanup([this] { annotation_lookups_.pop_back(); });
1051 }
1052 
1053 template <typename Map>
1054 auto Printer::WithAnnotations(Map&& vars) {
1055   annotation_lookups_.emplace_back(
1056       [vars = std::forward<Map>(vars)](
1057           absl::string_view var) -> absl::optional<AnnotationRecord> {
1058         auto it = vars.find(ToStringKey<Map>(var));
1059         if (it == vars.end()) {
1060           return absl::nullopt;
1061         }
1062         return AnnotationRecord(it->second);
1063       });
1064   return absl::MakeCleanup([this] { annotation_lookups_.pop_back(); });
1065 }
1066 
1067 inline void Printer::Emit(absl::string_view format, SourceLocation loc) {
1068   Emit({}, format, loc);
1069 }
1070 
1071 template <typename Map>
1072 void Printer::Print(const Map& vars, absl::string_view text) {
1073   PrintOptions opts;
1074   opts.checks_are_debug_only = true;
1075   opts.use_substitution_map = true;
1076   opts.allow_digit_substitutions = false;
1077 
1078   auto pop = WithVars(&vars);
1079   PrintImpl(text, {}, opts);
1080 }
1081 
1082 template <typename... Args>
1083 void Printer::Print(absl::string_view text, const Args&... args) {
1084   static_assert(sizeof...(args) % 2 == 0, "");
1085 
1086   // Include an extra arg, since a zero-length array is ill-formed, and
1087   // MSVC complains.
1088   absl::string_view vars[] = {args..., ""};
1089   absl::flat_hash_map<absl::string_view, absl::string_view> map;
1090   map.reserve(sizeof...(args) / 2);
1091   for (size_t i = 0; i < sizeof...(args); i += 2) {
1092     map.emplace(vars[i], vars[i + 1]);
1093   }
1094 
1095   Print(map, text);
1096 }
1097 
1098 template <typename Desc>
1099 void Printer::Annotate(absl::string_view begin_varname,
1100                        absl::string_view end_varname, const Desc* descriptor,
1101                        absl::optional<AnnotationCollector::Semantic> semantic) {
1102   if (options_.annotation_collector == nullptr) {
1103     return;
1104   }
1105 
1106   std::vector<int> path;
1107   descriptor->GetLocationPath(&path);
1108   Annotate(begin_varname, end_varname, descriptor->file()->name(), path,
1109            semantic);
1110 }
1111 
1112 template <typename Map>
1113 void Printer::FormatInternal(absl::Span<const std::string> args,
1114                              const Map& vars, absl::string_view format) {
1115   PrintOptions opts;
1116   opts.use_curly_brace_substitutions = true;
1117   opts.strip_spaces_around_vars = true;
1118 
1119   auto pop = WithVars(&vars);
1120   PrintImpl(format, args, opts);
1121 }
1122 
1123 inline auto Printer::WithDefs(absl::Span<const Sub> vars,
1124                               bool allow_callbacks) {
1125   absl::flat_hash_map<std::string, Value> var_map;
1126   var_map.reserve(vars.size());
1127 
1128   absl::flat_hash_map<std::string, AnnotationRecord> annotation_map;
1129 
1130   for (const auto& var : vars) {
1131     ABSL_CHECK(allow_callbacks || var.value_.AsCallback() == nullptr)
1132         << "callback arguments are not permitted in this position";
1133     auto result = var_map.insert({var.key_, var.value_});
1134     ABSL_CHECK(result.second)
1135         << "repeated variable in Emit() or WithVars() call: \"" << var.key_
1136         << "\"";
1137     if (var.annotation_.has_value()) {
1138       annotation_map.insert({var.key_, *var.annotation_});
1139     }
1140   }
1141 
1142   var_lookups_.emplace_back([map = std::move(var_map)](absl::string_view var)
1143                                 -> absl::optional<ValueView> {
1144     auto it = map.find(var);
1145     if (it == map.end()) {
1146       return absl::nullopt;
1147     }
1148     return ValueView(it->second);
1149   });
1150 
1151   bool has_annotations = !annotation_map.empty();
1152   if (has_annotations) {
1153     annotation_lookups_.emplace_back(
1154         [map = std::move(annotation_map)](
1155             absl::string_view var) -> absl::optional<AnnotationRecord> {
1156           auto it = map.find(var);
1157           if (it == map.end()) {
1158             return absl::nullopt;
1159           }
1160           return it->second;
1161         });
1162   }
1163 
1164   return absl::MakeCleanup([this, has_annotations] {
1165     var_lookups_.pop_back();
1166     if (has_annotations) {
1167       annotation_lookups_.pop_back();
1168     }
1169   });
1170 }
1171 
1172 inline auto Printer::WithVars(absl::Span<const Sub> vars) {
1173   return WithDefs(vars, /*allow_callbacks=*/false);
1174 }
1175 }  // namespace io
1176 }  // namespace protobuf
1177 }  // namespace google
1178 
1179 #include "google/protobuf/port_undef.inc"
1180 
1181 #endif  // GOOGLE_PROTOBUF_IO_PRINTER_H__