diff --git a/Cargo.lock b/Cargo.lock index 91dec9f3b9..92a729c41c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,11 +74,11 @@ dependencies = [ "profile", "rust-analyzer-salsa", "rustc-hash", + "span", "stdx", "syntax", "test-utils", "triomphe", - "tt", "vfs", ] @@ -516,6 +516,7 @@ dependencies = [ "rustc-dependencies", "rustc-hash", "smallvec", + "span", "stdx", "syntax", "test-utils", @@ -542,6 +543,7 @@ dependencies = [ "profile", "rustc-hash", "smallvec", + "span", "stdx", "syntax", "test-utils", @@ -695,6 +697,7 @@ dependencies = [ "rayon", "rustc-hash", "sourcegen", + "span", "stdx", "syntax", "test-utils", @@ -910,6 +913,7 @@ dependencies = [ "itertools", "proc-macro-api", "project-model", + "span", "tracing", "tt", "vfs", @@ -977,6 +981,7 @@ dependencies = [ "parser", "rustc-hash", "smallvec", + "span", "stdx", "syntax", "test-utils", @@ -1253,6 +1258,7 @@ dependencies = [ "serde", "serde_json", "snap", + "span", "stdx", "text-size", "tracing", @@ -1728,6 +1734,17 @@ dependencies = [ "xshell", ] +[[package]] +name = "span" +version = "0.0.0" +dependencies = [ + "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rust-analyzer-salsa", + "stdx", + "syntax", + "vfs", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -2000,6 +2017,7 @@ name = "tt" version = "0.0.0" dependencies = [ "smol_str", + "span", "stdx", "text-size", ] diff --git a/Cargo.toml b/Cargo.toml index 1213979c39..f1f61d8ec7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,6 +71,7 @@ proc-macro-srv-cli = { path = "./crates/proc-macro-srv-cli", version = "0.0.0" } profile = { path = "./crates/profile", version = "0.0.0" } project-model = { path = "./crates/project-model", version = "0.0.0" } sourcegen = { path = "./crates/sourcegen", version = "0.0.0" } +span = { path = "./crates/span", version = "0.0.0" } stdx = { path = "./crates/stdx", version = "0.0.0" } syntax = { path = "./crates/syntax", version = "0.0.0" } test-utils = { path = "./crates/test-utils", version = "0.0.0" } diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml index 393ffe155b..a8ff97bded 100644 --- a/crates/base-db/Cargo.toml +++ b/crates/base-db/Cargo.toml @@ -23,5 +23,5 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true test-utils.workspace = true -tt.workspace = true vfs.workspace = true +span.workspace = true diff --git a/crates/base-db/src/lib.rs b/crates/base-db/src/lib.rs index 3e874adbe5..918c1cd3e0 100644 --- a/crates/base-db/src/lib.rs +++ b/crates/base-db/src/lib.rs @@ -4,12 +4,11 @@ mod input; mod change; -pub mod span; use std::panic; use rustc_hash::FxHashSet; -use syntax::{ast, Parse, SourceFile, TextRange, TextSize}; +use syntax::{ast, Parse, SourceFile}; use triomphe::Arc; pub use crate::{ @@ -21,6 +20,7 @@ pub use crate::{ }, }; pub use salsa::{self, Cancelled}; +pub use span::{FilePosition, FileRange}; pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath}; #[macro_export] @@ -41,18 +41,6 @@ pub trait Upcast { fn upcast(&self) -> &T; } -#[derive(Clone, Copy, Debug)] -pub struct FilePosition { - pub file_id: FileId, - pub offset: TextSize, -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] -pub struct FileRange { - pub file_id: FileId, - pub range: TextRange, -} - pub const DEFAULT_PARSE_LRU_CAP: usize = 128; pub trait FileLoader { diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml index 2d17451760..7ebaffcc13 100644 --- a/crates/hir-def/Cargo.toml +++ b/crates/hir-def/Cargo.toml @@ -42,6 +42,7 @@ mbe.workspace = true cfg.workspace = true tt.workspace = true limit.workspace = true +span.workspace = true [dev-dependencies] diff --git a/crates/hir-def/src/attr/tests.rs b/crates/hir-def/src/attr/tests.rs index 0f98a4ec93..20d53f31fb 100644 --- a/crates/hir-def/src/attr/tests.rs +++ b/crates/hir-def/src/attr/tests.rs @@ -2,7 +2,7 @@ //! Currently, it tests `#[doc(hidden)]` and `#[doc(alias)]`. use base_db::FileId; -use hir_expand::span::{RealSpanMap, SpanMapRef}; +use hir_expand::span_map::{RealSpanMap, SpanMapRef}; use mbe::syntax_node_to_token_tree; use syntax::{ast, AstNode}; diff --git a/crates/hir-def/src/expander.rs b/crates/hir-def/src/expander.rs index 398f116d83..490fd5382c 100644 --- a/crates/hir-def/src/expander.rs +++ b/crates/hir-def/src/expander.rs @@ -4,7 +4,7 @@ use base_db::CrateId; use cfg::CfgOptions; use drop_bomb::DropBomb; use hir_expand::{ - attrs::RawAttrs, mod_path::ModPath, span::SpanMap, ExpandError, ExpandResult, HirFileId, + attrs::RawAttrs, mod_path::ModPath, span_map::SpanMap, ExpandError, ExpandResult, HirFileId, InFile, MacroCallId, }; use limit::Limit; diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs index 3d2cddffa3..50253e4c8f 100644 --- a/crates/hir-def/src/item_tree.rs +++ b/crates/hir-def/src/item_tree.rs @@ -42,7 +42,7 @@ use std::{ }; use ast::{AstNode, HasName, StructKind}; -use base_db::{span::SyntaxContextId, CrateId}; +use base_db::CrateId; use either::Either; use hir_expand::{ ast_id_map::{AstIdNode, FileAstId}, @@ -55,6 +55,7 @@ use la_arena::{Arena, Idx, IdxRange, RawIdx}; use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; +use span::SyntaxContextId; use stdx::never; use syntax::{ast, match_ast, SyntaxKind}; use triomphe::Arc; diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs index 83a2790ce8..ed40f299d6 100644 --- a/crates/hir-def/src/item_tree/lower.rs +++ b/crates/hir-def/src/item_tree/lower.rs @@ -2,7 +2,7 @@ use std::collections::hash_map::Entry; -use hir_expand::{ast_id_map::AstIdMap, span::SpanMapRef, HirFileId}; +use hir_expand::{ast_id_map::AstIdMap, span_map::SpanMapRef, HirFileId}; use syntax::ast::{self, HasModuleItem, HasTypeBounds}; use crate::{ diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs index 1e68fd932c..41a41d6df3 100644 --- a/crates/hir-def/src/lib.rs +++ b/crates/hir-def/src/lib.rs @@ -63,7 +63,7 @@ use std::{ panic::{RefUnwindSafe, UnwindSafe}, }; -use base_db::{impl_intern_key, salsa, span::SyntaxContextId, CrateId}; +use base_db::{impl_intern_key, salsa, CrateId}; use hir_expand::{ ast_id_map::{AstIdNode, FileAstId}, attrs::{Attr, AttrId, AttrInput}, @@ -80,6 +80,7 @@ use hir_expand::{ use item_tree::ExternBlock; use la_arena::Idx; use nameres::DefMap; +use span::SyntaxContextId; use stdx::impl_from; use syntax::{ast, AstNode}; diff --git a/crates/hir-def/src/lower.rs b/crates/hir-def/src/lower.rs index a3505b65fe..395b69d284 100644 --- a/crates/hir-def/src/lower.rs +++ b/crates/hir-def/src/lower.rs @@ -3,7 +3,7 @@ use std::cell::OnceCell; use hir_expand::{ ast_id_map::{AstIdMap, AstIdNode}, - span::{SpanMap, SpanMapRef}, + span_map::{SpanMap, SpanMapRef}, AstId, HirFileId, InFile, }; use syntax::ast; diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs index 804645ff43..1d690d2575 100644 --- a/crates/hir-def/src/macro_expansion_tests/mod.rs +++ b/crates/hir-def/src/macro_expansion_tests/mod.rs @@ -16,15 +16,16 @@ mod proc_macros; use std::{iter, ops::Range, sync}; -use base_db::{span::SpanData, SourceDatabase}; +use base_db::SourceDatabase; use expect_test::Expect; use hir_expand::{ db::ExpandDatabase, fixture::WithFixture, proc_macro::{ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind}, - span::SpanMapRef, + span_map::SpanMapRef, InFile, MacroFileId, MacroFileIdExt, }; +use span::Span; use stdx::format_to; use syntax::{ ast::{self, edit::IndentLevel}, @@ -319,9 +320,9 @@ impl ProcMacroExpander for IdentityWhenValidProcMacroExpander { subtree: &Subtree, _: Option<&Subtree>, _: &base_db::Env, - _: SpanData, - _: SpanData, - _: SpanData, + _: Span, + _: Span, + _: Span, ) -> Result { let (parse, _) = ::mbe::token_tree_to_syntax_node(subtree, ::mbe::TopEntryPoint::MacroItems); diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs index d77be4a8a0..0f3dbdfd41 100644 --- a/crates/hir-def/src/nameres/collector.rs +++ b/crates/hir-def/src/nameres/collector.rs @@ -5,7 +5,7 @@ use std::{cmp::Ordering, iter, mem}; -use base_db::{span::SyntaxContextId, CrateId, Dependency, Edition, FileId}; +use base_db::{CrateId, Dependency, Edition, FileId}; use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{ @@ -23,6 +23,7 @@ use itertools::{izip, Itertools}; use la_arena::Idx; use limit::Limit; use rustc_hash::{FxHashMap, FxHashSet}; +use span::{Span, SyntaxContextId}; use stdx::always; use syntax::{ast, SmolStr}; use triomphe::Arc; @@ -86,11 +87,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI // FIXME: a hacky way to create a Name from string. let name = tt::Ident { text: it.name.clone(), - span: tt::SpanData { + span: Span { range: syntax::TextRange::empty(syntax::TextSize::new(0)), - anchor: base_db::span::SpanAnchor { + anchor: span::SpanAnchor { file_id: FileId::BOGUS, - ast_id: base_db::span::ROOT_ERASED_FILE_AST_ID, + ast_id: span::ROOT_ERASED_FILE_AST_ID, }, ctx: SyntaxContextId::ROOT, }, @@ -2095,11 +2096,11 @@ impl ModCollector<'_, '_> { // FIXME: a hacky way to create a Name from string. name = tt::Ident { text: it.clone(), - span: tt::SpanData { + span: Span { range: syntax::TextRange::empty(syntax::TextSize::new(0)), - anchor: base_db::span::SpanAnchor { + anchor: span::SpanAnchor { file_id: FileId::BOGUS, - ast_id: base_db::span::ROOT_ERASED_FILE_AST_ID, + ast_id: span::ROOT_ERASED_FILE_AST_ID, }, ctx: SyntaxContextId::ROOT, }, diff --git a/crates/hir-def/src/visibility.rs b/crates/hir-def/src/visibility.rs index f5803653c7..49688c5ee9 100644 --- a/crates/hir-def/src/visibility.rs +++ b/crates/hir-def/src/visibility.rs @@ -2,7 +2,7 @@ use std::iter; -use hir_expand::{span::SpanMapRef, InFile}; +use hir_expand::{span_map::SpanMapRef, InFile}; use la_arena::ArenaMap; use syntax::ast; use triomphe::Arc; diff --git a/crates/hir-expand/Cargo.toml b/crates/hir-expand/Cargo.toml index 3d1549225f..b39f090736 100644 --- a/crates/hir-expand/Cargo.toml +++ b/crates/hir-expand/Cargo.toml @@ -32,6 +32,7 @@ profile.workspace = true tt.workspace = true mbe.workspace = true limit.workspace = true +span.workspace = true test-utils.workspace = true [dev-dependencies] diff --git a/crates/hir-expand/src/ast_id_map.rs b/crates/hir-expand/src/ast_id_map.rs index be0b72f9df..2abeaaeec4 100644 --- a/crates/hir-expand/src/ast_id_map.rs +++ b/crates/hir-expand/src/ast_id_map.rs @@ -5,6 +5,8 @@ //! item as an ID. That way, id's don't change unless the set of items itself //! changes. +// FIXME: Consider moving this into the span crate + use std::{ any::type_name, fmt, @@ -17,9 +19,9 @@ use profile::Count; use rustc_hash::FxHasher; use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; -use crate::db; +use crate::db::ExpandDatabase; -pub use base_db::span::ErasedFileAstId; +pub use span::ErasedFileAstId; /// `AstId` points to an AST node in any file. /// @@ -27,13 +29,13 @@ pub use base_db::span::ErasedFileAstId; pub type AstId = crate::InFile>; impl AstId { - pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> N { + pub fn to_node(&self, db: &dyn ExpandDatabase) -> N { self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)) } - pub fn to_in_file_node(&self, db: &dyn db::ExpandDatabase) -> crate::InFile { + pub fn to_in_file_node(&self, db: &dyn ExpandDatabase) -> crate::InFile { crate::InFile::new(self.file_id, self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))) } - pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> AstPtr { + pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> AstPtr { db.ast_id_map(self.file_id).get(self.value) } } @@ -41,7 +43,7 @@ impl AstId { pub type ErasedAstId = crate::InFile; impl ErasedAstId { - pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> SyntaxNodePtr { + pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> SyntaxNodePtr { db.ast_id_map(self.file_id).get_erased(self.value) } } diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs index b8fc30c911..16a8518bc3 100644 --- a/crates/hir-expand/src/attrs.rs +++ b/crates/hir-expand/src/attrs.rs @@ -1,19 +1,20 @@ //! A higher level attributes based on TokenTree, with also some shortcuts. use std::{fmt, ops}; -use base_db::{span::SyntaxContextId, CrateId}; +use base_db::CrateId; use cfg::CfgExpr; use either::Either; use intern::Interned; use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct}; use smallvec::{smallvec, SmallVec}; +use span::SyntaxContextId; use syntax::{ast, match_ast, AstNode, AstToken, SmolStr, SyntaxNode}; use triomphe::Arc; use crate::{ db::ExpandDatabase, mod_path::ModPath, - span::SpanMapRef, + span_map::SpanMapRef, tt::{self, Subtree}, InFile, }; diff --git a/crates/hir-expand/src/builtin_attr_macro.rs b/crates/hir-expand/src/builtin_attr_macro.rs index de58a495fe..33ba6d37d5 100644 --- a/crates/hir-expand/src/builtin_attr_macro.rs +++ b/crates/hir-expand/src/builtin_attr_macro.rs @@ -1,12 +1,8 @@ //! Builtin attributes. - -use base_db::{ - span::{SyntaxContextId, ROOT_ERASED_FILE_AST_ID}, - FileId, -}; +use span::{FileId, MacroCallId, Span, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use syntax::{TextRange, TextSize}; -use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallId, MacroCallKind}; +use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind}; macro_rules! register_builtin { ($expand_fn:ident: $(($name:ident, $variant:ident) => $expand:ident),* ) => { @@ -120,9 +116,9 @@ pub fn pseudo_derive_attr_expansion( tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char, spacing: tt::Spacing::Alone, - span: tt::SpanData { + span: Span { range: TextRange::empty(TextSize::new(0)), - anchor: base_db::span::SpanAnchor { + anchor: span::SpanAnchor { file_id: FileId::BOGUS, ast_id: ROOT_ERASED_FILE_AST_ID, }, diff --git a/crates/hir-expand/src/builtin_derive_macro.rs b/crates/hir-expand/src/builtin_derive_macro.rs index 410aa4d289..867b75738a 100644 --- a/crates/hir-expand/src/builtin_derive_macro.rs +++ b/crates/hir-expand/src/builtin_derive_macro.rs @@ -1,20 +1,21 @@ //! Builtin derives. -use base_db::{span::SpanData, CrateOrigin, LangCrateOrigin}; +use base_db::{CrateOrigin, LangCrateOrigin}; use itertools::izip; use rustc_hash::FxHashSet; +use span::{MacroCallId, Span}; use stdx::never; use tracing::debug; use crate::{ hygiene::span_with_def_site_ctxt, name::{AsName, Name}, - span::SpanMapRef, + span_map::SpanMapRef, tt, }; use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds}; -use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult, MacroCallId}; +use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult}; macro_rules! register_builtin { ( $($trait:ident => $expand:ident),* ) => { @@ -73,16 +74,16 @@ enum VariantShape { Unit, } -fn tuple_field_iterator(span: SpanData, n: usize) -> impl Iterator { +fn tuple_field_iterator(span: Span, n: usize) -> impl Iterator { (0..n).map(move |it| tt::Ident::new(format!("f{it}"), span)) } impl VariantShape { - fn as_pattern(&self, path: tt::Subtree, span: SpanData) -> tt::Subtree { + fn as_pattern(&self, path: tt::Subtree, span: Span) -> tt::Subtree { self.as_pattern_map(path, span, |it| quote!(span => #it)) } - fn field_names(&self, span: SpanData) -> Vec { + fn field_names(&self, span: Span) -> Vec { match self { VariantShape::Struct(s) => s.clone(), VariantShape::Tuple(n) => tuple_field_iterator(span, *n).collect(), @@ -93,7 +94,7 @@ impl VariantShape { fn as_pattern_map( &self, path: tt::Subtree, - span: SpanData, + span: Span, field_map: impl Fn(&tt::Ident) -> tt::Subtree, ) -> tt::Subtree { match self { @@ -143,11 +144,11 @@ enum AdtShape { } impl AdtShape { - fn as_pattern(&self, span: SpanData, name: &tt::Ident) -> Vec { + fn as_pattern(&self, span: Span, name: &tt::Ident) -> Vec { self.as_pattern_map(name, |it| quote!(span =>#it), span) } - fn field_names(&self, span: SpanData) -> Vec> { + fn field_names(&self, span: Span) -> Vec> { match self { AdtShape::Struct(s) => { vec![s.field_names(span)] @@ -166,7 +167,7 @@ impl AdtShape { &self, name: &tt::Ident, field_map: impl Fn(&tt::Ident) -> tt::Subtree, - span: SpanData, + span: Span, ) -> Vec { match self { AdtShape::Struct(s) => { @@ -199,7 +200,7 @@ struct BasicAdtInfo { fn parse_adt( tm: SpanMapRef<'_>, adt: &ast::Adt, - call_site: SpanData, + call_site: Span, ) -> Result { let (name, generic_param_list, shape) = match adt { ast::Adt::Struct(it) => ( @@ -349,7 +350,7 @@ fn name_to_token( /// therefore does not get bound by the derived trait. fn expand_simple_derive( // FIXME: use - invoc_span: SpanData, + invoc_span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, trait_path: tt::Subtree, @@ -397,7 +398,7 @@ fn expand_simple_derive( ExpandResult::ok(expanded) } -fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: SpanData) -> tt::TokenTree { +fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: Span) -> tt::TokenTree { // FIXME: make hygiene works for builtin derive macro // such that $crate can be used here. let cg = db.crate_graph(); @@ -416,7 +417,7 @@ fn find_builtin_crate(db: &dyn ExpandDatabase, id: MacroCallId, span: SpanData) fn copy_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -427,7 +428,7 @@ fn copy_expand( fn clone_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -470,13 +471,13 @@ fn clone_expand( } /// This function exists since `quote! {span => => }` doesn't work. -fn fat_arrow(span: SpanData) -> tt::Subtree { +fn fat_arrow(span: Span) -> tt::Subtree { let eq = tt::Punct { char: '=', spacing: ::tt::Spacing::Joint, span }; quote! {span => #eq> } } /// This function exists since `quote! {span => && }` doesn't work. -fn and_and(span: SpanData) -> tt::Subtree { +fn and_and(span: Span) -> tt::Subtree { let and = tt::Punct { char: '&', spacing: ::tt::Spacing::Joint, span }; quote! {span => #and& } } @@ -484,7 +485,7 @@ fn and_and(span: SpanData) -> tt::Subtree { fn default_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -529,7 +530,7 @@ fn default_expand( fn debug_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -607,7 +608,7 @@ fn debug_expand( fn hash_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -660,7 +661,7 @@ fn hash_expand( fn eq_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -671,7 +672,7 @@ fn eq_expand( fn partial_eq_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -725,7 +726,7 @@ fn partial_eq_expand( fn self_and_other_patterns( adt: &BasicAdtInfo, name: &tt::Ident, - span: SpanData, + span: Span, ) -> (Vec, Vec) { let self_patterns = adt.shape.as_pattern_map( name, @@ -749,7 +750,7 @@ fn self_and_other_patterns( fn ord_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -760,7 +761,7 @@ fn ord_expand( left: tt::Subtree, right: tt::Subtree, rest: tt::Subtree, - span: SpanData, + span: Span, ) -> tt::Subtree { let fat_arrow1 = fat_arrow(span); let fat_arrow2 = fat_arrow(span); @@ -813,7 +814,7 @@ fn ord_expand( fn partial_ord_expand( db: &dyn ExpandDatabase, id: MacroCallId, - span: SpanData, + span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>, ) -> ExpandResult { @@ -824,7 +825,7 @@ fn partial_ord_expand( left: tt::Subtree, right: tt::Subtree, rest: tt::Subtree, - span: SpanData, + span: Span, ) -> tt::Subtree { let fat_arrow1 = fat_arrow(span); let fat_arrow2 = fat_arrow(span); diff --git a/crates/hir-expand/src/builtin_fn_macro.rs b/crates/hir-expand/src/builtin_fn_macro.rs index c8f04bfee5..36778cb72d 100644 --- a/crates/hir-expand/src/builtin_fn_macro.rs +++ b/crates/hir-expand/src/builtin_fn_macro.rs @@ -1,13 +1,11 @@ //! Builtin macro -use base_db::{ - span::{SpanAnchor, SpanData, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}, - AnchoredPath, Edition, FileId, -}; +use base_db::{AnchoredPath, Edition, FileId}; use cfg::CfgExpr; use either::Either; use itertools::Itertools; use mbe::{parse_exprs_with_sep, parse_to_token_tree}; +use span::{Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use syntax::{ ast::{self, AstToken}, SmolStr, @@ -122,7 +120,7 @@ register_builtin! { (option_env, OptionEnv) => option_env_expand } -fn mk_pound(span: SpanData) -> tt::Subtree { +fn mk_pound(span: Span) -> tt::Subtree { crate::quote::IntoTt::to_subtree( vec![crate::tt::Leaf::Punct(crate::tt::Punct { char: '#', @@ -138,7 +136,7 @@ fn module_path_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { // Just return a dummy result. ExpandResult::ok(quote! {span => @@ -150,7 +148,7 @@ fn line_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { // dummy implementation for type-checking purposes // Note that `line!` and `column!` will never be implemented properly, as they are by definition @@ -168,7 +166,7 @@ fn log_syntax_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { ExpandResult::ok(quote! {span =>}) } @@ -177,7 +175,7 @@ fn trace_macros_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { ExpandResult::ok(quote! {span =>}) } @@ -186,7 +184,7 @@ fn stringify_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let pretty = ::tt::pretty(&tt.token_trees); @@ -201,7 +199,7 @@ fn assert_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let args = parse_exprs_with_sep(tt, ','); let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; @@ -233,7 +231,7 @@ fn file_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { // FIXME: RA purposefully lacks knowledge of absolute file names // so just return "". @@ -250,7 +248,7 @@ fn format_args_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { format_args_expand_general(db, id, tt, "", span) } @@ -259,7 +257,7 @@ fn format_args_nl_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { format_args_expand_general(db, id, tt, "\\n", span) } @@ -270,7 +268,7 @@ fn format_args_expand_general( tt: &tt::Subtree, // FIXME: Make use of this so that mir interpretation works properly _end_string: &str, - span: SpanData, + span: Span, ) -> ExpandResult { let pound = mk_pound(span); let mut tt = tt.clone(); @@ -284,7 +282,7 @@ fn asm_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { // We expand all assembly snippets to `format_args!` invocations to get format syntax // highlighting for them. @@ -314,7 +312,7 @@ fn global_asm_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { // Expand to nothing (at item-level) ExpandResult::ok(quote! {span =>}) @@ -324,7 +322,7 @@ fn cfg_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let loc = db.lookup_intern_macro_call(id); let expr = CfgExpr::parse(tt); @@ -337,7 +335,7 @@ fn panic_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let loc: MacroCallLoc = db.lookup_intern_macro_call(id); let dollar_crate = tt::Ident { text: SmolStr::new_inline("$crate"), span }; @@ -357,7 +355,7 @@ fn unreachable_expand( db: &dyn ExpandDatabase, id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let loc: MacroCallLoc = db.lookup_intern_macro_call(id); // Expand to a macro call `$crate::panic::unreachable_{edition}` @@ -395,7 +393,7 @@ fn compile_error_expand( _db: &dyn ExpandDatabase, _id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let err = match &*tt.token_trees { [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => match unquote_str(it) { @@ -412,7 +410,7 @@ fn concat_expand( _db: &dyn ExpandDatabase, _arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let mut err = None; let mut text = String::new(); @@ -459,7 +457,7 @@ fn concat_bytes_expand( _db: &dyn ExpandDatabase, _arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let mut bytes = Vec::new(); let mut err = None; @@ -543,7 +541,7 @@ fn concat_idents_expand( _db: &dyn ExpandDatabase, _arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let mut err = None; let mut ident = String::new(); @@ -596,7 +594,7 @@ fn include_expand( db: &dyn ExpandDatabase, arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let file_id = match include_input_to_file_id(db, arg_id, tt) { Ok(it) => it, @@ -629,7 +627,7 @@ fn include_bytes_expand( _db: &dyn ExpandDatabase, _arg_id: MacroCallId, _tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { // FIXME: actually read the file here if the user asked for macro expansion let res = tt::Subtree { @@ -646,7 +644,7 @@ fn include_str_expand( db: &dyn ExpandDatabase, arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let path = match parse_string(tt) { Ok(it) => it, @@ -681,7 +679,7 @@ fn env_expand( db: &dyn ExpandDatabase, arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let key = match parse_string(tt) { Ok(it) => it, @@ -713,7 +711,7 @@ fn option_env_expand( db: &dyn ExpandDatabase, arg_id: MacroCallId, tt: &tt::Subtree, - span: SpanData, + span: Span, ) -> ExpandResult { let key = match parse_string(tt) { Ok(it) => it, diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index 1e86618ce8..dab9d5d560 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -2,13 +2,13 @@ use base_db::{ salsa::{self, debug::DebugQueryTable}, - span::SyntaxContextId, CrateId, Edition, FileId, SourceDatabase, }; use either::Either; use limit::Limit; use mbe::{syntax_node_to_token_tree, ValueResult}; use rustc_hash::FxHashSet; +use span::SyntaxContextId; use syntax::{ ast::{self, HasAttrs}, AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, @@ -23,7 +23,7 @@ use crate::{ fixup::{self, reverse_fixups, SyntaxFixupUndoInfo}, hygiene::{apply_mark, SyntaxContextData, Transparency}, proc_macro::ProcMacros, - span::{RealSpanMap, SpanMap, SpanMapRef}, + span_map::{RealSpanMap, SpanMap, SpanMapRef}, tt, AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, CustomProcMacroExpander, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, @@ -41,7 +41,7 @@ static TOKEN_LIMIT: Limit = Limit::new(1_048_576); #[derive(Debug, Clone, Eq, PartialEq)] /// Old-style `macro_rules` or the new macros 2.0 pub struct DeclarativeMacroExpander { - pub mac: mbe::DeclarativeMacro, + pub mac: mbe::DeclarativeMacro, pub transparency: Transparency, } @@ -170,7 +170,20 @@ pub fn span_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> SpanMap { } pub fn real_span_map(db: &dyn ExpandDatabase, file_id: FileId) -> Arc { - Arc::new(RealSpanMap::from_file(db, file_id)) + use syntax::ast::HasModuleItem; + let mut pairs = vec![(syntax::TextSize::new(0), span::ROOT_ERASED_FILE_AST_ID)]; + let ast_id_map = db.ast_id_map(file_id.into()); + let tree = db.parse(file_id).tree(); + pairs.extend( + tree.items() + .map(|item| (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase())), + ); + + Arc::new(RealSpanMap::from_file( + file_id, + pairs.into_boxed_slice(), + tree.syntax().text_range().end(), + )) } /// This expands the given macro call, but with different arguments. This is diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs index 8d55240aef..03b664fd95 100644 --- a/crates/hir-expand/src/eager.rs +++ b/crates/hir-expand/src/eager.rs @@ -18,7 +18,8 @@ //! //! //! See the full discussion : -use base_db::{span::SyntaxContextId, CrateId}; +use base_db::CrateId; +use span::SyntaxContextId; use syntax::{ted, Parse, SyntaxElement, SyntaxNode, TextSize, WalkEvent}; use triomphe::Arc; @@ -26,7 +27,7 @@ use crate::{ ast::{self, AstNode}, db::ExpandDatabase, mod_path::ModPath, - span::SpanMapRef, + span_map::SpanMapRef, EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, }; diff --git a/crates/hir-expand/src/files.rs b/crates/hir-expand/src/files.rs index 89f0685d5b..40553d3e96 100644 --- a/crates/hir-expand/src/files.rs +++ b/crates/hir-expand/src/files.rs @@ -1,11 +1,8 @@ //! Things to wrap other things in file ids. use std::iter; -use base_db::{ - span::{HirFileId, HirFileIdRepr, MacroFileId, SyntaxContextId}, - FileId, FileRange, -}; use either::Either; +use span::{FileId, FileRange, HirFileId, HirFileIdRepr, MacroFileId, SyntaxContextId}; use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize}; use crate::{db, ExpansionInfo, MacroFileIdExt}; diff --git a/crates/hir-expand/src/fixture.rs b/crates/hir-expand/src/fixture.rs index 9a65a5c5b7..0c194a1b1e 100644 --- a/crates/hir-expand/src/fixture.rs +++ b/crates/hir-expand/src/fixture.rs @@ -2,12 +2,13 @@ use std::{mem, ops::Not, str::FromStr, sync}; use base_db::{ - salsa::Durability, span::SpanData, CrateDisplayName, CrateGraph, CrateId, CrateName, - CrateOrigin, Dependency, DependencyKind, Edition, Env, FileChange, FileId, FilePosition, - FileRange, FileSet, LangCrateOrigin, ReleaseChannel, SourceDatabaseExt, SourceRoot, VfsPath, + salsa::Durability, CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, + DependencyKind, Edition, Env, FileChange, FileSet, LangCrateOrigin, ReleaseChannel, + SourceDatabaseExt, SourceRoot, VfsPath, }; use cfg::CfgOptions; use rustc_hash::FxHashMap; +use span::{FileId, FilePosition, FileRange, Span}; use test_utils::{ extract_range_or_offset, Fixture, FixtureWithProjectMeta, RangeOrOffset, CURSOR_MARKER, ESCAPED_CURSOR_MARKER, @@ -580,13 +581,13 @@ struct IdentityProcMacroExpander; impl ProcMacroExpander for IdentityProcMacroExpander { fn expand( &self, - subtree: &Subtree, - _: Option<&Subtree>, + subtree: &Subtree, + _: Option<&Subtree>, _: &Env, - _: SpanData, - _: SpanData, - _: SpanData, - ) -> Result, ProcMacroExpansionError> { + _: Span, + _: Span, + _: Span, + ) -> Result, ProcMacroExpansionError> { Ok(subtree.clone()) } } @@ -597,13 +598,13 @@ struct AttributeInputReplaceProcMacroExpander; impl ProcMacroExpander for AttributeInputReplaceProcMacroExpander { fn expand( &self, - _: &Subtree, - attrs: Option<&Subtree>, + _: &Subtree, + attrs: Option<&Subtree>, _: &Env, - _: SpanData, - _: SpanData, - _: SpanData, - ) -> Result, ProcMacroExpansionError> { + _: Span, + _: Span, + _: Span, + ) -> Result, ProcMacroExpansionError> { attrs .cloned() .ok_or_else(|| ProcMacroExpansionError::Panic("Expected attribute input".into())) @@ -615,14 +616,14 @@ struct MirrorProcMacroExpander; impl ProcMacroExpander for MirrorProcMacroExpander { fn expand( &self, - input: &Subtree, - _: Option<&Subtree>, + input: &Subtree, + _: Option<&Subtree>, _: &Env, - _: SpanData, - _: SpanData, - _: SpanData, - ) -> Result, ProcMacroExpansionError> { - fn traverse(input: &Subtree) -> Subtree { + _: Span, + _: Span, + _: Span, + ) -> Result, ProcMacroExpansionError> { + fn traverse(input: &Subtree) -> Subtree { let mut token_trees = vec![]; for tt in input.token_trees.iter().rev() { let tt = match tt { @@ -645,16 +646,16 @@ struct ShortenProcMacroExpander; impl ProcMacroExpander for ShortenProcMacroExpander { fn expand( &self, - input: &Subtree, - _: Option<&Subtree>, + input: &Subtree, + _: Option<&Subtree>, _: &Env, - _: SpanData, - _: SpanData, - _: SpanData, - ) -> Result, ProcMacroExpansionError> { + _: Span, + _: Span, + _: Span, + ) -> Result, ProcMacroExpansionError> { return Ok(traverse(input)); - fn traverse(input: &Subtree) -> Subtree { + fn traverse(input: &Subtree) -> Subtree { let token_trees = input .token_trees .iter() @@ -666,7 +667,7 @@ impl ProcMacroExpander for ShortenProcMacroExpander { Subtree { delimiter: input.delimiter, token_trees } } - fn modify_leaf(leaf: &Leaf) -> Leaf { + fn modify_leaf(leaf: &Leaf) -> Leaf { let mut leaf = leaf.clone(); match &mut leaf { Leaf::Literal(it) => { diff --git a/crates/hir-expand/src/fixup.rs b/crates/hir-expand/src/fixup.rs index 346cd39a76..3705ebc554 100644 --- a/crates/hir-expand/src/fixup.rs +++ b/crates/hir-expand/src/fixup.rs @@ -1,23 +1,20 @@ //! To make attribute macros work reliably when typing, we need to take care to //! fix up syntax errors in the code we're passing to them. -use base_db::{ - span::{ErasedFileAstId, SpanAnchor, SpanData}, - FileId, -}; use la_arena::RawIdx; use rustc_hash::{FxHashMap, FxHashSet}; use smallvec::SmallVec; +use span::{ErasedFileAstId, FileId, SpanAnchor, SpanData}; use stdx::never; use syntax::{ ast::{self, AstNode, HasLoopBody}, match_ast, SyntaxElement, SyntaxKind, SyntaxNode, TextRange, TextSize, }; use triomphe::Arc; -use tt::{Spacing, Span}; +use tt::Spacing; use crate::{ - span::SpanMapRef, + span_map::SpanMapRef, tt::{Ident, Leaf, Punct, Subtree}, }; @@ -301,6 +298,7 @@ fn has_error_to_handle(node: &SyntaxNode) -> bool { pub(crate) fn reverse_fixups(tt: &mut Subtree, undo_info: &SyntaxFixupUndoInfo) { let Some(undo_info) = undo_info.original.as_deref() else { return }; let undo_info = &**undo_info; + #[allow(deprecated)] if never!( tt.delimiter.close.anchor.file_id == FIXUP_DUMMY_FILE || tt.delimiter.open.anchor.file_id == FIXUP_DUMMY_FILE @@ -364,7 +362,7 @@ mod tests { use crate::{ fixup::reverse_fixups, - span::{RealSpanMap, SpanMap}, + span_map::{RealSpanMap, SpanMap}, tt, }; diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs index 7b03709ace..5ab8581aea 100644 --- a/crates/hir-expand/src/hygiene.rs +++ b/crates/hir-expand/src/hygiene.rs @@ -2,9 +2,12 @@ //! //! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at //! this moment, this is horribly incomplete and handles only `$crate`. + +// FIXME: Consider moving this into the span crate. + use std::iter; -use base_db::span::{MacroCallId, SpanData, SyntaxContextId}; +use span::{MacroCallId, Span, SyntaxContextId}; use crate::db::ExpandDatabase; @@ -78,37 +81,29 @@ pub enum Transparency { Opaque, } -pub fn span_with_def_site_ctxt( - db: &dyn ExpandDatabase, - span: SpanData, - expn_id: MacroCallId, -) -> SpanData { +pub fn span_with_def_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { span_with_ctxt_from_mark(db, span, expn_id, Transparency::Opaque) } -pub fn span_with_call_site_ctxt( - db: &dyn ExpandDatabase, - span: SpanData, - expn_id: MacroCallId, -) -> SpanData { +pub fn span_with_call_site_ctxt(db: &dyn ExpandDatabase, span: Span, expn_id: MacroCallId) -> Span { span_with_ctxt_from_mark(db, span, expn_id, Transparency::Transparent) } pub fn span_with_mixed_site_ctxt( db: &dyn ExpandDatabase, - span: SpanData, + span: Span, expn_id: MacroCallId, -) -> SpanData { +) -> Span { span_with_ctxt_from_mark(db, span, expn_id, Transparency::SemiTransparent) } fn span_with_ctxt_from_mark( db: &dyn ExpandDatabase, - span: SpanData, + span: Span, expn_id: MacroCallId, transparency: Transparency, -) -> SpanData { - SpanData { ctx: apply_mark(db, SyntaxContextId::ROOT, expn_id, transparency), ..span } +) -> Span { + Span { ctx: apply_mark(db, SyntaxContextId::ROOT, expn_id, transparency), ..span } } pub(super) fn apply_mark( diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs index bb2cb3f5b5..5496f2d661 100644 --- a/crates/hir-expand/src/lib.rs +++ b/crates/hir-expand/src/lib.rs @@ -20,7 +20,7 @@ pub mod mod_path; pub mod name; pub mod proc_macro; pub mod quote; -pub mod span; +pub mod span_map; mod fixup; use attrs::collect_attrs; @@ -28,11 +28,9 @@ use triomphe::Arc; use std::{fmt, hash::Hash}; -use base_db::{ - span::{HirFileIdRepr, SpanData, SyntaxContextId}, - CrateId, FileId, FileRange, -}; +use base_db::{CrateId, FileId}; use either::Either; +use span::{FileRange, HirFileIdRepr, Span, SyntaxContextId}; use syntax::{ ast::{self, AstNode}, SyntaxNode, SyntaxToken, TextRange, TextSize, @@ -47,29 +45,29 @@ use crate::{ fixup::SyntaxFixupUndoInfo, mod_path::ModPath, proc_macro::{CustomProcMacroExpander, ProcMacroKind}, - span::{ExpansionSpanMap, SpanMap}, + span_map::{ExpansionSpanMap, SpanMap}, }; pub use crate::ast_id_map::{AstId, ErasedAstId, ErasedFileAstId}; pub use crate::files::{InFile, InMacroFile, InRealFile}; -pub use base_db::span::{HirFileId, MacroCallId, MacroFileId}; pub use mbe::ValueResult; +pub use span::{HirFileId, MacroCallId, MacroFileId}; -pub type DeclarativeMacro = ::mbe::DeclarativeMacro; +pub type DeclarativeMacro = ::mbe::DeclarativeMacro; pub mod tt { - pub use base_db::span::SpanData; - pub use tt::{DelimiterKind, Spacing, Span, SpanAnchor}; + pub use span::Span; + pub use tt::{DelimiterKind, Spacing}; - pub type Delimiter = ::tt::Delimiter; - pub type DelimSpan = ::tt::DelimSpan; - pub type Subtree = ::tt::Subtree; - pub type Leaf = ::tt::Leaf; - pub type Literal = ::tt::Literal; - pub type Punct = ::tt::Punct; - pub type Ident = ::tt::Ident; - pub type TokenTree = ::tt::TokenTree; + pub type Delimiter = ::tt::Delimiter; + pub type DelimSpan = ::tt::DelimSpan; + pub type Subtree = ::tt::Subtree; + pub type Leaf = ::tt::Leaf; + pub type Literal = ::tt::Literal; + pub type Punct = ::tt::Punct; + pub type Ident = ::tt::Ident; + pub type TokenTree = ::tt::TokenTree; } pub type ExpandResult = ValueResult; @@ -212,8 +210,8 @@ impl HirFileIdExt for HirFileId { fn original_file_respecting_includes(mut self, db: &dyn db::ExpandDatabase) -> FileId { loop { match self.repr() { - base_db::span::HirFileIdRepr::FileId(id) => break id, - base_db::span::HirFileIdRepr::MacroFile(file) => { + HirFileIdRepr::FileId(id) => break id, + HirFileIdRepr::MacroFile(file) => { let loc = db.lookup_intern_macro_call(file.macro_call_id); if loc.def.is_include() { if let Some(eager) = &loc.eager { @@ -420,7 +418,7 @@ impl MacroDefId { } impl MacroCallLoc { - pub fn span(&self, db: &dyn db::ExpandDatabase) -> SpanData { + pub fn span(&self, db: &dyn db::ExpandDatabase) -> Span { let ast_id = self.kind.erased_ast_id(); let file_id = self.kind.file_id(); let range = db.ast_id_map(file_id).get_erased(ast_id).text_range(); @@ -618,7 +616,7 @@ impl ExpansionInfo { /// Maps the passed in file range down into a macro expansion if it is the input to a macro call. pub fn map_range_down<'a>( &'a self, - span: SpanData, + span: Span, ) -> Option + 'a>> { let tokens = self .exp_map @@ -652,7 +650,7 @@ impl ExpansionInfo { ) -> Option<(FileRange, SyntaxContextId)> { debug_assert!(self.expanded.value.text_range().contains_range(range)); let mut spans = self.exp_map.spans_for_range(range); - let SpanData { range, anchor, ctx } = spans.next()?; + let Span { range, anchor, ctx } = spans.next()?; let mut start = range.start(); let mut end = range.end(); diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs index 9534b5039f..30b8c189f5 100644 --- a/crates/hir-expand/src/mod_path.rs +++ b/crates/hir-expand/src/mod_path.rs @@ -9,10 +9,11 @@ use crate::{ db::ExpandDatabase, hygiene::{marks_rev, SyntaxContextExt, Transparency}, name::{known, AsName, Name}, - span::SpanMapRef, + span_map::SpanMapRef, }; -use base_db::{span::SyntaxContextId, CrateId}; +use base_db::CrateId; use smallvec::SmallVec; +use span::SyntaxContextId; use syntax::{ast, AstNode}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs index 2707df9d1a..25c78fade8 100644 --- a/crates/hir-expand/src/proc_macro.rs +++ b/crates/hir-expand/src/proc_macro.rs @@ -3,8 +3,9 @@ use core::fmt; use std::{panic::RefUnwindSafe, sync}; -use base_db::{span::SpanData, CrateId, Env}; +use base_db::{CrateId, Env}; use rustc_hash::FxHashMap; +use span::Span; use stdx::never; use syntax::SmolStr; @@ -26,9 +27,9 @@ pub trait ProcMacroExpander: fmt::Debug + Send + Sync + RefUnwindSafe { subtree: &tt::Subtree, attrs: Option<&tt::Subtree>, env: &Env, - def_site: SpanData, - call_site: SpanData, - mixed_site: SpanData, + def_site: Span, + call_site: Span, + mixed_site: Span, ) -> Result; } @@ -78,9 +79,9 @@ impl CustomProcMacroExpander { calling_crate: CrateId, tt: &tt::Subtree, attr_arg: Option<&tt::Subtree>, - def_site: SpanData, - call_site: SpanData, - mixed_site: SpanData, + def_site: Span, + call_site: Span, + mixed_site: Span, ) -> ExpandResult { match self.proc_macro_id { ProcMacroId(DUMMY_ID) => ExpandResult::new( diff --git a/crates/hir-expand/src/quote.rs b/crates/hir-expand/src/quote.rs index acbde26c8d..7c24724690 100644 --- a/crates/hir-expand/src/quote.rs +++ b/crates/hir-expand/src/quote.rs @@ -1,6 +1,6 @@ //! A simplified version of quote-crate like quasi quote macro -use base_db::span::SpanData; +use span::Span; // A helper macro quote macro // FIXME: @@ -130,12 +130,12 @@ macro_rules! quote { } pub(crate) trait IntoTt { - fn to_subtree(self, span: SpanData) -> crate::tt::Subtree; + fn to_subtree(self, span: Span) -> crate::tt::Subtree; fn to_tokens(self) -> Vec; } impl IntoTt for Vec { - fn to_subtree(self, span: SpanData) -> crate::tt::Subtree { + fn to_subtree(self, span: Span) -> crate::tt::Subtree { crate::tt::Subtree { delimiter: crate::tt::Delimiter::invisible_spanned(span), token_trees: self, @@ -148,7 +148,7 @@ impl IntoTt for Vec { } impl IntoTt for crate::tt::Subtree { - fn to_subtree(self, _: SpanData) -> crate::tt::Subtree { + fn to_subtree(self, _: Span) -> crate::tt::Subtree { self } @@ -158,23 +158,23 @@ impl IntoTt for crate::tt::Subtree { } pub(crate) trait ToTokenTree { - fn to_token(self, span: SpanData) -> crate::tt::TokenTree; + fn to_token(self, span: Span) -> crate::tt::TokenTree; } impl ToTokenTree for crate::tt::TokenTree { - fn to_token(self, _: SpanData) -> crate::tt::TokenTree { + fn to_token(self, _: Span) -> crate::tt::TokenTree { self } } impl ToTokenTree for &crate::tt::TokenTree { - fn to_token(self, _: SpanData) -> crate::tt::TokenTree { + fn to_token(self, _: Span) -> crate::tt::TokenTree { self.clone() } } impl ToTokenTree for crate::tt::Subtree { - fn to_token(self, _: SpanData) -> crate::tt::TokenTree { + fn to_token(self, _: Span) -> crate::tt::TokenTree { self.into() } } @@ -183,14 +183,14 @@ macro_rules! impl_to_to_tokentrees { ($($span:ident: $ty:ty => $this:ident $im:block);*) => { $( impl ToTokenTree for $ty { - fn to_token($this, $span: SpanData) -> crate::tt::TokenTree { + fn to_token($this, $span: Span) -> crate::tt::TokenTree { let leaf: crate::tt::Leaf = $im.into(); leaf.into() } } impl ToTokenTree for &$ty { - fn to_token($this, $span: SpanData) -> crate::tt::TokenTree { + fn to_token($this, $span: Span) -> crate::tt::TokenTree { let leaf: crate::tt::Leaf = $im.clone().into(); leaf.into() } @@ -215,14 +215,12 @@ impl_to_to_tokentrees! { #[cfg(test)] mod tests { use crate::tt; - use base_db::{ - span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}, - FileId, - }; + use base_db::FileId; use expect_test::expect; + use span::{SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; use syntax::{TextRange, TextSize}; - const DUMMY: tt::SpanData = tt::SpanData { + const DUMMY: tt::Span = tt::Span { range: TextRange::empty(TextSize::new(0)), anchor: SpanAnchor { file_id: FileId::BOGUS, ast_id: ROOT_ERASED_FILE_AST_ID }, ctx: SyntaxContextId::ROOT, diff --git a/crates/hir-expand/src/span.rs b/crates/hir-expand/src/span.rs deleted file mode 100644 index fe476a40fe..0000000000 --- a/crates/hir-expand/src/span.rs +++ /dev/null @@ -1,124 +0,0 @@ -//! Spanmaps allow turning absolute ranges into relative ranges for incrementality purposes as well -//! as associating spans with text ranges in a particular file. -use base_db::{ - span::{ErasedFileAstId, SpanAnchor, SpanData, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}, - FileId, -}; -use syntax::{ast::HasModuleItem, AstNode, TextRange, TextSize}; -use triomphe::Arc; - -use crate::db::ExpandDatabase; - -pub type ExpansionSpanMap = mbe::SpanMap; - -/// Spanmap for a macro file or a real file -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum SpanMap { - /// Spanmap for a macro file - ExpansionSpanMap(Arc), - /// Spanmap for a real file - RealSpanMap(Arc), -} - -#[derive(Copy, Clone)] -pub enum SpanMapRef<'a> { - /// Spanmap for a macro file - ExpansionSpanMap(&'a ExpansionSpanMap), - /// Spanmap for a real file - RealSpanMap(&'a RealSpanMap), -} - -impl mbe::SpanMapper for SpanMap { - fn span_for(&self, range: TextRange) -> SpanData { - self.span_for_range(range) - } -} -impl mbe::SpanMapper for SpanMapRef<'_> { - fn span_for(&self, range: TextRange) -> SpanData { - self.span_for_range(range) - } -} -impl mbe::SpanMapper for RealSpanMap { - fn span_for(&self, range: TextRange) -> SpanData { - self.span_for_range(range) - } -} - -impl SpanMap { - pub fn span_for_range(&self, range: TextRange) -> SpanData { - match self { - Self::ExpansionSpanMap(span_map) => span_map.span_at(range.start()), - Self::RealSpanMap(span_map) => span_map.span_for_range(range), - } - } - - pub fn as_ref(&self) -> SpanMapRef<'_> { - match self { - Self::ExpansionSpanMap(span_map) => SpanMapRef::ExpansionSpanMap(span_map), - Self::RealSpanMap(span_map) => SpanMapRef::RealSpanMap(span_map), - } - } -} - -impl SpanMapRef<'_> { - pub fn span_for_range(self, range: TextRange) -> SpanData { - match self { - Self::ExpansionSpanMap(span_map) => span_map.span_at(range.start()), - Self::RealSpanMap(span_map) => span_map.span_for_range(range), - } - } -} - -#[derive(PartialEq, Eq, Hash, Debug)] -pub struct RealSpanMap { - file_id: FileId, - /// Invariant: Sorted vec over TextSize - // FIXME: SortedVec<(TextSize, ErasedFileAstId)>? - pairs: Box<[(TextSize, ErasedFileAstId)]>, - end: TextSize, -} - -impl RealSpanMap { - /// Creates a real file span map that returns absolute ranges (relative ranges to the root ast id). - pub fn absolute(file_id: FileId) -> Self { - RealSpanMap { - file_id, - pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]), - end: TextSize::new(!0), - } - } - - pub fn from_file(db: &dyn ExpandDatabase, file_id: FileId) -> Self { - let mut pairs = vec![(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]; - let ast_id_map = db.ast_id_map(file_id.into()); - let tree = db.parse(file_id).tree(); - pairs - .extend(tree.items().map(|item| { - (item.syntax().text_range().start(), ast_id_map.ast_id(&item).erase()) - })); - RealSpanMap { - file_id, - pairs: pairs.into_boxed_slice(), - end: tree.syntax().text_range().end(), - } - } - - pub fn span_for_range(&self, range: TextRange) -> SpanData { - assert!( - range.end() <= self.end, - "range {range:?} goes beyond the end of the file {:?}", - self.end - ); - let start = range.start(); - let idx = self - .pairs - .binary_search_by(|&(it, _)| it.cmp(&start).then(std::cmp::Ordering::Less)) - .unwrap_err(); - let (offset, ast_id) = self.pairs[idx - 1]; - SpanData { - range: range - offset, - anchor: SpanAnchor { file_id: self.file_id, ast_id }, - ctx: SyntaxContextId::ROOT, - } - } -} diff --git a/crates/hir-expand/src/span_map.rs b/crates/hir-expand/src/span_map.rs new file mode 100644 index 0000000000..f9763cd886 --- /dev/null +++ b/crates/hir-expand/src/span_map.rs @@ -0,0 +1,61 @@ +//! Span maps for real files and macro expansions. +use span::Span; +use syntax::TextRange; +use triomphe::Arc; + +pub use span::RealSpanMap; + +pub type ExpansionSpanMap = span::SpanMap; + +/// Spanmap for a macro file or a real file +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum SpanMap { + /// Spanmap for a macro file + ExpansionSpanMap(Arc), + /// Spanmap for a real file + RealSpanMap(Arc), +} + +#[derive(Copy, Clone)] +pub enum SpanMapRef<'a> { + /// Spanmap for a macro file + ExpansionSpanMap(&'a ExpansionSpanMap), + /// Spanmap for a real file + RealSpanMap(&'a RealSpanMap), +} + +impl mbe::SpanMapper for SpanMap { + fn span_for(&self, range: TextRange) -> Span { + self.span_for_range(range) + } +} +impl mbe::SpanMapper for SpanMapRef<'_> { + fn span_for(&self, range: TextRange) -> Span { + self.span_for_range(range) + } +} + +impl SpanMap { + pub fn span_for_range(&self, range: TextRange) -> Span { + match self { + Self::ExpansionSpanMap(span_map) => span_map.span_at(range.start()), + Self::RealSpanMap(span_map) => span_map.span_for_range(range), + } + } + + pub fn as_ref(&self) -> SpanMapRef<'_> { + match self { + Self::ExpansionSpanMap(span_map) => SpanMapRef::ExpansionSpanMap(span_map), + Self::RealSpanMap(span_map) => SpanMapRef::RealSpanMap(span_map), + } + } +} + +impl SpanMapRef<'_> { + pub fn span_for_range(self, range: TextRange) -> Span { + match self { + Self::ExpansionSpanMap(span_map) => span_map.span_at(range.start()), + Self::RealSpanMap(span_map) => span_map.span_for_range(range), + } + } +} diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index 1858533531..d60d20f5b7 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs @@ -11,7 +11,7 @@ use hir_def::{ }; use hir_expand::{ name::Name, - span::{RealSpanMap, SpanMapRef}, + span_map::{RealSpanMap, SpanMapRef}, }; use hir_ty::db::HirDatabase; use syntax::{ast, AstNode}; diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ccf031df0c..5096cf2e9c 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -148,7 +148,7 @@ use { hir_def::path::Path, hir_expand::{ name::AsName, - span::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, + span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef}, }, }; diff --git a/crates/ide-db/Cargo.toml b/crates/ide-db/Cargo.toml index 4a2e770f19..e14117034f 100644 --- a/crates/ide-db/Cargo.toml +++ b/crates/ide-db/Cargo.toml @@ -34,6 +34,7 @@ profile.workspace = true stdx.workspace = true syntax.workspace = true text-edit.workspace = true +span.workspace = true # ide should depend only on the top-level `hir` package. if you need # something from some `hir-xxx` subpackage, reexport the API via `hir`. hir.workspace = true diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs index d2b6a73268..c653264006 100644 --- a/crates/ide-db/src/rename.rs +++ b/crates/ide-db/src/rename.rs @@ -22,9 +22,10 @@ //! Our current behavior is ¯\_(ツ)_/¯. use std::fmt; -use base_db::{span::SyntaxContextId, AnchoredPathBuf, FileId, FileRange}; +use base_db::{AnchoredPathBuf, FileId, FileRange}; use either::Either; use hir::{FieldSource, HasSource, HirFileIdExt, InFile, ModuleSource, Semantics}; +use span::SyntaxContextId; use stdx::{never, TupleExt}; use syntax::{ ast::{self, HasName}, diff --git a/crates/load-cargo/Cargo.toml b/crates/load-cargo/Cargo.toml index 06b3b94587..346c234f09 100644 --- a/crates/load-cargo/Cargo.toml +++ b/crates/load-cargo/Cargo.toml @@ -23,5 +23,6 @@ project-model.workspace = true tt.workspace = true vfs.workspace = true vfs-notify.workspace = true +span.workspace = true hir-expand.workspace = true diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs index cab8d609ea..ee42640ceb 100644 --- a/crates/load-cargo/src/lib.rs +++ b/crates/load-cargo/src/lib.rs @@ -11,13 +11,14 @@ use hir_expand::proc_macro::{ }; use ide::{AnalysisHost, SourceRoot}; use ide_db::{ - base_db::{span::SpanData, CrateGraph, Env}, + base_db::{CrateGraph, Env}, fixture::Change, FxHashMap, }; use itertools::Itertools; use proc_macro_api::{MacroDylib, ProcMacroServer}; use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace}; +use span::Span; use tt::DelimSpan; use vfs::{file_set::FileSetConfig, loader::Handle, AbsPath, AbsPathBuf, VfsPath}; @@ -376,13 +377,13 @@ struct Expander(proc_macro_api::ProcMacro); impl ProcMacroExpander for Expander { fn expand( &self, - subtree: &tt::Subtree, - attrs: Option<&tt::Subtree>, + subtree: &tt::Subtree, + attrs: Option<&tt::Subtree>, env: &Env, - def_site: SpanData, - call_site: SpanData, - mixed_site: SpanData, - ) -> Result, ProcMacroExpansionError> { + def_site: Span, + call_site: Span, + mixed_site: Span, + ) -> Result, ProcMacroExpansionError> { let env = env.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect(); match self.0.expand(subtree, attrs, env, def_site, call_site, mixed_site) { Ok(Ok(subtree)) => Ok(subtree), @@ -399,13 +400,13 @@ struct IdentityExpander; impl ProcMacroExpander for IdentityExpander { fn expand( &self, - subtree: &tt::Subtree, - _: Option<&tt::Subtree>, + subtree: &tt::Subtree, + _: Option<&tt::Subtree>, _: &Env, - _: SpanData, - _: SpanData, - _: SpanData, - ) -> Result, ProcMacroExpansionError> { + _: Span, + _: Span, + _: Span, + ) -> Result, ProcMacroExpansionError> { Ok(subtree.clone()) } } @@ -417,13 +418,13 @@ struct EmptyExpander; impl ProcMacroExpander for EmptyExpander { fn expand( &self, - _: &tt::Subtree, - _: Option<&tt::Subtree>, + _: &tt::Subtree, + _: Option<&tt::Subtree>, _: &Env, - call_site: SpanData, - _: SpanData, - _: SpanData, - ) -> Result, ProcMacroExpansionError> { + call_site: Span, + _: Span, + _: Span, + ) -> Result, ProcMacroExpansionError> { Ok(tt::Subtree::empty(DelimSpan { open: call_site, close: call_site })) } } diff --git a/crates/mbe/Cargo.toml b/crates/mbe/Cargo.toml index adab1003d1..cc0a47291e 100644 --- a/crates/mbe/Cargo.toml +++ b/crates/mbe/Cargo.toml @@ -22,6 +22,7 @@ syntax.workspace = true parser.workspace = true tt.workspace = true stdx.workspace = true +span.workspace = true [dev-dependencies] test-utils.workspace = true diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index 7a3e8653c2..9fccf5f424 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs @@ -226,6 +226,7 @@ fn expand_subtree( tt::Leaf::Literal(tt::Literal { text: index.to_string().into(), // FIXME + #[allow(deprecated)] span: S::DUMMY, }) .into(), @@ -286,6 +287,7 @@ fn expand_subtree( tt::Leaf::Literal(tt::Literal { text: c.to_string().into(), // FIXME + #[allow(deprecated)] span: S::DUMMY, }) .into(), @@ -343,8 +345,10 @@ fn expand_var( Err(e) => ExpandResult { value: Fragment::Tokens(tt::TokenTree::Subtree(tt::Subtree::empty(tt::DelimSpan { // FIXME + #[allow(deprecated)] open: S::DUMMY, // FIXME + #[allow(deprecated)] close: S::DUMMY, }))), err: Some(e), @@ -487,6 +491,7 @@ fn fix_up_and_push_path_tt(buf: &mut Vec>, subtree: tt char: ':', spacing: tt::Spacing::Joint, // FIXME + #[allow(deprecated)] span: S::DUMMY, }) .into(), @@ -496,6 +501,7 @@ fn fix_up_and_push_path_tt(buf: &mut Vec>, subtree: tt char: ':', spacing: tt::Spacing::Alone, // FIXME + #[allow(deprecated)] span: S::DUMMY, }) .into(), diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs index 9331798589..ee9b2bf700 100644 --- a/crates/mbe/src/lib.rs +++ b/crates/mbe/src/lib.rs @@ -16,7 +16,6 @@ mod to_parser_input; #[cfg(test)] mod benchmark; -mod token_map; use stdx::impl_from; use tt::Span; @@ -30,15 +29,12 @@ use crate::{ // FIXME: we probably should re-think `token_tree_to_syntax_node` interfaces pub use ::parser::TopEntryPoint; -pub use tt::{Delimiter, DelimiterKind, Punct, SyntaxContext}; +pub use tt::{Delimiter, DelimiterKind, Punct}; -pub use crate::{ - syntax_bridge::{ - parse_exprs_with_sep, parse_to_token_tree, parse_to_token_tree_static_span, - syntax_node_to_token_tree, syntax_node_to_token_tree_modified, token_tree_to_syntax_node, - SpanMapper, - }, - token_map::SpanMap, +pub use crate::syntax_bridge::{ + parse_exprs_with_sep, parse_to_token_tree, parse_to_token_tree_static_span, + syntax_node_to_token_tree, syntax_node_to_token_tree_modified, token_tree_to_syntax_node, + SpanMapper, }; pub use crate::syntax_bridge::dummy_test_span_utils::*; diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index b89bfd74a6..3440c1dd8c 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -1,6 +1,7 @@ //! Conversions between [`SyntaxNode`] and [`tt::TokenTree`]. use rustc_hash::{FxHashMap, FxHashSet}; +use span::{SpanAnchor, SpanData, SpanMap}; use stdx::{never, non_empty_vec::NonEmptyVec}; use syntax::{ ast::{self, make::tokens::doc_comment}, @@ -10,10 +11,10 @@ use syntax::{ }; use tt::{ buffer::{Cursor, TokenBuffer}, - Span, SpanData, SyntaxContext, + Span, SyntaxContext, }; -use crate::{to_parser_input::to_parser_input, tt_iter::TtIter, SpanMap}; +use crate::{to_parser_input::to_parser_input, tt_iter::TtIter}; #[cfg(test)] mod tests; @@ -36,16 +37,20 @@ impl> SpanMapper for &SM { /// Dummy things for testing where spans don't matter. pub(crate) mod dummy_test_span_utils { + use tt::SyntaxContext; + use super::*; - pub type DummyTestSpanData = tt::SpanData; - pub const DUMMY: DummyTestSpanData = DummyTestSpanData::DUMMY; + pub type DummyTestSpanData = span::SpanData; + pub const DUMMY: DummyTestSpanData = span::SpanData { + range: TextRange::empty(TextSize::new(0)), + anchor: span::SpanAnchor { + file_id: span::FileId::BOGUS, + ast_id: span::ROOT_ERASED_FILE_AST_ID, + }, + ctx: DummyTestSyntaxContext, + }; - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] - pub struct DummyTestSpanAnchor; - impl tt::SpanAnchor for DummyTestSpanAnchor { - const DUMMY: Self = DummyTestSpanAnchor; - } #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct DummyTestSyntaxContext; impl SyntaxContext for DummyTestSyntaxContext { @@ -54,27 +59,30 @@ pub(crate) mod dummy_test_span_utils { pub struct DummyTestSpanMap; - impl SpanMapper> for DummyTestSpanMap { - fn span_for( - &self, - range: syntax::TextRange, - ) -> tt::SpanData { - tt::SpanData { range, anchor: DummyTestSpanAnchor, ctx: DummyTestSyntaxContext } + impl SpanMapper> for DummyTestSpanMap { + fn span_for(&self, range: syntax::TextRange) -> span::SpanData { + span::SpanData { + range, + anchor: span::SpanAnchor { + file_id: span::FileId::BOGUS, + ast_id: span::ROOT_ERASED_FILE_AST_ID, + }, + ctx: DummyTestSyntaxContext, + } } } } /// Converts a syntax tree to a [`tt::Subtree`] using the provided span map to populate the /// subtree's spans. -pub fn syntax_node_to_token_tree( +pub fn syntax_node_to_token_tree( node: &SyntaxNode, map: SpanMap, -) -> tt::Subtree> +) -> tt::Subtree> where - SpanData: Span, - Anchor: Copy, + SpanData: Span, Ctx: SyntaxContext, - SpanMap: SpanMapper>, + SpanMap: SpanMapper>, { let mut c = Converter::new(node, map, Default::default(), Default::default()); convert_tokens(&mut c) @@ -83,16 +91,15 @@ where /// Converts a syntax tree to a [`tt::Subtree`] using the provided span map to populate the /// subtree's spans. Additionally using the append and remove parameters, the additional tokens can /// be injected or hidden from the output. -pub fn syntax_node_to_token_tree_modified( +pub fn syntax_node_to_token_tree_modified( node: &SyntaxNode, map: SpanMap, - append: FxHashMap>>>, + append: FxHashMap>>>, remove: FxHashSet, -) -> tt::Subtree> +) -> tt::Subtree> where - SpanMap: SpanMapper>, - SpanData: Span, - Anchor: Copy, + SpanMap: SpanMapper>, + SpanData: Span, Ctx: SyntaxContext, { let mut c = Converter::new(node, map, append, remove); @@ -113,13 +120,12 @@ where /// Converts a [`tt::Subtree`] back to a [`SyntaxNode`]. /// The produced `SpanMap` contains a mapping from the syntax nodes offsets to the subtree's spans. -pub fn token_tree_to_syntax_node( - tt: &tt::Subtree>, +pub fn token_tree_to_syntax_node( + tt: &tt::Subtree>, entry_point: parser::TopEntryPoint, -) -> (Parse, SpanMap>) +) -> (Parse, SpanMap>) where - SpanData: Span, - Anchor: Copy, + SpanData: Span, Ctx: SyntaxContext, { let buffer = match tt { @@ -150,21 +156,20 @@ where /// Convert a string to a `TokenTree`. The spans of the subtree will be anchored to the provided /// anchor with the given context. -pub fn parse_to_token_tree( - anchor: Anchor, +pub fn parse_to_token_tree( + anchor: SpanAnchor, ctx: Ctx, text: &str, -) -> Option>> +) -> Option>> where - SpanData: Span, - Anchor: Copy, + SpanData: Span, Ctx: SyntaxContext, { let lexed = parser::LexedStr::new(text); if lexed.errors().next().is_some() { return None; } - let mut conv = RawConverter { lexed, pos: 0, anchor, ctx }; + let mut conv = RawConverter { lexed, anchor, pos: 0, ctx }; Some(convert_tokens(&mut conv)) } @@ -450,10 +455,10 @@ fn convert_doc_comment( } /// A raw token (straight from lexer) converter -struct RawConverter<'a, Anchor, Ctx> { +struct RawConverter<'a, Ctx> { lexed: parser::LexedStr<'a>, pos: usize, - anchor: Anchor, + anchor: SpanAnchor, ctx: Ctx, } /// A raw token (straight from lexer) converter that gives every token the same span. @@ -487,16 +492,16 @@ trait TokenConverter: Sized { fn span_for(&self, range: TextRange) -> S; } -impl SrcToken, S> for usize { - fn kind(&self, ctx: &RawConverter<'_, Anchor, Ctx>) -> SyntaxKind { +impl SrcToken, S> for usize { + fn kind(&self, ctx: &RawConverter<'_, Ctx>) -> SyntaxKind { ctx.lexed.kind(*self) } - fn to_char(&self, ctx: &RawConverter<'_, Anchor, Ctx>) -> Option { + fn to_char(&self, ctx: &RawConverter<'_, Ctx>) -> Option { ctx.lexed.text(*self).chars().next() } - fn to_text(&self, ctx: &RawConverter<'_, Anchor, Ctx>) -> SmolStr { + fn to_text(&self, ctx: &RawConverter<'_, Ctx>) -> SmolStr { ctx.lexed.text(*self).into() } } @@ -515,18 +520,17 @@ impl SrcToken, S> for usize { } } -impl TokenConverter> - for RawConverter<'_, Anchor, Ctx> +impl TokenConverter> for RawConverter<'_, Ctx> where - SpanData: Span, + SpanData: Span, { type Token = usize; fn convert_doc_comment( &self, &token: &usize, - span: SpanData, - ) -> Option>>> { + span: SpanData, + ) -> Option>>> { let text = self.lexed.text(token); convert_doc_comment(&doc_comment(text), span) } @@ -550,7 +554,7 @@ where Some(self.pos) } - fn span_for(&self, range: TextRange) -> SpanData { + fn span_for(&self, range: TextRange) -> SpanData { SpanData { range, anchor: self.anchor, ctx: self.ctx } } } @@ -778,22 +782,22 @@ where } } -struct TtTreeSink<'a, Anchor, Ctx> +struct TtTreeSink<'a, Ctx> where - SpanData: Span, + SpanData: Span, { buf: String, - cursor: Cursor<'a, SpanData>, + cursor: Cursor<'a, SpanData>, text_pos: TextSize, inner: SyntaxTreeBuilder, - token_map: SpanMap>, + token_map: SpanMap>, } -impl<'a, Anchor, Ctx> TtTreeSink<'a, Anchor, Ctx> +impl<'a, Ctx> TtTreeSink<'a, Ctx> where - SpanData: Span, + SpanData: Span, { - fn new(cursor: Cursor<'a, SpanData>) -> Self { + fn new(cursor: Cursor<'a, SpanData>) -> Self { TtTreeSink { buf: String::new(), cursor, @@ -803,7 +807,7 @@ where } } - fn finish(mut self) -> (Parse, SpanMap>) { + fn finish(mut self) -> (Parse, SpanMap>) { self.token_map.finish(); (self.inner.finish(), self.token_map) } @@ -821,9 +825,9 @@ fn delim_to_str(d: tt::DelimiterKind, closing: bool) -> Option<&'static str> { Some(&texts[idx..texts.len() - (1 - idx)]) } -impl TtTreeSink<'_, Anchor, Ctx> +impl TtTreeSink<'_, Ctx> where - SpanData: Span, + SpanData: Span, { /// Parses a float literal as if it was a one to two name ref nodes with a dot inbetween. /// This occurs when a float literal is used as a field access. diff --git a/crates/proc-macro-api/Cargo.toml b/crates/proc-macro-api/Cargo.toml index 2cbbc9489a..209cbb945d 100644 --- a/crates/proc-macro-api/Cargo.toml +++ b/crates/proc-macro-api/Cargo.toml @@ -33,6 +33,7 @@ tt.workspace = true stdx.workspace = true profile.workspace = true text-size.workspace = true +span.workspace = true # Ideally this crate would not depend on salsa things, but we need span information here which wraps # InternIds for the syntax context base-db.workspace = true diff --git a/crates/proc-macro-api/src/lib.rs b/crates/proc-macro-api/src/lib.rs index f697ecd351..a5d4cfeb27 100644 --- a/crates/proc-macro-api/src/lib.rs +++ b/crates/proc-macro-api/src/lib.rs @@ -11,9 +11,9 @@ pub mod msg; mod process; mod version; -use base_db::span::SpanData; use indexmap::IndexSet; use paths::AbsPathBuf; +use span::Span; use std::{fmt, io, sync::Mutex}; use triomphe::Arc; @@ -136,13 +136,13 @@ impl ProcMacro { pub fn expand( &self, - subtree: &tt::Subtree, - attr: Option<&tt::Subtree>, + subtree: &tt::Subtree, + attr: Option<&tt::Subtree>, env: Vec<(String, String)>, - def_site: SpanData, - call_site: SpanData, - mixed_site: SpanData, - ) -> Result, PanicMessage>, ServerError> { + def_site: Span, + call_site: Span, + mixed_site: Span, + ) -> Result, PanicMessage>, ServerError> { let version = self.process.lock().unwrap_or_else(|e| e.into_inner()).version(); let current_dir = env .iter() diff --git a/crates/proc-macro-api/src/msg.rs b/crates/proc-macro-api/src/msg.rs index 1d3e45aff3..18fd9ed728 100644 --- a/crates/proc-macro-api/src/msg.rs +++ b/crates/proc-macro-api/src/msg.rs @@ -136,29 +136,27 @@ fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { #[cfg(test)] mod tests { - use base_db::{ - span::{ErasedFileAstId, SpanAnchor, SpanData, SyntaxContextId}, - FileId, - }; + use base_db::FileId; use la_arena::RawIdx; + use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId}; use text_size::{TextRange, TextSize}; use tt::{Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, Subtree, TokenTree}; use super::*; - fn fixture_token_tree() -> Subtree { + fn fixture_token_tree() -> Subtree { let anchor = SpanAnchor { file_id: FileId::from_raw(0), ast_id: ErasedFileAstId::from_raw(RawIdx::from(0)), }; let mut subtree = Subtree { delimiter: Delimiter { - open: SpanData { + open: Span { range: TextRange::empty(TextSize::new(0)), anchor, ctx: SyntaxContextId::ROOT, }, - close: SpanData { + close: Span { range: TextRange::empty(TextSize::new(13)), anchor, ctx: SyntaxContextId::ROOT, @@ -170,7 +168,7 @@ mod tests { subtree.token_trees.push(TokenTree::Leaf( Ident { text: "struct".into(), - span: SpanData { + span: Span { range: TextRange::at(TextSize::new(0), TextSize::of("struct")), anchor, ctx: SyntaxContextId::ROOT, @@ -181,7 +179,7 @@ mod tests { subtree.token_trees.push(TokenTree::Leaf( Ident { text: "Foo".into(), - span: SpanData { + span: Span { range: TextRange::at(TextSize::new(5), TextSize::of("Foo")), anchor, ctx: SyntaxContextId::ROOT, @@ -192,7 +190,7 @@ mod tests { subtree.token_trees.push(TokenTree::Leaf(Leaf::Literal(Literal { text: "Foo".into(), - span: SpanData { + span: Span { range: TextRange::at(TextSize::new(8), TextSize::of("Foo")), anchor, ctx: SyntaxContextId::ROOT, @@ -200,7 +198,7 @@ mod tests { }))); subtree.token_trees.push(TokenTree::Leaf(Leaf::Punct(Punct { char: '@', - span: SpanData { + span: Span { range: TextRange::at(TextSize::new(11), TextSize::of('@')), anchor, ctx: SyntaxContextId::ROOT, @@ -209,12 +207,12 @@ mod tests { }))); subtree.token_trees.push(TokenTree::Subtree(Subtree { delimiter: Delimiter { - open: SpanData { + open: Span { range: TextRange::at(TextSize::new(12), TextSize::of('{')), anchor, ctx: SyntaxContextId::ROOT, }, - close: SpanData { + close: Span { range: TextRange::at(TextSize::new(13), TextSize::of('}')), anchor, ctx: SyntaxContextId::ROOT, diff --git a/crates/proc-macro-api/src/msg/flat.rs b/crates/proc-macro-api/src/msg/flat.rs index 5835718628..12c0daa7e4 100644 --- a/crates/proc-macro-api/src/msg/flat.rs +++ b/crates/proc-macro-api/src/msg/flat.rs @@ -37,13 +37,13 @@ use std::collections::{HashMap, VecDeque}; -use base_db::span::SpanData; use indexmap::IndexSet; use serde::{Deserialize, Serialize}; +use span::Span; use crate::msg::ENCODE_CLOSE_SPAN_VERSION; -type SpanDataIndexMap = IndexSet; +type SpanIndexMap = IndexSet; #[derive(Clone, Copy, PartialEq, Eq, Hash)] pub struct TokenId(pub u32); @@ -93,9 +93,9 @@ struct IdentRepr { impl FlatTree { pub fn new( - subtree: &tt::Subtree, + subtree: &tt::Subtree, version: u32, - span_data_table: &mut SpanDataIndexMap, + span_data_table: &mut SpanIndexMap, ) -> FlatTree { let mut w = Writer { string_table: HashMap::new(), @@ -157,8 +157,8 @@ impl FlatTree { pub fn to_subtree_resolved( self, version: u32, - span_data_table: &SpanDataIndexMap, - ) -> tt::Subtree { + span_data_table: &SpanIndexMap, + ) -> tt::Subtree { Reader { subtree: if version >= ENCODE_CLOSE_SPAN_VERSION { read_vec(self.subtree, SubtreeRepr::read_with_close_span) @@ -281,13 +281,13 @@ impl IdentRepr { } } -trait Span: Copy { +trait InternableSpan: Copy { type Table; fn token_id_of(table: &mut Self::Table, s: Self) -> TokenId; fn span_for_token_id(table: &Self::Table, id: TokenId) -> Self; } -impl Span for TokenId { +impl InternableSpan for TokenId { type Table = (); fn token_id_of((): &mut Self::Table, token_id: Self) -> TokenId { token_id @@ -297,8 +297,8 @@ impl Span for TokenId { id } } -impl Span for SpanData { - type Table = IndexSet; +impl InternableSpan for Span { + type Table = IndexSet; fn token_id_of(table: &mut Self::Table, span: Self) -> TokenId { TokenId(table.insert_full(span).0 as u32) } @@ -307,7 +307,7 @@ impl Span for SpanData { } } -struct Writer<'a, 'span, S: Span> { +struct Writer<'a, 'span, S: InternableSpan> { work: VecDeque<(usize, &'a tt::Subtree)>, string_table: HashMap<&'a str, u32>, span_data_table: &'span mut S::Table, @@ -320,7 +320,7 @@ struct Writer<'a, 'span, S: Span> { text: Vec, } -impl<'a, 'span, S: Span> Writer<'a, 'span, S> { +impl<'a, 'span, S: InternableSpan> Writer<'a, 'span, S> { fn write(&mut self, root: &'a tt::Subtree) { self.enqueue(root); while let Some((idx, subtree)) = self.work.pop_front() { @@ -393,7 +393,7 @@ impl<'a, 'span, S: Span> Writer<'a, 'span, S> { } } -struct Reader<'span, S: Span> { +struct Reader<'span, S: InternableSpan> { subtree: Vec, literal: Vec, punct: Vec, @@ -403,7 +403,7 @@ struct Reader<'span, S: Span> { span_data_table: &'span S::Table, } -impl<'span, S: Span> Reader<'span, S> { +impl<'span, S: InternableSpan> Reader<'span, S> { pub(crate) fn read(self) -> tt::Subtree { let mut res: Vec>> = vec![None; self.subtree.len()]; let read_span = |id| S::span_for_token_id(self.span_data_table, id); diff --git a/crates/span/Cargo.toml b/crates/span/Cargo.toml new file mode 100644 index 0000000000..8b078f9df1 --- /dev/null +++ b/crates/span/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "span" +version = "0.0.0" +rust-version.workspace = true +edition.workspace = true +license.workspace = true +authors.workspace = true + + +[dependencies] +la-arena.workspace = true +rust-analyzer-salsa.workspace = true + + +# local deps +vfs.workspace = true +syntax.workspace = true +stdx.workspace = true diff --git a/crates/base-db/src/span.rs b/crates/span/src/lib.rs similarity index 77% rename from crates/base-db/src/span.rs rename to crates/span/src/lib.rs index d8990eb7ca..d9f20e18c4 100644 --- a/crates/base-db/src/span.rs +++ b/crates/span/src/lib.rs @@ -1,10 +1,28 @@ //! File and span related types. -// FIXME: This should probably be moved into its own crate. +// FIXME: This should be moved into its own crate to get rid of the dependency inversion, base-db +// has business depending on tt, tt should depend on a span crate only (which unforunately will have +// to depend on salsa) use std::fmt; use salsa::InternId; -use tt::SyntaxContext; -use vfs::FileId; + +mod map; + +pub use crate::map::{RealSpanMap, SpanMap}; +pub use syntax::{TextRange, TextSize}; +pub use vfs::FileId; + +#[derive(Clone, Copy, Debug)] +pub struct FilePosition { + pub file_id: FileId, + pub offset: TextSize, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub struct FileRange { + pub file_id: FileId, + pub range: TextRange, +} pub type ErasedFileAstId = la_arena::Idx; @@ -12,7 +30,26 @@ pub type ErasedFileAstId = la_arena::Idx; pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId = la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(0)); -pub type SpanData = tt::SpanData; +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct SpanData { + /// The text range of this span, relative to the anchor. + /// We need the anchor for incrementality, as storing absolute ranges will require + /// recomputation on every change in a file at all times. + pub range: TextRange, + pub anchor: SpanAnchor, + /// The syntax context of the span. + pub ctx: Ctx, +} +impl Span { + #[deprecated = "dummy spans will panic if surfaced incorrectly, as such they should be replaced appropriately"] + pub const DUMMY: Self = SpanData { + range: TextRange::empty(TextSize::new(0)), + anchor: SpanAnchor { file_id: FileId::BOGUS, ast_id: ROOT_ERASED_FILE_AST_ID }, + ctx: SyntaxContextId::ROOT, + }; +} + +pub type Span = SpanData; #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct SyntaxContextId(InternId); @@ -33,7 +70,15 @@ impl fmt::Debug for SyntaxContextId { } } } -crate::impl_intern_key!(SyntaxContextId); + +impl salsa::InternKey for SyntaxContextId { + fn from_intern_id(v: salsa::InternId) -> Self { + SyntaxContextId(v) + } + fn as_intern_id(&self) -> salsa::InternId { + self.0 + } +} impl fmt::Display for SyntaxContextId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -41,9 +86,6 @@ impl fmt::Display for SyntaxContextId { } } -impl SyntaxContext for SyntaxContextId { - const DUMMY: Self = Self::ROOT; -} // inherent trait impls please tyvm impl SyntaxContextId { pub const ROOT: Self = SyntaxContextId(unsafe { InternId::new_unchecked(0) }); @@ -69,10 +111,6 @@ impl fmt::Debug for SpanAnchor { } } -impl tt::SpanAnchor for SpanAnchor { - const DUMMY: Self = SpanAnchor { file_id: FileId::BOGUS, ast_id: ROOT_ERASED_FILE_AST_ID }; -} - /// Input to the analyzer is a set of files, where each file is identified by /// `FileId` and contains source code. However, another source of source code in /// Rust are macros: each macro can be thought of as producing a "temporary @@ -90,6 +128,7 @@ impl tt::SpanAnchor for SpanAnchor { /// The two variants are encoded in a single u32 which are differentiated by the MSB. /// If the MSB is 0, the value represents a `FileId`, otherwise the remaining 31 bits represent a /// `MacroCallId`. +// FIXME: Give this a better fitting name #[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct HirFileId(u32); @@ -120,7 +159,15 @@ pub struct MacroFileId { /// `println!("Hello, {}", world)`. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct MacroCallId(salsa::InternId); -crate::impl_intern_key!(MacroCallId); + +impl salsa::InternKey for MacroCallId { + fn from_intern_id(v: salsa::InternId) -> Self { + MacroCallId(v) + } + fn as_intern_id(&self) -> salsa::InternId { + self.0 + } +} impl MacroCallId { pub fn as_file(self) -> HirFileId { diff --git a/crates/mbe/src/token_map.rs b/crates/span/src/map.rs similarity index 59% rename from crates/mbe/src/token_map.rs rename to crates/span/src/map.rs index 7d15812f8c..d69df91b63 100644 --- a/crates/mbe/src/token_map.rs +++ b/crates/span/src/map.rs @@ -1,18 +1,23 @@ -//! Mapping between `TokenId`s and the token's position in macro definitions or inputs. +//! A map that maps a span to every position in a file. Usually maps a span to some range of positions. +//! Allows bidirectional lookup. use std::hash::Hash; use stdx::{always, itertools::Itertools}; use syntax::{TextRange, TextSize}; -use tt::Span; +use vfs::FileId; + +use crate::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID}; /// Maps absolute text ranges for the corresponding file to the relevant span data. #[derive(Debug, PartialEq, Eq, Clone, Hash)] -pub struct SpanMap { +pub struct SpanMap { spans: Vec<(TextSize, S)>, + // FIXME: Should be + // spans: Vec<(TextSize, crate::SyntaxContextId)>, } -impl SpanMap { +impl SpanMap { /// Creates a new empty [`SpanMap`]. pub fn empty() -> Self { Self { spans: Vec::new() } @@ -44,7 +49,10 @@ impl SpanMap { /// Returns all [`TextRange`]s that correspond to the given span. /// /// Note this does a linear search through the entire backing vector. - pub fn ranges_with_span(&self, span: S) -> impl Iterator + '_ { + pub fn ranges_with_span(&self, span: S) -> impl Iterator + '_ + where + S: Eq, + { // FIXME: This should ignore the syntax context! self.spans.iter().enumerate().filter_map(move |(idx, &(end, s))| { if s != span { @@ -74,3 +82,50 @@ impl SpanMap { self.spans.iter().copied() } } + +#[derive(PartialEq, Eq, Hash, Debug)] +pub struct RealSpanMap { + file_id: FileId, + /// Invariant: Sorted vec over TextSize + // FIXME: SortedVec<(TextSize, ErasedFileAstId)>? + pairs: Box<[(TextSize, ErasedFileAstId)]>, + end: TextSize, +} + +impl RealSpanMap { + /// Creates a real file span map that returns absolute ranges (relative ranges to the root ast id). + pub fn absolute(file_id: FileId) -> Self { + RealSpanMap { + file_id, + pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]), + end: TextSize::new(!0), + } + } + + pub fn from_file( + file_id: FileId, + pairs: Box<[(TextSize, ErasedFileAstId)]>, + end: TextSize, + ) -> Self { + Self { file_id, pairs, end } + } + + pub fn span_for_range(&self, range: TextRange) -> Span { + assert!( + range.end() <= self.end, + "range {range:?} goes beyond the end of the file {:?}", + self.end + ); + let start = range.start(); + let idx = self + .pairs + .binary_search_by(|&(it, _)| it.cmp(&start).then(std::cmp::Ordering::Less)) + .unwrap_err(); + let (offset, ast_id) = self.pairs[idx - 1]; + Span { + range: range - offset, + anchor: SpanAnchor { file_id: self.file_id, ast_id }, + ctx: SyntaxContextId::ROOT, + } + } +} diff --git a/crates/tt/Cargo.toml b/crates/tt/Cargo.toml index 5722244979..e2c0f7d9c7 100644 --- a/crates/tt/Cargo.toml +++ b/crates/tt/Cargo.toml @@ -16,3 +16,6 @@ smol_str.workspace = true text-size.workspace = true stdx.workspace = true + +# FIXME: Remove this dependency once the `Span` trait is gone (that is once Span::DUMMY has been removed) +span.workspace = true diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs index 481d575403..70843f0032 100644 --- a/crates/tt/src/lib.rs +++ b/crates/tt/src/lib.rs @@ -11,47 +11,35 @@ use stdx::impl_from; pub use smol_str::SmolStr; pub use text_size::{TextRange, TextSize}; -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] -pub struct SpanData { - /// The text range of this span, relative to the anchor. - /// We need the anchor for incrementality, as storing absolute ranges will require - /// recomputation on every change in a file at all times. - pub range: TextRange, - pub anchor: Anchor, - /// The syntax context of the span. - pub ctx: Ctx, -} - -impl Span for SpanData { - #[allow(deprecated)] - const DUMMY: Self = SpanData { - range: TextRange::empty(TextSize::new(0)), - anchor: Anchor::DUMMY, - ctx: Ctx::DUMMY, - }; -} - pub trait Span: std::fmt::Debug + Copy + Sized + Eq { // FIXME: Should not exist. Dummy spans will always be wrong if they leak somewhere. Instead, // the call site or def site spans should be used in relevant places, its just that we don't // expose those everywhere in the yet. + #[deprecated = "dummy spans will panic if surfaced incorrectly, as such they should be replaced appropriately"] const DUMMY: Self; } -// FIXME: Should not exist -pub trait SpanAnchor: - std::fmt::Debug + Copy + Sized + Eq + Copy + fmt::Debug + std::hash::Hash -{ - #[deprecated(note = "this should not exist")] - const DUMMY: Self; -} - -// FIXME: Should not exist pub trait SyntaxContext: std::fmt::Debug + Copy + Sized + Eq { - #[deprecated(note = "this should not exist")] + #[deprecated = "dummy spans will panic if surfaced incorrectly, as such they should be replaced appropriately"] const DUMMY: Self; } +impl Span for span::SpanData { + #[allow(deprecated)] + const DUMMY: Self = span::SpanData { + range: TextRange::empty(TextSize::new(0)), + anchor: span::SpanAnchor { + file_id: span::FileId::BOGUS, + ast_id: span::ROOT_ERASED_FILE_AST_ID, + }, + ctx: Ctx::DUMMY, + }; +} + +impl SyntaxContext for span::SyntaxContextId { + const DUMMY: Self = Self::ROOT; +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TokenTree { Leaf(Leaf), @@ -136,6 +124,7 @@ pub struct DelimSpan { impl DelimSpan { // FIXME should not exist + #[allow(deprecated)] pub const DUMMY: Self = Self { open: S::DUMMY, close: S::DUMMY }; } @@ -148,6 +137,7 @@ pub struct Delimiter { impl Delimiter { // FIXME should not exist + #[allow(deprecated)] pub const DUMMY_INVISIBLE: Self = Self { open: S::DUMMY, close: S::DUMMY, kind: DelimiterKind::Invisible };