• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 //
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file or at
6 // https://developers.google.com/open-source/licenses/bsd
7 
8 // Author: kenton@google.com (Kenton Varda)
9 //  Based on original Protocol Buffers design by
10 //  Sanjay Ghemawat, Jeff Dean, and others.
11 //
12 // Implements parsing of .proto files to FileDescriptorProtos.
13 
14 #ifndef GOOGLE_PROTOBUF_COMPILER_PARSER_H__
15 #define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
16 
17 #include <cstdint>
18 #include <string>
19 #include <type_traits>
20 #include <utility>
21 
22 #include "absl/container/flat_hash_map.h"
23 #include "absl/strings/string_view.h"
24 #include "google/protobuf/descriptor.h"
25 #include "google/protobuf/descriptor.pb.h"
26 #include "google/protobuf/io/tokenizer.h"
27 #include "google/protobuf/repeated_field.h"
28 
29 // Must be included last.
30 #include "google/protobuf/port_def.inc"
31 
32 namespace google {
33 namespace protobuf {
34 
35 class Message;
36 
37 namespace compiler {
38 
39 // Defined in this file.
40 class Parser;
41 class SourceLocationTable;
42 
43 // Implements parsing of protocol definitions (such as .proto files).
44 //
45 // Note that most users will be more interested in the Importer class.
46 // Parser is a lower-level class which simply converts a single .proto file
47 // to a FileDescriptorProto.  It does not resolve import directives or perform
48 // many other kinds of validation needed to construct a complete
49 // FileDescriptor.
50 class PROTOBUF_EXPORT Parser final {
51  public:
52   Parser();
53   Parser(const Parser&) = delete;
54   Parser& operator=(const Parser&) = delete;
55   ~Parser();
56 
57   // Parse the entire input and construct a FileDescriptorProto representing
58   // it.  Returns true if no errors occurred, false otherwise.
59   bool Parse(io::Tokenizer* input, FileDescriptorProto* file);
60 
61   // Optional features:
62 
63   // DEPRECATED:  New code should use the SourceCodeInfo embedded in the
64   //   FileDescriptorProto.
65   //
66   // Requests that locations of certain definitions be recorded to the given
67   // SourceLocationTable while parsing.  This can be used to look up exact line
68   // and column numbers for errors reported by DescriptorPool during validation.
69   // Set to NULL (the default) to discard source location information.
RecordSourceLocationsTo(SourceLocationTable * location_table)70   void RecordSourceLocationsTo(SourceLocationTable* location_table) {
71     source_location_table_ = location_table;
72   }
73 
74   // Requests that errors be recorded to the given ErrorCollector while
75   // parsing.  Set to NULL (the default) to discard error messages.
RecordErrorsTo(io::ErrorCollector * error_collector)76   void RecordErrorsTo(io::ErrorCollector* error_collector) {
77     error_collector_ = error_collector;
78   }
79 
80   // Returns the identifier used in the "syntax = " declaration, if one was
81   // seen during the last call to Parse(), or the empty string otherwise.
GetSyntaxIdentifier()82   absl::string_view GetSyntaxIdentifier() { return syntax_identifier_; }
83 
84   // If set true, input files will be required to begin with a syntax
85   // identifier.  Otherwise, files may omit this.  If a syntax identifier
86   // is provided, it must be 'syntax = "proto2";' and must appear at the
87   // top of this file regardless of whether or not it was required.
SetRequireSyntaxIdentifier(bool value)88   void SetRequireSyntaxIdentifier(bool value) {
89     require_syntax_identifier_ = value;
90   }
91 
92   // Call SetStopAfterSyntaxIdentifier(true) to tell the parser to stop
93   // parsing as soon as it has seen the syntax identifier, or lack thereof.
94   // This is useful for quickly identifying the syntax of the file without
95   // parsing the whole thing.  If this is enabled, no error will be recorded
96   // if the syntax identifier is something other than "proto2" (since
97   // presumably the caller intends to deal with that), but other kinds of
98   // errors (e.g. parse errors) will still be reported.  When this is enabled,
99   // you may pass a NULL FileDescriptorProto to Parse().
SetStopAfterSyntaxIdentifier(bool value)100   void SetStopAfterSyntaxIdentifier(bool value) {
101     stop_after_syntax_identifier_ = value;
102   }
103 
104  private:
105   class LocationRecorder;
106   struct MapField;
107 
108   // =================================================================
109   // Error recovery helpers
110 
111   // Consume the rest of the current statement.  This consumes tokens
112   // until it sees one of:
113   //   ';'  Consumes the token and returns.
114   //   '{'  Consumes the brace then calls SkipRestOfBlock().
115   //   '}'  Returns without consuming.
116   //   EOF  Returns (can't consume).
117   // The Parser often calls SkipStatement() after encountering a syntax
118   // error.  This allows it to go on parsing the following lines, allowing
119   // it to report more than just one error in the file.
120   void SkipStatement();
121 
122   // Consume the rest of the current block, including nested blocks,
123   // ending after the closing '}' is encountered and consumed, or at EOF.
124   void SkipRestOfBlock();
125 
126   // -----------------------------------------------------------------
127   // Single-token consuming helpers
128   //
129   // These make parsing code more readable.
130 
131   // True if the current token is TYPE_END.
132   inline bool AtEnd();
133 
134   // True if the next token matches the given text.
135   inline bool LookingAt(absl::string_view text);
136   // True if the next token is of the given type.
137   inline bool LookingAtType(io::Tokenizer::TokenType token_type);
138 
139   // If the next token exactly matches the text given, consume it and return
140   // true.  Otherwise, return false without logging an error.
141   bool TryConsume(absl::string_view text);
142 
143   // In the following functions the error is passed as a lazily evaluated
144   // callable to reduce stack usage and delay the actual execution of the error
145   // statement.
146   // Super simple type erasure interface. Similar to absl::FunctionRef but takes
147   // the callable by value. Optimized for lambdas with at most a single pointer
148   // as payload.
149   class ErrorMaker {
150     using StorageT = void*;
151 
152    public:
153     template <typename F,
154               typename = std::enable_if_t<std::is_same<
155                   std::string, decltype(std::declval<F>()())>::value>>
ErrorMaker(F f)156     ErrorMaker(F f) {
157       static_assert(sizeof(F) <= sizeof(StorageT), "");
158       static_assert(alignof(F) <= alignof(StorageT), "");
159       static_assert(std::is_trivially_destructible<F>::value, "");
160       ::new (static_cast<void*>(storage_)) F(f);
161       func_ = [](const void* p) { return (*reinterpret_cast<const F*>(p))(); };
162     }
163     // This overload helps callers that just want to pass a literal string.
ErrorMaker(const char * error)164     ErrorMaker(const char* error) : error_(error), func_(nullptr) {}
165 
get()166     std::string get() const { return func_ ? func_(storage_) : error_; }
167 
168    private:
169     union {
170       alignas(StorageT) char storage_[sizeof(StorageT)];
171       const char* error_;
172     };
173     std::string (*func_)(const void*);
174   };
175 
176   // These attempt to read some kind of token from the input.  If successful,
177   // they return true.  Otherwise they return false and add the given error
178   // to the error list.
179 
180   // Consume a token with the exact text given.
181   bool Consume(absl::string_view text, ErrorMaker error);
182   // Same as above, but automatically generates the error "Expected \"text\".",
183   // where "text" is the expected token text.
184   bool Consume(absl::string_view text);
185   // Consume a token of type IDENTIFIER and store its text in "output".
186   bool ConsumeIdentifier(std::string* output, ErrorMaker error);
187   // Consume an integer and store its value in "output".
188   bool ConsumeInteger(int* output, ErrorMaker error);
189   // Consume a signed integer and store its value in "output".
190   bool ConsumeSignedInteger(int* output, ErrorMaker error);
191   // Consume a 64-bit integer and store its value in "output".  If the value
192   // is greater than max_value, an error will be reported.
193   bool ConsumeInteger64(uint64_t max_value, uint64_t* output, ErrorMaker error);
194   // Try to consume a 64-bit integer and store its value in "output".  No
195   // error is reported on failure, allowing caller to consume token another way.
196   bool TryConsumeInteger64(uint64_t max_value, uint64_t* output);
197   // Consume a number and store its value in "output".  This will accept
198   // tokens of either INTEGER or FLOAT type.
199   bool ConsumeNumber(double* output, ErrorMaker error);
200   // Consume a string literal and store its (unescaped) value in "output".
201   bool ConsumeString(std::string* output, ErrorMaker error);
202 
203   // Consume a token representing the end of the statement.  Comments between
204   // this token and the next will be harvested for documentation.  The given
205   // LocationRecorder should refer to the declaration that was just parsed;
206   // it will be populated with these comments.
207   //
208   // TODO:  The LocationRecorder is const because historically locations
209   //   have been passed around by const reference, for no particularly good
210   //   reason.  We should probably go through and change them all to mutable
211   //   pointer to make this more intuitive.
212   bool TryConsumeEndOfDeclaration(absl::string_view text,
213                                   const LocationRecorder* location);
214   bool TryConsumeEndOfDeclarationFinishScope(absl::string_view text,
215                                              const LocationRecorder* location);
216 
217   bool ConsumeEndOfDeclaration(absl::string_view text,
218                                const LocationRecorder* location);
219 
220   // -----------------------------------------------------------------
221   // Error logging helpers
222 
223   // Invokes error_collector_->RecordError(), if error_collector_ is not NULL.
224   PROTOBUF_NOINLINE void RecordError(int line, int column, ErrorMaker error);
225 
226   // Invokes error_collector_->RecordError() with the line and column number
227   // of the current token.
228   PROTOBUF_NOINLINE void RecordError(ErrorMaker error);
229 
230   // Invokes error_collector_->RecordWarning(), if error_collector_ is not NULL.
231   PROTOBUF_NOINLINE void RecordWarning(int line, int column, ErrorMaker error);
232 
233   // Invokes error_collector_->RecordWarning() with the line and column number
234   // of the current token.
235   PROTOBUF_NOINLINE void RecordWarning(ErrorMaker error);
236 
237   // Records a location in the SourceCodeInfo.location table (see
238   // descriptor.proto).  We use RAII to ensure that the start and end locations
239   // are recorded -- the constructor records the start location and the
240   // destructor records the end location.  Since the parser is
241   // recursive-descent, this works out beautifully.
242   class PROTOBUF_EXPORT LocationRecorder {
243    public:
244     // Construct the file's "root" location.
245     LocationRecorder(Parser* parser);
246 
247     // Construct a location that represents a declaration nested within the
248     // given parent.  E.g. a field's location is nested within the location
249     // for a message type.  The parent's path will be copied, so you should
250     // call AddPath() only to add the path components leading from the parent
251     // to the child (as opposed to leading from the root to the child).
252     LocationRecorder(const LocationRecorder& parent);
253 
254     // Convenience constructors that call AddPath() one or two times.
255     LocationRecorder(const LocationRecorder& parent, int path1);
256     LocationRecorder(const LocationRecorder& parent, int path1, int path2);
257 
258     // Creates a recorder that generates locations into given source code info.
259     LocationRecorder(const LocationRecorder& parent, int path1,
260                      SourceCodeInfo* source_code_info);
261 
262     ~LocationRecorder();
263 
264     // Add a path component.  See SourceCodeInfo.Location.path in
265     // descriptor.proto.
266     void AddPath(int path_component);
267 
268     // By default the location is considered to start at the current token at
269     // the time the LocationRecorder is created.  StartAt() sets the start
270     // location to the given token instead.
271     void StartAt(const io::Tokenizer::Token& token);
272 
273     // Start at the same location as some other LocationRecorder.
274     void StartAt(const LocationRecorder& other);
275 
276     // By default the location is considered to end at the previous token at
277     // the time the LocationRecorder is destroyed.  EndAt() sets the end
278     // location to the given token instead.
279     void EndAt(const io::Tokenizer::Token& token);
280 
281     // Records the start point of this location to the SourceLocationTable that
282     // was passed to RecordSourceLocationsTo(), if any.  SourceLocationTable
283     // is an older way of keeping track of source locations which is still
284     // used in some places.
285     void RecordLegacyLocation(
286         const Message* descriptor,
287         DescriptorPool::ErrorCollector::ErrorLocation location);
288     void RecordLegacyImportLocation(const Message* descriptor,
289                                     const std::string& name);
290 
291     // Returns the number of path components in the recorder's current location.
292     int CurrentPathSize() const;
293 
294     // Attaches leading and trailing comments to the location.  The two strings
295     // will be swapped into place, so after this is called *leading and
296     // *trailing will be empty.
297     //
298     // TODO:  See comment on TryConsumeEndOfDeclaration(), above, for
299     //   why this is const.
300     void AttachComments(std::string* leading, std::string* trailing,
301                         std::vector<std::string>* detached_comments) const;
302 
303    private:
304     Parser* parser_;
305     SourceCodeInfo* source_code_info_;
306     SourceCodeInfo::Location* location_;
307 
308     void Init(const LocationRecorder& parent, SourceCodeInfo* source_code_info);
309   };
310 
311   // =================================================================
312   // Parsers for various language constructs
313 
314   // Parses the "syntax = \"proto2\";" line at the top of the file.  Returns
315   // false if it failed to parse or if the syntax identifier was not
316   // recognized.
317   bool ParseSyntaxIdentifier(const FileDescriptorProto* file,
318                              const LocationRecorder& parent);
319 
320   // These methods parse various individual bits of code.  They return
321   // false if they completely fail to parse the construct.  In this case,
322   // it is probably necessary to skip the rest of the statement to recover.
323   // However, if these methods return true, it does NOT mean that there
324   // were no errors; only that there were no *syntax* errors.  For instance,
325   // if a service method is defined using proper syntax but uses a primitive
326   // type as its input or output, ParseMethodField() still returns true
327   // and only reports the error by calling RecordError().  In practice, this
328   // makes logic much simpler for the caller.
329 
330   // Parse a top-level message, enum, service, etc.
331   bool ParseTopLevelStatement(FileDescriptorProto* file,
332                               const LocationRecorder& root_location);
333 
334   // Parse various language high-level language construrcts.
335   bool ParseMessageDefinition(DescriptorProto* message,
336                               const LocationRecorder& message_location,
337                               const FileDescriptorProto* containing_file);
338   bool ParseEnumDefinition(EnumDescriptorProto* enum_type,
339                            const LocationRecorder& enum_location,
340                            const FileDescriptorProto* containing_file);
341   bool ParseServiceDefinition(ServiceDescriptorProto* service,
342                               const LocationRecorder& service_location,
343                               const FileDescriptorProto* containing_file);
344   bool ParsePackage(FileDescriptorProto* file,
345                     const LocationRecorder& root_location,
346                     const FileDescriptorProto* containing_file);
347   bool ParseImport(RepeatedPtrField<std::string>* dependency,
348                    RepeatedField<int32_t>* public_dependency,
349                    RepeatedField<int32_t>* weak_dependency,
350                    const LocationRecorder& root_location,
351                    const FileDescriptorProto* containing_file);
352 
353   // These methods parse the contents of a message, enum, or service type and
354   // add them to the given object.  They consume the entire block including
355   // the beginning and ending brace.
356   bool ParseMessageBlock(DescriptorProto* message,
357                          const LocationRecorder& message_location,
358                          const FileDescriptorProto* containing_file);
359   bool ParseEnumBlock(EnumDescriptorProto* enum_type,
360                       const LocationRecorder& enum_location,
361                       const FileDescriptorProto* containing_file);
362   bool ParseServiceBlock(ServiceDescriptorProto* service,
363                          const LocationRecorder& service_location,
364                          const FileDescriptorProto* containing_file);
365 
366   // Parse one statement within a message, enum, or service block, including
367   // final semicolon.
368   bool ParseMessageStatement(DescriptorProto* message,
369                              const LocationRecorder& message_location,
370                              const FileDescriptorProto* containing_file);
371   bool ParseEnumStatement(EnumDescriptorProto* message,
372                           const LocationRecorder& enum_location,
373                           const FileDescriptorProto* containing_file);
374   bool ParseServiceStatement(ServiceDescriptorProto* message,
375                              const LocationRecorder& service_location,
376                              const FileDescriptorProto* containing_file);
377 
378   // Parse a field of a message.  If the field is a group, its type will be
379   // added to "messages".
380   //
381   // parent_location and location_field_number_for_nested_type are needed when
382   // parsing groups -- we need to generate a nested message type within the
383   // parent and record its location accordingly.  Since the parent could be
384   // either a FileDescriptorProto or a DescriptorProto, we must pass in the
385   // correct field number to use.
386   bool ParseMessageField(FieldDescriptorProto* field,
387                          RepeatedPtrField<DescriptorProto>* messages,
388                          const LocationRecorder& parent_location,
389                          int location_field_number_for_nested_type,
390                          const LocationRecorder& field_location,
391                          const FileDescriptorProto* containing_file);
392 
393   // Like ParseMessageField() but expects the label has already been filled in
394   // by the caller.
395   bool ParseMessageFieldNoLabel(FieldDescriptorProto* field,
396                                 RepeatedPtrField<DescriptorProto>* messages,
397                                 const LocationRecorder& parent_location,
398                                 int location_field_number_for_nested_type,
399                                 const LocationRecorder& field_location,
400                                 const FileDescriptorProto* containing_file);
401 
402   bool ParseMapType(MapField* map_field, FieldDescriptorProto* field,
403                     LocationRecorder& type_name_location);
404 
405   // Parse an "extensions" declaration.
406   bool ParseExtensions(DescriptorProto* message,
407                        const LocationRecorder& extensions_location,
408                        const FileDescriptorProto* containing_file);
409 
410   // Parse a "reserved" declaration.
411   bool ParseReserved(DescriptorProto* message,
412                      const LocationRecorder& message_location);
413   bool ParseReservedNames(DescriptorProto* message,
414                           const LocationRecorder& parent_location);
415   bool ParseReservedName(std::string* name, ErrorMaker error_message);
416   bool ParseReservedIdentifiers(DescriptorProto* message,
417                                 const LocationRecorder& parent_location);
418   bool ParseReservedIdentifier(std::string* name, ErrorMaker error_message);
419   bool ParseReservedNumbers(DescriptorProto* message,
420                             const LocationRecorder& parent_location);
421   bool ParseReserved(EnumDescriptorProto* message,
422                      const LocationRecorder& message_location);
423   bool ParseReservedNames(EnumDescriptorProto* message,
424                           const LocationRecorder& parent_location);
425   bool ParseReservedIdentifiers(EnumDescriptorProto* message,
426                                 const LocationRecorder& parent_location);
427   bool ParseReservedNumbers(EnumDescriptorProto* message,
428                             const LocationRecorder& parent_location);
429 
430   // Parse an "extend" declaration.  (See also comments for
431   // ParseMessageField().)
432   bool ParseExtend(RepeatedPtrField<FieldDescriptorProto>* extensions,
433                    RepeatedPtrField<DescriptorProto>* messages,
434                    const LocationRecorder& parent_location,
435                    int location_field_number_for_nested_type,
436                    const LocationRecorder& extend_location,
437                    const FileDescriptorProto* containing_file);
438 
439   // Parse a "oneof" declaration.  The caller is responsible for setting
440   // oneof_decl->label() since it will have had to parse the label before it
441   // knew it was parsing a oneof.
442   bool ParseOneof(OneofDescriptorProto* oneof_decl,
443                   DescriptorProto* containing_type, int oneof_index,
444                   const LocationRecorder& oneof_location,
445                   const LocationRecorder& containing_type_location,
446                   const FileDescriptorProto* containing_file);
447 
448   // Parse a single enum value within an enum block.
449   bool ParseEnumConstant(EnumValueDescriptorProto* enum_value,
450                          const LocationRecorder& enum_value_location,
451                          const FileDescriptorProto* containing_file);
452 
453   // Parse enum constant options, i.e. the list in square brackets at the end
454   // of the enum constant value definition.
455   bool ParseEnumConstantOptions(EnumValueDescriptorProto* value,
456                                 const LocationRecorder& enum_value_location,
457                                 const FileDescriptorProto* containing_file);
458 
459   // Parse a single method within a service definition.
460   bool ParseServiceMethod(MethodDescriptorProto* method,
461                           const LocationRecorder& method_location,
462                           const FileDescriptorProto* containing_file);
463 
464   // Parse options of a single method or stream.
465   bool ParseMethodOptions(const LocationRecorder& parent_location,
466                           const FileDescriptorProto* containing_file,
467                           const int optionsFieldNumber,
468                           Message* mutable_options);
469 
470   // Parse "required", "optional", or "repeated" and fill in "label"
471   // with the value. Returns true if such a label is consumed.
472   bool ParseLabel(FieldDescriptorProto::Label* label,
473                   const LocationRecorder& field_location);
474 
475   // Parse a type name and fill in "type" (if it is a primitive) or
476   // "type_name" (if it is not) with the type parsed.
477   bool ParseType(FieldDescriptorProto::Type* type, std::string* type_name);
478   // Parse a user-defined type and fill in "type_name" with the name.
479   // If a primitive type is named, it is treated as an error.
480   bool ParseUserDefinedType(std::string* type_name);
481 
482   // Parses field options, i.e. the stuff in square brackets at the end
483   // of a field definition.  Also parses default value.
484   bool ParseFieldOptions(FieldDescriptorProto* field,
485                          const LocationRecorder& field_location,
486                          const FileDescriptorProto* containing_file);
487 
488   // Parse the "default" option.  This needs special handling because its
489   // type is the field's type.
490   bool ParseDefaultAssignment(FieldDescriptorProto* field,
491                               const LocationRecorder& field_location,
492                               const FileDescriptorProto* containing_file);
493 
494   bool ParseJsonName(FieldDescriptorProto* field,
495                      const LocationRecorder& field_location,
496                      const FileDescriptorProto* containing_file);
497 
498   enum OptionStyle {
499     OPTION_ASSIGNMENT,  // just "name = value"
500     OPTION_STATEMENT    // "option name = value;"
501   };
502 
503   // Parse a single option name/value pair, e.g. "ctype = CORD".  The name
504   // identifies a field of the given Message, and the value of that field
505   // is set to the parsed value.
506   bool ParseOption(Message* options, const LocationRecorder& options_location,
507                    const FileDescriptorProto* containing_file,
508                    OptionStyle style);
509 
510   // Parses a single part of a multipart option name. A multipart name consists
511   // of names separated by dots. Each name is either an identifier or a series
512   // of identifiers separated by dots and enclosed in parentheses. E.g.,
513   // "foo.(bar.baz).moo".
514   bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option,
515                            const LocationRecorder& part_location,
516                            const FileDescriptorProto* containing_file);
517 
518   // Parses a string surrounded by balanced braces.  Strips off the outer
519   // braces and stores the enclosed string in *value.
520   // E.g.,
521   //     { foo }                     *value gets 'foo'
522   //     { foo { bar: box } }        *value gets 'foo { bar: box }'
523   //     {}                          *value gets ''
524   //
525   // REQUIRES: LookingAt("{")
526   // When finished successfully, we are looking at the first token past
527   // the ending brace.
528   bool ParseUninterpretedBlock(std::string* value);
529 
530   struct MapField {
531     // Whether the field is a map field.
532     bool is_map_field;
533     // The types of the key and value if they are primitive types.
534     FieldDescriptorProto::Type key_type;
535     FieldDescriptorProto::Type value_type;
536     // Or the type names string if the types are customized types.
537     std::string key_type_name;
538     std::string value_type_name;
539 
MapFieldMapField540     MapField() : is_map_field(false) {}
541   };
542   // Desugar the map syntax to generate a nested map entry message.
543   void GenerateMapEntry(const MapField& map_field, FieldDescriptorProto* field,
544                         RepeatedPtrField<DescriptorProto>* messages);
545 
546   // Whether fields without label default to optional fields.
DefaultToOptionalFields()547   bool DefaultToOptionalFields() const {
548     if (syntax_identifier_ == "editions") return true;
549     return syntax_identifier_ == "proto3";
550   }
551 
552   bool ValidateMessage(const DescriptorProto* proto);
553   bool ValidateEnum(const EnumDescriptorProto* proto);
554 
555   // =================================================================
556 
557   io::Tokenizer* input_;
558   io::ErrorCollector* error_collector_;
559   SourceCodeInfo* source_code_info_;
560   SourceLocationTable* source_location_table_;  // legacy
561   bool had_errors_;
562   bool require_syntax_identifier_;
563   bool stop_after_syntax_identifier_;
564   std::string syntax_identifier_;
565   Edition edition_ = Edition::EDITION_UNKNOWN;
566   int recursion_depth_;
567 
568   // Leading doc comments for the next declaration.  These are not complete
569   // yet; use ConsumeEndOfDeclaration() to get the complete comments.
570   std::string upcoming_doc_comments_;
571 
572   // Detached comments are not connected to any syntax entities. Elements in
573   // this vector are paragraphs of comments separated by empty lines. The
574   // detached comments will be put into the leading_detached_comments field for
575   // the next element (See SourceCodeInfo.Location in descriptor.proto), when
576   // ConsumeEndOfDeclaration() is called.
577   std::vector<std::string> upcoming_detached_comments_;
578 };
579 
580 // A table mapping (descriptor, ErrorLocation) pairs -- as reported by
581 // DescriptorPool when validating descriptors -- to line and column numbers
582 // within the original source code.
583 //
584 // This is semi-obsolete:  FileDescriptorProto.source_code_info now contains
585 // far more complete information about source locations.  However, as of this
586 // writing you still need to use SourceLocationTable when integrating with
587 // DescriptorPool.
588 class PROTOBUF_EXPORT SourceLocationTable {
589  public:
590   SourceLocationTable();
591   ~SourceLocationTable();
592 
593   // Finds the precise location of the given error and fills in *line and
594   // *column with the line and column numbers.  If not found, sets *line to
595   // -1 and *column to 0 (since line = -1 is used to mean "error has no exact
596   // location" in the ErrorCollector interface).  Returns true if found, false
597   // otherwise.
598   bool Find(const Message* descriptor,
599             DescriptorPool::ErrorCollector::ErrorLocation location, int* line,
600             int* column) const;
601   bool FindImport(const Message* descriptor, absl::string_view name, int* line,
602                   int* column) const;
603 
604   // Adds a location to the table.
605   void Add(const Message* descriptor,
606            DescriptorPool::ErrorCollector::ErrorLocation location, int line,
607            int column);
608   void AddImport(const Message* descriptor, const std::string& name, int line,
609                  int column);
610 
611   // Clears the contents of the table.
612   void Clear();
613 
614  private:
615   using LocationMap = absl::flat_hash_map<
616       std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
617       std::pair<int, int>>;
618   LocationMap location_map_;
619   absl::flat_hash_map<std::pair<const Message*, std::string>,
620                       std::pair<int, int>>
621       import_location_map_;
622 };
623 
624 }  // namespace compiler
625 }  // namespace protobuf
626 }  // namespace google
627 
628 #include "google/protobuf/port_undef.inc"
629 
630 #endif  // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
631