From 024a96d2cae1c52ad6d96cd3567d41098d8b0c41 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:01:29 +0200 Subject: [PATCH 1/9] Add method for retrieving input parameters in GalaxyToolXmlDocument --- server/galaxyls/services/tools/document.py | 11 +++++++++++ server/galaxyls/services/xml/nodes.py | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/server/galaxyls/services/tools/document.py b/server/galaxyls/services/tools/document.py index 779a94f..897a3c1 100644 --- a/server/galaxyls/services/tools/document.py +++ b/server/galaxyls/services/tools/document.py @@ -169,6 +169,17 @@ def get_outputs(self) -> List[XmlElement]: return outputs.elements return [] + def get_input_params(self) -> List[XmlElement]: + """Gets the input params of this document as a list of elements. + + Returns: + List[XmlElement]: The params defined in the document. + """ + inputs = self.find_element(INPUTS) + if inputs: + return inputs.get_recursive_descendants_with_name("param") + return [] + def get_tool_element(self) -> Optional[XmlElement]: """Gets the root tool element""" return self.find_element(TOOL) diff --git a/server/galaxyls/services/xml/nodes.py b/server/galaxyls/services/xml/nodes.py index 994b9f8..f3fc9d1 100644 --- a/server/galaxyls/services/xml/nodes.py +++ b/server/galaxyls/services/xml/nodes.py @@ -421,6 +421,15 @@ def get_children_with_name(self, name: str) -> List["XmlElement"]: children = [child for child in self.children if child.name == name] return list(children) + def get_recursive_descendants_with_name(self, name: str) -> List["XmlElement"]: + descendants = [] + for child in self.children: + if child.name == name: + descendants.append(child) + if isinstance(child, XmlElement): + descendants.extend(child.get_recursive_descendants_with_name(name)) + return descendants + def get_cdata_section(self) -> Optional["XmlCDATASection"]: """Gets the CDATA node inside this element or None if it doesn't have a CDATA section.""" return next((node for node in self.children if type(node) is XmlCDATASection), None) From b1fe26b70085ef2fced717ab2ede8b1bd495e7e3 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:02:58 +0200 Subject: [PATCH 2/9] Implement basic ParamReferencesProvider --- server/galaxyls/services/language.py | 2 + server/galaxyls/services/references.py | 51 ++++++++++++++++++++++++++ server/galaxyls/types.py | 10 +++++ 3 files changed, 63 insertions(+) create mode 100644 server/galaxyls/services/references.py diff --git a/server/galaxyls/services/language.py b/server/galaxyls/services/language.py index a0834ce..3abacdb 100644 --- a/server/galaxyls/services/language.py +++ b/server/galaxyls/services/language.py @@ -26,6 +26,7 @@ from galaxyls.services.definitions import DocumentDefinitionsProvider from galaxyls.services.links import DocumentLinksProvider from galaxyls.services.macros import MacroExpanderService +from galaxyls.services.references import ParamReferencesProvider from galaxyls.services.symbols import DocumentSymbolsProvider from galaxyls.services.tools.common import ( TestsDiscoveryService, @@ -78,6 +79,7 @@ def __init__(self) -> None: self.definitions_provider: Optional[DocumentDefinitionsProvider] = None self.link_provider = DocumentLinksProvider() self.symbols_provider = DocumentSymbolsProvider() + self.param_references_provider = ParamReferencesProvider() def set_workspace(self, workspace: Workspace) -> None: macro_definitions_provider = MacroDefinitionsProvider(workspace) diff --git a/server/galaxyls/services/references.py b/server/galaxyls/services/references.py new file mode 100644 index 0000000..1cd975f --- /dev/null +++ b/server/galaxyls/services/references.py @@ -0,0 +1,51 @@ +from typing import Optional + +from galaxyls.services.tools.document import GalaxyToolXmlDocument +from galaxyls.services.xml.document import XmlDocument +from galaxyls.services.xml.nodes import XmlElement +from galaxyls.types import ParamReferencesResult + + +class ParamReferencesProvider: + def get_param_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: + # TODO: Should work with expanded documents + + tool = GalaxyToolXmlDocument.from_xml_document(xml_document) + references = [] + params = tool.get_input_params() + for param in params: + reference = self._build_reference(param) + if reference: + references.append(reference) + + return ParamReferencesResult(references) + + def _build_reference(self, param: XmlElement) -> Optional[str]: + reference = None + # The reference should be a string with the path to the param separated by dots and starting with a $ + # Skip the first 3 ancestors (document root, tool, inputs) to start at the input element. + ancestors = param.ancestors[3:] + path = [] + for ancestor in ancestors: + name = ancestor.get_attribute_value("name") + if name: + path.append(name) + name = self._get_param_name(param) + if name: + path.append(name) + if path: + reference = f"${'.'.join(path)}" + return reference + + def _get_param_name(self, param: XmlElement) -> Optional[str]: + name = param.get_attribute_value("name") + if not name: + name = param.get_attribute_value("argument") + if name: + return self._normalize_argument_name(name) + return name + + def _normalize_argument_name(self, argument: str) -> str: + if argument.startswith("--"): + argument = argument[2:] + return argument.replace("-", "_") diff --git a/server/galaxyls/types.py b/server/galaxyls/types.py index 1c197cf..fbef4dd 100644 --- a/server/galaxyls/types.py +++ b/server/galaxyls/types.py @@ -88,3 +88,13 @@ class GeneratedExpandedDocument: content: Optional[str] = attrs.field(default=None) error_message: Optional[str] = attrs.field(default=None, alias="errorMessage") + + +class ParamReferencesResult: + """Contains information about the references to a parameter in the document.""" + + def __init__( + self, + references: List[str], + ) -> None: + self.references = references From 3040a6a48c0ddb5c5452c38695e0c375fac43a27 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:07:07 +0200 Subject: [PATCH 3/9] Add command for inserting parameter references in the document --- client/package.json | 14 +++++++++++++ client/src/commands.ts | 38 ++++++++++++++++++++++++++++++++++++ server/galaxyls/constants.py | 1 + server/galaxyls/server.py | 14 +++++++++++++ 4 files changed, 67 insertions(+) diff --git a/client/package.json b/client/package.json index 418880a..a188fce 100644 --- a/client/package.json +++ b/client/package.json @@ -133,6 +133,15 @@ "enablement": "galaxytools:isActive", "icon": "$(open-preview)" } + , + { + "command": "galaxytools.insert.paramReference", + "title": "Insert a reference to a param element.", + "category": "Galaxy Tools", + "enablement": "galaxytools:isActive", + "icon": "$(insert)", + "when": "editorTextFocus" + } ], "keybindings": [ { @@ -154,6 +163,11 @@ "command": "galaxytools.sort.documentParamsAttributes", "key": "ctrl+alt+s ctrl+alt+d", "mac": "cmd+alt+s cmd+alt+d" + }, + { + "command": "galaxytools.insert.paramReference", + "key": "ctrl+alt+i ctrl+alt+p", + "mac": "cmd+alt+i cmd+alt+p" } ], "configuration": { diff --git a/client/src/commands.ts b/client/src/commands.ts index 31cc4cf..689e74e 100644 --- a/client/src/commands.ts +++ b/client/src/commands.ts @@ -33,6 +33,7 @@ export namespace Commands { export const OPEN_TERMINAL_AT_DIRECTORY_ITEM: ICommand = getCommands("openTerminalAtDirectory"); export const GENERATE_EXPANDED_DOCUMENT: ICommand = getCommands("generate.expandedDocument"); export const PREVIEW_EXPANDED_DOCUMENT: ICommand = getCommands("preview.expandedDocument"); + export const INSERT_PARAM_REFERENCE: ICommand = getCommands("insert.paramReference"); } interface GeneratedSnippetResult { @@ -47,6 +48,10 @@ interface ReplaceTextRangeResult { replace_range: Range; } +interface ParamReferencesResult { + references: string[]; +} + export interface GeneratedExpandedDocument { content: string; error_message: string; @@ -65,6 +70,8 @@ export function setupCommands(client: LanguageClient, context: ExtensionContext) setupGenerateExpandedDocument(client, context); + setupInsertParamReference(client, context); + context.subscriptions.push( commands.registerCommand(Commands.PREVIEW_EXPANDED_DOCUMENT.internal, previewExpandedDocument) ); @@ -121,6 +128,13 @@ function setupGenerateTestCases(client: LanguageClient, context: ExtensionContex context.subscriptions.push(commands.registerCommand(Commands.GENERATE_TEST.internal, generateTest)); } +function setupInsertParamReference(client: LanguageClient, context: ExtensionContext) { + const insertParamReferenceHandler = async () => { + pickParamReferenceToInsert(client, Commands.INSERT_PARAM_REFERENCE.external); + }; + context.subscriptions.push(commands.registerCommand(Commands.INSERT_PARAM_REFERENCE.internal, insertParamReferenceHandler)); +} + function setupAutoCloseTags(client: LanguageClient, context: ExtensionContext) { const tagProvider = async (document: TextDocument, position: Position) => { let param = client.code2ProtocolConverter.asTextDocumentPositionParams(document, position); @@ -212,6 +226,30 @@ async function requestInsertSnippet(client: LanguageClient, command: string) { } } +async function pickParamReferenceToInsert(client: LanguageClient, command: string) { + const activeEditor = window.activeTextEditor; + if (!activeEditor) return; + + const document = activeEditor.document; + + const param = client.code2ProtocolConverter.asTextDocumentIdentifier(document); + const response = await commands.executeCommand(command, param); + if (!response || !response.references || response.references.length === 0) { + return; + } + + try { + const selected = await window.showQuickPick(response.references, { title: "Select a parameter reference to insert" }); + if (!selected) return; + + activeEditor.edit(editBuilder => { + editBuilder.insert(activeEditor.selection.active, selected); + }); + } catch (err: any) { + window.showErrorMessage(err); + } +} + async function ensureDocumentIsSaved(editor: TextEditor): Promise { if (editor.document.isDirty) { await editor.document.save(); diff --git a/server/galaxyls/constants.py b/server/galaxyls/constants.py index dc608a5..96f1341 100644 --- a/server/galaxyls/constants.py +++ b/server/galaxyls/constants.py @@ -15,6 +15,7 @@ class Commands: DISCOVER_TESTS_IN_WORKSPACE = "gls.tests.discoverInWorkspace" DISCOVER_TESTS_IN_DOCUMENT = "gls.tests.discoverInDocument" GENERATE_EXPANDED_DOCUMENT = "gls.generate.expandedDocument" + INSERT_PARAM_REFERENCE = "gls.insert.paramReference" class DiagnosticCodes: diff --git a/server/galaxyls/server.py b/server/galaxyls/server.py index 67e0477..bd027d8 100644 --- a/server/galaxyls/server.py +++ b/server/galaxyls/server.py @@ -56,6 +56,7 @@ CommandParameters, GeneratedExpandedDocument, GeneratedSnippetResult, + ParamReferencesResult, ReplaceTextRangeResult, TestSuiteInfoResult, ) @@ -298,6 +299,19 @@ def discover_tests_in_document_command( return None +@language_server.command(Commands.INSERT_PARAM_REFERENCE) +async def cmd_insert_param_reference( + server: GalaxyToolsLanguageServer, parameters: CommandParameters +) -> Optional[ParamReferencesResult]: + """Provides a list of possible parameter references to be inserted in the document.""" + params = convert_to(parameters[0], TextDocumentIdentifier) + document = _get_valid_document(server, params.uri) + if document: + xml_document = _get_xml_document(document) + return server.service.param_references_provider.get_param_references(xml_document) + return None + + def _validate(server: GalaxyToolsLanguageServer, params) -> None: """Validates the Galaxy tool and reports any problem found.""" diagnostics: List[Diagnostic] = [] From f3413ee89b35a8faedf02e02ab6763a0c19f036e Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:24:28 +0200 Subject: [PATCH 4/9] Refactor move `get_expanded_tool_document` to GalaxyToolXmlDocument --- server/galaxyls/services/tools/document.py | 18 ++++++++++++++++ .../services/tools/generators/snippets.py | 21 +------------------ 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/server/galaxyls/services/tools/document.py b/server/galaxyls/services/tools/document.py index 897a3c1..51139ba 100644 --- a/server/galaxyls/services/tools/document.py +++ b/server/galaxyls/services/tools/document.py @@ -7,10 +7,12 @@ ) from anytree import find # type: ignore +from galaxy.util import xml_macros from lsprotocol.types import ( Position, Range, ) +from lxml import etree from pygls.workspace import Document from galaxyls.services.tools.constants import ( @@ -228,6 +230,22 @@ def get_import_macro_file_range(self, file_path: Optional[str]) -> Optional[Rang return self.xml_document.get_full_range(imp) return None + def get_expanded_tool_document(self) -> "GalaxyToolXmlDocument": + """If the given tool document uses macros, a new tool document with the expanded macros is returned, + otherwise, the same document is returned. + """ + if self.uses_macros: + try: + document = self.document + expanded_tool_tree, _ = xml_macros.load_with_references(document.path) + expanded_tool_tree = cast(etree._ElementTree, expanded_tool_tree) # type: ignore + expanded_source = etree.tostring(expanded_tool_tree, encoding=str) + expanded_document = Document(uri=document.uri, source=expanded_source, version=document.version) + return GalaxyToolXmlDocument(expanded_document) + except BaseException: + return self + return self + def get_tool_id(self) -> Optional[str]: """Gets the identifier of the tool""" tool_element = self.get_tool_element() diff --git a/server/galaxyls/services/tools/generators/snippets.py b/server/galaxyls/services/tools/generators/snippets.py index 4de62d9..8983452 100644 --- a/server/galaxyls/services/tools/generators/snippets.py +++ b/server/galaxyls/services/tools/generators/snippets.py @@ -10,13 +10,10 @@ cast, ) -from galaxy.util import xml_macros from lsprotocol.types import ( Position, Range, ) -from lxml import etree -from pygls.workspace import Document from galaxyls.services.tools.constants import ( DASH, @@ -32,7 +29,7 @@ class SnippetGenerator(ABC): def __init__(self, tool_document: GalaxyToolXmlDocument, tabSize: int = 4) -> None: self.tool_document = tool_document - self.expanded_document = self._get_expanded_tool_document(tool_document) + self.expanded_document = tool_document.get_expanded_tool_document() self.tabstop_count: int = 0 self.indent_spaces: str = " " * tabSize super().__init__() @@ -63,22 +60,6 @@ def _find_snippet_insert_position(self) -> Union[Position, Range]: snippet will be inserted.""" pass - def _get_expanded_tool_document(self, tool_document: GalaxyToolXmlDocument) -> GalaxyToolXmlDocument: - """If the given tool document uses macros, a new tool document with the expanded macros is returned, - otherwise, the same document is returned. - """ - if tool_document.uses_macros: - try: - document = tool_document.document - expanded_tool_tree, _ = xml_macros.load_with_references(document.path) - expanded_tool_tree = cast(etree._ElementTree, expanded_tool_tree) # type: ignore - expanded_source = etree.tostring(expanded_tool_tree, encoding=str) - expanded_document = Document(uri=document.uri, source=expanded_source, version=document.version) - return GalaxyToolXmlDocument(expanded_document) - except BaseException: - return tool_document - return tool_document - def _get_next_tabstop(self) -> str: """Increments the tabstop count and returns the current tabstop in TextMate format. From c83cc9a16c7de11e1a9f99e17e835a2d05770691 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:25:22 +0200 Subject: [PATCH 5/9] Add support for params defined in macros for get_param_references --- server/galaxyls/services/references.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/server/galaxyls/services/references.py b/server/galaxyls/services/references.py index 1cd975f..6f4fb24 100644 --- a/server/galaxyls/services/references.py +++ b/server/galaxyls/services/references.py @@ -8,9 +8,7 @@ class ParamReferencesProvider: def get_param_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: - # TODO: Should work with expanded documents - - tool = GalaxyToolXmlDocument.from_xml_document(xml_document) + tool = GalaxyToolXmlDocument.from_xml_document(xml_document).get_expanded_tool_document() references = [] params = tool.get_input_params() for param in params: From 0b33428fa2a498394e7d83f79004b27671253533 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:56:04 +0200 Subject: [PATCH 6/9] Refactor ParamReferencesProvider --- server/galaxyls/services/references.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/server/galaxyls/services/references.py b/server/galaxyls/services/references.py index 6f4fb24..b93740d 100644 --- a/server/galaxyls/services/references.py +++ b/server/galaxyls/services/references.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import List, Optional from galaxyls.services.tools.document import GalaxyToolXmlDocument from galaxyls.services.xml.document import XmlDocument @@ -8,6 +8,7 @@ class ParamReferencesProvider: def get_param_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: + """Returns a list of references for the input parameters of the tool that can be used in the command section.""" tool = GalaxyToolXmlDocument.from_xml_document(xml_document).get_expanded_tool_document() references = [] params = tool.get_input_params() @@ -15,15 +16,12 @@ def get_param_references(self, xml_document: XmlDocument) -> Optional[ParamRefer reference = self._build_reference(param) if reference: references.append(reference) - return ParamReferencesResult(references) - def _build_reference(self, param: XmlElement) -> Optional[str]: - reference = None - # The reference should be a string with the path to the param separated by dots and starting with a $ + def get_param_path(self, param: XmlElement) -> List[str]: + path = [] # Skip the first 3 ancestors (document root, tool, inputs) to start at the input element. ancestors = param.ancestors[3:] - path = [] for ancestor in ancestors: name = ancestor.get_attribute_value("name") if name: @@ -31,9 +29,7 @@ def _build_reference(self, param: XmlElement) -> Optional[str]: name = self._get_param_name(param) if name: path.append(name) - if path: - reference = f"${'.'.join(path)}" - return reference + return path def _get_param_name(self, param: XmlElement) -> Optional[str]: name = param.get_attribute_value("name") @@ -47,3 +43,10 @@ def _normalize_argument_name(self, argument: str) -> str: if argument.startswith("--"): argument = argument[2:] return argument.replace("-", "_") + + def _build_reference(self, param: XmlElement) -> Optional[str]: + reference = None + path = self.get_param_path(param) + if path: + reference = f"${'.'.join(path)}" + return reference From 46c9203d71f22a17f4c406a6eefd68b7cd279ecc Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:13:53 +0200 Subject: [PATCH 7/9] Add get_param_filter_references to ParamReferencesProvider --- server/galaxyls/services/references.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/server/galaxyls/services/references.py b/server/galaxyls/services/references.py index b93740d..0971494 100644 --- a/server/galaxyls/services/references.py +++ b/server/galaxyls/services/references.py @@ -13,7 +13,18 @@ def get_param_references(self, xml_document: XmlDocument) -> Optional[ParamRefer references = [] params = tool.get_input_params() for param in params: - reference = self._build_reference(param) + reference = self._build_command_reference(param) + if reference: + references.append(reference) + return ParamReferencesResult(references) + + def get_param_filter_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: + """Returns a list of references for the input parameters of the tool that can be used in output filters.""" + tool = GalaxyToolXmlDocument.from_xml_document(xml_document).get_expanded_tool_document() + references = [] + params = tool.get_input_params() + for param in params: + reference = self._build_filter_reference(param) if reference: references.append(reference) return ParamReferencesResult(references) @@ -44,9 +55,18 @@ def _normalize_argument_name(self, argument: str) -> str: argument = argument[2:] return argument.replace("-", "_") - def _build_reference(self, param: XmlElement) -> Optional[str]: + def _build_command_reference(self, param: XmlElement) -> Optional[str]: reference = None path = self.get_param_path(param) if path: reference = f"${'.'.join(path)}" return reference + + def _build_filter_reference(self, param: XmlElement) -> Optional[str]: + reference = None + path = self.get_param_path(param) + if path: + reference = path[0] + for elem in path[1:]: + reference += f"['{elem}']" + return reference From 42cc011872de37dee97e706de679d60a253e9699 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:24:21 +0200 Subject: [PATCH 8/9] Refactor ParamReferencesProvider --- server/galaxyls/server.py | 2 +- server/galaxyls/services/references.py | 56 +++++++++++++------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/server/galaxyls/server.py b/server/galaxyls/server.py index bd027d8..10f2fb8 100644 --- a/server/galaxyls/server.py +++ b/server/galaxyls/server.py @@ -308,7 +308,7 @@ async def cmd_insert_param_reference( document = _get_valid_document(server, params.uri) if document: xml_document = _get_xml_document(document) - return server.service.param_references_provider.get_param_references(xml_document) + return server.service.param_references_provider.get_param_command_references(xml_document) return None diff --git a/server/galaxyls/services/references.py b/server/galaxyls/services/references.py index 0971494..38d4912 100644 --- a/server/galaxyls/services/references.py +++ b/server/galaxyls/services/references.py @@ -1,35 +1,51 @@ -from typing import List, Optional +from typing import Callable, List, Optional from galaxyls.services.tools.document import GalaxyToolXmlDocument from galaxyls.services.xml.document import XmlDocument from galaxyls.services.xml.nodes import XmlElement from galaxyls.types import ParamReferencesResult +ReferenceBuilder = Callable[[XmlElement], Optional[str]] + class ParamReferencesProvider: - def get_param_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: + def get_param_command_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: """Returns a list of references for the input parameters of the tool that can be used in the command section.""" - tool = GalaxyToolXmlDocument.from_xml_document(xml_document).get_expanded_tool_document() - references = [] - params = tool.get_input_params() - for param in params: - reference = self._build_command_reference(param) - if reference: - references.append(reference) - return ParamReferencesResult(references) + return self._get_param_references(xml_document, self._build_command_reference) def get_param_filter_references(self, xml_document: XmlDocument) -> Optional[ParamReferencesResult]: """Returns a list of references for the input parameters of the tool that can be used in output filters.""" + return self._get_param_references(xml_document, self._build_filter_reference) + + def _get_param_references( + self, xml_document: XmlDocument, reference_builder: ReferenceBuilder + ) -> Optional[ParamReferencesResult]: tool = GalaxyToolXmlDocument.from_xml_document(xml_document).get_expanded_tool_document() references = [] params = tool.get_input_params() for param in params: - reference = self._build_filter_reference(param) + reference = reference_builder(param) if reference: references.append(reference) return ParamReferencesResult(references) - def get_param_path(self, param: XmlElement) -> List[str]: + def _build_command_reference(self, param: XmlElement) -> Optional[str]: + reference = None + path = self._get_param_path(param) + if path: + reference = f"${'.'.join(path)}" + return reference + + def _build_filter_reference(self, param: XmlElement) -> Optional[str]: + reference = None + path = self._get_param_path(param) + if path: + reference = path[0] + for elem in path[1:]: + reference += f"['{elem}']" + return reference + + def _get_param_path(self, param: XmlElement) -> List[str]: path = [] # Skip the first 3 ancestors (document root, tool, inputs) to start at the input element. ancestors = param.ancestors[3:] @@ -54,19 +70,3 @@ def _normalize_argument_name(self, argument: str) -> str: if argument.startswith("--"): argument = argument[2:] return argument.replace("-", "_") - - def _build_command_reference(self, param: XmlElement) -> Optional[str]: - reference = None - path = self.get_param_path(param) - if path: - reference = f"${'.'.join(path)}" - return reference - - def _build_filter_reference(self, param: XmlElement) -> Optional[str]: - reference = None - path = self.get_param_path(param) - if path: - reference = path[0] - for elem in path[1:]: - reference += f"['{elem}']" - return reference From d7c5ce1b65fd40dabb0420d49a94c2aa5452ac43 Mon Sep 17 00:00:00 2001 From: davelopez <46503462+davelopez@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:48:07 +0200 Subject: [PATCH 9/9] Add command to insert param references for output filters --- client/package.json | 16 ++++++++++++++-- client/src/commands.ts | 13 ++++++++----- server/galaxyls/constants.py | 1 + server/galaxyls/server.py | 15 ++++++++++++++- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/client/package.json b/client/package.json index a188fce..fd5ea1e 100644 --- a/client/package.json +++ b/client/package.json @@ -132,8 +132,7 @@ "category": "Galaxy Tools", "enablement": "galaxytools:isActive", "icon": "$(open-preview)" - } - , + }, { "command": "galaxytools.insert.paramReference", "title": "Insert a reference to a param element.", @@ -141,6 +140,14 @@ "enablement": "galaxytools:isActive", "icon": "$(insert)", "when": "editorTextFocus" + }, + { + "command": "galaxytools.insert.paramFilterReference", + "title": "Insert a reference to a param element to be used as output filter.", + "category": "Galaxy Tools", + "enablement": "galaxytools:isActive", + "icon": "$(insert)", + "when": "editorTextFocus" } ], "keybindings": [ @@ -168,6 +175,11 @@ "command": "galaxytools.insert.paramReference", "key": "ctrl+alt+i ctrl+alt+p", "mac": "cmd+alt+i cmd+alt+p" + }, + { + "command": "galaxytools.insert.paramFilterReference", + "key": "ctrl+alt+i ctrl+alt+f", + "mac": "cmd+alt+i cmd+alt+f" } ], "configuration": { diff --git a/client/src/commands.ts b/client/src/commands.ts index 689e74e..5a30135 100644 --- a/client/src/commands.ts +++ b/client/src/commands.ts @@ -34,6 +34,7 @@ export namespace Commands { export const GENERATE_EXPANDED_DOCUMENT: ICommand = getCommands("generate.expandedDocument"); export const PREVIEW_EXPANDED_DOCUMENT: ICommand = getCommands("preview.expandedDocument"); export const INSERT_PARAM_REFERENCE: ICommand = getCommands("insert.paramReference"); + export const INSERT_PARAM_FILTER_REFERENCE: ICommand = getCommands("insert.paramFilterReference"); } interface GeneratedSnippetResult { @@ -129,10 +130,12 @@ function setupGenerateTestCases(client: LanguageClient, context: ExtensionContex } function setupInsertParamReference(client: LanguageClient, context: ExtensionContext) { - const insertParamReferenceHandler = async () => { + context.subscriptions.push(commands.registerCommand(Commands.INSERT_PARAM_REFERENCE.internal, () => { pickParamReferenceToInsert(client, Commands.INSERT_PARAM_REFERENCE.external); - }; - context.subscriptions.push(commands.registerCommand(Commands.INSERT_PARAM_REFERENCE.internal, insertParamReferenceHandler)); + })); + context.subscriptions.push(commands.registerCommand(Commands.INSERT_PARAM_FILTER_REFERENCE.internal, () => { + pickParamReferenceToInsert(client, Commands.INSERT_PARAM_FILTER_REFERENCE.external); + })) } function setupAutoCloseTags(client: LanguageClient, context: ExtensionContext) { @@ -226,7 +229,7 @@ async function requestInsertSnippet(client: LanguageClient, command: string) { } } -async function pickParamReferenceToInsert(client: LanguageClient, command: string) { +async function pickParamReferenceToInsert(client: LanguageClient, command: string, pickerTitle: string = "Select a parameter reference to insert") { const activeEditor = window.activeTextEditor; if (!activeEditor) return; @@ -239,7 +242,7 @@ async function pickParamReferenceToInsert(client: LanguageClient, command: strin } try { - const selected = await window.showQuickPick(response.references, { title: "Select a parameter reference to insert" }); + const selected = await window.showQuickPick(response.references, { title: pickerTitle }); if (!selected) return; activeEditor.edit(editBuilder => { diff --git a/server/galaxyls/constants.py b/server/galaxyls/constants.py index 96f1341..4ec03b4 100644 --- a/server/galaxyls/constants.py +++ b/server/galaxyls/constants.py @@ -16,6 +16,7 @@ class Commands: DISCOVER_TESTS_IN_DOCUMENT = "gls.tests.discoverInDocument" GENERATE_EXPANDED_DOCUMENT = "gls.generate.expandedDocument" INSERT_PARAM_REFERENCE = "gls.insert.paramReference" + INSERT_PARAM_FILTER_REFERENCE = "gls.insert.paramFilterReference" class DiagnosticCodes: diff --git a/server/galaxyls/server.py b/server/galaxyls/server.py index 10f2fb8..9c65543 100644 --- a/server/galaxyls/server.py +++ b/server/galaxyls/server.py @@ -303,7 +303,7 @@ def discover_tests_in_document_command( async def cmd_insert_param_reference( server: GalaxyToolsLanguageServer, parameters: CommandParameters ) -> Optional[ParamReferencesResult]: - """Provides a list of possible parameter references to be inserted in the document.""" + """Provides a list of possible parameter references to be inserted in the command section of the document.""" params = convert_to(parameters[0], TextDocumentIdentifier) document = _get_valid_document(server, params.uri) if document: @@ -312,6 +312,19 @@ async def cmd_insert_param_reference( return None +@language_server.command(Commands.INSERT_PARAM_FILTER_REFERENCE) +async def cmd_insert_param_filter_reference( + server: GalaxyToolsLanguageServer, parameters: CommandParameters +) -> Optional[ParamReferencesResult]: + """Provides a list of possible parameter references to be inserted as output filters.""" + params = convert_to(parameters[0], TextDocumentIdentifier) + document = _get_valid_document(server, params.uri) + if document: + xml_document = _get_xml_document(document) + return server.service.param_references_provider.get_param_filter_references(xml_document) + return None + + def _validate(server: GalaxyToolsLanguageServer, params) -> None: """Validates the Galaxy tool and reports any problem found.""" diagnostics: List[Diagnostic] = []