@@ -79,11 +79,18 @@ def pylsp_format_document(workspace: Workspace, document: Document) -> Generator
79
79
"""
80
80
log .debug (f"textDocument/formatting: { document } " )
81
81
outcome = yield
82
- results = outcome .get_result ()
83
- if results :
84
- document .source = results [0 ]["new_text" ]
82
+ result = outcome .get_result ()
83
+ if result :
84
+ source = result [0 ]["newText" ]
85
+ else :
86
+ source = document .source
87
+
88
+ new_text = run_ruff_format (workspace , document .path , document_source = source )
89
+
90
+ # Avoid applying empty text edit
91
+ if new_text == source :
92
+ return
85
93
86
- new_text = run_ruff_format (workspace , document )
87
94
range = Range (
88
95
start = Position (line = 0 , character = 0 ),
89
96
end = Position (line = len (document .lines ), character = 0 ),
@@ -331,7 +338,9 @@ def create_text_edits(fix: RuffFix) -> List[TextEdit]:
331
338
332
339
333
340
def run_ruff_check (workspace : Workspace , document : Document ) -> List [RuffCheck ]:
334
- result = run_ruff (workspace , document )
341
+ result = run_ruff (
342
+ workspace , document_path = document .path , document_source = document .source
343
+ )
335
344
try :
336
345
result = json .loads (result )
337
346
except json .JSONDecodeError :
@@ -340,23 +349,39 @@ def run_ruff_check(workspace: Workspace, document: Document) -> List[RuffCheck]:
340
349
341
350
342
351
def run_ruff_fix (workspace : Workspace , document : Document ) -> str :
343
- result = run_ruff (workspace , document , fix = True )
352
+ result = run_ruff (
353
+ workspace ,
354
+ document_path = document .path ,
355
+ document_source = document .source ,
356
+ fix = True ,
357
+ )
344
358
return result
345
359
346
360
347
- def run_ruff_format (workspace : Workspace , document : Document ) -> str :
348
- settings = load_settings (workspace , document )
361
+ def run_ruff_format (
362
+ workspace : Workspace , document_path : str , document_source : str
363
+ ) -> str :
364
+ settings = load_settings (workspace , document_path )
349
365
fixable_codes = ["I" ]
350
366
if settings .format :
351
367
fixable_codes .extend (settings .format )
352
- extra_arguments = [f"--fixable={ ',' .join (fixable_codes )} " ]
353
- result = run_ruff (workspace , document , fix = True , extra_arguments = extra_arguments )
368
+ extra_arguments = [
369
+ f"--fixable={ ',' .join (fixable_codes )} " ,
370
+ ]
371
+ result = run_ruff (
372
+ workspace ,
373
+ document_path ,
374
+ document_source ,
375
+ fix = True ,
376
+ extra_arguments = extra_arguments ,
377
+ )
354
378
return result
355
379
356
380
357
381
def run_ruff (
358
382
workspace : Workspace ,
359
- document : Document ,
383
+ document_path : str ,
384
+ document_source : str ,
360
385
fix : bool = False ,
361
386
extra_arguments : Optional [List [str ]] = None ,
362
387
) -> str :
@@ -367,8 +392,11 @@ def run_ruff(
367
392
----------
368
393
workspace : pyls.workspace.Workspace
369
394
Workspace to run ruff in.
370
- document : pylsp.workspace.Document
371
- File to run ruff on.
395
+ document_path : str
396
+ Path to file to run ruff on.
397
+ document_source : str
398
+ Document source or to apply ruff on.
399
+ Needed when the source differs from the file source, e.g. during formatting.
372
400
fix : bool
373
401
Whether to run fix or no-fix.
374
402
extra_arguments : List[str]
@@ -378,11 +406,11 @@ def run_ruff(
378
406
-------
379
407
String containing the result in json format.
380
408
"""
381
- settings = load_settings (workspace , document )
409
+ settings = load_settings (workspace , document_path )
382
410
executable = settings .executable
383
- arguments = build_arguments (document , settings , fix , extra_arguments )
411
+ arguments = build_arguments (document_path , settings , fix , extra_arguments )
384
412
385
- log .debug (f"Calling { executable } with args: { arguments } on '{ document . path } '" )
413
+ log .debug (f"Calling { executable } with args: { arguments } on '{ document_path } '" )
386
414
try :
387
415
cmd = [executable ]
388
416
cmd .extend (arguments )
@@ -392,7 +420,7 @@ def run_ruff(
392
420
cmd = [sys .executable , "-m" , "ruff" ]
393
421
cmd .extend (arguments )
394
422
p = Popen (cmd , stdin = PIPE , stdout = PIPE , stderr = PIPE )
395
- (stdout , stderr ) = p .communicate (document . source .encode ())
423
+ (stdout , stderr ) = p .communicate (document_source .encode ())
396
424
397
425
if stderr :
398
426
log .error (f"Error running ruff: { stderr .decode ()} " )
@@ -401,7 +429,7 @@ def run_ruff(
401
429
402
430
403
431
def build_arguments (
404
- document : Document ,
432
+ document_path : str ,
405
433
settings : PluginSettings ,
406
434
fix : bool = False ,
407
435
extra_arguments : Optional [List [str ]] = None ,
@@ -437,8 +465,8 @@ def build_arguments(
437
465
# Always force excludes
438
466
args .append ("--force-exclude" )
439
467
# Pass filename to ruff for per-file-ignores, catch unsaved
440
- if document . path != "" :
441
- args .append (f"--stdin-filename={ document . path } " )
468
+ if document_path != "" :
469
+ args .append (f"--stdin-filename={ document_path } " )
442
470
443
471
if settings .config :
444
472
args .append (f"--config={ settings .config } " )
@@ -463,7 +491,7 @@ def build_arguments(
463
491
464
492
if settings .per_file_ignores :
465
493
for path , errors in settings .per_file_ignores .items ():
466
- if not PurePath (document . path ).match (path ):
494
+ if not PurePath (document_path ).match (path ):
467
495
continue
468
496
args .append (f"--ignore={ ',' .join (errors )} " )
469
497
@@ -475,27 +503,27 @@ def build_arguments(
475
503
return args
476
504
477
505
478
- def load_settings (workspace : Workspace , document : Document ) -> PluginSettings :
506
+ def load_settings (workspace : Workspace , document_path : str ) -> PluginSettings :
479
507
"""
480
508
Load settings from pyproject.toml file in the project path.
481
509
482
510
Parameters
483
511
----------
484
512
workspace : pylsp.workspace.Workspace
485
513
Current workspace.
486
- document : pylsp.workspace.Document
487
- Document to apply ruff on.
514
+ document_path : str
515
+ Path to the document to apply ruff on.
488
516
489
517
Returns
490
518
-------
491
519
PluginSettings read via lsp.
492
520
"""
493
521
config = workspace ._config
494
- _plugin_settings = config .plugin_settings ("ruff" , document_path = document . path )
522
+ _plugin_settings = config .plugin_settings ("ruff" , document_path = document_path )
495
523
plugin_settings = converter .structure (_plugin_settings , PluginSettings )
496
524
497
525
pyproject_file = find_parents (
498
- workspace .root_path , document . path , ["pyproject.toml" ]
526
+ workspace .root_path , document_path , ["pyproject.toml" ]
499
527
)
500
528
501
529
# Check if pyproject is present, ignore user settings if toml exists
0 commit comments