aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/attr.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/attr.rs')
-rw-r--r--crates/ra_hir/src/attr.rs58
1 files changed, 58 insertions, 0 deletions
diff --git a/crates/ra_hir/src/attr.rs b/crates/ra_hir/src/attr.rs
new file mode 100644
index 000000000..19be6de32
--- /dev/null
+++ b/crates/ra_hir/src/attr.rs
@@ -0,0 +1,58 @@
1use mbe::ast_to_token_tree;
2use ra_syntax::{
3 ast::{self, AstNode},
4 SmolStr,
5};
6use tt::Subtree;
7
8use crate::{db::AstDatabase, path::Path, Source};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub(crate) struct Attr {
12 pub(crate) path: Path,
13 pub(crate) input: Option<AttrInput>,
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub enum AttrInput {
18 Literal(SmolStr),
19 TokenTree(Subtree),
20}
21
22impl Attr {
23 pub(crate) fn from_src(
24 Source { file_id, ast }: Source<ast::Attr>,
25 db: &impl AstDatabase,
26 ) -> Option<Attr> {
27 let path = Path::from_src(Source { file_id, ast: ast.path()? }, db)?;
28 let input = match ast.input() {
29 None => None,
30 Some(ast::AttrInput::Literal(lit)) => {
31 // FIXME: escape? raw string?
32 let value = lit.syntax().first_token()?.text().trim_matches('"').into();
33 Some(AttrInput::Literal(value))
34 }
35 Some(ast::AttrInput::TokenTree(tt)) => {
36 Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0))
37 }
38 };
39
40 Some(Attr { path, input })
41 }
42
43 pub(crate) fn is_simple_atom(&self, name: &str) -> bool {
44 // FIXME: Avoid cloning
45 self.path.as_ident().map_or(false, |s| s.to_string() == name)
46 }
47
48 pub(crate) fn as_cfg(&self) -> Option<&Subtree> {
49 if self.is_simple_atom("cfg") {
50 match &self.input {
51 Some(AttrInput::TokenTree(subtree)) => Some(subtree),
52 _ => None,
53 }
54 } else {
55 None
56 }
57 }
58}