1 //! Diagnostics produced by `hir_def`.
6 use cfg::{CfgExpr, CfgOptions, DnfExpr};
7 use hir_expand::diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSink};
8 use hir_expand::{HirFileId, InFile};
9 use syntax::{ast, AstPtr, SyntaxNodePtr, TextRange};
11 use crate::{db::DefDatabase, DefWithBodyId};
13 pub fn validate_body(db: &dyn DefDatabase, owner: DefWithBodyId, sink: &mut DiagnosticSink<'_>) {
14 let source_map = db.body_with_source_map(owner).1;
15 source_map.add_diagnostics(db, sink);
18 // Diagnostic: unresolved-module
20 // This diagnostic is triggered if rust-analyzer is unable to discover referred module.
22 pub struct UnresolvedModule {
24 pub decl: AstPtr<ast::Module>,
25 pub candidate: String,
28 impl Diagnostic for UnresolvedModule {
29 fn code(&self) -> DiagnosticCode {
30 DiagnosticCode("unresolved-module")
32 fn message(&self) -> String {
33 "unresolved module".to_string()
35 fn display_source(&self) -> InFile<SyntaxNodePtr> {
36 InFile::new(self.file, self.decl.clone().into())
38 fn as_any(&self) -> &(dyn Any + Send + 'static) {
43 // Diagnostic: unresolved-extern-crate
45 // This diagnostic is triggered if rust-analyzer is unable to discover referred extern crate.
47 pub struct UnresolvedExternCrate {
49 pub item: AstPtr<ast::ExternCrate>,
52 impl Diagnostic for UnresolvedExternCrate {
53 fn code(&self) -> DiagnosticCode {
54 DiagnosticCode("unresolved-extern-crate")
56 fn message(&self) -> String {
57 "unresolved extern crate".to_string()
59 fn display_source(&self) -> InFile<SyntaxNodePtr> {
60 InFile::new(self.file, self.item.clone().into())
62 fn as_any(&self) -> &(dyn Any + Send + 'static) {
67 // Diagnostic: unresolved-import
69 // This diagnostic is triggered if rust-analyzer is unable to discover imported module.
71 pub struct UnresolvedImport {
73 pub node: AstPtr<ast::UseTree>,
76 impl Diagnostic for UnresolvedImport {
77 fn code(&self) -> DiagnosticCode {
78 DiagnosticCode("unresolved-import")
80 fn message(&self) -> String {
81 "unresolved import".to_string()
83 fn display_source(&self) -> InFile<SyntaxNodePtr> {
84 InFile::new(self.file, self.node.clone().into())
86 fn as_any(&self) -> &(dyn Any + Send + 'static) {
89 fn is_experimental(&self) -> bool {
90 // This currently results in false positives in the following cases:
91 // - `cfg_if!`-generated code in libstd (we don't load the sysroot correctly)
92 // - `core::arch` (we don't handle `#[path = "../<path>"]` correctly)
93 // - proc macros and/or proc macro generated code
98 // Diagnostic: inactive-code
100 // This diagnostic is shown for code with inactive `#[cfg]` attributes.
101 #[derive(Debug, Clone, Eq, PartialEq)]
102 pub struct InactiveCode {
104 pub node: SyntaxNodePtr,
106 pub opts: CfgOptions,
109 impl Diagnostic for InactiveCode {
110 fn code(&self) -> DiagnosticCode {
111 DiagnosticCode("inactive-code")
113 fn message(&self) -> String {
114 let inactive = DnfExpr::new(self.cfg.clone()).why_inactive(&self.opts);
115 let mut buf = "code is inactive due to #[cfg] directives".to_string();
117 if let Some(inactive) = inactive {
118 format_to!(buf, ": {}", inactive);
123 fn display_source(&self) -> InFile<SyntaxNodePtr> {
124 InFile::new(self.file, self.node.clone())
126 fn as_any(&self) -> &(dyn Any + Send + 'static) {
131 // Diagnostic: unresolved-proc-macro
133 // This diagnostic is shown when a procedural macro can not be found. This usually means that
134 // procedural macro support is simply disabled (and hence is only a weak hint instead of an error),
135 // but can also indicate project setup problems.
136 #[derive(Debug, Clone, Eq, PartialEq)]
137 pub struct UnresolvedProcMacro {
139 pub node: SyntaxNodePtr,
140 /// If the diagnostic can be pinpointed more accurately than via `node`, this is the `TextRange`
142 pub precise_location: Option<TextRange>,
143 pub macro_name: Option<String>,
146 impl Diagnostic for UnresolvedProcMacro {
147 fn code(&self) -> DiagnosticCode {
148 DiagnosticCode("unresolved-proc-macro")
151 fn message(&self) -> String {
152 match &self.macro_name {
153 Some(name) => format!("proc macro `{}` not expanded", name),
154 None => "proc macro not expanded".to_string(),
158 fn display_source(&self) -> InFile<SyntaxNodePtr> {
159 InFile::new(self.file, self.node.clone())
162 fn as_any(&self) -> &(dyn Any + Send + 'static) {
167 // Diagnostic: macro-error
169 // This diagnostic is shown for macro expansion errors.
170 #[derive(Debug, Clone, Eq, PartialEq)]
171 pub struct MacroError {
173 pub node: SyntaxNodePtr,
177 impl Diagnostic for MacroError {
178 fn code(&self) -> DiagnosticCode {
179 DiagnosticCode("macro-error")
181 fn message(&self) -> String {
184 fn display_source(&self) -> InFile<SyntaxNodePtr> {
185 InFile::new(self.file, self.node.clone())
187 fn as_any(&self) -> &(dyn Any + Send + 'static) {
190 fn is_experimental(&self) -> bool {
191 // Newly added and not very well-tested, might contain false positives.