Skip to content

Commit 3e98837

Browse files
committed
Revert logical changes from #60
They have contributed to several regressions and I'm going to resolve issue #56 with a different approach.
1 parent a409402 commit 3e98837

File tree

1 file changed

+89
-96
lines changed

1 file changed

+89
-96
lines changed

sphinxcontrib/phpdomain.py

+89-96
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"""
2-
Sphinx PHP domain.
3-
4-
The PHP domain. Based off of the rubydomain by SHIBUKAWA Yoshiki
2+
Sphinx PHP domain.
53
6-
:copyright: Copyright 2016 by Mark Story
7-
:license: BSD, see LICENSE for details.
4+
The PHP domain. Based off of the rubydomain by SHIBUKAWA Yoshiki
5+
6+
:copyright: Copyright 2016 by Mark Story
7+
:license: BSD, see LICENSE for details.
88
"""
99
import re
1010
import inspect
@@ -70,9 +70,9 @@ def throw_if_false(fromdocnode, value, message: str):
7070

7171
separators = {
7272
"global": None,
73-
"namespace": None,
74-
"function": None,
75-
"interface": None,
73+
"namespace": NS,
74+
"function": NS,
75+
"interface": NS,
7676
"class": None,
7777
"trait": None,
7878
"enum": None,
@@ -229,17 +229,27 @@ def handle_signature(self, sig, signode):
229229
)
230230
separator = separators[self.objtype]
231231

232-
if "::" in name_prefix:
232+
classname = self.env.temp_data.get("php:class")
233+
# Method declared as Class::methodName
234+
if not classname and "::" in name_prefix:
233235
classname = name_prefix.rstrip("::")
234-
else:
235-
classname = self.env.temp_data.get("php:class")
236236

237-
if self.objtype == "global":
237+
if self.objtype == "global" or self.objtype == "function":
238+
add_module = False
238239
namespace = None
239240
classname = None
240241
fullname = name
241242
else:
242-
if name_prefix:
243+
add_module = True
244+
# name_prefix and a non-static method, means the classname was
245+
# repeated. Trim off the <class>::
246+
if name_prefix and self.objtype != 'staticmethod':
247+
if name_prefix.startswith(classname):
248+
name_prefix = name_prefix[len(classname):].rstrip('::')
249+
classname = classname.rstrip('::')
250+
fullname = name_prefix + classname + separator + name
251+
elif name_prefix:
252+
classname = classname.rstrip('::')
243253
fullname = name_prefix + name
244254

245255
# Currently in a class, but not creating another class,
@@ -279,13 +289,17 @@ def handle_signature(self, sig, signode):
279289
name_prefix = namespace + NS + name_prefix
280290
signode += addnodes.desc_addname(name_prefix, name_prefix)
281291

282-
elif (
283-
namespace
284-
and not self.env.temp_data.get("php:in_class", False)
285-
and self.env.config.add_module_names
286-
):
287-
nodetext = namespace + NS
288-
signode += addnodes.desc_addname(nodetext, nodetext)
292+
elif add_module and self.env.config.add_module_names:
293+
if self.objtype == 'global':
294+
nodetext = ''
295+
signode += addnodes.desc_addname(nodetext, nodetext)
296+
else:
297+
namespace = self.options.get(
298+
'namespace', self.env.temp_data.get('php:namespace'))
299+
300+
if namespace and not self.env.temp_data.get('php:in_class', False):
301+
nodetext = namespace + NS
302+
signode += addnodes.desc_addname(nodetext, nodetext)
289303

290304
signode += addnodes.desc_name(name, name)
291305
if not arglist:
@@ -603,26 +617,18 @@ class PhpXRefRole(XRefRole):
603617

604618
def process_link(self, env, refnode, has_explicit_title, title, target):
605619
if not has_explicit_title:
606-
# If the first char is '~' don't display the leading namespace & class.
607-
if target.startswith("~"): # only has a meaning for the title
608-
target = title[1:]
609-
if title.startswith("~"):
610-
title = title[1:]
611-
title = re.sub(r"^[\w\\]+::", "", title)
612-
613-
if title.startswith(NS):
614-
title = title[1:]
615-
616-
reftype = refnode.attributes["reftype"]
617-
if reftype == "global":
618-
namespace = None
619-
classname = None
620-
else:
621-
namespace = env.temp_data.get("php:namespace")
622-
classname = env.temp_data.get("php:class")
620+
if title.startswith("::"):
621+
title = title[2:]
622+
target = target.lstrip('~') # only has a meaning for the title
623623

624-
refnode["php:namespace"] = namespace
625-
refnode["php:class"] = classname
624+
# If the first char is ~ don't display the leading namespace & class.
625+
if title.startswith('~'):
626+
m = re.search(r"(?:.+[:]{2}|(?:.*?\\{1,2})+)?(.*)\Z", title)
627+
if m:
628+
title = m.group(1)
629+
630+
refnode["php:namespace"] = env.temp_data.get("php:namespace")
631+
refnode["php:class"] = env.temp_data.get("php:class")
626632

627633
return title, target
628634

@@ -814,76 +820,63 @@ def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
814820
else:
815821
namespace = node.get("php:namespace")
816822
clsname = node.get("php:class")
817-
name, obj = self.find_obj(env, node, namespace, clsname, target, typ)
823+
searchorder = node.hasattr("refspecific") and 1 or 0
824+
name, obj = self.find_obj(env, node, namespace, clsname, target, typ, searchorder)
818825
if not obj:
819826
return None
820827
else:
821828
return make_refnode(builder, fromdocname, obj[0], name, contnode, name)
822829

823-
def find_obj(self, env, fromdocnode, namespace, classname, name, type):
830+
def find_obj(self, env, fromdocnode, namespace, classname, name, type, searchorder=0):
824831
"""
825832
Find a PHP object for "name", using the given namespace and classname.
826833
"""
827834
# strip parenthesis
828835
if name[-2:] == "()":
829836
name = name[:-2]
830837

831-
objects = self.data["objects"]
832-
833-
if name.startswith(NS):
834-
absname = name[1:]
838+
if not name:
839+
return None, None
840+
841+
objects = self.data['objects']
842+
843+
newname = None
844+
if searchorder == 1:
845+
if namespace and classname and \
846+
namespace + NS + classname + '::' + name in objects:
847+
newname = namespace + NS + classname + '::' + name
848+
elif namespace and namespace + NS + name in objects:
849+
newname = namespace + NS + name
850+
elif namespace and namespace + NS + name in objects:
851+
newname = namespace + NS + name
852+
elif classname and classname + '::' + name in objects:
853+
newname = classname + '.' + name
854+
elif classname and classname + '::$' + name in objects:
855+
newname = classname + '::$' + name
856+
elif name in objects:
857+
newname = name
835858
else:
836-
absname = (namespace + NS if namespace else "") + name
837-
838-
if absname not in objects and name in objects:
839-
# constants/functions can be namespaced, but allow fallback to global namespace the same way as PHP does
840-
name_type = objects[name][1]
841-
if (
842-
(name_type == "function" or name_type == "const")
843-
and NS not in name
844-
and "::" not in name
845-
):
846-
absname = name
847-
else:
848-
if namespace and name.startswith(namespace + NS):
849-
log_info(
850-
fromdocnode,
851-
f"Target {absname} not found - did you mean to write {name[len(namespace + NS):]}?",
852-
)
853-
else:
854-
log_info(
855-
fromdocnode,
856-
f"Target {absname} not found - did you mean to write {NS + name}?",
857-
)
858-
absname = name # fallback for BC, might be removed in the next major release
859-
860-
if absname in objects:
861-
return absname, objects[absname]
862-
863-
# PHP reserved keywords are never resolved using NS and ignore them when not defined
864-
if name not in [
865-
"array",
866-
"bool",
867-
"callable",
868-
"false",
869-
"float",
870-
"int",
871-
"iterable",
872-
"mixed",
873-
"never",
874-
"null",
875-
"object",
876-
"parent",
877-
"resource",
878-
"self",
879-
"static",
880-
"string",
881-
"true",
882-
"void",
883-
]:
884-
log_info(fromdocnode, f"Target {absname} not found")
885-
886-
return None, None
859+
if name in objects:
860+
newname = name
861+
elif classname and classname + '::' + name in objects:
862+
newname = classname + '::' + name
863+
elif classname and classname + '::$' + name in objects:
864+
newname = classname + '::$' + name
865+
elif namespace and namespace + NS + name in objects:
866+
newname = namespace + NS + name
867+
elif namespace and classname and \
868+
namespace + NS + classname + '::' + name in objects:
869+
newname = namespace + NS + classname + '::' + name
870+
elif namespace and classname and \
871+
namespace + NS + classname + '::$' + name in objects:
872+
newname = namespace + NS + classname + '::$' + name
873+
# special case: object methods
874+
elif type in ('func', 'meth') and '::' not in name and \
875+
'object::' + name in objects:
876+
newname = 'object::' + name
877+
if newname is None:
878+
return None, None
879+
return newname, objects[newname]
887880

888881
def get_objects(self):
889882
for ns, info in self.data["namespaces"].items():

0 commit comments

Comments
 (0)