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

Fix Autopep8 and Yapf formatting with CR line endings #151

Merged
merged 4 commits into from
Jan 31, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
13 changes: 13 additions & 0 deletions pylsp/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

JEDI_VERSION = jedi.__version__

# Eol chars accepted by the LSP protocol
EOL_CHARS = ['\r\n', '\r', '\n']

log = logging.getLogger(__name__)


Expand Down Expand Up @@ -220,3 +223,13 @@ def is_process_alive(pid):
return e.errno == errno.EPERM
else:
return True


def get_eol_chars(text):
"""Get EOL chars used in text."""
for eol_chars in EOL_CHARS:
if text.find(eol_chars) > -1:
break
else:
return None
return eol_chars
ccordoba12 marked this conversation as resolved.
Show resolved Hide resolved
19 changes: 17 additions & 2 deletions pylsp/plugins/autopep8_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
# Copyright 2021- Python Language Server Contributors.

import logging

import pycodestyle
from autopep8 import fix_code, continued_indentation as autopep8_c_i

from pylsp import hookimpl
from pylsp._utils import get_eol_chars

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -38,15 +41,27 @@ def _format(config, document, line_range=None):
del pycodestyle._checks['logical_line'][pycodestyle.continued_indentation]
pycodestyle.register_check(autopep8_c_i)

new_source = fix_code(document.source, options=options)
# Autopep8 doesn't work with CR line endings, so we replace them by '\n'
# and restore them below.
replace_cr = False
source = document.source
eol_chars = get_eol_chars(source)
if eol_chars == '\r':
replace_cr = True
source = source.replace('\r', '\n')

new_source = fix_code(source, options=options)

# Switch it back
del pycodestyle._checks['logical_line'][autopep8_c_i]
pycodestyle.register_check(pycodestyle.continued_indentation)

if new_source == document.source:
if new_source == source:
return []

if replace_cr:
new_source = new_source.replace('\n', '\r')

# I'm too lazy at the moment to parse diffs into TextEdit items
# So let's just return the entire file...
return [{
Expand Down
17 changes: 16 additions & 1 deletion pylsp/plugins/yapf_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

import logging
import os

from yapf.yapflib import file_resources
from yapf.yapflib.yapf_api import FormatCode

from pylsp import hookimpl
from pylsp._utils import get_eol_chars

log = logging.getLogger(__name__)

Expand Down Expand Up @@ -34,8 +37,17 @@ def pylsp_format_range(document, range): # pylint: disable=redefined-builtin


def _format(document, lines=None):
# Yapf doesn't work with CR line endings, so we replace them by '\n'
# and restore them below.
replace_cr = False
source = document.source
eol_chars = get_eol_chars(source)
if eol_chars == '\r':
replace_cr = True
source = source.replace('\r', '\n')

new_source, changed = FormatCode(
document.source,
source,
lines=lines,
filename=document.filename,
style_config=file_resources.GetDefaultStyleForDir(
Expand All @@ -46,6 +58,9 @@ def _format(document, lines=None):
if not changed:
return []

if replace_cr:
new_source = new_source.replace('\n', '\r')

# I'm too lazy at the moment to parse diffs into TextEdit items
# So let's just return the entire file...
return [{
Expand Down
7 changes: 7 additions & 0 deletions test/plugins/test_autopep8_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,10 @@ def test_hanging_indentation(config, workspace):

assert len(res) == 1
assert res[0]['newText'] == CORRECT_INDENTED_DOC


def test_cr_line_endings(config, workspace):
doc = Document(DOC_URI, workspace, 'import os;import sys\r\rdict(a=1)')
res = pylsp_format_document(config, doc)

assert res[0]['newText'] == 'import os\rimport sys\r\rdict(a=1)\r'
7 changes: 7 additions & 0 deletions test/plugins/test_yapf_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,10 @@ def test_config_file(tmpdir, workspace):

# A was split on multiple lines because of column_limit from config file
assert pylsp_format_document(doc)[0]['newText'] == "A = [\n 'h', 'w',\n 'a'\n]\n\nB = ['h', 'w']\n"


def test_cr_line_endings(workspace):
doc = Document(DOC_URI, workspace, 'import os;import sys\r\rdict(a=1)')
res = pylsp_format_document(doc)

assert res[0]['newText'] == 'import os\rimport sys\r\rdict(a=1)\r'