biome_analyze/
services.rs

1use crate::{RuleKey, TextRange};
2use biome_diagnostics::{Diagnostic, LineIndexBuf, Resource, Result, SourceCode};
3use rustc_hash::FxHashMap;
4use std::any::{Any, TypeId};
5
6#[derive(Debug, Diagnostic)]
7#[diagnostic(category = "internalError/io", tags(INTERNAL))]
8pub struct MissingServicesDiagnostic {
9    #[message]
10    message: String,
11    #[description]
12    description: String,
13    #[location(resource)]
14    path: Resource<&'static str>,
15    #[location(span)]
16    span: Option<TextRange>,
17    #[location(source_code)]
18    source_code: Option<SourceCode<String, LineIndexBuf>>,
19}
20
21impl MissingServicesDiagnostic {
22    pub fn new(rule_name: &str, missing_services: &'static [&'static str]) -> Self {
23        let description = missing_services.join(", ");
24        Self {
25            message: format!("Errors emitted while attempting run the rule: {rule_name}"),
26            description: format!("Missing services: {description}"),
27            source_code: None,
28            path: Resource::Memory,
29            span: None,
30        }
31    }
32}
33
34pub trait FromServices: Sized {
35    #[allow(clippy::result_large_err)]
36    fn from_services(
37        rule_key: &RuleKey,
38        services: &ServiceBag,
39    ) -> Result<Self, MissingServicesDiagnostic>;
40}
41
42#[derive(Debug, Default)]
43pub struct ServiceBag {
44    services: FxHashMap<TypeId, Box<dyn Any>>,
45}
46
47impl ServiceBag {
48    pub fn insert_service<T: 'static>(&mut self, service: T) {
49        let id = TypeId::of::<T>();
50        self.services.insert(id, Box::new(service));
51    }
52
53    pub fn get_service<T: 'static>(&self) -> Option<&T> {
54        let id = TypeId::of::<T>();
55        let svc = self.services.get(&id)?;
56        svc.downcast_ref()
57    }
58}
59
60impl FromServices for () {
61    fn from_services(_: &RuleKey, _: &ServiceBag) -> Result<Self, MissingServicesDiagnostic> {
62        Ok(())
63    }
64}