From b1703de93ce02c414edb522f536187a4d963a27c Mon Sep 17 00:00:00 2001 From: masfrost Date: Wed, 8 Dec 2021 20:15:45 -0800 Subject: [PATCH 01/10] Update hookspec --- pylsp/hookspecs.py | 4 ++-- pylsp/plugins/autopep8_format.py | 4 ++-- pylsp/plugins/yapf_format.py | 10 +++++----- pylsp/python_lsp.py | 18 ++++++++---------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/pylsp/hookspecs.py b/pylsp/hookspecs.py index 736cf931..d1a2458e 100644 --- a/pylsp/hookspecs.py +++ b/pylsp/hookspecs.py @@ -80,12 +80,12 @@ def pylsp_folding_range(config, workspace, document): @hookspec(firstresult=True) -def pylsp_format_document(config, workspace, document): +def pylsp_format_document(config, workspace, document, options): pass @hookspec(firstresult=True) -def pylsp_format_range(config, workspace, document, range): +def pylsp_format_range(config, workspace, document, range, options): pass diff --git a/pylsp/plugins/autopep8_format.py b/pylsp/plugins/autopep8_format.py index 8915fb72..73934d54 100644 --- a/pylsp/plugins/autopep8_format.py +++ b/pylsp/plugins/autopep8_format.py @@ -13,13 +13,13 @@ @hookimpl(tryfirst=True) # Prefer autopep8 over YAPF -def pylsp_format_document(config, document): +def pylsp_format_document(config, document, _options=None): log.info("Formatting document %s with autopep8", document) return _format(config, document) @hookimpl(tryfirst=True) # Prefer autopep8 over YAPF -def pylsp_format_range(config, document, range): # pylint: disable=redefined-builtin +def pylsp_format_range(config, document, range, _options=None): # pylint: disable=redefined-builtin log.info("Formatting document %s in range %s with autopep8", document, range) # First we 'round' the range up/down to full lines only diff --git a/pylsp/plugins/yapf_format.py b/pylsp/plugins/yapf_format.py index 1c90f965..7c312eea 100644 --- a/pylsp/plugins/yapf_format.py +++ b/pylsp/plugins/yapf_format.py @@ -14,12 +14,12 @@ @hookimpl -def pylsp_format_document(document): - return _format(document) +def pylsp_format_document(document, options=None): + return _format(document, options=options) @hookimpl -def pylsp_format_range(document, range): # pylint: disable=redefined-builtin +def pylsp_format_range(document, range, options=None): # pylint: disable=redefined-builtin # First we 'round' the range up/down to full lines only range['start']['character'] = 0 range['end']['line'] += 1 @@ -33,10 +33,10 @@ def pylsp_format_range(document, range): # pylint: disable=redefined-builtin # Add 1 for 1-indexing vs LSP's 0-indexing lines = [(range['start']['line'] + 1, range['end']['line'] + 1)] - return _format(document, lines=lines) + return _format(document, lines=lines, options=None) -def _format(document, lines=None): +def _format(document, lines=None, options=None): # Yapf doesn't work with CR line endings, so we replace them by '\n' # and restore them below. replace_cr = False diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py index a11f6119..1044e7ab 100644 --- a/pylsp/python_lsp.py +++ b/pylsp/python_lsp.py @@ -277,11 +277,11 @@ def document_symbols(self, doc_uri): def execute_command(self, command, arguments): return self._hook('pylsp_execute_command', command=command, arguments=arguments) - def format_document(self, doc_uri): - return self._hook('pylsp_format_document', doc_uri) + def format_document(self, doc_uri, options): + return self._hook('pylsp_format_document', doc_uri, options) - def format_range(self, doc_uri, range): - return self._hook('pylsp_format_range', doc_uri, range=range) + def format_range(self, doc_uri, range, options): + return self._hook('pylsp_format_range', doc_uri, range=range, options=options) def highlight(self, doc_uri, position): return flatten(self._hook('pylsp_document_highlight', doc_uri, position=position)) or None @@ -362,9 +362,8 @@ def m_text_document__hover(self, textDocument=None, position=None, **_kwargs): def m_text_document__document_symbol(self, textDocument=None, **_kwargs): return self.document_symbols(textDocument['uri']) - def m_text_document__formatting(self, textDocument=None, _options=None, **_kwargs): - # For now we're ignoring formatting options. - return self.format_document(textDocument['uri']) + def m_text_document__formatting(self, textDocument=None, options=None, **_kwargs): + return self.format_document(textDocument['uri'], options) def m_text_document__rename(self, textDocument=None, position=None, newName=None, **_kwargs): return self.rename(textDocument['uri'], position, newName) @@ -372,9 +371,8 @@ def m_text_document__rename(self, textDocument=None, position=None, newName=None def m_text_document__folding_range(self, textDocument=None, **_kwargs): return self.folding(textDocument['uri']) - def m_text_document__range_formatting(self, textDocument=None, range=None, _options=None, **_kwargs): - # Again, we'll ignore formatting options for now. - return self.format_range(textDocument['uri'], range) + def m_text_document__range_formatting(self, textDocument=None, range=None, options=None, **_kwargs): + return self.format_range(textDocument['uri'], range, options) def m_text_document__references(self, textDocument=None, position=None, context=None, **_kwargs): exclude_declaration = not context['includeDeclaration'] From 635a9e9901461abfe30a18abbd4eee955bf0545a Mon Sep 17 00:00:00 2001 From: masfrost Date: Wed, 8 Dec 2021 20:18:33 -0800 Subject: [PATCH 02/10] Add options support to yapf --- pylsp/plugins/yapf_format.py | 43 +++++++++++++++++++++++++++++--- test/plugins/test_yapf_format.py | 27 ++++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/pylsp/plugins/yapf_format.py b/pylsp/plugins/yapf_format.py index 7c312eea..9e9f666c 100644 --- a/pylsp/plugins/yapf_format.py +++ b/pylsp/plugins/yapf_format.py @@ -46,13 +46,50 @@ def _format(document, lines=None, options=None): replace_cr = True source = source.replace('\r', '\n') + # Get the default styles as a string + # for a preset configuration, i.e. "pep8" + style_config = file_resources.GetDefaultStyleForDir( + os.path.dirname(document.path) + ) + if options is not None: + # We have options passed from LSP format request + # let's pass them to the formatter. + # First we want to get a dictionary of the preset style + # to pass instead of a string so that we can modify it + style_config = style.CreateStyleFromConfig(style_config) + + use_tabs = style_config['USE_TABS'] + indent_width = style_config['INDENT_WIDTH'] + + if options.get('tabSize') is not None: + indent_width = max(int(options.get('tabSize')), 1) + + if options.get('insertSpaces') is not None: + # TODO is it guaranteed to be a boolean, or can it be a string? + use_tabs = not options.get('insertSpaces') + + if use_tabs: + # Indent width doesn't make sense when using tabs + # the specifications state: "Size of a tab in spaces" + indent_width = 1 + + style_config['USE_TABS'] = use_tabs + style_config['INDENT_WIDTH'] = indent_width + style_config['CONTINUATION_INDENT_WIDTH'] = indent_width + + for style_option, value in options.items(): + # Apply arbitrary options passed as formatter options + if style_option not in style_config: + # ignore if it's not a known yapf config + continue + + style_config[style_option] = value + new_source, changed = FormatCode( source, lines=lines, filename=document.filename, - style_config=file_resources.GetDefaultStyleForDir( - os.path.dirname(document.path) - ) + style_config=style_config ) if not changed: diff --git a/test/plugins/test_yapf_format.py b/test/plugins/test_yapf_format.py index 4346985c..af2976dd 100644 --- a/test/plugins/test_yapf_format.py +++ b/test/plugins/test_yapf_format.py @@ -65,3 +65,30 @@ def test_cr_line_endings(workspace): res = pylsp_format_document(doc) assert res[0]['newText'] == 'import os\rimport sys\r\rdict(a=1)\r' + +FOUR_SPACE_DOC = """def hello(): + pass +""" + +def test_format_with_tab_size_option(workspace): + doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) + res = pyls_format_document(doc, { "tabSize": "8" }) + + assert len(res) == 1 + assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", " ") + + +def test_format_with_insert_spaces_option(workspace): + doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) + res = pyls_format_document(doc, { "insertSpaces": False }) + + assert len(res) == 1 + assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") + + +def test_format_with_yapf_specific_option(workspace): + doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) + res = pyls_format_document(doc, { "USE_TABS": True }) + + assert len(res) == 1 + assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") From 04f20cc463a1ebe48a95246608a865edfc660153 Mon Sep 17 00:00:00 2001 From: masfrost Date: Thu, 9 Dec 2021 02:01:49 -0800 Subject: [PATCH 03/10] oops --- test/plugins/test_yapf_format.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/plugins/test_yapf_format.py b/test/plugins/test_yapf_format.py index af2976dd..f3b213e4 100644 --- a/test/plugins/test_yapf_format.py +++ b/test/plugins/test_yapf_format.py @@ -72,7 +72,7 @@ def test_cr_line_endings(workspace): def test_format_with_tab_size_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) - res = pyls_format_document(doc, { "tabSize": "8" }) + res = pylsp_format_document(doc, { "tabSize": "8" }) assert len(res) == 1 assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", " ") @@ -80,7 +80,7 @@ def test_format_with_tab_size_option(workspace): def test_format_with_insert_spaces_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) - res = pyls_format_document(doc, { "insertSpaces": False }) + res = pylsp_format_document(doc, { "insertSpaces": False }) assert len(res) == 1 assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") @@ -88,7 +88,7 @@ def test_format_with_insert_spaces_option(workspace): def test_format_with_yapf_specific_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) - res = pyls_format_document(doc, { "USE_TABS": True }) + res = pylsp_format_document(doc, { "USE_TABS": True }) assert len(res) == 1 assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") From 95cd3e57245251390961e7ea1c4f71c4617fad84 Mon Sep 17 00:00:00 2001 From: masfrost Date: Wed, 9 Mar 2022 19:22:12 -0800 Subject: [PATCH 04/10] Add missing import --- pylsp/plugins/yapf_format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylsp/plugins/yapf_format.py b/pylsp/plugins/yapf_format.py index 9e9f666c..0ac24245 100644 --- a/pylsp/plugins/yapf_format.py +++ b/pylsp/plugins/yapf_format.py @@ -4,7 +4,7 @@ import logging import os -from yapf.yapflib import file_resources +from yapf.yapflib import file_resources, style from yapf.yapflib.yapf_api import FormatCode from pylsp import hookimpl From 8aa9ce881ae3f7e0df67432c44ba1dba7deb2752 Mon Sep 17 00:00:00 2001 From: masfrost Date: Thu, 17 Mar 2022 13:44:23 -0700 Subject: [PATCH 05/10] Pass options through for format range --- pylsp/plugins/yapf_format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylsp/plugins/yapf_format.py b/pylsp/plugins/yapf_format.py index 0ac24245..bbe43e7f 100644 --- a/pylsp/plugins/yapf_format.py +++ b/pylsp/plugins/yapf_format.py @@ -33,7 +33,7 @@ def pylsp_format_range(document, range, options=None): # pylint: disable=redefi # Add 1 for 1-indexing vs LSP's 0-indexing lines = [(range['start']['line'] + 1, range['end']['line'] + 1)] - return _format(document, lines=lines, options=None) + return _format(document, lines=lines, options=options) def _format(document, lines=None, options=None): From a61f1034e1612a98860d91da5f93e56b0a428a2e Mon Sep 17 00:00:00 2001 From: Faris Masad Date: Wed, 30 Mar 2022 16:18:23 -0700 Subject: [PATCH 06/10] Update test_yapf_format.py --- test/plugins/test_yapf_format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/plugins/test_yapf_format.py b/test/plugins/test_yapf_format.py index b68ba4ba..1fa91674 100644 --- a/test/plugins/test_yapf_format.py +++ b/test/plugins/test_yapf_format.py @@ -94,4 +94,4 @@ def test_format_with_yapf_specific_option(workspace): res = pylsp_format_document(doc, { "USE_TABS": True }) assert len(res) == 1 - assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") \ No newline at end of file + assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") From 535bfaea2f347a4df0b2cc86136b2323a8e6d764 Mon Sep 17 00:00:00 2001 From: masfrost Date: Sun, 3 Apr 2022 09:05:57 -0700 Subject: [PATCH 07/10] More lint --- pylsp/python_lsp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pylsp/python_lsp.py b/pylsp/python_lsp.py index 1044e7ab..81e93bdc 100644 --- a/pylsp/python_lsp.py +++ b/pylsp/python_lsp.py @@ -278,7 +278,7 @@ def execute_command(self, command, arguments): return self._hook('pylsp_execute_command', command=command, arguments=arguments) def format_document(self, doc_uri, options): - return self._hook('pylsp_format_document', doc_uri, options) + return self._hook('pylsp_format_document', doc_uri, options=options) def format_range(self, doc_uri, range, options): return self._hook('pylsp_format_range', doc_uri, range=range, options=options) From 067b24e555983d25f60a27cab19e7ab50ea0e570 Mon Sep 17 00:00:00 2001 From: Faris Masad Date: Mon, 4 Apr 2022 11:05:52 -0700 Subject: [PATCH 08/10] Address feedback --- pylsp/plugins/autopep8_format.py | 4 ++-- test/plugins/test_yapf_format.py | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pylsp/plugins/autopep8_format.py b/pylsp/plugins/autopep8_format.py index 73934d54..4b72b7f5 100644 --- a/pylsp/plugins/autopep8_format.py +++ b/pylsp/plugins/autopep8_format.py @@ -13,13 +13,13 @@ @hookimpl(tryfirst=True) # Prefer autopep8 over YAPF -def pylsp_format_document(config, document, _options=None): +def pylsp_format_document(config, document, options=None): log.info("Formatting document %s with autopep8", document) return _format(config, document) @hookimpl(tryfirst=True) # Prefer autopep8 over YAPF -def pylsp_format_range(config, document, range, _options=None): # pylint: disable=redefined-builtin +def pylsp_format_range(config, document, range, options=None): # pylint: disable=redefined-builtin log.info("Formatting document %s in range %s with autopep8", document, range) # First we 'round' the range up/down to full lines only diff --git a/test/plugins/test_yapf_format.py b/test/plugins/test_yapf_format.py index 1fa91674..8d96fd21 100644 --- a/test/plugins/test_yapf_format.py +++ b/test/plugins/test_yapf_format.py @@ -21,7 +21,9 @@ """ GOOD_DOC = """A = ['hello', 'world']\n""" - +FOUR_SPACE_DOC = """def hello(): + pass +""" def test_format(workspace): doc = Document(DOC_URI, workspace, DOC) @@ -69,9 +71,6 @@ def test_line_endings(workspace, newline): assert res[0]['newText'] == f'import os{newline}import sys{2 * newline}dict(a=1){newline}' -FOUR_SPACE_DOC = """def hello(): - pass -""" def test_format_with_tab_size_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) From f0d4f090b33dc68c31e4bc33d5d745636baca5e5 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 5 Apr 2022 10:27:41 -0500 Subject: [PATCH 09/10] Fix last linting issues --- pylsp/plugins/autopep8_format.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pylsp/plugins/autopep8_format.py b/pylsp/plugins/autopep8_format.py index 4b72b7f5..f605f830 100644 --- a/pylsp/plugins/autopep8_format.py +++ b/pylsp/plugins/autopep8_format.py @@ -13,13 +13,13 @@ @hookimpl(tryfirst=True) # Prefer autopep8 over YAPF -def pylsp_format_document(config, document, options=None): +def pylsp_format_document(config, document, options=None): # pylint: disable=unused-argument log.info("Formatting document %s with autopep8", document) return _format(config, document) @hookimpl(tryfirst=True) # Prefer autopep8 over YAPF -def pylsp_format_range(config, document, range, options=None): # pylint: disable=redefined-builtin +def pylsp_format_range(config, document, range, options=None): # pylint: disable=redefined-builtin,unused-argument log.info("Formatting document %s in range %s with autopep8", document, range) # First we 'round' the range up/down to full lines only From 56d6d19bc9a4bcf04b0a11018ea273a9310765b8 Mon Sep 17 00:00:00 2001 From: Carlos Cordoba Date: Tue, 5 Apr 2022 10:31:50 -0500 Subject: [PATCH 10/10] Fix linting issues in tests --- test/plugins/test_yapf_format.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/plugins/test_yapf_format.py b/test/plugins/test_yapf_format.py index 8d96fd21..cf4d9655 100644 --- a/test/plugins/test_yapf_format.py +++ b/test/plugins/test_yapf_format.py @@ -25,6 +25,7 @@ pass """ + def test_format(workspace): doc = Document(DOC_URI, workspace, DOC) res = pylsp_format_document(doc) @@ -74,7 +75,7 @@ def test_line_endings(workspace, newline): def test_format_with_tab_size_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) - res = pylsp_format_document(doc, { "tabSize": "8" }) + res = pylsp_format_document(doc, {"tabSize": "8"}) assert len(res) == 1 assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", " ") @@ -82,7 +83,7 @@ def test_format_with_tab_size_option(workspace): def test_format_with_insert_spaces_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) - res = pylsp_format_document(doc, { "insertSpaces": False }) + res = pylsp_format_document(doc, {"insertSpaces": False}) assert len(res) == 1 assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t") @@ -90,7 +91,7 @@ def test_format_with_insert_spaces_option(workspace): def test_format_with_yapf_specific_option(workspace): doc = Document(DOC_URI, workspace, FOUR_SPACE_DOC) - res = pylsp_format_document(doc, { "USE_TABS": True }) + res = pylsp_format_document(doc, {"USE_TABS": True}) assert len(res) == 1 assert res[0]['newText'] == FOUR_SPACE_DOC.replace(" ", "\t")