From f785b8b333f1fa141fc635ef4f4977235d727459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Vo=C5=99=C3=AD=C5=A1ek?= Date: Fri, 18 Aug 2023 03:54:23 +0200 Subject: [PATCH] Fix references resolving (#60) * Fix resolve for absolute reference names * move test/unit to test * move test/must-build to test * push changes to forks and only once per workflow * assert log using CI * fix method/property render /w explicit class name * remove dead code and prevent NS refetch * improve comments * refactor "modname" to "namespace" * refactor remaining module mentions * remove dead code * reserved names are never resolved using NS * "global" is for global variables only * stricter identifier matching in signature * improve separators def * log unable to parse signature * always resolve refs using namespace, never fallback to global * Enforce Coding Style using Black * "numeric" type is not reserved keyword * add mvorisek as coauthor * test warnings and non-zero exit code * fix ref type mismatch * fix .gitignore --------- Co-authored-by: Mark Story --- .github/workflows/ci.yml | 68 +- .gitignore | 3 +- README.rst | 1 + doc/conf.py | 129 +- setup.py | 32 +- sphinxcontrib/__init__.py | 3 +- sphinxcontrib/phpdomain.py | 914 ++++--- test/{must-build => }/Makefile | 0 test/conf.py | 17 + test/{unit => }/index.md | 0 test/log.html | 61 + test/log.md | 25 + test/log.txt | 13 + test/{must-build => }/make.bat | 0 test/{unit => }/method.html | 0 test/{unit => }/method.md | 0 test/must-build/conf.py | 210 -- test/ns.html | 171 ++ test/ns.md | 53 + test/{unit => }/requirements.txt | 0 test/rst_doc.html | 2201 +++++++++++++++++ test/{must-build/test_doc.rst => rst_doc.md} | 138 +- test/rst_doc2.html | 100 + .../{must-build/test_doc2.rst => rst_doc2.md} | 19 +- test/rst_index.html | 110 + test/{must-build/index.rst => rst_index.md} | 9 +- test/rst_nesting_regression.html | 68 + ...gression.rst => rst_nesting_regression.md} | 2 + test/unit/Makefile | 130 - test/unit/conf.py | 17 - test/unit/make.bat | 155 -- test/unit/ns.html | 51 - test/unit/ns.md | 14 - 33 files changed, 3535 insertions(+), 1179 deletions(-) rename test/{must-build => }/Makefile (100%) create mode 100644 test/conf.py rename test/{unit => }/index.md (100%) create mode 100644 test/log.html create mode 100644 test/log.md create mode 100644 test/log.txt rename test/{must-build => }/make.bat (100%) rename test/{unit => }/method.html (100%) rename test/{unit => }/method.md (100%) delete mode 100644 test/must-build/conf.py create mode 100644 test/ns.html create mode 100644 test/ns.md rename test/{unit => }/requirements.txt (100%) create mode 100644 test/rst_doc.html rename test/{must-build/test_doc.rst => rst_doc.md} (76%) create mode 100644 test/rst_doc2.html rename test/{must-build/test_doc2.rst => rst_doc2.md} (60%) create mode 100644 test/rst_index.html rename test/{must-build/index.rst => rst_index.md} (80%) create mode 100644 test/rst_nesting_regression.html rename test/{must-build/test_nesting_regression.rst => rst_nesting_regression.md} (96%) delete mode 100644 test/unit/Makefile delete mode 100644 test/unit/conf.py delete mode 100644 test/unit/make.bat delete mode 100644 test/unit/ns.html delete mode 100644 test/unit/ns.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c603587..f4c715e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,46 +33,66 @@ jobs: run: | python -m pip install --upgrade pip pip install -r requirements.txt - pip install -r test/unit/requirements.txt + pip install -r test/requirements.txt pip install . - - name: Build Test + - name: Build Unit Tests run: | - cd test/must-build && make html SPHINXOPTS='-W' + cd test + find . -name '*.html' -exec rm {} \; - - name: Build Test with toc show_parents=hide - run: | - cd test/must-build && make html SPHINXOPTS='-W -D toc_object_entries_show_parents=hide' + sed -i 's~, "log\.md"~~' conf.py + make html SPHINXOPTS='' 2>&1 | tee log.txt + git restore conf.py - - name: Build Test with toc show_parents=domain - run: | - cd test/must-build && make html SPHINXOPTS='-W -D toc_object_entries_show_parents=domain' - - - name: Build Test with toc show_parents=all - run: | - cd test/must-build && make html SPHINXOPTS='-W -D toc_object_entries_show_parents=all' + (cd _build/html && rm genindex.html index.html search.html php-modindex.html) + (cd _build/html && find . -name '*.html' -exec sh -c 'xmllint {} --xpath '"'"'//div[@role="main"]'"'"' | xmllint --format - > ../../{}' \;) + sed -i -r 's~.*/(test/)~\1~;t;d' log.txt - - name: Run Unit Testing + - name: Apply Coding Style + if: matrix.python == '3.11' run: | - cd test/unit - find . -name '*.html' -exec rm {} \; - make html SPHINXOPTS='-W' - (cd _build/html && find . -name '*.html' -exec sh -c 'xmllint {} --xpath '"'"'//div[@role="main"]'"'"' | xmllint --format - > ../../{}' \;) - rm genindex.html index.html search.html php-modindex.html + pip install black + python -m black . - - name: Diff Unit Outputs + - name: Diff Unit Tests Output and Coding Style run: | - cd test/unit + cd test rm -r _build git add . -N && git diff --exit-code - - name: Push Unit Changes - if: failure() + - name: Push Unit Tests Output + if: failure() && github.repository_owner != 'markstory' && matrix.python == '3.11' uses: stefanzweifel/git-auto-commit-action@v4 with: branch: ${{ github.head_ref || github.ref_name }}.changes + create_branch: true push_options: '--force' - commit_message: Unit Changes + commit_message: Unit Tests Changes commit_user_name: Bot commit_user_email: bot@example.com commit_author: Bot + + - name: Build Unit Tests with '-W' option + run: | + cd test + make html SPHINXOPTS='-W' + + sed -i 's~, "log\.md"~~' conf.py + ! make html SPHINXOPTS='-W' || (echo 'Unexpected zero exit code'; false) + git restore conf.py + + - name: Build Unit Tests with toc show_parents=hide + run: | + cd test + make html SPHINXOPTS='-W -D toc_object_entries_show_parents=hide' + + - name: Build Unit Tests with toc show_parents=domain + run: | + cd test + make html SPHINXOPTS='-W -D toc_object_entries_show_parents=domain' + + - name: Build Unit Tests with toc show_parents=all + run: | + cd test + make html SPHINXOPTS='-W -D toc_object_entries_show_parents=all' diff --git a/.gitignore b/.gitignore index 508e0cc1..c28a058b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ dist/ build/ doc/_build -test/must-build/_build -test/unit/_build +test/_build *.pyc *.egg-info .DS_Store diff --git a/README.rst b/README.rst index c197aa99..9407f786 100644 --- a/README.rst +++ b/README.rst @@ -2,6 +2,7 @@ PHP Domain for Sphinx ##################### :author: Mark Story +:author: Michael Voříšek About ===== diff --git a/doc/conf.py b/doc/conf.py index 39131ca1..21e646aa 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,203 +1,195 @@ -# -*- coding: utf-8 -*- -# -# sphinxcontrib-rubydomain-acceptancetest documentation build configuration file, created by -# sphinx-quickstart on Sun Apr 25 13:27:18 2010. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath('..')) +sys.path.append(os.path.abspath("..")) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.0' +needs_sphinx = "1.0" # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinxcontrib.phpdomain'] +extensions = ["sphinxcontrib.phpdomain"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = u'sphinxcontrib-phpdomain' -copyright = u'2011, Mark Story' +project = "sphinxcontrib-phpdomain" +copyright = "2011 - 2023, Mark Story and Michael Voříšek" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.1' +version = "0.1" # The full version, including alpha/beta/rc tags. -release = '0.1' +release = "0.1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'sphinxdoc' +html_theme = "sphinxdoc" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] +# html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' +# html_file_suffix = '' # Output file base name for HTML help builder. -htmlhelp_basename = 'sphinxcontrib-phpdomain' +htmlhelp_basename = "sphinxcontrib-phpdomain" # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'sphinxcontrib-phpdomain.tex', u'sphinxcontrib-phpdomain Documentation', - u'Mark Story', 'manual'), + ( + "index", + "sphinxcontrib-phpdomain.tex", + "sphinxcontrib-phpdomain Documentation", + "Mark Story and Michael Voříšek", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# latex_preamble = '' # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output -------------------------------------------- @@ -205,6 +197,11 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'sphinxcontrib-phpdomain', u'sphinxcontrib-phpdomain Documentation', - [u'Mark Story'], 1) + ( + "index", + "sphinxcontrib-phpdomain", + "sphinxcontrib-phpdomain Documentation", + ["Mark Story and Michael Voříšek"], + 1, + ) ] diff --git a/setup.py b/setup.py index 081c95e3..e6039e2b 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- import os from setuptools import setup, find_packages -with open(os.path.join(os.path.dirname(__file__), - 'requirements.txt'), 'r') as f: +with open(os.path.join(os.path.dirname(__file__), "requirements.txt"), "r") as f: requirements = f.read() -long_desc = ''' +long_desc = """ This package provides a Sphinx extension for documenting PHP projects. PHP Domain supports following objects: @@ -27,7 +25,7 @@ * Properties * Enums -''' +""" setup( name='sphinxcontrib-phpdomain', @@ -40,22 +38,22 @@ description='Sphinx extension to enable documenting PHP code', long_description=long_desc, project_urls={ - 'Documentation': 'https://markstory.github.io/sphinxcontrib-phpdomain/', + "Documentation": "https://markstory.github.io/sphinxcontrib-phpdomain/", }, classifiers=[ - 'Environment :: Console', - 'Environment :: Web Environment', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Documentation', - 'Topic :: Utilities', + "Environment :: Console", + "Environment :: Web Environment", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Topic :: Documentation", + "Topic :: Utilities", ], - platforms='any', + platforms="any", dependency_links=[], - namespace_packages=['sphinxcontrib'], - packages=find_packages(exclude=['test*']), + namespace_packages=["sphinxcontrib"], + packages=find_packages(exclude=["test*"]), include_package_data=True, install_requires=requirements, zip_safe=False, diff --git a/sphinxcontrib/__init__.py b/sphinxcontrib/__init__.py index fad99fcd..0e5de82e 100644 --- a/sphinxcontrib/__init__.py +++ b/sphinxcontrib/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ sphinxcontrib ~~~~~~~~~~~~~ @@ -11,4 +10,4 @@ :license: BSD, see LICENSE for details. """ -__import__('pkg_resources').declare_namespace(__name__) +__import__("pkg_resources").declare_namespace(__name__) diff --git a/sphinxcontrib/phpdomain.py b/sphinxcontrib/phpdomain.py index d73860fc..8dc5e84a 100644 --- a/sphinxcontrib/phpdomain.py +++ b/sphinxcontrib/phpdomain.py @@ -1,14 +1,13 @@ -# -*- coding: utf-8 -*- """ - sphinx.domains.php - ~~~~~~~~~~~~~~~~~~~ - + Sphinx PHP domain. + The PHP domain. Based off of the rubydomain by SHIBUKAWA Yoshiki :copyright: Copyright 2016 by Mark Story :license: BSD, see LICENSE for details. """ import re +import inspect from docutils import nodes from docutils.parsers.rst import directives, Directive @@ -18,38 +17,71 @@ from sphinx.locale import _ from sphinx.domains import Domain, ObjType, Index from sphinx.directives import ObjectDescription +from sphinx.util import logging from sphinx.util.nodes import make_refnode from sphinx.util.docfields import Field, GroupedField, TypedField from sphinx import __version__ as sphinx_version -php_sig_re = re.compile( - r'''^ (public\ |protected\ |private\ )? # visibility - (final\ |abstract\ |static\ )? # modifiers - ([\w.]*\:\:)? # class name(s) - (\$?\w+) \s* # thing name - (?: \((.*)\) # optional: arguments - (?:\s* -> \s* (.*))?)? # return annotation - (?:\s* : \s* (.*))? # backed enum type / case value - $ # and nothing more - ''', re.VERBOSE) + +def log_info(fromdocnode, message: str): + """ + Log informative message. Should have no effect on exit code. + """ + logger = logging.getLogger(__name__) + logger.info(f"[phpdomain] {message}", location=fromdocnode) -NS = '\\' +def log_warning(fromdocnode, message: str): + """ + Log warning. Should set exit code to non-zero. + """ + logger = logging.getLogger(__name__) + logger.warning(f"[phpdomain] {message}", location=fromdocnode, type="phpdomain") + + +def throw_if_false(fromdocnode, value, message: str): + """ + Log warning if the value is not true and throw ValueError. Should set exit code to non-zero. + """ + if not value: + log_warning(fromdocnode, message) + raise ValueError + + +php_sig_re = re.compile( + r""" + ^ + (public\ |protected\ |private\ )? # visibility + (final\ |abstract\ |static\ )? # modifiers + ((?:\\?(?!\d)\w+)\:\:)? # class name + (\$?(?:\\?(?!\d)\w+)+) \s* # thing name + (?: + \((.*)\) # optional: arguments + (?: \s* -> \s* (.*))? # return annotation + )? + (?: \s* : \s* (.*))? # backed enum type / case value + $ # and nothing more + """, + re.VERBOSE, +) + + +NS = "\\" separators = { - 'method': '::', - 'function': NS, - 'class': NS, - 'namespace': NS, - 'global': '', - 'const': '::', - 'attr': '::$', - 'exception': '', - 'staticmethod': '::', - 'interface': NS, - 'trait': NS, - 'enum': NS, - 'case': '::', + "global": None, + "namespace": None, + "function": None, + "interface": None, + "class": None, + "trait": None, + "enum": None, + "exception": None, + "method": "::", + "const": "::", + "attr": "::$", + "staticmethod": "::", + "case": "::", } php_separator = re.compile(r"(\w+)?(?:[:]{2})?") @@ -57,7 +89,8 @@ def _pseudo_parse_arglist(signode, arglist): # type: (addnodes.desc_signature, unicode) -> None - """"Parse" a list of arguments separated by commas. + """ + "Parse" a list of arguments separated by commas. Arguments can have "optional" annotations given by enclosing them in brackets. Currently, this will split at any comma, even if it's inside a string literal (e.g. default argument value). @@ -67,20 +100,20 @@ def _pseudo_parse_arglist(signode, arglist): paramlist = addnodes.desc_parameterlist() stack = [paramlist] try: - for argument in arglist.split(','): + for argument in arglist.split(","): argument = argument.strip() ends_open = ends_close = 0 - while argument.startswith('['): + while argument.startswith("["): stack.append(addnodes.desc_optional()) stack[-2] += stack[-1] argument = argument[1:].strip() - while argument.startswith(']'): + while argument.startswith("]"): stack.pop() argument = argument[1:].strip() - while argument.endswith(']') and not argument.endswith('[]'): + while argument.endswith("]") and not argument.endswith("[]"): ends_close += 1 argument = argument[:-1].strip() - while argument.endswith('['): + while argument.endswith("["): ends_open += 1 argument = argument[:-1].strip() if argument: @@ -106,41 +139,64 @@ def _pseudo_parse_arglist(signode, arglist): def php_rsplit(fullname): items = [item for item in php_separator.findall(fullname)] - return ''.join(items[:-2]), ''.join(items[1:-1]) + return "".join(items[:-2]), "".join(items[1:-1]) class PhpObject(ObjectDescription): """ Description of a general PHP object. """ + option_spec = { - 'noindex': directives.flag, - 'noindexentry': directives.flag, - 'nocontentsentry': directives.flag, - 'module': directives.unchanged, + "noindex": directives.flag, + "noindexentry": directives.flag, + "nocontentsentry": directives.flag, + "module": directives.unchanged, } doc_field_types = [ - TypedField('parameter', label=_('Parameters'), - names=('param', 'parameter', 'arg', 'argument'), - typerolename='obj', typenames=('paramtype', 'type')), - TypedField('variable', label=_('Variables'), rolename='obj', - names=('var', 'ivar', 'cvar'), - typerolename='obj', typenames=('vartype',)), - GroupedField('exceptions', label=_('Throws'), rolename='exc', - names=('throws', 'throw', 'exception', 'except'), - can_collapse=True), - Field('returnvalue', label=_('Returns'), has_arg=False, - names=('returns', 'return')), - Field('returntype', label=_('Return type'), has_arg=False, - names=('rtype', 'returntype'), bodyrolename='obj'), + TypedField( + "parameter", + label=_("Parameters"), + names=("param", "parameter", "arg", "argument"), + typerolename="obj", + typenames=("paramtype", "type"), + ), + TypedField( + "variable", + label=_("Variables"), + rolename="obj", + names=("var", "ivar", "cvar"), + typerolename="obj", + typenames=("vartype",), + ), + GroupedField( + "exceptions", + label=_("Throws"), + rolename="exc", + names=("throws", "throw", "exception", "except"), + can_collapse=True, + ), + Field( + "returnvalue", + label=_("Returns"), + has_arg=False, + names=("returns", "return"), + ), + Field( + "returntype", + label=_("Return type"), + has_arg=False, + names=("rtype", "returntype"), + bodyrolename="obj", + ), ] def get_signature_prefix(self, sig): """ May return a prefix to put before the object name in the signature. """ - return '' + return "" def needs_arglist(self): """ @@ -160,82 +216,76 @@ def handle_signature(self, sig, signode): """ m = php_sig_re.match(sig) if m is None: - raise ValueError + throw_if_false(signode, False, "Invalid signature") visibility, modifiers, name_prefix, name, arglist, retann, enumtype = m.groups() if not name_prefix: name_prefix = "" - # determine module and class name (if applicable), as well as full name - modname = self.options.get( - 'namespace', self.env.temp_data.get('php:namespace')) - - classname = self.env.temp_data.get('php:class') + # determine namespace and class name (if applicable), as well as full name + namespace = self.options.get( + "namespace", self.env.temp_data.get("php:namespace") + ) separator = separators[self.objtype] - # Method declared as Class::methodName - if not classname and '::' in name_prefix: - classname = name_prefix.rstrip('::') - if self.objtype == 'global' or self.objtype == 'function': - add_module = False - modname = None + if "::" in name_prefix: + classname = name_prefix.rstrip("::") + else: + classname = self.env.temp_data.get("php:class") + + if self.objtype == "global": + namespace = None classname = None fullname = name else: - add_module = True - # name_prefix and a non-static method, means the classname was - # repeated. Trim off the :: - if name_prefix and self.objtype != 'staticmethod': - if name_prefix.startswith(classname): - name_prefix = name_prefix[len(classname):].rstrip('::') - classname = classname.rstrip('::') - fullname = name_prefix + classname + separator + name - elif name_prefix: - classname = classname.rstrip('::') + if name_prefix: fullname = name_prefix + name # Currently in a class, but not creating another class, - elif classname and not self.objtype in ['class', 'exception', 'interface', 'trait', 'enum']: - if not self.env.temp_data['php:in_class']: + elif classname and not self.objtype in [ + "class", + "exception", + "interface", + "trait", + "enum", + "function", + ]: + if not self.env.temp_data["php:in_class"]: name_prefix = classname + separator fullname = classname + separator + name else: - classname = '' + classname = "" fullname = name - signode['namespace'] = modname - signode['class'] = self.class_name = classname - signode['fullname'] = fullname + signode["namespace"] = namespace + signode["class"] = self.class_name = classname + signode["fullname"] = fullname if visibility: signode += addnodes.desc_annotation(visibility, visibility) sig_prefix = self.get_signature_prefix(sig) - if modifiers and not (sig_prefix and 'static' in sig_prefix): - signode += addnodes.desc_annotation(modifiers, modifiers) + if modifiers and not (sig_prefix and "static" in sig_prefix): + signode += addnodes.desc_annotation(modifiers, modifiers) if sig_prefix: signode += addnodes.desc_annotation(sig_prefix, sig_prefix) if name_prefix: - if modname and not self.env.temp_data['php:in_class']: - name_prefix = modname + NS + name_prefix + if namespace and not self.env.temp_data["php:in_class"]: + name_prefix = namespace + NS + name_prefix signode += addnodes.desc_addname(name_prefix, name_prefix) - elif add_module and self.env.config.add_module_names: - if self.objtype == 'global': - nodetext = '' - signode += addnodes.desc_addname(nodetext, nodetext) - else: - modname = self.options.get( - 'namespace', self.env.temp_data.get('php:namespace')) - - if modname and not self.env.temp_data.get('php:in_class', False): - nodetext = modname + NS - signode += addnodes.desc_addname(nodetext, nodetext) + elif ( + namespace + and not self.env.temp_data.get("php:in_class", False) + and self.env.config.add_module_names + ): + nodetext = namespace + NS + signode += addnodes.desc_addname(nodetext, nodetext) signode += addnodes.desc_name(name, name) if not arglist: @@ -257,83 +307,87 @@ def handle_signature(self, sig, signode): return fullname, name_prefix def _object_hierarchy_parts(self, sig_node: addnodes.desc_signature): - if 'fullname' not in sig_node: + if "fullname" not in sig_node: return () - namespace = sig_node.get('namespace') - fullname = sig_node['fullname'] + namespace = sig_node.get("namespace") + fullname = sig_node["fullname"] if isinstance(namespace, str): - return (namespace, *fullname.split('::')) + return (namespace, *fullname.split("::")) else: - return tuple(fullname.split('::')) + return tuple(fullname.split("::")) def _toc_entry_name(self, sig_node: addnodes.desc_signature) -> str: - if not sig_node.get('_toc_parts'): - return '' + if not sig_node.get("_toc_parts"): + return "" config = self.env.app.config - objtype = sig_node.parent.get('objtype') - if config.add_function_parentheses and objtype in {'function', 'method'}: - parens = '()' + objtype = sig_node.parent.get("objtype") + if config.add_function_parentheses and objtype in {"function", "method"}: + parens = "()" else: - parens = '' - *parents, name = sig_node['_toc_parts'] - if config.toc_object_entries_show_parents == 'domain': - return sig_node.get('fullname', name) + parens - if config.toc_object_entries_show_parents == 'hide': + parens = "" + *parents, name = sig_node["_toc_parts"] + if config.toc_object_entries_show_parents == "domain": + return sig_node.get("fullname", name) + parens + if config.toc_object_entries_show_parents == "hide": return name + parens - if config.toc_object_entries_show_parents == 'all': - if objtype in {'method', 'const', 'attr', 'staticmethod', 'case'} and len(parents) > 0: - name = parents.pop() + '::' + name - return '\\'.join(parents + [name + parens]) - return '' - - def get_index_text(self, modname, name): + if config.toc_object_entries_show_parents == "all": + if ( + objtype in {"method", "const", "attr", "staticmethod", "case"} + and len(parents) > 0 + ): + name = parents.pop() + "::" + name + return "\\".join(parents + [name + parens]) + return "" + + def get_index_text(self, namespace, name): """ Return the text for the index entry of the object. """ - raise NotImplementedError('must be implemented in subclasses') + raise NotImplementedError("must be implemented in subclasses") def _is_class_member(self): - return (self.objtype.startswith('method') or - self.objtype.startswith('attr')) + return self.objtype.startswith("method") or self.objtype.startswith("attr") def add_target_and_index(self, name_cls, sig, signode): - if self.objtype == 'global': - modname = '' + if self.objtype == "global": + namespace = None else: - modname = self.options.get( - 'namespace', self.env.temp_data.get('php:namespace')) - separator = separators[self.objtype] + namespace = self.options.get( + "namespace", self.env.temp_data.get("php:namespace") + ) if self._is_class_member(): - if signode['class']: - prefix = modname and modname + NS or '' + if signode["class"]: + prefix = namespace and namespace + NS or "" else: - prefix = modname and modname + NS or '' + prefix = namespace and namespace + NS or "" else: - prefix = modname and modname + NS or '' + prefix = namespace and namespace + NS or "" fullname = prefix + name_cls[0] # note target if fullname not in self.state.document.ids: - signode['names'].append(fullname) - signode['ids'].append(fullname) - signode['first'] = (not self.names) + signode["names"].append(fullname) + signode["ids"].append(fullname) + signode["first"] = not self.names self.state.document.note_explicit_target(signode) - objects = self.env.domaindata['php']['objects'] + objects = self.env.domaindata["php"]["objects"] if fullname in objects: self.state_machine.reporter.warning( - 'duplicate object description of %s, ' % fullname + - 'other instance in ' + - self.env.doc2path(objects[fullname][0]), - line=self.lineno) + "duplicate object description of %s, " % fullname + + "other instance in " + + self.env.doc2path(objects[fullname][0]), + line=self.lineno, + ) objects[fullname] = (self.env.docname, self.objtype) - if 'noindexentry' not in self.options: - indextext = self.get_index_text(modname, name_cls) + if "noindexentry" not in self.options: + indextext = self.get_index_text(namespace, name_cls) if indextext: - self.indexnode['entries'].append(('single', indextext, - fullname, fullname, None)) + self.indexnode["entries"].append( + ("single", indextext, fullname, fullname, None) + ) class PhpGloballevel(PhpObject): @@ -341,11 +395,11 @@ class PhpGloballevel(PhpObject): Description of an object on global level (global variables). """ - def get_index_text(self, modname, name_cls): - if self.objtype == 'global': - return _('%s (global variable)') % name_cls[0] + def get_index_text(self, namespace, name_cls): + if self.objtype == "global": + return _("%s (global variable)") % name_cls[0] else: - return '' + return "" class PhpNamespacelevel(PhpObject): @@ -354,160 +408,168 @@ class PhpNamespacelevel(PhpObject): """ def needs_arglist(self): - return self.objtype == 'function' + return self.objtype == "function" def get_signature_prefix(self, sig): """ Adds class prefix for constants created inside classes """ - if self.objtype == 'const': - return _('constant ') - if self.class_name and self.class_name != '': - return self.class_name + '::' - - def get_index_text(self, modname, name_cls): - if self.objtype == 'function': - if not modname: - return _('%s() (global function)') % name_cls[0] - return _('%s() (function in %s)') % (name_cls[0], modname) - elif self.objtype == 'const' and self.class_name != '': - return _('%s (class constant)') % (name_cls[0]) - elif self.objtype == 'const': - if not modname: - return _('%s (global constant)') % (name_cls[0]) - return _('%s (constant in %s)') % (name_cls[0], modname) + if self.objtype == "const": + return _("constant ") + if self.class_name and self.class_name != "": + return self.class_name + "::" + + def get_index_text(self, namespace, name_cls): + if self.objtype == "function": + if not namespace: + return _("%s() (global function)") % name_cls[0] + return _("%s() (function in %s)") % (name_cls[0], namespace) + elif self.objtype == "const" and self.class_name != "": + return _("%s (class constant)") % (name_cls[0]) + elif self.objtype == "const": + if not namespace: + return _("%s (global constant)") % (name_cls[0]) + return _("%s (constant in %s)") % (name_cls[0], namespace) else: - return '' + return "" class PhpClasslike(PhpObject): """ Description of a class-like object - (classes, exceptions, interfaces, traits, enums). + (classes, interfaces, traits, enums). """ def get_signature_prefix(self, sig): - return self.objtype + ' ' - - def get_index_text(self, modname, name_cls): - if self.objtype == 'class': - if not modname: - return _('%s (class)') % name_cls[0] - return _('%s (class in %s)') % (name_cls[0], modname) - elif self.objtype == 'interface': - if not modname: - return _('%s (interface)') % name_cls[0] - return _('%s (interface in %s)') % (name_cls[0], modname) - elif self.objtype == 'trait': - if not modname: - return _('%s (trait)') % name_cls[0] - return _('%s (trait in %s)') % (name_cls[0], modname) - elif self.objtype == 'enum': - if not modname: - return _('%s (enum)') % name_cls[0] - return _('%s (enum in %s)') % (name_cls[0], modname) - elif self.objtype == 'exception': + return self.objtype + " " + + def get_index_text(self, namespace, name_cls): + if self.objtype == "class": + if not namespace: + return _("%s (class)") % name_cls[0] + return _("%s (class in %s)") % (name_cls[0], namespace) + elif self.objtype == "interface": + if not namespace: + return _("%s (interface)") % name_cls[0] + return _("%s (interface in %s)") % (name_cls[0], namespace) + elif self.objtype == "trait": + if not namespace: + return _("%s (trait)") % name_cls[0] + return _("%s (trait in %s)") % (name_cls[0], namespace) + elif self.objtype == "enum": + if not namespace: + return _("%s (enum)") % name_cls[0] + return _("%s (enum in %s)") % (name_cls[0], namespace) + elif self.objtype == "exception": return name_cls[0] else: - return '' + return "" def after_content(self): - self.env.temp_data['php:in_class'] = False + self.env.temp_data["php:in_class"] = False def before_content(self): - self.env.temp_data['php:in_class'] = True + self.env.temp_data["php:in_class"] = True if self.names: - self.env.temp_data['php:class'] = self.names[0][0] + self.env.temp_data["php:class"] = self.names[0][0] class PhpClassmember(PhpObject): """ - Description of a class member (methods, attributes). + Description of a class member (methods, properties). """ def get_signature_prefix(self, sig): - if self.objtype == 'attr': - return _('property ') - if self.objtype == 'staticmethod': - return _('static ') - if self.objtype == 'case': - return _('case ') - return '' + if self.objtype == "attr": + return _("property ") + if self.objtype == "staticmethod": + return _("static ") + if self.objtype == "case": + return _("case ") + return "" def needs_arglist(self): - return self.objtype == 'method' + return self.objtype == "method" - def get_index_text(self, modname, name_cls): + def get_index_text(self, namespace, name_cls): name, cls = name_cls - add_modules = self.env.config.add_module_names - if self.objtype.endswith('method') or self.objtype == 'attr' or self.objtype == 'case': + if ( + self.objtype.endswith("method") + or self.objtype == "attr" + or self.objtype == "case" + ): try: clsname, propname = php_rsplit(name) except ValueError: propname = name clsname = None - if self.objtype.endswith('method'): - if modname and clsname is None: - return _('%s() (in namespace %s)') % (name, modname) - elif modname and add_modules: - return _('%s() (%s\\%s method)') % (propname, modname, clsname) + if self.objtype.endswith("method"): + if namespace and clsname is None: + return _("%s() (in namespace %s)") % (name, namespace) + elif namespace and self.env.config.add_module_names: + return _("%s() (%s\\%s method)") % (propname, namespace, clsname) else: - return _('%s() (%s method)') % (propname, clsname) - elif self.objtype == 'attr': - if modname and clsname is None: - return _('%s (in namespace %s)') % (name, modname) - elif modname and add_modules: - return _('%s (%s\\%s property)') % (propname, modname, clsname) + return _("%s() (%s method)") % (propname, clsname) + elif self.objtype == "attr": + if namespace and clsname is None: + return _("%s (in namespace %s)") % (name, namespace) + elif namespace and self.env.config.add_module_names: + return _("%s (%s\\%s property)") % (propname, namespace, clsname) else: - return _('%s (%s property)') % (propname, clsname) - elif self.objtype == 'case': - if modname and clsname is None: - return _('%s enum case') % (name) - elif modname and add_modules: - return _('%s (%s\\%s enum case)') % (propname, modname, clsname) + return _("%s (%s property)") % (propname, clsname) + elif self.objtype == "case": + if namespace and clsname is None: + return _("%s enum case") % (name) + elif namespace and self.env.config.add_module_names: + return _("%s (%s\\%s enum case)") % (propname, namespace, clsname) else: - return _('%s (%s enum case)') % (propname, clsname) + return _("%s (%s enum case)") % (propname, clsname) else: - return '' + return "" class PhpNamespace(Directive): """ - Directive to start a new PHP namespace, which are similar to modules. + Directive to start a new PHP namespace, which is similar to module. """ + has_content = False required_arguments = 1 optional_arguments = 0 final_argument_whitespace = False option_spec = { - 'synopsis': lambda x: x, - 'noindex': directives.flag, - 'deprecated': directives.flag, + "synopsis": lambda x: x, + "noindex": directives.flag, + "deprecated": directives.flag, } def run(self): env = self.state.document.settings.env - modname = self.arguments[0].strip() - noindex = 'noindex' in self.options - env.temp_data['php:namespace'] = modname - env.temp_data['php:class'] = None - env.domaindata['php']['namespaces'][modname] = ( - env.docname, self.options.get('synopsis', ''), - 'deprecated' in self.options) - - targetnode = nodes.target('', '', ids=['namespace-' + modname], - ismod=True) + namespace = self.arguments[0].strip() + noindex = "noindex" in self.options + env.temp_data["php:namespace"] = namespace + env.temp_data["php:class"] = None + env.domaindata["php"]["namespaces"][namespace] = ( + env.docname, + self.options.get("synopsis", ""), + "deprecated" in self.options, + ) + + targetnode = nodes.target("", "", ids=["namespace-" + namespace], ismod=True) self.state.document.note_explicit_target(targetnode) ret = [targetnode] # the synopsis isn't printed; in fact, it is only used in the # modindex currently if not noindex: - indextext = _('%s (namespace)') % modname - inode = addnodes.index(entries=[('single', indextext, - 'namespace-' + modname, modname, None)]) + indextext = _("%s (namespace)") % namespace + inode = addnodes.index( + entries=[ + ("single", indextext, "namespace-" + namespace, namespace, None) + ] + ) ret.append(inode) return ret @@ -526,11 +588,11 @@ class PhpCurrentNamespace(Directive): def run(self): env = self.state.document.settings.env - modname = self.arguments[0].strip() - if modname == 'None': - env.temp_data['php:namespace'] = None + namespace = self.arguments[0].strip() + if namespace == "None": + env.temp_data["php:namespace"] = None else: - env.temp_data['php:namespace'] = modname + env.temp_data["php:namespace"] = namespace return [] @@ -538,86 +600,104 @@ class PhpXRefRole(XRefRole): """ Provides cross reference links for PHP objects """ + def process_link(self, env, refnode, has_explicit_title, title, target): if not has_explicit_title: - if title.startswith("::"): - title = title[2:] - target = target.lstrip('~') # only has a meaning for the title - - # If the first char is ~ don't display the leading namespace & class. - if title.startswith('~'): - m = re.search(r"(?:.+[:]{2}|(?:.*?\\{1,2})+)?(.*)\Z", title) - if m: - title = m.group(1) + # If the first char is '~' don't display the leading namespace & class. + if target.startswith("~"): # only has a meaning for the title + target = title[1:] + if title.startswith("~"): + title = title[1:] + title = re.sub(r"^[\w\\]+::", "", title) + + if title.startswith(NS): + title = title[1:] + + reftype = refnode.attributes["reftype"] + if reftype == "global": + namespace = None + classname = None + else: + namespace = env.temp_data.get("php:namespace") + classname = env.temp_data.get("php:class") - refnode['php:namespace'] = env.temp_data.get('php:namespace') - refnode['php:class'] = env.temp_data.get('php:class') + refnode["php:namespace"] = namespace + refnode["php:class"] = classname return title, target class PhpNamespaceIndex(Index): """ - Index subclass to provide the Php module index. + Index subclass to provide the PHP namespace index. """ - name = 'modindex' - localname = _('PHP Namespace Index') - shortname = _('namespaces') + name = "modindex" + localname = _("PHP Namespace Index") + shortname = _("namespaces") def generate(self, docnames=None): content = {} # list of prefixes to ignore - ignores = self.domain.env.config['modindex_common_prefix'] + ignores = self.domain.env.config["modindex_common_prefix"] ignores = sorted(ignores, key=len, reverse=True) - # list of all modules, sorted by module name - modules = sorted(self.domain.data['namespaces'].items(), - key=lambda x: x[0].lower()) - # sort out collapsable modules - prev_modname = '' + # list of all namespaces, sorted by name + namespaces = sorted( + self.domain.data["namespaces"].items(), key=lambda x: x[0].lower() + ) + # sort out collapsable namespaces + prev_namespace = "" num_toplevels = 0 - for modname, (docname, synopsis, deprecated) in modules: + for namespace, (docname, synopsis, deprecated) in namespaces: if docnames and docname not in docnames: continue for ignore in ignores: - if modname.startswith(ignore): - modname = modname[len(ignore):] + if namespace.startswith(ignore): + namespace = namespace[len(ignore) :] stripped = ignore break else: - stripped = '' + stripped = "" - # we stripped the whole module name? - if not modname: - modname, stripped = stripped, '' + # we stripped the whole namespace name? + if not namespace: + namespace, stripped = stripped, "" - entries = content.setdefault(modname[0].lower(), []) + entries = content.setdefault(namespace[0].lower(), []) - package = modname.split(NS)[0] - if package != modname: - # it's a submodule - if prev_modname == package: - # first submodule - make parent a group head + package = namespace.split(NS)[0] + if package != namespace: + # it's a subnamespace + if prev_namespace == package: + # first subnamespace - make parent a group head entries[-1][1] = 1 - elif not prev_modname.startswith(package): - # submodule without parent in list, add dummy entry - entries.append([stripped + package, 1, '', '', '', '', '']) + elif not prev_namespace.startswith(package): + # subnamespace without parent in list, add dummy entry + entries.append([stripped + package, 1, "", "", "", "", ""]) subtype = 2 else: num_toplevels += 1 subtype = 0 - qualifier = deprecated and _('Deprecated') or '' - entries.append([stripped + modname, subtype, docname, - 'namespace-' + stripped + modname, '', - qualifier, synopsis]) - prev_modname = modname + qualifier = deprecated and _("Deprecated") or "" + entries.append( + [ + stripped + namespace, + subtype, + docname, + "namespace-" + stripped + namespace, + "", + qualifier, + synopsis, + ] + ) + prev_namespace = namespace # apply heuristics when to collapse modindex at page load: - # only collapse if number of toplevel modules is larger than - # number of submodules - collapse = len(modules) - num_toplevels < num_toplevels + # only collapse if number of toplevel namespaces is larger than + # number of subnamespaces + collapse = len(namespaces) - num_toplevels < num_toplevels # sort by first letter content = sorted(content.items()) @@ -626,183 +706,193 @@ def generate(self, docnames=None): class PhpDomain(Domain): - """PHP language domain.""" - name = 'php' - label = 'PHP' + """ + PHP language domain. + """ + + name = "php" + label = "PHP" object_types = { - 'function': ObjType(_('function'), 'func', 'obj'), - 'global': ObjType(_('global variable'), 'global', 'obj'), - 'const': ObjType(_('const'), 'const', 'obj'), - 'method': ObjType(_('method'), 'meth', 'obj'), - 'class': ObjType(_('class'), 'class', 'obj'), - 'attr': ObjType(_('attribute'), 'attr', 'obj'), - 'exception': ObjType(_('exception'), 'exc', 'obj'), - 'namespace': ObjType(_('namespace'), 'ns', 'obj'), - 'interface': ObjType(_('interface'), 'interface', 'obj'), - 'trait': ObjType(_('trait'), 'trait', 'obj'), - 'enum': ObjType(_('enum'), 'enum', 'obj'), - 'case': ObjType(_('case'), 'case', 'obj'), + "function": ObjType(_("function"), "func", "obj"), + "global": ObjType(_("global variable"), "global", "obj"), + "const": ObjType(_("const"), "const", "obj"), + "method": ObjType(_("method"), "meth", "obj"), + "class": ObjType(_("class"), "class", "obj"), + "attr": ObjType(_("attribute"), "attr", "obj"), + "exception": ObjType(_("exception"), "exc", "obj"), + "namespace": ObjType(_("namespace"), "ns", "obj"), + "interface": ObjType(_("interface"), "interface", "obj"), + "trait": ObjType(_("trait"), "trait", "obj"), + "enum": ObjType(_("enum"), "enum", "obj"), + "case": ObjType(_("case"), "case", "obj"), } directives = { - 'function': PhpNamespacelevel, - 'global': PhpGloballevel, - 'const': PhpNamespacelevel, - 'class': PhpClasslike, - 'method': PhpClassmember, - 'staticmethod': PhpClassmember, - 'attr': PhpClassmember, - 'case': PhpClassmember, - 'exception': PhpClasslike, - 'interface': PhpClasslike, - 'trait': PhpClasslike, - 'enum': PhpClasslike, - 'namespace': PhpNamespace, - 'currentmodule': PhpCurrentNamespace, - 'currentnamespace': PhpCurrentNamespace, + "function": PhpNamespacelevel, + "global": PhpGloballevel, + "const": PhpNamespacelevel, + "class": PhpClasslike, + "method": PhpClassmember, + "staticmethod": PhpClassmember, + "attr": PhpClassmember, + "case": PhpClassmember, + "exception": PhpClasslike, + "interface": PhpClasslike, + "trait": PhpClasslike, + "enum": PhpClasslike, + "namespace": PhpNamespace, + "currentmodule": PhpCurrentNamespace, + "currentnamespace": PhpCurrentNamespace, } roles = { - 'func': PhpXRefRole(fix_parens=False), - 'global': PhpXRefRole(), - 'class': PhpXRefRole(), - 'exc': PhpXRefRole(), - 'meth': PhpXRefRole(fix_parens=False), - 'attr': PhpXRefRole(), - 'const': PhpXRefRole(), - 'ns': PhpXRefRole(), - 'obj': PhpXRefRole(), - 'interface': PhpXRefRole(), - 'trait': PhpXRefRole(), - 'enum': PhpXRefRole(), - 'case': PhpXRefRole(), + "func": PhpXRefRole(fix_parens=False), + "global": PhpXRefRole(), + "class": PhpXRefRole(), + "exc": PhpXRefRole(), + "meth": PhpXRefRole(fix_parens=False), + "attr": PhpXRefRole(), + "const": PhpXRefRole(), + "ns": PhpXRefRole(), + "obj": PhpXRefRole(), + "interface": PhpXRefRole(), + "trait": PhpXRefRole(), + "enum": PhpXRefRole(), + "case": PhpXRefRole(), } initial_data = { - 'objects': {}, # fullname -> docname, objtype - 'namespaces': {}, # namespace -> docname, synopsis + "objects": {}, # fullname -> docname, objtype + "namespaces": {}, # namespace -> docname, synopsis } indices = [ PhpNamespaceIndex, ] def clear_doc(self, docname): - for fullname, (fn, _l) in list(self.data['objects'].items()): + for fullname, (fn, _l) in list(self.data["objects"].items()): if fn == docname: - del self.data['objects'][fullname] - for ns, (fn, _x, _x) in list(self.data['namespaces'].items()): + del self.data["objects"][fullname] + for ns, (fn, _x, _x) in list(self.data["namespaces"].items()): if fn == docname: - del self.data['namespaces'][ns] + del self.data["namespaces"][ns] def merge_domaindata(self, docnames, otherdata): - for fullname, (fn, objtype) in otherdata['objects'].items(): + for fullname, (fn, objtype) in otherdata["objects"].items(): if fn in docnames: - self.data['objects'][fullname] = (fn, objtype) - for namespace, data in otherdata['namespaces'].items(): + self.data["objects"][fullname] = (fn, objtype) + for namespace, data in otherdata["namespaces"].items(): if data[0] in docnames: - self.data['namespaces'][namespace] = data + self.data["namespaces"][namespace] = data - def resolve_any_xref(self, env, fromdocname, builder, - target, node, contnode): + def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode): for typ in self.roles: - resolve = self.resolve_xref(env, fromdocname, builder, - typ, target, node, contnode) + resolve = self.resolve_xref( + env, fromdocname, builder, typ, target, node, contnode + ) if resolve: - return [('php:%s' % typ, resolve)] + return [("php:%s" % typ, resolve)] return [] - def resolve_xref(self, env, fromdocname, builder, - typ, target, node, contnode): - if (typ == 'ns' or - typ == 'obj' and target in self.data['namespaces']): - docname, synopsis, deprecated = self.data['namespaces'].get( - target, - ('', '', '') + def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): + if typ == "ns" or typ == "obj" and target in self.data["namespaces"]: + docname, synopsis, deprecated = self.data["namespaces"].get( + target, ("", "", "") ) if not docname: return None else: - title = '%s%s' % (synopsis, - (deprecated and ' (deprecated)' or '')) + title = "%s%s" % (synopsis, (deprecated and " (deprecated)" or "")) return make_refnode( builder, fromdocname, docname, - 'namespace-' + target, + "namespace-" + target, contnode, - title) + title, + ) else: - modname = node.get('php:namespace') - clsname = node.get('php:class') - searchorder = node.hasattr('refspecific') and 1 or 0 - name, obj = self.find_obj(env, modname, clsname, - target, typ, searchorder) + namespace = node.get("php:namespace") + clsname = node.get("php:class") + name, obj = self.find_obj(env, node, namespace, clsname, target, typ) if not obj: return None else: - return make_refnode(builder, fromdocname, obj[0], name, - contnode, name) + return make_refnode(builder, fromdocname, obj[0], name, contnode, name) - def find_obj(self, env, modname, classname, name, type, searchorder=0): + def find_obj(self, env, fromdocnode, namespace, classname, name, type): """ - Find a PHP object for "name", perhaps using the given namespace and/or - classname. + Find a PHP object for "name", using the given namespace and classname. """ - # skip parens - if name[-2:] == '()': + # strip parenthesis + if name[-2:] == "()": name = name[:-2] - if not name: - return None, None - - objects = self.data['objects'] - - newname = None - if searchorder == 1: - if modname and classname and \ - modname + NS + classname + '::' + name in objects: - newname = modname + NS + classname + '::' + name - elif modname and modname + NS + name in objects: - newname = modname + NS + name - elif modname and modname + NS + name in objects: - newname = modname + NS + name - elif classname and classname + '::' + name in objects: - newname = classname + '.' + name - elif classname and classname + '::$' + name in objects: - newname = classname + '::$' + name - elif name in objects: - newname = name + objects = self.data["objects"] + + if name.startswith(NS): + absname = name[1:] else: - if name in objects: - newname = name - elif classname and classname + '::' + name in objects: - newname = classname + '::' + name - elif classname and classname + '::$' + name in objects: - newname = classname + '::$' + name - elif modname and modname + NS + name in objects: - newname = modname + NS + name - elif modname and classname and \ - modname + NS + classname + '::' + name in objects: - newname = modname + NS + classname + '::' + name - elif modname and classname and \ - modname + NS + classname + '::$' + name in objects: - newname = modname + NS + classname + '::$' + name - # special case: object methods - elif type in ('func', 'meth') and '::' not in name and \ - 'object::' + name in objects: - newname = 'object::' + name - if newname is None: - return None, None - return newname, objects[newname] + absname = (namespace + NS if namespace else "") + name + + if absname not in objects and name in objects: + # constants/functions can be namespaced, but allow fallback to global namespace the same way as PHP does + name_type = objects[name][1] + if ( + (name_type == "function" or name_type == "const") + and NS not in name + and "::" not in name + ): + absname = name + else: + if namespace and name.startswith(namespace + NS): + log_info( + fromdocnode, + f"Target {absname} not found - did you mean to write {name[len(namespace + NS):]}?", + ) + else: + log_info( + fromdocnode, + f"Target {absname} not found - did you mean to write {NS + name}?", + ) + absname = name # fallback for BC, might be removed in the next major release + + if absname in objects: + return absname, objects[absname] + + # PHP reserved keywords are never resolved using NS and ignore them when not defined + if name not in [ + "array", + "bool", + "callable", + "false", + "float", + "int", + "iterable", + "mixed", + "never", + "null", + "object", + "parent", + "resource", + "self", + "static", + "string", + "true", + "void", + ]: + log_info(fromdocnode, f"Target {absname} not found") + + return None, None def get_objects(self): - for ns, info in self.data['namespaces'].items(): - yield (ns, ns, 'namespace', info[0], 'namespace-' + ns, 0) - for refname, (docname, type) in self.data['objects'].items(): + for ns, info in self.data["namespaces"].items(): + yield (ns, ns, "namespace", info[0], "namespace-" + ns, 0) + for refname, (docname, type) in self.data["objects"].items(): yield (refname, refname, type, docname, refname, 1) def setup(app): app.add_domain(PhpDomain) - return {'version': sphinx_version, 'parallel_read_safe': True} + return {"version": sphinx_version, "parallel_read_safe": True} diff --git a/test/must-build/Makefile b/test/Makefile similarity index 100% rename from test/must-build/Makefile rename to test/Makefile diff --git a/test/conf.py b/test/conf.py new file mode 100644 index 00000000..2be6ab33 --- /dev/null +++ b/test/conf.py @@ -0,0 +1,17 @@ +import sys, os + +sys.path.append(os.path.abspath("..")) + +extensions = [ + "sphinxcontrib.phpdomain", + "myst_parser", +] + +myst_enable_extensions = ["colon_fence"] + +source_suffix = ".md" +master_doc = "index" + +exclude_patterns = ["_build", "log.md"] + +html_theme = "default" diff --git a/test/unit/index.md b/test/index.md similarity index 100% rename from test/unit/index.md rename to test/index.md diff --git a/test/log.html b/test/log.html new file mode 100644 index 00000000..b6a2cb37 --- /dev/null +++ b/test/log.html @@ -0,0 +1,61 @@ + +
+
+

Invalid domain type

+
+
+

Invalid signature

+
+
+ + x(); + +
+
+
+
+
+

Unresolved references

+
    +
  • +

    + + Foo\Aa + +

    +
  • +
  • +

    + + Foo\A::simplifyy + +

    +
  • +
+ + + + +
+
+
diff --git a/test/log.md b/test/log.md new file mode 100644 index 00000000..fd119717 --- /dev/null +++ b/test/log.md @@ -0,0 +1,25 @@ +# Invalid domain type + +:::{php:namespacee} Foo +::: + +# Invalid signature + +:::{php:method} x(); +::: + +# Unresolved references + +- {php:class}`Foo\Aa` + +- {php:meth}`Foo\A::simplifyy` + +:::{php:namespace} Foo +::: + +- {php:meth}`Foo\A::simplify` + +:::{php:namespace} Fooo +::: + +- {php:meth}`Foo\A::simplify` diff --git a/test/log.txt b/test/log.txt new file mode 100644 index 00000000..12ca82b9 --- /dev/null +++ b/test/log.txt @@ -0,0 +1,13 @@ +test/log.md:3: WARNING: Unknown directive type: 'php:namespacee' [myst.directive_unknown] +test/log.md:8: WARNING: [phpdomain] Invalid signature +test/log.md:13: [phpdomain] Target Foo\Aa not found +test/log.md:15: [phpdomain] Target Foo\A::simplifyy not found +test/log.md:20: [phpdomain] Target Foo\Foo\A::simplify not found - did you mean to write A::simplify? +test/log.md:25: [phpdomain] Target Fooo\Foo\A::simplify not found - did you mean to write \Foo\A::simplify? +test/ns.md:48: [phpdomain] Target A2::simplify not found +test/ns.md:53: [phpdomain] Target Bar2\A::simplify not found +test/rst_doc.md:506: [phpdomain] Target OtherLibrary\int|string|ReturnedClass|\LibraryName\SubPackage\SubpackageInterface|null not found +test/rst_doc2.md:11: [phpdomain] Target Imagine\Image\ImageInterface::draw not found +test/rst_doc2.md:17: [phpdomain] Target Imagine\Image\PointInterface not found +test/rst_doc2.md:17: [phpdomain] Target Imagine\Image\BoxInterface not found +test/rst_doc2.md:17: [phpdomain] Target Imagine\Image\Color not found diff --git a/test/must-build/make.bat b/test/make.bat similarity index 100% rename from test/must-build/make.bat rename to test/make.bat diff --git a/test/unit/method.html b/test/method.html similarity index 100% rename from test/unit/method.html rename to test/method.html diff --git a/test/unit/method.md b/test/method.md similarity index 100% rename from test/unit/method.md rename to test/method.md diff --git a/test/must-build/conf.py b/test/must-build/conf.py deleted file mode 100644 index e3bde517..00000000 --- a/test/must-build/conf.py +++ /dev/null @@ -1,210 +0,0 @@ -# -*- coding: utf-8 -*- -# -# sphinxcontrib-rubydomain-acceptancetest documentation build configuration file, created by -# sphinx-quickstart on Sun Apr 25 13:27:18 2010. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath('..')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinxcontrib.phpdomain'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'sphinxcontrib-phpdomain-acceptancetest' -copyright = u'2011, Mark Story' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '0.1' -# The full version, including alpha/beta/rc tags. -release = '0.1' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - -# Output file base name for HTML help builder. -htmlhelp_basename = 'sphinxcontrib-phpdomain-acceptancetestdoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'sphinxcontrib-phpdomain-acceptancetest.tex', u'sphinxcontrib-phpdomain-acceptancetest Documentation', - u'Mark Story', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'sphinxcontrib-phpdomain-acceptancetest', u'sphinxcontrib-phpdomain-acceptancetest Documentation', - [u'Mark Story'], 1) -] diff --git a/test/ns.html b/test/ns.html new file mode 100644 index 00000000..cbfc2d8f --- /dev/null +++ b/test/ns.html @@ -0,0 +1,171 @@ + +
+
+ +

Simple NS

+
+
+ + class + + + Foo\ + + + A + + +
+
+
+
+
+ + Foo\A:: + + + simplify + + ( + ) + +
+
+
+
+

Cross linking

+ +
+
+
+ +

NS can be changed

+
+
+ + class + + + Foo\Bar\ + + + A + + +
+
+
+
+
+ + Foo\Bar\A:: + + + simplify + + ( + ) + +
+
+
+ +
+
+ + class + + + Bar\ + + + A + + +
+
+
+
+
+ + Bar\A:: + + + simplify + + ( + ) + +
+
+
+
+

Cross linking

+ +
+
+
+

NS must not be guessed

+
+

These cross references must not have a link as the target methods are not defined.

+
+
    +
  • +

    + + A2::simplify + +

    +
  • +
+ +
    +
  • +

    + + A::simplify + +

    +
  • +
+
+
+
diff --git a/test/ns.md b/test/ns.md new file mode 100644 index 00000000..fc594651 --- /dev/null +++ b/test/ns.md @@ -0,0 +1,53 @@ +# Simple NS + +:::{php:namespace} Foo +::: + +:::{php:class} A +::: + +:::{php:method} simplify() +::: + +## Cross linking + +- {php:meth}`A::simplify` + +# NS can be changed + +:::{php:namespace} Foo\Bar +::: + +:::{php:class} A +::: + +:::{php:method} simplify() +::: + +:::{php:namespace} Bar +::: + +:::{php:class} A +::: + +:::{php:method} simplify() +::: + +## Cross linking + +- {php:meth}`A::simplify` +- {php:meth}`\Foo\Bar\A::simplify` +- {php:meth}`\Bar\A::simplify` + +# NS must not be guessed + +:::note +These cross references must not have a link as the target methods are not defined. +::: + +- {php:meth}`\A2::simplify` + +:::{php:namespace} Bar2 +::: + +- {php:meth}`A::simplify` diff --git a/test/unit/requirements.txt b/test/requirements.txt similarity index 100% rename from test/unit/requirements.txt rename to test/requirements.txt diff --git a/test/rst_doc.html b/test/rst_doc.html new file mode 100644 index 00000000..e6dfa1af --- /dev/null +++ b/test/rst_doc.html @@ -0,0 +1,2201 @@ + +
+
+

Acceptance tests for PHPdomain

+
+

Globals

+
+
+ + $global_var + + +
+
+

A global variable

+
+
+
+
+ + constant + + + SOME_CONSTANT + + +
+
+

A global constant

+
+
+
+
+ + constant + + + VALUE + + +
+
+

A global constant

+
+
+
+
in_array(needle, haystack)
+
+

Checks for needle in haystack.

+
+
Parameters:
+
+
    +
  • +

    needle – The element to search for.

    +
  • +
  • +

    haystack (array) – The array to search.

    +
  • +
+
+
Returns:
+
+

Element exists in array.

+
+
Return type:
+
+

+ + + bool + + +

+
+
+
+
+
+
+

Classes

+
+
+ + class + + + DateTime + + +
+
+

Datetime class

+
+
setDate($year, $month, $day)
+
+

Set the date in the datetime object

+
+
Parameters:
+
+
    +
  • +

    $year (int) – The year.

    +
  • +
  • +

    $month (int) – The month.

    +
  • +
  • +

    $day (int) – The day.

    +
  • +
+
+
+
+
+
+
setTime($hour, $minute[, $second])
+
+

Set the time

+
+
Parameters:
+
+
    +
  • +

    $hour (int) – The hour

    +
  • +
  • +

    $minute (int) – The minute

    +
  • +
  • +

    $second (int) – The second

    +
  • +
+
+
+
+
+
+
+ + public + + + static + + + getLastErrors + + ( + ) + +
+
+

Returns the warnings and errors

+
+
Returns:
+
+

array Returns array containing info about warnings and errors.

+
+
+
+
+
+
+ + constant + + + ATOM + + +
+
+

Y-m-dTH:i:sP

+
+
+
+
+ + property + + + testattr + + +
+
+

Value of some attribute

+
+
+
+
+
+
+ + class + + + OtherClass + + +
+
+

Another class

+
+
+
+
OtherClass::update($arg='', $arg2=[], $arg3=[])
+
+

Update something.

+
+
+
+
+ + property + + + OtherClass::$ + + + nonIndentedAttribute + + +
+
+

This attribute wasn’t indented

+
+
+
+
+ + constant + + + OtherClass:: + + + NO_INDENT + + +
+
+

This class constant wasn’t indented

+
+
+
+
+ + static + + + OtherClass:: + + + staticMethod + + +
+
+

A static method.

+
+
+
+
+

Exceptions

+
+
+ + exception + + + InvalidArgumentException + + +
+
+

Throw when you get an argument that is bad.

+
+
+
+
+

Interfaces

+
+
+ + interface + + + DateTimeInterface + + +
+
+

Datetime interface

+
+
setDate($year, $month, $day)
+
+

Set the date in the datetime object

+
+
Parameters:
+
+
    +
  • +

    $year (int) – The year.

    +
  • +
  • +

    $month (int) – The month.

    +
  • +
  • +

    $day (int) – The day.

    +
  • +
+
+
+
+
+
+
setTime($hour, $minute[, $second])
+
+

Set the time

+
+
Parameters:
+
+
    +
  • +

    $hour (int) – The hour

    +
  • +
  • +

    $minute (int) – The minute

    +
  • +
  • +

    $second (int) – The second

    +
  • +
+
+
+
+
+
+
+ + constant + + + ATOM + + +
+
+

Y-m-dTH:i:sP

+
+
+
+
+ + property + + + testattr + + +
+
+

Value of some attribute

+
+
+
+
+
+
+ + interface + + + OtherInterface + + +
+
+

Another interface

+
+
+
+
+

Traits

+
+
+ + trait + + + LogTrait + + +
+
+

A logging trait

+
+
log($level, $string)
+
+

A method description.

+
+
+
+
+
+
+

More globals after classes

+
+
+ + $other_global_var + + +
+
+

A global variable

+
+
+
+
strpos($needle, $haystack)
+
+

Position of needle in haystack

+
+
+
+

Test Case - Global symbols with no namespaces

+

+ + + $global_var + + +

+

+ + + $other_global_var + + +

+

+ + + SOME_CONSTANT + + +

+

+ + + in_array + + +

+

+ + + strpos + + +

+

+ + + DateTime + + +

+

+ + + DateTime::setTime() + + +

+

+ + + DateTime::getLastErrors() + + +

+

+ + + DateTime::setDate() + + +

+

+ + + DateTime::ATOM + + +

+

+ + + DateTime::$testattr + + +

+

+ + + OtherClass::update + + +

+

+ + + OtherClass::$nonIndentedAttribute + + +

+

+ + + OtherClass::NO_INDENT + + +

+

+ + + OtherClass::staticMethod + + +

+

+ + + InvalidArgumentException + + +

+

+ + + DateTimeInterface + + +

+

+ + + DateTimeInterface::setTime() + + +

+

+ + + setDate() + + +

+

+ + + DateTimeInterface::ATOM + + +

+

+ + + DateTimeInterface::$testattr + + +

+

+ + + OtherInterface + + +

+

+ + + LogTrait + + +

+

+ + + LogTrait::log() + + +

+
+ +
+
+ +

Namespaced elements

+
+
LibraryName\namespaced_function($one[, $two])
+
+

A function in a namespace

+
+
Parameters:
+
+
    +
  • +

    $one (string) – First parameter.

    +
  • +
  • +

    $two (string) – Second parameter.

    +
  • +
+
+
+
+
+
+
+ + constant + + + LibraryName\ + + + NS_CONST + + +
+
+

A constant in a namespace

+
+
+
+
+ + exception + + + LibraryName\ + + + NamespaceException + + +
+
+

This exception is in a namespace.

+
+
+
+
+ + class + + + LibraryName\ + + + LibraryClass + + +
+
+

A class in a namespace

+
+
+ + LibraryClass:: + + + instanceMethod + + ( + + $foo + + ) + +
+
+

An instance method

+
+
+
+
+ + constant + + + TEST_CONST + + +
+
+

Test constant

+
+
+
+
+ + property + + + property + + +
+
+

A property!

+
+
+
+
+
+
+ + static + + + LibraryName\LibraryClass:: + + + staticMethod + + +
+
+

A static method in a namespace

+
+
+
+
+ + class + + + LibraryName\ + + + NamespaceClass + + +
+
+

A class in the namespace, no indenting on children

+
+
+
+
LibraryName\NamespaceClass::firstMethod($one, $two)
+
+

A normal instance method.

+
+
+
+
+ + property + + + LibraryName\NamespaceClass::$ + + + property + + +
+
+

A property

+
+
+
+
+ + constant + + + LibraryName\NamespaceClass:: + + + NAMESPACE_CONST + + +
+
+

Const on class in namespace

+
+
+
+
+ + static + + + LibraryName\NamespaceClass:: + + + namespaceStatic + + ( + + $foo + + ) + +
+
+

A static method here.

+
+
+
+
+ + final + + + class + + + LibraryName\ + + + LibraryClassFinal + + +
+
+

A final class

+
+
+
+
publicLibraryName\LibraryClassFinal::firstMethod($one, $two)
+
+

A public instance method.

+
+
+
+
protectedLibraryName\LibraryClassFinal::secondMethod($one, $two)
+
+

A protected instance method.

+
+
+
+
privateLibraryName\LibraryClassFinal::thirdMethod($one, $two)
+
+

A private instance method.

+
+
+
+
staticLibraryName\LibraryClassFinal::fourthMethod($one, $two)
+
+

A static method.

+
+
+
+
protectedfinalLibraryName\LibraryClassFinal::fifthMethod($one, $two)
+
+

A protected final method.

+
+
+
+
+ + abstract + + + class + + + LibraryName\ + + + LibraryClassAbstract + + +
+
+

An abstract class

+
+
+
+
+ + interface + + + LibraryName\ + + + LibraryInterface + + +
+
+

A interface in a namespace

+
+
+ + instanceMethod + + ( + + $foo + + ) + +
+
+
+

An instance method

+
+
+
+
+ + trait + + + LibraryName\ + + + TemplateTrait + + +
+
+

A trait in a namespace

+
+
+ + render + + ( + + $template + + ) + +
+
+
+

Render a template.

+
+
+
+

Test Case - not including namespace

+

Within a namespace context you don’t need to include the namespace in links.

+

+ + + LibraryName + + +

+

+ + + namespaced_function() + + +

+

+ + + NS_CONST + + +

+

+ + + LibraryClass + + +

+

+ + + LibraryClass::instanceMethod + + +

+

+ + + LibraryClass::staticMethod() + + +

+

+ + + LibraryClass::$property + + +

+

+ + + LibraryClass::TEST_CONST + + +

+

+ + + OtherClass + + +

+

+ + + ThirdClass + + +

+

+ + + NamespaceClass + + +

+

+ + + NamespaceClass::firstMethod + + +

+

+ + + NamespaceClass::$property + + +

+

+ + + NamespaceClass::NAMESPACE_CONST + + +

+

+ + + LibraryClassFinal + + +

+

+ + + LibraryClassFinal::firstMethod + + +

+

+ + + LibraryClassFinal::secondMethod + + +

+

+ + + LibraryClassFinal::thirdMethod + + +

+

+ + + LibraryClassFinal::fourthMethod + + +

+

+ + + LibraryClassFinal::fifthMethod + + +

+

+ + + LibraryInterface + + +

+

+ + + LibraryInterface::instanceMethod + + +

+

+ + + NamespaceException + + +

+

+ + + TemplateTrait + + +

+

+ + + TemplateTrait::render() + + +

+
+ +
+

Test Case - global access

+

+ + + DateTime + + +

+

+ + + DateTime::setTime() + + +

+

+ + + $global_var + + +

+

+ + + SOME_CONSTANT + + +

+

+ + + in_array() + + +

+

+ + + LibraryName\LibraryClass::$property + + +

+

$property Should not be prefixed with classname.

+

+ + + LibraryName\LibraryClass::TEST_CONST + + +

+

+ + + LibraryName\NS_CONST + + +

+

+ + + DateTimeInterface + + +

+

+ + + DateTimeInterface::setTime() + + +

+
+
+
+

Any Cross Ref

+

+ + + LibraryName\NS_CONST + + +

+

+ + + DateTimeInterface::setTime() + + +

+
+
+ +

Nested namespaces

+
+
+ + exception + + + LibraryName\SubPackage\ + + + NestedNamespaceException + + +
+
+

In a package

+
+
+
+
+ + class + + + LibraryName\SubPackage\ + + + SubpackageClass + + +
+
+

A class in a subpackage

+
+
+
+
+ + interface + + + LibraryName\SubPackage\ + + + SubpackageInterface + + +
+
+

A class in a subpackage

+
+
+ +
+
+ +

Return Types

+
+
+ + class + + + OtherLibrary\ + + + ReturningClass + + +
+
+

A class to do some returning.

+
+
+ + returnClassFromSameNamespace + + ( + ) + +
+
+
+
Returns:
+
+

An object instance of a class from the same namespace.

+
+
Return type:
+
+

+ + + + ReturnedClass + + + +

+
+
+
+
+
+
+ + returnClassFromOtherNamespace + + ( + ) + +
+
+
+
Returns:
+
+

An object instance of a class from another namespace.

+
+
Return type:
+
+

+ + + + LibraryName\SubPackage\SubpackageInterface + + + +

+
+
+
+
+
+
+ + returnClassConstant + + ( + ) + +
+
+
+
Returns:
+
+

The value of a specific class constant.

+
+
Return type:
+
+

+ + + + LibraryName\NamespaceClass::NAMESPACE_CONST + + + +

+
+
+
+
+
+
+ + returnGlobalConstant + + ( + ) + +
+
+
+
Returns:
+
+

The value of a specific global constant. # TODO link is not working without “\”

+
+
Return type:
+
+

+ + + + SOME_CONSTANT + + + +

+
+
+
+
+
+
+ + returnExceptionInstance + + ( + ) + +
+
+
+
Returns:
+
+

An instance of an exception.

+
+
Return type:
+
+

+ + + + InvalidArgumentException + + + +

+
+
+
+
+
+
+ + returnScalarType + + ( + ) + +
+
+
+
Returns:
+
+

A scalar string type.

+
+
Return type:
+
+

+ + + string + + +

+
+
+
+
+
+
+ + returnUnionType + + ( + ) + +
+
+
+
Returns:
+
+

Any of a whole bunch of things specified with a PHP 8 union type.

+
+
Return type:
+
+

+ + + int|string|ReturnedClass|\LibraryName\SubPackage\SubpackageInterface|null + + +

+
+
+
+
+
+
+
+
+ + class + + + OtherLibrary\ + + + ReturnedClass + + +
+
+

A class to return.

+
+
+
+
+

Enums

+
+ +

Basic Enumerations

+
+
+ + enum + + + Example\Basic\ + + + Suit + + +
+
+

In playing cards, a suit is one of the categories into which the cards of a +deck are divided.

+
+
+ + case + + + Hearts + + +
+
+
+
+
+ + case + + + Diamonds + + +
+
+
+
+
+ + case + + + Clubs + + +
+
+
+
+
+ + case + + + Spades + + +
+
+
+
+
+
+
+ +

Backed Enumerations

+
+
+ + enum + + + Example\Backed\ + + + Suit + + + + + string + + + +
+
+

In playing cards, a suit is one of the categories into which the cards of a +deck are divided.

+
+
+ + case + + + Hearts + + + + + 'H' + + + +
+
+
+
+
+ + case + + + Diamonds + + + + + 'D' + + + +
+
+
+
+
+ + case + + + Clubs + + + + + 'C' + + + +
+
+
+
+
+ + case + + + Spades + + + + + 'S' + + + +
+
+
+
+
+
+
+ +

Advanced Enumerations

+
+
+ + enum + + + Example\Advanced\ + + + Suit + + + + + string + + + +
+
+

In playing cards, a suit is one of the categories into which the cards of a +deck are divided.

+
+
+ + case + + + Hearts + + + + + 'H' + + + +
+
+
+
+
+ + case + + + Diamonds + + + + + 'D' + + + +
+
+
+
+
+ + case + + + Clubs + + + + + 'C' + + + +
+
+
+
+
+ + case + + + Spades + + + + + 'S' + + + +
+
+
+
+
+ + color + + ( + ) + + + + string + + + +
+
+

Returns “red” for hearts and diamonds, “black” for clubs and spades.

+
+
+
+
+ + static + + + values + + + + + string[] + + + +
+
+

Returns an array of the values of all the cases on this enum.

+
+
+
+
+ + constant + + + Roses + + + + + Hearts + + + +
+
+

An alias for Suit::Hearts.

+
+
+
+
+ + constant + + + Bells + + + + + Diamonds + + + +
+
+

An alias for Suit::Diamonds.

+
+
+
+
+ + constant + + + Acorns + + + + + Clubs + + + +
+
+

An alias for Suit::Clubs.

+
+
+
+
+ + constant + + + Shields + + + + + Spades + + + +
+
+

An alias for Suit::Spades.

+
+
+
+
+
+ +
+
+
+
diff --git a/test/must-build/test_doc.rst b/test/rst_doc.md similarity index 76% rename from test/must-build/test_doc.rst rename to test/rst_doc.md index 862936a5..d29c7c8d 100644 --- a/test/must-build/test_doc.rst +++ b/test/rst_doc.md @@ -1,3 +1,4 @@ +```{eval-rst} Acceptance tests for PHPdomain ############################## @@ -23,7 +24,7 @@ Globals :param needle: The element to search for. :param array haystack: The array to search. :returns: Element exists in array. - :returntype: boolean + :returntype: bool Classes ======= @@ -142,7 +143,7 @@ More globals after classes A global variable -.. php:global:: strpos($needle, $haystack) +.. php:function:: strpos($needle, $haystack) Position of needle in haystack @@ -162,17 +163,17 @@ Test Case - Global symbols with no namespaces :php:class:`DateTime` -:php:func:`DateTime::setTime()` +:php:meth:`DateTime::setTime()` -:php:func:`DateTime::getLastErrors()` +:php:meth:`DateTime::getLastErrors()` -:php:func:`DateTime::setDate()` +:php:meth:`DateTime::setDate()` -:php:func:`DateTime::ATOM` +:php:const:`DateTime::ATOM` -:php:func:`DateTime::$testattr` +:php:attr:`DateTime::$testattr` -:php:func:`OtherClass::update` +:php:meth:`OtherClass::update` :php:attr:`OtherClass::$nonIndentedAttribute` @@ -184,26 +185,26 @@ Test Case - Global symbols with no namespaces :php:interface:`DateTimeInterface` -:php:func:`DateTimeInterface::setTime()` +:php:meth:`DateTimeInterface::setTime()` -:php:func:`~DateTimeInterface::setDate()` +:php:meth:`~DateTimeInterface::setDate()` -:php:func:`DateTimeInterface::ATOM` +:php:const:`DateTimeInterface::ATOM` -:php:func:`DateTimeInterface::$testattr` +:php:attr:`DateTimeInterface::$testattr` -:php:func:`OtherInterface` +:php:interface:`OtherInterface` :php:trait:`LogTrait` -:php:func:`LogTrait::log()` +:php:meth:`LogTrait::log()` Test Case - Prefix less links ----------------------------- The following links should not be prefixed with a classname. -:php:func:`~DateTime::setDate()` +:php:meth:`~DateTime::setDate()` :php:attr:`~DateTime::$testattr` @@ -336,9 +337,9 @@ Within a namespace context you don't need to include the namespace in links. :php:const:`LibraryClass::TEST_CONST` -:php:class:`LibraryName\\OtherClass` +:php:class:`OtherClass` -:php:class:`LibraryName\\ThirdClass` +:php:class:`ThirdClass` :php:class:`NamespaceClass` @@ -368,22 +369,20 @@ Within a namespace context you don't need to include the namespace in links. :php:trait:`TemplateTrait` -:php:trait:`LibraryName\\TemplateTrait` - -:php:func:`LibraryName\\TemplateTrait::render()` +:php:meth:`TemplateTrait::render()` Test Case - Links with prefix trimming -------------------------------------- All of the following links should not be prefixed with a namespace. -:php:interface:`~LibraryName\\LibraryInterface` +:php:interface:`~LibraryInterface` -:php:class:`~LibraryName\\LibraryClass` +:php:class:`~LibraryClass` -:php:trait:`~LibraryName\\TemplateTrait` +:php:trait:`~TemplateTrait` -:php:exc:`~LibraryName\\NamespaceException` +:php:exc:`~NamespaceException` All of the following links should not be prefixed with a classname. @@ -397,25 +396,27 @@ All of the following links should not be prefixed with a classname. Test Case - global access ------------------------- -:php:class:`DateTime` +:php:class:`\\DateTime` -:php:func:`DateTime::setTime()` +:php:func:`\\DateTime::setTime()` :php:global:`$global_var` :php:const:`SOME_CONSTANT` -:php:attr:`LibraryName\\LibraryClass::$property` +:php:func:`in_array()` -:php:attr:`~LibraryName\\LibraryClass::$property` Should not be prefixed with classname. +:php:attr:`\\LibraryName\\LibraryClass::$property` -:php:const:`LibraryName\\LibraryClass::TEST_CONST` +:php:attr:`~\\LibraryName\\LibraryClass::$property` Should not be prefixed with classname. -:php:const:`LibraryName\\NS_CONST` +:php:const:`\\LibraryName\\LibraryClass::TEST_CONST` -:php:interface:`DateTimeInterface` +:php:const:`\\LibraryName\\NS_CONST` -:php:func:`DateTimeInterface::setTime()` +:php:interface:`\\DateTimeInterface` + +:php:func:`\\DateTimeInterface::setTime()` Any Cross Ref ============= @@ -446,15 +447,19 @@ Test Case - Test subpackage links :php:ns:`LibraryName\\SubPackage` +:php:ns:`\\LibraryName\\SubPackage` + :php:class:`SubpackageClass` -:php:class:`LibraryName\\SubPackage\\SubpackageClass` +:php:class:`\\LibraryName\\SubPackage\\SubpackageClass` :php:interface:`SubpackageInterface` -:php:class:`LibraryName\\SubPackage\\SubpackageInterface` +:php:class:`\\LibraryName\\SubPackage\\SubpackageInterface` + +:php:exc:`NestedNamespaceException` -:php:exc:`LibraryName\\SubPackage\\NestedNamespaceException` +:php:exc:`\\LibraryName\\SubPackage\\NestedNamespaceException` Return Types ============ @@ -468,27 +473,27 @@ Return Types .. php:method:: returnClassFromSameNamespace() :returns: An object instance of a class from the same namespace. - :returntype: OtherLibrary\\ReturnedClass + :returntype: ReturnedClass .. php:method:: returnClassFromOtherNamespace() :returns: An object instance of a class from another namespace. - :returntype: LibraryName\\SubPackage\\SubpackageInterface + :returntype: \\LibraryName\\SubPackage\\SubpackageInterface .. php:method:: returnClassConstant() :returns: The value of a specific class constant. - :returntype: LibraryName\\NamespaceClass::NAMESPACE_CONST + :returntype: \\LibraryName\\NamespaceClass::NAMESPACE_CONST .. php:method:: returnGlobalConstant() - :returns: The value of a specific global constant. + :returns: The value of a specific global constant. # TODO link is not working without "\\" :returntype: SOME_CONSTANT .. php:method:: returnExceptionInstance() :returns: An instance of an exception. - :returntype: InvalidArgumentException + :returntype: \\InvalidArgumentException .. php:method:: returnScalarType() @@ -498,7 +503,7 @@ Return Types .. php:method:: returnUnionType() :returns: Any of a whole bunch of things specified with a PHP 8 union type. - :returntype: int|string|OtherLibrary\\ReturnedClass|LibraryName\\SubPackage\\SubpackageInterface|null + :returntype: int|string|ReturnedClass|\\LibraryName\\SubPackage\\SubpackageInterface|null .. php:class:: ReturnedClass @@ -562,19 +567,19 @@ Advanced Enumerations .. php:const:: Roses() : Hearts - An alias for :php:case:`Example\\Advanced\\Suit::Hearts`. + An alias for :php:case:`Suit::Hearts`. .. php:const:: Bells : Diamonds - An alias for :php:case:`Example\\Advanced\\Suit::Diamonds`. + An alias for :php:case:`Suit::Diamonds`. .. php:const:: Acorns : Clubs - An alias for :php:case:`Example\\Advanced\\Suit::Clubs`. + An alias for :php:case:`Suit::Clubs`. .. php:const:: Shields : Spades - An alias for :php:case:`Example\\Advanced\\Suit::Spades`. + An alias for :php:case:`Suit::Spades`. Enumeration Links ----------------- @@ -582,50 +587,51 @@ Enumeration Links Links to Basic Enumeration Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:php:enum:`Example\\Basic\\Suit` +:php:enum:`\\Example\\Basic\\Suit` -:php:case:`Example\\Basic\\Suit::Hearts` +:php:case:`\\Example\\Basic\\Suit::Hearts` -:php:case:`Example\\Basic\\Suit::Diamonds` +:php:case:`\\Example\\Basic\\Suit::Diamonds` -:php:case:`Example\\Basic\\Suit::Clubs` +:php:case:`\\Example\\Basic\\Suit::Clubs` -:php:case:`Example\\Basic\\Suit::Spades` +:php:case:`\\Example\\Basic\\Suit::Spades` Links to Backed Enumeration Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:php:enum:`Example\\Backed\\Suit` +:php:enum:`\\Example\\Backed\\Suit` -:php:case:`Example\\Backed\\Suit::Hearts` +:php:case:`\\Example\\Backed\\Suit::Hearts` -:php:case:`Example\\Backed\\Suit::Diamonds` +:php:case:`\\Example\\Backed\\Suit::Diamonds` -:php:case:`Example\\Backed\\Suit::Clubs` +:php:case:`\\Example\\Backed\\Suit::Clubs` -:php:case:`Example\\Backed\\Suit::Spades` +:php:case:`\\Example\\Backed\\Suit::Spades` Links to Advanced Enumeration Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -:php:enum:`Example\\Advanced\\Suit` +:php:enum:`Suit` -:php:case:`Example\\Advanced\\Suit::Hearts` +:php:case:`Suit::Hearts` -:php:case:`Example\\Advanced\\Suit::Diamonds` +:php:case:`Suit::Diamonds` -:php:case:`Example\\Advanced\\Suit::Clubs` +:php:case:`Suit::Clubs` -:php:case:`Example\\Advanced\\Suit::Spades` +:php:case:`Suit::Spades` -:php:meth:`Example\\Advanced\\Suit::color` +:php:meth:`Suit::color` -:php:meth:`Example\\Advanced\\Suit::values` +:php:meth:`Suit::values` -:php:const:`Example\\Advanced\\Suit::Roses` +:php:const:`Suit::Roses` -:php:const:`Example\\Advanced\\Suit::Bells` +:php:const:`Suit::Bells` -:php:const:`Example\\Advanced\\Suit::Acorns` +:php:const:`Suit::Acorns` -:php:const:`Example\\Advanced\\Suit::Shields` +:php:const:`Suit::Shields` +``` diff --git a/test/rst_doc2.html b/test/rst_doc2.html new file mode 100644 index 00000000..cf7f78f9 --- /dev/null +++ b/test/rst_doc2.html @@ -0,0 +1,100 @@ + +
+
+

Top Level Namespace

+

namespace Imagine\Draw

+ +
+
+ + class + + + Imagine\Draw\ + + + DrawerInterface + + +
+
+
+

Instance of this interface is returned by Imagine\Image\ImageInterface::draw.

+
+
Imagine\Draw\DrawerInterface::arc(PointInterface$center, BoxInterface$size, $start, $end, Color$color)
+
+

Draws an arc on a starting at a given x, y coordinates under a given start and end angles

+
+
Parameters:
+
+
    +
  • +

    $center (Imagine\Image\PointInterface) – Center of the arc.

    +
  • +
  • +

    $size (Imagine\Image\BoxInterface) – Size of the bounding box.

    +
  • +
  • +

    $start (int) – Start angle.

    +
  • +
  • +

    $end (int) – End angle.

    +
  • +
  • +

    $color (Imagine\Image\Color) – Line color.

    +
  • +
+
+
Throws:
+
+

\Imagine\Exception\RuntimeException

+
+
Returns:
+
+

DrawerInterface

+
+
+
+
+
+

Re-used namespace

+

No indexing errors or links should point to this namespace.

+
+
+ + class + + + LibraryName\ + + + ThirdClass + + +
+
+

Another class in a currentmodule block

+
+
+

No indexing errors or links should point to this namespace.

+
+
+ + class + + + LibraryName\ + + + OtherClass + + +
+
+

Another class in a reused namespace

+
+
+
+
+
+
diff --git a/test/must-build/test_doc2.rst b/test/rst_doc2.md similarity index 60% rename from test/must-build/test_doc2.rst rename to test/rst_doc2.md index 2da3f00c..79b7e168 100644 --- a/test/must-build/test_doc2.rst +++ b/test/rst_doc2.md @@ -1,3 +1,4 @@ +```{eval-rst} Top Level Namespace ################### @@ -7,21 +8,21 @@ namespace ``Imagine\Draw`` .. php:class:: DrawerInterface -Instance of this interface is returned by :php:meth:`Imagine\Image\ImageInterface::draw`. +Instance of this interface is returned by :php:meth:`\\Imagine\\Image\\ImageInterface::draw`. .. php:method:: arc(PointInterface $center, BoxInterface $size, $start, $end, Color $color) Draws an arc on a starting at a given x, y coordinates under a given start and end angles - :param Imagine\Image\PointInterface $center: Center of the arc. - :param Imagine\Image\BoxInterface $size: Size of the bounding box. - :param integer $start: Start angle. - :param integer $end: End angle. - :param Imagine\Image\Color $color: Line color. + :param \\Imagine\\Image\\PointInterface $center: Center of the arc. + :param \\Imagine\\Image\\BoxInterface $size: Size of the bounding box. + :param int $start: Start angle. + :param int $end: End angle. + :param \\Imagine\\Image\\Color $color: Line color. - :throws: Imagine\Exception\RuntimeException + :throws: \\Imagine\\Exception\\RuntimeException - :returns: Imagine\Draw\DrawerInterface + :returns: DrawerInterface Re-used namespace ================= @@ -41,4 +42,4 @@ No indexing errors or links should point to this namespace. .. php:class:: OtherClass Another class in a reused namespace - +``` diff --git a/test/rst_index.html b/test/rst_index.html new file mode 100644 index 00000000..fc236e7e --- /dev/null +++ b/test/rst_index.html @@ -0,0 +1,110 @@ + +
+
+

Welcome to sphinxcontrib-phpdomain-acceptancetest’s documentation!

+

Contents:

+ +
+
+

Indices and tables

+ +
+
+
diff --git a/test/must-build/index.rst b/test/rst_index.md similarity index 80% rename from test/must-build/index.rst rename to test/rst_index.md index cc97f676..798ea246 100644 --- a/test/must-build/index.rst +++ b/test/rst_index.md @@ -1,3 +1,4 @@ +```{eval-rst} Welcome to sphinxcontrib-phpdomain-acceptancetest's documentation! =================================================================== @@ -6,9 +7,9 @@ Contents: .. toctree:: :maxdepth: 2 - test_doc - test_doc2 - test_nesting_regression + rst_doc + rst_doc2 + rst_nesting_regression Indices and tables ================== @@ -16,4 +17,4 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` - +``` diff --git a/test/rst_nesting_regression.html b/test/rst_nesting_regression.html new file mode 100644 index 00000000..8661e110 --- /dev/null +++ b/test/rst_nesting_regression.html @@ -0,0 +1,68 @@ + +
+
+

Nested method Regression

+

Test nested methods to ensure page generation doesn’t hard fail.

+
+
+ + Largo_Byline:: + + + populate_variables + + ( + ) + +
+
+
+
+

Set us up the vars

+
+
+
    +
  • +

    ‘post_id’: an integer post ID

    +
  • +
  • +

    ‘exclude_date’: boolean whether or not to include the date in the byline

    +
  • +
+
+
+
+
param array $args:
+
+

Associative array containing following keys:

+
+
+
+
+
+
+ + Largo_Byline:: + + + generate_byline + + ( + ) + +
+
+

this creates the byline text and adds it to $this->output

+
+
See:
+
+

$output $reates this

+
+
+
+
+
+
+
+
+
diff --git a/test/must-build/test_nesting_regression.rst b/test/rst_nesting_regression.md similarity index 96% rename from test/must-build/test_nesting_regression.rst rename to test/rst_nesting_regression.md index e4eb4d63..54d9cabe 100644 --- a/test/must-build/test_nesting_regression.rst +++ b/test/rst_nesting_regression.md @@ -1,3 +1,4 @@ +```{eval-rst} Nested method Regression ======================== @@ -17,3 +18,4 @@ Test nested methods to ensure page generation doesn't hard fail. this creates the byline text and adds it to $this->output :see: $output $reates this +``` diff --git a/test/unit/Makefile b/test/unit/Makefile deleted file mode 100644 index f61d9887..00000000 --- a/test/unit/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/sphinxcontrib-rubydomain-acceptancetest.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/sphinxcontrib-rubydomain-acceptancetest.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/sphinxcontrib-rubydomain-acceptancetest" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/sphinxcontrib-rubydomain-acceptancetest" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -latexpdf: latex - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/test/unit/conf.py b/test/unit/conf.py deleted file mode 100644 index 2487b293..00000000 --- a/test/unit/conf.py +++ /dev/null @@ -1,17 +0,0 @@ -import sys, os - -sys.path.append(os.path.abspath('..')) - -extensions = [ - 'sphinxcontrib.phpdomain', - 'myst_parser', -] - -myst_enable_extensions = ['colon_fence'] - -source_suffix = '.rst' -master_doc = 'index' - -exclude_patterns = ['_build'] - -html_theme = 'default' diff --git a/test/unit/make.bat b/test/unit/make.bat deleted file mode 100644 index 4310ae15..00000000 --- a/test/unit/make.bat +++ /dev/null @@ -1,155 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\sphinxcontrib-rubydomain-acceptancetest.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\sphinxcontrib-rubydomain-acceptancetest.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -:end diff --git a/test/unit/ns.html b/test/unit/ns.html deleted file mode 100644 index bf0c670a..00000000 --- a/test/unit/ns.html +++ /dev/null @@ -1,51 +0,0 @@ - -
-
- -

Simple NS

-
-
- - class - - - Foo\ - - - A - - -
-
-
-
-
- - Foo\A:: - - - simplify - - ( - ) - -
-
-
-
-

Cross linking

- -
-
-
-
diff --git a/test/unit/ns.md b/test/unit/ns.md deleted file mode 100644 index 1ebfe4dd..00000000 --- a/test/unit/ns.md +++ /dev/null @@ -1,14 +0,0 @@ -# Simple NS - -:::{php:namespace} Foo -::: - -:::{php:class} A -::: - -:::{php:method} simplify() -::: - -## Cross linking - -- {php:meth}`A::simplify`