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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

For unresolved macros, hightlight only the last segment #7805

Merged
merged 1 commit into from Feb 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion crates/hir/src/diagnostics.rs
@@ -1,5 +1,7 @@
//! FIXME: write short doc here
pub use hir_def::diagnostics::{InactiveCode, UnresolvedModule, UnresolvedProcMacro};
pub use hir_def::diagnostics::{
InactiveCode, UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro,
};
pub use hir_expand::diagnostics::{
Diagnostic, DiagnosticCode, DiagnosticSink, DiagnosticSinkBuilder,
};
Expand Down
8 changes: 3 additions & 5 deletions crates/hir/src/semantics.rs
Expand Up @@ -16,13 +16,12 @@ use rustc_hash::{FxHashMap, FxHashSet};
use syntax::{
algo::find_node_at_offset,
ast::{self, GenericParamsOwner, LoopBodyOwner},
match_ast, AstNode, SyntaxNode, SyntaxToken, TextSize,
match_ast, AstNode, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize,
};

use crate::{
code_model::Access,
db::HirDatabase,
diagnostics::Diagnostic,
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
source_analyzer::{resolve_hir_path, SourceAnalyzer},
AssocItem, Callable, ConstParam, Crate, Field, Function, HirFileId, Impl, InFile, Label,
Expand Down Expand Up @@ -141,7 +140,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.original_range(node)
}

pub fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange {
pub fn diagnostics_display_range(&self, diagnostics: InFile<SyntaxNodePtr>) -> FileRange {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General code smell: if you need only a single thing, better to just require that single thing

self.imp.diagnostics_display_range(diagnostics)
}

Expand Down Expand Up @@ -385,8 +384,7 @@ impl<'db> SemanticsImpl<'db> {
node.as_ref().original_file_range(self.db.upcast())
}

fn diagnostics_display_range(&self, diagnostics: &dyn Diagnostic) -> FileRange {
let src = diagnostics.display_source();
fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange {
let root = self.db.parse_or_expand(src.file_id).unwrap();
let node = src.value.to_node(&root);
self.cache(root, src.file_id);
Expand Down
2 changes: 1 addition & 1 deletion crates/hir_def/src/body.rs
Expand Up @@ -123,7 +123,7 @@ impl Expander {
Some(it) => it,
None => {
if err.is_none() {
eprintln!("no error despite `as_call_id_with_errors` returning `None`");
log::warn!("no error despite `as_call_id_with_errors` returning `None`");
}
return ExpandResult { value: None, err };
}
Expand Down
28 changes: 28 additions & 0 deletions crates/hir_def/src/diagnostics.rs
Expand Up @@ -95,6 +95,34 @@ impl Diagnostic for UnresolvedImport {
}
}

// Diagnostic: unresolved-macro-call
//
// This diagnostic is triggered if rust-analyzer is unable to resolove path to a
// macro in a macro invocation.
#[derive(Debug)]
pub struct UnresolvedMacroCall {
pub file: HirFileId,
pub node: AstPtr<ast::MacroCall>,
}

impl Diagnostic for UnresolvedMacroCall {
fn code(&self) -> DiagnosticCode {
DiagnosticCode("unresolved-macro-call")
}
fn message(&self) -> String {
"unresolved macro call".to_string()
}
fn display_source(&self) -> InFile<SyntaxNodePtr> {
InFile::new(self.file, self.node.clone().into())
}
fn as_any(&self) -> &(dyn Any + Send + 'static) {
self
}
fn is_experimental(&self) -> bool {
true
}
}

// Diagnostic: inactive-code
//
// This diagnostic is shown for code with inactive `#[cfg]` attributes.
Expand Down
114 changes: 56 additions & 58 deletions crates/hir_def/src/lib.rs
Expand Up @@ -57,8 +57,10 @@ use std::{

use base_db::{impl_intern_key, salsa, CrateId};
use hir_expand::{
ast_id_map::FileAstId, eager::expand_eager_macro, hygiene::Hygiene, AstId, HirFileId, InFile,
MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
ast_id_map::FileAstId,
eager::{expand_eager_macro, ErrorEmitted},
hygiene::Hygiene,
AstId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
};
use la_arena::Idx;
use nameres::DefMap;
Expand Down Expand Up @@ -592,8 +594,15 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
error_sink(mbe::ExpandError::Other("malformed macro invocation".into()));
}

AstIdWithPath::new(ast_id.file_id, ast_id.value, path?)
.as_call_id_with_errors(db, krate, resolver, error_sink)
macro_call_as_call_id(
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path?),
db,
krate,
resolver,
error_sink,
)
.ok()?
.ok()
}
}

Expand All @@ -610,61 +619,50 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
}
}

impl AsMacroCall for AstIdWithPath<ast::MacroCall> {
fn as_call_id_with_errors(
&self,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
error_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Option<MacroCallId> {
let def: MacroDefId = resolver(self.path.clone()).or_else(|| {
error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path)));
None
})?;

if let MacroDefKind::BuiltInEager(_) = def.kind {
let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db.upcast()));
let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id);

Some(
expand_eager_macro(
db.upcast(),
krate,
macro_call,
def,
&|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
error_sink,
)
.ok()?
.into(),
)
} else {
Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
}
}
struct UnresolvedMacro;

fn macro_call_as_call_id(
call: &AstIdWithPath<ast::MacroCall>,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
error_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
let def: MacroDefId = resolver(call.path.clone()).ok_or(UnresolvedMacro)?;

let res = if let MacroDefKind::BuiltInEager(_) = def.kind {
let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db.upcast()));
let hygiene = Hygiene::new(db.upcast(), call.ast_id.file_id);

expand_eager_macro(
db.upcast(),
krate,
macro_call,
def,
&|path: ast::Path| resolver(path::ModPath::from_src(path, &hygiene)?),
error_sink,
)
.map(MacroCallId::from)
} else {
Ok(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(call.ast_id)).into())
};
Ok(res)
}

impl AsMacroCall for AstIdWithPath<ast::Item> {
fn as_call_id_with_errors(
&self,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
error_sink: &mut dyn FnMut(mbe::ExpandError),
) -> Option<MacroCallId> {
let def: MacroDefId = resolver(self.path.clone()).or_else(|| {
error_sink(mbe::ExpandError::Other(format!("could not resolve macro `{}`", self.path)));
None
})?;

Some(
def.as_lazy_macro(
db.upcast(),
krate,
MacroCallKind::Attr(self.ast_id, self.path.segments().last()?.to_string()),
)
.into(),
fn item_attr_as_call_id(
item_attr: &AstIdWithPath<ast::Item>,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
) -> Result<MacroCallId, UnresolvedMacro> {
let def: MacroDefId = resolver(item_attr.path.clone()).ok_or(UnresolvedMacro)?;
let last_segment = item_attr.path.segments().last().ok_or(UnresolvedMacro)?;
let res = def
.as_lazy_macro(
db.upcast(),
krate,
MacroCallKind::Attr(item_attr.ast_id, last_segment.to_string()),
)
}
.into();
Ok(res)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}
14 changes: 14 additions & 0 deletions crates/hir_def/src/nameres.rs
Expand Up @@ -417,6 +417,8 @@ mod diagnostics {

UnresolvedProcMacro { ast: MacroCallKind },

UnresolvedMacroCall { ast: AstId<ast::MacroCall> },

MacroError { ast: MacroCallKind, message: String },
}

Expand Down Expand Up @@ -477,6 +479,13 @@ mod diagnostics {
Self { in_module: container, kind: DiagnosticKind::MacroError { ast, message } }
}

pub(super) fn unresolved_macro_call(
container: LocalModuleId,
ast: AstId<ast::MacroCall>,
) -> Self {
Self { in_module: container, kind: DiagnosticKind::UnresolvedMacroCall { ast } }
}

pub(super) fn add_to(
&self,
db: &dyn DefDatabase,
Expand Down Expand Up @@ -589,6 +598,11 @@ mod diagnostics {
});
}

DiagnosticKind::UnresolvedMacroCall { ast } => {
let node = ast.to_node(db.upcast());
sink.push(UnresolvedMacroCall { file: ast.file_id, node: AstPtr::new(&node) });
}

DiagnosticKind::MacroError { ast, message } => {
let (file, ast) = match ast {
MacroCallKind::FnLike(ast) => {
Expand Down