8000 Fix Autopep8 and Yapf formatting with CR line endings (#151) · python-lsp/python-lsp-server@2f7a13e · GitHub
[go: up one dir, main page]

Skip to content

Commit 2f7a13e

Browse files
Fix Autopep8 and Yapf formatting with CR line endings (#151)
Co-authored-by: Michał Krassowski <5832902+krassowski@users.noreply.github.com>
1 parent 963fd4d commit 2f7a13e

File tree

5 files changed

+60
-3
lines changed

5 files changed

+60
-3
lines changed

pylsp/_utils.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
import logging
77
import os
88
import pathlib
9+
import re
910
import threading
1011

1112
import jedi
1213

1314
JEDI_VERSION = jedi.__version__
1415

16+
# Eol chars accepted by the LSP protocol
17+
EOL_CHARS = ['\r\n', '\r', '\n']
18+
EOL_REGEX = re.compile(f'({"|".join(EOL_CHARS)})')
19+
1520
log = logging.getLogger(__name__)
1621

1722

@@ -220,3 +225,11 @@ def is_process_alive(pid):
220225
return e.errno == errno.EPERM
221226
else:
222227
return True
228+
229+
230+
def get_eol_chars(text):
231+
"""Get EOL chars used in text."""
232+
match = EOL_REGEX.search(text)
233+
if match:
234+
return match.group(0)
235+
return None

pylsp/plugins/autopep8_format.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
# Copyright 2021- Python Language Server Contributors.
33

44
import logging
5+
56
import pycodestyle
67
from autopep8 import fix_code, continued_indentation as autopep8_c_i
8+
79
from pylsp import hookimpl
10+
from pylsp._utils import get_eol_chars
811

912
log = logging.getLogger(__name__)
1013

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

41-
new_source = fix_code(document.source, options=options)
44+
# Autopep8 doesn't work with CR line endings, so we replace them by '\n'
45+
# and restore them below.
46+
replace_cr = False
47+
source = document.source
48+
eol_chars = get_eol_chars(source)
49+
if eol_chars == '\r':
50+
replace_cr = True
51+
source = source.replace('\r', '\n')
52+
53+
new_source = fix_code(source, options=options)
4254

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

47-
if new_source == document.source:
59+
if new_source == source:
4860
return []
4961

62+
if replace_cr:
63+
new_source = new_source.replace('\n', '\r')
64+
5065
# I'm too lazy at the moment to parse diffs into TextEdit items
5166
# So let's just return the entire file...
5267
return [{

pylsp/plugins/yapf_format.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33

44
import logging
55
import os
6+
67
from yapf.yapflib import file_resources
78
from yapf.yapflib.yapf_api import FormatCode
9+
810
from pylsp import hookimpl
11+
from pylsp._utils import get_eol_chars
912

1013
log = logging.getLogger(__name__)
1114

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

3538

3639
def _format(document, lines=None):
40+
# Yapf doesn't work with CR line endings, so we replace them by '\n'
41+
# and restore them below.
42+
replace_cr = False
43+
source = document.source
44+
eol_chars = get_eol_chars(source)
45+
if eol_chars == '\r':
46+
replace_cr = True
47+
source = source.replace('\r', '\n')
48+
3749
new_source, changed = FormatCode(
38-
document.source,
50+
source,
3951
lines=lines,
4052
filename=document.filename,
4153
style_config=file_resources.GetDefaultStyleForDir(
@@ -46,6 +58,9 @@ def _format(document, lines=None):
4658
if not changed:
4759
return []
4860

61+
if replace_cr:
62+
new_source = new_source.replace('\n', '\r')
63+
4964
# I'm too lazy at the moment to parse diffs into TextEdit items
5065
# So let's just return the entire file...
5166
return [{

test/plugins/test_autopep8_format.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,10 @@ def test_hanging_indentation(config, workspace):
7171

7272
assert len(res) == 1
7373
assert res[0]['newText'] == CORRECT_INDENTED_DOC
74+
75+
76+
def test_cr_line_endings(config, workspace):
77+
doc = Document(DOC_URI, workspace, 'import os;import sys\r\rdict(a=1)')
78+
res = pylsp_format_document(config, doc)
79+
80+
assert res[0]['newText'] == 'import os\rimport sys\r\rdict(a=1)\r'

test/plugins/test_yapf_format.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,10 @@ def test_config_file(tmpdir, workspace):
5858

5959
# A was split on multiple lines because of column_limit from config file
6060
assert pylsp_format_document(doc)[0]['newText'] == "A = [\n 'h', 'w',\n 'a'\n]\n\nB = ['h', 'w']\n"
61+
62+
63+
def test_cr_line_endings(workspace):
64+
doc = Document(DOC_URI, workspace, 'import os;import sys\r\rdict(a=1)')
65+
res = pylsp_format_document(doc)
66+
67+
assert res[0]['newText'] == 'import os\rimport sys\r\rdict(a=1)\r'

0 commit comments

Comments
 (0)
0