import textwrap from debputy.lsp.debputy_ls import DebputyLanguageServer try: from lsprotocol.types import ( CompletionParams, TextDocumentIdentifier, HoverParams, MarkupContent, SemanticTokensParams, ) from debputy.lsp.lsp_debian_control import ( _debian_control_completions, _debian_control_hover, _debian_control_semantic_tokens_full, ) from pygls.server import LanguageServer except ImportError: pass from lsp_tests.lsp_tutil import ( put_doc_with_cursor, put_doc_no_cursor, resolve_semantic_tokens, resolved_semantic_token, ) def test_dctrl_complete_field(ls: "DebputyLanguageServer") -> None: dctrl_uri = "file:///nowhere/debian/control" cursor_pos = put_doc_with_cursor( ls, dctrl_uri, "debian/control", textwrap.dedent( """\ Source: foo Package: foo """ ), ) matches = _debian_control_completions( ls, CompletionParams(TextDocumentIdentifier(dctrl_uri), cursor_pos), ) assert isinstance(matches, list) keywords = {m.label for m in matches} assert "Multi-Arch" in keywords assert "Architecture" in keywords # Already present or wrong section assert "Package" not in keywords assert "Source" not in keywords def test_dctrl_hover_doc_field(ls: "DebputyLanguageServer") -> None: dctrl_uri = "file:///nowhere/debian/control" cursor_pos = put_doc_with_cursor( ls, dctrl_uri, "debian/control", textwrap.dedent( """\ Source: foo Package: foo Architecture: any """ ), ) hover_doc = _debian_control_hover( ls, HoverParams(TextDocumentIdentifier(dctrl_uri), cursor_pos), ) assert hover_doc is not None and isinstance(hover_doc.contents, MarkupContent) assert "Determines which architecture" in hover_doc.contents.value def test_dctrl_hover_doc_synopsis(ls: "DebputyLanguageServer") -> None: dctrl_uri = "file:///nowhere/debian/control" cursor_pos = put_doc_with_cursor( ls, dctrl_uri, "debian/control", textwrap.dedent( """\ Source: foo Package: foo Architecture: any Description: super charged tool with batteries included """ ), ) hover_doc = _debian_control_hover( ls, HoverParams(TextDocumentIdentifier(dctrl_uri), cursor_pos), ) assert hover_doc is not None and isinstance(hover_doc.contents, MarkupContent) assert hover_doc.contents.value.startswith("# Package synopsis") assert "super charged tool with batteries included" in hover_doc.contents.value def test_dctrl_hover_doc_substvars(ls: "DebputyLanguageServer") -> None: dctrl_uri = "file:///nowhere/debian/control" matching_cases = [ "bar (= ${binary:Version})", "bar (= ${binary:Version})", "bar (= ${binary:Version})", ] for variant in matching_cases: cursor_pos = put_doc_with_cursor( ls, dctrl_uri, "debian/control", textwrap.dedent( f"""\ Source: foo Package: foo Architecture: any Depends: bar (= {variant}) Description: super charged tool with batteries included """ ), ) hover_doc = _debian_control_hover( ls, HoverParams(TextDocumentIdentifier(dctrl_uri), cursor_pos), ) assert hover_doc is not None and isinstance(hover_doc.contents, MarkupContent) assert hover_doc.contents.value.startswith("# Substvar `${binary:Version}`") non_matching_cases = [ "bar (= ${binary:Version})", "bar (= ${binary:Version})", ] for variant in non_matching_cases: cursor_pos = put_doc_with_cursor( ls, dctrl_uri, "debian/control", textwrap.dedent( f"""\ Source: foo Package: foo Architecture: any Depends: bar (= {variant}) Description: super charged tool with batteries included """ ), ) hover_doc = _debian_control_hover( ls, HoverParams(TextDocumentIdentifier(dctrl_uri), cursor_pos), ) provided_doc = "" if hover_doc is not None and isinstance(hover_doc.contents, MarkupContent): provided_doc = hover_doc.contents.value assert not provided_doc.startswith("# Substvar `${binary:Version}`") def test_dctrl_semantic_tokens(ls: "DebputyLanguageServer") -> None: dctrl_uri = "file:///nowhere/debian/control" put_doc_no_cursor( ls, dctrl_uri, "debian/control", textwrap.dedent( """\ # Some leading comment Source: foo # Comment between stanzas Package: foo # Comment before Architecture Architecture: any Depends: # Comment about bar bar (>= 1.0), baz [linux-any] Description: super charged tool with batteries included Unknown-Field: Some value # Comment in that field that we do not know about. """ ), ) semantic_tokens = _debian_control_semantic_tokens_full( ls, SemanticTokensParams(TextDocumentIdentifier(dctrl_uri)), ) resolved_semantic_tokens = resolve_semantic_tokens(semantic_tokens) assert resolved_semantic_tokens is not None assert resolved_semantic_tokens == [ resolved_semantic_token(0, 0, len("# Some leading comment"), "comment"), resolved_semantic_token(2, 0, len("Source"), "keyword"), resolved_semantic_token(4, 0, len("# Comment between stanzas"), "comment"), resolved_semantic_token(6, 0, len("Package"), "keyword"), resolved_semantic_token(7, 0, len("# Comment before Architecture"), "comment"), resolved_semantic_token(8, 0, len("Architecture"), "keyword"), resolved_semantic_token(8, len("Architecture: "), len("any"), "enumMember"), resolved_semantic_token(9, 0, len("Depends"), "keyword"), resolved_semantic_token(10, 0, len("# Comment about bar"), "comment"), resolved_semantic_token(13, 0, len("Description"), "keyword"), resolved_semantic_token(14, 0, len("Unknown-Field"), "keyword"), # TODO: resolved_semantic_token(15, 0, len("# Comment in that field"), "comment"), ]