gboolean ide_file_equal (IdeFile *self, IdeFile *other) { g_return_val_if_fail (IDE_IS_FILE (self), FALSE); g_return_val_if_fail (IDE_IS_FILE (other), FALSE); return g_file_equal (self->file, other->file); }
static GtkSourceLanguage * ide_file_create_language (IdeFile *self) { GtkSourceLanguageManager *manager; GtkSourceLanguage *srclang; g_autofree gchar *content_type = NULL; const gchar *filename; gboolean uncertain = FALSE; g_assert (IDE_IS_FILE (self)); filename = g_file_get_basename (self->file); if (self->content_type) content_type = g_strdup (self->content_type); else content_type = g_content_type_guess (filename, NULL, 0, &uncertain); if (uncertain) g_clear_pointer (&content_type, g_free); else if (self->content_type == NULL) self->content_type = g_strdup (content_type); manager = gtk_source_language_manager_get_default (); srclang = gtk_source_language_manager_guess_language (manager, filename, content_type); return srclang; }
/** * ide_file_get_temporary_id: * @self: (in): A #IdeFile. * * Gets the #IdeFile:temporary-id property for the file. * * Temporary files have unique identifiers associated with them so that we can * display names such as "unsaved file 1" and know that it will not collide with * another temporary file. * * Files that are not temporary, will return zero. * * Returns: A positive integer greater than zero if the file is a temporary file. */ guint ide_file_get_temporary_id (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), 0); return self->temporary_id; }
static void ide_autotools_build_system_get_build_flags_async (IdeBuildSystem *build_system, IdeFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { IdeAutotoolsBuildSystem *self = (IdeAutotoolsBuildSystem *)build_system; g_autoptr(GTask) task = NULL; GFile *gfile; g_assert (IDE_IS_AUTOTOOLS_BUILD_SYSTEM (self)); g_assert (IDE_IS_FILE (file)); EGG_COUNTER_INC (build_flags); gfile = ide_file_get_file (file); task = g_task_new (self, cancellable, callback, user_data); g_task_set_task_data (task, g_object_ref (gfile), g_object_unref); ide_autotools_build_system_get_makecache_async (self, cancellable, ide_autotools_build_system__makecache_cb, g_object_ref (task)); }
gboolean ide_file_get_is_temporary (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), FALSE); return (self->temporary_id != 0); }
guint ide_file_hash (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), 0); return g_file_hash (self->file); }
static IdeUnsavedFile * get_unsaved_file (IdeGettextDiagnosticProvider *self, IdeFile *file) { g_autoptr(GPtrArray) array = NULL; IdeUnsavedFiles *unsaved_files; IdeContext *context; guint i; g_assert (IDE_IS_GETTEXT_DIAGNOSTIC_PROVIDER (self)); g_assert (IDE_IS_FILE (file)); context = ide_object_get_context (IDE_OBJECT (self)); unsaved_files = ide_context_get_unsaved_files (context); array = ide_unsaved_files_to_array (unsaved_files); for (i = 0; i < array->len; i++) { IdeUnsavedFile *unsaved_file = g_ptr_array_index (array, i); GFile *ufile = ide_unsaved_file_get_file (unsaved_file); GFile *ifile = ide_file_get_file (file); g_assert (G_IS_FILE (ufile)); g_assert (G_IS_FILE (ifile)); if (g_file_equal (ufile, ifile)) return ide_unsaved_file_ref (unsaved_file); } return NULL; }
/** * ide_file_get_file: * * Retrieves the underlying #GFile represented by @self. * * Returns: (transfer none): A #GFile. */ GFile * ide_file_get_file (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), NULL); return self->file; }
static void ide_file_set_temporary_id (IdeFile *self, guint temporary_id) { g_return_if_fail (IDE_IS_FILE (self)); self->temporary_id = temporary_id; }
/** * ide_clang_service_get_translation_unit_async: * * This function is used to asynchronously retrieve the translation unit for * a particular file. * * If the translation unit is up to date, then no parsing will occur and the * existing translation unit will be used. * * If the translation unit is out of date, then the source file(s) will be * parsed via clang_parseTranslationUnit() asynchronously. */ void ide_clang_service_get_translation_unit_async (IdeClangService *self, IdeFile *file, gint64 min_serial, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { IdeClangTranslationUnit *cached; g_autoptr(GTask) task = NULL; g_return_if_fail (IDE_IS_CLANG_SERVICE (self)); g_return_if_fail (IDE_IS_FILE (file)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = g_task_new (self, cancellable, callback, user_data); /* * Clang likes to crash on our temporary files. */ if (ide_file_get_is_temporary (file)) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "File does not yet exist, ignoring translation unit request."); return; } if (min_serial == 0) { IdeContext *context; IdeUnsavedFiles *unsaved_files; context = ide_object_get_context (IDE_OBJECT (self)); unsaved_files = ide_context_get_unsaved_files (context); min_serial = ide_unsaved_files_get_sequence (unsaved_files); } /* * If we have a cached unit, and it is new enough, then re-use it. */ if ((cached = egg_task_cache_peek (self->units_cache, file)) && (ide_clang_translation_unit_get_serial (cached) >= min_serial)) { g_task_return_pointer (task, g_object_ref (cached), g_object_unref); return; } egg_task_cache_get_async (self->units_cache, file, TRUE, cancellable, ide_clang_service_get_translation_unit_cb, g_object_ref (task)); }
static void ide_file_set_path (IdeFile *self, const gchar *path) { g_return_if_fail (IDE_IS_FILE (self)); g_return_if_fail (!self->path); g_clear_pointer (&self->path, g_free); self->path = g_strdup (path); }
const gchar * _ide_file_get_content_type (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), NULL); if (self->content_type != NULL) return self->content_type; return "text/plain"; }
/** * ide_file_find_other_finish: * * Completes an asynchronous call to ide_file_find_other_async(). This function * will try to find a matching file for languages where this exists. Such cases * include C and C++ where a .c or .cpp file may have a .h or .hh header. Additional * suffixes are implemented including (.c, .cc, .cpp, .cxx, .h, .hh, .hpp, and .hxx). * * Returns an #IdeFile if successful, otherwise %NULL and @error is set. * * Returns: (transfer full) (nullable): An #IdeFIle or %NULL. */ IdeFile * ide_file_find_other_finish (IdeFile *self, GAsyncResult *result, GError **error) { g_return_val_if_fail (IDE_IS_FILE (self), NULL); g_return_val_if_fail (G_IS_TASK (result), NULL); return g_task_propagate_pointer (G_TASK (result), error); }
static void ide_file_settings_set_file (IdeFileSettings *self, IdeFile *file) { IdeFileSettingsPrivate *priv = ide_file_settings_get_instance_private (self); g_return_if_fail (IDE_IS_FILE_SETTINGS (self)); g_return_if_fail (IDE_IS_FILE (file)); if (ide_set_weak_pointer (&priv->file, file)) g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE]); }
static void ide_file_set_file (IdeFile *self, GFile *file) { g_return_if_fail (IDE_IS_FILE (self)); g_return_if_fail (G_IS_FILE (file)); if (file != self->file) { if (g_set_object (&self->file, file)) g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_FILE]); } }
void ide_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *self, IdeFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_return_if_fail (IDE_IS_DIAGNOSTIC_PROVIDER (self)); g_return_if_fail (IDE_IS_FILE (file)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); IDE_DIAGNOSTIC_PROVIDER_GET_IFACE (self)->diagnose_async (self, file, cancellable, callback, user_data); }
/** * ide_clang_service_get_cached_translation_unit: * @self: A #IdeClangService. * * Gets a cached translation unit if one exists for the file. * * Returns: (transfer full) (nullable): An #IdeClangTranslationUnit or %NULL. */ IdeClangTranslationUnit * ide_clang_service_get_cached_translation_unit (IdeClangService *self, IdeFile *file) { IdeClangTranslationUnit *cached; g_return_val_if_fail (IDE_IS_CLANG_SERVICE (self), NULL); g_return_val_if_fail (IDE_IS_FILE (file), NULL); cached = egg_task_cache_peek (self->units_cache, file); return cached ? g_object_ref (cached) : NULL; }
void ide_file_find_other_async (IdeFile *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GTask) task = NULL; g_return_if_fail (IDE_IS_FILE (self)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = g_task_new (self, cancellable, callback, user_data); g_task_run_in_thread (task, ide_file_find_other_worker); }
void ide_file_load_settings_async (IdeFile *self, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GTask) task = NULL; g_autoptr(IdeFileSettings) file_settings = NULL; IDE_ENTRY; g_return_if_fail (IDE_IS_FILE (self)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); task = g_task_new (self, cancellable, callback, user_data); /* Use shared instance if available */ if (self->file_settings != NULL) { g_task_return_pointer (task, g_object_ref (self->file_settings), g_object_unref); IDE_EXIT; } /* Create our new settings instance, races are okay */ file_settings = ide_file_settings_new (self); /* If this is settled immediately (not using editorconfig), then we can use this now * and cache the result for later */ if (ide_file_settings_get_settled (file_settings)) { self->file_settings = g_steal_pointer (&file_settings); g_task_return_pointer (task, g_object_ref (self->file_settings), g_object_unref); IDE_EXIT; } /* * We need to wait until the settings have settled. editorconfig may need to * background load a bunch of .editorconfig files off of disk/sshfs/etc to * determine the settings. */ g_signal_connect (file_settings, "notify::settled", G_CALLBACK (ide_file__file_settings_settled_cb), g_object_ref (task)); g_task_set_task_data (task, g_steal_pointer (&file_settings), g_object_unref); IDE_EXIT; }
void _ide_file_set_content_type (IdeFile *self, const gchar *content_type) { g_assert (IDE_IS_FILE (self)); g_assert (content_type); if (0 != g_strcmp0 (self->content_type, content_type)) { g_clear_pointer (&self->content_type, g_free); g_clear_object (&self->language); self->content_type = g_strdup (content_type); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LANGUAGE]); } }
const gchar * ide_file_get_path (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), NULL); if (g_once_init_enter (&self->path)) { gchar *path; path = g_file_get_path (self->file); g_once_init_leave (&self->path, path); } return self->path; }
/** * ide_file_get_language: * * Retrieves the #GtkSourceLanguage that was discovered for the file. * * Returns: (nullable) (transfer none): A #GtkSourceLanguage or %NULL. */ GtkSourceLanguage * ide_file_get_language (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), NULL); if (self->language == NULL) { GtkSourceLanguage *language; language = ide_file_create_language (self); self->language = language ? g_object_ref (language) : NULL; } return self->language; }
void gb_view_stack_focus_location (GbViewStack *self, IdeSourceLocation *location) { IdeBufferManager *buffer_manager; IdeBuffer *buffer; IdeFile *file; GFile *gfile; g_return_if_fail (GB_IS_VIEW_STACK (self)); g_return_if_fail (location != NULL); if (self->context == NULL) return; file = ide_source_location_get_file (location); gfile = ide_file_get_file (file); g_assert (file != NULL); g_assert (IDE_IS_FILE (file)); gfile = ide_file_get_file (file); buffer_manager = ide_context_get_buffer_manager (self->context); buffer = ide_buffer_manager_find_buffer (buffer_manager, gfile); if (buffer != NULL && GB_IS_DOCUMENT (buffer)) { GtkWidget *active_view; gb_view_stack_focus_document (self, GB_DOCUMENT (buffer)); active_view = gb_view_stack_get_active_view (self); g_assert (GB_DOCUMENT (buffer) == gb_view_get_document (GB_VIEW (active_view))); gb_view_navigate_to (GB_VIEW (active_view), location); } else { g_autoptr(GTask) task = NULL; task = g_task_new (self, NULL, NULL, NULL); g_task_set_task_data (task, ide_source_location_ref (location), (GDestroyNotify)ide_source_location_unref); ide_buffer_manager_load_file_async (buffer_manager, file, FALSE, NULL, NULL, gb_view_stack__navigate_to_load_cb, g_object_ref (task)); } }
/** * _ide_file_get_source_file: * @self: (in): A #IdeFile. * * Gets the GtkSourceFile for the #IdeFile. * * Returns: (transfer none): A #GtkSourceFile. */ GtkSourceFile * _ide_file_get_source_file (IdeFile *self) { g_return_val_if_fail (IDE_IS_FILE (self), NULL); if (g_once_init_enter (&self->source_file)) { GtkSourceFile *source_file; source_file = gtk_source_file_new (); gtk_source_file_set_location (source_file, self->file); g_once_init_leave (&self->source_file, source_file); } return self->source_file; }
/** * ide_build_system_get_build_flags_async: * * Asynchronously requests the build flags for a file. For autotools and C based projects, this * would be similar to the $CFLAGS variable and is suitable for generating warnings and errors * with clang. */ void ide_build_system_get_build_flags_async (IdeBuildSystem *self, IdeFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GTask) task = NULL; g_return_if_fail (IDE_IS_BUILD_SYSTEM (self)); g_return_if_fail (IDE_IS_FILE (file)); g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); if (IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_flags_async) return IDE_BUILD_SYSTEM_GET_IFACE (self)->get_build_flags_async (self, file, cancellable, callback, user_data); task = g_task_new (self, cancellable, callback, user_data); g_task_return_pointer (task, NULL, NULL); }
/** * ide_source_location_new: * @file: an #IdeFile * @line: the line number starting from zero * @line_offset: the character offset within the line * @offset: the character offset in the file * * Creates a new #IdeSourceLocation, using the file, line, column, and character * offset provided. * * Returns: (transfer full): A newly allocated #IdeSourceLocation. */ IdeSourceLocation * ide_source_location_new (IdeFile *file, guint line, guint line_offset, guint offset) { IdeSourceLocation *ret; g_return_val_if_fail (IDE_IS_FILE (file), NULL); ret = g_slice_new0 (IdeSourceLocation); ret->ref_count = 1; ret->file = g_object_ref (file); ret->line = MIN (G_MAXINT, line); ret->line_offset = MIN (G_MAXINT, line_offset); ret->offset = offset; DZL_COUNTER_INC (instances); return ret; }
static void ide_file__file_settings_settled_cb (IdeFileSettings *file_settings, GParamSpec *pspec, gpointer user_data) { g_autoptr(GTask) task = user_data; IdeFile *self; IDE_ENTRY; g_assert (IDE_IS_FILE_SETTINGS (file_settings)); g_assert (G_IS_TASK (task)); self = g_task_get_source_object (task); g_assert (IDE_IS_FILE (self)); g_signal_handlers_disconnect_by_func (file_settings, G_CALLBACK (ide_file__file_settings_settled_cb), task); g_set_object (&self->file_settings, file_settings); g_task_return_pointer (task, g_object_ref (file_settings), g_object_unref); IDE_EXIT; }
IdeFileSettings * ide_file_settings_new (IdeFile *file) { IdeFileSettingsPrivate *priv; GIOExtensionPoint *extension_point; IdeFileSettings *ret; IdeContext *context; GList *list; g_return_val_if_fail (IDE_IS_FILE (file), NULL); context = ide_object_get_context (IDE_OBJECT (file)); ret = g_object_new (IDE_TYPE_FILE_SETTINGS, "context", context, "file", file, NULL); priv = ide_file_settings_get_instance_private (ret); extension_point = g_io_extension_point_lookup (IDE_FILE_SETTINGS_EXTENSION_POINT); list = g_io_extension_point_get_extensions (extension_point); /* * Don't allow our unsettled count to hit zero until we are finished. */ priv->unsettled_count++; for (; list; list = list->next) { GIOExtension *extension = list->data; g_autoptr(IdeFileSettings) child = NULL; GType gtype; gtype = g_io_extension_get_type (extension); if (!g_type_is_a (gtype, IDE_TYPE_FILE_SETTINGS)) { g_warning ("%s is not an IdeFileSettings", g_type_name (gtype)); continue; } child = g_object_new (gtype, "file", file, "context", context, NULL); if (G_IS_INITABLE (child)) { g_autoptr(GError) error = NULL; if (!g_initable_init (G_INITABLE (child), NULL, &error)) g_warning ("%s", error->message); } else if (G_IS_ASYNC_INITABLE (child)) { priv->unsettled_count++; g_async_initable_init_async (G_ASYNC_INITABLE (child), G_PRIORITY_DEFAULT, NULL, ide_file_settings__init_cb, g_object_ref (ret)); } _ide_file_settings_append (ret, child); } priv->unsettled_count--; return ret; }
static void populate_cache (EggTaskCache *cache, gconstpointer key, GTask *task, gpointer user_data) { IdeGettextDiagnosticProvider *self = user_data; g_autoptr(IdeUnsavedFile) unsaved_file = NULL; g_autoptr(GSubprocess) subprocess = NULL; GtkSourceLanguage *language; const gchar *language_id; const gchar *xgettext_lang; const gchar *temp_path; TranslationUnit *unit; IdeFile *file = (IdeFile *)key; GCancellable *cancellable; GError *error = NULL; GPtrArray *args; g_assert (EGG_IS_TASK_CACHE (cache)); g_assert (IDE_IS_FILE (file)); g_assert (IDE_IS_GETTEXT_DIAGNOSTIC_PROVIDER (self)); cancellable = g_task_get_cancellable (task); if (NULL == (unsaved_file = get_unsaved_file (self, file))) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Failed to locate file contents"); return; } if (NULL == (language = ide_file_get_language (file)) || NULL == (language_id = gtk_source_language_get_id (language)) || NULL == (xgettext_lang = id_to_xgettext_language (language_id))) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, "Failed to determine language type"); return; } if (!ide_unsaved_file_persist (unsaved_file, cancellable, &error)) { g_task_return_error (task, error); return; } temp_path = ide_unsaved_file_get_temp_path (unsaved_file); g_assert (temp_path != NULL); args = g_ptr_array_new (); g_ptr_array_add (args, "xgettext"); g_ptr_array_add (args, "--check=ellipsis-unicode"); g_ptr_array_add (args, "--check=quote-unicode"); g_ptr_array_add (args, "--check=space-ellipsis"); g_ptr_array_add (args, "-k_"); g_ptr_array_add (args, "-kN_"); g_ptr_array_add (args, "-L"); g_ptr_array_add (args, (gchar *)xgettext_lang); g_ptr_array_add (args, "-o"); g_ptr_array_add (args, "-"); g_ptr_array_add (args, (gchar *)temp_path); g_ptr_array_add (args, NULL); #ifdef IDE_ENABLE_TRACE { g_autofree gchar *str = NULL; str = g_strjoinv (" ", (gchar **)args->pdata); IDE_TRACE_MSG ("Launching '%s'", str); } #endif subprocess = g_subprocess_newv ((const gchar * const *)args->pdata, G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE | G_SUBPROCESS_FLAGS_STDERR_PIPE, &error); g_ptr_array_free (args, TRUE); if (subprocess == NULL) { g_task_return_error (task, error); return; } unit = g_slice_new0 (TranslationUnit); unit->file = g_object_ref (file); unit->unsaved_file = ide_unsaved_file_ref (unsaved_file); g_task_set_task_data (task, unit, (GDestroyNotify)translation_unit_free); g_subprocess_wait_async (subprocess, cancellable, subprocess_wait_cb, g_object_ref (task)); }
static void ide_file_find_other_worker (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { IdeFile *self = source_object; const gchar *src_suffixes[] = { "c", "cc", "cpp", "cxx", NULL }; const gchar *hdr_suffixes[] = { "h", "hh", "hpp", "hxx", NULL }; const gchar **target = NULL; g_autofree gchar *prefix = NULL; g_autofree gchar *uri = NULL; gsize i; g_assert (IDE_IS_FILE (self)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); uri = g_file_get_uri (self->file); if (has_suffix (uri, src_suffixes)) { target = hdr_suffixes; } else if (has_suffix (uri, hdr_suffixes)) { target = src_suffixes; } else { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, "File is missing a suffix."); return; } prefix = g_strndup (uri, strrchr (uri, '.') - uri); for (i = 0; target [i]; i++) { g_autofree gchar *new_uri = NULL; g_autoptr(GFile) gfile = NULL; new_uri = g_strdup_printf ("%s.%s", prefix, target [i]); gfile = g_file_new_for_uri (new_uri); if (g_file_query_exists (gfile, cancellable)) { g_autofree gchar *path = NULL; IdeContext *context; IdeVcs *vcs; IdeFile *ret; GFile *workdir; context = ide_object_get_context (IDE_OBJECT (self)); vcs = ide_context_get_vcs (context); workdir = ide_vcs_get_working_directory (vcs); path = g_file_get_relative_path (workdir, gfile); ret = g_object_new (IDE_TYPE_FILE, "context", context, "path", path, "file", gfile, NULL); g_task_return_pointer (task, ret, g_object_unref); return; } } g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "Failed to locate other file."); }