qapi: Recognize section tags and 'Features:' only after blank line
Putting a blank line before section tags and 'Features:' is good, existing practice. Enforce it. Signed-off-by: Markus Armbruster <armbru@redhat.com> Message-ID: <20240216145841.2099240-12-armbru@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
		
							parent
							
								
									d23055b8db
								
							
						
					
					
						commit
						66227e9047
					
				| @ -986,16 +986,17 @@ indented like this:: | ||||
| Extensions added after the definition was first released carry a | ||||
| "(since x.y.z)" comment. | ||||
| 
 | ||||
| The feature descriptions must be preceded by a line "Features:", like | ||||
| this:: | ||||
| The feature descriptions must be preceded by a blank line and then a | ||||
| line "Features:", like this:: | ||||
| 
 | ||||
|   # | ||||
|   # Features: | ||||
|   # | ||||
|   # @feature: Description text | ||||
| 
 | ||||
| A tagged section starts with one of the following words: | ||||
| "Note:"/"Notes:", "Since:", "Example:"/"Examples:", "Returns:", | ||||
| "TODO:".  The section ends with the start of a new section. | ||||
| A tagged section begins with a paragraph that starts with one of the | ||||
| following words: "Note:"/"Notes:", "Since:", "Example:"/"Examples:", | ||||
| "Returns:", "TODO:".  It ends with the start of a new section. | ||||
| 
 | ||||
| The second and subsequent lines of tagged sections must be indented | ||||
| like this:: | ||||
| @ -1086,8 +1087,10 @@ need to line up with each other, like this:: | ||||
|  #     or cache associativity unknown) | ||||
|  #     (since 5.0) | ||||
| 
 | ||||
| Section tags are case-sensitive and end with a colon.  Good example:: | ||||
| Section tags are case-sensitive and end with a colon.  They are only | ||||
| recognized after a blank line.  Good example:: | ||||
| 
 | ||||
|  # | ||||
|  # Since: 7.1 | ||||
| 
 | ||||
| Bad examples (all ordinary paragraphs):: | ||||
|  | ||||
| @ -538,6 +538,7 @@ class QAPIDoc: | ||||
|         # the current section | ||||
|         self._section = self.body | ||||
|         self._append_line = self._append_body_line | ||||
|         self._first_line_in_paragraph = False | ||||
| 
 | ||||
|     def has_section(self, tag: str) -> bool: | ||||
|         """Return True if we have a section with this tag.""" | ||||
| @ -560,12 +561,14 @@ class QAPIDoc: | ||||
|         line = line[1:] | ||||
|         if not line: | ||||
|             self._append_freeform(line) | ||||
|             self._first_line_in_paragraph = True | ||||
|             return | ||||
| 
 | ||||
|         if line[0] != ' ': | ||||
|             raise QAPIParseError(self._parser, "missing space after #") | ||||
|         line = line[1:] | ||||
|         self._append_line(line) | ||||
|         self._first_line_in_paragraph = False | ||||
| 
 | ||||
|     def end_comment(self) -> None: | ||||
|         self._switch_section(QAPIDoc.NullSection(self._parser)) | ||||
| @ -574,9 +577,11 @@ class QAPIDoc: | ||||
|     def _match_at_name_colon(string: str) -> Optional[Match[str]]: | ||||
|         return re.match(r'@([^:]*): *', string) | ||||
| 
 | ||||
|     @staticmethod | ||||
|     def _match_section_tag(string: str) -> Optional[Match[str]]: | ||||
|         return re.match(r'(Returns|Since|Notes?|Examples?|TODO): *', string) | ||||
|     def _match_section_tag(self, string: str) -> Optional[Match[str]]: | ||||
|         if not self._first_line_in_paragraph: | ||||
|             return None | ||||
|         return re.match(r'(Returns|Since|Notes?|Examples?|TODO): *', | ||||
|                         string) | ||||
| 
 | ||||
|     def _append_body_line(self, line: str) -> None: | ||||
|         """ | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| doc-duplicated-return.json:7:1: duplicated 'Returns' section | ||||
| doc-duplicated-return.json:8:1: duplicated 'Returns' section | ||||
|  | ||||
| @ -4,5 +4,6 @@ | ||||
| # @foo: | ||||
| # | ||||
| # Returns: 0 | ||||
| # | ||||
| # Returns: 1 | ||||
| ## | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| doc-duplicated-since.json:7:1: duplicated 'Since' section | ||||
| doc-duplicated-since.json:8:1: duplicated 'Since' section | ||||
|  | ||||
| @ -4,5 +4,6 @@ | ||||
| # @foo: | ||||
| # | ||||
| # Since: 0 | ||||
| # | ||||
| # Since: 1 | ||||
| ## | ||||
|  | ||||
| @ -154,22 +154,29 @@ | ||||
| # Features: | ||||
| # @cmd-feat1: a feature | ||||
| # @cmd-feat2: another feature | ||||
| # | ||||
| # Note: @arg3 is undocumented | ||||
| # | ||||
| # Returns: @Object | ||||
| # | ||||
| # TODO: frobnicate | ||||
| # | ||||
| # Notes: | ||||
| # | ||||
| #  - Lorem ipsum dolor sit amet | ||||
| #  - Ut enim ad minim veniam | ||||
| # | ||||
| #  Duis aute irure dolor | ||||
| # | ||||
| # Example: | ||||
| # | ||||
| #  -> in | ||||
| #  <- out | ||||
| # | ||||
| # Examples: | ||||
| #  - *verbatim* | ||||
| #  - {braces} | ||||
| # | ||||
| # Since: 2.10 | ||||
| ## | ||||
| { 'command': 'cmd', | ||||
| @ -180,9 +187,11 @@ | ||||
| ## | ||||
| # @cmd-boxed: | ||||
| # If you're bored enough to read this, go see a video of boxed cats | ||||
| # | ||||
| # Features: | ||||
| # @cmd-feat1: a feature | ||||
| # @cmd-feat2: another feature | ||||
| # | ||||
| # Example: | ||||
| # | ||||
| #  -> in | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| doc-invalid-return.json:5: 'Returns:' is only valid for commands | ||||
| doc-invalid-return.json:6: 'Returns:' is only valid for commands | ||||
|  | ||||
| @ -2,6 +2,7 @@ | ||||
| 
 | ||||
| ## | ||||
| # @FOO: | ||||
| # | ||||
| # Returns: blah | ||||
| ## | ||||
| { 'event': 'FOO' } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Markus Armbruster
						Markus Armbruster