diff options
author | Minijackson <minijackson@riseup.net> | 2020-01-23 20:58:59 +0100 |
---|---|---|
committer | Minijackson <minijackson@riseup.net> | 2020-01-23 20:58:59 +0100 |
commit | ab5a6da519f91faa1ba5aa281112e547fcd08b88 (patch) | |
tree | 8f6192c420f420cbbe081c92ca9f273b7e9c914e /src/parser/clang | |
parent | ab042962e3977b9519476bc73c7252d24c8f587e (diff) | |
download | poseidoc-ab5a6da519f91faa1ba5aa281112e547fcd08b88.tar.gz poseidoc-ab5a6da519f91faa1ba5aa281112e547fcd08b88.zip |
clang-parser: centralize diagnostic building/reporting
Diffstat (limited to 'src/parser/clang')
-rw-r--r-- | src/parser/clang/diagnostics.rs | 313 | ||||
-rw-r--r-- | src/parser/clang/mod.rs | 1 | ||||
-rw-r--r-- | src/parser/clang/parsing.rs | 102 |
3 files changed, 330 insertions, 86 deletions
diff --git a/src/parser/clang/diagnostics.rs b/src/parser/clang/diagnostics.rs new file mode 100644 index 0000000..7aa43be --- /dev/null +++ b/src/parser/clang/diagnostics.rs | |||
@@ -0,0 +1,313 @@ | |||
1 | use anyhow::{anyhow, Context, Result}; | ||
2 | use clang::{ | ||
3 | source::{SourceLocation as ClangSourceLocation, SourceRange as ClangSourceRange}, | ||
4 | Entity as ClangEntity, | ||
5 | }; | ||
6 | use codemap::File; | ||
7 | use codemap_diagnostic::{Diagnostic, Level, SpanLabel}; | ||
8 | use lazy_static::lazy_static; | ||
9 | |||
10 | use std::collections::{hash_map, HashMap}; | ||
11 | use std::path::PathBuf; | ||
12 | use std::sync::{Arc, RwLock}; | ||
13 | |||
14 | lazy_static! { | ||
15 | pub(super) static ref CODEMAP: RwLock<CodeMap> = RwLock::new(CodeMap::new()); | ||
16 | } | ||
17 | |||
18 | #[derive(Default)] | ||
19 | pub(super) struct CodeMap { | ||
20 | files: HashMap<PathBuf, Arc<File>>, | ||
21 | raw_codemap: codemap::CodeMap, | ||
22 | } | ||
23 | |||
24 | impl CodeMap { | ||
25 | pub fn new() -> Self { | ||
26 | Default::default() | ||
27 | } | ||
28 | |||
29 | pub fn span_from_entity(&mut self, entity: ClangEntity) -> Result<codemap::Span> { | ||
30 | self.span_from_libclang_range(entity.get_range().ok_or_else(|| { | ||
31 | anyhow!("Trying to build a diagnostic from an entity that doesn't have a range") | ||
32 | })?) | ||
33 | } | ||
34 | |||
35 | pub fn span_from_libclang_range(&mut self, range: ClangSourceRange) -> Result<codemap::Span> { | ||
36 | let start_file_location = range.get_start().get_file_location(); | ||
37 | let file_name = start_file_location | ||
38 | .file | ||
39 | .ok_or_else(|| { | ||
40 | anyhow!("Trying to build a diagnostic from an entity that isn't located in a file") | ||
41 | })? | ||
42 | .get_path(); | ||
43 | |||
44 | let file = self.get_file(file_name)?; | ||
45 | |||
46 | let begin = start_file_location.offset as u64; | ||
47 | let end = range.get_end().get_file_location().offset as u64; | ||
48 | |||
49 | Ok(file.span.subspan(begin, end)) | ||
50 | } | ||
51 | |||
52 | pub fn span_from_libclang_location( | ||
53 | &mut self, | ||
54 | location: ClangSourceLocation, | ||
55 | ) -> Result<codemap::Span> { | ||
56 | let file_location = location.get_file_location(); | ||
57 | let file_name = file_location | ||
58 | .file | ||
59 | .ok_or_else(|| { | ||
60 | anyhow!("Trying to build a diagnostic from an entity that isn't located in a file") | ||
61 | })? | ||
62 | .get_path(); | ||
63 | |||
64 | let file = self.get_file(file_name)?; | ||
65 | |||
66 | let offset = file_location.offset as u64; | ||
67 | |||
68 | Ok(file.span.subspan(offset, offset)) | ||
69 | } | ||
70 | |||
71 | pub fn get_file(&mut self, file_name: PathBuf) -> Result<&mut Arc<File>> { | ||
72 | Ok(match self.files.entry(file_name.clone()) { | ||
73 | hash_map::Entry::Occupied(file) => file.into_mut(), | ||
74 | hash_map::Entry::Vacant(entry) => { | ||
75 | let file = self.raw_codemap.add_file( | ||
76 | file_name | ||
77 | .to_str() | ||
78 | .context("Filename is not valid UTF-8")? | ||
79 | .to_owned(), | ||
80 | std::fs::read_to_string(&file_name) | ||
81 | .with_context(|| format!("Cannot readfile: {:?}", file_name))?, | ||
82 | ); | ||
83 | entry.insert(file) | ||
84 | } | ||
85 | }) | ||
86 | } | ||
87 | |||
88 | pub fn emitter(&self) -> codemap_diagnostic::Emitter { | ||
89 | use codemap_diagnostic::{ColorConfig, Emitter}; | ||
90 | Emitter::stderr(ColorConfig::Auto, Some(&self.raw_codemap)) | ||
91 | } | ||
92 | } | ||
93 | |||
94 | #[derive(Debug, Clone)] | ||
95 | pub(super) struct DiagnosticBuilder { | ||
96 | level: Level, | ||
97 | message: String, | ||
98 | code: Option<String>, | ||
99 | spans: Vec<SpanLabel>, | ||
100 | } | ||
101 | |||
102 | impl DiagnosticBuilder { | ||
103 | pub fn new(level: Level, message: String) -> Self { | ||
104 | DiagnosticBuilder { | ||
105 | level, | ||
106 | message, | ||
107 | code: None, | ||
108 | spans: vec![], | ||
109 | } | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | pub fn error(message: String) -> Self { | ||
114 | Self::new(Level::Error, message) | ||
115 | } | ||
116 | |||
117 | pub fn warning(message: String) -> Self { | ||
118 | Self::new(Level::Warning, message) | ||
119 | } | ||
120 | |||
121 | pub fn note(message: String) -> Self { | ||
122 | Self::new(Level::Note, message) | ||
123 | } | ||
124 | |||
125 | pub fn help(message: String) -> Self { | ||
126 | Self::new(Level::Help, message) | ||
127 | } | ||
128 | |||
129 | pub fn bug(message: String) -> Self { | ||
130 | Self::new(Level::Bug, message) | ||
131 | } | ||
132 | |||
133 | pub fn level(&mut self, level: Level) -> &mut Self { | ||
134 | self.level = level; | ||
135 | self | ||
136 | } | ||
137 | |||
138 | pub fn message(&mut self, message: String) -> &mut Self { | ||
139 | self.message = message; | ||
140 | self | ||
141 | } | ||
142 | |||
143 | pub fn code(&mut self, code: String) -> &mut Self { | ||
144 | self.code = Some(code); | ||
145 | self | ||
146 | } | ||
147 | */ | ||
148 | |||
149 | pub fn span(&mut self, span: SpanLabel) -> &mut Self { | ||
150 | self.spans.push(span); | ||
151 | self | ||
152 | } | ||
153 | |||
154 | pub fn build(self) -> Diagnostic { | ||
155 | Diagnostic { | ||
156 | level: self.level, | ||
157 | code: self.code, | ||
158 | message: self.message, | ||
159 | spans: self.spans, | ||
160 | } | ||
161 | } | ||
162 | } | ||
163 | |||
164 | fn clang_fixit_to_label( | ||
165 | fixit: clang::diagnostic::FixIt, | ||
166 | ) -> Result<SpanLabel> { | ||
167 | use clang::diagnostic::FixIt; | ||
168 | use codemap_diagnostic::SpanStyle; | ||
169 | |||
170 | let mut codemap = CODEMAP | ||
171 | .write() | ||
172 | .expect("Failed to lock the codemap for writing"); | ||
173 | |||
174 | Ok(match fixit { | ||
175 | FixIt::Deletion(range) => { | ||
176 | let span = codemap.span_from_libclang_range(range)?; | ||
177 | SpanLabel { | ||
178 | span, | ||
179 | label: Some(String::from("help: try deleting this")), | ||
180 | style: SpanStyle::Secondary, | ||
181 | } | ||
182 | } | ||
183 | FixIt::Insertion(location, text) => { | ||
184 | let span = codemap.span_from_libclang_location(location)?; | ||
185 | SpanLabel { | ||
186 | span, | ||
187 | label: Some(format!("help: try inserting {:?}", text)), | ||
188 | style: SpanStyle::Secondary, | ||
189 | } | ||
190 | } | ||
191 | FixIt::Replacement(range, text) => { | ||
192 | let span = codemap.span_from_libclang_range(range)?; | ||
193 | SpanLabel { | ||
194 | span, | ||
195 | label: Some(format!("help: try replacing this with {:?}", text)), | ||
196 | style: SpanStyle::Secondary, | ||
197 | } | ||
198 | } | ||
199 | }) | ||
200 | } | ||
201 | |||
202 | pub(super) fn clang_diagnostic_to_diagnostics( | ||
203 | diagnostic: clang::diagnostic::Diagnostic, | ||
204 | ) -> Vec<Diagnostic> { | ||
205 | use clang::diagnostic::Severity; | ||
206 | use codemap_diagnostic::SpanStyle; | ||
207 | |||
208 | let level = match diagnostic.get_severity() { | ||
209 | Severity::Error | Severity::Fatal => Level::Error, | ||
210 | Severity::Warning => Level::Warning, | ||
211 | Severity::Note => Level::Note, | ||
212 | Severity::Ignored => return vec![], | ||
213 | }; | ||
214 | |||
215 | let mut diag = DiagnosticBuilder::new(level, diagnostic.get_text()); | ||
216 | |||
217 | { | ||
218 | let mut codemap = CODEMAP | ||
219 | .write() | ||
220 | .expect("Failed to lock the codemap for writing"); | ||
221 | if let Ok(span) = codemap.span_from_libclang_location(diagnostic.get_location()) { | ||
222 | diag.span(SpanLabel { | ||
223 | span, | ||
224 | label: None, | ||
225 | style: SpanStyle::Primary, | ||
226 | }); | ||
227 | }; | ||
228 | } | ||
229 | |||
230 | for range in diagnostic.get_ranges() { | ||
231 | let mut codemap = CODEMAP | ||
232 | .write() | ||
233 | .expect("Failed to lock the codemap for writing"); | ||
234 | let span = match codemap.span_from_libclang_range(range) { | ||
235 | Ok(span) => span, | ||
236 | Err(_) => continue, | ||
237 | }; | ||
238 | |||
239 | diag.span(SpanLabel { | ||
240 | span, | ||
241 | label: None, | ||
242 | style: SpanStyle::Primary, | ||
243 | }); | ||
244 | } | ||
245 | |||
246 | let mut child_diags = diagnostic | ||
247 | .get_children() | ||
248 | .into_iter() | ||
249 | .flat_map(|diag| clang_diagnostic_to_diagnostics(diag)) | ||
250 | .collect(); | ||
251 | |||
252 | for fixit_label in diagnostic | ||
253 | .get_fix_its() | ||
254 | .into_iter() | ||
255 | .filter_map(|fixit| clang_fixit_to_label(fixit).ok()) | ||
256 | { | ||
257 | diag.span(fixit_label); | ||
258 | } | ||
259 | |||
260 | let mut diags = vec![diag.build()]; | ||
261 | diags.append(&mut child_diags); | ||
262 | diags | ||
263 | } | ||
264 | |||
265 | pub(super) fn emit(diagnostics: &[Diagnostic]) { | ||
266 | CODEMAP | ||
267 | .read() | ||
268 | .expect("Failed to lock the codemap for reading") | ||
269 | .emitter() | ||
270 | .emit(diagnostics) | ||
271 | } | ||
272 | |||
273 | pub(super) fn log(level: Level, message: String, entity: ClangEntity) { | ||
274 | use codemap_diagnostic::SpanStyle; | ||
275 | |||
276 | let mut diag = DiagnosticBuilder::new(level, message); | ||
277 | |||
278 | if let Ok(span) = CODEMAP | ||
279 | .write() | ||
280 | .expect("Failed to lock the codemap for writing") | ||
281 | .span_from_entity(entity) | ||
282 | { | ||
283 | diag.span(SpanLabel { | ||
284 | span, | ||
285 | label: None, | ||
286 | style: SpanStyle::Primary, | ||
287 | }); | ||
288 | }; | ||
289 | |||
290 | emit(&[diag.build()]); | ||
291 | } | ||
292 | |||
293 | pub(super) fn error(message: String, entity: ClangEntity) { | ||
294 | log(Level::Error, message, entity) | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | pub(super) fn warn(message: String, entity: ClangEntity) { | ||
299 | log(Level::Warning, message, entity) | ||
300 | } | ||
301 | |||
302 | pub(super) fn note(message: String, entity: ClangEntity) { | ||
303 | log(Level::Note, message, entity) | ||
304 | } | ||
305 | |||
306 | pub(super) fn help(message: String, entity: ClangEntity) { | ||
307 | log(Level::Help, message, entity) | ||
308 | } | ||
309 | |||
310 | pub(super) fn bug(message: String, entity: ClangEntity) { | ||
311 | log(Level::Bug, message, entity) | ||
312 | } | ||
313 | */ | ||
diff --git a/src/parser/clang/mod.rs b/src/parser/clang/mod.rs index da49462..a65beed 100644 --- a/src/parser/clang/mod.rs +++ b/src/parser/clang/mod.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | pub(crate) mod config; | 1 | pub(crate) mod config; |
2 | mod diagnostics; | ||
2 | mod entities; | 3 | mod entities; |
3 | mod parsing; | 4 | mod parsing; |
4 | 5 | ||
diff --git a/src/parser/clang/parsing.rs b/src/parser/clang/parsing.rs index 6883d06..50ec5d9 100644 --- a/src/parser/clang/parsing.rs +++ b/src/parser/clang/parsing.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | use super::config::Config; | 1 | use super::config::Config; |
2 | use super::diagnostics; | ||
2 | use super::entities::*; | 3 | use super::entities::*; |
3 | use crate::types::*; | 4 | use crate::types::*; |
4 | 5 | ||
5 | use anyhow::{anyhow, Context, Error, Result}; | 6 | use anyhow::{anyhow, Context, Error, Result}; |
6 | use clang::{Clang, CompilationDatabase, Index, TranslationUnit, Usr}; | 7 | use clang::{Clang, CompilationDatabase, Index, TranslationUnit, Usr}; |
7 | use codemap::CodeMap; | ||
8 | use thiserror::Error; | 8 | use thiserror::Error; |
9 | 9 | ||
10 | use std::collections::BTreeMap; | 10 | use std::collections::BTreeMap; |
@@ -234,10 +234,7 @@ impl FromTopLevel for Struct { | |||
234 | } | 234 | } |
235 | */ | 235 | */ |
236 | 236 | ||
237 | pub(crate) fn parse_compile_commands( | 237 | pub(crate) fn parse_compile_commands(config: &Config) -> Result<BTreeMap<EntityId, Entity>> { |
238 | config: &Config, | ||
239 | codemap: &mut CodeMap, | ||
240 | ) -> Result<BTreeMap<EntityId, Entity>> { | ||
241 | let clang = Clang::new().unwrap(); | 238 | let clang = Clang::new().unwrap(); |
242 | let index = Index::new( | 239 | let index = Index::new( |
243 | &clang, /* exclude from pch = */ false, /* print diagnostics = */ false, | 240 | &clang, /* exclude from pch = */ false, /* print diagnostics = */ false, |
@@ -268,15 +265,6 @@ pub(crate) fn parse_compile_commands( | |||
268 | 265 | ||
269 | let filename = command.get_filename(); | 266 | let filename = command.get_filename(); |
270 | 267 | ||
271 | let file_map = codemap.add_file( | ||
272 | filename | ||
273 | .to_str() | ||
274 | .context("File is not valid UTF-8")? | ||
275 | .to_owned(), | ||
276 | std::fs::read_to_string(&filename) | ||
277 | .with_context(|| format!("Cannot readfile: {:?}", filename))?, | ||
278 | ); | ||
279 | |||
280 | trace!("Parsing file: {:?}", filename); | 268 | trace!("Parsing file: {:?}", filename); |
281 | // The file name is passed as an argument in the compile commands | 269 | // The file name is passed as an argument in the compile commands |
282 | let mut parser = index.parser(""); | 270 | let mut parser = index.parser(""); |
@@ -293,8 +281,6 @@ pub(crate) fn parse_compile_commands( | |||
293 | .with_context(|| format!("Could not parse file: {:?}", filename))?, | 281 | .with_context(|| format!("Could not parse file: {:?}", filename))?, |
294 | &mut entities, | 282 | &mut entities, |
295 | &toplevel_directory, | 283 | &toplevel_directory, |
296 | file_map.span, | ||
297 | &codemap, | ||
298 | )?; | 284 | )?; |
299 | 285 | ||
300 | trace!("Changing directory to: {:?}", toplevel_directory); | 286 | trace!("Changing directory to: {:?}", toplevel_directory); |
@@ -309,11 +295,7 @@ pub(crate) fn parse_compile_commands( | |||
309 | Ok(entities.into()) | 295 | Ok(entities.into()) |
310 | } | 296 | } |
311 | 297 | ||
312 | pub(crate) fn parse_file<T>( | 298 | pub(crate) fn parse_file<T>(path: T, config: &Config) -> Result<BTreeMap<EntityId, Entity>> |
313 | path: T, | ||
314 | config: &Config, | ||
315 | codemap: &mut CodeMap, | ||
316 | ) -> Result<BTreeMap<EntityId, Entity>> | ||
317 | where | 299 | where |
318 | T: Into<PathBuf>, | 300 | T: Into<PathBuf>, |
319 | T: AsRef<Path>, | 301 | T: AsRef<Path>, |
@@ -324,7 +306,6 @@ where | |||
324 | 306 | ||
325 | // as provided in the command line | 307 | // as provided in the command line |
326 | let filename = path.to_string(); | 308 | let filename = path.to_string(); |
327 | let file_map = codemap.add_file(filename.clone(), std::fs::read_to_string(&path)?); | ||
328 | 309 | ||
329 | let path = path.as_ref().canonicalize()?; | 310 | let path = path.as_ref().canonicalize()?; |
330 | let toplevel_directory = std::env::current_dir().context("Cannot read current directory")?; | 311 | let toplevel_directory = std::env::current_dir().context("Cannot read current directory")?; |
@@ -341,14 +322,18 @@ where | |||
341 | .unwrap_or_default(); | 322 | .unwrap_or_default(); |
342 | clang_arguments.extend_from_slice(&config.extra_args); | 323 | clang_arguments.extend_from_slice(&config.extra_args); |
343 | 324 | ||
344 | if let Some(command) = maybe_command { | 325 | let mut parser = if let Some(command) = maybe_command { |
345 | let directory = command.get_directory(); | 326 | let directory = command.get_directory(); |
346 | trace!("Changing directory to: {:?}", directory); | 327 | trace!("Changing directory to: {:?}", directory); |
347 | std::env::set_current_dir(&directory) | 328 | std::env::set_current_dir(&directory) |
348 | .with_context(|| format!("Cannot change current directory to: {:?}", directory))?; | 329 | .with_context(|| format!("Cannot change current directory to: {:?}", directory))?; |
349 | } | 330 | // If it has the parameters provided by the compilation database, |
331 | // then it knows which file to parse | ||
332 | index.parser("") | ||
333 | } else { | ||
334 | index.parser(path) | ||
335 | }; | ||
350 | 336 | ||
351 | let mut parser = index.parser(""); | ||
352 | parser.skip_function_bodies(true); | 337 | parser.skip_function_bodies(true); |
353 | 338 | ||
354 | parser.arguments(&clang_arguments); | 339 | parser.arguments(&clang_arguments); |
@@ -363,8 +348,6 @@ where | |||
363 | .with_context(|| format!("Could not parse file: {:?}", filename))?, | 348 | .with_context(|| format!("Could not parse file: {:?}", filename))?, |
364 | &mut entities, | 349 | &mut entities, |
365 | &toplevel_directory, | 350 | &toplevel_directory, |
366 | file_map.span, | ||
367 | &codemap, | ||
368 | )?; | 351 | )?; |
369 | 352 | ||
370 | trace!("Changing directory to: {:?}", toplevel_directory); | 353 | trace!("Changing directory to: {:?}", toplevel_directory); |
@@ -382,8 +365,6 @@ fn parse_unit( | |||
382 | trans_unit: &TranslationUnit, | 365 | trans_unit: &TranslationUnit, |
383 | entities: &mut TopLevel, | 366 | entities: &mut TopLevel, |
384 | base_dir: impl AsRef<Path>, | 367 | base_dir: impl AsRef<Path>, |
385 | file_span: codemap::Span, | ||
386 | codemap: &CodeMap, | ||
387 | ) -> Result<()> { | 368 | ) -> Result<()> { |
388 | trans_unit.get_entity().visit_children(|entity, _parent| { | 369 | trans_unit.get_entity().visit_children(|entity, _parent| { |
389 | if is_in_system_header(entity, &base_dir) { | 370 | if is_in_system_header(entity, &base_dir) { |
@@ -400,36 +381,18 @@ fn parse_unit( | |||
400 | trace!("Entity with USR = {:?}", usr); | 381 | trace!("Entity with USR = {:?}", usr); |
401 | debug!("Parsing toplevel entity: {:?}", entity); | 382 | debug!("Parsing toplevel entity: {:?}", entity); |
402 | 383 | ||
403 | add_entity(entity, entities, file_span, codemap) | 384 | add_entity(entity, entities) |
404 | }); | 385 | }); |
405 | 386 | ||
406 | use codemap_diagnostic::{ColorConfig, Emitter}; | 387 | for diagnostic in trans_unit.get_diagnostics() { |
407 | 388 | let diags = diagnostics::clang_diagnostic_to_diagnostics(diagnostic); | |
408 | let mut emitter = Emitter::stderr(ColorConfig::Auto, Some(&codemap)); | 389 | diagnostics::emit(&diags); |
409 | |||
410 | for diagnostic in trans_unit.get_diagnostics().iter() { | ||
411 | warn!("{}", diagnostic); | ||
412 | /* | 390 | /* |
413 | let main_diag = match clang_diag_to_codemap_diag(&diagnostic, file_span) { | ||
414 | Some(diag) => diag, | ||
415 | None => continue, | ||
416 | }; | ||
417 | |||
418 | let sub_diags = diagnostic | 391 | let sub_diags = diagnostic |
419 | .get_children() | 392 | .get_children() |
420 | .into_iter() | 393 | .into_iter() |
421 | .filter_map(|diagnostic| clang_diag_to_codemap_diag(&diagnostic, file_span)); | 394 | .filter_map(|diagnostic| clang_diag_to_codemap_diag(&diagnostic, file_span)); |
422 | 395 | ||
423 | let fix_it_diags = diagnostic | ||
424 | .get_fix_its() | ||
425 | .into_iter() | ||
426 | .map(|fix_it| clang_fix_it_to_codemap_diag(&fix_it, file_span)); | ||
427 | |||
428 | emitter.emit( | ||
429 | &std::iter::once(main_diag) | ||
430 | .chain(sub_diags) | ||
431 | .chain(fix_it_diags) | ||
432 | .collect::<Vec<_>>(), | ||
433 | ); | 396 | ); |
434 | */ | 397 | */ |
435 | } | 398 | } |
@@ -462,8 +425,6 @@ fn is_in_system_header(entity: clang::Entity, base_dir: impl AsRef<Path>) -> boo | |||
462 | fn add_entity( | 425 | fn add_entity( |
463 | libclang_entity: clang::Entity, | 426 | libclang_entity: clang::Entity, |
464 | toplevel: &mut TopLevel, | 427 | toplevel: &mut TopLevel, |
465 | file_span: codemap::Span, | ||
466 | codemap: &CodeMap, | ||
467 | ) -> clang::EntityVisitResult { | 428 | ) -> clang::EntityVisitResult { |
468 | if libclang_entity.get_usr().is_none() { | 429 | if libclang_entity.get_usr().is_none() { |
469 | return clang::EntityVisitResult::Continue; | 430 | return clang::EntityVisitResult::Continue; |
@@ -472,38 +433,7 @@ fn add_entity( | |||
472 | let kind = match ClangEntityKind::try_from(libclang_entity.get_kind()) { | 433 | let kind = match ClangEntityKind::try_from(libclang_entity.get_kind()) { |
473 | Ok(kind) => kind, | 434 | Ok(kind) => kind, |
474 | Err(err) => { | 435 | Err(err) => { |
475 | use codemap_diagnostic::{ | 436 | diagnostics::error(format!("{}", err), libclang_entity); |
476 | ColorConfig, Diagnostic, Emitter, Level, SpanLabel, SpanStyle, | ||
477 | }; | ||
478 | let spans = if let Some(range) = libclang_entity.get_range() { | ||
479 | // TODO: add every file parsed in this translation unit to the | ||
480 | // codemap, so we can properly report errors | ||
481 | if !range.is_in_main_file() { | ||
482 | vec![] | ||
483 | } else { | ||
484 | let begin = range.get_start().get_file_location().offset as u64; | ||
485 | let end = range.get_end().get_file_location().offset as u64; | ||
486 | |||
487 | vec![SpanLabel { | ||
488 | span: file_span.subspan(begin, end), | ||
489 | label: None, | ||
490 | style: SpanStyle::Primary, | ||
491 | }] | ||
492 | } | ||
493 | } else { | ||
494 | vec![] | ||
495 | }; | ||
496 | |||
497 | let diag = Diagnostic { | ||
498 | level: Level::Warning, | ||
499 | message: format!("{}", err), | ||
500 | code: None, | ||
501 | spans, | ||
502 | }; | ||
503 | |||
504 | let mut emitter = Emitter::stderr(ColorConfig::Auto, Some(codemap)); | ||
505 | emitter.emit(&[diag]); | ||
506 | |||
507 | return clang::EntityVisitResult::Continue; | 437 | return clang::EntityVisitResult::Continue; |
508 | } | 438 | } |
509 | }; | 439 | }; |
@@ -547,7 +477,7 @@ fn add_entity( | |||
547 | // TODO: check result | 477 | // TODO: check result |
548 | 478 | ||
549 | if let Err(err) = result { | 479 | if let Err(err) = result { |
550 | error!("{}: {:?}", err, libclang_entity); | 480 | diagnostics::error(format!("{}", err), libclang_entity); |
551 | return ::clang::EntityVisitResult::Continue; | 481 | return ::clang::EntityVisitResult::Continue; |
552 | } | 482 | } |
553 | } | 483 | } |