diff --git a/src/cmd/sources.rs b/src/cmd/sources.rs index b6ab0269..358f3cbd 100644 --- a/src/cmd/sources.rs +++ b/src/cmd/sources.rs @@ -16,6 +16,7 @@ use tokio::runtime::Runtime; use crate::config::{Dependency, Validate, ValidationContext}; use crate::error::*; use crate::sess::{Session, SessionIo}; +use crate::src::FilteredSourceGroup; use crate::target::{TargetSet, TargetSpec}; /// Emit the source file manifest for the package @@ -124,10 +125,14 @@ pub fn run(sess: &Session, args: &SourcesArgs) -> Result<()> { let stdout = std::io::stdout(); let handle = stdout.lock(); if args.flatten { - let srcs = srcs.flatten(); + let srcs = srcs + .flatten() + .into_iter() + .map(FilteredSourceGroup::from) + .collect::>(); serde_json::to_writer_pretty(handle, &srcs) } else { - serde_json::to_writer_pretty(handle, &srcs) + serde_json::to_writer_pretty(handle, &FilteredSourceGroup::from(srcs)) } }; let _ = writeln!(std::io::stdout(),); diff --git a/src/diagnostic.rs b/src/diagnostic.rs index 112cd0a3..dd77a1a7 100644 --- a/src/diagnostic.rs +++ b/src/diagnostic.rs @@ -394,6 +394,10 @@ pub enum Warnings { #[error("Override files in {} does not support additional fields like include_dirs, defines, etc.", fmt_pkg!(.0))] #[diagnostic(code(W33))] OverrideFilesWithExtras(String), + + #[error("Source group in package {} uses `override_files`, which is not supported in the simplified source output and will be ignored.", fmt_pkg!(.0))] + #[diagnostic(code(W34))] + OverrideFilesIgnored(String), } #[cfg(test)] diff --git a/src/src.rs b/src/src.rs index 6cb37feb..3539427f 100644 --- a/src/src.rs +++ b/src/src.rs @@ -381,6 +381,109 @@ impl<'ctx> SourceGroup<'ctx> { } } +/// A source file group. +#[derive(Serialize, Clone, Debug, Default)] +pub struct FilteredSourceGroup<'ctx> { + /// The package which this source group represents. + pub package: Option<&'ctx str>, + /// Whether the source files in this group can be treated in parallel. + pub independent: bool, + /// The directories to search for include files. + pub include_dirs: Vec<&'ctx Path>, + /// The preprocessor definitions. + pub defines: IndexMap>, + /// The files in this group. + pub files: Vec>, + /// Package dependencies of this source group + pub dependencies: IndexSet, + /// Version information of the package + pub version: Option, +} + +impl<'ctx> From> for FilteredSourceGroup<'ctx> { + fn from(group: SourceGroup<'ctx>) -> Self { + if group.override_files { + if let Some(pkg) = group.package { + Warnings::OverrideFilesIgnored(pkg.to_string()).emit(); + } + } + let include_dirs = group + .include_dirs + .into_iter() + .map(|(_, path)| path) + .chain( + group + .export_incdirs + .into_iter() + .flat_map(|(_, dirs)| dirs.into_iter().map(|(_, path)| path)), + ) + .collect(); + FilteredSourceGroup { + package: group.package, + independent: group.independent, + include_dirs, + defines: group.defines, + files: group + .files + .into_iter() + .map(FilteredSourceFile::from) + .collect(), + dependencies: group.dependencies, + version: group.version, + } + } +} + +/// A filtered source file. +/// +/// This can either be an individual file, or a filtered subgroup of files. +#[derive(Clone)] +pub enum FilteredSourceFile<'ctx> { + /// A file. + File(&'ctx Path, &'ctx Option), + /// A group of files. + Group(Box>), +} + +impl<'ctx> From> for FilteredSourceFile<'ctx> { + fn from(file: SourceFile<'ctx>) -> Self { + match file { + SourceFile::File(path, ty) => FilteredSourceFile::File(path, ty), + SourceFile::Group(grp) => { + FilteredSourceFile::Group(Box::new(FilteredSourceGroup::from(*grp))) + } + } + } +} + +impl<'ctx> fmt::Debug for FilteredSourceFile<'ctx> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + FilteredSourceFile::File(path, ty) => { + fmt::Debug::fmt(path, f)?; + if let Some(t) = ty { + write!(f, " as {:?}", t) + } else { + write!(f, " as ") + } + } + FilteredSourceFile::Group(ref srcs) => fmt::Debug::fmt(srcs, f), + } + } +} + +impl<'ctx> Serialize for FilteredSourceFile<'ctx> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match *self { + FilteredSourceFile::File(path, _) => path.serialize(serializer), + FilteredSourceFile::Group(ref group) => group.serialize(serializer), + } + } +} + /// File types for a source file. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum SourceType {