Adding Language Support¶
How to add support for new programming languages in Feluda.
Feluda follows a modular architecture for language support. Each language has its own module in src/languages/ that implements dependency parsing and license resolution.
Language Module Structure¶
When adding a new language, create a new file src/languages/your_language.rs with this structure:
use crate::config::FeludaConfig;
use crate::debug::{log, LogLevel};
use crate::licenses::LicenseInfo;
use std::collections::{HashMap, HashSet};
/// Analyze dependencies and their licenses for YourLanguage projects
pub fn analyze_your_language_licenses(project_path: &str, config: &FeludaConfig) -> Vec<LicenseInfo> {
// Implementation here
}
/// Parse direct dependencies from project files
fn parse_direct_dependencies(project_path: &str, config: &FeludaConfig) -> Vec<(String, String)> {
// Parse project files (package.json, Cargo.toml, etc.)
}
/// Resolve transitive dependencies with depth tracking
fn resolve_transitive_dependencies(
project_path: &str,
direct_deps: &[(String, String)],
max_depth: u32,
) -> Vec<(String, String)> {
// Implement BFS traversal for transitive dependencies
// Follow the pattern used in other language modules
}
/// Fetch license information for a specific dependency
fn fetch_license_for_dependency(name: &str, version: &str) -> Option<String> {
// Query package registries/APIs for license information
}
Implementation Guidelines¶
Follow Existing Patterns: Study
src/languages/rust.rsorsrc/languages/python.rsfor reference implementation patterns.Transitive Dependency Resolution: Implement BFS (Breadth-First Search) traversal with these features:
Cycle detection using
HashSet<String>to track visited packagesDepth tracking with
max_depthparameter from configProgress tracking for large dependency trees
Error Handling: Use the debug logging system consistently:
use crate::debug::{log, LogLevel}; if let Err(err) = some_operation() { log(LogLevel::Warn, &format!("Failed to fetch {}: {}", package_name, err)); }
Configuration Support: Respect the
max_depthconfiguration:let max_depth = config.max_depth.unwrap_or(3);Package Manager Integration: Connect to official package registries when possible:
Query official APIs for license information
Handle API rate limits and failures gracefully
Cache results when appropriate
Language Implementation Examples¶
Different language ecosystems require different approaches. Here are some examples:
C Module Features (src/languages/c.rs):
Autotools support (
configure.ac,configure.in)Makefile parsing
pkg-config integration
System package resolution
C++ Module Features (src/languages/cpp.rs):
Modern package managers (vcpkg, Conan)
Build system integration (CMake, Bazel)
Package manager API queries
Transitive dependency resolution
R Module Features (src/languages/r.rs):
DESCRIPTION file parsing (DCF format)
renv.lock support (JSON format)
R-universe API integration for license fetching
Handles Imports, Depends, Suggests, and LinkingTo fields
Java Module Features (src/languages/java.rs):
Maven
pom.xmlparsing viaquick-xmlwith full<dependencyManagement>and${property}resolutionGradle
build.gradle/build.gradle.ktsparsing (Groovy and Kotlin DSL) via regexgradle.propertiesvariable resolutionTest-scoped dependency exclusion (
scope=test,testImplementation)License fetching from Maven Central POM files and search API as fallback
Updating Language Detection¶
After creating your language module, update src/languages/mod.rs:
Add the module:
pub mod your_language;Add to exports:
pub use your_language::analyze_your_language_licenses;Update Language enum:
pub enum Language { YourLanguage(&'static str), // ... existing variants }
Add file detection:
impl Language { pub fn from_file_name(file_name: &str) -> Option<Self> { match file_name { "your-project-file.ext" => Some(Language::YourLanguage("your-project-file.ext")), // ... existing patterns } } }
Update parser.rs: Add parsing logic in
src/parser.rs:match language { Language::YourLanguage(file_name) => { languages::analyze_your_language_licenses(project_path, config) } // ... existing cases }
Testing New Language Support¶
Create test projects in various scenarios
Test transitive dependency resolution with different depth configurations
Validate license detection accuracy
Test error handling for invalid/missing project files
Documentation Updates¶
After implementing language support:
Update README.md with language badge and supported file types
Add usage examples specific to your language
Document supported package managers and build systems
Update CLI help text to include the new language filter