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/parsing.rs | |
parent | ab042962e3977b9519476bc73c7252d24c8f587e (diff) | |
download | poseidoc-ab5a6da519f91faa1ba5aa281112e547fcd08b88.tar.gz poseidoc-ab5a6da519f91faa1ba5aa281112e547fcd08b88.zip |
clang-parser: centralize diagnostic building/reporting
Diffstat (limited to 'src/parser/clang/parsing.rs')
-rw-r--r-- | src/parser/clang/parsing.rs | 102 |
1 files changed, 16 insertions, 86 deletions
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 | } |