Merge pull request #1154 from zerone0x/fix/allow-project-creation-without-detected-languages

fix: allow project creation when no LSP-supported languages are detected
This commit is contained in:
Dr. Dominik Jain authored and GitHub committed 2026-03-11 00:40:05 +01:00
commit f561204840
2 files changed
+47 -41

No files matched your search

+32 -32
View File
@@ -292,40 +292,40 @@ class ProjectConfig(SharedConfig):
language_composition = determine_programming_language_composition(str(project_root))
log.info("Language composition: %s", language_composition)
if len(language_composition) == 0:
language_values = ", ".join([lang.value for lang in Language])
raise ValueError(
f"No source files found in {project_root}\n\n"
f"To use Serena with this project, you need to either\n"
f" 1. specify a programming language by adding parameters --language <language>\n"
f" when creating the project via the Serena CLI command OR\n"
f" 2. add source files in one of the supported languages first.\n\n"
f"Supported languages are: {language_values}\n"
f"Read the documentation for more information."
log.warning(
"No source files for supported language servers were found in %s. "
"Creating project with no configured languages. "
"Symbol-related tools (e.g. find_symbol, get_symbols_overview) will not work "
"when using the LSP backend. You can add languages later via the Serena dashboard "
"or by manually editing the project configuration.",
project_root,
)
# sort languages by number of files found
languages_and_percentages = sorted(
language_composition.items(), key=lambda item: (item[1], item[0].get_priority()), reverse=True
)
# find the language with the highest percentage and enable it
top_language_pair = languages_and_percentages[0]
other_language_pairs = languages_and_percentages[1:]
languages_to_use: list[str] = [top_language_pair[0].value]
# if in interactive mode, ask the user which other languages to enable
if len(other_language_pairs) > 0 and interactive:
print(
"Detected and enabled main language '%s' (%.2f%% of source files)."
% (top_language_pair[0].value, top_language_pair[1])
languages_to_use: list[str] = []
else:
# sort languages by number of files found
languages_and_percentages = sorted(
language_composition.items(), key=lambda item: (item[1], item[0].get_priority()), reverse=True
)
print(f"Additionally detected {len(other_language_pairs)} other language(s).\n")
print("Note: Enable only languages you need symbolic retrieval/editing capabilities for.")
print(" Additional language servers use resources and some languages may require additional")
print(" system-level installations/configuration (see Serena documentation).")
print("\nWhich additional languages do you want to enable?")
for lang, perc in other_language_pairs:
enable = ask_yes_no("Enable %s (%.2f%% of source files)?" % (lang.value, perc), default=False)
if enable:
languages_to_use.append(lang.value)
print()
# find the language with the highest percentage and enable it
top_language_pair = languages_and_percentages[0]
other_language_pairs = languages_and_percentages[1:]
languages_to_use = [top_language_pair[0].value]
# if in interactive mode, ask the user which other languages to enable
if len(other_language_pairs) > 0 and interactive:
print(
"Detected and enabled main language '%s' (%.2f%% of source files)."
% (top_language_pair[0].value, top_language_pair[1])
)
print(f"Additionally detected {len(other_language_pairs)} other language(s).\n")
print("Note: Enable only languages you need symbolic retrieval/editing capabilities for.")
print(" Additional language servers use resources and some languages may require additional")
print(" system-level installations/configuration (see Serena documentation).")
print("\nWhich additional languages do you want to enable?")
for lang, perc in other_language_pairs:
enable = ask_yes_no("Enable %s (%.2f%% of source files)?" % (lang.value, perc), default=False)
if enable:
languages_to_use.append(lang.value)
print()
log.info("Using languages: %s", languages_to_use)
else:
languages_to_use = [lang.value for lang in languages]
+15 -9
View File
@@ -37,12 +37,18 @@ class TestProjectConfigAutogenerate:
shutil.rmtree(self.test_dir)
def test_autogenerate_empty_directory(self):
"""Test that autogenerate raises ValueError with helpful message for empty directory."""
with pytest.raises(ValueError) as exc_info:
"""Test that autogenerate succeeds with empty languages list for an empty directory."""
config = ProjectConfig.autogenerate(self.project_path, self.serena_config, save_to_disk=False)
assert config.project_name == self.project_path.name
assert config.languages == []
def test_autogenerate_empty_directory_logs_warning(self, caplog):
"""Test that autogenerate logs a warning when no language files are found."""
with caplog.at_level(logging.WARNING):
ProjectConfig.autogenerate(self.project_path, self.serena_config, save_to_disk=False)
error_message = str(exc_info.value)
assert "No source files found" in error_message
assert any("No source files for supported language servers were found" in msg for msg in caplog.messages)
def test_autogenerate_with_python_files(self):
"""Test successful autogeneration with Python source files."""
@@ -105,7 +111,7 @@ class TestProjectConfigAutogenerate:
assert "Project root not found" in str(exc_info.value)
def test_autogenerate_with_gitignored_files_only(self):
"""Test autogenerate behavior when only gitignored files exist."""
"""Test autogenerate creates a project with empty languages when only gitignored files exist."""
# Create a .gitignore that ignores all Python files
gitignore = self.project_path / ".gitignore"
gitignore.write_text("*.py\n")
@@ -113,11 +119,11 @@ class TestProjectConfigAutogenerate:
# Create Python files that will be ignored
(self.project_path / "ignored.py").write_text("print('ignored')")
# Should still raise ValueError as no source files are detected
with pytest.raises(ValueError) as exc_info:
ProjectConfig.autogenerate(self.project_path, self.serena_config, save_to_disk=False)
# Should succeed with empty languages (gitignored files are not counted)
config = ProjectConfig.autogenerate(self.project_path, self.serena_config, save_to_disk=False)
assert "No source files found" in str(exc_info.value)
assert config.project_name == self.project_path.name
assert config.languages == []
def test_autogenerate_custom_project_name(self):
"""Test autogenerate with custom project name."""