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: