From 292f7a051b651e9c003b6fc5c6e9b0cc8f5401bc Mon Sep 17 00:00:00 2001 From: TiM Date: Mon, 1 Jun 2026 11:42:56 +1200 Subject: [PATCH] solidlsp: recognize Arduino .ino files as C++ .ino sketches are C++ but were absent from the CPP and CPP_CCLS source-file matchers, so Serena refused symbol operations on them ("Cannot extract symbols ... Active languages"). Add .ino to both matchers, plus a server-independent unit test. Note: clangd cannot infer a compile job from the .ino extension by itself, so a project still needs to declare the language (a .clangd with CompileFlags Add: [-xc++], or a compile DB). With that in place clangd returns the full document-symbol tree for a sketch. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/solidlsp/ls_config.py | 7 +++++++ test/solidlsp/cpp/test_cpp_basic.py | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/solidlsp/ls_config.py b/src/solidlsp/ls_config.py index 8f593833a..9ef5da853 100644 --- a/src/solidlsp/ls_config.py +++ b/src/solidlsp/ls_config.py @@ -350,6 +350,11 @@ def get_source_fn_matcher(self) -> FilenameMatcher: # OpenCL ".cl", ".clcpp", + # Arduino sketch: not in clang's extension table, but it is C++. + # Routing it here lets clangd serve symbols; the project must + # tell clangd it is C++ (a .clangd with CompileFlags Add: [-xc++], + # or a compile DB), since the clang driver can't infer a job from .ino. + ".ino", case_sensitive=False, ) case self.CPP_CCLS: @@ -375,6 +380,8 @@ def get_source_fn_matcher(self) -> FilenameMatcher: # Objective-C ".m", ".mm", + # Arduino sketch (C++); see note in the CPP case above. + ".ino", case_sensitive=False, ) case self.KOTLIN: diff --git a/test/solidlsp/cpp/test_cpp_basic.py b/test/solidlsp/cpp/test_cpp_basic.py index 21b904528..749efcac6 100644 --- a/test/solidlsp/cpp/test_cpp_basic.py +++ b/test/solidlsp/cpp/test_cpp_basic.py @@ -24,6 +24,20 @@ _cpp_servers.append(Language.CPP_CCLS) +@pytest.mark.parametrize("language", [Language.CPP, Language.CPP_CCLS]) +def test_source_fn_matcher_includes_ino(language: Language) -> None: + """Arduino .ino sketches are C++ and must route to the C++ language server. + + This is a pure matcher check; it needs no running language server. + """ + matcher = language.get_source_fn_matcher() + assert matcher.is_relevant_filename("sketch.ino") + assert matcher.is_relevant_filename("BLINK.INO") # case-insensitive + assert matcher.is_relevant_filename("/path/to/s3_camera.ino") + assert matcher.is_relevant_filename("main.cpp") # regression: ordinary C++ still matches + assert not matcher.is_relevant_filename("notes.md") + + @pytest.mark.cpp @pytest.mark.skipif(not _cpp_servers, reason="No C++ language server (clangd or ccls) available") class TestCppLanguageServer: