Skip to content

Commit

Permalink
add testing of diagnostics
Browse files Browse the repository at this point in the history
Signed-off-by: Jade Abraham <[email protected]>
  • Loading branch information
jabraham17 committed May 11, 2024
1 parent 70948ba commit 93c55ff
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 23 deletions.
9 changes: 6 additions & 3 deletions tools/chpl-language-server/test/basic-resolver.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

@pytest_lsp.fixture(
config=ClientServerConfig(
server_command=[sys.executable, CLS_PATH(), "--resolver"]
server_command=[sys.executable, CLS_PATH(), "--resolver"],
client_factory=get_base_client,
)
)
async def client(lsp_client: LanguageClient):
Expand Down Expand Up @@ -52,7 +53,8 @@ async def test_go_to_record_def(client: LanguageClient):
await check_goto_type_def(client, doc, pos((2, 4)), pos((0, 7)))
await check_goto_type_def(client, doc, pos((3, 9)), pos((0, 7)))

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand All @@ -72,4 +74,5 @@ async def test_string(client: LanguageClient):
await check_goto_type_def(client, doc, pos((0, 4)), string_loc)
await check_goto_type_def(client, doc, pos((0, 12)), string_loc)

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0
32 changes: 23 additions & 9 deletions tools/chpl-language-server/test/basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@


@pytest_lsp.fixture(
config=ClientServerConfig(server_command=[sys.executable, CLS_PATH()])
config=ClientServerConfig(
server_command=[sys.executable, CLS_PATH()],
client_factory=get_base_client,
)
)
async def client(lsp_client: LanguageClient):
# Setup
Expand Down Expand Up @@ -67,7 +70,8 @@ async def test_global_completion(client: LanguageClient):
for symbol in global_symbols:
assert symbol in result_names

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -112,7 +116,8 @@ async def test_go_to_definition_simple(client: LanguageClient):
await check_goto_decl_def(client, doc, pos((0, 13)), None)
await check_goto_decl_def(client, doc, pos((4, 10)), None)

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -140,7 +145,8 @@ async def test_go_to_definition_use_standard(client: LanguageClient):
await check_goto_decl_def_module(client, doc, pos((1, 10)), mod_Map)
await check_goto_decl_def_module(client, doc, pos((2, 8)), mod_Time)

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -174,7 +180,8 @@ async def test_go_to_definition_standard_rename(client: LanguageClient):
client, doc, pos((2, 14)), mod_List, expect_str="record list"
)

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand All @@ -194,7 +201,8 @@ async def test_go_to_record_def(client: LanguageClient):
await check_goto_decl_def(client, doc, pos((1, 7)), pos((0, 7)))
await check_goto_decl_def(client, doc, pos((2, 12)), pos((0, 7)))

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand All @@ -214,7 +222,8 @@ async def test_go_to_string_type(client: LanguageClient):
client, doc, pos((0, 7)), mod_String, expect_str="record _string"
)

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -262,7 +271,8 @@ async def test_list_references(client: LanguageClient):
client, doc, pos((8, 13)), [pos((8, 13))]
)

assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -300,7 +310,11 @@ async def test_list_references_across_files(client: LanguageClient):
await check_references_and_cross_check(
client, docs("A"), pos((1, 6)), all_refs
)
assert len(client.diagnostics) == 0

await save_file(client, docs("A"), docs("B"), docs("C"))
assert len(client.diagnostics[docs("A").uri]) == 0
assert len(client.diagnostics[docs("B").uri]) == 0
assert len(client.diagnostics[docs("C").uri]) == 0


@pytest.mark.asyncio
Expand Down
12 changes: 8 additions & 4 deletions tools/chpl-language-server/test/call-inlays.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"--no-type-inlays",
"--no-param-inlays",
"--end-markers=none",
]
],
client_factory=get_base_client,
)
)
async def client(lsp_client: LanguageClient):
Expand Down Expand Up @@ -75,7 +76,8 @@ async def test_call_inlays(client: LanguageClient):
rng = Range(pos((0, 0)), pos((0, 0)))
with source_file(client, file) as doc:
await check_inlay_hints(client, doc, rng, inlays)
assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -104,7 +106,8 @@ async def test_nested_call_inlays(client: LanguageClient):
rng = Range(pos((0, 0)), pos((0, 0)))
with source_file(client, file) as doc:
await check_inlay_hints(client, doc, rng, inlays)
assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0


@pytest.mark.asyncio
Expand Down Expand Up @@ -137,4 +140,5 @@ async def test_call_inlays_generic(client: LanguageClient):

with source_file(client, file) as doc:
await check_inlay_hints(client, doc, rng, inlays)
assert len(client.diagnostics) == 0
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 0
13 changes: 9 additions & 4 deletions tools/chpl-language-server/test/cls-commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import sys

from lsprotocol.types import ClientCapabilities
from lsprotocol.types import CompletionList, CompletionParams
from lsprotocol.types import ReferenceParams, ReferenceContext
from lsprotocol.types import InitializeParams
import pytest
import pytest_lsp
Expand All @@ -17,7 +15,10 @@


@pytest_lsp.fixture(
config=ClientServerConfig(server_command=[sys.executable, CLS_PATH()])
config=ClientServerConfig(
server_command=[sys.executable, CLS_PATH()],
client_factory=get_base_client,
),
)
async def client(lsp_client: LanguageClient):
# Setup
Expand Down Expand Up @@ -102,4 +103,8 @@ async def test_list_references_across_dirs(client: LanguageClient):
client, z_refs[0][0], z_refs[0][1], z_refs
)

assert len(client.diagnostics) == 0
await save_file(client, docs("Main"), docs("subdir/A"), docs("subdir/B"), docs("subdir2/nested/C"))
assert len(client.diagnostics[docs("Main").uri]) == 0
assert len(client.diagnostics[docs("subdir/A").uri]) == 0
assert len(client.diagnostics[docs("subdir/B").uri]) == 0
assert len(client.diagnostics[docs("subdir2/nested/C").uri]) == 0
87 changes: 87 additions & 0 deletions tools/chpl-language-server/test/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,90 @@
Test that various diagnostics are reported properly such as syntax errors,
deprecations, and scope resolution errors
"""

import sys

from lsprotocol.types import ClientCapabilities
from lsprotocol.types import InitializeParams
import pytest
import pytest_lsp
from pytest_lsp import ClientServerConfig, LanguageClient

from util.utils import *
from util.config import CLS_PATH


@pytest_lsp.fixture(
config=ClientServerConfig(
server_command=[sys.executable, CLS_PATH()],
client_factory=get_base_client,
)
)
async def client(lsp_client: LanguageClient):
# Setup
params = InitializeParams(capabilities=ClientCapabilities())
await lsp_client.initialize_session(params)

yield

# Teardown
await lsp_client.shutdown_session()


@pytest.mark.asyncio
async def test_incorrect_cross_file_diagnostics(client: LanguageClient):
"""
Test that implicit module error only shows in correct file
"""
fileA = """
module A {
use B;
var x = 42;
}
"""
fileB = """
module B {
var x = 42;
}
writeln(x);
"""

with source_files(client, A=fileA, B=fileB) as docs:
await save_file(client, docs("B"), docs("A"))
assert len(client.diagnostics[docs("A").uri]) == 0
assert len(client.diagnostics[docs("B").uri]) == 1
assert (
"an implicit module named 'B' is being introduced to contain file-scope code"
in client.diagnostics[docs("B").uri][0].message
)


@pytest.mark.asyncio
async def test_deprecations(client: LanguageClient):
"""
Test that deprecations are reported
"""
file = """
@deprecated("a is deprecated")
var a = 10;
var b = a;
"""
with source_file(client, file) as doc:
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 1
assert "deprecated" in client.diagnostics[doc.uri][0].message


@pytest.mark.asyncio
async def test_syntax_errors(client: LanguageClient):
"""
Test that syntax errors are reported
"""
file = """
var a = 10
var b = a;
"""
with source_file(client, file) as doc:
await save_file(client, doc)
assert len(client.diagnostics[doc.uri]) == 1
assert "Syntax: " in client.diagnostics[doc.uri][0].message
5 changes: 5 additions & 0 deletions tools/chpl-language-server/test/highlight.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@


# hightlighs from symbols

# highlights from other files do not show in the current file
45 changes: 42 additions & 3 deletions tools/chpl-language-server/test/util/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,18 @@
from lsprotocol.types import InlayHintParams, InlayHintKind
from lsprotocol.types import LocationLink, Location, Position, Range
from lsprotocol.types import TextDocumentIdentifier
from lsprotocol.types import (
DidSaveTextDocumentParams,
TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS,
WORKSPACE_INLAY_HINT_REFRESH,
WORKSPACE_SEMANTIC_TOKENS_REFRESH,
)
from lsprotocol.types import (
DidChangeWorkspaceFoldersParams,
WorkspaceFoldersChangeEvent,
WorkspaceFolder,
)
from pytest_lsp import LanguageClient
from pytest_lsp import LanguageClient, make_test_lsp_client

from .config import CHPL_HOME

Expand All @@ -35,6 +41,22 @@ def strip_leading_whitespace(text: str) -> str:
return "\n".join(line[min_indent:] for line in lines)


def get_base_client() -> LanguageClient:
client = make_test_lsp_client()

@client.feature(WORKSPACE_INLAY_HINT_REFRESH)
def on_inlay_hint_refresh(params):
"""stub method for inlay hint refresh notifications"""
pass

@client.feature(WORKSPACE_SEMANTIC_TOKENS_REFRESH)
def on_semantic_token_refresh(params):
"""stub method for semantic token refresh notifications"""
pass

return client


class SourceFilesContext:
def __init__(self, client: LanguageClient, files: typing.Dict[str, str]):
self.tempdir = tempfile.TemporaryDirectory(delete=False)
Expand Down Expand Up @@ -131,6 +153,16 @@ def source_files_dict(client: LanguageClient, files: typing.Dict[str, str]):
return SourceFilesContext(client, files)


async def save_file(client: LanguageClient, *docs: TextDocumentIdentifier):
"""
Saves the given document.
"""
for doc in docs:
client.text_document_did_save(
params=DidSaveTextDocumentParams(text_document=doc)
)
await client.wait_for_notification(TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS)

def pos(coord: typing.Tuple[int, int]):
"""
Shorthand for writing position literals.
Expand Down Expand Up @@ -376,7 +408,15 @@ async def check_references_and_cross_check(
new_doc = TextDocumentIdentifier(uri=ref.uri)
await check_references(client, new_doc, ref.range.start, locations)

async def check_inlay_hints(client: LanguageClient, doc: TextDocumentIdentifier, rng: Range, expected_inlays: typing.List[typing.Tuple[Position, str, typing.Optional[InlayHintKind]]]):

async def check_inlay_hints(
client: LanguageClient,
doc: TextDocumentIdentifier,
rng: Range,
expected_inlays: typing.List[
typing.Tuple[Position, str, typing.Optional[InlayHintKind]]
],
):
"""
Check that the inlay hints in the document match the expected inlays. The
expected inlays list should be sorted in the order that the inlays appear
Expand All @@ -398,7 +438,6 @@ async def check_inlay_hints(client: LanguageClient, doc: TextDocumentIdentifier,
assert len(expected_inlays) == len(results)

sorted_results = sorted(results, key=lambda x: x.position)
print(sorted_results)

for expected, actual in zip(expected_inlays, sorted_results):
assert expected[0] == actual.position
Expand Down

0 comments on commit 93c55ff

Please sign in to comment.