Skip to content

Commit 3c46061

Browse files
committed
Add indexing for qualified imports
1 parent eac2b42 commit 3c46061

File tree

6 files changed

+107
-3
lines changed

6 files changed

+107
-3
lines changed

crates/indexing/src/algorithm.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use rowan::ast::AstChildren;
2-
use smol_str::SmolStr;
2+
use smol_str::{SmolStr, SmolStrBuilder};
33
use syntax::cst;
44

55
use crate::{
@@ -18,6 +18,12 @@ struct State {
1818
pub(super) fn index_module(module: &cst::Module) -> (IndexingResult, Vec<IndexingError>) {
1919
let mut state = State::default();
2020

21+
if let Some(imports) = module.imports() {
22+
for import in imports.children() {
23+
index_import(&mut state, import);
24+
}
25+
}
26+
2127
if let Some(statements) = module.statements() {
2228
for statement in statements.children() {
2329
index_statement(&mut state, statement);
@@ -30,6 +36,26 @@ pub(super) fn index_module(module: &cst::Module) -> (IndexingResult, Vec<Indexin
3036
(result, errors)
3137
}
3238

39+
fn index_import(state: &mut State, import: cst::ImportStatement) {
40+
let import_id = state.source_map.insert_import(&import);
41+
42+
let Some(import_alias) = import.import_alias() else { return };
43+
let Some(module_name) = import_alias.module_name() else { return };
44+
45+
let mut buffer = SmolStrBuilder::default();
46+
if let Some(qualifier) = module_name.qualifier() {
47+
if let Some(token) = qualifier.text() {
48+
buffer.push_str(token.text());
49+
}
50+
}
51+
52+
let Some(token) = module_name.name_token() else { return };
53+
buffer.push_str(token.text());
54+
55+
let name = buffer.finish();
56+
state.nominal.insert_qualified(name, import_id);
57+
}
58+
3359
fn index_statement(state: &mut State, declaration: cst::Declaration) {
3460
match declaration {
3561
cst::Declaration::ValueSignature(s) => {

crates/indexing/src/indexes.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use indexmap::IndexMap;
22
use smol_str::SmolStr;
33

4-
use crate::{id::Id, ClassMemberId, ConstructorId, DeclarationId, InstanceId, InstanceMemberId};
4+
use crate::{
5+
id::Id, ClassMemberId, ConstructorId, DeclarationId, ImportId, InstanceId, InstanceMemberId,
6+
};
57

68
/// A group of type signature and declaration.
79
#[derive(Debug, Default, PartialEq, Eq)]
@@ -129,13 +131,18 @@ pub enum TypeItem {
129131
/// [`SourceMap`]: crate::SourceMap
130132
#[derive(Default)]
131133
pub struct NominalIndex {
134+
qualified: IndexMap<SmolStr, Vec<ImportId>>,
132135
expr_item: IndexMap<SmolStr, ExprItem>,
133136
type_item: IndexMap<SmolStr, TypeItem>,
134137
}
135138

136139
pub(crate) type MutableItem<'t, T> = (&'t mut T, Id<T>);
137140

138141
impl NominalIndex {
142+
pub(crate) fn insert_qualified(&mut self, name: SmolStr, import: ImportId) {
143+
self.qualified.entry(name).or_default().push(import);
144+
}
145+
139146
pub(crate) fn expr_get_mut(&mut self, name: &str) -> Option<MutableItem<ExprItem>> {
140147
self.expr_item.get_full_mut(name).map(|(index, _, item)| (item, Id::from_raw(index)))
141148
}
@@ -164,6 +171,10 @@ impl NominalIndex {
164171
}
165172

166173
impl NominalIndex {
174+
pub fn lookup_qualified(&self, name: &str) -> Option<&[ImportId]> {
175+
self.qualified.get(name).map(|v| &v[..])
176+
}
177+
167178
pub fn lookup_expr_item(&self, name: &str) -> Option<(ExprItemId, &ExprItem)> {
168179
self.expr_item.get_full(name).map(|(id, _, item)| (Id::from_raw(id), item))
169180
}

crates/indexing/src/sourcemap.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ use syntax::cst;
55

66
use crate::id::Id;
77

8+
pub type ImportId = Id<cst::ImportStatement>;
9+
pub type ImportPtr = AstPtr<cst::ImportStatement>;
10+
811
pub type DeclarationId = Id<cst::Declaration>;
912
pub type DeclarationPtr = AstPtr<cst::Declaration>;
1013

@@ -64,6 +67,7 @@ pub type InstanceMemberPtr = AstPtr<cst::InstanceMemberStatement>;
6467
/// implementation works well enough for the general case.
6568
#[derive(Debug, Default)]
6669
pub struct SourceMap {
70+
imports: FxIndexSet<ImportPtr>,
6771
declaration: FxIndexSet<DeclarationPtr>,
6872
constructor: FxIndexSet<ConstructorPtr>,
6973
class_member: FxIndexSet<ClassMemberPtr>,
@@ -89,6 +93,10 @@ fn id<T: AstNode>(m: &FxIndexSet<AstPtr<T>>, ptr: AstPtr<T>) -> Option<Id<T>> {
8993
}
9094

9195
impl SourceMap {
96+
pub(crate) fn insert_import(&mut self, import: &cst::ImportStatement) -> ImportId {
97+
insert(&mut self.imports, import)
98+
}
99+
92100
pub(crate) fn insert_declaration(&mut self, declaration: &cst::Declaration) -> DeclarationId {
93101
insert(&mut self.declaration, declaration)
94102
}
@@ -120,6 +128,14 @@ impl SourceMap {
120128
}
121129

122130
impl SourceMap {
131+
pub fn import_ptr(&self, id: ImportId) -> Option<ImportPtr> {
132+
ptr(&self.imports, id)
133+
}
134+
135+
pub fn import_id(&self, ptr: ImportPtr) -> Option<ImportId> {
136+
id(&self.imports, ptr)
137+
}
138+
123139
pub fn declaration_ptr(&self, id: DeclarationId) -> Option<DeclarationPtr> {
124140
ptr(&self.declaration, id)
125141
}

crates/indexing/tests/indexing.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ fn index<'s>(lines: impl AsRef<[&'s str]>) -> (cst::Module, IndexingResult, Inde
2020
#[test]
2121
fn well_formed_module() {
2222
let (_, index, _) = index([
23+
"import Prelude as Prelude",
24+
"import Data.List as Data.List",
25+
"import Halogen as H",
26+
"import Halogen.HTML as H",
2327
"id :: forall a. a -> a",
2428
"id x = x",
2529
"data Maybe :: Type -> Type",
@@ -44,6 +48,9 @@ fn well_formed_module() {
4448
"infix 5 type Eq as ==",
4549
]);
4650

51+
let prelude = index.nominal.lookup_qualified("Prelude");
52+
let data_list = index.nominal.lookup_qualified("Data.List");
53+
let halogen = index.nominal.lookup_qualified("H");
4754
let id = index.nominal.lookup_expr_item("id");
4855
let maybe = index.nominal.lookup_type_item("Maybe");
4956
let just = index.nominal.lookup_expr_item("Just");
@@ -60,6 +67,9 @@ fn well_formed_module() {
6067
let type_equal = index.nominal.lookup_type_item("==");
6168

6269
let mut snapshot = String::new();
70+
writeln!(snapshot, "prelude: {:?}", prelude).unwrap();
71+
writeln!(snapshot, "data_list: {:?}", data_list).unwrap();
72+
writeln!(snapshot, "halogen: {:?}", halogen).unwrap();
6373
writeln!(snapshot, "id: {:?}", id).unwrap();
6474
writeln!(snapshot, "maybe: {:?}", maybe).unwrap();
6575
writeln!(snapshot, "just: {:?}", just).unwrap();

crates/indexing/tests/snapshots/indexing__well_formed_module.snap

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ source: crates/indexing/tests/indexing.rs
33
expression: snapshot
44
snapshot_kind: text
55
---
6+
prelude: Some([Id(0)])
7+
data_list: Some([Id(1)])
8+
halogen: Some([Id(2), Id(3)])
69
id: Some((Id(0), Value(ValueGroupId { signature: Some(Id(0)), equations: [Id(1)] })))
710
maybe: Some((Id(0), Data(TypeGroupId { signature: Some(Id(2)), declaration: Some(Id(3)), role: Some(Id(4)) })))
811
just: Some((Id(1), Constructor(Id(0))))

crates/syntax/src/cst.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,19 @@ use rowan::ast::AstNode;
33
#[macro_use]
44
mod macros;
55

6-
create_cst_struct!(Module, ModuleHeader, ExportList);
6+
create_cst_struct!(Annotation, Qualifier);
7+
8+
has_token!(
9+
Annotation
10+
| text() -> TEXT
11+
);
12+
13+
has_token!(
14+
Qualifier
15+
| text() -> TEXT
16+
);
17+
18+
create_cst_struct!(Module, ModuleHeader, ModuleName, ExportList);
719

820
create_cst_enum!(
921
ExportItem
@@ -171,9 +183,35 @@ create_cst_enum!(RecordUpdate | RecordUpdateLeaf | RecordUpdateBranch);
171183

172184
has_child!(
173185
Module
186+
| imports() -> ModuleImports
174187
| statements() -> ModuleStatements
175188
);
176189

190+
has_children!(
191+
ModuleImports
192+
| children() -> ImportStatement
193+
);
194+
195+
has_child!(
196+
ImportStatement
197+
| import_alias() -> ImportAlias
198+
);
199+
200+
has_child!(
201+
ImportAlias
202+
| module_name() -> ModuleName
203+
);
204+
205+
has_child!(
206+
ModuleName
207+
| qualifier() -> Qualifier
208+
);
209+
210+
has_token!(
211+
ModuleName
212+
| name_token() -> UPPER
213+
);
214+
177215
has_children!(
178216
ModuleStatements
179217
| children() -> Declaration

0 commit comments

Comments
 (0)