@@ -1215,14 +1215,41 @@ async def apply_format(arguments: tuple[TextDocument]):
12151215
12161216
12171217@LSP_SERVER .feature (TEXT_DOCUMENT_FORMATTING )
1218- async def format_document (
1219- params : DocumentFormattingParams , range : Range | None = None
1218+ async def format_document (params : DocumentFormattingParams ) -> list [TextEdit ] | None :
1219+ return await _format_document_impl (params , None )
1220+
1221+
1222+ @LSP_SERVER .feature (
1223+ TEXT_DOCUMENT_RANGE_FORMATTING ,
1224+ DocumentRangeFormattingRegistrationOptions (
1225+ document_selector = [
1226+ TextDocumentFilter_Type1 (language = "python" , scheme = "file" ),
1227+ TextDocumentFilter_Type1 (language = "python" , scheme = "untitled" ),
1228+ ],
1229+ ranges_support = False ,
1230+ work_done_progress = False ,
1231+ ),
1232+ )
1233+ async def format_document_range (
1234+ params : DocumentRangeFormattingParams ,
1235+ ) -> list [TextEdit ] | None :
1236+ return await _format_document_impl (
1237+ DocumentFormattingParams (
1238+ params .text_document , params .options , params .work_done_token
1239+ ),
1240+ params .range ,
1241+ )
1242+
1243+
1244+ async def _format_document_impl (
1245+ params : DocumentFormattingParams , range : Range | None
12201246) -> list [TextEdit ] | None :
12211247 # For a Jupyter Notebook, this request can only format a single cell as the
12221248 # request itself can only act on a text document. A cell in a Notebook is
12231249 # represented as a text document. The "Notebook: Format notebook" action calls
12241250 # this request for every cell.
12251251 document = Document .from_cell_or_text_uri (params .text_document .uri )
1252+
12261253 settings = _get_settings_by_document (document .path )
12271254
12281255 # We don't support range formatting of notebooks yet but VS Code
@@ -1253,28 +1280,6 @@ async def format_document(
12531280 )
12541281
12551282
1256- @LSP_SERVER .feature (
1257- TEXT_DOCUMENT_RANGE_FORMATTING ,
1258- DocumentRangeFormattingRegistrationOptions (
1259- document_selector = [
1260- TextDocumentFilter_Type1 (language = "python" , scheme = "file" ),
1261- TextDocumentFilter_Type1 (language = "python" , scheme = "untitled" ),
1262- ],
1263- ranges_support = False ,
1264- work_done_progress = False ,
1265- ),
1266- )
1267- async def format_document_range (
1268- params : DocumentRangeFormattingParams ,
1269- ) -> list [TextEdit ] | None :
1270- return await format_document (
1271- DocumentFormattingParams (
1272- params .text_document , params .options , params .work_done_token
1273- ),
1274- params .range ,
1275- )
1276-
1277-
12781283async def _fix_document_impl (
12791284 document : Document ,
12801285 settings : WorkspaceSettings ,
@@ -1913,23 +1918,15 @@ async def _run_format_on_document(
19131918 ]
19141919
19151920 if format_range :
1916- # Convert the start and end to character offsets instead of line:column
1917- lines = document .source .splitlines (True )
19181921 codec = PositionCodec (PositionEncodingKind .Utf16 )
1919- range = codec .range_from_client_units (lines , format_range )
1920- start = format_range .start .character
1921- end = format_range .end .character
1922-
1923- for index , line in enumerate (lines ):
1924- if index < range .start .line :
1925- start += len (line )
1926-
1927- if index < range .end .line :
1928- end += len (line )
1929- else :
1930- break
1922+ format_range = codec .range_from_client_units (document .source .splitlines (True ), format_range )
19311923
1932- argv .extend (["--range-start" , str (start ), "--range-end" , str (end )])
1924+ argv .extend (
1925+ [
1926+ "--range" ,
1927+ f"{ format_range .start .line + 1 } :{ format_range .start .character + 1 } -{ format_range .end .line + 1 } :{ format_range .end .character + 1 } " ,
1928+ ]
1929+ )
19331930
19341931 for arg in settings .get ("format" , {}).get ("args" , []):
19351932 if arg in UNSUPPORTED_FORMAT_ARGS :
0 commit comments