1- """ This module implements a handler for the C language."""
1+ # This module implements a handler for the C language.
22
33from __future__ import annotations
44
1010from pathlib import Path
1111from typing import TYPE_CHECKING , Any , ClassVar , Protocol
1212
13+ from mkdocs .exceptions import PluginError
1314from mkdocstrings import BaseHandler , CollectionError , CollectorItem , get_logger
1415from pycparser import CParser , c_ast
1516
17+ from mkdocstrings_handlers .c ._internal .config import COptions
18+
1619if TYPE_CHECKING :
1720 from collections .abc import Mapping , MutableMapping
1821
1922 from mkdocs .config .defaults import MkDocsConfig
2023 from pycparser .c_ast import FileAST
2124
2225
23- logger = get_logger (__name__ )
26+ _logger = get_logger (__name__ )
2427
2528
2629@dataclass
2730class Comment :
2831 """A comment extracted from the source code."""
2932
3033 text : str
34+ """The text of the comment."""
3135 last_line_number : int
36+ """The last line number of the comment in the source code."""
3237
3338
3439@dataclass
3540class Macro :
3641 """A macro extracted from the source code."""
3742
3843 text : str
44+ """The text of the macro."""
3945 line_number : int
46+ """The line number of the macro in the source code."""
4047
4148
4249_C_PARSER = CParser ()
@@ -167,26 +174,35 @@ class InOut(str, Enum):
167174 """Enumeration for parameter direction."""
168175
169176 UNSPECIFIED = "unspecified"
177+ """The direction is unspecified."""
170178 IN = "in"
179+ """The parameter is an input."""
171180 OUT = "out"
181+ """The parameter is an output."""
172182
173183
174184@dataclass
175185class Param :
176186 """A parameter in a function signature."""
177187
178188 name : str
189+ """The name of the parameter."""
179190 desc : str
191+ """The description of the parameter."""
180192 in_out : InOut
193+ """The direction of the parameter (input, output, or unspecified)."""
181194
182195
183196@dataclass
184197class Docstring :
185198 """A parsed docstring."""
186199
187200 desc : str
201+ """The description of the docstring."""
188202 params : list [Param ] | None = None
203+ """The parameters of the docstring."""
189204 ret : str | None = None
205+ """The return value of the docstring."""
190206
191207
192208def parse_docstring (content : str ) -> Docstring :
@@ -270,82 +286,113 @@ class DocMacro:
270286 """A parsed macro."""
271287
272288 name : str
289+ """The name of the macro."""
273290 content : str | None
291+ """The content of the macro."""
274292 doc : Docstring | None
293+ """The docstring of the macro."""
275294
276295
277296@dataclass
278297class DocType :
279298 """A parsed typedef."""
280299
281300 name : str
301+ """The name of the typedef."""
282302 tp : TypeRef
303+ """The type reference of the typedef."""
283304 doc : Docstring | None
305+ """The docstring of the typedef."""
284306 quals : list [str ]
307+ """The qualifiers of the typedef."""
285308
286309
287310@dataclass
288311class DocGlobalVar :
289312 """A parsed global variable."""
290313
291314 name : str
315+ """The name of the global variable."""
292316 tp : TypeRef
317+ """The type reference of the global variable."""
293318 doc : Docstring | None
319+ """The docstring of the global variable."""
294320 quals : list [str ]
321+ """The qualifiers of the global variable."""
295322
296323
297324@dataclass
298325class FuncParam :
299326 """A parameter in a function signature."""
300327
301328 name : str
329+ """The name of the parameter."""
302330 tp : TypeRef
331+ """The type reference of the parameter."""
303332
304333
305334@dataclass
306335class DocFunc :
307336 """A parsed function."""
308337
309338 name : str
339+ """The name of the function."""
310340 args : list [FuncParam ]
341+ """The arguments of the function."""
311342 ret : TypeRef
343+ """The return type of the function."""
312344 doc : Docstring | None
345+ """The docstring of the function."""
313346
314347
315348@dataclass
316349class CodeDoc :
317350 """A parsed C source file."""
318351
319352 macros : list [DocMacro ]
353+ """List of macros in the source file."""
320354 functions : list [DocFunc ]
355+ """"List of functions in the source file."""
321356 global_vars : list [DocGlobalVar ]
357+ """List of global variables in the source file."""
322358 typedefs : dict [str , DocType ]
359+ """List of typedefs in the source file."""
323360
324361
325362class TypeDecl (str , Enum ):
326363 """Enumeration for type declarations."""
327364
328365 NORMAL = "normal"
366+ """A normal type declaration."""
329367 POINTER = "pointer"
368+ """A pointer type declaration."""
330369 ARRAY = "array"
370+ """An array type declaration."""
331371 FUNCTION = "function"
372+ """A function type declaration."""
332373
333374
334375@dataclass
335376class TypeRef :
336377 """A reference to a type in C."""
337378
338379 name : TypeRef | str
380+ """The name of the type reference."""
339381 decl : TypeDecl
382+ """The type declaration of the type reference."""
340383 quals : list [str ]
384+ """The qualifiers of the type reference."""
341385 params : list [TypeRef ] | None = None # only in functions
386+ """The parameters of the type reference."""
342387
343388
344389class SupportsQualsAndType (Protocol ):
345390 """A protocol for types that can have qualifiers and a type."""
346391
347392 quals : list [str ]
393+ """The qualifiers of the type."""
348394 type : SupportsQualsAndType | c_ast .TypeDecl | c_ast .IdentifierType
395+ """The type of the node."""
349396
350397
351398def ast_to_decl (node : SupportsQualsAndType , types : dict [str , DocType ]) -> TypeRef :
@@ -477,25 +524,6 @@ class CHandler(BaseHandler):
477524 fallback_theme : ClassVar [str ] = "material"
478525 """The theme to fallback to."""
479526
480- fallback_config : ClassVar [dict ] = {"fallback" : True }
481- """The configuration used to collect item during autorefs fallback."""
482-
483- default_config : ClassVar [dict ] = {
484- "show_root_heading" : False ,
485- "show_root_toc_entry" : True ,
486- "show_symbol_type_heading" : True ,
487- "show_symbol_type_toc_entry" : True ,
488- "heading_level" : 2 ,
489- }
490- """The default configuration options.
491-
492- Option | Type | Description | Default
493- ------ | ---- | ----------- | -------
494- **`show_root_heading`** | `bool` | Show the heading of the object at the root of the documentation tree. | `False`
495- **`show_root_toc_entry`** | `bool` | If the root heading is not shown, at least add a ToC entry for it. | `True`
496- **`heading_level`** | `int` | The initial heading level to use. | `2`
497- """
498-
499527 def __init__ (self , config : Mapping [str , Any ], base_dir : Path , ** kwargs : Any ) -> None :
500528 """Initialize the handler.
501529
@@ -507,14 +535,22 @@ def __init__(self, config: Mapping[str, Any], base_dir: Path, **kwargs: Any) ->
507535 super ().__init__ (** kwargs )
508536
509537 self .config = config
538+ """The handler configuration."""
510539 self .base_dir = base_dir
540+ """The base directory of the project."""
511541 self .global_options = config .get ("options" , {})
542+ """The global options for the handler."""
512543
513- def get_options (self , local_options : Mapping [str , Any ]) -> Mapping [ str , Any ] :
544+ def get_options (self , local_options : Mapping [str , Any ]) -> COptions :
514545 """Combine configuration options."""
515- return {** self .default_config , ** self .global_options , ** local_options }
516-
517- def collect (self , identifier : str , options : MutableMapping [str , Any ]) -> CollectorItem :
546+ extra = {** self .global_options .get ("extra" , {}), ** local_options .get ("extra" , {})}
547+ options = {** self .global_options , ** local_options , "extra" : extra }
548+ try :
549+ return COptions .from_data (** options )
550+ except Exception as error :
551+ raise PluginError (f"Invalid options: { error } " ) from error
552+
553+ def collect (self , identifier : str , options : COptions ) -> CollectorItem :
518554 """Collect data given an identifier and selection configuration.
519555
520556 In the implementation, you typically call a subprocess that returns JSON, and load that JSON again into
@@ -530,7 +566,7 @@ def collect(self, identifier: str, options: MutableMapping[str, Any]) -> Collect
530566 Returns:
531567 Anything you want, as long as you can feed it to the `render` method.
532568 """
533- if options . get ( "fallback" , False ) :
569+ if options == {} :
534570 raise CollectionError ("Not loading additional headers during fallback" )
535571
536572 source = Path (identifier ).read_text (encoding = "utf-8" )
@@ -607,7 +643,7 @@ def collect(self, identifier: str, options: MutableMapping[str, Any]) -> Collect
607643
608644 return CodeDoc (macros , funcs , global_vars , types )
609645
610- def render (self , data : CodeDoc , options : MutableMapping [ str , Any ] ) -> str :
646+ def render (self , data : CodeDoc , options : COptions ) -> str :
611647 """Render a template using provided data and configuration options.
612648
613649 Parameters:
@@ -618,7 +654,7 @@ def render(self, data: CodeDoc, options: MutableMapping[str, Any]) -> str:
618654 Returns:
619655 The rendered template as HTML.
620656 """
621- heading_level = options [ " heading_level" ]
657+ heading_level = options . heading_level
622658 template = self .env .get_template ("header.html.jinja" )
623659 return template .render (
624660 config = options ,
0 commit comments