mod effective_languages;
pub mod ffi;
pub mod fields;
pub mod identifiers;
pub mod imports;
pub mod lookups;
pub mod naming;
#[cfg(test)]
mod package_dir_trailing_slash_tests;
#[cfg(test)]
mod removed_command_config_tests;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use std::path::PathBuf;
use std::sync::OnceLock;
use crate::core::config::GenerateConfig;
use crate::core::config::SourceCrate;
use crate::core::config::cargo_lints::CargoLintsConfig;
use crate::core::config::component::{ComponentConfig, ComponentContractConfig, ComponentDistributionConfig};
use crate::core::config::dto::DtoConfig;
use crate::core::config::e2e::E2eConfig;
use crate::core::config::extras::{AdapterConfig, Language};
use crate::core::config::languages::{
CSharpConfig, CustomModulesConfig, CustomRegistrationsConfig, DartConfig, ElixirConfig, FfiConfig, GleamConfig,
GoConfig, JavaConfig, JniConfig, KotlinAndroidConfig, KotlinConfig, NodeConfig, PhpConfig, PythonConfig, RConfig,
RubyConfig, SwiftConfig, WasmConfig, ZigConfig,
};
#[cfg(test)]
use crate::core::config::output::BuildCommandConfig;
use crate::core::config::output::{
CitationConfig, DocsConfig, ExcludeConfig, IncludeConfig, OutputConfig, ReadmeConfig, ScaffoldConfig, SyncConfig,
TestConfig,
};
use crate::core::config::package_metadata::PackageMetadataConfig;
use crate::core::config::poly::PolyConfig;
use crate::core::config::publish::PublishConfig;
use crate::core::config::service::{HandlerContractConfig, ServiceConfig};
use crate::core::config::tools::ToolsConfig;
use crate::core::config::trait_bridge::TraitBridgeConfig;
use crate::core::config::verify::VerifyConfig;
use crate::core::config::workspace::ClientConstructorConfig;
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ResolvedCrateConfig {
pub name: String,
pub sources: Vec<PathBuf>,
pub source_crates: Vec<SourceCrate>,
#[serde(skip)]
pub resolved_source_crates: OnceLock<Vec<SourceCrate>>,
pub version_from: String,
pub core_import: Option<String>,
pub workspace_root: Option<PathBuf>,
pub skip_core_import: bool,
pub error_type: Option<String>,
pub error_constructor: Option<String>,
pub features: Vec<String>,
pub wrapper_default_features: Vec<String>,
pub component_contracts: Vec<ComponentContractConfig>,
pub components: Vec<ComponentConfig>,
pub component_distribution: Option<ComponentDistributionConfig>,
pub path_mappings: HashMap<String, String>,
pub extra_dependencies: HashMap<String, toml::Value>,
pub auto_path_mappings: bool,
pub languages: Vec<Language>,
pub targets: std::collections::BTreeMap<String, bool>,
pub python: Option<PythonConfig>,
pub node: Option<NodeConfig>,
pub ruby: Option<RubyConfig>,
pub php: Option<PhpConfig>,
pub elixir: Option<ElixirConfig>,
pub wasm: Option<WasmConfig>,
pub ffi: Option<FfiConfig>,
pub go: Option<GoConfig>,
pub java: Option<JavaConfig>,
pub dart: Option<DartConfig>,
pub kotlin: Option<KotlinConfig>,
pub kotlin_android: Option<KotlinAndroidConfig>,
pub jni: Option<JniConfig>,
pub swift: Option<SwiftConfig>,
pub gleam: Option<GleamConfig>,
pub csharp: Option<CSharpConfig>,
pub r: Option<RConfig>,
pub zig: Option<ZigConfig>,
pub exclude: ExcludeConfig,
pub include: IncludeConfig,
pub output_paths: HashMap<String, PathBuf>,
pub explicit_output: OutputConfig,
pub test: HashMap<String, TestConfig>,
#[cfg(test)]
#[serde(skip)]
pub build_commands: HashMap<String, BuildCommandConfig>,
pub generate: GenerateConfig,
pub generate_overrides: HashMap<String, GenerateConfig>,
pub dto: DtoConfig,
pub tools: ToolsConfig,
pub opaque_types: BTreeMap<String, String>,
pub client_constructors: HashMap<String, ClientConstructorConfig>,
pub sync: Option<SyncConfig>,
pub citation: Option<CitationConfig>,
pub publish: Option<PublishConfig>,
pub e2e: Option<E2eConfig>,
pub adapters: Vec<AdapterConfig>,
pub trait_bridges: Vec<TraitBridgeConfig>,
pub services: Vec<ServiceConfig>,
pub handler_contracts: Vec<HandlerContractConfig>,
pub scaffold: Option<ScaffoldConfig>,
pub package_metadata: Option<PackageMetadataConfig>,
pub readme: Option<ReadmeConfig>,
pub docs: Option<DocsConfig>,
pub custom_files: HashMap<String, Vec<PathBuf>>,
pub custom_modules: CustomModulesConfig,
pub custom_registrations: CustomRegistrationsConfig,
pub suppress_validation_codes: Vec<String>,
pub untagged_union_text_types: Vec<String>,
pub poly: PolyConfig,
pub extra_clippy_allows: Vec<String>,
pub crate_attributes: Vec<String>,
pub cargo_lints: CargoLintsConfig,
pub verify: VerifyConfig,
}
impl ResolvedCrateConfig {
pub(in crate::core::config) fn all_trait_bridges(&self) -> &[TraitBridgeConfig] {
&self.trait_bridges
}
pub fn trait_bridges_for(&self, language: Language) -> impl Iterator<Item = &TraitBridgeConfig> {
self.all_trait_bridges().iter().filter(move |bridge| {
crate::codegen::generators::trait_bridge::bridge_targets_language(bridge, language.bridge_spellings())
})
}
pub fn trait_bridges_for_vec(&self, language: Language) -> Vec<TraitBridgeConfig> {
self.trait_bridges_for(language).cloned().collect()
}
pub fn trait_bridge_manages_function(&self, name: &str) -> bool {
crate::codegen::generators::trait_bridge::is_trait_bridge_managed_fn(name, self.all_trait_bridges())
}
pub fn trait_bridge_stale_artifact_types(&self) -> impl Iterator<Item = &str> {
self.all_trait_bridges().iter().flat_map(|bridge| {
[bridge.context_type.as_deref(), bridge.result_type.as_deref()]
.into_iter()
.flatten()
})
}
pub fn configured_trait_bridge_names(&self) -> impl Iterator<Item = &str> {
self.all_trait_bridges().iter().map(|bridge| bridge.trait_name.as_str())
}
pub fn trait_bridge_carrier_diagnostics(
&self,
api: &crate::core::ir::ApiSurface,
) -> Vec<crate::core::validation::ValidationDiagnostic> {
crate::core::validation::trait_bridge_carrier_diagnostics(api, self.all_trait_bridges())
}
pub fn trait_bridge_language_surface(
&self,
api: &crate::core::ir::ApiSurface,
language: Language,
) -> Option<crate::core::ir::ApiSurface> {
crate::codegen::generators::trait_bridge::language_surface(api, self.all_trait_bridges(), language)
}
pub fn replace_trait_bridges(&mut self, bridges: Vec<TraitBridgeConfig>) {
self.trait_bridges = bridges;
}
pub fn push_trait_bridge(&mut self, bridge: TraitBridgeConfig) {
let mut bridges = self.all_trait_bridges().to_vec();
bridges.push(bridge);
self.replace_trait_bridges(bridges);
}
pub fn update_trait_bridge(&mut self, index: usize, update: impl FnOnce(&mut TraitBridgeConfig)) {
let mut bridges = self.all_trait_bridges().to_vec();
update(&mut bridges[index]);
self.replace_trait_bridges(bridges);
}
pub fn resolved_source_crates(&self) -> Result<&[SourceCrate], crate::core::config::ResolveError> {
if let Some(resolved) = self.resolved_source_crates.get() {
return Ok(resolved);
}
let resolved = crate::core::config::new_config::resolve_source_crates(
&self.source_crates,
self.workspace_root.as_deref(),
)?;
let _ = self.resolved_source_crates.set(resolved);
Ok(self
.resolved_source_crates
.get()
.expect("just set or set by a racing caller"))
}
pub fn source_hash_paths(&self) -> Result<Vec<PathBuf>, crate::core::config::ResolveError> {
let mut sources = self.sources.clone();
for source_crate in self.resolved_source_crates()? {
sources.extend(source_crate.sources.iter().cloned());
}
sources.sort();
sources.dedup();
Ok(sources)
}
pub fn output_for(&self, lang: &str) -> Option<&std::path::Path> {
self.output_paths.get(lang).map(|p| p.as_path())
}
pub fn targets(&self, lang: Language) -> bool {
self.languages.contains(&lang)
}
#[must_use]
pub fn target_enabled(&self, triple: &str) -> bool {
crate::publish::platform::target_triple_enabled(&self.targets, triple)
}
}
#[cfg(test)]
mod trait_bridge_applicability_tests {
use super::*;
fn bridge(name: &str, excluded: &[&str]) -> TraitBridgeConfig {
TraitBridgeConfig {
trait_name: name.to_owned(),
exclude_languages: excluded.iter().map(|value| (*value).to_owned()).collect(),
..Default::default()
}
}
#[test]
fn trait_bridges_for_filters_language_and_backend_spellings() {
let config = ResolvedCrateConfig {
trait_bridges: vec![
bridge("Active", &[]),
bridge("ByLanguage", &["python"]),
bridge("ByBackend", &["pyo3"]),
bridge("OtherTarget", &["go"]),
],
..Default::default()
};
let names: Vec<_> = config
.trait_bridges_for(Language::Python)
.map(|bridge| bridge.trait_name.as_str())
.collect();
assert_eq!(names, ["Active", "OtherTarget"]);
}
}