summaryrefslogtreecommitdiffstats
path: root/src/parser/clang/parsing.rs
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2020-01-23 20:58:59 +0100
committerMinijackson <minijackson@riseup.net>2020-01-23 20:58:59 +0100
commitab5a6da519f91faa1ba5aa281112e547fcd08b88 (patch)
tree8f6192c420f420cbbe081c92ca9f273b7e9c914e /src/parser/clang/parsing.rs
parentab042962e3977b9519476bc73c7252d24c8f587e (diff)
downloadposeidoc-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.rs102
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 @@
1use super::config::Config; 1use super::config::Config;
2use super::diagnostics;
2use super::entities::*; 3use super::entities::*;
3use crate::types::*; 4use crate::types::*;
4 5
5use anyhow::{anyhow, Context, Error, Result}; 6use anyhow::{anyhow, Context, Error, Result};
6use clang::{Clang, CompilationDatabase, Index, TranslationUnit, Usr}; 7use clang::{Clang, CompilationDatabase, Index, TranslationUnit, Usr};
7use codemap::CodeMap;
8use thiserror::Error; 8use thiserror::Error;
9 9
10use std::collections::BTreeMap; 10use std::collections::BTreeMap;
@@ -234,10 +234,7 @@ impl FromTopLevel for Struct {
234} 234}
235*/ 235*/
236 236
237pub(crate) fn parse_compile_commands( 237pub(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
312pub(crate) fn parse_file<T>( 298pub(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>>
317where 299where
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
462fn add_entity( 425fn 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 }