## Summary - **CMake-based CDB generation for module tests**: Replace hand-written compile_commands.json with CMakeLists.txt (CMake 3.28 `FILE_SET CXX_MODULES`) in all 26 `tests/data/modules/*/` directories. CDB is generated on-the-fly via `cmake -G Ninja` during test setup. - **`@pytest.mark.workspace()` decorator**: Introduce a marker + fixture pattern so tests declare their workspace via decorator and receive a resolved `workspace` path. The fixture auto-generates CDB when a CMakeLists.txt is present. - **`CliceClient` helper methods**: Add `initialize()`, `open()`, `wait_diagnostics()`, and `open_and_wait()` to reduce boilerplate across all test files. - **Use `asyncio_mode = "auto"`**: Switch from `@pytest_asyncio.fixture` + `@pytest.mark.asyncio` to `@pytest.fixture` + auto mode for proper Pylance type inference on fixtures. - **Test cleanup**: Remove redundant section separators and docstrings, delete `tests/pyproject.toml` (config moved to `pytest.ini`). - **Format task**: Add `.cppm` to `format-cpp` glob pattern. - **CI fix**: Disable `CMAKE_CXX_SCAN_FOR_MODULES` and prefer pixi clang++ to fix macOS CI where CMake rejects module scanning. ## Test plan - [x] All 26 module test directories have CMakeLists.txt with FILE_SET CXX_MODULES - [x] generate_cdb() produces valid compile_commands.json with module flags - [x] Integration tests pass locally - [ ] CI passes on all platforms (Linux, macOS, Windows) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Unified fixtures and client workflow: new init/open/wait helpers, workspace marker support, bounded diagnostics waiting, CMake-based compilation-database generation, and directory-backed temp-file workflows; enabled asyncio test mode. * **Chores** * Added many C++20 module test projects and test data; removed prior test pyproject in favor of pytest config; updated formatter to include .cppm files. * **Style** * Reformatted many module/source implementations to consistent multi-line function bodies. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
110 lines
3.2 KiB
Python
110 lines
3.2 KiB
Python
"""File operation tests for the clice LSP server."""
|
|
|
|
import asyncio
|
|
|
|
import pytest
|
|
from lsprotocol.types import (
|
|
CompletionParams,
|
|
DidChangeTextDocumentParams,
|
|
DidCloseTextDocumentParams,
|
|
DidSaveTextDocumentParams,
|
|
HoverParams,
|
|
Position,
|
|
SignatureHelpParams,
|
|
TextDocumentContentChangeWholeDocument,
|
|
TextDocumentIdentifier,
|
|
VersionedTextDocumentIdentifier,
|
|
)
|
|
|
|
|
|
@pytest.mark.workspace("hello_world")
|
|
async def test_did_open(client, workspace):
|
|
client.open(workspace / "main.cpp")
|
|
await asyncio.sleep(5)
|
|
|
|
|
|
@pytest.mark.workspace("hello_world")
|
|
async def test_did_change(client, workspace):
|
|
uri, content = client.open(workspace / "main.cpp")
|
|
|
|
for i in range(20):
|
|
content += "\n"
|
|
await asyncio.sleep(0.2)
|
|
client.text_document_did_change(
|
|
DidChangeTextDocumentParams(
|
|
text_document=VersionedTextDocumentIdentifier(uri=uri, version=i + 1),
|
|
content_changes=[TextDocumentContentChangeWholeDocument(text=content)],
|
|
)
|
|
)
|
|
await asyncio.sleep(5)
|
|
|
|
|
|
@pytest.mark.workspace("clang_tidy")
|
|
async def test_clang_tidy(client, workspace):
|
|
client.open(workspace / "main.cpp")
|
|
await asyncio.sleep(5)
|
|
|
|
|
|
@pytest.mark.workspace("hello_world")
|
|
async def test_hover_save_close(client, workspace):
|
|
main_cpp = workspace / "main.cpp"
|
|
|
|
uri, content = client.open(main_cpp)
|
|
|
|
# Wait for initial compilation
|
|
await client.wait_diagnostics(uri)
|
|
|
|
# Change and save
|
|
content += "\nint saved = 1;\n"
|
|
event = client.wait_for_diagnostics(uri)
|
|
client.text_document_did_change(
|
|
DidChangeTextDocumentParams(
|
|
text_document=VersionedTextDocumentIdentifier(uri=uri, version=1),
|
|
content_changes=[TextDocumentContentChangeWholeDocument(text=content)],
|
|
)
|
|
)
|
|
client.text_document_did_save(
|
|
DidSaveTextDocumentParams(text_document=TextDocumentIdentifier(uri=uri))
|
|
)
|
|
|
|
# Wait for recompilation
|
|
await asyncio.wait_for(event.wait(), timeout=30.0)
|
|
|
|
# Hover on 'add'
|
|
hover = await client.text_document_hover_async(
|
|
HoverParams(
|
|
text_document=TextDocumentIdentifier(uri=uri),
|
|
position=Position(line=0, character=4),
|
|
)
|
|
)
|
|
assert hover is not None
|
|
assert hover.contents is not None
|
|
|
|
# Completion and signature help at (0,0) — just verify no crash
|
|
await client.text_document_completion_async(
|
|
CompletionParams(
|
|
text_document=TextDocumentIdentifier(uri=uri),
|
|
position=Position(line=0, character=0),
|
|
)
|
|
)
|
|
await client.text_document_signature_help_async(
|
|
SignatureHelpParams(
|
|
text_document=TextDocumentIdentifier(uri=uri),
|
|
position=Position(line=0, character=0),
|
|
)
|
|
)
|
|
|
|
# Close
|
|
client.text_document_did_close(
|
|
DidCloseTextDocumentParams(text_document=TextDocumentIdentifier(uri=uri))
|
|
)
|
|
|
|
# Hover on closed file should return null
|
|
closed_hover = await client.text_document_hover_async(
|
|
HoverParams(
|
|
text_document=TextDocumentIdentifier(uri=uri),
|
|
position=Position(line=0, character=0),
|
|
)
|
|
)
|
|
assert closed_hover is None
|