Skip to main content

Detector

Struct Detector 

Source
pub struct Detector<'a> { /* private fields */ }
Expand description

Searches a database for functions similar to checked ones.

§Examples

let original = br#"class Search {
    static int find(int[] values, int key) {
        int low = 0, high = values.length - 1;
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (values[mid] < key) low = mid + 1;
            else if (values[mid] > key) high = mid - 1;
            else return mid;
        }
        return -(low + 1);
    }
}"#;
let package = PackageInfo {
    ecosystem: "maven".into(),
    name: "org.example:search".into(),
    version: "1.0".into(),
    ..PackageInfo::default()
};
let stored = extract_bytes("Search.java".as_ref(), Language::Java, original, &config).unwrap();
db.index(&package, &[stored]).unwrap();

// The same code with other names.
let copy = String::from_utf8_lossy(original)
    .replace("Search", "Finder").replace("values", "xs").replace("key", "target");
let checked = extract_bytes("Finder.java".as_ref(), Language::Java, copy.as_bytes(), &config).unwrap();
let detector = Detector::new(&db, Options { min_tokens: 20, ..Options::default() }).unwrap();
let reports = detector.detect(&[checked], |_, _| true).unwrap();
assert_eq!(reports[0].name, "find");
assert_eq!(reports[0].candidates[0].kind, MatchKind::Exact(pelicode_core::Level::N1));
assert_eq!(reports[0].candidates[0].occurrences[0].package, "org.example:search");

Implementations§

Source§

impl<'a> Detector<'a>

Source

pub fn new(db: &'a Database, options: Options) -> Result<Detector<'a>>

db must have been opened for features computed like the checked ones (see Database::config_from_meta).

§Errors

Error when the database cannot be read.

§Examples
use pelicode_core::Config;
use pelicode_db::Database;
use pelicode_detect::{Detector, Options};

let dir = tempfile::tempdir().unwrap();
let db = Database::open(dir.path().join("pelicode.db"), &Config::default()).unwrap();
let detector = Detector::new(&db, Options::default()).unwrap();
Source

pub fn excluded_as_dependencies(&self) -> usize

Number of candidates left out so far because they were found only in Options::dependencies.

§Examples
use pelicode_core::{Config, Language, extract_bytes};
use pelicode_db::{Database, PackageInfo};
use pelicode_detect::{Detector, Options, dependencies::Dependencies};

let dir = tempfile::tempdir().unwrap();
let config = Config { min_tokens: 0, ..Config::default() };
let mut db = Database::open(dir.path().join("pelicode.db"), &config).unwrap();
let source = b"def total(xs):\n    s = 0\n    for x in xs:\n        s += x * 2\n    return s\n";
let file = extract_bytes("calc.py".as_ref(), Language::Python, source, &config).unwrap();
let package = PackageInfo {
    ecosystem: "pypi".into(), name: "calc".into(), version: "1.0".into(), ..PackageInfo::default()
};
db.index(&package, &[file.clone()]).unwrap();

// The checked project depends on calc.
let mut dependencies = Dependencies::default();
dependencies.add_file("requirements.txt", "calc>=1\n");
let options = Options { min_tokens: 0, dependencies, ..Options::default() };
let detector = Detector::new(&db, options).unwrap();
assert!(detector.detect(&[file], |_, _| true).unwrap().is_empty());
assert_eq!(detector.excluded_as_dependencies(), 1);
Source

pub fn detect( &self, files: &[FileFeatures], select: impl Fn(&FileFeatures, &FunctionFeatures) -> bool, ) -> Result<Vec<Report>>

Checks the functions of files accepted by select; only functions with at least one candidate are reported.

§Errors

Error when the database cannot be read.

§Examples

Only the functions accepted by select are checked, here those starting after line 1:

let original = br#"class Search {
    static int find(int[] values, int key) {
        int low = 0, high = values.length - 1;
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (values[mid] < key) low = mid + 1;
            else if (values[mid] > key) high = mid - 1;
            else return mid;
        }
        return -(low + 1);
    }
}"#;
let package = PackageInfo {
    ecosystem: "maven".into(),
    name: "org.example:search".into(),
    version: "1.0".into(),
    ..PackageInfo::default()
};
let stored = extract_bytes("Search.java".as_ref(), Language::Java, original, &config).unwrap();
db.index(&package, &[stored]).unwrap();

// The same code with other names.
let copy = String::from_utf8_lossy(original)
    .replace("Search", "Finder").replace("values", "xs").replace("key", "target");
let checked = extract_bytes("Finder.java".as_ref(), Language::Java, copy.as_bytes(), &config).unwrap();
let detector = Detector::new(&db, Options { min_tokens: 20, ..Options::default() }).unwrap();
let reports = detector.detect(&[checked], |_, f| f.start_line > 1).unwrap();
assert_eq!(reports.len(), 1);
Source

pub fn candidates(&self, function: &FunctionFeatures) -> Result<Vec<Candidate>>

Candidates for one function, best first.

Unlike Detector::detect, the function is checked whatever its size.

§Errors

Error when the database cannot be read.

§Examples
let original = br#"class Search {
    static int find(int[] values, int key) {
        int low = 0, high = values.length - 1;
        while (low <= high) {
            int mid = (low + high) >>> 1;
            if (values[mid] < key) low = mid + 1;
            else if (values[mid] > key) high = mid - 1;
            else return mid;
        }
        return -(low + 1);
    }
}"#;
let package = PackageInfo {
    ecosystem: "maven".into(),
    name: "org.example:search".into(),
    version: "1.0".into(),
    ..PackageInfo::default()
};
let stored = extract_bytes("Search.java".as_ref(), Language::Java, original, &config).unwrap();
db.index(&package, &[stored]).unwrap();

// The same code with other names.
let copy = String::from_utf8_lossy(original)
    .replace("Search", "Finder").replace("values", "xs").replace("key", "target");
let checked = extract_bytes("Finder.java".as_ref(), Language::Java, copy.as_bytes(), &config).unwrap();
let detector = Detector::new(&db, Options::default()).unwrap();
let candidates = detector.candidates(&checked.functions[0]).unwrap();
assert_eq!(candidates[0].similarity, 1.0);
assert_eq!(candidates[0].function.name, "find");

Auto Trait Implementations§

§

impl<'a> !Freeze for Detector<'a>

§

impl<'a> !RefUnwindSafe for Detector<'a>

§

impl<'a> !Send for Detector<'a>

§

impl<'a> !Sync for Detector<'a>

§

impl<'a> !UnwindSafe for Detector<'a>

§

impl<'a> Unpin for Detector<'a>

§

impl<'a> UnsafeUnpin for Detector<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.