Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: assoc method completion #578

Merged
merged 4 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions crates/mun_hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use crate::{
ArithOp, BinaryOp, Body, CmpOp, Expr, ExprId, ExprScopes, Literal, LogicOp, Ordering, Pat,
PatId, RecordLitField, Statement, UnaryOp,
},
ids::ItemLoc,
ids::{AssocItemId, ItemLoc},
in_file::InFile,
name::Name,
name_resolution::PerNs,
Expand Down Expand Up @@ -62,7 +62,7 @@ mod utils;

mod has_module;
mod item_scope;
mod method_resolution;
pub mod method_resolution;
#[cfg(test)]
mod mock;
mod package_defs;
Expand Down
20 changes: 20 additions & 0 deletions crates/mun_hir/src/semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@
HirDatabase, InFile, ModuleDef, Name, PatId, PerNs, Resolver, Ty, Visibility,
};

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PathResolution {
/// An item
Def(ModuleDef),
/// A local binding (only value namespace)
Local(Local),
SelfType(Impl),
}

/// The primary API to get semantic information, like types, from syntax trees.
/// Exposes the database it was created with through the `db` field.
pub struct Semantics<'db> {
Expand Down Expand Up @@ -147,6 +156,11 @@
});
InFile::new(file_id, node)
}

/// Resolves the specified `ast::Path`
pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
self.analyze(path.syntax()).resolve_path(self.db, path)
}
}

/// Returns the root node of the specified node.
Expand Down Expand Up @@ -201,6 +215,12 @@
pub(crate) id: ImplId,
}

impl From<ImplId> for Impl {
fn from(id: ImplId) -> Self {
Impl { id }
}

Check warning on line 221 in crates/mun_hir/src/semantics.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/semantics.rs#L219-L221

Added lines #L219 - L221 were not covered by tests
}

impl Impl {
pub fn self_ty(self, db: &dyn HirDatabase) -> Ty {
db.type_for_impl_self(self.id)
Expand Down
50 changes: 48 additions & 2 deletions crates/mun_hir/src/source_analyzer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
use crate::{
expr::{scope::LocalScopeId, BodySourceMap},
ids::DefWithBodyId,
resolver_for_scope, Body, ExprId, ExprScopes, HirDatabase, InFile, InferenceResult, Resolver,
Ty,
resolver_for_scope,
semantics::PathResolution,
Body, ExprId, ExprScopes, HirDatabase, InFile, InferenceResult, Path, Resolver, Struct, Ty,
TypeAlias, TypeNs,
};

/// A `SourceAnalyzer` is a wrapper which exposes the HIR API in terms of the
Expand Down Expand Up @@ -79,6 +81,22 @@
let sm = self.body_source_map.as_ref()?;
sm.node_expr(expr)
}

pub(crate) fn resolve_path(
&self,
db: &dyn HirDatabase,
path: &ast::Path,
) -> Option<PathResolution> {
let hir_path = Path::from_ast(path.clone())?;

// Case where path is a qualifier of another path, e.g. foo::bar::Baz where we
// are trying to resolve foo::bar.
if path.parent_path().is_some() {
return resolve_hir_path_qualifier(db, &self.resolver, &hir_path);
}

None

Check warning on line 98 in crates/mun_hir/src/source_analyzer.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/source_analyzer.rs#L96-L98

Added lines #L96 - L98 were not covered by tests
}
}

/// Returns the id of the scope that is active at the location of `node`.
Expand Down Expand Up @@ -173,3 +191,31 @@
})
.map(|(_ptr, scope)| *scope)
}

/// Resolves a path where we know it is a qualifier of another path.
fn resolve_hir_path_qualifier(
db: &dyn HirDatabase,
resolver: &Resolver,
path: &Path,
) -> Option<PathResolution> {
let (ty, _, remaining_idx) = resolver.resolve_path_as_type(db.upcast(), path)?;
let (ty, _unresolved) = match remaining_idx {
Some(remaining_idx) => {
if remaining_idx + 1 == path.segments.len() {
Some((ty, path.segments.last()))

Check warning on line 205 in crates/mun_hir/src/source_analyzer.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/source_analyzer.rs#L203-L205

Added lines #L203 - L205 were not covered by tests
} else {
None

Check warning on line 207 in crates/mun_hir/src/source_analyzer.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/source_analyzer.rs#L207

Added line #L207 was not covered by tests
}
}
None => Some((ty, None)),
}?;

Check warning on line 211 in crates/mun_hir/src/source_analyzer.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/source_analyzer.rs#L211

Added line #L211 was not covered by tests

let res = match ty {
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),

Check warning on line 214 in crates/mun_hir/src/source_analyzer.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/source_analyzer.rs#L214

Added line #L214 was not covered by tests
TypeNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
TypeNs::PrimitiveType(it) => PathResolution::Def(it.into()),

Check warning on line 217 in crates/mun_hir/src/source_analyzer.rs

View check run for this annotation

Codecov / codecov/patch

crates/mun_hir/src/source_analyzer.rs#L216-L217

Added lines #L216 - L217 were not covered by tests
};

Some(res)
}
2 changes: 1 addition & 1 deletion crates/mun_hir/src/ty/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ pub mod diagnostics {
};

#[derive(Debug, PartialEq, Eq, Clone)]
pub(crate) enum LowerDiagnostic {
pub enum LowerDiagnostic {
UnresolvedType { id: LocalTypeRefId },
TypeIsPrivate { id: LocalTypeRefId },
}
Expand Down
1 change: 1 addition & 0 deletions crates/mun_language_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ mun_test = { path = "../mun_test"}
insta = { workspace = true }
itertools = { workspace = true }
tempdir = { workspace = true }
text_trees = { workspace = true }
38 changes: 31 additions & 7 deletions crates/mun_language_server/src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,26 @@
//! completions.

mod context;
mod dot;
// mod dot;
mod item;
mod render;
mod unqualified_path;
// mod unqualified_path;

mod dot;
mod expr;
mod name_ref;
#[cfg(test)]
mod test_utils;

use context::CompletionContext;
use context::{
CompletionAnalysis, CompletionContext, DotAccess, NameRefContext, NameRefKind,
PathCompletionContext, PathExprContext, PathKind, Qualified,
};
pub use item::{CompletionItem, CompletionItemKind, CompletionKind};
use mun_hir::semantics::ScopeDef;

use crate::{
completion::render::{render_field, render_resolution, RenderContext},
completion::render::{render_field, render_fn, render_resolution, RenderContext},
db::AnalysisDatabase,
FilePosition,
};
Expand All @@ -36,11 +42,18 @@ use crate::{
/// complete the fields of `foo` and don't want the local variables of
/// the active scope.
pub(crate) fn completions(db: &AnalysisDatabase, position: FilePosition) -> Option<Completions> {
let context = CompletionContext::new(db, position)?;
let (context, analysis) = CompletionContext::new(db, position)?;

let mut result = Completions::default();
unqualified_path::complete_unqualified_path(&mut result, &context);
dot::complete_dot(&mut result, &context);

match analysis {
CompletionAnalysis::NameRef(name_ref_ctx) => {
name_ref::complete_name_ref(&mut result, &context, &name_ref_ctx);
}
}

// unqualified_path::complete_unqualified_path(&mut result, &context);
// dot::complete_dot(&mut result, &context);
Some(result)
}

Expand Down Expand Up @@ -80,4 +93,15 @@ impl Completions {
let item = render_field(RenderContext::new(ctx), field);
self.add(item);
}

fn add_function(
&mut self,
ctx: &CompletionContext<'_>,
func: mun_hir::Function,
local_name: Option<String>,
) {
if let Some(item) = render_fn(RenderContext::new(ctx), local_name, func) {
self.add(item);
}
}
}
146 changes: 0 additions & 146 deletions crates/mun_language_server/src/completion/context.rs

This file was deleted.

Loading
Loading