pylyzer/src/analyze.rs

106 lines
3.4 KiB
Rust

use erg_common::traits::{Runnable, Stream};
use erg_common::config::{ErgConfig};
use erg_common::error::MultiErrorDisplay;
use erg_compiler::artifact::{BuildRunnable, CompleteArtifact, IncompleteArtifact, Buildable};
use erg_compiler::context::Context;
use erg_compiler::erg_parser::ast::AST;
use erg_compiler::error::{CompileErrors, CompileError};
use erg_compiler::lower::ASTLowerer;
use rustpython_parser::parser;
use crate::handle_err;
#[derive(Debug, Default)]
pub struct PythonAnalyzer {
pub cfg: ErgConfig,
checker: ASTLowerer,
}
impl Runnable for PythonAnalyzer {
type Err = CompileError;
type Errs = CompileErrors;
const NAME: &'static str = "Python Analyzer";
fn new(cfg: ErgConfig) -> Self {
let checker = ASTLowerer::new(cfg.clone());
Self {
checker,
cfg,
}
}
fn cfg(&self) -> &ErgConfig {
&self.cfg
}
fn finish(&mut self) {
self.checker.finish();
}
fn initialize(&mut self) {
self.checker.initialize();
}
fn clear(&mut self) {
self.checker.clear();
}
fn eval(&mut self, src: String) -> Result<String, Self::Errs> {
self.checker.eval(src)
}
fn exec(&mut self) -> Result<i32, Self::Errs> {
self.checker.exec()
}
}
impl Buildable for PythonAnalyzer {
fn build(&mut self, code: String, mode: &str) -> Result<CompleteArtifact, IncompleteArtifact> {
self.analyze(code, mode)
}
fn pop_context(&mut self) -> Option<Context> {
Some(self.checker.pop_mod_ctx())
}
fn get_context(&self) -> Option<&Context> {
Some(self.checker.get_mod_ctx())
}
}
impl BuildRunnable for PythonAnalyzer {}
impl PythonAnalyzer {
pub fn analyze(&mut self, py_code: String, mode: &str) -> Result<CompleteArtifact, IncompleteArtifact> {
let filename = self.cfg.input.filename();
let py_program = parser::parse_program(&py_code).unwrap();
let erg_module = py2erg::convert_program(py_program);
let erg_ast = AST::new(erg_common::Str::rc(filename), erg_module);
self.checker.lower(erg_ast, mode).map_err(|iart| {
let filtered = handle_err::filter_errors(self.checker.get_mod_ctx(), iart.errors);
IncompleteArtifact::new(iart.object, filtered, iart.warns)
})
}
pub fn run(&mut self) {
let filename = self.cfg.input.filename();
let py_code = self.cfg.input.read();
println!("Start checking: {filename}");
match self.analyze(py_code, "exec") {
Ok(artifact) => {
if !artifact.warns.is_empty() {
println!("Found warnings: {}", artifact.warns.len());
artifact.warns.fmt_all_stderr();
}
println!("All checks OK.");
std::process::exit(0);
}
Err(artifact) => {
if !artifact.warns.is_empty() {
println!("Found warnings: {}", artifact.warns.len());
artifact.warns.fmt_all_stderr();
}
if artifact.errors.is_empty() {
println!("All checks OK.");
std::process::exit(0);
} else {
println!("Found errors: {}", artifact.errors.len());
artifact.errors.fmt_all_stderr();
std::process::exit(1);
}
}
}
}
}