Skip to content

Commit

Permalink
Improve role discovery (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
alcarney authored Dec 3, 2020
1 parent dcec497 commit 8effd96
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 4 deletions.
2 changes: 2 additions & 0 deletions lib/esbonio/changes/26.fix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix discovery of roles so that roles in Sphinx domains are used and that unimplemented
``docutils`` roles are not surfaced.
26 changes: 24 additions & 2 deletions lib/esbonio/esbonio/lsp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,26 @@ def completion_from_role(name, role) -> CompletionItem:
)


def discover_roles(app: Sphinx):
"""Discover roles that we can offer as autocomplete suggestions."""
# Pull out the roles that are available via docutils.
local_roles = {
k: v for k, v in roles._roles.items() if v != roles.unimplemented_role
}

role_registry = {
k: v for k, v in roles._role_registry.items() if v != roles.unimplemented_role
}

# Don't forget to include the roles that are stored under Sphinx domains.
# TODO: Implement proper domain handling, focus on std + python for now.
domains = app.registry.domains
std_roles = domains["std"].roles
py_roles = domains["py"].roles

return {**local_roles, **role_registry, **py_roles, **std_roles}


class RstLanguageServer(LanguageServer):
def __init__(self):
super().__init__()
Expand Down Expand Up @@ -99,8 +119,10 @@ def on_initialized(rst: RstLanguageServer, params):
dirs = {**directives._directive_registry, **directives._directives}
rst.directives = {k: completion_from_directive(k, v) for k, v in dirs.items()}

role_s = {**roles._roles, **roles._role_registry}
rst.roles = {k: completion_from_role(k, v) for k, v in role_s.items()}
rst.roles = {
k: completion_from_role(k, v) for k, v in discover_roles(rst.app).items()
}
rst.logger.debug("Discovered %s roles", len(rst.roles))


NEW_DIRECTIVE = re.compile(r"^\s*\.\.[ ]*([\w-]+)?$")
Expand Down
17 changes: 17 additions & 0 deletions lib/esbonio/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from docutils.parsers.rst import Parser
from docutils.parsers.rst import directives
from docutils.readers.standalone import Reader

from sphinx.application import Sphinx
from sphinx.ext.doctest import DoctestDirective

from esbonio.tutorial import SolutionDirective
Expand Down Expand Up @@ -34,6 +36,21 @@ def loader(filename, path_only=False):
return loader


@py.test.fixture(scope="session")
def sphinx():
"""Return a Sphinx application instance pointed at the given project."""

basepath = pathlib.Path(__file__).parent / "data"

def loader(project):
src = str(basepath / project)
build = str(basepath / project / "_build")

return Sphinx(src, src, build, build, "html", status=None, warning=None)

return loader


@py.test.fixture(scope="session")
def rst_mock_settings():
"""Return a mock that can pretend to be the settings object needed to parse rst
Expand Down
20 changes: 20 additions & 0 deletions lib/esbonio/tests/data/sphinx-default/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#

# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build

# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

.PHONY: help Makefile

# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
52 changes: 52 additions & 0 deletions lib/esbonio/tests/data/sphinx-default/conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html

# -- Path setup --------------------------------------------------------------

# 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.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))


# -- Project information -----------------------------------------------------

project = 'Defaults'
copyright = '2020, Sphinx'
author = 'Sphinx'


# -- General configuration ---------------------------------------------------

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']


# -- Options for HTML output -------------------------------------------------

# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'

# 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']
20 changes: 20 additions & 0 deletions lib/esbonio/tests/data/sphinx-default/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.. Defaults documentation master file, created by
sphinx-quickstart on Wed Dec 2 22:54:25 2020.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to Defaults's documentation!
====================================

.. toctree::
:maxdepth: 2
:caption: Contents:



Indices and tables
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
35 changes: 35 additions & 0 deletions lib/esbonio/tests/data/sphinx-default/make.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@ECHO OFF

pushd %~dp0

REM Command file for Sphinx documentation

if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build

if "%1" == "" goto help

%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)

%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end

:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%

:end
popd
35 changes: 34 additions & 1 deletion lib/esbonio/tests/lsp/test_completions.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
)
from pygls.workspace import Document, Workspace

from esbonio.lsp import completions
from esbonio.lsp import completions, discover_roles


def make_document(contents) -> Document:
Expand Down Expand Up @@ -116,3 +116,36 @@ def test_completion_suggestions(rst, doc, params, expected):

actual = completions(rst, params).items
assert actual == expected


@py.test.mark.parametrize(
"project,expected,unexpected",
[
(
"sphinx-default",
[
"emphasis",
"subscript",
"raw",
"func",
"meth",
"class",
"ref",
"doc",
"term",
],
["named-reference", "restructuredtext-unimplemented-role"],
)
],
)
def test_role_discovery(sphinx, project, expected, unexpected):
"""Ensure that we can discover the roles from the various places they are stored."""

app = sphinx(project)
roles = discover_roles(app)

for name in expected:
assert name in roles.keys(), "Missing expected role '{}'".format(name)

for name in unexpected:
assert name not in roles.keys(), "Unexpected role '{}'".format(name)
2 changes: 1 addition & 1 deletion scripts/make-release.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ COMPONENT=$1
case $1 in
vscode)
SRC="code"
TAG_PREFIX="esbonio-vscode"
TAG_PREFIX="esbonio-vscode-v"
COMMIT_MSG="Esbonio VSCode Ext Release v"
;;
python)
Expand Down

0 comments on commit 8effd96

Please sign in to comment.