@@ -79,11 +79,18 @@ def pylsp_format_document(workspace: Workspace, document: Document) -> Generator
7979 """
8080 log .debug (f"textDocument/formatting: { document } " )
8181 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
8593
86- new_text = run_ruff_format (workspace , document )
8794 range = Range (
8895 start = Position (line = 0 , character = 0 ),
8996 end = Position (line = len (document .lines ), character = 0 ),
@@ -331,7 +338,9 @@ def create_text_edits(fix: RuffFix) -> List[TextEdit]:
331338
332339
333340def 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+ )
335344 try :
336345 result = json .loads (result )
337346 except json .JSONDecodeError :
@@ -340,23 +349,39 @@ def run_ruff_check(workspace: Workspace, document: Document) -> List[RuffCheck]:
340349
341350
342351def 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+ )
344358 return result
345359
346360
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 )
349365 fixable_codes = ["I" ]
350366 if settings .format :
351367 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+ )
354378 return result
355379
356380
357381def run_ruff (
358382 workspace : Workspace ,
359- document : Document ,
383+ document_path : str ,
384+ document_source : str ,
360385 fix : bool = False ,
361386 extra_arguments : Optional [List [str ]] = None ,
362387) -> str :
@@ -367,8 +392,11 @@ def run_ruff(
367392 ----------
368393 workspace : pyls.workspace.Workspace
369394 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.
372400 fix : bool
373401 Whether to run fix or no-fix.
374402 extra_arguments : List[str]
@@ -378,11 +406,11 @@ def run_ruff(
378406 -------
379407 String containing the result in json format.
380408 """
381- settings = load_settings (workspace , document )
409+ settings = load_settings (workspace , document_path )
382410 executable = settings .executable
383- arguments = build_arguments (document , settings , fix , extra_arguments )
411+ arguments = build_arguments (document_path , settings , fix , extra_arguments )
384412
385- log .debug (f"Calling { executable } with args: { arguments } on '{ document . path } '" )
413+ log .debug (f"Calling { executable } with args: { arguments } on '{ document_path } '" )
386414 try :
387415 cmd = [executable ]
388416 cmd .extend (arguments )
@@ -392,7 +420,7 @@ def run_ruff(
392420 cmd = [sys .executable , "-m" , "ruff" ]
393421 cmd .extend (arguments )
394422 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 ())
396424
397425 if stderr :
398426 log .error (f"Error running ruff: { stderr .decode ()} " )
@@ -401,7 +429,7 @@ def run_ruff(
401429
402430
403431def build_arguments (
404- document : Document ,
432+ document_path : str ,
405433 settings : PluginSettings ,
406434 fix : bool = False ,
407435 extra_arguments : Optional [List [str ]] = None ,
@@ -437,8 +465,8 @@ def build_arguments(
437465 # Always force excludes
438466 args .append ("--force-exclude" )
439467 # 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 } " )
442470
443471 if settings .config :
444472 args .append (f"--config={ settings .config } " )
@@ -463,7 +491,7 @@ def build_arguments(
463491
464492 if settings .per_file_ignores :
465493 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 ):
467495 continue
468496 args .append (f"--ignore={ ',' .join (errors )} " )
469497
@@ -475,27 +503,27 @@ def build_arguments(
475503 return args
476504
477505
478- def load_settings (workspace : Workspace , document : Document ) -> PluginSettings :
506+ def load_settings (workspace : Workspace , document_path : str ) -> PluginSettings :
479507 """
480508 Load settings from pyproject.toml file in the project path.
481509
482510 Parameters
483511 ----------
484512 workspace : pylsp.workspace.Workspace
485513 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.
488516
489517 Returns
490518 -------
491519 PluginSettings read via lsp.
492520 """
493521 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 )
495523 plugin_settings = converter .structure (_plugin_settings , PluginSettings )
496524
497525 pyproject_file = find_parents (
498- workspace .root_path , document . path , ["pyproject.toml" ]
526+ workspace .root_path , document_path , ["pyproject.toml" ]
499527 )
500528
501529 # Check if pyproject is present, ignore user settings if toml exists
0 commit comments