use jbuild::checkstyle::api::ast::DetailAst;
use jbuild::checkstyle::api::check::{Check, FileSetCheck};
use jbuild::checkstyle::api::config::{Context, Contextualizable};
use jbuild::checkstyle::api::file::{FileContents, FileText};
use jbuild::checkstyle::checks::empty_catch_block::EmptyCatchBlockCheck;
use jbuild::checkstyle::checks::empty_statement::EmptyStatementCheck;
use jbuild::checkstyle::checks::line_length::LineLengthCheck;
use jbuild::checkstyle::checks::missing_switch_default::MissingSwitchDefaultCheck;
use jbuild::checkstyle::checks::multiple_variable_declarations::MultipleVariableDeclarationsCheck;
use jbuild::checkstyle::checks::package_name::PackageNameCheck;
use jbuild::checkstyle::checks::type_name::TypeNameCheck;
use std::path::PathBuf;
fn read_example_file(filename: &str) -> String {
let path = PathBuf::from(format!("examples/checkstyle-examples/{filename}"));
std::fs::read_to_string(&path)
.unwrap_or_else(|_| panic!("Failed to read example file: {filename}"))
}
fn create_context() -> Context {
Context::new()
}
#[test]
fn test_nested_empty_catch_example() {
let java_code = read_example_file("NestedEmptyCatchExample.java");
let file_text = FileText::new(PathBuf::from("NestedEmptyCatchExample.java"), java_code);
let file_contents = FileContents::new(file_text);
let mut check = EmptyCatchBlockCheck::new();
let context = create_context();
check.contextualize(&context).unwrap();
check.init().unwrap();
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(catch_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::LITERAL_CATCH) {
check.visit_token(catch_ast.as_ref() as &dyn DetailAst).unwrap();
}
let violations = check.get_violations();
println!("NestedEmptyCatchExample: Found {} violations", violations.len());
}
#[test]
fn test_multiple_violations_example() {
let java_code = read_example_file("MultipleViolationsExample.java");
let file_text = FileText::new(PathBuf::from("MultipleViolationsExample.java"), java_code.clone());
let file_contents = FileContents::new(FileText::new(PathBuf::from("MultipleViolationsExample.java"), java_code));
let mut package_check = PackageNameCheck::new();
let context = create_context();
package_check.contextualize(&context).unwrap();
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
package_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(package_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::PACKAGE_DEF) {
package_check.visit_token(package_ast.as_ref() as &dyn DetailAst).unwrap();
}
let package_violations = package_check.get_violations();
println!("MultipleViolationsExample - PackageName: Found {} violations", package_violations.len());
let mut type_check = TypeNameCheck::new();
type_check.contextualize(&context).unwrap();
type_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(class_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::CLASS_DEF) {
type_check.visit_token(class_ast.as_ref() as &dyn DetailAst).unwrap();
}
let type_violations = type_check.get_violations();
println!("MultipleViolationsExample - TypeName: Found {} violations", type_violations.len());
let mut line_length_check = LineLengthCheck::new();
line_length_check.contextualize(&context).unwrap();
line_length_check.init().unwrap();
let violations = line_length_check.process(&PathBuf::from("MultipleViolationsExample.java"), &file_text).unwrap();
println!("MultipleViolationsExample - LineLength: Found {} violations", violations.len());
}
#[test]
fn test_valid_code_example() {
let java_code = read_example_file("ValidCodeExample.java");
let file_text = FileText::new(PathBuf::from("ValidCodeExample.java"), java_code);
let file_contents = FileContents::new(file_text);
let mut package_check = PackageNameCheck::new();
let context = create_context();
package_check.contextualize(&context).unwrap();
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
package_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(package_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::PACKAGE_DEF) {
package_check.visit_token(package_ast.as_ref() as &dyn DetailAst).unwrap();
}
let package_violations = package_check.get_violations();
assert_eq!(package_violations.len(), 0, "Valid package name should not trigger violations");
let mut type_check = TypeNameCheck::new();
type_check.contextualize(&context).unwrap();
type_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(class_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::CLASS_DEF) {
type_check.visit_token(class_ast.as_ref() as &dyn DetailAst).unwrap();
}
let type_violations = type_check.get_violations();
assert_eq!(type_violations.len(), 0, "Valid type names should not trigger violations");
let mut switch_check = MissingSwitchDefaultCheck::new();
switch_check.contextualize(&context).unwrap();
switch_check.init().unwrap();
switch_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(switch_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::LITERAL_SWITCH) {
switch_check.visit_token(switch_ast.as_ref() as &dyn DetailAst).unwrap();
}
let switch_violations = switch_check.get_violations();
assert_eq!(switch_violations.len(), 0, "Switches with default should not trigger violations");
let mut catch_check = EmptyCatchBlockCheck::new();
catch_check.contextualize(&context).unwrap();
catch_check.init().unwrap();
catch_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(catch_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::LITERAL_CATCH) {
catch_check.visit_token(catch_ast.as_ref() as &dyn DetailAst).unwrap();
}
let catch_violations = catch_check.get_violations();
assert_eq!(catch_violations.len(), 0, "Non-empty catch blocks should not trigger violations");
}
#[test]
fn test_edge_case_line_length_example() {
let java_code = read_example_file("EdgeCaseLineLengthExample.java");
let file_text = FileText::new(PathBuf::from("EdgeCaseLineLengthExample.java"), java_code);
let mut check = LineLengthCheck::new();
let context = create_context();
check.contextualize(&context).unwrap();
check.init().unwrap();
let violations = check.process(&PathBuf::from("EdgeCaseLineLengthExample.java"), &file_text).unwrap();
println!("EdgeCaseLineLengthExample: Found {} violations", violations.len());
}
#[test]
fn test_complex_type_name_example() {
let java_code = read_example_file("ComplexTypeNameExample.java");
let file_text = FileText::new(PathBuf::from("ComplexTypeNameExample.java"), java_code);
let file_contents = FileContents::new(file_text);
let mut check = TypeNameCheck::new();
let context = create_context();
check.contextualize(&context).unwrap();
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(class_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::CLASS_DEF) {
check.visit_token(class_ast.as_ref() as &dyn DetailAst).unwrap();
}
if let Some(interface_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::INTERFACE_DEF) {
check.visit_token(interface_ast.as_ref() as &dyn DetailAst).unwrap();
}
if let Some(enum_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::ENUM_DEF) {
check.visit_token(enum_ast.as_ref() as &dyn DetailAst).unwrap();
}
let violations = check.get_violations();
println!("ComplexTypeNameExample: Found {} violations", violations.len());
}
#[test]
fn test_complex_switch_example() {
let java_code = read_example_file("ComplexSwitchExample.java");
let file_text = FileText::new(PathBuf::from("ComplexSwitchExample.java"), java_code);
let file_contents = FileContents::new(file_text);
let mut check = MissingSwitchDefaultCheck::new();
let context = create_context();
check.contextualize(&context).unwrap();
check.init().unwrap();
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(switch_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::LITERAL_SWITCH) {
check.visit_token(switch_ast.as_ref() as &dyn DetailAst).unwrap();
}
let violations = check.get_violations();
println!("ComplexSwitchExample: Found {} violations", violations.len());
assert!(!violations.is_empty(), "Should find switch violations");
}
#[test]
fn test_complex_variable_declarations_example() {
let java_code = read_example_file("ComplexVariableDeclarationsExample.java");
let file_text = FileText::new(PathBuf::from("ComplexVariableDeclarationsExample.java"), java_code);
let file_contents = FileContents::new(file_text);
let mut check = MultipleVariableDeclarationsCheck::new();
let context = create_context();
check.contextualize(&context).unwrap();
check.init().unwrap();
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(var_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::VARIABLE_DEF) {
check.visit_token(var_ast.as_ref() as &dyn DetailAst).unwrap();
}
if let Some(for_init_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::FOR_INIT) {
check.visit_token(for_init_ast.as_ref() as &dyn DetailAst).unwrap();
}
let violations = check.get_violations();
println!("ComplexVariableDeclarationsExample: Found {} violations", violations.len());
}
#[test]
fn test_all_checks_on_valid_code() {
let java_code = read_example_file("ValidCodeExample.java");
let file_text = FileText::new(PathBuf::from("ValidCodeExample.java"), java_code);
let file_contents = FileContents::new(file_text);
let ast = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents).unwrap();
let context = create_context();
let mut package_check = PackageNameCheck::new();
package_check.contextualize(&context).unwrap();
package_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(package_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::PACKAGE_DEF) {
package_check.visit_token(package_ast.as_ref() as &dyn DetailAst).unwrap();
}
let package_violations = package_check.get_violations().len();
println!("ValidCodeExample - PackageName: {package_violations} violations");
assert_eq!(package_violations, 0);
let mut type_check = TypeNameCheck::new();
type_check.contextualize(&context).unwrap();
type_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(class_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::CLASS_DEF) {
type_check.visit_token(class_ast.as_ref() as &dyn DetailAst).unwrap();
}
let type_violations = type_check.get_violations().len();
println!("ValidCodeExample - TypeName: {type_violations} violations");
assert_eq!(type_violations, 0);
let mut switch_check = MissingSwitchDefaultCheck::new();
switch_check.contextualize(&context).unwrap();
switch_check.init().unwrap();
switch_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(switch_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::LITERAL_SWITCH) {
switch_check.visit_token(switch_ast.as_ref() as &dyn DetailAst).unwrap();
}
let switch_violations = switch_check.get_violations().len();
println!("ValidCodeExample - MissingSwitchDefault: {switch_violations} violations");
assert_eq!(switch_violations, 0);
let mut catch_check = EmptyCatchBlockCheck::new();
catch_check.contextualize(&context).unwrap();
catch_check.init().unwrap();
catch_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(catch_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::LITERAL_CATCH) {
catch_check.visit_token(catch_ast.as_ref() as &dyn DetailAst).unwrap();
}
let catch_violations = catch_check.get_violations().len();
println!("ValidCodeExample - EmptyCatchBlock: {catch_violations} violations");
assert_eq!(catch_violations, 0);
let mut empty_stat_check = EmptyStatementCheck::new();
empty_stat_check.contextualize(&context).unwrap();
empty_stat_check.init().unwrap();
empty_stat_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(empty_stat_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::EMPTY_STAT) {
empty_stat_check.visit_token(empty_stat_ast.as_ref() as &dyn DetailAst).unwrap();
}
let empty_stat_violations = empty_stat_check.get_violations().len();
println!("ValidCodeExample - EmptyStatement: {empty_stat_violations} violations");
assert_eq!(empty_stat_violations, 0);
let mut var_decl_check = MultipleVariableDeclarationsCheck::new();
var_decl_check.contextualize(&context).unwrap();
var_decl_check.init().unwrap();
var_decl_check.begin_tree(ast.as_ref() as &dyn DetailAst).unwrap();
if let Some(var_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::VARIABLE_DEF) {
var_decl_check.visit_token(var_ast.as_ref() as &dyn DetailAst).unwrap();
}
if let Some(for_init_ast) = ast.find_first_token_arc(jbuild::checkstyle::api::ast::token_types::FOR_INIT) {
var_decl_check.visit_token(for_init_ast.as_ref() as &dyn DetailAst).unwrap();
}
let var_decl_violations = var_decl_check.get_violations().len();
println!("ValidCodeExample - MultipleVariableDeclarations: {var_decl_violations} violations");
assert_eq!(var_decl_violations, 0);
}
#[test]
fn test_integration_all_examples() {
let examples = vec![
("EmptyCatchBlockExample.java", "EmptyCatchBlock"),
("EmptyStatementExample.java", "EmptyStatement"),
("MissingSwitchDefaultExample.java", "MissingSwitchDefault"),
("MultipleVariableDeclarationsExample.java", "MultipleVariableDeclarations"),
("LineLengthExample.java", "LineLength"),
("PackageNameExample.java", "PackageName"),
("RedundantImportExample.java", "RedundantImport"),
("TypeNameExample.java", "TypeName"),
("NestedEmptyCatchExample.java", "EmptyCatchBlock"),
("ComplexSwitchExample.java", "MissingSwitchDefault"),
("ComplexTypeNameExample.java", "TypeName"),
("MultipleViolationsExample.java", "MultipleChecks"),
("ValidCodeExample.java", "AllChecks"),
("EdgeCaseLineLengthExample.java", "LineLength"),
("ComplexVariableDeclarationsExample.java", "MultipleVariableDeclarations"),
];
for (example_file, check_name) in examples {
let java_code = read_example_file(example_file);
let file_text = FileText::new(PathBuf::from(example_file), java_code.clone());
let file_contents = FileContents::new(file_text.clone());
let ast_result = jbuild::checkstyle::parser::java_parser::JavaParser::parse(&file_contents);
assert!(ast_result.is_ok(), "Should parse {example_file} successfully");
println!("✓ {example_file} parsed successfully and can be checked with {check_name}");
}
}