1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use anyhow::Result;
use serde::Serialize;
use std::future::Future;
use std::path::Path;
use std::path::PathBuf;
use std::pin::Pin;
use std::sync::Arc;
use crate::configuration::ConfigKeyMap;
use crate::configuration::GlobalConfiguration;
use crate::configuration::ResolveConfigurationResult;
use crate::plugins::PluginInfo;
pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub type FormatRange = Option<std::ops::Range<usize>>;
#[derive(Debug)]
pub struct CriticalFormatError(pub anyhow::Error);
impl std::fmt::Display for CriticalFormatError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl std::error::Error for CriticalFormatError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.0.source()
}
}
pub trait CancellationToken: Send + Sync {
fn is_cancelled(&self) -> bool;
fn wait_cancellation(&self) -> BoxFuture<'static, ()>;
}
pub struct NullCancellationToken;
impl CancellationToken for NullCancellationToken {
fn is_cancelled(&self) -> bool {
false
}
fn wait_cancellation(&self) -> BoxFuture<'static, ()> {
Box::pin(std::future::pending())
}
}
pub struct HostFormatRequest {
pub file_path: PathBuf,
pub file_text: String,
pub range: FormatRange,
pub override_config: ConfigKeyMap,
pub token: Arc<dyn CancellationToken>,
}
pub trait Host: Send + Sync {
fn format(&self, request: HostFormatRequest) -> BoxFuture<FormatResult>;
}
pub struct NoopHost;
impl Host for NoopHost {
fn format(&self, _: HostFormatRequest) -> BoxFuture<FormatResult> {
Box::pin(async { Ok(None) })
}
}
pub type FormatResult = Result<Option<String>>;
pub struct FormatRequest<TConfiguration> {
pub file_path: PathBuf,
pub file_text: String,
pub config: Arc<TConfiguration>,
pub range: FormatRange,
pub token: Arc<dyn CancellationToken>,
}
pub trait AsyncPluginHandler: Send + Sync + 'static {
type Configuration: Serialize + Clone + Send + Sync;
fn resolve_config(&self, config: ConfigKeyMap, global_config: GlobalConfiguration) -> ResolveConfigurationResult<Self::Configuration>;
fn plugin_info(&self) -> PluginInfo;
fn license_text(&self) -> String;
fn format(&self, request: FormatRequest<Self::Configuration>, host: Arc<dyn Host>) -> BoxFuture<FormatResult>;
}
pub trait SyncPluginHandler<TConfiguration: Clone + Serialize> {
fn resolve_config(&mut self, config: ConfigKeyMap, global_config: &GlobalConfiguration) -> ResolveConfigurationResult<TConfiguration>;
fn plugin_info(&mut self) -> PluginInfo;
fn license_text(&mut self) -> String;
fn format(
&mut self,
file_path: &Path,
file_text: &str,
config: &TConfiguration,
format_with_host: impl FnMut(&Path, String, &ConfigKeyMap) -> FormatResult,
) -> FormatResult;
}