Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
928bf92
chore(deps): bump solar, compilers
DaniPopes Aug 20, 2025
bcbab2e
chore: pin to git
DaniPopes Aug 20, 2025
24506e1
sort
DaniPopes Aug 20, 2025
5b2eb75
chore: bump
DaniPopes Aug 20, 2025
86242f9
bump
DaniPopes Aug 20, 2025
0ae4801
chore: slightly clean up solar utils
DaniPopes Aug 20, 2025
99d2f1d
chore: clippy
DaniPopes Aug 20, 2025
58c5561
chore: don't Graph in configure_pcx
DaniPopes Aug 20, 2025
b1d66b3
docs
DaniPopes Aug 20, 2025
202ab25
fix: source map
DaniPopes Aug 20, 2025
84c5258
docs: Linter docs
DaniPopes Aug 20, 2025
9d49d8d
doc
DaniPopes Aug 21, 2025
92dbc1b
update
DaniPopes Aug 21, 2025
596fe52
Merge branch 'master' into dani/bump-compilers222
DaniPopes Aug 21, 2025
97c50a3
fix
DaniPopes Aug 21, 2025
18947ee
fix: revert graph removal
DaniPopes Aug 22, 2025
3a1cfe7
update
DaniPopes Aug 22, 2025
0181e25
chore: remove visit workaround
DaniPopes Aug 24, 2025
ae3112e
bump
DaniPopes Aug 24, 2025
d299b69
perf: load files in parallel
DaniPopes Aug 24, 2025
1a64c07
Merge remote-tracking branch 'origin/master' into dani/bump-compilers222
DaniPopes Aug 24, 2025
118ca60
bump
DaniPopes Aug 24, 2025
3891be7
fuck you windows-sys
DaniPopes Aug 25, 2025
128fd2e
bump
DaniPopes Aug 25, 2025
18c7a6c
nff
DaniPopes Aug 25, 2025
01e3978
tmp: revert resolve imports
DaniPopes Aug 25, 2025
70eaac4
revert
DaniPopes Aug 25, 2025
23c0251
fix: use foundry_compilers parser
DaniPopes Aug 25, 2025
e9283ef
feat: demo using output.compiler
DaniPopes Aug 25, 2025
514750a
Merge branch 'master' into dani/bump-compilers222
DaniPopes Aug 25, 2025
9825b6f
chore: mega bump, use solar meta crate
DaniPopes Aug 25, 2025
8955eb7
fmt
DaniPopes Aug 25, 2025
2c3a4cc
Merge branch 'master' into dani/bump-compilers222
DaniPopes Aug 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 48 additions & 81 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -407,12 +407,12 @@ idna_adapter = "=1.1.0"

## foundry
# foundry-block-explorers = { git = "https://github.com/foundry-rs/block-explorers.git", rev = "e09cb89" }
# foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", rev = "e4a9b04" }
foundry-compilers = { git = "https://github.com/foundry-rs/compilers.git", branch = "dani/parsed-sources" }
# foundry-fork-db = { git = "https://github.com/foundry-rs/foundry-fork-db", rev = "50683eb" }

## solar
# solar-ast = { git = "https://github.com/paradigmxyz/solar.git", branch = "main" }
# solar-parse = { git = "https://github.com/paradigmxyz/solar.git", branch = "main" }
# solar-interface = { git = "https://github.com/paradigmxyz/solar.git", branch = "main" }
# solar-sema = { git = "https://github.com/paradigmxyz/solar.git", branch = "main" }
# solar-data-structures = { git = "https://github.com/paradigmxyz/solar.git", branch = "main" }
solar-ast = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/compiler-interface" }
solar-data-structures = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/compiler-interface" }
solar-interface = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/compiler-interface" }
solar-parse = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/compiler-interface" }
solar-sema = { git = "https://github.com/paradigmxyz/solar.git", branch = "dani/compiler-interface" }
2 changes: 1 addition & 1 deletion crates/chisel/src/solidity_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl SolidityHelper {

/// Enters the session.
fn enter(&self, f: impl FnOnce(&Session)) {
self.sess.enter(|| f(&self.sess));
self.sess.enter_sequential(|| f(&self.sess));
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/cli/src/opts/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ mod paths;
pub use self::paths::ProjectPathOpts;

mod utils;
pub use self::utils::{solar_pcx_from_build_opts, solar_pcx_from_solc_project};
pub use self::utils::{configure_pcx, configure_pcx_from_solc};

// A set of solc compiler settings that can be set via command line arguments, which are intended
// to be merged into an existing `foundry_config::Config`.
Expand Down
100 changes: 42 additions & 58 deletions crates/cli/src/opts/build/utils.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
use crate::{opts::BuildOpts, utils::LoadConfig};

use eyre::Result;
use foundry_compilers::{
CompilerInput, Graph, Project,
CompilerInput, Project,
artifacts::{Source, Sources},
multi::{MultiCompilerLanguage, MultiCompilerParsedSource},
solc::{SolcLanguage, SolcVersionedInput},
};
use solar_sema::{ParsingContext, interface::Session};
use foundry_config::Config;
use solar_sema::ParsingContext;
use std::path::PathBuf;

/// Builds a Solar [`solar_sema::ParsingContext`] from [`BuildOpts`].
/// Configures a [`ParsingContext`] from [`Config`].
///
/// * Configures include paths, remappings and registers all in-memory sources so that solar can
/// operate without touching disk.
/// * If no `project` is provided, it will spin up a new ephemeral project.
/// * If no `target_paths` are provided, all project files are processed.
/// * Only processes the subset of sources with the most up-to-date Solitidy version.
pub fn solar_pcx_from_build_opts<'sess>(
sess: &'sess Session,
build: &BuildOpts,
/// - Configures include paths, remappings
/// - Source files are added if `add_source_file` is set
/// - If no `project` is provided, it will spin up a new ephemeral project.
/// - If no `target_paths` are provided, all project files are processed.
/// - Only processes the subset of sources with the most up-to-date Solidity version.
pub fn configure_pcx(
pcx: &mut ParsingContext<'_>,
config: &Config,
project: Option<&Project>,
target_paths: Option<&[PathBuf]>,
) -> Result<ParsingContext<'sess>> {
) -> Result<()> {
// Process build options
let config = build.load_config()?;
let project = match project {
Some(project) => project,
None => &config.ephemeral_project()?,
Expand All @@ -45,66 +42,53 @@ pub fn solar_pcx_from_build_opts<'sess>(
None => project.paths.read_input_files()?,
};

// Only process sources with latest Solidity version to avoid conflicts.
let graph = Graph::<MultiCompilerParsedSource>::resolve_sources(&project.paths, sources)?;
let (version, sources, _) = graph
// resolve graph into mapping language -> version -> sources
.into_sources_by_version(project)?
.sources
.into_iter()
// only interested in Solidity sources
.find(|(lang, _)| *lang == MultiCompilerLanguage::Solc(SolcLanguage::Solidity))
.ok_or_else(|| eyre::eyre!("no Solidity sources"))?
.1
.into_iter()
// always pick the latest version
.max_by(|(v1, _, _), (v2, _, _)| v1.cmp(v2))
.unwrap();

let solc = SolcVersionedInput::build(
sources,
config.solc_settings()?,
SolcLanguage::Solidity,
version,
foundry_config::semver::Version::new(0, 0, 0), // Unused
);

Ok(solar_pcx_from_solc_project(sess, project, &solc, true))
configure_pcx_from_solc(pcx, project, &solc, true);

Ok(())
}

/// Builds a Solar [`solar_sema::ParsingContext`] from a [`foundry_compilers::Project`] and a
/// [`SolcVersionedInput`].
/// Configures a [`ParsingContext`] from a [`Project`] and [`SolcVersionedInput`].
///
/// * Configures include paths, remappings.
/// * Source files can be manually added if the param `add_source_file` is set to `false`.
pub fn solar_pcx_from_solc_project<'sess>(
sess: &'sess Session,
/// - Configures include paths, remappings.
/// - Source files are added if `add_source_file` is set
pub fn configure_pcx_from_solc(
pcx: &mut ParsingContext<'_>,
project: &Project,
solc: &SolcVersionedInput,
vinput: &SolcVersionedInput,
add_source_files: bool,
) -> ParsingContext<'sess> {
// Configure the parsing context with the paths, remappings and sources
let mut pcx = ParsingContext::new(sess);
) {
configure_pcx_from_solc_cli(pcx, project, &vinput.cli_settings);
if add_source_files {
for (path, source) in &vinput.input.sources {
if let Ok(src_file) =
pcx.sess.source_map().new_source_file(path.clone(), source.content.as_str())
{
pcx.add_file(src_file);
}
}
}
}

fn configure_pcx_from_solc_cli(
pcx: &mut ParsingContext<'_>,
project: &Project,
cli_settings: &foundry_compilers::solc::CliSettings,
) {
pcx.file_resolver
.set_current_dir(solc.cli_settings.base_path.as_ref().unwrap_or(&project.paths.root));
.set_current_dir(cli_settings.base_path.as_ref().unwrap_or(&project.paths.root));
for remapping in &project.paths.remappings {
pcx.file_resolver.add_import_remapping(solar_sema::interface::config::ImportRemapping {
context: remapping.context.clone().unwrap_or_default(),
prefix: remapping.name.clone(),
path: remapping.path.clone(),
});
}
pcx.file_resolver.add_include_paths(solc.cli_settings.include_paths.iter().cloned());

if add_source_files {
for (path, source) in &solc.input.sources {
if let Ok(src_file) =
sess.source_map().new_source_file(path.clone(), source.content.as_str())
{
pcx.add_file(src_file);
}
}
}

pcx
pcx.file_resolver.add_include_paths(cli_settings.include_paths.iter().cloned());
}
76 changes: 41 additions & 35 deletions crates/common/src/preprocessor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ use solar_parse::{
ast::Span,
interface::{Session, SourceMap},
};
use solar_sema::{ParsingContext, thread_local::ThreadLocal};
use std::{collections::HashSet, ops::Range, path::PathBuf};
use solar_sema::ParsingContext;
use std::{
collections::HashSet,
ops::{ControlFlow, Range},
path::PathBuf,
};

mod data;
use data::{collect_preprocessor_data, create_deploy_helpers};
Expand Down Expand Up @@ -50,54 +54,58 @@ impl Preprocessor<SolcCompiler> for DynamicTestLinkingPreprocessor {
}

let sess = solar_session_from_solc(input);
let _ = sess.enter_parallel(|| -> solar_parse::interface::Result {
let mut compiler = solar_sema::Compiler::new(sess);
let _ = compiler.enter_mut(|compiler| -> solar_parse::interface::Result {
// Set up the parsing context with the project paths.
let mut parsing_context = solar_pcx_from_solc_no_sources(&sess, input, paths);
let mut pcx = compiler.parse();
solar_pcx_from_solc_no_sources(&mut pcx, input, paths);

// Add the sources into the context.
// Include all sources in the source map so as to not re-load them from disk, but only
// parse and preprocess tests and scripts.
let mut preprocessed_paths = vec![];
let sources = &mut input.input.sources;
for (path, source) in sources.iter() {
if let Ok(src_file) =
sess.source_map().new_source_file(path.clone(), source.content.as_str())
if let Ok(src_file) = compiler
.sess()
.source_map()
.new_source_file(path.clone(), source.content.as_str())
&& paths.is_test_or_script(path)
{
parsing_context.add_file(src_file);
pcx.add_file(src_file);
preprocessed_paths.push(path.clone());
}
}

// Parse and preprocess.
let hir_arena = ThreadLocal::new();
if let Some(gcx) = parsing_context.parse_and_lower(&hir_arena)? {
let hir = &gcx.get().hir;
// Collect tests and scripts dependencies and identify mock contracts.
let deps = PreprocessorDependencies::new(
&sess,
hir,
&preprocessed_paths,
&paths.paths_relative().sources,
&paths.root,
mocks,
);
// Collect data of source contracts referenced in tests and scripts.
let data = collect_preprocessor_data(&sess, hir, &deps.referenced_contracts);

// Extend existing sources with preprocessor deploy helper sources.
sources.extend(create_deploy_helpers(&data));

// Generate and apply preprocessor source updates.
apply_updates(sources, remove_bytecode_dependencies(hir, &deps, &data));
}
pcx.parse();
let ControlFlow::Continue(()) = compiler.lower_asts()? else { return Ok(()) };
let gcx = compiler.gcx();
let hir = &gcx.hir;
// Collect tests and scripts dependencies and identify mock contracts.
let deps = PreprocessorDependencies::new(
gcx.sess,
hir,
&preprocessed_paths,
&paths.paths_relative().sources,
&paths.root,
mocks,
);
// Collect data of source contracts referenced in tests and scripts.
let data = collect_preprocessor_data(gcx.sess, hir, &deps.referenced_contracts);

// Extend existing sources with preprocessor deploy helper sources.
sources.extend(create_deploy_helpers(&data));

// Generate and apply preprocessor source updates.
apply_updates(sources, remove_bytecode_dependencies(hir, &deps, &data));

Ok(())
});

// Warn if any diagnostics emitted during content parsing.
if let Err(err) = sess.emitted_errors().unwrap() {
warn!("failed preprocessing {err}");
if let Err(err) = compiler.sess().emitted_errors().unwrap() {
warn!("failed preprocessing:\n{err}");
}

Ok(())
Expand Down Expand Up @@ -143,12 +151,11 @@ fn solar_session_from_solc(solc: &SolcVersionedInput) -> Session {
.build()
}

fn solar_pcx_from_solc_no_sources<'sess>(
sess: &'sess Session,
fn solar_pcx_from_solc_no_sources(
pcx: &mut ParsingContext<'_>,
solc: &SolcVersionedInput,
paths: &ProjectPathsConfig<impl Language>,
) -> ParsingContext<'sess> {
let mut pcx = ParsingContext::new(sess);
) {
pcx.file_resolver.set_current_dir(solc.cli_settings.base_path.as_ref().unwrap_or(&paths.root));
for remapping in &paths.remappings {
pcx.file_resolver.add_import_remapping(solar_sema::interface::config::ImportRemapping {
Expand All @@ -158,5 +165,4 @@ fn solar_pcx_from_solc_no_sources<'sess>(
});
}
pcx.file_resolver.add_include_paths(solc.cli_settings.include_paths.iter().cloned());
pcx
}
6 changes: 4 additions & 2 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ use foundry_compilers::{
vyper::{Vyper, VyperSettings},
},
error::SolcError,
multi::{MultiCompilerParsedSource, MultiCompilerRestrictions},
multi::{MultiCompilerParser, MultiCompilerRestrictions},
solc::{CliSettings, SolcSettings},
};
use regex::Regex;
Expand Down Expand Up @@ -133,6 +133,8 @@ pub use compilation::{CompilationRestrictions, SettingsOverrides};
pub mod extend;
use extend::Extends;

pub use semver;

/// Foundry configuration
///
/// # Defaults
Expand Down Expand Up @@ -990,7 +992,7 @@ impl Config {
return Ok(BTreeMap::new());
}

let graph = Graph::<MultiCompilerParsedSource>::resolve(paths)?;
let graph = Graph::<MultiCompilerParser>::resolve(paths)?;
let (sources, _) = graph.into_sources();

for res in &self.compilation_restrictions {
Expand Down
Loading
Loading