cxxheaderparser 1.2.2__tar.gz → 1.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/PKG-INFO +1 -1
  2. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/parser.py +55 -28
  3. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/simple.py +9 -0
  4. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/types.py +31 -3
  5. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/version.py +1 -1
  6. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/visitor.py +13 -0
  7. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser.egg-info/PKG-INFO +1 -1
  8. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_concepts.py +96 -29
  9. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_doxygen.py +51 -0
  10. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_template.py +84 -0
  11. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/LICENSE.txt +0 -0
  12. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/README.md +0 -0
  13. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/__init__.py +0 -0
  14. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/__main__.py +0 -0
  15. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/_ply/__init__.py +0 -0
  16. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/_ply/lex.py +0 -0
  17. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/dump.py +0 -0
  18. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/errors.py +0 -0
  19. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/gentest.py +0 -0
  20. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/lexer.py +0 -0
  21. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/options.py +0 -0
  22. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/parserstate.py +0 -0
  23. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/preprocessor.py +0 -0
  24. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/py.typed +0 -0
  25. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser/tokfmt.py +0 -0
  26. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser.egg-info/SOURCES.txt +0 -0
  27. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser.egg-info/dependency_links.txt +0 -0
  28. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser.egg-info/requires.txt +0 -0
  29. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/cxxheaderparser.egg-info/top_level.txt +0 -0
  30. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/setup.cfg +0 -0
  31. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/setup.py +0 -0
  32. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_abv_template.py +0 -0
  33. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_attributes.py +0 -0
  34. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_class.py +0 -0
  35. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_class_base.py +0 -0
  36. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_enum.py +0 -0
  37. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_fn.py +0 -0
  38. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_friends.py +0 -0
  39. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_misc.py +0 -0
  40. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_namespaces.py +0 -0
  41. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_operators.py +0 -0
  42. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_preprocessor.py +0 -0
  43. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_skip.py +0 -0
  44. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_tokfmt.py +0 -0
  45. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_typedef.py +0 -0
  46. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_typefmt.py +0 -0
  47. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_union.py +0 -0
  48. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_using.py +0 -0
  49. {cxxheaderparser-1.2.2 → cxxheaderparser-1.3.0}/tests/test_var.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cxxheaderparser
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: Parse C++ header files and generate a data structure representing the class
5
5
  Home-page: https://github.com/robotpy/cxxheaderparser
6
6
  Author: Dustin Spicuzza
@@ -25,6 +25,7 @@ from .types import (
25
25
  Concept,
26
26
  DecltypeSpecifier,
27
27
  DecoratedType,
28
+ DeductionGuide,
28
29
  EnumDecl,
29
30
  Enumerator,
30
31
  Field,
@@ -992,7 +993,9 @@ class CxxParser:
992
993
 
993
994
  self.visitor.on_using_namespace(state, names)
994
995
 
995
- def _parse_using_declaration(self, tok: LexToken) -> None:
996
+ def _parse_using_declaration(
997
+ self, tok: LexToken, doxygen: typing.Optional[str]
998
+ ) -> None:
996
999
  """
997
1000
  using_declaration: "using" ["typename"] ["::"] nested_name_specifier unqualified_id ";"
998
1001
  | "using" "::" unqualified_id ";"
@@ -1004,12 +1007,15 @@ class CxxParser:
1004
1007
  typename, _ = self._parse_pqname(
1005
1008
  tok, fn_ok=True, compound_ok=True, fund_ok=True
1006
1009
  )
1007
- decl = UsingDecl(typename, self._current_access)
1010
+ decl = UsingDecl(typename, self._current_access, doxygen)
1008
1011
 
1009
1012
  self.visitor.on_using_declaration(self.state, decl)
1010
1013
 
1011
1014
  def _parse_using_typealias(
1012
- self, id_tok: LexToken, template: typing.Optional[TemplateDecl]
1015
+ self,
1016
+ id_tok: LexToken,
1017
+ template: typing.Optional[TemplateDecl],
1018
+ doxygen: typing.Optional[str],
1013
1019
  ) -> None:
1014
1020
  """
1015
1021
  alias_declaration: "using" IDENTIFIER "=" type_id ";"
@@ -1023,7 +1029,7 @@ class CxxParser:
1023
1029
 
1024
1030
  dtype = self._parse_cv_ptr(parsed_type)
1025
1031
 
1026
- alias = UsingAlias(id_tok.value, dtype, template, self._current_access)
1032
+ alias = UsingAlias(id_tok.value, dtype, template, self._current_access, doxygen)
1027
1033
 
1028
1034
  self.visitor.on_using_alias(self.state, alias)
1029
1035
 
@@ -1052,9 +1058,9 @@ class CxxParser:
1052
1058
  raise CxxParseError(
1053
1059
  "unexpected using-declaration when parsing alias-declaration", tok
1054
1060
  )
1055
- self._parse_using_declaration(tok)
1061
+ self._parse_using_declaration(tok, doxygen)
1056
1062
  else:
1057
- self._parse_using_typealias(tok, template)
1063
+ self._parse_using_typealias(tok, template, doxygen)
1058
1064
 
1059
1065
  # All using things end with a semicolon
1060
1066
  self._next_token_must_be(";")
@@ -1863,10 +1869,9 @@ class CxxParser:
1863
1869
  _auto_return_typename = PQName([AutoSpecifier()])
1864
1870
 
1865
1871
  def _parse_trailing_return_type(
1866
- self, fn: typing.Union[Function, FunctionType]
1867
- ) -> None:
1872
+ self, return_type: typing.Optional[DecoratedType]
1873
+ ) -> DecoratedType:
1868
1874
  # entry is "->"
1869
- return_type = fn.return_type
1870
1875
  if not (
1871
1876
  isinstance(return_type, Type)
1872
1877
  and not return_type.const
@@ -1885,8 +1890,7 @@ class CxxParser:
1885
1890
 
1886
1891
  dtype = self._parse_cv_ptr(parsed_type)
1887
1892
 
1888
- fn.has_trailing_return = True
1889
- fn.return_type = dtype
1893
+ return dtype
1890
1894
 
1891
1895
  def _parse_fn_end(self, fn: Function) -> None:
1892
1896
  """
@@ -1907,15 +1911,15 @@ class CxxParser:
1907
1911
  else:
1908
1912
  rtok = self.lex.token_if("requires")
1909
1913
  if rtok:
1910
- fn_template = fn.template
1911
- if fn_template is None:
1914
+ # requires on a function must always be accompanied by a template
1915
+ if fn.template is None:
1912
1916
  raise self._parse_error(rtok)
1913
- elif isinstance(fn_template, list):
1914
- fn_template = fn_template[0]
1915
- fn_template.raw_requires_post = self._parse_requires(rtok)
1917
+ fn.raw_requires = self._parse_requires(rtok)
1916
1918
 
1917
1919
  if self.lex.token_if("ARROW"):
1918
- self._parse_trailing_return_type(fn)
1920
+ return_type = self._parse_trailing_return_type(fn.return_type)
1921
+ fn.has_trailing_return = True
1922
+ fn.return_type = return_type
1919
1923
 
1920
1924
  if self.lex.token_if("{"):
1921
1925
  self._discard_contents("{", "}")
@@ -1963,7 +1967,9 @@ class CxxParser:
1963
1967
  elif tok_value in ("&", "&&"):
1964
1968
  method.ref_qualifier = tok_value
1965
1969
  elif tok_value == "->":
1966
- self._parse_trailing_return_type(method)
1970
+ return_type = self._parse_trailing_return_type(method.return_type)
1971
+ method.has_trailing_return = True
1972
+ method.return_type = return_type
1967
1973
  if self.lex.token_if("{"):
1968
1974
  self._discard_contents("{", "}")
1969
1975
  method.has_body = True
@@ -1978,12 +1984,7 @@ class CxxParser:
1978
1984
  toks = self._consume_balanced_tokens(otok)[1:-1]
1979
1985
  method.noexcept = self._create_value(toks)
1980
1986
  elif tok_value == "requires":
1981
- method_template = method.template
1982
- if method_template is None:
1983
- raise self._parse_error(tok)
1984
- elif isinstance(method_template, list):
1985
- method_template = method_template[0]
1986
- method_template.raw_requires_post = self._parse_requires(tok)
1987
+ method.raw_requires = self._parse_requires(tok)
1987
1988
  else:
1988
1989
  self.lex.return_token(tok)
1989
1990
  break
@@ -2002,6 +2003,7 @@ class CxxParser:
2002
2003
  is_friend: bool,
2003
2004
  is_typedef: bool,
2004
2005
  msvc_convention: typing.Optional[LexToken],
2006
+ is_guide: bool = False,
2005
2007
  ) -> bool:
2006
2008
  """
2007
2009
  Assumes the caller has already consumed the return type and name, this consumes the
@@ -2078,7 +2080,21 @@ class CxxParser:
2078
2080
  self.visitor.on_method_impl(state, method)
2079
2081
 
2080
2082
  return method.has_body or method.has_trailing_return
2081
-
2083
+ elif is_guide:
2084
+ assert isinstance(state, (ExternBlockState, NamespaceBlockState))
2085
+ if not self.lex.token_if("ARROW"):
2086
+ raise self._parse_error(None, expected="Trailing return type")
2087
+ return_type = self._parse_trailing_return_type(
2088
+ Type(PQName([AutoSpecifier()]))
2089
+ )
2090
+ guide = DeductionGuide(
2091
+ return_type,
2092
+ name=pqname,
2093
+ parameters=params,
2094
+ doxygen=doxygen,
2095
+ )
2096
+ self.visitor.on_deduction_guide(state, guide)
2097
+ return False
2082
2098
  else:
2083
2099
  assert return_type is not None
2084
2100
  fn = Function(
@@ -2212,7 +2228,9 @@ class CxxParser:
2212
2228
  assert not isinstance(dtype, FunctionType)
2213
2229
  dtype = dtype_fn = FunctionType(dtype, fn_params, vararg)
2214
2230
  if self.lex.token_if("ARROW"):
2215
- self._parse_trailing_return_type(dtype_fn)
2231
+ return_type = self._parse_trailing_return_type(dtype_fn.return_type)
2232
+ dtype_fn.has_trailing_return = True
2233
+ dtype_fn.return_type = return_type
2216
2234
 
2217
2235
  else:
2218
2236
  msvc_convention = None
@@ -2393,6 +2411,7 @@ class CxxParser:
2393
2411
  destructor = False
2394
2412
  op = None
2395
2413
  msvc_convention = None
2414
+ is_guide = False
2396
2415
 
2397
2416
  # If we have a leading (, that's either an obnoxious grouping
2398
2417
  # paren or it's a constructor
@@ -2443,8 +2462,15 @@ class CxxParser:
2443
2462
  # grouping paren like "void (name(int x));"
2444
2463
  toks = self._consume_balanced_tokens(tok)
2445
2464
 
2446
- # .. not sure what it's grouping, so put it back?
2447
- self.lex.return_tokens(toks[1:-1])
2465
+ # check to see if the next token is an arrow, and thus a trailing return
2466
+ if self.lex.token_peek_if("ARROW"):
2467
+ self.lex.return_tokens(toks)
2468
+ # the leading name of the class/ctor has been parsed as a type before the parens
2469
+ pqname = parsed_type.typename
2470
+ is_guide = True
2471
+ else:
2472
+ # .. not sure what it's grouping, so put it back?
2473
+ self.lex.return_tokens(toks[1:-1])
2448
2474
 
2449
2475
  if dtype:
2450
2476
  msvc_convention = self.lex.token_if_val(*self._msvc_conventions)
@@ -2475,6 +2501,7 @@ class CxxParser:
2475
2501
  is_friend,
2476
2502
  is_typedef,
2477
2503
  msvc_convention,
2504
+ is_guide,
2478
2505
  )
2479
2506
  elif msvc_convention:
2480
2507
  raise self._parse_error(msvc_convention)
@@ -35,6 +35,7 @@ from dataclasses import dataclass, field
35
35
  from .types import (
36
36
  ClassDecl,
37
37
  Concept,
38
+ DeductionGuide,
38
39
  EnumDecl,
39
40
  Field,
40
41
  ForwardDecl,
@@ -123,6 +124,9 @@ class NamespaceScope:
123
124
  #: Child namespaces
124
125
  namespaces: typing.Dict[str, "NamespaceScope"] = field(default_factory=dict)
125
126
 
127
+ #: Deduction guides
128
+ deduction_guides: typing.List[DeductionGuide] = field(default_factory=list)
129
+
126
130
 
127
131
  Block = typing.Union[ClassScope, NamespaceScope]
128
132
 
@@ -317,6 +321,11 @@ class SimpleCxxVisitor:
317
321
  def on_class_end(self, state: SClassBlockState) -> None:
318
322
  pass
319
323
 
324
+ def on_deduction_guide(
325
+ self, state: SNonClassBlockState, guide: DeductionGuide
326
+ ) -> None:
327
+ state.user_data.deduction_guides.append(guide)
328
+
320
329
 
321
330
  def parse_string(
322
331
  content: str,
@@ -526,9 +526,6 @@ class TemplateDecl:
526
526
  #: template <typename T> requires ...
527
527
  raw_requires_pre: typing.Optional[Value] = None
528
528
 
529
- #: template <typename T> int main() requires ...
530
- raw_requires_post: typing.Optional[Value] = None
531
-
532
529
 
533
530
  #: If no template, this is None. This is a TemplateDecl if this there is a single
534
531
  #: declaration:
@@ -730,6 +727,13 @@ class Function:
730
727
  #: is the string "conversion" and the full Type is found in return_type
731
728
  operator: typing.Optional[str] = None
732
729
 
730
+ #: A requires constraint following the function declaration. If you need the
731
+ #: prior, look at TemplateDecl.raw_requires_pre. At the moment this is just
732
+ #: a raw value, if we interpret it in the future this will change.
733
+ #:
734
+ #: template <typename T> int main() requires ...
735
+ raw_requires: typing.Optional[Value] = None
736
+
733
737
 
734
738
  @dataclass
735
739
  class Method(Function):
@@ -866,6 +870,9 @@ class UsingDecl:
866
870
  #: If within a class, the access level for this decl
867
871
  access: typing.Optional[str] = None
868
872
 
873
+ #: Documentation if present
874
+ doxygen: typing.Optional[str] = None
875
+
869
876
 
870
877
  @dataclass
871
878
  class UsingAlias:
@@ -886,3 +893,24 @@ class UsingAlias:
886
893
 
887
894
  #: If within a class, the access level for this decl
888
895
  access: typing.Optional[str] = None
896
+
897
+ #: Documentation if present
898
+ doxygen: typing.Optional[str] = None
899
+
900
+
901
+ @dataclass
902
+ class DeductionGuide:
903
+ """
904
+ .. code-block:: c++
905
+
906
+ template <class T>
907
+ MyClass(T) -> MyClass(int);
908
+ """
909
+
910
+ #: Only constructors and destructors don't have a return type
911
+ result_type: typing.Optional[DecoratedType]
912
+
913
+ name: PQName
914
+ parameters: typing.List[Parameter]
915
+
916
+ doxygen: typing.Optional[str] = None
@@ -1,2 +1,2 @@
1
1
  # Autogenerated by setup.py
2
- __version__ = '1.2.2'
2
+ __version__ = '1.3.0'
@@ -9,6 +9,7 @@ else:
9
9
 
10
10
  from .types import (
11
11
  Concept,
12
+ DeductionGuide,
12
13
  EnumDecl,
13
14
  Field,
14
15
  ForwardDecl,
@@ -236,6 +237,13 @@ class CxxVisitor(Protocol):
236
237
  ``on_variable`` for each instance declared.
237
238
  """
238
239
 
240
+ def on_deduction_guide(
241
+ self, state: NonClassBlockState, guide: DeductionGuide
242
+ ) -> None:
243
+ """
244
+ Called when a deduction guide is encountered
245
+ """
246
+
239
247
 
240
248
  class NullVisitor:
241
249
  """
@@ -318,5 +326,10 @@ class NullVisitor:
318
326
  def on_class_end(self, state: ClassBlockState) -> None:
319
327
  return None
320
328
 
329
+ def on_deduction_guide(
330
+ self, state: NonClassBlockState, guide: DeductionGuide
331
+ ) -> None:
332
+ return None
333
+
321
334
 
322
335
  null_visitor = NullVisitor()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cxxheaderparser
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: Parse C++ header files and generate a data structure representing the class
5
5
  Home-page: https://github.com/robotpy/cxxheaderparser
6
6
  Author: Dustin Spicuzza
@@ -6,6 +6,7 @@ from cxxheaderparser.types import (
6
6
  Concept,
7
7
  Function,
8
8
  FundamentalSpecifier,
9
+ Method,
9
10
  MoveReference,
10
11
  NameSpecifier,
11
12
  PQName,
@@ -495,15 +496,15 @@ def test_requires_last_elem() -> None:
495
496
  )
496
497
  ],
497
498
  template=TemplateDecl(
498
- params=[TemplateTypeParam(typekey="typename", name="T")],
499
- raw_requires_post=Value(
500
- tokens=[
501
- Token(value="Eq"),
502
- Token(value="<"),
503
- Token(value="T"),
504
- Token(value=">"),
505
- ]
506
- ),
499
+ params=[TemplateTypeParam(typekey="typename", name="T")]
500
+ ),
501
+ raw_requires=Value(
502
+ tokens=[
503
+ Token(value="Eq"),
504
+ Token(value="<"),
505
+ Token(value="T"),
506
+ Token(value=">"),
507
+ ]
507
508
  ),
508
509
  )
509
510
  ]
@@ -752,14 +753,14 @@ def test_requires_both() -> None:
752
753
  Token(value=">"),
753
754
  ]
754
755
  ),
755
- raw_requires_post=Value(
756
- tokens=[
757
- Token(value="Subtractable"),
758
- Token(value="<"),
759
- Token(value="T"),
760
- Token(value=">"),
761
- ]
762
- ),
756
+ ),
757
+ raw_requires=Value(
758
+ tokens=[
759
+ Token(value="Subtractable"),
760
+ Token(value="<"),
761
+ Token(value="T"),
762
+ Token(value=">"),
763
+ ]
763
764
  ),
764
765
  )
765
766
  ]
@@ -791,20 +792,86 @@ def test_requires_paren() -> None:
791
792
  )
792
793
  ],
793
794
  template=TemplateDecl(
794
- params=[TemplateTypeParam(typekey="class", name="T")],
795
- raw_requires_post=Value(
796
- tokens=[
797
- Token(value="("),
798
- Token(value="is_purrable"),
799
- Token(value="<"),
800
- Token(value="T"),
801
- Token(value=">"),
802
- Token(value="("),
803
- Token(value=")"),
804
- Token(value=")"),
805
- ]
795
+ params=[TemplateTypeParam(typekey="class", name="T")]
796
+ ),
797
+ raw_requires=Value(
798
+ tokens=[
799
+ Token(value="("),
800
+ Token(value="is_purrable"),
801
+ Token(value="<"),
802
+ Token(value="T"),
803
+ Token(value=">"),
804
+ Token(value="("),
805
+ Token(value=")"),
806
+ Token(value=")"),
807
+ ]
808
+ ),
809
+ )
810
+ ]
811
+ )
812
+ )
813
+
814
+
815
+ def test_non_template_requires() -> None:
816
+ content = """
817
+ // clang-format off
818
+
819
+ template <class T>
820
+ struct Payload
821
+ {
822
+ constexpr Payload(T v)
823
+ requires(std::is_pod_v<T>)
824
+ : Value(v)
825
+ {
826
+ }
827
+ };
828
+ """
829
+ data = parse_string(content, cleandoc=True)
830
+
831
+ assert data == ParsedData(
832
+ namespace=NamespaceScope(
833
+ classes=[
834
+ ClassScope(
835
+ class_decl=ClassDecl(
836
+ typename=PQName(
837
+ segments=[NameSpecifier(name="Payload")], classkey="struct"
838
+ ),
839
+ template=TemplateDecl(
840
+ params=[TemplateTypeParam(typekey="class", name="T")]
806
841
  ),
807
842
  ),
843
+ methods=[
844
+ Method(
845
+ return_type=None,
846
+ name=PQName(segments=[NameSpecifier(name="Payload")]),
847
+ parameters=[
848
+ Parameter(
849
+ type=Type(
850
+ typename=PQName(
851
+ segments=[NameSpecifier(name="T")]
852
+ )
853
+ ),
854
+ name="v",
855
+ )
856
+ ],
857
+ constexpr=True,
858
+ has_body=True,
859
+ raw_requires=Value(
860
+ tokens=[
861
+ Token(value="("),
862
+ Token(value="std"),
863
+ Token(value="::"),
864
+ Token(value="is_pod_v"),
865
+ Token(value="<"),
866
+ Token(value="T"),
867
+ Token(value=">"),
868
+ Token(value=")"),
869
+ ]
870
+ ),
871
+ access="public",
872
+ constructor=True,
873
+ )
874
+ ],
808
875
  )
809
876
  ]
810
877
  )
@@ -26,6 +26,7 @@ from cxxheaderparser.types import (
26
26
  Type,
27
27
  Typedef,
28
28
  UsingDecl,
29
+ UsingAlias,
29
30
  Value,
30
31
  Variable,
31
32
  )
@@ -436,3 +437,53 @@ def test_doxygen_attribute() -> None:
436
437
  ]
437
438
  )
438
439
  )
440
+
441
+
442
+ def test_doxygen_using_decl() -> None:
443
+ content = """
444
+ // clang-format off
445
+
446
+ /// Comment
447
+ using ns::ClassName;
448
+ """
449
+ data = parse_string(content, cleandoc=True)
450
+
451
+ assert data == ParsedData(
452
+ namespace=NamespaceScope(
453
+ using=[
454
+ UsingDecl(
455
+ typename=PQName(
456
+ segments=[
457
+ NameSpecifier(name="ns"),
458
+ NameSpecifier(name="ClassName"),
459
+ ]
460
+ ),
461
+ doxygen="/// Comment",
462
+ )
463
+ ]
464
+ )
465
+ )
466
+
467
+
468
+ def test_doxygen_using_alias() -> None:
469
+ content = """
470
+ // clang-format off
471
+
472
+ /// Comment
473
+ using alias = sometype;
474
+ """
475
+ data = parse_string(content, cleandoc=True)
476
+
477
+ assert data == ParsedData(
478
+ namespace=NamespaceScope(
479
+ using_alias=[
480
+ UsingAlias(
481
+ alias="alias",
482
+ type=Type(
483
+ typename=PQName(segments=[NameSpecifier(name="sometype")])
484
+ ),
485
+ doxygen="/// Comment",
486
+ )
487
+ ]
488
+ )
489
+ )
@@ -5,6 +5,7 @@ from cxxheaderparser.types import (
5
5
  BaseClass,
6
6
  ClassDecl,
7
7
  DecltypeSpecifier,
8
+ DeductionGuide,
8
9
  Field,
9
10
  ForwardDecl,
10
11
  Function,
@@ -2163,3 +2164,86 @@ def test_member_class_template_specialization() -> None:
2163
2164
  ]
2164
2165
  )
2165
2166
  )
2167
+
2168
+
2169
+ def test_template_deduction_guide() -> None:
2170
+ content = """
2171
+ template <class CharT, class Traits = std::char_traits<CharT>>
2172
+ Error(std::basic_string_view<CharT, Traits>) -> Error<std::string>;
2173
+ """
2174
+ data = parse_string(content, cleandoc=True)
2175
+
2176
+ assert data == ParsedData(
2177
+ namespace=NamespaceScope(
2178
+ deduction_guides=[
2179
+ DeductionGuide(
2180
+ result_type=Type(
2181
+ typename=PQName(
2182
+ segments=[
2183
+ NameSpecifier(
2184
+ name="Error",
2185
+ specialization=TemplateSpecialization(
2186
+ args=[
2187
+ TemplateArgument(
2188
+ arg=Type(
2189
+ typename=PQName(
2190
+ segments=[
2191
+ NameSpecifier(name="std"),
2192
+ NameSpecifier(
2193
+ name="string"
2194
+ ),
2195
+ ]
2196
+ )
2197
+ )
2198
+ )
2199
+ ]
2200
+ ),
2201
+ )
2202
+ ]
2203
+ )
2204
+ ),
2205
+ name=PQName(segments=[NameSpecifier(name="Error")]),
2206
+ parameters=[
2207
+ Parameter(
2208
+ type=Type(
2209
+ typename=PQName(
2210
+ segments=[
2211
+ NameSpecifier(name="std"),
2212
+ NameSpecifier(
2213
+ name="basic_string_view",
2214
+ specialization=TemplateSpecialization(
2215
+ args=[
2216
+ TemplateArgument(
2217
+ arg=Type(
2218
+ typename=PQName(
2219
+ segments=[
2220
+ NameSpecifier(
2221
+ name="CharT"
2222
+ )
2223
+ ]
2224
+ )
2225
+ )
2226
+ ),
2227
+ TemplateArgument(
2228
+ arg=Type(
2229
+ typename=PQName(
2230
+ segments=[
2231
+ NameSpecifier(
2232
+ name="Traits"
2233
+ )
2234
+ ]
2235
+ )
2236
+ )
2237
+ ),
2238
+ ]
2239
+ ),
2240
+ ),
2241
+ ]
2242
+ )
2243
+ )
2244
+ )
2245
+ ],
2246
+ )
2247
+ ]
2248
+ )
2249
+ )