Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved defs plugins files to be based on external files. #6225

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 7 additions & 3 deletions crates/cairo-lang-compiler/src/db.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::Arc;

use anyhow::{anyhow, bail, Result};
use cairo_lang_defs::db::{DefsDatabase, DefsGroup};
use cairo_lang_defs::db::{ext_as_virtual_impl, DefsDatabase, DefsGroup};
use cairo_lang_defs::plugin::{InlineMacroExprPlugin, MacroPlugin};
use cairo_lang_filesystem::cfg::CfgSet;
use cairo_lang_filesystem::db::{
Expand All @@ -10,7 +10,7 @@ use cairo_lang_filesystem::db::{
};
use cairo_lang_filesystem::detect::detect_corelib;
use cairo_lang_filesystem::flag::Flag;
use cairo_lang_filesystem::ids::{CrateLongId, FlagId};
use cairo_lang_filesystem::ids::{CrateLongId, FlagId, VirtualFile};
use cairo_lang_lowering::db::{init_lowering_group, LoweringDatabase, LoweringGroup};
use cairo_lang_parser::db::{ParserDatabase, ParserGroup};
use cairo_lang_project::ProjectConfig;
Expand Down Expand Up @@ -38,7 +38,11 @@ pub struct RootDatabase {
storage: salsa::Storage<RootDatabase>,
}
impl salsa::Database for RootDatabase {}
impl ExternalFiles for RootDatabase {}
impl ExternalFiles for RootDatabase {
fn ext_as_virtual(&self, external_id: salsa::InternId) -> VirtualFile {
ext_as_virtual_impl(self.upcast(), external_id)
}
}
impl salsa::ParallelDatabase for RootDatabase {
fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
salsa::Snapshot::new(RootDatabase { storage: self.storage.snapshot() })
Expand Down
45 changes: 34 additions & 11 deletions crates/cairo-lang-defs/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
use cairo_lang_syntax::node::{ast, Terminal, TypedStablePtr, TypedSyntaxNode};
use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use cairo_lang_utils::ordered_hash_set::OrderedHashSet;
use cairo_lang_utils::{Intern, Upcast};
use cairo_lang_utils::{Intern, LookupIntern, Upcast};
use itertools::{chain, Itertools};
use salsa::InternKey;

use crate::ids::*;
use crate::plugin::{
Expand Down Expand Up @@ -83,6 +84,8 @@ pub trait DefsGroup:
fn intern_generic_param(&self, id: GenericParamLongId) -> GenericParamId;
#[salsa::interned]
fn intern_local_var(&self, id: LocalVarLongId) -> LocalVarId;
#[salsa::interned]
fn intern_plugin_generated_file(&self, id: PluginGeneratedFileLongId) -> PluginGeneratedFileId;

// Plugins.
// ========
Expand Down Expand Up @@ -390,13 +393,13 @@ pub struct ModuleData {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PrivModuleSubFiles {
/// The files generated by plugins running on items.
pub files: Vec<FileId>,
files: OrderedHashMap<FileId, VirtualFile>,
/// The aux data per such file.
pub aux_data: Vec<Option<DynGeneratedFileAuxData>>,
aux_data: Vec<Option<DynGeneratedFileAuxData>>,
/// The items not filtered out by plugins.
pub items: Vec<ast::ModuleItem>,
items: Vec<ast::ModuleItem>,
/// The diagnostics generated by the plugins.
pub plugin_diagnostics: Vec<PluginDiagnostic>,
plugin_diagnostics: Vec<PluginDiagnostic>,
}

fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData> {
Expand Down Expand Up @@ -449,7 +452,7 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
files.push(file_id);

let priv_module_data = db.priv_module_sub_files(module_id, file_id)?;
file_queue.extend(priv_module_data.files.iter().copied());
file_queue.extend(priv_module_data.files.keys().copied());
for diag in &priv_module_data.plugin_diagnostics {
plugin_diagnostics.push((module_file_id, diag.clone()));
}
Expand Down Expand Up @@ -561,6 +564,16 @@ fn priv_module_data(db: &dyn DefsGroup, module_id: ModuleId) -> Maybe<ModuleData
Ok(res)
}

/// Returns the `VirtualFile` matching the given external id.
pub fn ext_as_virtual_impl(db: &dyn DefsGroup, external_id: salsa::InternId) -> VirtualFile {
let long_id = PluginGeneratedFileId::from_intern_id(external_id).lookup_intern(db);
let file_id = FileLongId::External(external_id).intern(db);
let data = db
.priv_module_sub_files(long_id.module_id, long_id.stable_ptr.file_id(db.upcast()))
.unwrap();
data.files[&file_id].clone()
}

fn priv_module_sub_files(
db: &dyn DefsGroup,
module_id: ModuleId,
Expand Down Expand Up @@ -605,7 +618,7 @@ fn priv_module_sub_files(
edition,
};

let mut files = Vec::new();
let mut files = OrderedHashMap::<_, _>::default();
let mut aux_data = Vec::new();
let mut items = Vec::new();
let mut plugin_diagnostics = Vec::new();
Expand All @@ -622,15 +635,25 @@ fn priv_module_sub_files(
}

if let Some(generated) = result.code {
files.push(
FileLongId::Virtual(VirtualFile {
let generated_file_id = FileLongId::External(
PluginGeneratedFileLongId {
module_id,
stable_ptr: item_ast.stable_ptr().untyped(),
name: generated.name.clone(),
}
.intern(db)
.as_intern_id(),
)
.intern(db);
files.insert(
generated_file_id,
VirtualFile {
parent: Some(file_id),
name: generated.name,
content: generated.content.into(),
code_mappings: generated.code_mappings.into(),
kind: FileKind::Module,
})
.intern(db),
},
);
aux_data.push(generated.aux_data);
}
Expand Down
18 changes: 18 additions & 0 deletions crates/cairo-lang-defs/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,24 @@ impl ModuleFileId {
}
}

/// An id for a file defined out of the filesystem crate, for files generated by plugins.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct PluginGeneratedFileLongId {
/// The module that the file was generated from.
pub module_id: ModuleId,
/// The stable pointer the file was generated from being ran on.
pub stable_ptr: SyntaxStablePtrId,
/// The name of the generated file to differentiate between different generated files.
pub name: SmolStr,
}
define_short_id!(
PluginGeneratedFileId,
PluginGeneratedFileLongId,
DefsGroup,
lookup_intern_plugin_generated_file,
intern_plugin_generated_file
);

define_language_element_id_as_enum! {
#[toplevel]
/// Id for direct children of a module.
Expand Down
10 changes: 7 additions & 3 deletions crates/cairo-lang-defs/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use cairo_lang_filesystem::db::{
init_files_group, AsFilesGroupMut, CrateConfiguration, ExternalFiles, FilesDatabase,
FilesGroup, FilesGroupEx,
};
use cairo_lang_filesystem::ids::{CrateLongId, Directory, FileLongId};
use cairo_lang_filesystem::ids::{CrateLongId, Directory, FileLongId, VirtualFile};
use cairo_lang_parser::db::{ParserDatabase, ParserGroup};
use cairo_lang_syntax::node::db::{SyntaxDatabase, SyntaxGroup};
use cairo_lang_syntax::node::helpers::QueryAttrs;
Expand All @@ -17,7 +17,7 @@ use cairo_lang_utils::ordered_hash_map::OrderedHashMap;
use cairo_lang_utils::{extract_matches, try_extract_matches, Intern, LookupIntern, Upcast};
use indoc::indoc;

use crate::db::{DefsDatabase, DefsGroup};
use crate::db::{ext_as_virtual_impl, DefsDatabase, DefsGroup};
use crate::ids::{
FileIndex, GenericParamLongId, ModuleFileId, ModuleId, ModuleItemId, NamedLanguageElementId,
SubmoduleLongId,
Expand All @@ -31,7 +31,11 @@ pub struct DatabaseForTesting {
storage: salsa::Storage<DatabaseForTesting>,
}
impl salsa::Database for DatabaseForTesting {}
impl ExternalFiles for DatabaseForTesting {}
impl ExternalFiles for DatabaseForTesting {
fn ext_as_virtual(&self, external_id: salsa::InternId) -> VirtualFile {
ext_as_virtual_impl(self.upcast(), external_id)
}
}
impl Default for DatabaseForTesting {
fn default() -> Self {
let mut res = Self { storage: Default::default() };
Expand Down
38 changes: 20 additions & 18 deletions crates/cairo-lang-filesystem/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ use serde::{Deserialize, Serialize};
use crate::cfg::CfgSet;
use crate::flag::Flag;
use crate::ids::{
CrateId, CrateLongId, Directory, FileId, FileLongId, FlagId, FlagLongId, VirtualFile,
CodeMapping, CrateId, CrateLongId, Directory, FileId, FileLongId, FlagId, FlagLongId,
VirtualFile,
};
use crate::span::{FileSummary, TextOffset, TextSpan, TextWidth};

Expand Down Expand Up @@ -109,19 +110,9 @@ pub struct ExperimentalFeaturesConfig {

/// A trait for defining files external to the `filesystem` crate.
pub trait ExternalFiles {
/// Returns the content of an external file.
fn ext_file_content(&self, _external_id: u32) -> Option<Arc<str>> {
None
}

/// Returns the name of an external file.
fn ext_file_name(&self, _external_id: u32) -> String {
"<external>".to_string()
}

/// Returns the full path of an external file.
fn ext_file_full_path(&self, _external_id: u32) -> String {
"<external>".to_string()
/// Returns the virtual file matching the external id.
fn ext_as_virtual(&self, _external_id: salsa::InternId) -> VirtualFile {
panic!("Should not be called, unless specifically implemented!");
}
}

Expand Down Expand Up @@ -262,7 +253,7 @@ fn priv_raw_file_content(db: &dyn FilesGroup, file: FileId) -> Option<Arc<str>>
Err(_) => None,
},
FileLongId::Virtual(virt) => Some(virt.content),
FileLongId::External(external_id) => db.ext_file_content(external_id),
FileLongId::External(external_id) => Some(db.ext_as_virtual(external_id).content),
}
}
fn file_content(db: &dyn FilesGroup, file: FileId) -> Option<Arc<str>> {
Expand Down Expand Up @@ -291,9 +282,7 @@ pub fn get_originating_location(
mut file_id: FileId,
mut span: TextSpan,
) -> (FileId, TextSpan) {
while let FileLongId::Virtual(VirtualFile { parent: Some(parent), code_mappings, .. }) =
file_id.lookup_intern(db)
{
while let Some((parent, code_mappings)) = get_parent_and_mapping(db, file_id) {
if let Some(origin) = code_mappings.iter().find_map(|mapping| mapping.translate(span)) {
span = origin;
file_id = parent;
Expand All @@ -303,3 +292,16 @@ pub fn get_originating_location(
}
(file_id, span)
}

/// Returns the parent file and the code mappings of the file.
fn get_parent_and_mapping(
db: &dyn FilesGroup,
file_id: FileId,
) -> Option<(FileId, Arc<[CodeMapping]>)> {
let vf = match file_id.lookup_intern(db) {
FileLongId::OnDisk(_) => return None,
FileLongId::Virtual(vf) => vf,
FileLongId::External(id) => db.ext_as_virtual(id),
};
Some((vf.parent?, vf.code_mappings))
}
6 changes: 3 additions & 3 deletions crates/cairo-lang-filesystem/src/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl FlagId {
pub enum FileLongId {
OnDisk(PathBuf),
Virtual(VirtualFile),
External(u32),
External(salsa::InternId),
}
/// Whether the file holds syntax for a module or for an expression.
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -132,14 +132,14 @@ impl<'b> FileId {
path.file_name().and_then(|x| x.to_str()).unwrap_or("<unknown>").to_string()
}
FileLongId::Virtual(vf) => vf.name.to_string(),
FileLongId::External(external_id) => db.ext_file_name(external_id),
FileLongId::External(external_id) => db.ext_as_virtual(external_id).name.to_string(),
}
}
pub fn full_path(self, db: &dyn FilesGroup) -> String {
match self.lookup_intern(db) {
FileLongId::OnDisk(path) => path.to_str().unwrap_or("<unknown>").to_string(),
FileLongId::Virtual(vf) => vf.full_path(db),
FileLongId::External(external_id) => db.ext_file_full_path(external_id),
FileLongId::External(external_id) => db.ext_as_virtual(external_id).full_path(db),
}
}
pub fn kind(self, db: &dyn FilesGroup) -> FileKind {
Expand Down
9 changes: 7 additions & 2 deletions crates/cairo-lang-language-server/src/lang/db/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use cairo_lang_defs::db::{DefsDatabase, DefsGroup};
use cairo_lang_defs::db::{ext_as_virtual_impl, DefsDatabase, DefsGroup};
use cairo_lang_doc::db::DocDatabase;
use cairo_lang_filesystem::cfg::{Cfg, CfgSet};
use cairo_lang_filesystem::db::{
init_files_group, AsFilesGroupMut, ExternalFiles, FilesDatabase, FilesGroup,
};
use cairo_lang_filesystem::ids::VirtualFile;
use cairo_lang_lowering::db::{init_lowering_group, LoweringDatabase, LoweringGroup};
use cairo_lang_lowering::utils::InliningStrategy;
use cairo_lang_parser::db::{ParserDatabase, ParserGroup};
Expand Down Expand Up @@ -73,7 +74,11 @@ impl AnalysisDatabase {
}

impl salsa::Database for AnalysisDatabase {}
impl ExternalFiles for AnalysisDatabase {}
impl ExternalFiles for AnalysisDatabase {
fn ext_as_virtual(&self, external_id: salsa::InternId) -> VirtualFile {
ext_as_virtual_impl(self.upcast(), external_id)
}
}

impl salsa::ParallelDatabase for AnalysisDatabase {
fn snapshot(&self) -> salsa::Snapshot<Self> {
Expand Down
25 changes: 11 additions & 14 deletions crates/cairo-lang-language-server/src/lang/lsp/ls_proto_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,17 @@ pub trait LsProtoGroup: Upcast<dyn FilesGroup> {

/// Get the canonical [`Url`] for a [`FileId`].
fn url_for_file(&self, file_id: FileId) -> Url {
match self.upcast().lookup_intern_file(file_id) {
FileLongId::OnDisk(path) => Url::from_file_path(path).unwrap(),
FileLongId::Virtual(virtual_file) => {
// NOTE: The URL is constructed using setters and path segments in order to
// url-encode any funky characters in parts that LS is not controlling.
let mut url = Url::parse("vfs://").unwrap();
url.set_host(Some(&file_id.as_intern_id().to_string())).unwrap();
url.path_segments_mut().unwrap().push(&format!("{}.cairo", virtual_file.name));
url
}
FileLongId::External(id) => {
unimplemented!("External files are not supported yet: {id}")
}
}
let vf = match self.upcast().lookup_intern_file(file_id) {
FileLongId::OnDisk(path) => return Url::from_file_path(path).unwrap(),
FileLongId::Virtual(vf) => vf,
FileLongId::External(id) => self.upcast().ext_as_virtual(id),
};
// NOTE: The URL is constructed using setters and path segments in order to
// url-encode any funky characters in parts that LS is not controlling.
let mut url = Url::parse("vfs://").unwrap();
url.set_host(Some(&file_id.as_intern_id().to_string())).unwrap();
url.path_segments_mut().unwrap().push(&format!("{}.cairo", vf.name));
url
}
}

Expand Down
9 changes: 7 additions & 2 deletions crates/cairo-lang-lowering/src/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use std::sync::{LazyLock, Mutex};

use cairo_lang_defs::db::{DefsDatabase, DefsGroup};
use cairo_lang_defs::db::{ext_as_virtual_impl, DefsDatabase, DefsGroup};
use cairo_lang_filesystem::db::{
init_dev_corelib, init_files_group, AsFilesGroupMut, ExternalFiles, FilesDatabase, FilesGroup,
};
use cairo_lang_filesystem::detect::detect_corelib;
use cairo_lang_filesystem::ids::VirtualFile;
use cairo_lang_parser::db::{ParserDatabase, ParserGroup};
use cairo_lang_semantic::db::{SemanticDatabase, SemanticGroup};
use cairo_lang_semantic::inline_macros::get_default_plugin_suite;
Expand All @@ -26,7 +27,11 @@ pub struct LoweringDatabaseForTesting {
storage: salsa::Storage<LoweringDatabaseForTesting>,
}
impl salsa::Database for LoweringDatabaseForTesting {}
impl ExternalFiles for LoweringDatabaseForTesting {}
impl ExternalFiles for LoweringDatabaseForTesting {
fn ext_as_virtual(&self, external_id: salsa::InternId) -> VirtualFile {
ext_as_virtual_impl(self.upcast(), external_id)
}
}
impl salsa::ParallelDatabase for LoweringDatabaseForTesting {
fn snapshot(&self) -> salsa::Snapshot<LoweringDatabaseForTesting> {
salsa::Snapshot::new(LoweringDatabaseForTesting { storage: self.storage.snapshot() })
Expand Down
10 changes: 7 additions & 3 deletions crates/cairo-lang-plugins/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::Arc;

use cairo_lang_defs::db::{DefsDatabase, DefsGroup};
use cairo_lang_defs::db::{ext_as_virtual_impl, DefsDatabase, DefsGroup};
use cairo_lang_defs::ids::ModuleId;
use cairo_lang_defs::plugin::{
MacroPlugin, MacroPluginMetadata, PluginDiagnostic, PluginGeneratedFile, PluginResult,
Expand All @@ -10,7 +10,7 @@ use cairo_lang_filesystem::db::{
init_files_group, AsFilesGroupMut, CrateConfiguration, ExternalFiles, FilesDatabase,
FilesGroup, FilesGroupEx,
};
use cairo_lang_filesystem::ids::{CrateLongId, Directory, FileLongId};
use cairo_lang_filesystem::ids::{CrateLongId, Directory, FileLongId, VirtualFile};
use cairo_lang_parser::db::ParserDatabase;
use cairo_lang_syntax::node::ast;
use cairo_lang_syntax::node::db::{SyntaxDatabase, SyntaxGroup};
Expand Down Expand Up @@ -50,7 +50,11 @@ pub struct DatabaseForTesting {
storage: salsa::Storage<DatabaseForTesting>,
}
impl salsa::Database for DatabaseForTesting {}
impl ExternalFiles for DatabaseForTesting {}
impl ExternalFiles for DatabaseForTesting {
fn ext_as_virtual(&self, external_id: salsa::InternId) -> VirtualFile {
ext_as_virtual_impl(self.upcast(), external_id)
}
}
impl Default for DatabaseForTesting {
fn default() -> Self {
let mut res = Self { storage: Default::default() };
Expand Down
Loading
Loading