Skip to content

Commit 1d29672

Browse files
committed
Support PHP enumerations
1 parent e364c24 commit 1d29672

File tree

4 files changed

+227
-7
lines changed

4 files changed

+227
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
dist/
22
build/
3+
doc/_build
34
test/_build
45
*.pyc
56
*.egg-info

doc/reference.rst

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,62 @@ Each directive populates the index, and or the namespace index.
5050
Describe a trait. Methods beloning to the trait should follow or be nested
5151
inside this directive.
5252

53+
.. rst:directive:: .. php:enum:: name [ : type ]
54+
55+
Describes an enum. Cases, methods, and constants belonging to the enum
56+
should be inside this directive's body::
57+
58+
.. php:enum:: Suit
59+
60+
In playing cards, a suit is one of the categories into which the
61+
cards of a deck are divided.
62+
63+
.. php:case:: Hearts
64+
65+
Hearts is one of the four suits in playing cards.
66+
67+
.. php:case:: Diamonds
68+
69+
Diamonds is one of the four suits in playing cards.
70+
71+
.. php:case:: Clubs
72+
73+
Clubs is one of the four suits in playing cards.
74+
75+
.. php:case:: Spades
76+
77+
Spades is one of the four suits in playing cards.
78+
79+
.. php:method:: color() -> string
80+
81+
Returns "Red" for hearts and diamonds and "black" for clubs
82+
and spades.
83+
84+
.. php:const:: Roses : Hearts
85+
86+
An alias for :php:case:`Suit::Hearts`.
87+
88+
You may describe a backed enum by specifying the optional enum type and
89+
case values::
90+
91+
.. php:enum:: Suit : string
92+
93+
In playing cards, a suit is one of the categories into which the
94+
cards of a deck are divided.
95+
96+
.. php:case:: Hearts : 'H'
97+
98+
.. php:case:: Diamonds : 'D'
99+
100+
.. php:case:: Clubs : 'C'
101+
102+
.. php:case:: Spades : 'S'
103+
104+
.. rst:directive:: .. php:case:: name [ : value ]
105+
106+
Describes an enum case. If describing a backed enum case, you may also
107+
provide the case value. See :rst:dir:`php:enum` for examples.
108+
53109
.. rst:directive:: .. php:class:: name
54110
55111
Describes a class. Methods, attributes, and constants belonging to the class
@@ -166,3 +222,14 @@ matching directive is found:
166222
167223
Reference a trait. A namespaced name may be used.
168224

225+
.. rst:role:: php:enum
226+
227+
Reference an enum. A namespaced name may be used::
228+
229+
:php:enum:`Example\\Suit`
230+
231+
.. rst:role:: php:case
232+
233+
Reference an enum case. A namespace name may be used::
234+
235+
:php:case:`Example\\Suit::Hearts`

sphinxcontrib/phpdomain.py

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
([\w.]*\:\:)? # class name(s)
2929
(\$?\w+) \s* # thing name
3030
(?: \((.*)\) # optional: arguments
31-
(?:\s* -> \s* (.*))? # return annotation
32-
)? $ # and nothing more
31+
(?:\s* -> \s* (.*))?)? # return annotation
32+
(?:\s* : \s* (.*))? # backed enum type / case value
33+
$ # and nothing more
3334
''', re.VERBOSE)
3435

3536

@@ -46,7 +47,9 @@
4647
'exception': '',
4748
'staticmethod': '::',
4849
'interface': NS,
49-
'trait': NS
50+
'trait': NS,
51+
'enum': NS,
52+
'case': '::',
5053
}
5154

5255
php_separator = re.compile(r"(\w+)?(?:[:]{2})?")
@@ -157,7 +160,7 @@ def handle_signature(self, sig, signode):
157160
if m is None:
158161
raise ValueError
159162

160-
visibility, modifiers, name_prefix, name, arglist, retann = m.groups()
163+
visibility, modifiers, name_prefix, name, arglist, retann, enumtype = m.groups()
161164

162165
if not name_prefix:
163166
name_prefix = ""
@@ -191,7 +194,7 @@ def handle_signature(self, sig, signode):
191194
fullname = name_prefix + name
192195

193196
# Currently in a class, but not creating another class,
194-
elif classname and not self.objtype in ['class', 'exception', 'interface', 'trait']:
197+
elif classname and not self.objtype in ['class', 'exception', 'interface', 'trait', 'enum']:
195198
if not self.env.temp_data['php:in_class']:
196199
name_prefix = classname + separator
197200

@@ -239,12 +242,16 @@ def handle_signature(self, sig, signode):
239242
signode += addnodes.desc_parameterlist()
240243
if retann:
241244
signode += addnodes.desc_returns(retann, retann)
245+
elif enumtype:
246+
signode += addnodes.desc_returns(enumtype, enumtype)
242247
return fullname, name_prefix
243248

244249
_pseudo_parse_arglist(signode, arglist)
245250

246251
if retann:
247252
signode += addnodes.desc_returns(retann, retann)
253+
elif enumtype:
254+
signode += addnodes.desc_returns(enumtype, enumtype)
248255
return fullname, name_prefix
249256

250257
def get_index_text(self, modname, name):
@@ -341,7 +348,7 @@ def get_index_text(self, modname, name_cls):
341348
class PhpClasslike(PhpObject):
342349
"""
343350
Description of a class-like object
344-
(classes, exceptions, interfaces, traits).
351+
(classes, exceptions, interfaces, traits, enums).
345352
"""
346353

347354
def get_signature_prefix(self, sig):
@@ -360,6 +367,10 @@ def get_index_text(self, modname, name_cls):
360367
if not modname:
361368
return _('%s (trait)') % name_cls[0]
362369
return _('%s (trait in %s)') % (name_cls[0], modname)
370+
elif self.objtype == 'enum':
371+
if not modname:
372+
return _('%s (enum)') % name_cls[0]
373+
return _('%s (enum in %s)') % (name_cls[0], modname)
363374
elif self.objtype == 'exception':
364375
return name_cls[0]
365376
else:
@@ -384,6 +395,8 @@ def get_signature_prefix(self, sig):
384395
return _('property ')
385396
if self.objtype == 'staticmethod':
386397
return _('static ')
398+
if self.objtype == 'case':
399+
return _('case ')
387400
return ''
388401

389402
def needs_arglist(self):
@@ -393,7 +406,7 @@ def get_index_text(self, modname, name_cls):
393406
name, cls = name_cls
394407
add_modules = self.env.config.add_module_names
395408

396-
if self.objtype.endswith('method') or self.objtype == 'attr':
409+
if self.objtype.endswith('method') or self.objtype == 'attr' or self.objtype == 'case':
397410
try:
398411
clsname, propname = php_rsplit(name)
399412
except ValueError:
@@ -414,6 +427,13 @@ def get_index_text(self, modname, name_cls):
414427
return _('%s (%s\\%s property)') % (propname, modname, clsname)
415428
else:
416429
return _('%s (%s property)') % (propname, clsname)
430+
elif self.objtype == 'case':
431+
if modname and clsname is None:
432+
return _('%s enum case') % (name)
433+
elif modname and add_modules:
434+
return _('%s (%s\\%s enum case)') % (propname, modname, clsname)
435+
else:
436+
return _('%s (%s enum case)') % (propname, clsname)
417437
else:
418438
return ''
419439

@@ -586,6 +606,8 @@ class PhpDomain(Domain):
586606
'namespace': ObjType(_('namespace'), 'ns', 'obj'),
587607
'interface': ObjType(_('interface'), 'interface', 'obj'),
588608
'trait': ObjType(_('trait'), 'trait', 'obj'),
609+
'enum': ObjType(_('enum'), 'enum', 'obj'),
610+
'case': ObjType(_('case'), 'case', 'obj'),
589611
}
590612

591613
directives = {
@@ -596,9 +618,11 @@ class PhpDomain(Domain):
596618
'method': PhpClassmember,
597619
'staticmethod': PhpClassmember,
598620
'attr': PhpClassmember,
621+
'case': PhpClassmember,
599622
'exception': PhpClasslike,
600623
'interface': PhpClasslike,
601624
'trait': PhpClasslike,
625+
'enum': PhpClasslike,
602626
'namespace': PhpNamespace,
603627
'currentmodule': PhpCurrentNamespace,
604628
'currentnamespace': PhpCurrentNamespace,
@@ -616,6 +640,8 @@ class PhpDomain(Domain):
616640
'obj': PhpXRefRole(),
617641
'interface': PhpXRefRole(),
618642
'trait': PhpXRefRole(),
643+
'enum': PhpXRefRole(),
644+
'case': PhpXRefRole(),
619645
}
620646

621647
initial_data = {

test/test_doc.rst

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,3 +472,129 @@ Return Types
472472
.. php:class:: ReturnedClass
473473
474474
A class to return.
475+
476+
Enums
477+
=====
478+
479+
Basic Enumerations
480+
------------------
481+
482+
.. php:namespace:: Example\Basic
483+
484+
.. php:enum:: Suit
485+
486+
In playing cards, a suit is one of the categories into which the cards of a
487+
deck are divided.
488+
489+
.. php:case:: Hearts
490+
.. php:case:: Diamonds
491+
.. php:case:: Clubs
492+
.. php:case:: Spades
493+
494+
Backed Enumerations
495+
-------------------
496+
497+
.. php:namespace:: Example\Backed
498+
499+
.. php:enum:: Suit : string
500+
501+
In playing cards, a suit is one of the categories into which the cards of a
502+
deck are divided.
503+
504+
.. php:case:: Hearts : 'H'
505+
.. php:case:: Diamonds : 'D'
506+
.. php:case:: Clubs : 'C'
507+
.. php:case:: Spades : 'S'
508+
509+
Advanced Enumerations
510+
---------------------
511+
512+
.. php:namespace:: Example\Advanced
513+
514+
.. php:enum:: Suit : string
515+
516+
In playing cards, a suit is one of the categories into which the cards of a
517+
deck are divided.
518+
519+
.. php:case:: Hearts : 'H'
520+
.. php:case:: Diamonds : 'D'
521+
.. php:case:: Clubs : 'C'
522+
.. php:case:: Spades : 'S'
523+
524+
.. php:method:: color() -> string
525+
526+
Returns "red" for hearts and diamonds, "black" for clubs and spades.
527+
528+
.. php:staticmethod:: values() -> string[]
529+
530+
Returns an array of the values of all the cases on this enum.
531+
532+
.. php:const:: Roses() : Hearts
533+
534+
An alias for :php:case:`Example\\Advanced\\Suit::Hearts`.
535+
536+
.. php:const:: Bells : Diamonds
537+
538+
An alias for :php:case:`Example\\Advanced\\Suit::Diamonds`.
539+
540+
.. php:const:: Acorns : Clubs
541+
542+
An alias for :php:case:`Example\\Advanced\\Suit::Clubs`.
543+
544+
.. php:const:: Shields : Spades
545+
546+
An alias for :php:case:`Example\\Advanced\\Suit::Spades`.
547+
548+
Enumeration Links
549+
-----------------
550+
551+
Links to Basic Enumeration Example
552+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
553+
554+
:php:enum:`Example\\Basic\\Suit`
555+
556+
:php:case:`Example\\Basic\\Suit::Hearts`
557+
558+
:php:case:`Example\\Basic\\Suit::Diamonds`
559+
560+
:php:case:`Example\\Basic\\Suit::Clubs`
561+
562+
:php:case:`Example\\Basic\\Suit::Spades`
563+
564+
Links to Backed Enumeration Example
565+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
566+
567+
:php:enum:`Example\\Backed\\Suit`
568+
569+
:php:case:`Example\\Backed\\Suit::Hearts`
570+
571+
:php:case:`Example\\Backed\\Suit::Diamonds`
572+
573+
:php:case:`Example\\Backed\\Suit::Clubs`
574+
575+
:php:case:`Example\\Backed\\Suit::Spades`
576+
577+
Links to Advanced Enumeration Example
578+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
579+
580+
:php:enum:`Example\\Advanced\\Suit`
581+
582+
:php:case:`Example\\Advanced\\Suit::Hearts`
583+
584+
:php:case:`Example\\Advanced\\Suit::Diamonds`
585+
586+
:php:case:`Example\\Advanced\\Suit::Clubs`
587+
588+
:php:case:`Example\\Advanced\\Suit::Spades`
589+
590+
:php:meth:`Example\\Advanced\\Suit::color`
591+
592+
:php:meth:`Example\\Advanced\\Suit::values`
593+
594+
:php:const:`Example\\Advanced\\Suit::Roses`
595+
596+
:php:const:`Example\\Advanced\\Suit::Bells`
597+
598+
:php:const:`Example\\Advanced\\Suit::Acorns`
599+
600+
:php:const:`Example\\Advanced\\Suit::Shields`

0 commit comments

Comments
 (0)