1use std::ops::Not;
4
5use cfg::{CfgExpr, CfgOptions};
6use hir_expand::{ErasedAstId, ExpandErrorKind, MacroCallKind, attrs::AttrId, mod_path::ModPath};
7use la_arena::Idx;
8use syntax::ast;
9
10use crate::{AstId, nameres::LocalModuleId};
11
12#[derive(Debug, PartialEq, Eq)]
13pub enum DefDiagnosticKind {
14 UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> },
15 UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
16 UnresolvedImport { id: AstId<ast::Use>, index: Idx<ast::UseTree> },
17 UnconfiguredCode { ast_id: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
18 UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
19 UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
20 InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
21 MalformedDerive { ast: AstId<ast::Adt>, id: usize },
22 MacroDefError { ast: AstId<ast::Macro>, message: String },
23 MacroError { ast: AstId<ast::Item>, path: ModPath, err: ExpandErrorKind },
24}
25
26#[derive(Clone, Debug, PartialEq, Eq)]
27pub struct DefDiagnostics(Option<triomphe::ThinArc<(), DefDiagnostic>>);
28
29impl DefDiagnostics {
30 pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self {
31 Self(
32 diagnostics
33 .is_empty()
34 .not()
35 .then(|| triomphe::ThinArc::from_header_and_iter((), diagnostics.into_iter())),
36 )
37 }
38
39 pub fn iter(&self) -> impl Iterator<Item = &DefDiagnostic> {
40 self.0.as_ref().into_iter().flat_map(|it| &it.slice)
41 }
42}
43
44#[derive(Debug, PartialEq, Eq)]
45pub struct DefDiagnostic {
46 pub in_module: LocalModuleId,
47 pub kind: DefDiagnosticKind,
48}
49
50impl DefDiagnostic {
51 pub(super) fn unresolved_module(
52 container: LocalModuleId,
53 declaration: AstId<ast::Module>,
54 candidates: Box<[String]>,
55 ) -> Self {
56 Self {
57 in_module: container,
58 kind: DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates },
59 }
60 }
61
62 pub(super) fn unresolved_extern_crate(
63 container: LocalModuleId,
64 declaration: AstId<ast::ExternCrate>,
65 ) -> Self {
66 Self {
67 in_module: container,
68 kind: DefDiagnosticKind::UnresolvedExternCrate { ast: declaration },
69 }
70 }
71
72 pub(super) fn unresolved_import(
73 container: LocalModuleId,
74 id: AstId<ast::Use>,
75 index: Idx<ast::UseTree>,
76 ) -> Self {
77 Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } }
78 }
79
80 pub fn macro_error(
81 container: LocalModuleId,
82 ast: AstId<ast::Item>,
83 path: ModPath,
84 err: ExpandErrorKind,
85 ) -> Self {
86 Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, path, err } }
87 }
88
89 pub fn unconfigured_code(
90 container: LocalModuleId,
91 ast_id: ErasedAstId,
92 cfg: CfgExpr,
93 opts: CfgOptions,
94 ) -> Self {
95 Self {
96 in_module: container,
97 kind: DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts },
98 }
99 }
100
101 pub(crate) fn unresolved_macro_call(
103 container: LocalModuleId,
104 ast: MacroCallKind,
105 path: ModPath,
106 ) -> Self {
107 Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } }
108 }
109
110 pub(super) fn unimplemented_builtin_macro(
111 container: LocalModuleId,
112 ast: AstId<ast::Macro>,
113 ) -> Self {
114 Self { in_module: container, kind: DefDiagnosticKind::UnimplementedBuiltinMacro { ast } }
115 }
116
117 pub(super) fn invalid_derive_target(
118 container: LocalModuleId,
119 ast: AstId<ast::Item>,
120 id: AttrId,
121 ) -> Self {
122 Self {
123 in_module: container,
124 kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index() },
125 }
126 }
127
128 pub(super) fn malformed_derive(
129 container: LocalModuleId,
130 ast: AstId<ast::Adt>,
131 id: AttrId,
132 ) -> Self {
133 Self {
134 in_module: container,
135 kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index() },
136 }
137 }
138}