biome_analyze/
services.rs1use 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}