mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-03 07:04:49 +00:00
Implment include macro
This commit is contained in:
parent
d75577fcee
commit
0a06c7e6e6
4 changed files with 107 additions and 19 deletions
|
@ -5,8 +5,9 @@ use crate::{
|
||||||
name, AstId, CrateId, MacroDefId, MacroDefKind, TextUnit,
|
name, AstId, CrateId, MacroDefId, MacroDefKind, TextUnit,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{quote, LazyMacroId};
|
use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
|
use ra_db::{FileId, RelativePath};
|
||||||
use ra_parser::FragmentKind;
|
use ra_parser::FragmentKind;
|
||||||
|
|
||||||
macro_rules! register_builtin {
|
macro_rules! register_builtin {
|
||||||
|
@ -38,12 +39,14 @@ macro_rules! register_builtin {
|
||||||
impl EagerExpander {
|
impl EagerExpander {
|
||||||
pub fn expand(
|
pub fn expand(
|
||||||
&self,
|
&self,
|
||||||
|
db: &dyn AstDatabase,
|
||||||
|
arg_id: EagerMacroId,
|
||||||
tt: &tt::Subtree,
|
tt: &tt::Subtree,
|
||||||
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
|
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
|
||||||
let expander = match *self {
|
let expander = match *self {
|
||||||
$( EagerExpander::$e_kind => $e_expand, )*
|
$( EagerExpander::$e_kind => $e_expand, )*
|
||||||
};
|
};
|
||||||
expander(tt)
|
expander(db,arg_id,tt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +83,6 @@ pub fn find_builtin_macro(
|
||||||
|
|
||||||
register_builtin! {
|
register_builtin! {
|
||||||
LAZY:
|
LAZY:
|
||||||
|
|
||||||
(column, Column) => column_expand,
|
(column, Column) => column_expand,
|
||||||
(compile_error, CompileError) => compile_error_expand,
|
(compile_error, CompileError) => compile_error_expand,
|
||||||
(file, File) => file_expand,
|
(file, File) => file_expand,
|
||||||
|
@ -94,8 +96,8 @@ register_builtin! {
|
||||||
(format_args_nl, FormatArgsNl) => format_args_expand,
|
(format_args_nl, FormatArgsNl) => format_args_expand,
|
||||||
|
|
||||||
EAGER:
|
EAGER:
|
||||||
// eagers
|
(concat, Concat) => concat_expand,
|
||||||
(concat, Concat) => concat_expand
|
(include, Include) => include_expand
|
||||||
}
|
}
|
||||||
|
|
||||||
fn line_expand(
|
fn line_expand(
|
||||||
|
@ -251,7 +253,11 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
|
||||||
token.value()
|
token.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
|
fn concat_expand(
|
||||||
|
_db: &dyn AstDatabase,
|
||||||
|
_arg_id: EagerMacroId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
|
||||||
let mut text = String::new();
|
let mut text = String::new();
|
||||||
for (i, t) in tt.token_trees.iter().enumerate() {
|
for (i, t) in tt.token_trees.iter().enumerate() {
|
||||||
match t {
|
match t {
|
||||||
|
@ -266,6 +272,40 @@ fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::E
|
||||||
Ok((quote!(#text), FragmentKind::Expr))
|
Ok((quote!(#text), FragmentKind::Expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> {
|
||||||
|
let call_site = call_id.as_file().original_file(db);
|
||||||
|
let path = RelativePath::new(&path);
|
||||||
|
|
||||||
|
db.resolve_relative_path(call_site, &path)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn include_expand(
|
||||||
|
db: &dyn AstDatabase,
|
||||||
|
arg_id: EagerMacroId,
|
||||||
|
tt: &tt::Subtree,
|
||||||
|
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
|
||||||
|
let path = tt
|
||||||
|
.token_trees
|
||||||
|
.get(0)
|
||||||
|
.and_then(|tt| match tt {
|
||||||
|
tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(&it),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.ok_or_else(|| mbe::ExpandError::ConversionError)?;
|
||||||
|
|
||||||
|
let file_id =
|
||||||
|
relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?;
|
||||||
|
|
||||||
|
// FIXME:
|
||||||
|
// Handle include as expression
|
||||||
|
let node =
|
||||||
|
db.parse_or_expand(file_id.into()).ok_or_else(|| mbe::ExpandError::ConversionError)?;
|
||||||
|
let res =
|
||||||
|
mbe::syntax_node_to_token_tree(&node).ok_or_else(|| mbe::ExpandError::ConversionError)?.0;
|
||||||
|
|
||||||
|
Ok((res, FragmentKind::Items))
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -42,24 +42,26 @@ pub fn expand_eager_macro(
|
||||||
// When `lazy_expand` is called, its *parent* file must be already exists.
|
// When `lazy_expand` is called, its *parent* file must be already exists.
|
||||||
// Here we store an eager macro id for the argument expanded subtree here
|
// Here we store an eager macro id for the argument expanded subtree here
|
||||||
// for that purpose.
|
// for that purpose.
|
||||||
let arg_id: MacroCallId = db
|
let arg_id = db.intern_eager_expansion({
|
||||||
.intern_eager_expansion({
|
|
||||||
EagerCallLoc {
|
EagerCallLoc {
|
||||||
def,
|
def,
|
||||||
fragment: FragmentKind::Expr,
|
fragment: FragmentKind::Expr,
|
||||||
subtree: Arc::new(parsed_args.clone()),
|
subtree: Arc::new(parsed_args.clone()),
|
||||||
file_id: macro_call.file_id,
|
file_id: macro_call.file_id,
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
.into();
|
let arg_file_id: MacroCallId = arg_id.into();
|
||||||
|
|
||||||
let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0;
|
let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0;
|
||||||
let result =
|
let result = eager_macro_recur(
|
||||||
eager_macro_recur(db, InFile::new(arg_id.as_file(), parsed_args.syntax_node()), resolver)?;
|
db,
|
||||||
|
InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()),
|
||||||
|
resolver,
|
||||||
|
)?;
|
||||||
let subtree = to_subtree(&result)?;
|
let subtree = to_subtree(&result)?;
|
||||||
|
|
||||||
if let MacroDefKind::BuiltInEager(eager) = def.kind {
|
if let MacroDefKind::BuiltInEager(eager) = def.kind {
|
||||||
let (subtree, fragment) = eager.expand(&subtree).ok()?;
|
let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?;
|
||||||
let eager =
|
let eager =
|
||||||
EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id };
|
EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id };
|
||||||
|
|
||||||
|
|
|
@ -174,6 +174,7 @@ pub mod known {
|
||||||
line,
|
line,
|
||||||
stringify,
|
stringify,
|
||||||
concat,
|
concat,
|
||||||
|
include,
|
||||||
format_args,
|
format_args,
|
||||||
format_args_nl,
|
format_args_nl,
|
||||||
env,
|
env,
|
||||||
|
|
|
@ -438,6 +438,51 @@ fn main() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_builtin_macros_include() {
|
||||||
|
let (db, pos) = TestDB::with_position(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! include {() => {}}
|
||||||
|
|
||||||
|
include!("foo.rs");
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
bar()<|>;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /foo.rs
|
||||||
|
fn bar() -> u32 {0}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!("u32", type_at_pos(&db, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_builtin_macros_include_concat() {
|
||||||
|
let (db, pos) = TestDB::with_position(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! include {() => {}}
|
||||||
|
|
||||||
|
#[rustc_builtin_macro]
|
||||||
|
macro_rules! concat {() => {}}
|
||||||
|
|
||||||
|
include!(concat!("f", "oo.rs"));
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
bar()<|>;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /foo.rs
|
||||||
|
fn bar() -> u32 {0}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!("u32", type_at_pos(&db, pos));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_builtin_macros_concat_with_lazy() {
|
fn infer_builtin_macros_concat_with_lazy() {
|
||||||
assert_snapshot!(
|
assert_snapshot!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue