mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-03 09:13:49 +00:00
Merge pull request #1642 from weiconghe/feat/perl-configurable-file-filter
Perl: expose file_filter/ignore_dirs via ls_specific_settings (#1449)
This commit is contained in:
7 files changed
+341
-9
No files matched your search
@@ -56,6 +56,12 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
(e.g. JDTLS reporting Lombok-generated classes under `target/classes`). Missing paths are now
|
||||
classified by the usual ignore rules, and symbol locations resolving to non-existent files are skipped.
|
||||
- Solidity: fix diagnostics intermittently coming back empty on slow or cold environments (macOS/Windows CI).
|
||||
- Perl: expose `file_filter` and `ignore_dirs` via `ls_specific_settings["perl"]`, so projects with
|
||||
non-standard extensions (e.g. `.cgi`, `.psgi`) can make those files visible to Perl::LanguageServer.
|
||||
Configured extensions are also synced into the Perl source-file matcher (now a cached singleton),
|
||||
keeping `find_symbol` / symbol indexing consistent with the LS; the matcher is reset on every
|
||||
language server activation so one project's reconfiguration does not leak into the next.
|
||||
`FilenameMatcher` gains `add_extensions` / `reset` methods. Defaults are unchanged. #1449
|
||||
- C/C++ (clangd): improve support and documentation for Unreal Engine 5 projects.
|
||||
- HLSL (`shader-language-server`): pass `--locked` to `cargo install` when building from source
|
||||
on macOS (and in the manual-install instructions), honoring the crate's packaged `Cargo.lock`.
|
||||
|
||||
@@ -871,6 +871,34 @@ Notes:
|
||||
- Use the FPC compiler driver (`fpc`/`fpc.exe`), not backend compilers like `ppc386.exe`.
|
||||
- These settings are passed as environment variables to the pasls process.
|
||||
|
||||
#### Perl
|
||||
|
||||
Serena uses [Perl::LanguageServer](https://metacpan.org/pod/Perl::LanguageServer) for Perl support. Install Perl and the server with `cpanm Perl::LanguageServer`; Linux and macOS only (the server does not run on Windows).
|
||||
|
||||
Perl::LanguageServer only indexes files whose extension is in its `perl.fileFilter` and skips directories listed in `perl.ignoreDirs`. Both are exposed below so projects with non-standard extensions (e.g. `.cgi` / `.psgi` web handlers) can make those files visible (#1449).
|
||||
|
||||
**Configuration:**
|
||||
|
||||
Configure the language server via `ls_specific_settings.perl` in `serena_config.yml`:
|
||||
|
||||
| Setting | Default | Description |
|
||||
| -------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
||||
| `file_filter` | `[".pm", ".pl", ".t"]` | File extensions (with leading dot) that Perl::LanguageServer should index, e.g. `[".pm", ".pl", ".t", ".cgi"]`. |
|
||||
| `ignore_dirs` | `[".git", ".svn", "blib", "local", ".carton", "vendor", "_build", "cover_db"]` | Directory names Perl::LanguageServer should skip when indexing. |
|
||||
|
||||
Example configuration:
|
||||
|
||||
```yaml
|
||||
ls_specific_settings:
|
||||
perl:
|
||||
file_filter: [".pm", ".pl", ".t", ".cgi", ".psgi"]
|
||||
ignore_dirs: [".git", "blib", "local", "vendor", "cover_db"]
|
||||
```
|
||||
|
||||
Notes:
|
||||
- Extensions added via `file_filter` are also synced into Serena's Perl source-file matcher, so `find_symbol` and symbol indexing treat the same files as the language server. Defaults are unchanged when these keys are omitted.
|
||||
- The matcher is reset on every language server activation, so one project's `file_filter` does not leak into another.
|
||||
|
||||
#### PHP (`Intelephense`)
|
||||
|
||||
Serena uses Intelephense for the `php` language key.
|
||||
|
||||
@@ -12,7 +12,7 @@ from typing import Any
|
||||
from overrides import override
|
||||
|
||||
from solidlsp.ls import SolidLanguageServer
|
||||
from solidlsp.ls_config import LanguageServerConfig
|
||||
from solidlsp.ls_config import Language, LanguageServerConfig
|
||||
from solidlsp.ls_utils import PlatformId, PlatformUtils
|
||||
from solidlsp.lsp_protocol_handler.lsp_types import DidChangeConfigurationParams
|
||||
from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo
|
||||
@@ -20,15 +20,26 @@ from solidlsp.settings import SolidLSPSettings
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
# Defaults handed to Perl::LanguageServer via its `perl.fileFilter` / `perl.ignoreDirs` settings.
|
||||
# Exposed for override via `ls_specific_settings["perl"]`. Extensions added via `file_filter` are
|
||||
# also synced into Language.PERL.get_source_fn_matcher() (a cached singleton) so Serena's symbol
|
||||
# index and the language server agree on which files are Perl sources (#1449).
|
||||
_DEFAULT_FILE_FILTER: list[str] = [".pm", ".pl", ".t"]
|
||||
_DEFAULT_IGNORE_DIRS: list[str] = [".git", ".svn", "blib", "local", ".carton", "vendor", "_build", "cover_db"]
|
||||
|
||||
|
||||
class PerlLanguageServer(SolidLanguageServer):
|
||||
"""
|
||||
Provides Perl specific instantiation of the LanguageServer class using Perl::LanguageServer.
|
||||
"""
|
||||
|
||||
# Keep in sync with Language.PERL.get_source_fn_matcher() in solidlsp/ls_config.py:
|
||||
# extensions missing here are invisible to Perl::LanguageServer's project index.
|
||||
_FILE_FILTER: list = [".pm", ".pl", ".t"]
|
||||
You can pass the following entries in ``ls_specific_settings["perl"]``:
|
||||
- file_filter: List of file extensions (with leading dot) that Perl::LanguageServer should
|
||||
index, e.g. ``[".pm", ".pl", ".t", ".cgi"]``. Defaults to ``[".pm", ".pl", ".t"]``.
|
||||
The same extensions are added to Serena's Perl source-file matcher, so ``find_symbol``
|
||||
and symbol indexing treat them consistently (see #1449).
|
||||
- ignore_dirs: Directory names Perl::LanguageServer should skip when indexing. Defaults to
|
||||
``[".git", ".svn", "blib", "local", ".carton", "vendor", "_build", "cover_db"]``.
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def _get_perl_version() -> str | None:
|
||||
@@ -101,6 +112,31 @@ class PerlLanguageServer(SolidLanguageServer):
|
||||
|
||||
return "perl -MPerl::LanguageServer -e 'Perl::LanguageServer::run'"
|
||||
|
||||
@staticmethod
|
||||
def _resolve_filter_settings(solidlsp_settings: SolidLSPSettings) -> tuple[list[str], list[str]]:
|
||||
"""Resolve the ``fileFilter`` / ``ignoreDirs`` to hand to Perl::LanguageServer.
|
||||
|
||||
Reads optional overrides from ``ls_specific_settings["perl"]`` (keys ``file_filter`` and
|
||||
``ignore_dirs``); falls back to the defaults otherwise. Extracted as a pure function so the
|
||||
configuration plumbing can be unit-tested without starting the language server.
|
||||
"""
|
||||
perl_settings = solidlsp_settings.get_ls_specific_settings(Language.PERL)
|
||||
file_filter = perl_settings.get("file_filter", list(_DEFAULT_FILE_FILTER))
|
||||
ignore_dirs = perl_settings.get("ignore_dirs", list(_DEFAULT_IGNORE_DIRS))
|
||||
return file_filter, ignore_dirs
|
||||
|
||||
@staticmethod
|
||||
def _sync_source_fn_matcher(file_filter: list[str]) -> None:
|
||||
"""Keep Serena's Perl source-file matcher in sync with the LS ``fileFilter``.
|
||||
|
||||
``Language.PERL.get_source_fn_matcher()`` is a ``@cache``d per-language singleton, so adding
|
||||
the configured extensions here propagates to every consumer of the matcher — symbol index
|
||||
traversal (``project.is_ignored_path``), the LS ignore check (``ls.is_ignored_path``), and
|
||||
language composition detection. Without this, ``find_symbol`` would not surface symbols in
|
||||
files whose extensions were added to ``file_filter`` (#1449).
|
||||
"""
|
||||
Language.PERL.get_source_fn_matcher().add_extensions(*file_filter)
|
||||
|
||||
def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings):
|
||||
# Setup runtime dependencies before initializing
|
||||
perl_ls_cmd = self._setup_runtime_dependencies()
|
||||
@@ -109,6 +145,10 @@ class PerlLanguageServer(SolidLanguageServer):
|
||||
config, repository_root_path, ProcessLaunchInfo(cmd=perl_ls_cmd, cwd=repository_root_path), "perl", solidlsp_settings
|
||||
)
|
||||
self.request_id = 0
|
||||
self._file_filter, self._ignore_dirs = self._resolve_filter_settings(solidlsp_settings)
|
||||
# Sync Serena's source-file matcher with the configured extensions so find_symbol and the
|
||||
# language server agree on which files are Perl sources (see #1449).
|
||||
self._sync_source_fn_matcher(self._file_filter)
|
||||
|
||||
def _create_base_initialize_params(self) -> dict:
|
||||
"""
|
||||
@@ -153,8 +193,8 @@ class PerlLanguageServer(SolidLanguageServer):
|
||||
|
||||
perl_config = {
|
||||
"perlInc": [self.repository_root_path, "."],
|
||||
"fileFilter": self._FILE_FILTER,
|
||||
"ignoreDirs": [".git", ".svn", "blib", "local", ".carton", "vendor", "_build", "cover_db"],
|
||||
"fileFilter": self._file_filter,
|
||||
"ignoreDirs": self._ignore_dirs,
|
||||
}
|
||||
|
||||
return [perl_config]
|
||||
@@ -189,8 +229,8 @@ class PerlLanguageServer(SolidLanguageServer):
|
||||
"settings": {
|
||||
"perl": {
|
||||
"perlInc": [self.repository_root_path, "."],
|
||||
"fileFilter": self._FILE_FILTER,
|
||||
"ignoreDirs": [".git", ".svn", "blib", "local", ".carton", "vendor", "_build", "cover_db"],
|
||||
"fileFilter": self._file_filter,
|
||||
"ignoreDirs": self._ignore_dirs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -699,6 +699,11 @@ class SolidLanguageServer(ABC):
|
||||
"""
|
||||
identifies the language server (not to be confused with the language id passed to the language server)
|
||||
"""
|
||||
# The source filename matcher is a @cache'd per-language singleton. A previous project may
|
||||
# have extended it (e.g. Perl's file_filter adding .cgi); reset it here so every activation
|
||||
# starts from the language's default extensions, then language-server subclasses re-apply
|
||||
# their own settings during the rest of __init__.
|
||||
self.language.get_source_fn_matcher().reset()
|
||||
self._published_diagnostics: dict[str, list[ls_types.Diagnostic]] = {}
|
||||
self._published_diagnostics_generation_by_uri: dict[str, int] = {}
|
||||
self._published_diagnostics_generation = 0
|
||||
|
||||
@@ -26,6 +26,38 @@ class FilenameMatcher:
|
||||
"""
|
||||
self._file_extensions = list(set(file_extensions)) if case_sensitive else list(set(ext.lower() for ext in file_extensions))
|
||||
self._case_sensitive = case_sensitive
|
||||
# Snapshot of the initial configuration, used by ``reset``. Relevant for matchers that are
|
||||
# per-language singletons (``Language.get_source_fn_matcher`` is ``@cache``d): extensions added
|
||||
# via ``add_extensions`` for one project must not leak into the next, so the singleton is reset
|
||||
# to this snapshot at every language server initialisation.
|
||||
self._initial_file_extensions = list(self._file_extensions)
|
||||
|
||||
def reset(self) -> None:
|
||||
"""
|
||||
Restore the matcher to its initial set of extensions (as provided at construction).
|
||||
|
||||
Undoes any extensions added via :meth:`add_extensions`. Intended for the per-language
|
||||
singleton matchers, which are reset at the start of every language server initialisation so
|
||||
that a previous project's reconfiguration does not leak into a newly activated one.
|
||||
"""
|
||||
self._file_extensions = list(self._initial_file_extensions)
|
||||
|
||||
def add_extensions(self, *file_extensions: str) -> None:
|
||||
"""
|
||||
Add further file extensions to this matcher (idempotent).
|
||||
|
||||
This is intended for matchers that are per-language singletons, i.e. those returned by
|
||||
:meth:`Language.get_source_fn_matcher` (which is ``@cache``d): extensions that a user
|
||||
configures for a language server (e.g. ``.cgi`` for Perl) can be added here so that every
|
||||
consumer of the matcher — symbol index traversal, ignore checks, language composition —
|
||||
treats the same set of files as sources, staying in sync with the language server.
|
||||
|
||||
:param file_extensions: the additional file extensions, e.g. ``.cgi``
|
||||
"""
|
||||
for ext in file_extensions:
|
||||
norm = ext if self._case_sensitive else ext.lower()
|
||||
if norm not in self._file_extensions:
|
||||
self._file_extensions.append(norm)
|
||||
|
||||
def is_relevant_filename(self, fn: str) -> bool:
|
||||
if not self._case_sensitive:
|
||||
@@ -311,6 +343,7 @@ class Language(str, Enum):
|
||||
"""
|
||||
return self.get_ls_class().supports_implementation_request()
|
||||
|
||||
# NOTE: Caching results in a singleton per enum item, which is a precondition for persistent configuration of the matcher.
|
||||
@cache
|
||||
def get_source_fn_matcher(self) -> FilenameMatcher:
|
||||
match self:
|
||||
|
||||
Whitespace-only changes.
@@ -0,0 +1,220 @@
|
||||
"""Configuration plumbing for ``PerlLanguageServer``'s fileFilter / ignoreDirs.
|
||||
|
||||
``Perl::LanguageServer`` only indexes files whose extension is in ``perl.fileFilter`` and skips
|
||||
directories listed in ``perl.ignoreDirs``; both are pushed to the LS at startup (see
|
||||
``_start_server``). The defaults must stay backward-compatible, but projects with non-standard
|
||||
layouts — e.g. ``.cgi`` / ``.psgi`` Perl web handlers that can dominate a mature codebase — need
|
||||
a way to extend visibility (#1449).
|
||||
|
||||
These tests pin the configuration plumbing without starting the language server (which would
|
||||
require a Perl runtime), so they run in every environment. They also cover the source-file matcher
|
||||
sync that keeps ``find_symbol`` consistent with the LS (#1449).
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from solidlsp.language_servers.perl_language_server import (
|
||||
_DEFAULT_FILE_FILTER,
|
||||
_DEFAULT_IGNORE_DIRS,
|
||||
PerlLanguageServer,
|
||||
)
|
||||
from solidlsp.ls_config import FilenameMatcher, Language
|
||||
from solidlsp.settings import SolidLSPSettings
|
||||
|
||||
|
||||
def _settings(tmp_path: Path, ls_specific_settings: dict | None = None) -> SolidLSPSettings:
|
||||
"""A SolidLSPSettings rooted under ``tmp_path`` with optional perl overrides."""
|
||||
return SolidLSPSettings(
|
||||
solidlsp_dir=str(tmp_path / ".solidlsp"),
|
||||
ls_specific_settings=ls_specific_settings or {},
|
||||
)
|
||||
|
||||
|
||||
class TestResolveFilterSettings:
|
||||
def test_defaults_when_no_ls_specific_settings(self, tmp_path: Path) -> None:
|
||||
# Behaviour unchanged for projects that don't set ls_specific_settings at all.
|
||||
file_filter, ignore_dirs = PerlLanguageServer._resolve_filter_settings(_settings(tmp_path))
|
||||
|
||||
assert file_filter == _DEFAULT_FILE_FILTER
|
||||
assert ignore_dirs == _DEFAULT_IGNORE_DIRS
|
||||
|
||||
def test_defaults_when_perl_key_absent(self, tmp_path: Path) -> None:
|
||||
# ls_specific_settings configured for another language must not leak into Perl.
|
||||
settings = _settings(tmp_path, {Language.PYTHON: {"something": "unrelated"}})
|
||||
|
||||
file_filter, ignore_dirs = PerlLanguageServer._resolve_filter_settings(settings)
|
||||
|
||||
assert file_filter == _DEFAULT_FILE_FILTER
|
||||
assert ignore_dirs == _DEFAULT_IGNORE_DIRS
|
||||
|
||||
def test_custom_file_filter_makes_extra_extensions_visible(self, tmp_path: Path) -> None:
|
||||
# #1449: a Perl web backend must be able to surface .cgi / .psgi handlers.
|
||||
custom = [".pm", ".pl", ".t", ".cgi", ".psgi"]
|
||||
settings = _settings(tmp_path, {Language.PERL: {"file_filter": custom}})
|
||||
|
||||
file_filter, _ = PerlLanguageServer._resolve_filter_settings(settings)
|
||||
|
||||
assert file_filter == custom
|
||||
assert ".cgi" in file_filter
|
||||
|
||||
def test_custom_ignore_dirs(self, tmp_path: Path) -> None:
|
||||
custom = [".git", "blib", "local", "cover_db", "t"]
|
||||
settings = _settings(tmp_path, {Language.PERL: {"ignore_dirs": custom}})
|
||||
|
||||
_, ignore_dirs = PerlLanguageServer._resolve_filter_settings(settings)
|
||||
|
||||
assert ignore_dirs == custom
|
||||
|
||||
def test_both_overrides_apply_independently(self, tmp_path: Path) -> None:
|
||||
file_filter = [".pm", ".pl", ".cgi"]
|
||||
ignore_dirs = [".git", "vendor"]
|
||||
settings = _settings(
|
||||
tmp_path,
|
||||
{Language.PERL: {"file_filter": file_filter, "ignore_dirs": ignore_dirs}},
|
||||
)
|
||||
|
||||
resolved_filter, resolved_dirs = PerlLanguageServer._resolve_filter_settings(settings)
|
||||
|
||||
assert resolved_filter == file_filter
|
||||
assert resolved_dirs == ignore_dirs
|
||||
|
||||
def test_default_lists_are_not_mutated_across_instances(self, tmp_path: Path) -> None:
|
||||
# The resolver must copy the module-level defaults, otherwise one instance mutating its
|
||||
# returned list (or the LS handlers appending to self._file_filter) would corrupt every
|
||||
# subsequently created default-configured instance.
|
||||
file_filter, _ = PerlLanguageServer._resolve_filter_settings(_settings(tmp_path))
|
||||
file_filter.append(".cgi")
|
||||
|
||||
next_filter, _ = PerlLanguageServer._resolve_filter_settings(_settings(tmp_path))
|
||||
|
||||
assert next_filter == _DEFAULT_FILE_FILTER
|
||||
assert ".cgi" not in _DEFAULT_FILE_FILTER
|
||||
|
||||
|
||||
class TestFilenameMatcherAddExtensions:
|
||||
def test_adds_new_extension(self) -> None:
|
||||
matcher = FilenameMatcher(".pm", ".pl")
|
||||
|
||||
matcher.add_extensions(".cgi")
|
||||
|
||||
assert matcher.is_relevant_filename("lib/Foo.pm")
|
||||
assert matcher.is_relevant_filename("web/handler.cgi")
|
||||
|
||||
def test_is_idempotent(self) -> None:
|
||||
# Re-adding an existing extension must not duplicate it; calling sync twice (e.g. across
|
||||
# two PerlLanguageServer instances) must be a no-op.
|
||||
matcher = FilenameMatcher(".pm", ".pl")
|
||||
baseline = len(matcher._file_extensions)
|
||||
|
||||
matcher.add_extensions(".pm", ".pl")
|
||||
matcher.add_extensions(".cgi")
|
||||
matcher.add_extensions(".cgi")
|
||||
|
||||
assert len(matcher._file_extensions) == baseline + 1
|
||||
assert matcher.is_relevant_filename("foo.cgi")
|
||||
|
||||
def test_respects_case_insensitivity(self) -> None:
|
||||
matcher = FilenameMatcher(".pm", case_sensitive=False)
|
||||
|
||||
matcher.add_extensions(".CGI")
|
||||
|
||||
# case-insensitive matcher normalises to lower case
|
||||
assert matcher.is_relevant_filename("Handler.Cgi")
|
||||
assert ".cgi" in matcher._file_extensions
|
||||
assert ".CGI" not in matcher._file_extensions
|
||||
|
||||
|
||||
class TestFilenameMatcherReset:
|
||||
def test_reset_undoes_added_extensions(self) -> None:
|
||||
matcher = FilenameMatcher(".pm", ".pl")
|
||||
|
||||
matcher.add_extensions(".cgi", ".psgi")
|
||||
assert matcher.is_relevant_filename("h.cgi")
|
||||
|
||||
matcher.reset()
|
||||
|
||||
assert not matcher.is_relevant_filename("h.cgi")
|
||||
assert not matcher.is_relevant_filename("h.psgi")
|
||||
assert matcher.is_relevant_filename("h.pm")
|
||||
|
||||
def test_reset_restores_original_after_case_insensitive_add(self) -> None:
|
||||
matcher = FilenameMatcher(".PM", case_sensitive=False)
|
||||
|
||||
matcher.add_extensions(".cgi")
|
||||
matcher.reset()
|
||||
|
||||
# original extension survives the round-trip (normalised to lower case at construction)
|
||||
assert matcher._file_extensions == [".pm"]
|
||||
assert not matcher.is_relevant_filename("h.cgi")
|
||||
|
||||
def test_reset_is_idempotent(self) -> None:
|
||||
# SolidLanguageServer.__init__ calls reset on every activation; repeated resets must be safe
|
||||
# and must not shrink below the original configuration.
|
||||
matcher = FilenameMatcher(".pm", ".pl")
|
||||
baseline = len(matcher._file_extensions)
|
||||
|
||||
matcher.add_extensions(".cgi")
|
||||
matcher.reset()
|
||||
matcher.reset()
|
||||
|
||||
assert len(matcher._file_extensions) == baseline
|
||||
|
||||
|
||||
class TestSourceFnMatcherSync:
|
||||
def test_custom_file_filter_extends_perl_matcher(self, tmp_path: Path) -> None:
|
||||
# #1449: find_symbol relies on Language.PERL.get_source_fn_matcher(); unless the configured
|
||||
# extensions are synced into it, symbols in .cgi/.psgi files stay invisible even though the
|
||||
# LS indexes them. get_source_fn_matcher() is a @cache singleton, so reset() afterwards.
|
||||
matcher = Language.PERL.get_source_fn_matcher()
|
||||
try:
|
||||
assert not matcher.is_relevant_filename("handler.cgi") # guard: not matched by default
|
||||
|
||||
file_filter, _ = PerlLanguageServer._resolve_filter_settings(
|
||||
_settings(tmp_path, {Language.PERL: {"file_filter": [".pm", ".pl", ".t", ".cgi", ".psgi"]}})
|
||||
)
|
||||
PerlLanguageServer._sync_source_fn_matcher(file_filter)
|
||||
|
||||
assert matcher.is_relevant_filename("lib/Foo.pm")
|
||||
assert matcher.is_relevant_filename("web/handler.cgi")
|
||||
assert matcher.is_relevant_filename("app.psgi")
|
||||
finally:
|
||||
matcher.reset()
|
||||
|
||||
def test_default_file_filter_leaves_matcher_unchanged(self, tmp_path: Path) -> None:
|
||||
# The default file_filter matches the existing Perl matcher extensions, so syncing it must
|
||||
# be a no-op (no duplicate entries, no new matches).
|
||||
matcher = Language.PERL.get_source_fn_matcher()
|
||||
try:
|
||||
initial = list(matcher._file_extensions)
|
||||
file_filter, _ = PerlLanguageServer._resolve_filter_settings(_settings(tmp_path))
|
||||
PerlLanguageServer._sync_source_fn_matcher(file_filter)
|
||||
|
||||
assert sorted(matcher._file_extensions) == sorted(initial)
|
||||
finally:
|
||||
matcher.reset()
|
||||
|
||||
def test_reset_prevents_cross_project_leak(self, tmp_path: Path) -> None:
|
||||
# The matcher is a per-language singleton shared across projects. Project A reconfigures
|
||||
# file_filter (adds .cgi); when project B is activated, SolidLanguageServer.__init__ resets
|
||||
# the matcher first, so project B must NOT see .cgi even though project A added it.
|
||||
# Mirrors the reset-then-sync ordering of PerlLanguageServer.__init__.
|
||||
matcher = Language.PERL.get_source_fn_matcher()
|
||||
try:
|
||||
# project A: custom file_filter with .cgi
|
||||
filter_a, _ = PerlLanguageServer._resolve_filter_settings(
|
||||
_settings(tmp_path, {Language.PERL: {"file_filter": [".pm", ".pl", ".t", ".cgi"]}})
|
||||
)
|
||||
PerlLanguageServer._sync_source_fn_matcher(filter_a)
|
||||
assert matcher.is_relevant_filename("handler.cgi")
|
||||
|
||||
# project B activates: base __init__ resets, then default config is applied (no .cgi)
|
||||
matcher.reset()
|
||||
filter_b, _ = PerlLanguageServer._resolve_filter_settings(_settings(tmp_path / "proj_b"))
|
||||
PerlLanguageServer._sync_source_fn_matcher(filter_b)
|
||||
|
||||
assert not matcher.is_relevant_filename("handler.cgi"), (
|
||||
"project B inherited project A's .cgi — reset did not undo the reconfiguration"
|
||||
)
|
||||
assert matcher.is_relevant_filename("lib/Foo.pm")
|
||||
finally:
|
||||
matcher.reset()
|
||||
Reference in new issue
Block a user