aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model')
-rw-r--r--crates/ra_hir/src/code_model/docs.rs96
-rw-r--r--crates/ra_hir/src/code_model/src.rs110
2 files changed, 206 insertions, 0 deletions
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs
new file mode 100644
index 000000000..da2b9b854
--- /dev/null
+++ b/crates/ra_hir/src/code_model/docs.rs
@@ -0,0 +1,96 @@
1use std::sync::Arc;
2
3use ra_syntax::ast;
4
5use crate::{
6 HirDatabase, DefDatabase, AstDatabase, HasSource,
7 Module, StructField, Struct, Enum, EnumVariant, Static, Const, Function, Union, Trait, TypeAlias, FieldSource, MacroDef,
8};
9
10#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
11pub enum DocDef {
12 Module(Module),
13 StructField(StructField),
14 Struct(Struct),
15 Enum(Enum),
16 EnumVariant(EnumVariant),
17 Static(Static),
18 Const(Const),
19 Function(Function),
20 Union(Union),
21 Trait(Trait),
22 TypeAlias(TypeAlias),
23 MacroDef(MacroDef),
24}
25
26impl_froms!(
27 DocDef: Module,
28 StructField,
29 Struct,
30 Enum,
31 EnumVariant,
32 Static,
33 Const,
34 Function,
35 Union,
36 Trait,
37 TypeAlias,
38 MacroDef
39);
40
41/// Holds documentation
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub struct Documentation(Arc<str>);
44
45impl Documentation {
46 fn new(s: &str) -> Documentation {
47 Documentation(s.into())
48 }
49
50 pub fn as_str(&self) -> &str {
51 &*self.0
52 }
53}
54
55impl Into<String> for Documentation {
56 fn into(self) -> String {
57 self.as_str().to_owned()
58 }
59}
60
61pub trait Docs {
62 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
63}
64
65pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
66 node.doc_comment_text().map(|it| Documentation::new(&it))
67}
68
69pub(crate) fn documentation_query(
70 db: &(impl DefDatabase + AstDatabase),
71 def: DocDef,
72) -> Option<Documentation> {
73 match def {
74 DocDef::Module(it) => docs_from_ast(&*it.declaration_source(db)?.ast),
75 DocDef::StructField(it) => match it.source(db).ast {
76 FieldSource::Named(named) => docs_from_ast(&*named),
77 FieldSource::Pos(..) => return None,
78 },
79 DocDef::Struct(it) => docs_from_ast(&*it.source(db).ast),
80 DocDef::Enum(it) => docs_from_ast(&*it.source(db).ast),
81 DocDef::EnumVariant(it) => docs_from_ast(&*it.source(db).ast),
82 DocDef::Static(it) => docs_from_ast(&*it.source(db).ast),
83 DocDef::Const(it) => docs_from_ast(&*it.source(db).ast),
84 DocDef::Function(it) => docs_from_ast(&*it.source(db).ast),
85 DocDef::Union(it) => docs_from_ast(&*it.source(db).ast),
86 DocDef::Trait(it) => docs_from_ast(&*it.source(db).ast),
87 DocDef::TypeAlias(it) => docs_from_ast(&*it.source(db).ast),
88 DocDef::MacroDef(it) => docs_from_ast(&*it.source(db).ast),
89 }
90}
91
92impl<T: Into<DocDef> + Copy> Docs for T {
93 fn docs(&self, db: &impl HirDatabase) -> Option<Documentation> {
94 db.documentation((*self).into())
95 }
96}
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
new file mode 100644
index 000000000..5785d3b26
--- /dev/null
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -0,0 +1,110 @@
1use ra_syntax::{TreeArc, ast};
2
3use crate::{
4 HirFileId, DefDatabase, AstDatabase, Module, ModuleSource,
5 StructField, Struct, Enum, Union, EnumVariant, Function, Static, Trait, Const, TypeAlias,
6 FieldSource, MacroDef, ids::AstItemDef,
7};
8
9pub struct Source<T> {
10 pub file_id: HirFileId,
11 pub ast: T,
12}
13
14pub trait HasSource {
15 type Ast;
16 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>;
17}
18
19/// NB: Module is !HasSource, because it has two source nodes at the same time:
20/// definition and declaration.
21impl Module {
22 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
23 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> {
24 let def_map = db.crate_def_map(self.krate);
25 let decl_id = def_map[self.module_id].declaration;
26 let file_id = def_map[self.module_id].definition;
27 let ast = ModuleSource::new(db, file_id, decl_id);
28 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
29 Source { file_id, ast }
30 }
31
32 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
33 /// `None` for the crate root.
34 pub fn declaration_source(
35 self,
36 db: &(impl DefDatabase + AstDatabase),
37 ) -> Option<Source<TreeArc<ast::Module>>> {
38 let def_map = db.crate_def_map(self.krate);
39 let decl = def_map[self.module_id].declaration?;
40 let ast = decl.to_node(db);
41 Some(Source { file_id: decl.file_id(), ast })
42 }
43}
44
45impl HasSource for StructField {
46 type Ast = FieldSource;
47 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
48 self.source_impl(db)
49 }
50}
51impl HasSource for Struct {
52 type Ast = TreeArc<ast::StructDef>;
53 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StructDef>> {
54 self.id.source(db)
55 }
56}
57impl HasSource for Union {
58 type Ast = TreeArc<ast::StructDef>;
59 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StructDef>> {
60 self.id.source(db)
61 }
62}
63impl HasSource for Enum {
64 type Ast = TreeArc<ast::EnumDef>;
65 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::EnumDef>> {
66 self.id.source(db)
67 }
68}
69impl HasSource for EnumVariant {
70 type Ast = TreeArc<ast::EnumVariant>;
71 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::EnumVariant>> {
72 self.source_impl(db)
73 }
74}
75impl HasSource for Function {
76 type Ast = TreeArc<ast::FnDef>;
77 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::FnDef>> {
78 self.id.source(db)
79 }
80}
81impl HasSource for Const {
82 type Ast = TreeArc<ast::ConstDef>;
83 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::ConstDef>> {
84 self.id.source(db)
85 }
86}
87impl HasSource for Static {
88 type Ast = TreeArc<ast::StaticDef>;
89 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StaticDef>> {
90 self.id.source(db)
91 }
92}
93impl HasSource for Trait {
94 type Ast = TreeArc<ast::TraitDef>;
95 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::TraitDef>> {
96 self.id.source(db)
97 }
98}
99impl HasSource for TypeAlias {
100 type Ast = TreeArc<ast::TypeAliasDef>;
101 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::TypeAliasDef>> {
102 self.id.source(db)
103 }
104}
105impl HasSource for MacroDef {
106 type Ast = TreeArc<ast::MacroCall>;
107 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::MacroCall>> {
108 Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) }
109 }
110}