1#![cfg_attr(feature = "clippy", feature(plugin))]
2#![cfg_attr(feature = "clippy", plugin(clippy))]
3
4extern crate clang;
5#[macro_use]
6extern crate failure;
7extern crate glob;
8#[macro_use]
9extern crate lazy_static;
10#[macro_use]
11extern crate log;
12extern crate python_parser;
13extern crate regex;
14extern crate run_script;
15#[macro_use]
16extern crate serde_derive;
17extern crate serde;
18extern crate slog_envlogger;
19extern crate snapshot;
20extern crate walkdir;
21extern crate yaml_rust;
22
23pub mod analysis;
24pub mod config_parser;
25pub mod entity;
26pub mod language_type;
27pub mod synthesis;
28
29use analysis::{Analysis, ProjectFile};
30use config_parser::ProjectParameters;
31use failure::{err_msg, Fallible};
32use language_type::LanguageType;
33use std::path::PathBuf;
34use synthesis::*;
35
36#[derive(Default, Debug)]
37pub struct Thinline<T>
39where
40 T: LanguageType,
41{
42 pub project_parameters: ProjectParameters,
44
45 pub analysis: Analysis<T>,
47
48 pub synthesis: Synthesis,
50}
51
52impl<T> Thinline<T>
53where
54 T: LanguageType,
55{
56 pub fn new() -> Self {
58 Self::default()
59 }
60
61 pub fn parse_project_config<P: Into<PathBuf>>(
63 &mut self,
64 project_dir: P,
65 config_name: &str,
66 ) -> Fallible<()> {
67 let project_config = project_dir.into().join(config_name);
68
69 if !project_config.exists() || !project_config.is_file() {
70 return Err(format_err!(
71 "The given project config file '{}' does not exist or is a directory.",
72 project_config
73 .to_str()
74 .ok_or_else(|| err_msg("Unable to stringify project config file."))?
75 ));
76 }
77
78 self.project_parameters = ProjectParameters::parse(
79 project_config
80 .to_str()
81 .ok_or_else(|| err_msg("Unable to stringify project config file."))?,
82 )?;
83
84 debug!("{:#?}", self.project_parameters);
85
86 Ok(())
87 }
88
89 pub fn analyze_project<P: Into<PathBuf>>(&mut self, project_path: P) -> Fallible<()> {
91 let project_path_p = project_path.into();
92
93 if let Some(project_path_s) = project_path_p.to_str() {
94 info!("Starting project analysis at '{}'", project_path_s);
95 }
96
97 self.analysis = Analysis::new();
98
99 if project_path_p.is_dir() {
100 self.analysis
103 .collect_sources(&project_path_p, &self.project_parameters.source_dirs)?;
104 }
105
106 if project_path_p.is_file() {
107 if let Some(ext) = project_path_p.extension() {
108 if T::file_types().contains(
110 &ext.to_str()
111 .ok_or_else(|| err_msg("Unable to stringify file extension."))?,
112 ) {
113 self.analysis
115 .project_files_mut()
116 .push(ProjectFile::new(&project_path_p));
117 }
118 }
119 }
120
121 self.analysis.extract_entities()?;
122
123 Ok(())
124 }
125}