Skip to content
Open
Show file tree
Hide file tree
Changes from all 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: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ This project has the following main goals:
- [Full Galaxy tool linter integration](#document-validation)
- [Document Outline](#document-outline)
- [Insert param reference](#insert-param-reference)
- [Automatically update tests to comply with 24.2 profile validation](#automatically-update-tests-to-comply-with-242-profile-validation) _New feature!_ ✨
- [Automatically update tests to comply with 24.2 profile validation](#automatically-update-tests-to-comply-with-242-profile-validation)
- [Rename tool parameters](#rename-tool-parameters) _New feature!_ ✨

# Getting Started

Expand Down Expand Up @@ -182,3 +183,13 @@ A new command is available to update old tests to comply with the 24.2 profile v
You can use this command to automatically update the tests to meet the new validation rules. The command is accessible from the command palette as `Galaxy Tools: Update existing test cases to comply with 24.2 profile validation`, or you can use the default key binding `ctrl+alt+u`.

For more details about how this command works, you can check an example in this [Pull Request](https://github.com/galaxyproject/galaxy-language-server/pull/278).

## Rename Tool Parameters

> This feature requires the optional [`galaxy-tool-source`](https://pypi.org/project/galaxy-tool-source/) engine. Install it into the same environment as the language server with `pip install galaxy-tool-source`; the feature self-registers once that package is present.

Rename a tool parameter and every reference to it in a single edit. Place the cursor on a `<param>` (or any `$param` reference) and invoke **Rename Symbol** (`F2`). The rename updates the definition and every live reference — through `#if` directives, dotted `$param.metadata` accesses, output labels, by-name cross-reference attributes and the `<tests>` mirror — while leaving occurrences inside `#raw` blocks, `##` comments and `<help>` prose untouched.

The rename **spans imported macro files**: a reference that lives only in a macro the tool `<import>`s is rewritten too, so it is never silently left dangling. When a macro is **shared** by other tools in the workspace, the rename is refused (rather than leave the sibling tools referencing the old name) with a pointer to the [`galaxy-tool-refactor`](https://github.com/galaxyproject/galaxy-tool-refactor) CLI (`rename-param --across-importers`), which renames across every importer at once. If a parameter cannot be renamed safely, the editor reports the specific reason.

**Find All References** for the same parameters is available too (`Shift+F12`), listing every occurrence across the tool and its imported macros.
13 changes: 12 additions & 1 deletion client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ Since version `0.4.0` you can use some of the cool features of [planemo](https:/
- [Full Galaxy tool linter integration](#document-validation)
- [Document Outline](#document-outline)
- [Insert param reference](#insert-param-reference)
- [Automatically update tests to comply with 24.2 profile validation](#automatically-update-tests-to-comply-with-242-profile-validation) _New feature!_ ✨
- [Automatically update tests to comply with 24.2 profile validation](#automatically-update-tests-to-comply-with-242-profile-validation)
- [Rename tool parameters](#rename-tool-parameters) _New feature!_ ✨

# Installation

Expand Down Expand Up @@ -219,3 +220,13 @@ A new command is available to update old tests to comply with the 24.2 profile v
You can use this command to automatically update the tests to meet the new validation rules. The command is accessible from the command palette as `Galaxy Tools: Update existing test cases to comply with 24.2 profile validation`, or you can use the default key binding `ctrl+alt+u`.

For more details about how this command works, you can check an example in this [Pull Request](https://github.com/galaxyproject/galaxy-language-server/pull/278).

## Rename Tool Parameters

> This feature requires the optional [`galaxy-tool-source`](https://pypi.org/project/galaxy-tool-source/) engine. Install it into the same environment as the language server with `pip install galaxy-tool-source`; the feature self-registers once that package is present.

Rename a tool parameter and every reference to it in a single edit. Place the cursor on a `<param>` (or any `$param` reference) and invoke **Rename Symbol** (`F2`). The rename updates the definition and every live reference — through `#if` directives, dotted `$param.metadata` accesses, output labels, by-name cross-reference attributes and the `<tests>` mirror — while leaving occurrences inside `#raw` blocks, `##` comments and `<help>` prose untouched.

The rename **spans imported macro files**: a reference that lives only in a macro the tool `<import>`s is rewritten too, so it is never silently left dangling. When a macro is **shared** by other tools in the workspace, the rename is refused (rather than leave the sibling tools referencing the old name) with a pointer to the [`galaxy-tool-refactor`](https://github.com/galaxyproject/galaxy-tool-refactor) CLI (`rename-param --across-importers`), which renames across every importer at once. If a parameter cannot be renamed safely, the editor reports the specific reason.

**Find All References** for the same parameters is available too (`Shift+F12`), listing every occurrence across the tool and its imported macros.
6 changes: 6 additions & 0 deletions server/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Galaxy Language Server Changelog

## [Unreleased]

### Added

- Add **Rename Symbol** and **Find All References** for tool parameters, spanning the tool and its imported macro files. Backed by the optional [`galaxy-tool-source`](https://pypi.org/project/galaxy-tool-source/) engine ([#331](https://github.com/galaxyproject/galaxy-language-server/pull/331)).

## [0.15.0] - 2026-02-16

### Changed
Expand Down
43 changes: 42 additions & 1 deletion server/galaxyls/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
TEXT_DOCUMENT_DOCUMENT_SYMBOL,
TEXT_DOCUMENT_FORMATTING,
TEXT_DOCUMENT_HOVER,
TEXT_DOCUMENT_PREPARE_RENAME,
TEXT_DOCUMENT_REFERENCES,
TEXT_DOCUMENT_RENAME,
WORKSPACE_DID_CHANGE_CONFIGURATION,
CodeAction,
CodeActionKind,
Expand All @@ -37,18 +40,27 @@
Location,
LogMessageParams,
MessageType,
PrepareRenameParams,
PublishDiagnosticsParams,
Range,
ReferenceParams,
RenameOptions,
RenameParams,
ShowMessageParams,
TextDocumentIdentifier,
TextDocumentPositionParams,
TextEdit,
WorkspaceEdit,
)
from pygls.lsp.server import LanguageServer
from pygls.workspace import TextDocument

from galaxyls.config import CompletionMode, GalaxyToolsConfiguration
from galaxyls.constants import Commands
from galaxyls.services.language import GalaxyToolLanguageService
from galaxyls.services.language import (
RENAME_FEATURE_AVAILABLE,
GalaxyToolLanguageService,
)
from galaxyls.services.validation import DocumentValidator
from galaxyls.services.xml.document import XmlDocument
from galaxyls.services.xml.parser import XmlDocumentParser
Expand Down Expand Up @@ -175,6 +187,35 @@ def definition(server: GalaxyToolsLanguageServer, params: TextDocumentPositionPa
return None


# The parameter Rename Symbol / Find References feature depends on an optional engine
# (galaxy-tool-source); only advertise it to clients when that engine is installed.
if RENAME_FEATURE_AVAILABLE:

@language_server.feature(TEXT_DOCUMENT_PREPARE_RENAME)
def prepare_rename(server: GalaxyToolsLanguageServer, params: PrepareRenameParams) -> Range | None:
"""Checks whether the symbol under the cursor (a tool parameter) can be renamed."""
document = _get_valid_document(server, params.text_document.uri)
if document:
return server.service.prepare_param_rename(document, params.position)
return None

@language_server.feature(TEXT_DOCUMENT_RENAME, RenameOptions(prepare_provider=True))
def rename(server: GalaxyToolsLanguageServer, params: RenameParams) -> WorkspaceEdit | None:
"""Renames a tool parameter and every reference to it across the document."""
document = _get_valid_document(server, params.text_document.uri)
if document:
return server.service.rename_param(document, params.position, params.new_name)
return None

@language_server.feature(TEXT_DOCUMENT_REFERENCES)
def references(server: GalaxyToolsLanguageServer, params: ReferenceParams) -> list[Location] | None:
"""Finds every occurrence of the tool parameter under the cursor."""
document = _get_valid_document(server, params.text_document.uri)
if document:
return server.service.get_param_references(document, params.position)
return None


@language_server.feature(TEXT_DOCUMENT_DOCUMENT_LINK)
def document_link(server: GalaxyToolsLanguageServer, params: DocumentLinkParams) -> list[DocumentLink]:
document = _get_valid_document(server, params.text_document.uri)
Expand Down
32 changes: 32 additions & 0 deletions server/galaxyls/services/language.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Position,
Range,
TextEdit,
WorkspaceEdit,
)
from pygls.workspace import (
TextDocument,
Expand All @@ -37,6 +38,16 @@
RefactoringService,
RefactorMacrosService,
)

try:
# Optional: the parameter rename/references engine (galaxy-tool-source). The feature
# self-registers only when it is importable, so the server still works without it.
from galaxyls.services.tools.rename import RenameService

RENAME_FEATURE_AVAILABLE = True
except ImportError:
RenameService = None # type: ignore[assignment, misc]
RENAME_FEATURE_AVAILABLE = False
from galaxyls.services.tools.testing import ToolTestsDiscoveryService

from ..config import CompletionMode
Expand Down Expand Up @@ -76,8 +87,11 @@ def __init__(self) -> None:
self.link_provider = DocumentLinksProvider()
self.symbols_provider = DocumentSymbolsProvider()
self.param_references_provider = ParamReferencesProvider()
self.rename_service = RenameService() if RENAME_FEATURE_AVAILABLE else None

def set_workspace(self, workspace: Workspace) -> None:
if self.rename_service is not None:
self.rename_service.set_workspace(workspace)
macro_definitions_provider = MacroDefinitionsProvider(workspace)
self.definitions_provider = DocumentDefinitionsProvider(macro_definitions_provider)
self.completion_service = XmlCompletionService(self.xsd_tree, self.definitions_provider)
Expand Down Expand Up @@ -174,3 +188,21 @@ def go_to_definition(self, xml_document: XmlDocument, position: Position) -> lis
if self.definitions_provider:
return self.definitions_provider.go_to_definition(xml_document, position)
return None

def prepare_param_rename(self, document: TextDocument, position: Position) -> Range | None:
"""Returns the renameable range under the cursor, or None to reject the rename."""
if self.rename_service is None:
return None
return self.rename_service.prepare_rename(document, position)

def rename_param(self, document: TextDocument, position: Position, new_name: str) -> WorkspaceEdit | None:
"""Returns a minimal WorkspaceEdit renaming the parameter under the cursor."""
if self.rename_service is None:
return None
return self.rename_service.rename(document, position, new_name)

def get_param_references(self, document: TextDocument, position: Position) -> list[Location] | None:
"""Returns every occurrence of the parameter under the cursor (definition + references)."""
if self.rename_service is None:
return None
return self.rename_service.find_references(document, position)
Loading
Loading