eska_presentation/diagnostics/
application.rs1use std::path::Path;
4
5use crate::{
6 localization::{LocalizationValue, Localizer},
7 path_output,
8};
9use eska_project_core::application::{ContextError, SettingsError};
10use serde_json::{Value, json};
11
12#[must_use]
14pub fn context_data(error: &ContextError) -> Value {
15 let path = |value: &Path| {
16 let (value, encoding) = crate::encoding::json_path(value.as_os_str());
17 json!({"value":value,"encoding":encoding})
18 };
19 match error {
20 ContextError::LibraryConfiguration { name, source } => json!({
21 "reason":"library_configuration","library":name,
22 "configuration":source.path().map(path),"cause":source.code()
23 }),
24 ContextError::LibrarySource {
25 name,
26 config,
27 path: source_path,
28 source,
29 } => json!({
30 "reason":"library_source","library":name,"configuration":path(config),
31 "path":path(source_path),"cause":context_data(source)
32 }),
33 ContextError::UnknownApplication {
34 requested,
35 available,
36 } => json!({"reason":"unknown_application","requested":requested,"available":available}),
37 ContextError::AmbiguousApplication { available } => {
38 json!({"reason":"ambiguous_application","available":available})
39 }
40 ContextError::EmptyWorkspace => json!({"reason":"empty_workspace"}),
41 ContextError::Discovery(_) => json!({"reason":"project_discovery"}),
42 ContextError::Source(_) => json!({"reason":"source"}),
43 ContextError::Settings(_) => json!({"reason":"application_settings"}),
44 }
45}
46
47#[must_use]
49pub fn library_message(error: &ContextError, localizer: &Localizer) -> Option<String> {
50 match error {
51 ContextError::LibraryConfiguration { name, source } => {
52 let detail = super::global::present_global_config_error(source, localizer);
53 Some(localizer.format(
54 "analysis-library-config-error",
55 &[
56 ("name", LocalizationValue::Text(name)),
57 ("detail", LocalizationValue::Text(&detail)),
58 ],
59 ))
60 }
61 ContextError::LibrarySource {
62 name, config, path, ..
63 } => Some(localizer.format(
64 "analysis-library-source-error",
65 &[
66 ("name", LocalizationValue::Text(name)),
67 (
68 "config",
69 LocalizationValue::Text(&path_output::display_path(config)),
70 ),
71 (
72 "path",
73 LocalizationValue::Text(&path_output::display_path(path)),
74 ),
75 ],
76 )),
77 _ => None,
78 }
79}
80
81pub fn present(
83 localizer: &Localizer,
84 path: &Path,
85 error: &SettingsError,
86 hyperlinks: bool,
87) -> String {
88 let detail = reason(localizer, error);
89 localizer.format(
90 "analysis-config-invalid",
91 &[
92 (
93 "path",
94 LocalizationValue::Text(&path_output::render(path, hyperlinks)),
95 ),
96 ("detail", LocalizationValue::Text(&detail)),
97 ],
98 )
99}
100
101fn reason(localizer: &Localizer, error: &SettingsError) -> String {
103 match error {
104 SettingsError::ExtensionScopeLocation => {
105 localizer.text("analysis-extension-scope-location")
106 }
107 SettingsError::EmptyConfigurationSource => localizer.text("analysis-reference-empty"),
108 SettingsError::EmptyConfigurationLibrary => localizer.text("analysis-library-empty"),
109 SettingsError::ConfigurationReferenceScope => localizer.text("analysis-reference-scope"),
110 SettingsError::ManagedAnalyzerField { field } => localizer.format(
111 "analysis-managed-field",
112 &[("field", LocalizationValue::Text(field))],
113 ),
114 SettingsError::InvalidAnalyzerPolicy => localizer.text("analysis-policy-invalid"),
115 SettingsError::InvalidName { field, value } => localizer.format(
116 "analysis-name-invalid",
117 &[
118 ("field", LocalizationValue::Text(field)),
119 ("value", LocalizationValue::Text(value)),
120 ],
121 ),
122 SettingsError::InvalidPlatformVersion { value } => localizer.format(
123 "analysis-platform-invalid",
124 &[("value", LocalizationValue::Text(value))],
125 ),
126 SettingsError::UnknownDefaultApplication { name } => localizer.format(
127 "analysis-default-unknown",
128 &[("name", LocalizationValue::Text(name.as_str()))],
129 ),
130 SettingsError::DuplicateMember {
131 application,
132 member,
133 } => member_reason(
134 localizer,
135 "analysis-member-duplicate",
136 application.as_str(),
137 member.as_str(),
138 ),
139 SettingsError::DependencyOutsideApplication {
140 application,
141 member,
142 } => member_reason(
143 localizer,
144 "analysis-dependency-outside",
145 application.as_str(),
146 member.as_str(),
147 ),
148 SettingsError::DependencyCycle { application } => localizer.format(
149 "analysis-dependency-cycle",
150 &[("application", LocalizationValue::Text(application.as_str()))],
151 ),
152 SettingsError::UnknownMember {
153 application,
154 member,
155 } => member_reason(
156 localizer,
157 "analysis-member-unknown",
158 application.as_str(),
159 member.as_str(),
160 ),
161 SettingsError::WrongMemberType {
162 application,
163 member,
164 expected,
165 actual,
166 } => {
167 let expected = expected
168 .project_types()
169 .iter()
170 .map(|kind| kind.as_str())
171 .collect::<Vec<_>>()
172 .join("|");
173 localizer.format(
174 "analysis-member-type",
175 &[
176 ("application", LocalizationValue::Text(application.as_str())),
177 ("member", LocalizationValue::Text(member.as_str())),
178 ("expected", LocalizationValue::Text(&expected)),
179 ("actual", LocalizationValue::Text(actual.as_str())),
180 ],
181 )
182 }
183 SettingsError::MemberAnalysisUnsupported { member } => localizer.format(
184 "analysis-member-settings",
185 &[("member", LocalizationValue::Text(member.as_str()))],
186 ),
187 SettingsError::TargetPlatformScope => localizer.text("analysis-platform-scope"),
188 }
189}
190
191fn member_reason(localizer: &Localizer, key: &str, application: &str, member: &str) -> String {
193 localizer.format(
194 key,
195 &[
196 ("application", LocalizationValue::Text(application)),
197 ("member", LocalizationValue::Text(member)),
198 ],
199 )
200}