Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Check subclass gtk check #745

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions gtk/src/subclass/scrolled_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ unsafe impl<T: ScrolledWindowImpl> IsSubclassable<T> for ScrolledWindow {
fn class_init(class: &mut ::glib::Class<Self>) {
Self::parent_class_init::<T>(class);

if !crate::rt::is_initialized() {
panic!("GTK has to be initialized first");
}

let klass = class.as_mut();
klass.move_focus_out = Some(window_move_focus_out::<T>);
klass.scroll_child = Some(window_scroll_child::<T>);
Expand Down
69 changes: 69 additions & 0 deletions gtk/tests/check_subclass_panic.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Take a look at the license at the top of the repository in the LICENSE file.

// We want to ensure that all subclasses have:
//
// ```
// if !crate::rt::is_initialized() {
// panic!("GTK has to be initialized first");
// }
// ```

use std::fs::{read_dir, read_to_string};
use std::path::Path;

fn check_file(f: &Path) -> usize {
let s = read_to_string(f).expect("cannot read file");
let mut checking_type: Option<String> = None;
let mut found_is_initialized_check = false;

for line in s.lines() {
if checking_type.is_none() {
if !line.starts_with("unsafe impl") || !line.contains(" IsSubclassable<") {
continue;
}
if let Some(for_) = line.split(" for ").nth(1).and_then(|s| s.split(' ').next()) {
checking_type = Some(for_.to_owned());
}
continue;
}
if line == "}" {
// Analysis complete!
break;
}
let trimmed = line.trim();
if trimmed.contains("is_initialized()") {
found_is_initialized_check = true;
}
}
if !found_is_initialized_check {
if let Some(for_) = checking_type {
if for_ == "Application" {
return 0;
}
eprintln!(
"[{}] Missing `is_initialized()` check in subclass implementation (`{}`)",
f.display(),
for_
);
1
} else {
0
}
} else {
0
}
}

#[test]
fn check_subclass_panic() {
let mut errors = 0;

for entry in read_dir("src/subclass").unwrap() {
let entry = entry.expect("invalid entry");
let path = entry.path();
if path.is_file() {
errors += check_file(&path);
}
}
assert!(errors == 0);
}