diff --git a/src/serena/config/serena_config.py b/src/serena/config/serena_config.py index d8e10a65..2a13934c 100644 --- a/src/serena/config/serena_config.py +++ b/src/serena/config/serena_config.py @@ -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 \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] diff --git a/test/serena/config/test_serena_config.py b/test/serena/config/test_serena_config.py index f6a107a5..1c09cceb 100644 --- a/test/serena/config/test_serena_config.py +++ b/test/serena/config/test_serena_config.py @@ -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."""