diff --git a/server/galaxyls/constants.py b/server/galaxyls/constants.py index 13230b34..0e10e865 100644 --- a/server/galaxyls/constants.py +++ b/server/galaxyls/constants.py @@ -1,7 +1,5 @@ """This module contains definitions for constants used by the Galaxy Tools Language Server.""" -SERVER_NAME = "Galaxy Tools LS" - class Commands: AUTO_CLOSE_TAGS = "gls.completion.autoCloseTags" diff --git a/server/galaxyls/server.py b/server/galaxyls/server.py index f54b2b93..96f51215 100644 --- a/server/galaxyls/server.py +++ b/server/galaxyls/server.py @@ -48,10 +48,7 @@ CompletionMode, GalaxyToolsConfiguration, ) -from galaxyls.constants import ( - Commands, - SERVER_NAME, -) +from galaxyls.constants import Commands from galaxyls.services.language import GalaxyToolLanguageService from galaxyls.services.validation import DocumentValidator from galaxyls.services.xml.document import XmlDocument @@ -72,7 +69,7 @@ class GalaxyToolsLanguageServer(LanguageServer): def __init__(self) -> None: super().__init__() - self.service = GalaxyToolLanguageService(SERVER_NAME) + self.service = GalaxyToolLanguageService() self.configuration: GalaxyToolsConfiguration = GalaxyToolsConfiguration() diff --git a/server/galaxyls/services/language.py b/server/galaxyls/services/language.py index aae8582c..46f8193c 100644 --- a/server/galaxyls/services/language.py +++ b/server/galaxyls/services/language.py @@ -61,8 +61,8 @@ class GalaxyToolLanguageService: by the LSP. """ - def __init__(self, server_name: str) -> None: - self.xsd_service = GalaxyToolXsdService(server_name) + def __init__(self) -> None: + self.xsd_service = GalaxyToolXsdService() self.format_service = GalaxyToolFormatService() self.xsd_tree = self.xsd_service.xsd_parser.get_tree() self.xml_context_service = XmlContextService(self.xsd_tree) @@ -81,9 +81,7 @@ def set_workspace(self, workspace: Workspace) -> None: ) def get_diagnostics(self, xml_document: XmlDocument) -> List[Diagnostic]: - """Validates the Galaxy tool XML document and returns a list - of diagnostics if there are any problems. - """ + """Validates the Galaxy tool XML document and returns a list of diagnostics if there are any problems.""" return self.xsd_service.validate_document(xml_document) + self.linter.lint_document(xml_document) def get_documentation(self, xml_document: XmlDocument, position: Position) -> Optional[Hover]: @@ -105,9 +103,7 @@ def get_documentation(self, xml_document: XmlDocument, position: Position) -> Op return None def format_document(self, content: str, params: DocumentFormattingParams) -> List[TextEdit]: - """Given the document contents returns the list of TextEdits - needed to properly format and layout the document. - """ + """Given the document contents returns the list of TextEdits needed to properly format and layout the document.""" return self.format_service.format(content, params) def get_completion( diff --git a/server/galaxyls/services/tools/linting.py b/server/galaxyls/services/tools/linting.py index 8717154e..336c46dd 100644 --- a/server/galaxyls/services/tools/linting.py +++ b/server/galaxyls/services/tools/linting.py @@ -1,17 +1,18 @@ -from typing import List, cast -from lxml import etree +from typing import List from galaxy.tool_util.lint import ( - lint_tool_source_with, + lint_xml_with, LintContext, LintLevel, XMLLintMessageXPath, ) -from galaxy.tool_util.parser import get_tool_source -from galaxy.util import xml_macros +from pygls.lsp.types import ( + Diagnostic, + DiagnosticSeverity, +) + from galaxyls.services.tools.common import ToolLinter from galaxyls.services.xml.document import XmlDocument -from pygls.lsp.types import Diagnostic, Range, DiagnosticSeverity class GalaxyToolLinter(ToolLinter): @@ -20,21 +21,20 @@ class GalaxyToolLinter(ToolLinter): def lint_document(self, xml_document: XmlDocument) -> List[Diagnostic]: """ """ result: List[Diagnostic] = [] - if xml_document.is_macros_file: + xml_tree = xml_document.xml_tree_expanded + if not xml_document.is_tool_file or xml_tree is None: return result - xml_tree, _ = xml_macros.load_with_references(xml_document.document.path) - tool_source = get_tool_source(xml_tree=xml_tree) lint_context = LintContext(level=LintLevel.SILENT, lint_message_class=XMLLintMessageXPath) - context = lint_tool_source_with(lint_context, tool_source) + context = lint_xml_with(lint_context, xml_tree) result.extend( [ - self._to_diagnostic(lint_message, xml_tree, xml_document, DiagnosticSeverity.Error) + self._to_diagnostic(lint_message, xml_document, DiagnosticSeverity.Error) for lint_message in context.error_messages ] ) result.extend( [ - self._to_diagnostic(lint_message, xml_tree, xml_document, DiagnosticSeverity.Warning) + self._to_diagnostic(lint_message, xml_document, DiagnosticSeverity.Warning) for lint_message in context.warn_messages ] ) @@ -43,11 +43,10 @@ def lint_document(self, xml_document: XmlDocument) -> List[Diagnostic]: def _to_diagnostic( self, lint_message: XMLLintMessageXPath, - xml_tree: etree._ElementTree, xml_document: XmlDocument, level: DiagnosticSeverity, ) -> Diagnostic: - range = self._get_range_from_xpath(lint_message.xpath, xml_tree, xml_document) + range = xml_document.get_element_range_from_xpath_or_default(lint_message.xpath) result = Diagnostic( range=range, message=lint_message.message, @@ -55,10 +54,3 @@ def _to_diagnostic( severity=level, ) return result - - def _get_range_from_xpath(self, xpath: str, xml_tree: etree._ElementTree, xml_document: XmlDocument) -> Range: - result = None - found = cast(list, xml_tree.xpath(xpath))[0] - if found is not None: - result = xml_document.get_element_name_range_at_line(found.tag, found.sourceline - 1) - return result or xml_document.get_default_range() diff --git a/server/galaxyls/services/xml/document.py b/server/galaxyls/services/xml/document.py index fc930029..cc67c56e 100644 --- a/server/galaxyls/services/xml/document.py +++ b/server/galaxyls/services/xml/document.py @@ -1,10 +1,14 @@ from typing import ( + Any, + cast, Dict, List, Optional, ) from anytree.search import findall +from galaxy.util import xml_macros +from lxml import etree from pygls.lsp.types import ( Position, Range, @@ -44,6 +48,8 @@ def __init__(self, document: Document): "tool": DocumentType.TOOL, "macros": DocumentType.MACROS, } + self._xml_tree: Optional[etree._ElementTree] = None + self._xml_tree_expanded: Optional[etree._ElementTree] = None @property def node_type(self) -> NodeType: @@ -103,6 +109,40 @@ def is_tool_file(self) -> bool: """Indicates if the document is a tool definition file.""" return self.document_type == DocumentType.TOOL + @property + def xml_tree(self) -> Optional[etree._ElementTree]: + """Internal XML tree structure.""" + if self._xml_tree is None: + try: + tree = etree.parse(self.document.path) + self._xml_tree = tree + except etree.XMLSyntaxError: + pass # Invalid XML document + return self._xml_tree + + @property + def xml_has_syntax_errors(self) -> bool: + return self.xml_tree is None + + @property + def xml_tree_expanded(self) -> Optional[etree._ElementTree]: + """Internal XML tree structure after expanding macros. + + If there are no macro definitions, it returns the same as `xml_tree` property.""" + if self._xml_tree_expanded is None: + if self.uses_macros: + try: + expanded_tool_tree, _ = xml_macros.load_with_references(self.document.path) + self._xml_tree_expanded = expanded_tool_tree + except etree.XMLSyntaxError: + pass # Invalid XML document + except BaseException: + pass # TODO: Errors expanding macros should be catch during validation + if self._xml_tree_expanded is None: + # Fallback to the non-expanded version if something failed + self._xml_tree_expanded = self.xml_tree + return self._xml_tree_expanded + def get_node_at(self, offset: int) -> Optional[XmlSyntaxNode]: """Gets the syntax node a the given offset.""" return self.root.find_node_at(offset) if self.root else None @@ -231,12 +271,38 @@ def get_default_range(self) -> Range: return self.get_element_name_range(self.root) or DEFAULT_RANGE return DEFAULT_RANGE - def get_element_name_range_at_line(self, name: str, line_number: int) -> Range: - """Gets the range of the element with the given tag name located at the given line number.""" - line_text = self.document.lines[line_number] - start = line_text.index(f"<{name}") + 1 - end = start + len(name) - return Range( - start=Position(line=line_number, character=start), - end=Position(line=line_number, character=end), - ) + def get_tree_element_from_xpath(self, tree, xpath: Optional[str]) -> Optional[Any]: + if xpath is None or tree is None: + return None + element: Any = tree.xpath(xpath) + if element is not None: + if isinstance(element, list): + element = cast(list, element) + if len(element) > 0: + return element[0] + return None + + def get_element_from_xpath(self, xpath: Optional[str]) -> Optional[Any]: + return self.get_tree_element_from_xpath(self.xml_tree, xpath) + + def get_internal_element_range_or_default(self, element: Optional[Any]) -> Range: + if element is not None: + line_number = element.sourceline - 1 + line_text = self.document.lines[line_number] + if isinstance(element, etree._Comment): + text = cast(str, element.text) + start = line_text.index(f"{text}") + end = start + len(text) + else: + # Prepend '<' for searching tag names + start = line_text.index(f"<{element.tag}") + 1 + end = start + len(element.tag) + return Range( + start=Position(line=line_number, character=start), + end=Position(line=line_number, character=end), + ) + return self.get_default_range() + + def get_element_range_from_xpath_or_default(self, xpath: Optional[str]) -> Range: + element = self.get_element_from_xpath(xpath) + return self.get_internal_element_range_or_default(element) diff --git a/server/galaxyls/services/xsd/service.py b/server/galaxyls/services/xsd/service.py index 318b334e..649b2e21 100644 --- a/server/galaxyls/services/xsd/service.py +++ b/server/galaxyls/services/xsd/service.py @@ -22,7 +22,7 @@ ) from galaxyls.services.xsd.parser import GalaxyToolXsdParser from galaxyls.services.xsd.types import XsdBase -from galaxyls.services.xsd.validation import GalaxyToolValidationService +from galaxyls.services.xsd.validation import GalaxyToolSchemaValidationService NO_DOC_MARKUP = MarkupContent(kind=MarkupKind.Markdown, value=MSG_NO_DOCUMENTATION_AVAILABLE) @@ -34,13 +34,12 @@ class GalaxyToolXsdService: the XSD schema and validate XML files against it. """ - def __init__(self, server_name: str) -> None: + def __init__(self) -> None: """Initializes the validator by loading the XSD.""" - self.server_name = server_name self.xsd_doc: etree._ElementTree = etree.parse(str(TOOL_XSD_FILE)) self.xsd_schema = etree.XMLSchema(self.xsd_doc) self.xsd_parser = GalaxyToolXsdParser(self.xsd_doc.getroot()) - self.validator = GalaxyToolValidationService(server_name, self.xsd_schema) + self.validator = GalaxyToolSchemaValidationService(self.xsd_schema) def validate_document(self, xml_document: XmlDocument) -> List[Diagnostic]: """Validates the Galaxy tool xml using the XSD schema and returns a list diff --git a/server/galaxyls/services/xsd/validation.py b/server/galaxyls/services/xsd/validation.py index 7972fa29..7c51e690 100644 --- a/server/galaxyls/services/xsd/validation.py +++ b/server/galaxyls/services/xsd/validation.py @@ -2,12 +2,8 @@ """ from pathlib import Path -from typing import ( - List, - Optional, -) +from typing import List -from galaxy.util import xml_macros from lxml import etree from pygls.lsp.types import ( Diagnostic, @@ -16,23 +12,21 @@ Position, Range, ) -from pygls.workspace import Document from galaxyls.constants import DiagnosticCodes -from galaxyls.services.format import DEFAULT_INDENTATION -from galaxyls.services.macros import remove_macros from galaxyls.services.tools.document import GalaxyToolXmlDocument from galaxyls.services.xml.document import XmlDocument EXPAND_DOCUMENT_URI_SUFFIX = "%20%28Expanded%29" -class GalaxyToolValidationService: +class GalaxyToolSchemaValidationService: """Service providing diagnostics for errors in the XML validation.""" - def __init__(self, server_name: str, xsd_schema: etree.XMLSchema): + diagnostics_source = "Galaxy Schema Validator" + + def __init__(self, xsd_schema: etree.XMLSchema): """Initializes the validator""" - self.server_name = server_name self.xsd_schema = xsd_schema def validate_document(self, xml_document: XmlDocument) -> List[Diagnostic]: @@ -47,23 +41,20 @@ def validate_document(self, xml_document: XmlDocument) -> List[Diagnostic]: List[Diagnostic]: The list of issues found in the document. """ - syntax_errors = self._check_syntax(xml_document.document) + syntax_errors = self._check_syntax(xml_document) if syntax_errors: return syntax_errors if not xml_document.is_tool_file: return [] - tool = GalaxyToolXmlDocument.from_xml_document(xml_document) try: - xml_tree = etree.fromstring(tool.source) - return self._validate_tree(xml_tree) + return self._validate(xml_document) except ExpandMacrosFoundException: - result = self._validate_expanded(tool) - return result + return self._validate_expanded(xml_document) except etree.XMLSyntaxError as e: return self._build_diagnostics_from_syntax_error(e) - def _check_syntax(self, document: Document) -> List[Diagnostic]: + def _check_syntax(self, xml_document: XmlDocument) -> List[Diagnostic]: """Check if the XML document contains any syntax error and returns it in a list. Args: @@ -73,12 +64,12 @@ def _check_syntax(self, document: Document) -> List[Diagnostic]: List[Diagnostic]: The list containing the syntax error found or an empty list. """ try: - etree.fromstring(document.source) + etree.fromstring(xml_document.document.source) return [] except etree.XMLSyntaxError as e: return self._build_diagnostics_from_syntax_error(e) - def _validate_expanded(self, tool: GalaxyToolXmlDocument) -> List[Diagnostic]: + def _validate_expanded(self, xml_document: XmlDocument) -> List[Diagnostic]: """Validates the document after loading all the macros referenced and expands them. Args: @@ -89,39 +80,31 @@ def _validate_expanded(self, tool: GalaxyToolXmlDocument) -> List[Diagnostic]: List[Diagnostic]: [description] """ try: - expanded_tool_tree, _ = xml_macros.load_with_references(tool.path) - expanded_xml = remove_macros(expanded_tool_tree) - root = expanded_xml.getroot() - etree.indent(root, space=DEFAULT_INDENTATION) - content = etree.tostring(root, pretty_print=True, encoding=str) - formatted_xml = etree.fromstring(content) - self.xsd_schema.assertValid(formatted_xml) + if xml_document.xml_tree_expanded: + self.xsd_schema.assertValid(xml_document.xml_tree_expanded) return [] except etree.DocumentInvalid as e: - diagnostics = self._build_diagnostics_for_expanded_macros(tool, e) - return diagnostics + return self._build_diagnostics_for_expanded_macros(xml_document, e) except etree.XMLSyntaxError as e: - return self._build_diagnostics_for_macros_file_syntax_error(tool, e) + return self._build_diagnostics_for_macros_file_syntax_error(xml_document, e) - def _validate_tree(self, xml_tree) -> List[Diagnostic]: - """Validates an XML tree against the XSD schema. - - Args: - xml_tree (etree.ElementTree): The root element + except AssertionError as e: + return self._build_diagnostics_for_assertion_error(xml_document, e) + def _validate(self, xml_document: XmlDocument) -> List[Diagnostic]: + """Validates an XML document against the XSD schema. Returns: List[Diagnostic]: The diagnosis results """ try: - self.xsd_schema.assertValid(xml_tree) + if xml_document.xml_tree: + self.xsd_schema.assertValid(xml_document.xml_tree) return [] except etree.DocumentInvalid as e: - return self._build_diagnostics(e.error_log, xml_tree) + return self._build_diagnostics(e.error_log, xml_document) - def _build_diagnostics( - self, error_log: etree._ListErrorLog, xml_tree: Optional[etree._ElementTree] = None - ) -> List[Diagnostic]: + def _build_diagnostics(self, error_log: etree._ListErrorLog, xml_document: XmlDocument) -> List[Diagnostic]: """Gets a list of diagnostics from the XSD validation error log. Args: @@ -140,15 +123,13 @@ def _build_diagnostics( diagnostics = [] for error in error_log.filter_from_errors(): if "expand" in error.message: - raise ExpandMacrosFoundException(xml_tree) + raise ExpandMacrosFoundException() + range = xml_document.get_element_range_from_xpath_or_default(error.path) result = Diagnostic( - range=Range( - start=Position(line=error.line - 1, character=error.column), - end=Position(line=error.line - 1, character=error.column), - ), + range=range, message=error.message, - source=self.server_name, + source=self.diagnostics_source, ) diagnostics.append(result) return diagnostics @@ -168,15 +149,16 @@ def _build_diagnostics_from_syntax_error(self, error) -> List[Diagnostic]: end=Position(line=error.lineno - 1, character=error.position[1] - 1), ), message=error.msg, - source=self.server_name, + source=self.diagnostics_source, ) return [result] - def _build_diagnostics_for_macros_file_syntax_error(self, tool: GalaxyToolXmlDocument, syntax_error) -> List[Diagnostic]: + def _build_diagnostics_for_macros_file_syntax_error(self, xml_document: XmlDocument, syntax_error) -> List[Diagnostic]: + tool = GalaxyToolXmlDocument.from_xml_document(xml_document) result = Diagnostic( range=tool.get_import_macro_file_range(syntax_error.filename), message=syntax_error.msg, - source=self.server_name, + source=self.diagnostics_source, related_information=[ DiagnosticRelatedInformation( message="Syntax error found on imported file.", @@ -192,15 +174,15 @@ def _build_diagnostics_for_macros_file_syntax_error(self, tool: GalaxyToolXmlDoc ) return [result] - def _build_diagnostics_for_expanded_macros(self, tool: GalaxyToolXmlDocument, invalid_document_error) -> List[Diagnostic]: - virtual_uri = tool.xml_document.document.uri.replace("file", "gls-expand") - diagnostics = [ - Diagnostic( - range=tool.get_macros_range(), - message=error.message, - source=self.server_name, - code=DiagnosticCodes.INVALID_EXPANDED_TOOL, - related_information=[ + def _build_diagnostics_for_expanded_macros(self, xml_document: XmlDocument, invalid_document_error) -> List[Diagnostic]: + virtual_uri = xml_document.document.uri.replace("file", "gls-expand") + diagnostics = [] + for error in invalid_document_error.error_log.filter_from_errors(): + related_info: List[DiagnosticRelatedInformation] = [] + elem_in_main_doc = xml_document.get_element_from_xpath(error.path) + if elem_in_main_doc is None: + elem_in_main_doc = xml_document.get_element_from_xpath("/tool/macros") + related_info = [ DiagnosticRelatedInformation( message=( "The validation error ocurred on the expanded version of " @@ -215,12 +197,25 @@ def _build_diagnostics_for_expanded_macros(self, tool: GalaxyToolXmlDocument, in ), ), ) - ], + ] + result = Diagnostic( + range=xml_document.get_internal_element_range_or_default(elem_in_main_doc), + message=error.message, + source=self.diagnostics_source, + code=DiagnosticCodes.INVALID_EXPANDED_TOOL, + related_information=related_info, ) - for error in invalid_document_error.error_log.filter_from_errors() - ] + diagnostics.append(result) return diagnostics + def _build_diagnostics_for_assertion_error(self, xml_document: XmlDocument, error: AssertionError) -> List[Diagnostic]: + result = Diagnostic( + range=xml_document.get_default_range(), + message=str(error), + source=self.diagnostics_source, + ) + return [result] + class ExpandMacrosFoundException(Exception): """This exceptions indicates that the current tool contains diff --git a/server/galaxyls/tests/files/test_invalid_tool_01.xml b/server/galaxyls/tests/files/test_invalid_tool_01.xml new file mode 100644 index 00000000..090fae55 --- /dev/null +++ b/server/galaxyls/tests/files/test_invalid_tool_01.xml @@ -0,0 +1 @@ + diff --git a/server/galaxyls/tests/files/test_tool_01.xml b/server/galaxyls/tests/files/test_tool_01.xml new file mode 100644 index 00000000..6f2f04b6 --- /dev/null +++ b/server/galaxyls/tests/files/test_tool_01.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/server/galaxyls/tests/integration/test_completion.py b/server/galaxyls/tests/integration/test_completion.py index 84c7715f..3f7d361a 100644 --- a/server/galaxyls/tests/integration/test_completion.py +++ b/server/galaxyls/tests/integration/test_completion.py @@ -18,7 +18,7 @@ @pytest.fixture() def galaxy_xsd_tree() -> XsdTree: - xsd_service = GalaxyToolXsdService("Integration Tests") + xsd_service = GalaxyToolXsdService() tree = xsd_service.xsd_parser.get_tree() return tree diff --git a/server/galaxyls/tests/integration/test_context.py b/server/galaxyls/tests/integration/test_context.py index 4954cc56..0701d10c 100644 --- a/server/galaxyls/tests/integration/test_context.py +++ b/server/galaxyls/tests/integration/test_context.py @@ -8,7 +8,7 @@ @pytest.fixture() def galaxy_xsd_tree() -> XsdTree: - xsd_service = GalaxyToolXsdService("Integration Tests") + xsd_service = GalaxyToolXsdService() tree = xsd_service.xsd_parser.get_tree() return tree diff --git a/server/galaxyls/tests/unit/test_validation.py b/server/galaxyls/tests/unit/test_validation.py index 195f2fc8..237412db 100644 --- a/server/galaxyls/tests/unit/test_validation.py +++ b/server/galaxyls/tests/unit/test_validation.py @@ -3,18 +3,14 @@ from galaxyls.services.validation import DocumentValidator from ...services.xsd.constants import TOOL_XSD_FILE -from ...services.xsd.validation import GalaxyToolValidationService +from ...services.xsd.validation import GalaxyToolSchemaValidationService from .sample_data import ( - TEST_INVALID_TOOL_01_DOCUMENT, TEST_MACRO_01_DOCUMENT, TEST_SYNTAX_ERROR_MACRO_01_DOCUMENT, TEST_SYNTAX_ERROR_TOOL_01_DOCUMENT, - TEST_TOOL_01_DOCUMENT, ) from .utils import TestUtils -TEST_SERVER_NAME = "Test Server" - @pytest.fixture(scope="module") def xsd_schema() -> etree.XMLSchema: @@ -25,15 +21,15 @@ def xsd_schema() -> etree.XMLSchema: class TestGalaxyToolValidationServiceClass: def test_validate_document_returns_empty_diagnostics_when_valid(self, xsd_schema: etree.XMLSchema) -> None: - service = GalaxyToolValidationService(TEST_SERVER_NAME, xsd_schema) - xml_document = TestUtils.from_document_to_xml_document(TEST_TOOL_01_DOCUMENT) + service = GalaxyToolSchemaValidationService(xsd_schema) + xml_document = TestUtils.get_test_xml_document_from_file("test_tool_01.xml") actual = service.validate_document(xml_document) assert actual == [] def test_validate_macro_file_returns_empty_diagnostics_when_valid(self, xsd_schema: etree.XMLSchema) -> None: - service = GalaxyToolValidationService(TEST_SERVER_NAME, xsd_schema) + service = GalaxyToolSchemaValidationService(xsd_schema) xml_document = TestUtils.from_document_to_xml_document(TEST_MACRO_01_DOCUMENT) actual = service.validate_document(xml_document) @@ -41,15 +37,15 @@ def test_validate_macro_file_returns_empty_diagnostics_when_valid(self, xsd_sche assert actual == [] def test_validate_document_returns_diagnostics_when_invalid(self, xsd_schema: etree.XMLSchema) -> None: - service = GalaxyToolValidationService(TEST_SERVER_NAME, xsd_schema) - xml_document = TestUtils.from_document_to_xml_document(TEST_INVALID_TOOL_01_DOCUMENT) + service = GalaxyToolSchemaValidationService(xsd_schema) + xml_document = TestUtils.get_test_xml_document_from_file("test_invalid_tool_01.xml") actual = service.validate_document(xml_document) assert len(actual) > 0 def test_validate_document_returns_diagnostics_when_syntax_error(self, xsd_schema: etree.XMLSchema) -> None: - service = GalaxyToolValidationService(TEST_SERVER_NAME, xsd_schema) + service = GalaxyToolSchemaValidationService(xsd_schema) xml_document = TestUtils.from_document_to_xml_document(TEST_SYNTAX_ERROR_TOOL_01_DOCUMENT) actual = service.validate_document(xml_document) @@ -57,7 +53,7 @@ def test_validate_document_returns_diagnostics_when_syntax_error(self, xsd_schem assert len(actual) == 1 def test_validate_macro_file_returns_diagnostics_when_syntax_error(self, xsd_schema: etree.XMLSchema) -> None: - service = GalaxyToolValidationService(TEST_SERVER_NAME, xsd_schema) + service = GalaxyToolSchemaValidationService(xsd_schema) xml_document = TestUtils.from_document_to_xml_document(TEST_SYNTAX_ERROR_MACRO_01_DOCUMENT) actual = service.validate_document(xml_document) diff --git a/server/galaxyls/tests/unit/test_xsd_service.py b/server/galaxyls/tests/unit/test_xsd_service.py index f989cec7..7be81305 100644 --- a/server/galaxyls/tests/unit/test_xsd_service.py +++ b/server/galaxyls/tests/unit/test_xsd_service.py @@ -6,7 +6,7 @@ class TestGalaxyToolXsdServiceClass: def test_get_documentation_for_unknown_node_attribute_returns_no_documentation(self, mocker: MockerFixture) -> None: - service = GalaxyToolXsdService("Test") + service = GalaxyToolXsdService() fake_context = mocker.Mock() fake_context.xsd_element = None @@ -15,7 +15,7 @@ def test_get_documentation_for_unknown_node_attribute_returns_no_documentation(s assert doc.value == MSG_NO_DOCUMENTATION_AVAILABLE def test_get_documentation_for_annotated_element(self, mocker: MockerFixture) -> None: - service = GalaxyToolXsdService("Test") + service = GalaxyToolXsdService() fake_context = mocker.Mock() fake_context.is_tag = True fake_context.is_attribute_key = False @@ -27,7 +27,7 @@ def test_get_documentation_for_annotated_element(self, mocker: MockerFixture) -> assert doc.value != MSG_NO_DOCUMENTATION_AVAILABLE def test_get_documentation_for_element_using_annotated_type(self, mocker: MockerFixture) -> None: - service = GalaxyToolXsdService("Test") + service = GalaxyToolXsdService() fake_context = mocker.Mock() fake_context.is_tag = True fake_context.is_attribute_key = False @@ -39,7 +39,7 @@ def test_get_documentation_for_element_using_annotated_type(self, mocker: Mocker assert doc.value != MSG_NO_DOCUMENTATION_AVAILABLE def test_get_documentation_for_annotated_attribute(self, mocker: MockerFixture) -> None: - service = GalaxyToolXsdService("Test") + service = GalaxyToolXsdService() fake_context = mocker.Mock() fake_context.is_tag = False fake_context.is_attribute_key = True diff --git a/server/galaxyls/tests/unit/utils.py b/server/galaxyls/tests/unit/utils.py index a6bad166..d8d40912 100644 --- a/server/galaxyls/tests/unit/utils.py +++ b/server/galaxyls/tests/unit/utils.py @@ -88,6 +88,12 @@ def get_test_document_from_file(filename: str) -> Document: uri = path.as_uri() return Document(uri) + @staticmethod + def get_test_xml_document_from_file(filename: str) -> XmlDocument: + """Gets a parsed XML document from the tests/files directory.""" + document = TestUtils.get_test_document_from_file(filename) + return TestUtils.from_document_to_xml_document(document) + @staticmethod def get_test_file_contents(filename: str) -> str: """Gets a the text contents of the given filename within the tests/files directory.