//! Diagnostics emitted during DefMap construction. use std::ops::Not; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind}; use la_arena::Idx; use syntax::{ast, SyntaxError}; use crate::{ item_tree::{self, ItemTreeId}, nameres::LocalModuleId, path::ModPath, AstId, }; #[derive(Debug, PartialEq, Eq)] pub enum DefDiagnosticKind { UnresolvedModule { ast: AstId, candidates: Box<[String]> }, UnresolvedExternCrate { ast: AstId }, UnresolvedImport { id: ItemTreeId, index: Idx }, UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions }, UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId }, UnresolvedMacroCall { ast: MacroCallKind, path: ModPath }, MacroError { ast: MacroCallKind, message: String }, MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> }, UnimplementedBuiltinMacro { ast: AstId }, InvalidDeriveTarget { ast: AstId, id: usize }, MalformedDerive { ast: AstId, id: usize }, MacroDefError { ast: AstId, message: String }, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct DefDiagnostics(Option>>); impl DefDiagnostics { pub fn new(diagnostics: Vec) -> Self { Self( diagnostics .is_empty() .not() .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())), ) } pub fn iter(&self) -> impl Iterator { self.0.as_ref().into_iter().flat_map(|it| &***it) } } #[derive(Debug, PartialEq, Eq)] pub struct DefDiagnostic { pub in_module: LocalModuleId, pub kind: DefDiagnosticKind, } impl DefDiagnostic { pub(super) fn unresolved_module( container: LocalModuleId, declaration: AstId, candidates: Box<[String]>, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates }, } } pub(super) fn unresolved_extern_crate( container: LocalModuleId, declaration: AstId, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedExternCrate { ast: declaration }, } } pub(super) fn unresolved_import( container: LocalModuleId, id: ItemTreeId, index: Idx, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedImport { id, index } } } pub fn unconfigured_code( container: LocalModuleId, ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } } } // FIXME: Whats the difference between this and unresolved_macro_call // FIXME: This is used for a lot of things, unresolved proc macros, disabled proc macros, etc // yet the diagnostic handler in ide-diagnostics has to figure out what happened because this // struct loses all that information! pub(crate) fn unresolved_proc_macro( container: LocalModuleId, ast: MacroCallKind, krate: CrateId, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedProcMacro { ast, krate } } } pub(crate) fn macro_error( container: LocalModuleId, ast: MacroCallKind, message: String, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::MacroError { ast, message } } } pub(crate) fn macro_expansion_parse_error( container: LocalModuleId, ast: MacroCallKind, errors: Box<[SyntaxError]>, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors }, } } // FIXME: Whats the difference between this and unresolved_proc_macro pub(crate) fn unresolved_macro_call( container: LocalModuleId, ast: MacroCallKind, path: ModPath, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } } } pub(super) fn unimplemented_builtin_macro( container: LocalModuleId, ast: AstId, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::UnimplementedBuiltinMacro { ast } } } pub(super) fn invalid_derive_target( container: LocalModuleId, ast: AstId, id: AttrId, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index() }, } } pub(super) fn malformed_derive( container: LocalModuleId, ast: AstId, id: AttrId, ) -> Self { Self { in_module: container, kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index() }, } } }