Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Pyright langserver spec #587

Merged
merged 15 commits into from
May 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions .github/workflows/job.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,15 +214,16 @@ jobs:
include:
# if using 3.6, use an old node
- python: 3.6
# Node 10 end-of-life: April 2021
nodejs: '>=10,<11.0.0.a0'
# if using 3.7, use newer node, etc...
- python: 3.7
# Node 12 end-of-life: April 2022
nodejs: '>=12,<13.0.0.a0'
- python: 3.8
# if using 3.7, use newer node, etc...
- python: 3.7
# Node 14 end-of-life: April 2023
nodejs: '>=14,<15.0.0.a0'
- python: 3.8
# TODO: switch to Node 16 once gets merged https://github.com/conda-forge/nodejs-feedstock/pull/189
# Node 15 end-of-life: June 2021
nodejs: '>=15,<16.0.0.a0'
# TODO: remove when mambaforge just works on setup-miniconda
- os: ubuntu
mambaforge: Linux-x86_64.sh
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@

- add ability to deactivate Kernel completions or LSP completion through the settings ([#586], thanks @Carreau)
- allow to set a priority for LSP server, allowing to choose which server to use when multiple servers are installed ([#588])
- add auto-detection of pyright server ([#587], thanks @yuntan)

- bug fixes:
- workaround url-parse issue causing problems when using JupyterLab 3.0.15 [#599]

- workaround url-parse issue causing problems when using JupyterLab 3.0.15 ([#599])

- other changes:
- drop Node 10 (EOL 2 weeks ago) testing on CI, add Node 15 ([#587])

[#586]: https://github.com/krassowski/jupyterlab-lsp/pull/586
[#587]: https://github.com/krassowski/jupyterlab-lsp/pull/587
[#588]: https://github.com/krassowski/jupyterlab-lsp/pull/588
[#599]: https://github.com/krassowski/jupyterlab-lsp/pull/599

Expand Down
14 changes: 12 additions & 2 deletions atest/01_Editor.robot
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,13 @@ Less
Markdown
Editor Shows Features for Language Markdown example.md Diagnostics=`Color` is misspelt

Python
Python (pylsp)
${def} = Set Variable xpath:(//span[contains(@class, 'cm-variable')][contains(text(), 'fib')])[last()]
Editor Shows Features for Language Python example.py Diagnostics=multiple spaces after keyword Jump to Definition=${def} Rename=${def}
Editor Shows Features for Server pylsp Python example.py Diagnostics=undefined name 'result' (pyflakes) Jump to Definition=${def} Rename=${def}

Python (pyright)
${def} = Set Variable xpath:(//span[contains(@class, 'cm-variable')][contains(text(), 'fib')])[last()]
Editor Shows Features for Server pyright Python example.py Diagnostics=is not defined (Pyright) Jump to Definition=${def}

R
${def} = Set Variable xpath:(//span[contains(@class, 'cm-variable')][contains(text(), 'fib')])[last()]
Expand All @@ -70,6 +74,12 @@ YAML
Editor Shows Features for Language YAML example.yaml Diagnostics=duplicate key

*** Keywords ***
Editor Shows Features for Server
[Arguments] ${server} ${Language} ${file} &{features}
Configure JupyterLab Plugin
... {"language_servers": {"${server}": {"priority": 10000}}}
Editor Shows Features for Language ${Language} ${file} &{features}

Editor Shows Features for Language
[Arguments] ${Language} ${file} &{features}
Prepare File for Editing ${Language} editor ${file}
Expand Down
1 change: 1 addition & 0 deletions atest/Keywords.robot
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ Configure JupyterLab Plugin
Set Editor Content ${settings json} ${CSS USER SETTINGS}
Wait Until Page Contains No errors found
Click Element css:button[title\='Save User Settings']
Wait Until Page Contains No errors found
Click Element ${JLAB XP CLOSE SETTINGS}

Clean Up After Working with File and Settings
Expand Down
4 changes: 2 additions & 2 deletions atest/examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from itertools import (accumulate, chain); accumulate


# fibs :: Integer :: [Integer]
def fibs(n):
'''An accumulation of the first n integers in
Expand All @@ -27,5 +26,6 @@ def go(ab, _):
print(
'First twenty: ' + repr(
fibs(20)
)
),
result
)
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"npm-run-all": "^4.1.5",
"precise-commits": "^1.0.2",
"prettier": "^2.1.2",
"pyright": "^1.1",
"sql-language-server": "^0.11.4",
"typescript": "~4.1.3",
"unified-language-server": "^0.3.0",
Expand Down
8 changes: 7 additions & 1 deletion packages/jupyterlab-lsp/schema/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@
"language_servers": {
"title": "Language Server",
"description": "Language-server specific configuration, keyed by implementation, e.g: \n\npyls: {\n serverSettings: {\n pyls: {\n plugins: {\n pydocstyle: {\n enabled: true\n },\n pyflakes: {\n enabled: false\n },\n flake8: {\n enabled: true\n }\n }\n }\n }\n}\n\nAlternatively, using VSCode's naming convention:\n\npyls: {\n serverSettings: {\n \"pyls.plugins.pydocstyle.enabled\": true,\n \"pyls.plugins.pyflakes.enabled\": false,\n \"pyls.plugins.flake8.enabled\": true\n }\n}",
"default": {},
"default": {
"pyright": {
"serverSettings": {
"python.analysis.useLibraryCodeForTypes": true
}
}
},
"patternProperties": {
".*": {
"$ref": "#/definitions/language-server"
Expand Down
22 changes: 17 additions & 5 deletions packages/jupyterlab-lsp/src/connection_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,16 +162,28 @@ export class DocumentConnectionManager {
}

/**
* Currently only supports the settings that the language servers
* accept using onDidChangeConfiguration messages, under the
* "serverSettings" keyword in the setting registry. New keywords can
* be added and extra functionality implemented here when needed.
* Handles the settings that do not require an existing connection
* with a language server (or can influence to which server the
* connection will be created, e.g. `priority`).
*
* This function should be called **before** initialization of servers.
*/
public updateConfiguration(allServerSettings: TLanguageServerConfigurations) {
this.language_server_manager.setConfiguration(allServerSettings);
}

/**
* Handles the settings that the language servers accept using
* `onDidChangeConfiguration` messages, which should be passed under
* the "serverSettings" keyword in the setting registry.
* Other configuration options are handled by `updateConfiguration` instead.
*
* This function should be called **after** initialization of servers.
*/
public updateServerConfigurations(
allServerSettings: TLanguageServerConfigurations
) {
let language_server_id: TServerKeys;
this.language_server_manager.setConfiguration(allServerSettings);

for (language_server_id in allServerSettings) {
if (!allServerSettings.hasOwnProperty(language_server_id)) {
Expand Down
11 changes: 9 additions & 2 deletions packages/jupyterlab-lsp/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,11 @@ export class LSPExtension implements ILSPExtension {
.then(settings => {
// Store the initial server settings, to be sent asynchronously
// when the servers are initialized.
this.connection_manager.initial_configurations = (settings.composite
.language_servers || {}) as TLanguageServerConfigurations;
const initial_configuration = (settings.composite.language_servers ||
{}) as TLanguageServerConfigurations;
this.connection_manager.initial_configurations = initial_configuration;
// update the server-independent part of configuration immediately
this.connection_manager.updateConfiguration(initial_configuration);

settings.changed.connect(() => {
this.updateOptions(settings);
Expand Down Expand Up @@ -223,6 +226,10 @@ export class LSPExtension implements ILSPExtension {

const languageServerSettings = (options.language_servers ||
{}) as TLanguageServerConfigurations;

this.connection_manager.initial_configurations = languageServerSettings;
// TODO: if priorities changed reset connections
this.connection_manager.updateConfiguration(languageServerSettings);
this.connection_manager.updateServerConfigurations(languageServerSettings);
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/jupyterlab-lsp/src/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class LanguageServerManager implements ILanguageServerManager {
}
}

return matchingSessionsKeys.sort(this._comparePriorities);
return matchingSessionsKeys.sort(this._comparePriorities.bind(this));
}

get statusCode(): number {
Expand Down
13 changes: 13 additions & 0 deletions packages/jupyterlab-lsp/src/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { expect } from 'chai';

import { uris_equal } from './utils';

describe('uris_equal', () => {
it('should workaround Windows paths/Pyright issues', () => {
const result = uris_equal(
'file:///d%3A/a/jupyterlab-lsp/jupyterlab-lsp/atest/output/windows_39_4/home/n%C3%B6te%20b%C3%B2%C3%B3ks/example.py',
'file:///d:/a/jupyterlab-lsp/jupyterlab-lsp/atest/output/windows_39_4/home/n%C3%B6te%20b%C3%B2%C3%B3ks/example.py'
);
expect(result).to.equal(true);
});
});
8 changes: 6 additions & 2 deletions packages/jupyterlab-lsp/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PageConfig } from '@jupyterlab/coreutils';
import { ReadonlyJSONObject, ReadonlyJSONValue } from '@lumino/coreutils';
import mergeWith from 'lodash.mergewith';

const RE_PATH_ANCHOR = /^file:\/\/([^\/]+|\/[A-Z]:)/;
const RE_PATH_ANCHOR = /^file:\/\/([^\/]+|\/[a-zA-Z](?::|%3A))/;

export async function sleep(timeout: number) {
return new Promise<void>(resolve => {
Expand Down Expand Up @@ -142,7 +142,11 @@ export function is_win_path(uri: string) {
* lowercase the drive component of a URI
*/
export function normalize_win_path(uri: string) {
return uri.replace(RE_PATH_ANCHOR, it => it.toLowerCase());
// Pyright encodes colon on Windows, see:
// https://github.com/krassowski/jupyterlab-lsp/pull/587#issuecomment-844225253
return uri.replace(RE_PATH_ANCHOR, it =>
it.replace('%3A', ':').toLowerCase()
);
}

export function uri_to_contents_path(child: string, parent?: string) {
Expand Down
2 changes: 2 additions & 0 deletions python_packages/jupyter_lsp/jupyter_lsp/specs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from .jedi_language_server import JediLanguageServer
from .julia_language_server import JuliaLanguageServer
from .pyls import PalantirPythonLanguageServer
from .pyright import PyrightLanguageServer
from .python_lsp_server import PythonLSPServer
from .r_languageserver import RLanguageServer
from .sql_language_server import SQLLanguageServer
Expand All @@ -28,6 +29,7 @@
md = UnifiedLanguageServer()
py_palantir = PalantirPythonLanguageServer()
py_lsp_server = PythonLSPServer()
pyright = PyrightLanguageServer()
r = RLanguageServer()
tex = Texlab()
ts = JavascriptTypescriptLanguageServer()
Expand Down
21 changes: 21 additions & 0 deletions python_packages/jupyter_lsp/jupyter_lsp/specs/pyright.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from .utils import NodeModuleSpec


class PyrightLanguageServer(NodeModuleSpec):
node_module = key = "pyright"
script = ["langserver.index.js"]
args = ["--stdio"]
languages = ["python"]
spec = dict(
display_name=key,
mime_types=["text/python", "text/x-ipython"],
urls=dict(
home="https://github.com/microsoft/pyright",
issues="https://github.com/microsoft/pyright/issues",
),
install=dict(
npm="npm install --save-dev {}".format(key),
yarn="yarn add --dev {}".format(key),
jlpm="jlpm add --dev {}".format(key),
),
)
1 change: 1 addition & 0 deletions python_packages/jupyter_lsp/setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ jupyter_lsp_spec_v1 =
julia-language-server = jupyter_lsp.specs:julia
python-language-server = jupyter_lsp.specs:py_palantir
python-lsp-server = jupyter_lsp.specs:py_lsp_server
pyright = jupyter_lsp.specs:pyright
r-languageserver = jupyter_lsp.specs:r
texlab = jupyter_lsp.specs:tex
sql-language-server = jupyter_lsp.specs:sql
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11445,6 +11445,11 @@ puppeteer@^1.17.0:
rimraf "^2.6.1"
ws "^6.1.0"

pyright@^1.1:
version "1.1.140"
resolved "https://registry.yarnpkg.com/pyright/-/pyright-1.1.140.tgz#2692f67b2769e664983dff3fefee4c0e4d12f4fa"
integrity sha512-isJj7cahjEK7xAy5/aLJ4TfzLJGA4SCWqPk1pLJA3k8S6VUo4FIiPrvHOd1LM2gxImqgef4rwUeHRC+vrOKLRQ==

q@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
Expand Down