/* fuzzy-finder.c generated by valac 0.56.19, the Vala compiler
 * generated from fuzzy-finder.vala, do not modify */

/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 * SPDX-FileCopyrightText: 2023 elementary, Inc. <https://elementary.io>
 *
 * Authored by: Marvin Ahlgrimm
 *              Colin Kiama <colinkiama@gmail.com>
 */

#include <glib.h>
#include "fuzzy-search.h"
#include <gee.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <gio/gio.h>
#include <gobject/gvaluecollector.h>

#define SEPARATOR_BONUS 30
#define SEQUENTIAL_BONUS 40
#define CURRENT_PROJECT_PRIORITY_BONUS 40
#define CAMEL_BONUS 30
#define FIRST_LETTER_BONUS 15
#define LEADING_LETTER_PENALTY -5
#define MAX_LEADING_LETTER_PENALTY -15
#define UNMATCHED_LETTER_PENALTY -1
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _scratch_services_fuzzy_finder_unref0(var) ((var == NULL) ? NULL : (var = (scratch_services_fuzzy_finder_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))
typedef struct _Block2Data Block2Data;
#define _g_thread_unref0(var) ((var == NULL) ? NULL : (var = (g_thread_unref (var), NULL)))
typedef struct _ScratchServicesFuzzyFinderFuzzyFindAsyncData ScratchServicesFuzzyFinderFuzzyFindAsyncData;
#define _search_result_unref0(var) ((var == NULL) ? NULL : (var = (search_result_unref (var), NULL)))
#define _scratch_services_search_project_unref0(var) ((var == NULL) ? NULL : (var = (scratch_services_search_project_unref (var), NULL)))

#define SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER (scratch_services_fuzzy_finder_recursive_finder_get_type ())
#define SCRATCH_SERVICES_FUZZY_FINDER_RECURSIVE_FINDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER, ScratchServicesFuzzyFinderRecursiveFinder))
#define SCRATCH_SERVICES_FUZZY_FINDER_RECURSIVE_FINDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER, ScratchServicesFuzzyFinderRecursiveFinderClass))
#define SCRATCH_SERVICES_FUZZY_FINDER_IS_RECURSIVE_FINDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER))
#define SCRATCH_SERVICES_FUZZY_FINDER_IS_RECURSIVE_FINDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER))
#define SCRATCH_SERVICES_FUZZY_FINDER_RECURSIVE_FINDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER, ScratchServicesFuzzyFinderRecursiveFinderClass))

typedef struct _ScratchServicesFuzzyFinderRecursiveFinder ScratchServicesFuzzyFinderRecursiveFinder;
typedef struct _ScratchServicesFuzzyFinderRecursiveFinderClass ScratchServicesFuzzyFinderRecursiveFinderClass;
#define _scratch_services_fuzzy_finder_recursive_finder_unref0(var) ((var == NULL) ? NULL : (var = (scratch_services_fuzzy_finder_recursive_finder_unref (var), NULL)))
typedef struct _ScratchServicesFuzzyFinderRecursiveFinderPrivate ScratchServicesFuzzyFinderRecursiveFinderPrivate;
typedef struct _ScratchServicesFuzzyFinderParamSpecRecursiveFinder ScratchServicesFuzzyFinderParamSpecRecursiveFinder;
typedef struct _ScratchServicesParamSpecFuzzyFinder ScratchServicesParamSpecFuzzyFinder;

struct _ScratchServicesFuzzyFinderPrivate {
	gint recursion_limit;
	gint max_matches;
	GeeHashMap* project_paths;
};

struct _Block2Data {
	int _ref_count_;
	ScratchServicesFuzzyFinder* self;
	GeeArrayList* results;
	GSourceFunc callback;
	gpointer callback_target;
	GDestroyNotify callback_target_destroy_notify;
	gchar* search_str;
	guint dir_length;
	gchar* current_project;
	GCancellable* cancellable;
	gpointer _async_data_;
};

struct _ScratchServicesFuzzyFinderFuzzyFindAsyncData {
	int _state_;
	GObject* _source_object_;
	GAsyncResult* _res_;
	GTask* _async_result;
	ScratchServicesFuzzyFinder* self;
	gchar* search_str;
	guint dir_length;
	gchar* current_project;
	GCancellable* cancellable;
	GeeArrayList* result;
	Block2Data* _data2_;
	GeeArrayList* _tmp0_;
	GThread* _tmp1_;
	GThread* _tmp2_;
	GeeArrayList* _tmp3_;
};

struct _ScratchServicesFuzzyFinderRecursiveFinder {
	GTypeInstance parent_instance;
	volatile int ref_count;
	ScratchServicesFuzzyFinderRecursiveFinderPrivate * priv;
};

struct _ScratchServicesFuzzyFinderRecursiveFinderClass {
	GTypeClass parent_class;
	void (*finalize) (ScratchServicesFuzzyFinderRecursiveFinder *self);
};

struct _ScratchServicesFuzzyFinderRecursiveFinderPrivate {
	gint recursion_limit;
	gint max_matches;
	gint recursion_count;
};

struct _ScratchServicesFuzzyFinderParamSpecRecursiveFinder {
	GParamSpec parent_instance;
};

struct _ScratchServicesParamSpecFuzzyFinder {
	GParamSpec parent_instance;
};

static gint ScratchServicesFuzzyFinder_private_offset;
static gpointer scratch_services_fuzzy_finder_parent_class = NULL;
static gint ScratchServicesFuzzyFinderRecursiveFinder_private_offset;
static gpointer scratch_services_fuzzy_finder_recursive_finder_parent_class = NULL;
static GType scratch_services_fuzzy_finder_recursive_finder_type_id = 0;
static GType scratch_services_fuzzy_finder_type_id = 0;

static void scratch_services_fuzzy_finder_fuzzy_find_async_data_free (gpointer _data);
static gboolean scratch_services_fuzzy_finder_fuzzy_find_async_co (ScratchServicesFuzzyFinderFuzzyFindAsyncData* _data_);
static Block2Data* block2_data_ref (Block2Data* _data2_);
static void block2_data_unref (void * _userdata_);
static gboolean _scratch_services_fuzzy_finder_fuzzy_find_async_co_gsource_func (gpointer self);
static void __lambda17_ (Block2Data* _data2_);
static gpointer ___lambda17__gthread_func (gpointer self);
static SearchResult* scratch_services_fuzzy_finder_fuzzy_match (ScratchServicesFuzzyFinder* self,
                                                         const gchar* pattern,
                                                         guint dir_length,
                                                         const gchar* str,
                                                         GCancellable* cancellable);
static gint __lambda18_ (ScratchServicesFuzzyFinder* self,
                  SearchResult* a,
                  SearchResult* b);
static gint ___lambda18__gcompare_data_func (gconstpointer a,
                                      gconstpointer b,
                                      gpointer self);
static gpointer scratch_services_fuzzy_finder_recursive_finder_ref (gpointer instance);
static void scratch_services_fuzzy_finder_recursive_finder_unref (gpointer instance);
static GParamSpec* scratch_services_fuzzy_finder_param_spec_recursive_finder (const gchar* name,
                                                                       const gchar* nick,
                                                                       const gchar* blurb,
                                                                       GType object_type,
                                                                       GParamFlags flags) G_GNUC_UNUSED ;
static void scratch_services_fuzzy_finder_value_set_recursive_finder (GValue* value,
                                                               gpointer v_object) G_GNUC_UNUSED ;
static void scratch_services_fuzzy_finder_value_take_recursive_finder (GValue* value,
                                                                gpointer v_object) G_GNUC_UNUSED ;
static gpointer scratch_services_fuzzy_finder_value_get_recursive_finder (const GValue* value) G_GNUC_UNUSED ;
GType scratch_services_fuzzy_finder_recursive_finder_register_type (GTypeModule * module);
VALA_EXTERN GType scratch_services_fuzzy_finder_recursive_finder_get_type (void) G_GNUC_CONST ;
static ScratchServicesFuzzyFinderRecursiveFinder* scratch_services_fuzzy_finder_recursive_finder_new (gint limit,
                                                                                               gint mx_mtchs);
static ScratchServicesFuzzyFinderRecursiveFinder* scratch_services_fuzzy_finder_recursive_finder_construct (GType object_type,
                                                                                                     gint limit,
                                                                                                     gint mx_mtchs);
static SearchResult* scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive (ScratchServicesFuzzyFinderRecursiveFinder* self,
                                                                                    const gchar* pattern,
                                                                                    guint dir_length,
                                                                                    const gchar* str,
                                                                                    GCancellable* cancellable);
static gboolean scratch_services_fuzzy_finder_recursive_finder_limit_reached (ScratchServicesFuzzyFinderRecursiveFinder* self);
static SearchResult* scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive_internal (ScratchServicesFuzzyFinderRecursiveFinder* self,
                                                                                             const gchar* pattern,
                                                                                             guint dir_length,
                                                                                             const gchar* str,
                                                                                             gint pattern_current_index,
                                                                                             gint str_current_index,
                                                                                             gint next_match,
                                                                                             GCancellable* cancellable,
                                                                                             GeeArrayList* matches,
                                                                                             GeeArrayList* src_matches);
static void scratch_services_fuzzy_finder_recursive_finder_finalize (ScratchServicesFuzzyFinderRecursiveFinder * obj);
static void scratch_services_fuzzy_finder_finalize (ScratchServicesFuzzyFinder * obj);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);

static inline gpointer
scratch_services_fuzzy_finder_get_instance_private (ScratchServicesFuzzyFinder* self)
{
	return G_STRUCT_MEMBER_P (self, ScratchServicesFuzzyFinder_private_offset);
}

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

ScratchServicesFuzzyFinder*
scratch_services_fuzzy_finder_construct (GType object_type,
                                         GeeHashMap* pps,
                                         gint limit,
                                         gint mx_mtchs)
{
	ScratchServicesFuzzyFinder* self = NULL;
	GeeHashMap* _tmp0_;
	g_return_val_if_fail (pps != NULL, NULL);
	self = (ScratchServicesFuzzyFinder*) g_type_create_instance (object_type);
	self->priv->max_matches = mx_mtchs;
	self->priv->recursion_limit = limit;
	_tmp0_ = _g_object_ref0 (pps);
	_g_object_unref0 (self->priv->project_paths);
	self->priv->project_paths = _tmp0_;
	return self;
}

ScratchServicesFuzzyFinder*
scratch_services_fuzzy_finder_new (GeeHashMap* pps,
                                   gint limit,
                                   gint mx_mtchs)
{
	return scratch_services_fuzzy_finder_construct (SCRATCH_SERVICES_TYPE_FUZZY_FINDER, pps, limit, mx_mtchs);
}

static void
scratch_services_fuzzy_finder_fuzzy_find_async_data_free (gpointer _data)
{
	ScratchServicesFuzzyFinderFuzzyFindAsyncData* _data_;
	_data_ = _data;
	_g_object_unref0 (_data_->result);
	_scratch_services_fuzzy_finder_unref0 (_data_->self);
	g_slice_free (ScratchServicesFuzzyFinderFuzzyFindAsyncData, _data_);
}

static gpointer
_scratch_services_fuzzy_finder_ref0 (gpointer self)
{
	return self ? scratch_services_fuzzy_finder_ref (self) : NULL;
}

void
scratch_services_fuzzy_finder_fuzzy_find_async (ScratchServicesFuzzyFinder* self,
                                                const gchar* search_str,
                                                guint dir_length,
                                                const gchar* current_project,
                                                GCancellable* cancellable,
                                                GAsyncReadyCallback _callback_,
                                                gpointer _user_data_)
{
	ScratchServicesFuzzyFinderFuzzyFindAsyncData* _data_;
	ScratchServicesFuzzyFinder* _tmp0_;
	gchar* _tmp1_;
	gchar* _tmp2_;
	GCancellable* _tmp3_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (search_str != NULL);
	g_return_if_fail (current_project != NULL);
	g_return_if_fail (cancellable != NULL);
	_data_ = g_slice_new0 (ScratchServicesFuzzyFinderFuzzyFindAsyncData);
	_data_->_async_result = g_task_new (NULL, cancellable, _callback_, _user_data_);
	g_task_set_task_data (_data_->_async_result, _data_, scratch_services_fuzzy_finder_fuzzy_find_async_data_free);
	_tmp0_ = _scratch_services_fuzzy_finder_ref0 (self);
	_data_->self = _tmp0_;
	_tmp1_ = g_strdup (search_str);
	_g_free0 (_data_->search_str);
	_data_->search_str = _tmp1_;
	_data_->dir_length = dir_length;
	_tmp2_ = g_strdup (current_project);
	_g_free0 (_data_->current_project);
	_data_->current_project = _tmp2_;
	_tmp3_ = _g_object_ref0 (cancellable);
	_g_object_unref0 (_data_->cancellable);
	_data_->cancellable = _tmp3_;
	scratch_services_fuzzy_finder_fuzzy_find_async_co (_data_);
}

GeeArrayList*
scratch_services_fuzzy_finder_fuzzy_find_finish (ScratchServicesFuzzyFinder* self,
                                                 GAsyncResult* _res_)
{
	GeeArrayList* result;
	ScratchServicesFuzzyFinderFuzzyFindAsyncData* _data_;
	_data_ = g_task_propagate_pointer (G_TASK (_res_), NULL);
	if (NULL == _data_) {
		return NULL;
	}
	result = _data_->result;
	_data_->result = NULL;
	return result;
}

static Block2Data*
block2_data_ref (Block2Data* _data2_)
{
	g_atomic_int_inc (&_data2_->_ref_count_);
	return _data2_;
}

static void
block2_data_unref (void * _userdata_)
{
	Block2Data* _data2_;
	_data2_ = (Block2Data*) _userdata_;
	if (g_atomic_int_dec_and_test (&_data2_->_ref_count_)) {
		ScratchServicesFuzzyFinder* self;
		self = _data2_->self;
		(_data2_->callback_target_destroy_notify == NULL) ? NULL : (_data2_->callback_target_destroy_notify (_data2_->callback_target), NULL);
		_data2_->callback = NULL;
		_data2_->callback_target = NULL;
		_data2_->callback_target_destroy_notify = NULL;
		_g_object_unref0 (_data2_->results);
		_g_free0 (_data2_->search_str);
		_g_free0 (_data2_->current_project);
		_g_object_unref0 (_data2_->cancellable);
		_scratch_services_fuzzy_finder_unref0 (self);
		g_slice_free (Block2Data, _data2_);
	}
}

static gboolean
_scratch_services_fuzzy_finder_fuzzy_find_async_co_gsource_func (gpointer self)
{
	gboolean result;
	result = scratch_services_fuzzy_finder_fuzzy_find_async_co (self);
	return result;
}

static void
__lambda17_ (Block2Data* _data2_)
{
	ScratchServicesFuzzyFinder* self;
	GeeArrayList* _tmp0_;
	GSourceFunc _tmp1_;
	gpointer _tmp1__target;
	GDestroyNotify _tmp1__target_destroy_notify;
	self = _data2_->self;
	_tmp0_ = scratch_services_fuzzy_finder_fuzzy_find (self, _data2_->search_str, _data2_->dir_length, _data2_->current_project, _data2_->cancellable);
	_g_object_unref0 (_data2_->results);
	_data2_->results = _tmp0_;
	_tmp1_ = _data2_->callback;
	_tmp1__target = _data2_->callback_target;
	_tmp1__target_destroy_notify = _data2_->callback_target_destroy_notify;
	_data2_->callback = NULL;
	_data2_->callback_target = NULL;
	_data2_->callback_target_destroy_notify = NULL;
	g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, _tmp1_, _tmp1__target, _tmp1__target_destroy_notify);
}

static gpointer
___lambda17__gthread_func (gpointer self)
{
	gpointer result;
	__lambda17_ (self);
	result = NULL;
	block2_data_unref (self);
	return result;
}

static gboolean
scratch_services_fuzzy_finder_fuzzy_find_async_co (ScratchServicesFuzzyFinderFuzzyFindAsyncData* _data_)
{
	switch (_data_->_state_) {
		case 0:
		goto _state_0;
		case 1:
		goto _state_1;
		default:
		g_assert_not_reached ();
	}
	_state_0:
	_data_->_data2_ = g_slice_new0 (Block2Data);
	_data_->_data2_->_ref_count_ = 1;
	_data_->_data2_->self = scratch_services_fuzzy_finder_ref (_data_->self);
	_g_free0 (_data_->_data2_->search_str);
	_data_->_data2_->search_str = _data_->search_str;
	_data_->_data2_->dir_length = _data_->dir_length;
	_g_free0 (_data_->_data2_->current_project);
	_data_->_data2_->current_project = _data_->current_project;
	_g_object_unref0 (_data_->_data2_->cancellable);
	_data_->_data2_->cancellable = _data_->cancellable;
	_data_->_data2_->_async_data_ = _data_;
	_data_->_tmp0_ = gee_array_list_new (TYPE_SEARCH_RESULT, (GBoxedCopyFunc) search_result_ref, (GDestroyNotify) search_result_unref, NULL, NULL, NULL);
	_data_->_data2_->results = _data_->_tmp0_;
	_data_->_data2_->callback = _scratch_services_fuzzy_finder_fuzzy_find_async_co_gsource_func;
	_data_->_data2_->callback_target = _data_;
	_data_->_data2_->callback_target_destroy_notify = NULL;
	_data_->_tmp1_ = g_thread_new ("fuzzy-find", ___lambda17__gthread_func, block2_data_ref (_data_->_data2_));
	_data_->_tmp2_ = _data_->_tmp1_;
	_g_thread_unref0 (_data_->_tmp2_);
	_data_->_state_ = 1;
	return FALSE;
	_state_1:
	;
	_data_->_tmp3_ = _g_object_ref0 (_data_->_data2_->results);
	_data_->result = _data_->_tmp3_;
	block2_data_unref (_data_->_data2_);
	_data_->_data2_ = NULL;
	g_task_return_pointer (_data_->_async_result, _data_, NULL);
	if (_data_->_state_ != 0) {
		while (!g_task_get_completed (_data_->_async_result)) {
			g_main_context_iteration (g_task_get_context (_data_->_async_result), TRUE);
		}
	}
	g_object_unref (_data_->_async_result);
	return FALSE;
}

static gpointer
_scratch_services_search_project_ref0 (gpointer self)
{
	return self ? scratch_services_search_project_ref (self) : NULL;
}

static const gchar*
string_to_string (const gchar* self)
{
	const gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	result = self;
	return result;
}

static gint
__lambda18_ (ScratchServicesFuzzyFinder* self,
             SearchResult* a,
             SearchResult* b)
{
	gint result;
	g_return_val_if_fail (a != NULL, -1);
	g_return_val_if_fail (b != NULL, -1);
	result = b->score - a->score;
	return result;
}

static gint
___lambda18__gcompare_data_func (gconstpointer a,
                                 gconstpointer b,
                                 gpointer self)
{
	gint result;
	result = __lambda18_ ((ScratchServicesFuzzyFinder*) self, (SearchResult*) a, (SearchResult*) b);
	return result;
}

GeeArrayList*
scratch_services_fuzzy_finder_fuzzy_find (ScratchServicesFuzzyFinder* self,
                                          const gchar* search_str,
                                          guint dir_length,
                                          const gchar* current_project,
                                          GCancellable* cancellable)
{
	GeeArrayList* results = NULL;
	GeeArrayList* _tmp0_;
	ScratchServicesSearchProject** projects = NULL;
	GeeHashMap* _tmp1_;
	GeeCollection* _tmp2_;
	GeeCollection* _tmp3_;
	GeeCollection* _tmp4_;
	gint _tmp5_ = 0;
	gpointer* _tmp6_;
	ScratchServicesSearchProject** _tmp7_;
	gint _tmp7__length1;
	gint projects_length1;
	gint _projects_size_;
	GeeArrayList* _tmp102_;
	GeeArrayList* _tmp103_;
	gint _tmp104_;
	gint _tmp105_;
	GeeArrayList* _tmp106_;
	GeeList* _tmp107_;
	GeeArrayList* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (search_str != NULL, NULL);
	g_return_val_if_fail (current_project != NULL, NULL);
	g_return_val_if_fail (cancellable != NULL, NULL);
	_tmp0_ = gee_array_list_new (TYPE_SEARCH_RESULT, (GBoxedCopyFunc) search_result_ref, (GDestroyNotify) search_result_unref, NULL, NULL, NULL);
	results = _tmp0_;
	_tmp1_ = self->priv->project_paths;
	_tmp2_ = gee_abstract_map_get_values ((GeeAbstractMap*) _tmp1_);
	_tmp3_ = _tmp2_;
	_tmp4_ = _tmp3_;
	_tmp6_ = gee_collection_to_array (_tmp4_, &_tmp5_);
	_tmp7_ = _tmp6_;
	_tmp7__length1 = _tmp5_;
	_g_object_unref0 (_tmp4_);
	projects = _tmp7_;
	projects_length1 = _tmp7__length1;
	_projects_size_ = projects_length1;
	{
		gint i = 0;
		i = 0;
		{
			gboolean _tmp8_ = FALSE;
			_tmp8_ = TRUE;
			while (TRUE) {
				ScratchServicesSearchProject** _tmp10_;
				gint _tmp10__length1;
				ScratchServicesSearchProject* project = NULL;
				ScratchServicesSearchProject** _tmp16_;
				gint _tmp16__length1;
				ScratchServicesSearchProject* _tmp17_;
				ScratchServicesSearchProject* _tmp18_;
				GeeIterator* iter = NULL;
				ScratchServicesSearchProject* _tmp19_;
				GeeHashSet* _tmp20_;
				GeeHashSet* _tmp21_;
				GeeIterator* _tmp22_;
				if (!_tmp8_) {
					gint _tmp9_;
					_tmp9_ = i;
					i = _tmp9_ + 1;
				}
				_tmp8_ = FALSE;
				_tmp10_ = projects;
				_tmp10__length1 = projects_length1;
				if (!(i < _tmp10__length1)) {
					break;
				}
				if (g_cancellable_is_cancelled (cancellable)) {
					GeeArrayList* _tmp11_;
					gint _tmp12_;
					gint _tmp13_;
					GeeArrayList* _tmp14_;
					GeeList* _tmp15_;
					_tmp11_ = results;
					_tmp12_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) _tmp11_);
					_tmp13_ = _tmp12_;
					if (_tmp13_ <= 20) {
						result = results;
						projects = (_vala_array_free (projects, projects_length1, (GDestroyNotify) scratch_services_search_project_unref), NULL);
						return result;
					}
					_tmp14_ = results;
					_tmp15_ = gee_abstract_list_slice ((GeeAbstractList*) _tmp14_, 0, 20);
					result = G_TYPE_CHECK_INSTANCE_CAST (_tmp15_, GEE_TYPE_ARRAY_LIST, GeeArrayList);
					projects = (_vala_array_free (projects, projects_length1, (GDestroyNotify) scratch_services_search_project_unref), NULL);
					_g_object_unref0 (results);
					return result;
				}
				_tmp16_ = projects;
				_tmp16__length1 = projects_length1;
				_tmp17_ = _tmp16_[i];
				_tmp18_ = _scratch_services_search_project_ref0 (_tmp17_);
				project = _tmp18_;
				_tmp19_ = project;
				_tmp20_ = scratch_services_search_project_get_relative_file_paths (_tmp19_);
				_tmp21_ = _tmp20_;
				_tmp22_ = gee_abstract_collection_iterator ((GeeAbstractCollection*) _tmp21_);
				iter = _tmp22_;
				while (TRUE) {
					gboolean _tmp23_ = FALSE;
					GeeIterator* _tmp24_;
					gchar* path = NULL;
					GeeIterator* _tmp25_;
					gpointer _tmp26_;
					SearchResult* path_search_result = NULL;
					SearchResult* filename_search_result = NULL;
					gchar* project_name = NULL;
					gchar* _tmp27_;
					gchar* _tmp28_ = NULL;
					GeeHashMap* _tmp29_;
					gint _tmp30_;
					gint _tmp31_;
					gchar* _tmp37_;
					gboolean _tmp38_ = FALSE;
					gchar* root_path = NULL;
					ScratchServicesSearchProject* _tmp56_;
					const gchar* _tmp57_;
					const gchar* _tmp58_;
					gchar* _tmp59_;
					SearchResult* _tmp60_;
					_tmp24_ = iter;
					if (gee_iterator_next (_tmp24_)) {
						_tmp23_ = !g_cancellable_is_cancelled (cancellable);
					} else {
						_tmp23_ = FALSE;
					}
					if (!_tmp23_) {
						break;
					}
					_tmp25_ = iter;
					_tmp26_ = gee_iterator_get (_tmp25_);
					path = (gchar*) _tmp26_;
					_tmp27_ = g_strdup ("");
					project_name = _tmp27_;
					_tmp29_ = self->priv->project_paths;
					_tmp30_ = gee_abstract_map_get_size ((GeeAbstractMap*) _tmp29_);
					_tmp31_ = _tmp30_;
					if (_tmp31_ > 1) {
						ScratchServicesSearchProject* _tmp32_;
						const gchar* _tmp33_;
						const gchar* _tmp34_;
						gchar* _tmp35_;
						_tmp32_ = project;
						_tmp33_ = scratch_services_search_project_get_root_path (_tmp32_);
						_tmp34_ = _tmp33_;
						_tmp35_ = g_path_get_basename (_tmp34_);
						_g_free0 (_tmp28_);
						_tmp28_ = _tmp35_;
					} else {
						gchar* _tmp36_;
						_tmp36_ = g_strdup ("");
						_g_free0 (_tmp28_);
						_tmp28_ = _tmp36_;
					}
					_tmp37_ = _tmp28_;
					_tmp28_ = NULL;
					_g_free0 (project_name);
					project_name = _tmp37_;
					if (dir_length > ((guint) 0)) {
						_tmp38_ = TRUE;
					} else {
						GeeHashMap* _tmp39_;
						gint _tmp40_;
						gint _tmp41_;
						_tmp39_ = self->priv->project_paths;
						_tmp40_ = gee_abstract_map_get_size ((GeeAbstractMap*) _tmp39_);
						_tmp41_ = _tmp40_;
						_tmp38_ = _tmp41_ == 1;
					}
					if (_tmp38_) {
						const gchar* _tmp42_;
						SearchResult* _tmp43_;
						_tmp42_ = path;
						_tmp43_ = scratch_services_fuzzy_finder_fuzzy_match (self, search_str, dir_length, _tmp42_, cancellable);
						_search_result_unref0 (path_search_result);
						path_search_result = _tmp43_;
					} else {
						const gchar* _tmp44_;
						const gchar* _tmp45_;
						const gchar* _tmp46_;
						const gchar* _tmp47_;
						gchar* _tmp48_;
						gchar* _tmp49_;
						SearchResult* _tmp50_;
						_tmp44_ = project_name;
						_tmp45_ = string_to_string (_tmp44_);
						_tmp46_ = path;
						_tmp47_ = string_to_string (_tmp46_);
						_tmp48_ = g_strconcat (_tmp45_, "/", _tmp47_, NULL);
						_tmp49_ = _tmp48_;
						_tmp50_ = scratch_services_fuzzy_finder_fuzzy_match (self, search_str, dir_length, _tmp49_, cancellable);
						_search_result_unref0 (path_search_result);
						path_search_result = _tmp50_;
						_g_free0 (_tmp49_);
					}
					if (dir_length == ((guint) 0)) {
						gchar* filename = NULL;
						const gchar* _tmp51_;
						gchar* _tmp52_;
						const gchar* _tmp53_;
						SearchResult* _tmp54_;
						_tmp51_ = path;
						_tmp52_ = g_path_get_basename (_tmp51_);
						filename = _tmp52_;
						_tmp53_ = filename;
						_tmp54_ = scratch_services_fuzzy_finder_fuzzy_match (self, search_str, dir_length, _tmp53_, cancellable);
						_search_result_unref0 (filename_search_result);
						filename_search_result = _tmp54_;
						_g_free0 (filename);
					} else {
						SearchResult* _tmp55_;
						_tmp55_ = search_result_new (FALSE, 0);
						_search_result_unref0 (filename_search_result);
						filename_search_result = _tmp55_;
					}
					_tmp56_ = project;
					_tmp57_ = scratch_services_search_project_get_root_path (_tmp56_);
					_tmp58_ = _tmp57_;
					_tmp59_ = g_strdup (_tmp58_);
					root_path = _tmp59_;
					_tmp60_ = filename_search_result;
					if (_tmp60_->found) {
						SearchResult* _tmp61_;
						const gchar* _tmp62_;
						gchar* _tmp63_;
						SearchResult* _tmp64_;
						const gchar* _tmp65_;
						const gchar* _tmp66_;
						const gchar* _tmp67_;
						const gchar* _tmp68_;
						gchar* _tmp69_;
						SearchResult* _tmp70_;
						const gchar* _tmp71_;
						gchar* _tmp72_;
						gint _tmp73_ = 0;
						ScratchServicesSearchProject* _tmp74_;
						const gchar* _tmp75_;
						const gchar* _tmp76_;
						SearchResult* _tmp77_;
						SearchResult* _tmp78_;
						GeeArrayList* _tmp79_;
						SearchResult* _tmp80_;
						_tmp61_ = filename_search_result;
						_tmp62_ = path;
						_tmp63_ = g_strdup (_tmp62_);
						_g_free0 (_tmp61_->relative_path);
						_tmp61_->relative_path = _tmp63_;
						_tmp64_ = filename_search_result;
						_tmp65_ = root_path;
						_tmp66_ = string_to_string (_tmp65_);
						_tmp67_ = path;
						_tmp68_ = string_to_string (_tmp67_);
						_tmp69_ = g_strconcat (_tmp66_, "/", _tmp68_, NULL);
						_g_free0 (_tmp64_->full_path);
						_tmp64_->full_path = _tmp69_;
						_tmp70_ = filename_search_result;
						_tmp71_ = project_name;
						_tmp72_ = g_strdup (_tmp71_);
						_g_free0 (_tmp70_->project);
						_tmp70_->project = _tmp72_;
						_tmp74_ = project;
						_tmp75_ = scratch_services_search_project_get_root_path (_tmp74_);
						_tmp76_ = _tmp75_;
						if (g_strcmp0 (_tmp76_, current_project) == 0) {
							_tmp73_ = CURRENT_PROJECT_PRIORITY_BONUS;
						} else {
							_tmp73_ = 0;
						}
						_tmp77_ = filename_search_result;
						_tmp78_ = filename_search_result;
						_tmp78_->score = _tmp78_->score + _tmp73_;
						_tmp79_ = results;
						_tmp80_ = filename_search_result;
						gee_abstract_collection_add ((GeeAbstractCollection*) _tmp79_, _tmp80_);
					} else {
						SearchResult* _tmp81_;
						_tmp81_ = path_search_result;
						if (_tmp81_->found) {
							SearchResult* _tmp82_;
							const gchar* _tmp83_;
							gchar* _tmp84_;
							SearchResult* _tmp85_;
							const gchar* _tmp86_;
							const gchar* _tmp87_;
							const gchar* _tmp88_;
							const gchar* _tmp89_;
							gchar* _tmp90_;
							SearchResult* _tmp91_;
							const gchar* _tmp92_;
							gchar* _tmp93_;
							gint _tmp94_ = 0;
							ScratchServicesSearchProject* _tmp95_;
							const gchar* _tmp96_;
							const gchar* _tmp97_;
							SearchResult* _tmp98_;
							SearchResult* _tmp99_;
							GeeArrayList* _tmp100_;
							SearchResult* _tmp101_;
							_tmp82_ = path_search_result;
							_tmp83_ = path;
							_tmp84_ = g_strdup (_tmp83_);
							_g_free0 (_tmp82_->relative_path);
							_tmp82_->relative_path = _tmp84_;
							_tmp85_ = path_search_result;
							_tmp86_ = root_path;
							_tmp87_ = string_to_string (_tmp86_);
							_tmp88_ = path;
							_tmp89_ = string_to_string (_tmp88_);
							_tmp90_ = g_strconcat (_tmp87_, "/", _tmp89_, NULL);
							_g_free0 (_tmp85_->full_path);
							_tmp85_->full_path = _tmp90_;
							_tmp91_ = path_search_result;
							_tmp92_ = project_name;
							_tmp93_ = g_strdup (_tmp92_);
							_g_free0 (_tmp91_->project);
							_tmp91_->project = _tmp93_;
							_tmp95_ = project;
							_tmp96_ = scratch_services_search_project_get_root_path (_tmp95_);
							_tmp97_ = _tmp96_;
							if (g_strcmp0 (_tmp97_, current_project) == 0) {
								_tmp94_ = CURRENT_PROJECT_PRIORITY_BONUS;
							} else {
								_tmp94_ = 0;
							}
							_tmp98_ = path_search_result;
							_tmp99_ = path_search_result;
							_tmp98_->score = ((gint) (_tmp99_->score * 0.2)) + _tmp94_;
							_tmp100_ = results;
							_tmp101_ = path_search_result;
							gee_abstract_collection_add ((GeeAbstractCollection*) _tmp100_, _tmp101_);
						}
					}
					_g_free0 (root_path);
					_g_free0 (_tmp28_);
					_g_free0 (project_name);
					_search_result_unref0 (filename_search_result);
					_search_result_unref0 (path_search_result);
					_g_free0 (path);
				}
				if (g_cancellable_is_cancelled (cancellable)) {
					result = results;
					_g_object_unref0 (iter);
					_scratch_services_search_project_unref0 (project);
					projects = (_vala_array_free (projects, projects_length1, (GDestroyNotify) scratch_services_search_project_unref), NULL);
					return result;
				}
				_g_object_unref0 (iter);
				_scratch_services_search_project_unref0 (project);
			}
		}
	}
	_tmp102_ = results;
	gee_list_sort ((GeeList*) _tmp102_, ___lambda18__gcompare_data_func, scratch_services_fuzzy_finder_ref (self), scratch_services_fuzzy_finder_unref);
	_tmp103_ = results;
	_tmp104_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) _tmp103_);
	_tmp105_ = _tmp104_;
	if (_tmp105_ <= 20) {
		result = results;
		projects = (_vala_array_free (projects, projects_length1, (GDestroyNotify) scratch_services_search_project_unref), NULL);
		return result;
	}
	_tmp106_ = results;
	_tmp107_ = gee_abstract_list_slice ((GeeAbstractList*) _tmp106_, 0, 20);
	result = G_TYPE_CHECK_INSTANCE_CAST (_tmp107_, GEE_TYPE_ARRAY_LIST, GeeArrayList);
	projects = (_vala_array_free (projects, projects_length1, (GDestroyNotify) scratch_services_search_project_unref), NULL);
	_g_object_unref0 (results);
	return result;
}

static SearchResult*
scratch_services_fuzzy_finder_fuzzy_match (ScratchServicesFuzzyFinder* self,
                                           const gchar* pattern,
                                           guint dir_length,
                                           const gchar* str,
                                           GCancellable* cancellable)
{
	ScratchServicesFuzzyFinderRecursiveFinder* finder = NULL;
	ScratchServicesFuzzyFinderRecursiveFinder* _tmp0_;
	SearchResult* _tmp1_;
	SearchResult* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (pattern != NULL, NULL);
	g_return_val_if_fail (str != NULL, NULL);
	g_return_val_if_fail (cancellable != NULL, NULL);
	_tmp0_ = scratch_services_fuzzy_finder_recursive_finder_new (self->priv->recursion_limit, self->priv->max_matches);
	finder = _tmp0_;
	_tmp1_ = scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive (finder, pattern, dir_length, str, cancellable);
	result = _tmp1_;
	_scratch_services_fuzzy_finder_recursive_finder_unref0 (finder);
	return result;
}

static inline gpointer
scratch_services_fuzzy_finder_recursive_finder_get_instance_private (ScratchServicesFuzzyFinderRecursiveFinder* self)
{
	return G_STRUCT_MEMBER_P (self, ScratchServicesFuzzyFinderRecursiveFinder_private_offset);
}

static ScratchServicesFuzzyFinderRecursiveFinder*
scratch_services_fuzzy_finder_recursive_finder_construct (GType object_type,
                                                          gint limit,
                                                          gint mx_mtchs)
{
	ScratchServicesFuzzyFinderRecursiveFinder* self = NULL;
	self = (ScratchServicesFuzzyFinderRecursiveFinder*) g_type_create_instance (object_type);
	self->priv->recursion_limit = limit;
	self->priv->max_matches = mx_mtchs;
	self->priv->recursion_count = 0;
	return self;
}

static ScratchServicesFuzzyFinderRecursiveFinder*
scratch_services_fuzzy_finder_recursive_finder_new (gint limit,
                                                    gint mx_mtchs)
{
	return scratch_services_fuzzy_finder_recursive_finder_construct (SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER, limit, mx_mtchs);
}

static gboolean
scratch_services_fuzzy_finder_recursive_finder_limit_reached (ScratchServicesFuzzyFinderRecursiveFinder* self)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	result = self->priv->recursion_count >= self->priv->recursion_limit;
	return result;
}

static SearchResult*
scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive (ScratchServicesFuzzyFinderRecursiveFinder* self,
                                                                      const gchar* pattern,
                                                                      guint dir_length,
                                                                      const gchar* str,
                                                                      GCancellable* cancellable)
{
	GeeArrayList* matches = NULL;
	GeeArrayList* _tmp0_;
	SearchResult* _tmp1_;
	SearchResult* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (pattern != NULL, NULL);
	g_return_val_if_fail (str != NULL, NULL);
	g_return_val_if_fail (cancellable != NULL, NULL);
	_tmp0_ = gee_array_list_new (G_TYPE_INT, NULL, NULL, NULL, NULL, NULL);
	matches = _tmp0_;
	_tmp1_ = scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive_internal (self, pattern, dir_length, str, 0, 0, 0, cancellable, matches, NULL);
	result = _tmp1_;
	_g_object_unref0 (matches);
	return result;
}

static gunichar
string_get_char (const gchar* self,
                 glong index)
{
	gunichar result;
	g_return_val_if_fail (self != NULL, 0U);
	result = g_utf8_get_char (((gchar*) self) + index);
	return result;
}

static gchar
string_get (const gchar* self,
            glong index)
{
	gchar _tmp0_;
	gchar result;
	g_return_val_if_fail (self != NULL, '\0');
	_tmp0_ = ((gchar*) self)[index];
	result = _tmp0_;
	return result;
}

static SearchResult*
scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive_internal (ScratchServicesFuzzyFinderRecursiveFinder* self,
                                                                               const gchar* pattern,
                                                                               guint dir_length,
                                                                               const gchar* str,
                                                                               gint pattern_current_index,
                                                                               gint str_current_index,
                                                                               gint next_match,
                                                                               GCancellable* cancellable,
                                                                               GeeArrayList* matches,
                                                                               GeeArrayList* src_matches)
{
	gint out_score = 0;
	gboolean recursive_match = FALSE;
	GeeArrayList* best_recursive_matches = NULL;
	GeeArrayList* _tmp0_;
	gint best_recursive_score = 0;
	gboolean first_match = FALSE;
	gboolean allowed_separators = FALSE;
	gint _tmp1_;
	gboolean _tmp2_ = FALSE;
	gboolean _tmp4_ = FALSE;
	gint _tmp5_;
	gint _tmp6_;
	gboolean matched = FALSE;
	gint _tmp37_;
	gint _tmp38_;
	SearchResult* _tmp57_;
	SearchResult* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (pattern != NULL, NULL);
	g_return_val_if_fail (str != NULL, NULL);
	g_return_val_if_fail (cancellable != NULL, NULL);
	g_return_val_if_fail (matches != NULL, NULL);
	out_score = 0;
	recursive_match = FALSE;
	_tmp0_ = gee_array_list_new (G_TYPE_INT, NULL, NULL, NULL, NULL, NULL);
	best_recursive_matches = _tmp0_;
	best_recursive_score = 0;
	first_match = TRUE;
	allowed_separators = TRUE;
	_tmp1_ = self->priv->recursion_count;
	self->priv->recursion_count = _tmp1_ + 1;
	if (g_cancellable_is_cancelled (cancellable)) {
		_tmp2_ = TRUE;
	} else {
		_tmp2_ = scratch_services_fuzzy_finder_recursive_finder_limit_reached (self);
	}
	if (_tmp2_) {
		SearchResult* _tmp3_;
		_tmp3_ = search_result_new (FALSE, out_score);
		result = _tmp3_;
		_g_object_unref0 (best_recursive_matches);
		return result;
	}
	_tmp5_ = strlen (pattern);
	_tmp6_ = _tmp5_;
	if (pattern_current_index == _tmp6_) {
		_tmp4_ = TRUE;
	} else {
		gint _tmp7_;
		gint _tmp8_;
		_tmp7_ = strlen (str);
		_tmp8_ = _tmp7_;
		_tmp4_ = str_current_index == _tmp8_;
	}
	if (_tmp4_) {
		SearchResult* _tmp9_;
		_tmp9_ = search_result_new (FALSE, out_score);
		result = _tmp9_;
		_g_object_unref0 (best_recursive_matches);
		return result;
	}
	while (TRUE) {
		gboolean _tmp10_ = FALSE;
		gint _tmp11_;
		gint _tmp12_;
		gunichar lower_case_char = 0U;
		gunichar lower_case_str_char = 0U;
		gint _tmp36_;
		_tmp11_ = strlen (pattern);
		_tmp12_ = _tmp11_;
		if (pattern_current_index < _tmp12_) {
			gint _tmp13_;
			gint _tmp14_;
			_tmp13_ = strlen (str);
			_tmp14_ = _tmp13_;
			_tmp10_ = str_current_index < _tmp14_;
		} else {
			_tmp10_ = FALSE;
		}
		if (!_tmp10_) {
			break;
		}
		if (g_cancellable_is_cancelled (cancellable)) {
			SearchResult* _tmp15_;
			_tmp15_ = search_result_new (FALSE, out_score);
			result = _tmp15_;
			_g_object_unref0 (best_recursive_matches);
			return result;
		}
		lower_case_char = g_unichar_tolower (string_get_char (pattern, (glong) pattern_current_index));
		lower_case_str_char = g_unichar_tolower (string_get_char (str, (glong) str_current_index));
		if (lower_case_char == lower_case_str_char) {
			gboolean _tmp16_ = FALSE;
			gboolean _tmp19_ = FALSE;
			GeeArrayList* recursive_matches = NULL;
			GeeArrayList* _tmp20_;
			SearchResult* recursive_result_search = NULL;
			GeeArrayList* _tmp21_;
			SearchResult* _tmp22_;
			SearchResult* _tmp23_;
			gint _tmp30_;
			gint _tmp31_;
			gint _tmp32_;
			gint _tmp33_;
			if (dir_length > ((guint) 0)) {
				_tmp16_ = pattern_current_index == 0;
			} else {
				_tmp16_ = FALSE;
			}
			if (_tmp16_) {
				gboolean _tmp17_ = FALSE;
				if (str_current_index > 0) {
					_tmp17_ = g_unichar_tolower (string_get_char (str, (glong) (str_current_index - 1))) != ((gunichar) G_DIR_SEPARATOR);
				} else {
					_tmp17_ = FALSE;
				}
				if (_tmp17_) {
					break;
				}
			}
			allowed_separators = FALSE;
			if (next_match >= self->priv->max_matches) {
				SearchResult* _tmp18_;
				_tmp18_ = search_result_new (FALSE, out_score);
				result = _tmp18_;
				_g_object_unref0 (best_recursive_matches);
				return result;
			}
			if (first_match) {
				_tmp19_ = src_matches != NULL;
			} else {
				_tmp19_ = FALSE;
			}
			if (_tmp19_) {
				gee_abstract_collection_clear ((GeeAbstractCollection*) matches);
				gee_list_insert_all ((GeeList*) matches, 0, (GeeCollection*) src_matches);
				first_match = FALSE;
			}
			_tmp20_ = gee_array_list_new (G_TYPE_INT, NULL, NULL, NULL, NULL, NULL);
			recursive_matches = _tmp20_;
			_tmp21_ = recursive_matches;
			_tmp22_ = scratch_services_fuzzy_finder_recursive_finder_fuzzy_match_recursive_internal (self, pattern, dir_length, str, pattern_current_index, str_current_index + 1, next_match, cancellable, _tmp21_, matches);
			recursive_result_search = _tmp22_;
			_tmp23_ = recursive_result_search;
			if (_tmp23_->found) {
				gboolean _tmp24_ = FALSE;
				if (!recursive_match) {
					_tmp24_ = TRUE;
				} else {
					SearchResult* _tmp25_;
					_tmp25_ = recursive_result_search;
					_tmp24_ = _tmp25_->score > best_recursive_score;
				}
				if (_tmp24_) {
					GeeArrayList* _tmp26_;
					GeeArrayList* _tmp27_;
					GeeArrayList* _tmp28_;
					SearchResult* _tmp29_;
					_tmp26_ = best_recursive_matches;
					gee_abstract_collection_clear ((GeeAbstractCollection*) _tmp26_);
					_tmp27_ = best_recursive_matches;
					_tmp28_ = recursive_matches;
					gee_list_insert_all ((GeeList*) _tmp27_, 0, (GeeCollection*) _tmp28_);
					_tmp29_ = recursive_result_search;
					best_recursive_score = _tmp29_->score;
				}
				recursive_match = TRUE;
			}
			_tmp30_ = gee_abstract_collection_get_size ((GeeAbstractCollection*) matches);
			_tmp31_ = _tmp30_;
			if (_tmp31_ <= next_match) {
				gee_abstract_collection_add ((GeeAbstractCollection*) matches, (gpointer) ((gintptr) str_current_index));
			}
			next_match = next_match + 1;
			_tmp32_ = next_match;
			pattern_current_index = pattern_current_index + 1;
			_tmp33_ = pattern_current_index;
			_search_result_unref0 (recursive_result_search);
			_g_object_unref0 (recursive_matches);
		} else {
			gboolean _tmp34_ = FALSE;
			if (pattern_current_index > 0) {
				_tmp34_ = ((guint) pattern_current_index) <= dir_length;
			} else {
				_tmp34_ = FALSE;
			}
			if (_tmp34_) {
				break;
			} else {
				gboolean _tmp35_ = FALSE;
				if (lower_case_str_char == ((gunichar) G_DIR_SEPARATOR)) {
					_tmp35_ = !allowed_separators;
				} else {
					_tmp35_ = FALSE;
				}
				if (_tmp35_) {
					break;
				}
			}
		}
		str_current_index = str_current_index + 1;
		_tmp36_ = str_current_index;
	}
	_tmp37_ = strlen (pattern);
	_tmp38_ = _tmp37_;
	matched = pattern_current_index == _tmp38_;
	if (matched) {
		gint penalty = 0;
		gpointer _tmp39_;
		gint _tmp40_ = 0;
		gint unmatched = 0;
		gint _tmp41_;
		gint _tmp42_;
		out_score = 100;
		_tmp39_ = gee_abstract_list_get ((GeeAbstractList*) matches, 0);
		penalty = LEADING_LETTER_PENALTY * ((gint) ((gintptr) _tmp39_));
		if (penalty < MAX_LEADING_LETTER_PENALTY) {
			_tmp40_ = MAX_LEADING_LETTER_PENALTY;
		} else {
			_tmp40_ = penalty;
		}
		penalty = _tmp40_;
		out_score += penalty;
		_tmp41_ = strlen (str);
		_tmp42_ = _tmp41_;
		unmatched = _tmp42_ - next_match;
		out_score += UNMATCHED_LETTER_PENALTY * unmatched;
		{
			gint i = 0;
			i = 0;
			{
				gboolean _tmp43_ = FALSE;
				_tmp43_ = TRUE;
				while (TRUE) {
					gint current_index = 0;
					gpointer _tmp46_;
					if (!_tmp43_) {
						gint _tmp44_;
						_tmp44_ = i;
						i = _tmp44_ + 1;
					}
					_tmp43_ = FALSE;
					if (!(i < next_match)) {
						break;
					}
					if (g_cancellable_is_cancelled (cancellable)) {
						SearchResult* _tmp45_;
						_tmp45_ = search_result_new (FALSE, out_score);
						result = _tmp45_;
						_g_object_unref0 (best_recursive_matches);
						return result;
					}
					_tmp46_ = gee_abstract_list_get ((GeeAbstractList*) matches, i);
					current_index = (gint) ((gintptr) _tmp46_);
					if (i > 0) {
						gint previous_index = 0;
						gpointer _tmp47_;
						_tmp47_ = gee_abstract_list_get ((GeeAbstractList*) matches, i - 1);
						previous_index = (gint) ((gintptr) _tmp47_);
						if (current_index == (previous_index + 1)) {
							out_score += SEQUENTIAL_BONUS;
						}
					}
					if (current_index > 0) {
						gchar neighbor = '\0';
						gchar curr = '\0';
						gboolean _tmp48_ = FALSE;
						gboolean _tmp49_ = FALSE;
						gboolean is_neighbour_separator = FALSE;
						neighbor = string_get (str, (glong) (current_index - 1));
						curr = string_get (str, (glong) current_index);
						if (neighbor != g_ascii_toupper (neighbor)) {
							_tmp48_ = curr != g_ascii_tolower (curr);
						} else {
							_tmp48_ = FALSE;
						}
						if (_tmp48_) {
							out_score += CAMEL_BONUS;
						}
						if (neighbor == '_') {
							_tmp49_ = TRUE;
						} else {
							_tmp49_ = neighbor == ' ';
						}
						is_neighbour_separator = _tmp49_;
						if (is_neighbour_separator) {
							out_score += SEPARATOR_BONUS;
						}
					} else {
						out_score += FIRST_LETTER_BONUS;
					}
				}
			}
		}
		if (out_score <= 0) {
			SearchResult* _tmp50_;
			_tmp50_ = search_result_new (FALSE, out_score);
			result = _tmp50_;
			_g_object_unref0 (best_recursive_matches);
			return result;
		} else {
			gboolean _tmp51_ = FALSE;
			if (recursive_match) {
				gboolean _tmp52_ = FALSE;
				if (!matched) {
					_tmp52_ = TRUE;
				} else {
					_tmp52_ = best_recursive_score > out_score;
				}
				_tmp51_ = _tmp52_;
			} else {
				_tmp51_ = FALSE;
			}
			if (_tmp51_) {
				GeeArrayList* _tmp53_;
				SearchResult* _tmp54_;
				_tmp53_ = best_recursive_matches;
				gee_list_insert_all ((GeeList*) matches, 0, (GeeCollection*) _tmp53_);
				out_score = best_recursive_score;
				_tmp54_ = search_result_new (TRUE, out_score);
				result = _tmp54_;
				_g_object_unref0 (best_recursive_matches);
				return result;
			} else {
				if (matched) {
					SearchResult* _tmp55_;
					_tmp55_ = search_result_new (TRUE, out_score);
					result = _tmp55_;
					_g_object_unref0 (best_recursive_matches);
					return result;
				} else {
					SearchResult* _tmp56_;
					_tmp56_ = search_result_new (FALSE, out_score);
					result = _tmp56_;
					_g_object_unref0 (best_recursive_matches);
					return result;
				}
			}
		}
	}
	_tmp57_ = search_result_new (FALSE, out_score);
	result = _tmp57_;
	_g_object_unref0 (best_recursive_matches);
	return result;
}

static void
scratch_services_fuzzy_finder_value_recursive_finder_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
scratch_services_fuzzy_finder_value_recursive_finder_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		scratch_services_fuzzy_finder_recursive_finder_unref (value->data[0].v_pointer);
	}
}

static void
scratch_services_fuzzy_finder_value_recursive_finder_copy_value (const GValue* src_value,
                                                                 GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = scratch_services_fuzzy_finder_recursive_finder_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
scratch_services_fuzzy_finder_value_recursive_finder_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
scratch_services_fuzzy_finder_value_recursive_finder_collect_value (GValue* value,
                                                                    guint n_collect_values,
                                                                    GTypeCValue* collect_values,
                                                                    guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		ScratchServicesFuzzyFinderRecursiveFinder * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = scratch_services_fuzzy_finder_recursive_finder_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
scratch_services_fuzzy_finder_value_recursive_finder_lcopy_value (const GValue* value,
                                                                  guint n_collect_values,
                                                                  GTypeCValue* collect_values,
                                                                  guint collect_flags)
{
	ScratchServicesFuzzyFinderRecursiveFinder ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = scratch_services_fuzzy_finder_recursive_finder_ref (value->data[0].v_pointer);
	}
	return NULL;
}

static GParamSpec*
scratch_services_fuzzy_finder_param_spec_recursive_finder (const gchar* name,
                                                           const gchar* nick,
                                                           const gchar* blurb,
                                                           GType object_type,
                                                           GParamFlags flags)
{
	ScratchServicesFuzzyFinderParamSpecRecursiveFinder* spec;
	g_return_val_if_fail (g_type_is_a (object_type, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

static gpointer
scratch_services_fuzzy_finder_value_get_recursive_finder (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER), NULL);
	return value->data[0].v_pointer;
}

static void
scratch_services_fuzzy_finder_value_set_recursive_finder (GValue* value,
                                                          gpointer v_object)
{
	ScratchServicesFuzzyFinderRecursiveFinder * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		scratch_services_fuzzy_finder_recursive_finder_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		scratch_services_fuzzy_finder_recursive_finder_unref (old);
	}
}

static void
scratch_services_fuzzy_finder_value_take_recursive_finder (GValue* value,
                                                           gpointer v_object)
{
	ScratchServicesFuzzyFinderRecursiveFinder * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		scratch_services_fuzzy_finder_recursive_finder_unref (old);
	}
}

static void
scratch_services_fuzzy_finder_recursive_finder_class_init (ScratchServicesFuzzyFinderRecursiveFinderClass * klass,
                                                           gpointer klass_data)
{
	scratch_services_fuzzy_finder_recursive_finder_parent_class = g_type_class_peek_parent (klass);
	((ScratchServicesFuzzyFinderRecursiveFinderClass *) klass)->finalize = scratch_services_fuzzy_finder_recursive_finder_finalize;
	g_type_class_adjust_private_offset (klass, &ScratchServicesFuzzyFinderRecursiveFinder_private_offset);
}

static void
scratch_services_fuzzy_finder_recursive_finder_instance_init (ScratchServicesFuzzyFinderRecursiveFinder * self,
                                                              gpointer klass)
{
	self->priv = scratch_services_fuzzy_finder_recursive_finder_get_instance_private (self);
	self->ref_count = 1;
}

static void
scratch_services_fuzzy_finder_recursive_finder_finalize (ScratchServicesFuzzyFinderRecursiveFinder * obj)
{
	ScratchServicesFuzzyFinderRecursiveFinder * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, SCRATCH_SERVICES_FUZZY_FINDER_TYPE_RECURSIVE_FINDER, ScratchServicesFuzzyFinderRecursiveFinder);
	g_signal_handlers_destroy (self);
}

GType
scratch_services_fuzzy_finder_recursive_finder_get_type (void)
{
	return scratch_services_fuzzy_finder_recursive_finder_type_id;
}

GType
scratch_services_fuzzy_finder_recursive_finder_register_type (GTypeModule * module)
{
	static const GTypeValueTable g_define_type_value_table = { scratch_services_fuzzy_finder_value_recursive_finder_init, scratch_services_fuzzy_finder_value_recursive_finder_free_value, scratch_services_fuzzy_finder_value_recursive_finder_copy_value, scratch_services_fuzzy_finder_value_recursive_finder_peek_pointer, "p", scratch_services_fuzzy_finder_value_recursive_finder_collect_value, "p", scratch_services_fuzzy_finder_value_recursive_finder_lcopy_value };
	static const GTypeInfo g_define_type_info = { sizeof (ScratchServicesFuzzyFinderRecursiveFinderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scratch_services_fuzzy_finder_recursive_finder_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScratchServicesFuzzyFinderRecursiveFinder), 0, (GInstanceInitFunc) scratch_services_fuzzy_finder_recursive_finder_instance_init, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	scratch_services_fuzzy_finder_recursive_finder_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScratchServicesFuzzyFinderRecursiveFinder", &g_define_type_info, &g_define_type_fundamental_info, G_TYPE_FLAG_NONE);
	ScratchServicesFuzzyFinderRecursiveFinder_private_offset = sizeof (ScratchServicesFuzzyFinderRecursiveFinderPrivate);
	return scratch_services_fuzzy_finder_recursive_finder_type_id;
}

static gpointer
scratch_services_fuzzy_finder_recursive_finder_ref (gpointer instance)
{
	ScratchServicesFuzzyFinderRecursiveFinder * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

static void
scratch_services_fuzzy_finder_recursive_finder_unref (gpointer instance)
{
	ScratchServicesFuzzyFinderRecursiveFinder * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		SCRATCH_SERVICES_FUZZY_FINDER_RECURSIVE_FINDER_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

static void
scratch_services_value_fuzzy_finder_init (GValue* value)
{
	value->data[0].v_pointer = NULL;
}

static void
scratch_services_value_fuzzy_finder_free_value (GValue* value)
{
	if (value->data[0].v_pointer) {
		scratch_services_fuzzy_finder_unref (value->data[0].v_pointer);
	}
}

static void
scratch_services_value_fuzzy_finder_copy_value (const GValue* src_value,
                                                GValue* dest_value)
{
	if (src_value->data[0].v_pointer) {
		dest_value->data[0].v_pointer = scratch_services_fuzzy_finder_ref (src_value->data[0].v_pointer);
	} else {
		dest_value->data[0].v_pointer = NULL;
	}
}

static gpointer
scratch_services_value_fuzzy_finder_peek_pointer (const GValue* value)
{
	return value->data[0].v_pointer;
}

static gchar*
scratch_services_value_fuzzy_finder_collect_value (GValue* value,
                                                   guint n_collect_values,
                                                   GTypeCValue* collect_values,
                                                   guint collect_flags)
{
	if (collect_values[0].v_pointer) {
		ScratchServicesFuzzyFinder * object;
		object = collect_values[0].v_pointer;
		if (object->parent_instance.g_class == NULL) {
			return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		} else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) {
			return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL);
		}
		value->data[0].v_pointer = scratch_services_fuzzy_finder_ref (object);
	} else {
		value->data[0].v_pointer = NULL;
	}
	return NULL;
}

static gchar*
scratch_services_value_fuzzy_finder_lcopy_value (const GValue* value,
                                                 guint n_collect_values,
                                                 GTypeCValue* collect_values,
                                                 guint collect_flags)
{
	ScratchServicesFuzzyFinder ** object_p;
	object_p = collect_values[0].v_pointer;
	if (!object_p) {
		return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value));
	}
	if (!value->data[0].v_pointer) {
		*object_p = NULL;
	} else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) {
		*object_p = value->data[0].v_pointer;
	} else {
		*object_p = scratch_services_fuzzy_finder_ref (value->data[0].v_pointer);
	}
	return NULL;
}

GParamSpec*
scratch_services_param_spec_fuzzy_finder (const gchar* name,
                                          const gchar* nick,
                                          const gchar* blurb,
                                          GType object_type,
                                          GParamFlags flags)
{
	ScratchServicesParamSpecFuzzyFinder* spec;
	g_return_val_if_fail (g_type_is_a (object_type, SCRATCH_SERVICES_TYPE_FUZZY_FINDER), NULL);
	spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags);
	G_PARAM_SPEC (spec)->value_type = object_type;
	return G_PARAM_SPEC (spec);
}

gpointer
scratch_services_value_get_fuzzy_finder (const GValue* value)
{
	g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, SCRATCH_SERVICES_TYPE_FUZZY_FINDER), NULL);
	return value->data[0].v_pointer;
}

void
scratch_services_value_set_fuzzy_finder (GValue* value,
                                         gpointer v_object)
{
	ScratchServicesFuzzyFinder * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, SCRATCH_SERVICES_TYPE_FUZZY_FINDER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, SCRATCH_SERVICES_TYPE_FUZZY_FINDER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
		scratch_services_fuzzy_finder_ref (value->data[0].v_pointer);
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		scratch_services_fuzzy_finder_unref (old);
	}
}

void
scratch_services_value_take_fuzzy_finder (GValue* value,
                                          gpointer v_object)
{
	ScratchServicesFuzzyFinder * old;
	g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, SCRATCH_SERVICES_TYPE_FUZZY_FINDER));
	old = value->data[0].v_pointer;
	if (v_object) {
		g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, SCRATCH_SERVICES_TYPE_FUZZY_FINDER));
		g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value)));
		value->data[0].v_pointer = v_object;
	} else {
		value->data[0].v_pointer = NULL;
	}
	if (old) {
		scratch_services_fuzzy_finder_unref (old);
	}
}

static void
scratch_services_fuzzy_finder_class_init (ScratchServicesFuzzyFinderClass * klass,
                                          gpointer klass_data)
{
	scratch_services_fuzzy_finder_parent_class = g_type_class_peek_parent (klass);
	((ScratchServicesFuzzyFinderClass *) klass)->finalize = scratch_services_fuzzy_finder_finalize;
	g_type_class_adjust_private_offset (klass, &ScratchServicesFuzzyFinder_private_offset);
}

static void
scratch_services_fuzzy_finder_instance_init (ScratchServicesFuzzyFinder * self,
                                             gpointer klass)
{
	self->priv = scratch_services_fuzzy_finder_get_instance_private (self);
	self->ref_count = 1;
}

static void
scratch_services_fuzzy_finder_finalize (ScratchServicesFuzzyFinder * obj)
{
	ScratchServicesFuzzyFinder * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, SCRATCH_SERVICES_TYPE_FUZZY_FINDER, ScratchServicesFuzzyFinder);
	g_signal_handlers_destroy (self);
	_g_object_unref0 (self->priv->project_paths);
}

GType
scratch_services_fuzzy_finder_get_type (void)
{
	return scratch_services_fuzzy_finder_type_id;
}

GType
scratch_services_fuzzy_finder_register_type (GTypeModule * module)
{
	static const GTypeValueTable g_define_type_value_table = { scratch_services_value_fuzzy_finder_init, scratch_services_value_fuzzy_finder_free_value, scratch_services_value_fuzzy_finder_copy_value, scratch_services_value_fuzzy_finder_peek_pointer, "p", scratch_services_value_fuzzy_finder_collect_value, "p", scratch_services_value_fuzzy_finder_lcopy_value };
	static const GTypeInfo g_define_type_info = { sizeof (ScratchServicesFuzzyFinderClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) scratch_services_fuzzy_finder_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ScratchServicesFuzzyFinder), 0, (GInstanceInitFunc) scratch_services_fuzzy_finder_instance_init, &g_define_type_value_table };
	static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) };
	scratch_services_fuzzy_finder_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ScratchServicesFuzzyFinder", &g_define_type_info, &g_define_type_fundamental_info, G_TYPE_FLAG_NONE);
	ScratchServicesFuzzyFinder_private_offset = sizeof (ScratchServicesFuzzyFinderPrivate);
	return scratch_services_fuzzy_finder_type_id;
}

gpointer
scratch_services_fuzzy_finder_ref (gpointer instance)
{
	ScratchServicesFuzzyFinder * self;
	self = instance;
	g_atomic_int_inc (&self->ref_count);
	return instance;
}

void
scratch_services_fuzzy_finder_unref (gpointer instance)
{
	ScratchServicesFuzzyFinder * self;
	self = instance;
	if (g_atomic_int_dec_and_test (&self->ref_count)) {
		SCRATCH_SERVICES_FUZZY_FINDER_GET_CLASS (self)->finalize (self);
		g_type_free_instance ((GTypeInstance *) self);
	}
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

