-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: Add architecture diagram to reference section
- Loading branch information
Showing
3 changed files
with
284 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
.. _lsp-reference: | ||
|
||
Reference | ||
========= | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,282 @@ | ||
Server Architecture | ||
=================== | ||
|
||
.. raw:: html | ||
|
||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | ||
<!-- Created with Inkscape (http://www.inkscape.org/) --> | ||
|
||
<div class="figure align-default"> | ||
<svg | ||
width="100%" | ||
viewBox="0 0 297 210" | ||
style="background: var(--color-content-background)" | ||
version="1.1" | ||
id="svg5" | ||
xmlns="http://www.w3.org/2000/svg" | ||
xmlns:svg="http://www.w3.org/2000/svg"> | ||
<defs | ||
id="defs2"> | ||
<marker | ||
style="overflow:visible" | ||
id="Arrow1Mstart" | ||
refX="0.0" | ||
refY="0.0" | ||
orient="auto"> | ||
<path | ||
transform="scale(0.4) translate(10,0)" | ||
style="fill:var(--color-content-foreground);fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt" | ||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " | ||
id="path35046" /> | ||
</marker> | ||
<marker | ||
style="overflow:visible;" | ||
id="Arrow1Mend" | ||
refX="0.0" | ||
refY="0.0" | ||
orient="auto"> | ||
<path | ||
transform="scale(0.4) rotate(180) translate(10,0)" | ||
style="fill:var(--color-content-foreground);fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;" | ||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " | ||
id="path35049" /> | ||
</marker> | ||
<marker | ||
style="overflow:visible;" | ||
id="Arrow1Lend" | ||
refX="0.0" | ||
refY="0.0" | ||
orient="auto"> | ||
<path | ||
transform="scale(0.8) rotate(180) translate(12.5,0)" | ||
style="fill:var(--color-content-foreground);fill-rule:evenodd;fill:context-stroke;stroke:context-stroke;stroke-width:1.0pt;" | ||
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " | ||
id="path35043" /> | ||
</marker> | ||
<marker | ||
style="overflow:visible" | ||
id="Arrow1Mend-1" | ||
refX="0" | ||
refY="0" | ||
orient="auto"> | ||
<path | ||
transform="matrix(-0.4,0,0,-0.4,-4,0)" | ||
style="fill:var(--color-content-foreground);fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt" | ||
d="M 0,0 5,-5 -12.5,0 5,5 Z" | ||
id="path35049-8" /> | ||
</marker> | ||
<marker | ||
style="overflow:visible" | ||
id="Arrow1Mend-9" | ||
refX="0" | ||
refY="0" | ||
orient="auto"> | ||
<path | ||
transform="matrix(-0.4,0,0,-0.4,-4,0)" | ||
style="fill:var(--color-content-foreground);fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:1pt" | ||
d="M 0,0 5,-5 -12.5,0 5,5 Z" | ||
id="path35049-2" /> | ||
</marker> | ||
</defs> | ||
<g | ||
id="layer1"> | ||
<rect | ||
style="fill:var(--color-content-background);stroke:var(--color-content-foreground);stroke-width:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" | ||
id="rect1192" | ||
width="121.70834" | ||
height="129.64583" | ||
x="166.15813" | ||
y="31.75" /> | ||
<rect | ||
style="fill:var(--color-content-background);stroke:var(--color-content-foreground);stroke-width:1;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" | ||
id="rect1192-3" | ||
width="52.916668" | ||
height="129.64583" | ||
x="5.2916665" | ||
y="31.75001" /> | ||
<rect | ||
style="fill:var(--color-sidebar-background);fill-rule:evenodd;stroke:var(--color-content-foreground);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||
id="rect31" | ||
width="68.096382" | ||
height="25.12426" | ||
x="211.90756" | ||
y="46.209999" /> | ||
<rect | ||
style="fill:var(--color-sidebar-background);fill-rule:evenodd;stroke:var(--color-content-foreground);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||
id="rect31-3" | ||
width="68.096382" | ||
height="25.12426" | ||
x="211.83255" | ||
y="123.03125" /> | ||
<rect | ||
style="fill:var(--color-sidebar-background);fill-rule:evenodd;stroke:var(--color-content-foreground);stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||
id="rect31-5" | ||
width="68.096382" | ||
height="25.12426" | ||
x="211.83257" | ||
y="75.406258" /> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="215.90004" | ||
y="60.854172" | ||
id="text3354"><tspan | ||
id="tspan3352" | ||
style="font-size:5.64444px;stroke-width:0.264583" | ||
x="215.90004" | ||
y="60.854172">Language Feature #1</tspan></text> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="215.5123" | ||
y="89.815636" | ||
id="text3354-6"><tspan | ||
id="tspan3352-2" | ||
style="font-size:5.64444px;stroke-width:0.264583" | ||
x="215.5123" | ||
y="89.815636">Language Feature #2</tspan></text> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="190.10786" | ||
y="96.331848" | ||
id="text3354-6-0"><tspan | ||
id="tspan3352-2-9" | ||
style="font-size:5.64444px;text-align:center;text-anchor:middle;stroke-width:0.264583" | ||
x="190.10786" | ||
y="96.331848">Language </tspan><tspan | ||
style="font-size:5.64444px;text-align:center;text-anchor:middle;stroke-width:0.264583" | ||
x="190.10786" | ||
y="103.3874" | ||
id="tspan25491">Server</tspan></text> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="31.655663" | ||
y="97.075394" | ||
id="text3354-6-0-6"><tspan | ||
id="tspan3352-2-9-2" | ||
style="font-size:5.64444px;text-align:center;text-anchor:middle;stroke-width:0.264583" | ||
x="31.655663" | ||
y="97.075394">Language </tspan><tspan | ||
style="font-size:5.64444px;text-align:center;text-anchor:middle;stroke-width:0.264583" | ||
x="31.655663" | ||
y="104.13094" | ||
id="tspan25491-6">Client</tspan></text> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="92.105232" | ||
y="99.029205" | ||
id="text3354-6-0-6-2"><tspan | ||
style="font-size:5.64444px;text-align:center;text-anchor:middle;stroke-width:0.264583" | ||
x="92.105232" | ||
y="99.029205" | ||
id="tspan25491-6-7">LSP Protocol</tspan></text> | ||
<g | ||
id="g34651" | ||
transform="translate(-5.8208336)"> | ||
<rect | ||
style="fill:var(--color-content-background);stroke:var(--color-content-foreground);stroke-width:1.07275;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" | ||
id="rect1192-3-5" | ||
width="24.358648" | ||
height="129.64583" | ||
x="129.62888" | ||
y="31.750002" /> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="141.52403" | ||
y="98.416359" | ||
id="text3354-6-0-3"><tspan | ||
style="font-size:5.64444px;text-align:center;text-anchor:middle;stroke-width:0.264583" | ||
x="141.52403" | ||
y="98.416359" | ||
id="tspan25491-0">Engine</tspan></text> | ||
</g> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="105.41908" | ||
y="-245.68881" | ||
id="text3354-6-9" | ||
transform="rotate(90.528171)"><tspan | ||
style="font-size:5.64444px;stroke-width:0.264583" | ||
x="105.41908" | ||
y="-245.68881" | ||
id="tspan20015">.....</tspan></text> | ||
<text | ||
xml:space="preserve" | ||
style="font-style:normal;font-weight:normal;font-size:5.64444px;line-height:1.25;font-family:sans-serif;fill:var(--color-content-foreground);fill-opacity:1;stroke:none;stroke-width:0.264583" | ||
x="215.92711" | ||
y="137.34949" | ||
id="text3354-6-9-2"><tspan | ||
id="tspan3352-2-1-7" | ||
style="font-size:5.64444px;stroke-width:0.264583" | ||
x="215.92711" | ||
y="137.34949">Language Feature #N</tspan></text> | ||
<path | ||
style="fill:none;stroke:var(--color-content-foreground);stroke-width:0.83959;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend)" | ||
d="M 59.546327,89.945827 H 121.22207" | ||
id="path34806" /> | ||
<path | ||
style="fill:none;stroke:var(--color-content-foreground);stroke-width:0.83959;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#Arrow1Mend-9)" | ||
d="M 122.87663,104.76253 H 61.200895" | ||
id="path34806-0" /> | ||
<path | ||
style="fill:none;stroke:var(--color-content-foreground);stroke-width:0.417578;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-start:url(#Arrow1Mstart);marker-end:url(#Arrow1Mend-1)" | ||
d="m 149.53571,96.847604 h 15.25657" | ||
id="path34806-7" /> | ||
</g> | ||
</svg> | ||
<p class="caption">A rough sketch of how the language server(s) in Esbonio are architected.</p> | ||
</div> | ||
|
||
|
||
.. glossary:: | ||
|
||
Language Server | ||
A language server is a subclass of the ``LanguageServer`` class provided by the `pygls`_ library. | ||
|
||
In Esbonio, all the features you would typically associate with a language server, e.g. completions are not actually implemented by the language server. | ||
These features are provided through a number of "language features" (see below). | ||
Instead a language server acts a container for all the active language features and provides an API they can use to query aspects of the environment. | ||
|
||
Esbonio currently provides two language servers | ||
|
||
- :class:`~esbonio.lsp.rst.RstLanguageServer`: Base language server, meant for "vanilla" docutils projects. | ||
- :class:`~esbonio.lsp.sphinx.SphinxLanguageServer` Language server, specialising in Sphinx projects. | ||
|
||
Language Feature | ||
Language features are subclasses of :class:`~esbonio.lsp.rst.LanguageFeature`. | ||
They are typically based on a single aspect of reStructuredText (e.g. :class:`~esbonio.lsp.roles.Roles`). | ||
|
||
Language Features (where it makes sense) should be server agnostic, that way the same features can be reused across different envrionments. | ||
|
||
Engine | ||
For lack of a better name... an "engine" is responsible for mapping messages from the LSP Protocol into function calls within the language server. | ||
Unlike the other components of the architecture, an "engine" isn't formally defined and there is no API to implement. | ||
Instead it's just the term used to refer to all the ``@server.feature()`` handlers that define how LSP messages should be handled. | ||
|
||
Currently we provide just a single "engine" :func:`~esbonio.lsp.create_language_server`. | ||
As an example, here is how it handles ``textDocument/completion`` requests. | ||
|
||
.. literalinclude:: ../../../lib/esbonio/esbonio/lsp/__init__.py | ||
:language: python | ||
:dedent: | ||
:start-after: # <engine-example> | ||
:end-before: # </engine-example> | ||
|
||
There is nothing in Esbonio that would prevent you from writing your own if you so desired. | ||
|
||
Extension Module | ||
Ordinary Python modules are used to group related functionality together. | ||
Taking inspiration from how Sphinx is architected, language servers are assembled by passing the list of modules to load to the :func:`~esbonio.lsp.create_language_server`. | ||
This assembly process calls any functions with the name ``esbonio_setup`` allowing for ``LanguageFeatures`` to be configured and loaded into the server. | ||
|
||
Startup Module | ||
As mentioned above, language servers are assembled and this is done inside a startup module. | ||
A startup module in Esbonio is any Python script or module runnable by a ``python -m <modulename>`` command that results in a running language server. | ||
A good use case for a custom entry point would be starting up a language server instance pre configured with all the extensions required by your project. | ||
|
||
.. _pygls: https://pygls.readthedocs.io/en/latest/index.html |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters