static void ide_subprocess_supervisor_wait_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeSubprocess *subprocess = (IdeSubprocess *)object; g_autoptr(IdeSubprocessSupervisor) self = user_data; IdeSubprocessSupervisorPrivate *priv = ide_subprocess_supervisor_get_instance_private (self); g_autoptr(GError) error = NULL; g_return_if_fail (IDE_IS_SUBPROCESS_SUPERVISOR (self)); g_return_if_fail (IDE_IS_SUBPROCESS (subprocess)); if (!ide_subprocess_wait_finish (subprocess, result, &error)) g_warning ("%s", error->message); #ifdef IDE_ENABLE_TRACE { if (ide_subprocess_get_if_exited (subprocess)) IDE_TRACE_MSG ("process exited with code: %u", ide_subprocess_get_exit_status (subprocess)); else IDE_TRACE_MSG ("process terminated due to signal: %u", ide_subprocess_get_term_sig (subprocess)); } #endif /* * If we end up here in response to ide_subprocess_supervisor_reset() force * exiting the process, we won't successfully match * (priv->subprocess==subprocess) and therefore will not restart the process * immediately (allowing the caller of ide_subprocess_supervisor_reset() to * complete the operation. */ if (priv->subprocess == subprocess) { g_clear_object (&priv->subprocess); if (priv->supervising) { gint64 sleep_usec; if (ide_subprocess_supervisor_needs_rate_limit (self, &sleep_usec)) ide_subprocess_supervisor_start_in_usec (self, sleep_usec); else ide_subprocess_supervisor_start (self); } } }
void _ide_back_forward_list_load_async (IdeBackForwardList *self, GFile *file, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { g_autoptr(GTask) task = NULL; g_assert (IDE_IS_BACK_FORWARD_LIST (self)); g_assert (G_IS_FILE (file)); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); #ifdef IDE_ENABLE_TRACE { g_autofree gchar *path = NULL; path = g_file_get_path (file); IDE_TRACE_MSG ("Loading %s", path); } #endif task = g_task_new (self, cancellable, callback, user_data); g_file_load_contents_async (file, cancellable, ide_back_forward_list_load_cb, g_object_ref (task)); }
gboolean ide_unsaved_file_persist (IdeUnsavedFile *self, GCancellable *cancellable, GError **error) { gboolean ret; IDE_ENTRY; g_return_val_if_fail (self, FALSE); g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE); IDE_TRACE_MSG ("Saving draft to \"%s\"", self->temp_path); /* * TODO: Support cancellable. */ ret = g_file_set_contents (self->temp_path, g_bytes_get_data (self->content, NULL), g_bytes_get_size (self->content), error); IDE_RETURN (ret); }
static void gb_keybindings_reload (GbKeybindings *self) { const gchar *mode; g_autofree gchar *path = NULL; g_autoptr(GBytes) bytes = NULL; g_autoptr(GError) error = NULL; IDE_ENTRY; g_assert (GB_IS_KEYBINDINGS (self)); mode = self->mode ? self->mode : "default"; IDE_TRACE_MSG ("Loading %s keybindings", mode); path = g_strdup_printf ("/org/gnome/builder/keybindings/%s.css", mode); bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, &error); if (error == NULL) gtk_css_provider_load_from_data (self->css_provider, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), &error); if (error) g_warning ("%s", error->message); IDE_EXIT; }
static void ide_keybindings_load_plugin (IdeKeybindings *self, PeasPluginInfo *plugin_info, PeasEngine *engine) { g_autofree gchar *path = NULL; const gchar *module_name; g_autoptr(GBytes) bytes = NULL; g_autoptr(GtkCssProvider) provider = NULL; g_assert (IDE_IS_KEYBINDINGS (self)); g_assert (plugin_info != NULL); g_assert (PEAS_IS_ENGINE (engine)); if (!self->mode || !self->plugin_providers) return; module_name = peas_plugin_info_get_module_name (plugin_info); path = g_strdup_printf ("/org/gnome/builder/plugins/%s/keybindings/%s.css", module_name, self->mode); bytes = g_resources_lookup_data (path, 0, NULL); if (bytes == NULL) return; IDE_TRACE_MSG ("Loading %s keybindings for \"%s\" plugin", self->mode, module_name); provider = gtk_css_provider_new (); gtk_css_provider_load_from_resource (provider, path); gtk_style_context_add_provider_for_screen (gdk_screen_get_default (), GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1); g_hash_table_insert (self->plugin_providers, g_strdup (module_name), g_steal_pointer (&provider)); }
static gboolean ide_git_vcs_load_monitor (IdeGitVcs *self, GError **error) { gboolean ret = TRUE; g_assert (IDE_IS_GIT_VCS (self)); if (self->monitor == NULL) { g_autoptr(GFile) location = NULL; g_autoptr(GFileMonitor) monitor = NULL; g_autoptr(GFile) heads_dir = NULL; GFileMonitorFlags flags = G_FILE_MONITOR_WATCH_MOUNTS; location = ggit_repository_get_location (self->repository); heads_dir = g_file_get_child (location, "refs/heads"); monitor = g_file_monitor (heads_dir, flags, NULL, error); ret = !!monitor; if (monitor) { IDE_TRACE_MSG ("Git index monitor registered."); g_signal_connect_object (monitor, "changed", G_CALLBACK (ide_git_vcs__monitor_changed_cb), self, G_CONNECT_SWAPPED); self->monitor = g_object_ref (monitor); } } return ret; }
static void ide_worker_manager_constructed (GObject *object) { IdeWorkerManager *self = (IdeWorkerManager *)object; g_autofree gchar *guid = NULL; g_autofree gchar *address = NULL; GError *error = NULL; g_assert (IDE_IS_WORKER_MANAGER (self)); G_OBJECT_CLASS (ide_worker_manager_parent_class)->constructed (object); if (g_unix_socket_address_abstract_names_supported ()) { address = g_strdup_printf ("unix:abstract=/tmp/gnome-builder-%u", (int)getpid ()); } else { g_autofree gchar *tmpdir = NULL; tmpdir = g_dir_make_tmp ("gnome-builder-worker-XXXXXX", NULL); if (tmpdir == NULL) { g_error ("Failed to determine temporary directory for DBus."); exit (EXIT_FAILURE); } address = g_strdup_printf ("unix:tmpdir=%s", tmpdir); } guid = g_dbus_generate_guid (); self->dbus_server = g_dbus_server_new_sync (address, G_DBUS_SERVER_FLAGS_NONE, guid, NULL, NULL, &error); if (error != NULL) { g_error ("%s", error->message); exit (EXIT_FAILURE); } g_signal_connect_object (self->dbus_server, "new-connection", G_CALLBACK (ide_worker_manager_new_connection_cb), self, G_CONNECT_SWAPPED); IDE_TRACE_MSG ("GDBusServer listening at %s", address); g_dbus_server_start (self->dbus_server); g_assert (g_dbus_server_is_active (self->dbus_server)); }
static void provider_entry_destroy (gpointer data) { ProviderEntry *entry = data; IDE_ENTRY; IDE_TRACE_MSG ("releasing %p", data); ide_clear_weak_pointer (&entry->group); g_clear_object (&entry->provider); g_free (entry); IDE_EXIT; }
static void ide_workbench_addin_added (PeasExtensionSet *set, PeasPluginInfo *plugin_info, PeasExtension *extension, gpointer user_data) { IdeWorkbench *self = user_data; g_assert (PEAS_IS_EXTENSION_SET (set)); g_assert (plugin_info != NULL); g_assert (IDE_IS_WORKBENCH_ADDIN (extension)); g_assert (IDE_IS_WORKBENCH (self)); IDE_TRACE_MSG ("Loading workbench addin for %s", peas_plugin_info_get_module_name (plugin_info)); ide_workbench_addin_load (IDE_WORKBENCH_ADDIN (extension), self); }
static void ide_clang_service__get_build_flags_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeBuildSystem *build_system = (IdeBuildSystem *)object; g_autoptr(GTask) task = user_data; ParseRequest *request; gchar **argv; GError *error = NULL; g_assert (IDE_IS_BUILD_SYSTEM (build_system)); g_assert (G_IS_TASK (task)); request = g_task_get_task_data (task); argv = ide_build_system_get_build_flags_finish (build_system, result, &error); if (!argv) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) g_message ("%s", error->message); g_clear_error (&error); argv = g_new0 (gchar*, 1); } request->command_line_args = argv; #ifdef IDE_ENABLE_TRACE { gchar *cflags; cflags = g_strjoinv (" ", argv); IDE_TRACE_MSG ("CFLAGS = %s", cflags); g_free (cflags); } #endif ide_thread_pool_push_task (IDE_THREAD_POOL_COMPILER, task, ide_clang_service_parse_worker); }
static gboolean ide_git_vcs_load_monitor_locked (IdeGitVcs *self, GError **error) { gboolean ret = TRUE; g_assert (IDE_IS_GIT_VCS (self)); if (self->monitor == NULL) { g_autoptr(GFile) location = NULL; g_autoptr(GFileMonitor) monitor = NULL; GError *local_error = NULL; location = ggit_repository_get_location (self->repository); monitor = g_file_monitor_directory (location, G_FILE_MONITOR_NONE, NULL, &local_error); if (monitor == NULL) { g_warning ("Failed to establish git monitor: %s", local_error->message); g_propagate_error (error, local_error); ret = FALSE; } else { IDE_TRACE_MSG ("Git index monitor registered."); g_signal_connect_object (monitor, "changed", G_CALLBACK (ide_git_vcs__monitor_changed_cb), self, G_CONNECT_SWAPPED); self->monitor = g_steal_pointer (&monitor); } } return ret; }
void ide_run_manager_set_handler (IdeRunManager *self, const gchar *id) { g_return_if_fail (IDE_IS_RUN_MANAGER (self)); self->handler = NULL; for (GList *iter = self->handlers; iter; iter = iter->next) { const IdeRunHandlerInfo *info = iter->data; if (g_strcmp0 (info->id, id) == 0) { self->handler = info; IDE_TRACE_MSG ("run handler set to %s", info->title); g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_HANDLER]); break; } } }
static void gb_vim_complete_colorscheme (const gchar *line, GPtrArray *ar) { GtkSourceStyleSchemeManager *manager; const gchar * const *scheme_ids; const gchar *tmp; g_autofree gchar *prefix = NULL; gsize i; manager = gtk_source_style_scheme_manager_get_default (); scheme_ids = gtk_source_style_scheme_manager_get_scheme_ids (manager); for (tmp = strchr (line, ' '); tmp && *tmp && g_unichar_isspace (g_utf8_get_char (tmp)); tmp = g_utf8_next_char (tmp)) { /* do nothing */ } if (!tmp) return; prefix = g_strndup (line, tmp - line); for (i = 0; scheme_ids [i]; i++) { const gchar *scheme_id = scheme_ids [i]; if (g_str_has_prefix (scheme_id, tmp)) { gchar *item; item = g_strdup_printf ("%s%s", prefix, scheme_id); IDE_TRACE_MSG ("colorscheme: %s", item); g_ptr_array_add (ar, item); } } }
static void ide_language_defaults_init_worker (GTask *task, gpointer source_object, gpointer task_data, GCancellable *cancellable) { g_autofree gchar *version_path = NULL; g_autofree gchar *version_contents = NULL; g_autofree gchar *version_dir = NULL; g_autoptr(GBytes) defaults = NULL; g_autoptr(GKeyFile) key_file = NULL; gint global_version; gboolean ret; GError *error = NULL; gint current_version; IDE_ENTRY; g_assert (G_IS_TASK (task)); g_assert (source_object == NULL); g_assert (task_data == NULL); g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); version_path = g_build_filename (g_get_user_config_dir (), ide_get_program_name (), "syntax", ".defaults", NULL); current_version = ide_language_defaults_get_current_version (version_path, &error); if (current_version < 0) { g_task_return_error (task, error); goto failure; } defaults = ide_language_defaults_get_defaults (&error); if (!defaults) { g_task_return_error (task, error); goto failure; } key_file = g_key_file_new (); ret = g_key_file_load_from_data (key_file, g_bytes_get_data (defaults, NULL), g_bytes_get_size (defaults), G_KEY_FILE_NONE, &error); if (!ret) { g_task_return_error (task, error); goto failure; } if (!g_key_file_has_group (key_file, "global") || !g_key_file_has_key (key_file, "global", "version", NULL)) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, _("language defaults missing version in [global] group.")); goto failure; } global_version = g_key_file_get_integer (key_file, "global", "version", &error); if ((global_version == 0) && error) { g_task_return_error (task, error); goto failure; } if (global_version > current_version) { if (!ide_language_defaults_migrate (key_file, current_version, global_version, &error)) { g_task_return_error (task, error); goto failure; } version_contents = g_strdup_printf ("%d", global_version); version_dir = g_path_get_dirname (version_path); if (!g_file_test (version_dir, G_FILE_TEST_IS_DIR)) { if (g_mkdir_with_parents (version_dir, 0750) == -1) { g_task_return_new_error (task, G_IO_ERROR, g_io_error_from_errno (errno), "%s", g_strerror (errno)); goto failure; } } IDE_TRACE_MSG ("Writing new language defaults version to \"%s\"", version_path); if (!g_file_set_contents (version_path, version_contents, -1, &error)) { g_task_return_error (task, error); goto failure; } } g_task_return_boolean (task, TRUE); { GList *list; GList *iter; G_LOCK (lock); initializing = FALSE; initialized = TRUE; list = tasks; tasks = NULL; G_UNLOCK (lock); for (iter = list; iter; iter = iter->next) { g_task_return_boolean (iter->data, TRUE); g_object_unref (iter->data); } g_list_free (list); } IDE_EXIT; failure: { GList *list; GList *iter; G_LOCK (lock); initializing = FALSE; initialized = TRUE; list = tasks; tasks = NULL; G_UNLOCK (lock); for (iter = list; iter; iter = iter->next) { g_task_return_new_error (iter->data, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to initialize defaults.")); g_object_unref (iter->data); } g_list_free (list); } IDE_EXIT; }
static void ide_lsp_formatter_apply_changes (IdeLspFormatter *self, IdeBuffer *buffer, GVariant *text_edits) { g_autoptr(GPtrArray) edits = NULL; g_autoptr(IdeContext) context = NULL; IdeBufferManager *buffer_manager; GVariant *text_edit; GFile *file; GVariantIter iter; IDE_ENTRY; g_assert (IDE_IS_LSP_FORMATTER (self)); g_assert (text_edits != NULL); if (!g_variant_is_container (text_edits)) { g_warning ("variant is not a container, ignoring"); IDE_EXIT; } file = ide_buffer_get_file (buffer); edits = g_ptr_array_new_with_free_func (g_object_unref); g_variant_iter_init (&iter, text_edits); while (g_variant_iter_loop (&iter, "v", &text_edit)) { g_autoptr(IdeLocation) begin_location = NULL; g_autoptr(IdeLocation) end_location = NULL; g_autoptr(IdeRange) range = NULL; const gchar *new_text = NULL; gboolean success; struct { gint64 line; gint64 column; } begin, end; success = JSONRPC_MESSAGE_PARSE (text_edit, "range", "{", "start", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line), "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column), "}", "end", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&end.line), "character", JSONRPC_MESSAGE_GET_INT64 (&end.column), "}", "}", "newText", JSONRPC_MESSAGE_GET_STRING (&new_text) ); if (!success) { IDE_TRACE_MSG ("Failed to extract change from variant"); continue; } begin_location = ide_location_new (file, begin.line, begin.column); end_location = ide_location_new (file, end.line, end.column); range = ide_range_new (begin_location, end_location); g_ptr_array_add (edits, ide_text_edit_new (range, new_text)); } context = ide_buffer_ref_context (buffer); buffer_manager = ide_buffer_manager_from_context (context); ide_buffer_manager_apply_edits_async (buffer_manager, IDE_PTR_ARRAY_STEAL_FULL (&edits), NULL, NULL, NULL); IDE_EXIT; }
static void gb_vim_complete_edit_files (GtkWidget *active_widget, const gchar *command, GPtrArray *ar, const gchar *prefix) { IdeWorkbench *workbench; IdeContext *context; IdeVcs *vcs; GFile *workdir; g_autoptr(GFile) child = NULL; g_autoptr(GFile) parent = NULL; IDE_ENTRY; g_assert (command); g_assert (ar); g_assert (prefix); if (!(workbench = ide_widget_get_workbench (GTK_WIDGET (active_widget))) || !(context = ide_workbench_get_context (workbench)) || !(vcs = ide_context_get_vcs (context)) || !(workdir = ide_vcs_get_working_directory (vcs))) IDE_EXIT; child = g_file_get_child (workdir, prefix); if (g_file_query_exists (child, NULL)) { if (g_file_query_file_type (child, 0, NULL) == G_FILE_TYPE_DIRECTORY) { g_autoptr(GFileEnumerator) fe = NULL; GFileInfo *descendent; if (!g_str_has_suffix (prefix, "/")) { g_ptr_array_add (ar, g_strdup_printf ("%s %s/", command, prefix)); IDE_EXIT; } fe = g_file_enumerate_children (child, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (fe == NULL) IDE_EXIT; while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL))) { const gchar *name; name = g_file_info_get_display_name (descendent); g_ptr_array_add (ar, g_strdup_printf ("%s %s%s", command, prefix, name)); g_object_unref (descendent); } IDE_EXIT; } } parent = g_file_get_parent (child); if (parent != NULL) { g_autoptr(GFileEnumerator) fe = NULL; GFileInfo *descendent; const gchar *slash; const gchar *partial_name; g_autofree gchar *prefix_dir = NULL; #ifdef IDE_ENABLE_TRACE { g_autofree gchar *parent_path = g_file_get_path (parent); IDE_TRACE_MSG ("parent_path: %s", parent_path); } #endif if ((slash = strrchr (prefix, G_DIR_SEPARATOR))) { partial_name = slash + 1; prefix_dir = g_strndup (prefix, slash - prefix + 1); } else { partial_name = prefix; } fe = g_file_enumerate_children (parent, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (fe == NULL) IDE_EXIT; while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL))) { const gchar *name; name = g_file_info_get_display_name (descendent); IDE_TRACE_MSG ("name=%s prefix=%s", name, prefix); if (name && g_str_has_prefix (name, partial_name)) { gchar *completed_command; const gchar *descendent_name; g_autofree gchar *full_path = NULL; g_autofree gchar *parent_path = NULL; parent_path = g_file_get_path (parent); descendent_name = g_file_info_get_name (descendent); full_path = g_build_filename (parent_path, descendent_name, NULL); if (prefix[0] == G_DIR_SEPARATOR) completed_command = g_strdup_printf ("%s %s", command, full_path); else if (strchr (prefix, G_DIR_SEPARATOR) == NULL) completed_command = g_strdup_printf ("%s %s", command, descendent_name); else completed_command = g_strdup_printf ("%s %s%s", command, prefix_dir, descendent_name); IDE_TRACE_MSG ("edit completion: %s", completed_command); g_ptr_array_add (ar, completed_command); } g_object_unref (descendent); } IDE_EXIT; } IDE_EXIT; }
static void ide_frame_pan_end (IdeFrame *self, GdkEventSequence *sequence, GtkGesturePan *gesture) { IdeFramePrivate *priv = ide_frame_get_instance_private (self); IdeFramePrivate *dest_priv; IdeFrame *dest; GtkAllocation alloc; GtkWidget *grid; GtkWidget *column; gdouble x, y; gint direction; gint index = 0; IDE_ENTRY; g_assert (IDE_IS_FRAME (self)); g_assert (GTK_IS_GESTURE_PAN (gesture)); if (priv->pan_theatric == NULL || priv->pan_page == NULL) IDE_GOTO (cleanup); gtk_widget_get_allocation (GTK_WIDGET (self), &alloc); gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (gesture), &x, &y); if (x > DISTANCE_THRESHOLD (&alloc)) direction = 1; else if (x < -DISTANCE_THRESHOLD (&alloc)) direction = -1; else direction = 0; grid = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_GRID); g_assert (grid != NULL); g_assert (IDE_IS_GRID (grid)); column = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_GRID_COLUMN); g_assert (column != NULL); g_assert (IDE_IS_GRID_COLUMN (column)); gtk_container_child_get (GTK_CONTAINER (grid), GTK_WIDGET (column), "index", &index, NULL); dest = _ide_grid_get_nth_stack (IDE_GRID (grid), index + direction); dest_priv = ide_frame_get_instance_private (dest); g_assert (dest != NULL); g_assert (IDE_IS_FRAME (dest)); gtk_widget_get_allocation (GTK_WIDGET (dest), &alloc); if (!is_uninitialized (&alloc)) { AnimationState *state; state = g_slice_new0 (AnimationState); state->source = g_object_ref (self); state->dest = g_object_ref (dest); state->page = g_object_ref (priv->pan_page); state->theatric = g_object_ref (priv->pan_theatric); gtk_widget_translate_coordinates (GTK_WIDGET (dest_priv->top_stack), grid, 0, 0, &alloc.x, &alloc.y); /* * Use EASE_OUT_CUBIC, because user initiated the beginning of the * acceleration curve just by swiping. No need to duplicate. */ dzl_object_animate_full (state->theatric, DZL_ANIMATION_EASE_OUT_CUBIC, TRANSITION_DURATION, gtk_widget_get_frame_clock (GTK_WIDGET (self)), animation_state_complete, state, "x", alloc.x, "width", alloc.width, NULL); if (dest != self) { g_ptr_array_add (priv->in_transition, g_object_ref (priv->pan_page)); gtk_container_remove (GTK_CONTAINER (priv->stack), GTK_WIDGET (priv->pan_page)); } IDE_TRACE_MSG ("Animating transition to %s column", dest != self ? "another" : "same"); } else { g_autoptr(IdePage) page = g_object_ref (priv->pan_page); IDE_TRACE_MSG ("Moving page to a previously non-existant column"); gtk_container_remove (GTK_CONTAINER (priv->stack), GTK_WIDGET (page)); gtk_widget_show (GTK_WIDGET (page)); gtk_container_add (GTK_CONTAINER (dest_priv->stack), GTK_WIDGET (page)); } cleanup: g_clear_object (&priv->pan_theatric); g_clear_object (&priv->pan_page); gtk_widget_queue_draw (gtk_widget_get_toplevel (GTK_WIDGET (self))); ide_frame_set_cursor (self, "arrow"); IDE_EXIT; }
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_editor_perspective_focus_location_full (IdeEditorPerspective *self, IdeSourceLocation *location, gboolean open_if_not_found) { struct { IdeFile *file; IdeEditorView *view; } lookup = { 0 }; GtkWidget *stack; guint line; guint line_offset; IDE_ENTRY; g_assert (IDE_IS_EDITOR_PERSPECTIVE (self)); g_assert (location != NULL); lookup.file = ide_source_location_get_file (location); lookup.view = NULL; if (lookup.file == NULL) { g_warning ("IdeSourceLocation does not contain a file"); IDE_EXIT; } #ifdef IDE_ENABLE_TRACE { const gchar *path = ide_file_get_path (lookup.file); IDE_TRACE_MSG ("Locating %s, open_if_not_found=%d", path, open_if_not_found); } #endif ide_perspective_views_foreach (IDE_PERSPECTIVE (self), ide_editor_perspective_find_source_location, &lookup); if (!open_if_not_found && lookup.view == NULL) IDE_EXIT; if (lookup.view == NULL) { FocusLocation *state; IdeBufferManager *bufmgr; IdeWorkbench *workbench; IdeContext *context; workbench = ide_widget_get_workbench (GTK_WIDGET (self)); context = ide_workbench_get_context (workbench); bufmgr = ide_context_get_buffer_manager (context); state = g_slice_new0 (FocusLocation); state->self = g_object_ref (self); state->location = ide_source_location_ref (location); ide_buffer_manager_load_file_async (bufmgr, lookup.file, FALSE, IDE_WORKBENCH_OPEN_FLAGS_NONE, NULL, NULL, ide_editor_perspective_focus_location_cb, state); IDE_EXIT; } line = ide_source_location_get_line (location); line_offset = ide_source_location_get_line_offset (location); stack = gtk_widget_get_ancestor (GTK_WIDGET (lookup.view), IDE_TYPE_LAYOUT_STACK); ide_layout_stack_set_visible_child (IDE_LAYOUT_STACK (stack), IDE_LAYOUT_VIEW (lookup.view)); ide_editor_view_scroll_to_line_offset (lookup.view, line, line_offset); IDE_EXIT; }
static void ide_keybindings_reload (IdeKeybindings *self) { GdkScreen *screen; PeasEngine *engine; const GList *list; IDE_ENTRY; g_assert (IDE_IS_KEYBINDINGS (self)); { g_autofree gchar *path = NULL; g_autoptr(GBytes) bytes = NULL; g_autoptr(GError) error = NULL; if (self->mode == NULL) self->mode = g_strdup ("default"); IDE_TRACE_MSG ("Loading %s keybindings", self->mode); path = g_strdup_printf ("/org/gnome/builder/keybindings/%s.css", self->mode); bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, &error); if (error == NULL) { /* * We use -1 for the length so that the CSS provider knows that the * string is \0 terminated. This is guaranteed to us by GResources so * that interned data can be used as C strings. */ gtk_css_provider_load_from_data (self->css_provider, g_bytes_get_data (bytes, NULL), -1, &error); } if (error) g_warning ("%s", error->message); } engine = peas_engine_get_default (); screen = gdk_screen_get_default (); if (self->plugin_providers != NULL) { GHashTableIter iter; GtkStyleProvider *provider; g_hash_table_iter_init (&iter, self->plugin_providers); while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&provider)) gtk_style_context_remove_provider_for_screen (screen, provider); g_clear_pointer (&self->plugin_providers, g_hash_table_unref); } self->plugin_providers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); list = peas_engine_get_plugin_list (engine); for (; list != NULL; list = list->next) { PeasPluginInfo *plugin_info = list->data; if (!peas_plugin_info_is_loaded (plugin_info)) continue; ide_keybindings_load_plugin (self, plugin_info, engine); } IDE_EXIT; }
static void ide_langserv_completion_provider_complete_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeLangservClient *client = (IdeLangservClient *)object; g_autoptr(CompletionState) state = user_data; g_autoptr(GVariant) return_value = NULL; g_autoptr(GError) error = NULL; GVariant *node; GList *list = NULL; GVariantIter iter; IDE_ENTRY; g_assert (IDE_IS_LANGSERV_CLIENT (client)); g_assert (G_IS_ASYNC_RESULT (result)); g_assert (state != NULL); g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (state->self)); g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (state->context)); if (!ide_langserv_client_call_finish (client, result, &return_value, &error)) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) g_message ("%s", error->message); IDE_GOTO (failure); } /* * TODO: We will want to make a much more optimized version of this using * the other completion result work we've done. */ g_variant_iter_init (&iter, return_value); while (g_variant_iter_loop (&iter, "v", &node)) { g_autoptr(GtkSourceCompletionItem) item = NULL; g_autofree gchar *full_label = NULL; const gchar *label; const gchar *detail; const gchar *icon_name = NULL; gboolean success; gint64 kind = 0; success = JSONRPC_MESSAGE_PARSE (node, "label", JSONRPC_MESSAGE_GET_STRING (&label), "detail", JSONRPC_MESSAGE_GET_STRING (&detail) ); if (!success) { IDE_TRACE_MSG ("Failed to extract completion item from node"); continue; } /* Optional kind field */ JSONRPC_MESSAGE_PARSE (node, "kind", JSONRPC_MESSAGE_GET_INT64 (&kind)); kind = ide_langserv_decode_completion_kind (kind); if (kind != IDE_SYMBOL_NONE) icon_name = ide_symbol_kind_get_icon_name (kind); if (label != NULL && detail != NULL) full_label = g_strdup_printf ("%s : %s", label, detail); else full_label = g_strdup (label); //item = gtk_source_completion_item_new (full_label, label, NULL, NULL); item = g_object_new (GTK_SOURCE_TYPE_COMPLETION_ITEM, "icon-name", icon_name, "label", full_label, "text", label, NULL); list = g_list_prepend (list, g_steal_pointer (&item)); } failure: gtk_source_completion_context_add_proposals (state->context, GTK_SOURCE_COMPLETION_PROVIDER (state->self), list, TRUE); g_list_free_full (list, g_object_unref); IDE_EXIT; }
static void ide_langserv_completion_provider_populate (GtkSourceCompletionProvider *provider, GtkSourceCompletionContext *context) { IdeLangservCompletionProvider *self = (IdeLangservCompletionProvider *)provider; IdeLangservCompletionProviderPrivate *priv = ide_langserv_completion_provider_get_instance_private (self); g_autoptr(GVariant) params = NULL; g_autoptr(GCancellable) cancellable = NULL; g_autoptr(CompletionState) state = NULL; g_autofree gchar *uri = NULL; GtkTextIter iter; IdeBuffer *buffer; gint line; gint column; IDE_ENTRY; g_assert (IDE_IS_LANGSERV_COMPLETION_PROVIDER (self)); g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context)); if (priv->client == NULL) { IDE_TRACE_MSG ("No client set, cannot provide proposals"); gtk_source_completion_context_add_proposals (context, provider, NULL, TRUE); IDE_EXIT; } gtk_source_completion_context_get_iter (context, &iter); buffer = IDE_BUFFER (gtk_text_iter_get_buffer (&iter)); uri = ide_buffer_get_uri (buffer); line = gtk_text_iter_get_line (&iter); column = gtk_text_iter_get_line_offset (&iter); params = JSONRPC_MESSAGE_NEW ( "textDocument", "{", "uri", JSONRPC_MESSAGE_PUT_STRING (uri), "}", "position", "{", "line", JSONRPC_MESSAGE_PUT_INT32 (line), "character", JSONRPC_MESSAGE_PUT_INT32 (column), "}" ); cancellable = g_cancellable_new (); g_signal_connect_data (context, "cancelled", G_CALLBACK (g_cancellable_cancel), g_object_ref (cancellable), (GClosureNotify)g_object_unref, G_CONNECT_SWAPPED); state = completion_state_new (self, context); ide_langserv_client_call_async (priv->client, "textDocument/completion", g_steal_pointer (¶ms), g_steal_pointer (&cancellable), ide_langserv_completion_provider_complete_cb, g_steal_pointer (&state)); IDE_EXIT; }
static void ide_ctags_completion_provider_populate (GtkSourceCompletionProvider *provider, GtkSourceCompletionContext *context) { IdeCtagsCompletionProvider *self = (IdeCtagsCompletionProvider *)provider; g_autofree gchar *word = NULL; const IdeCtagsIndexEntry *entries; const gchar * const *allowed; g_autoptr(GPtrArray) ar = NULL; IdeCtagsIndexEntry *last = NULL; GtkSourceBuffer *buffer; gsize n_entries; GtkTextIter iter; GList *list = NULL; gsize i; gsize j; IDE_ENTRY; g_assert (IDE_IS_CTAGS_COMPLETION_PROVIDER (self)); g_assert (GTK_SOURCE_IS_COMPLETION_CONTEXT (context)); if (self->indexes->len == 0) IDE_GOTO (failure); if (!g_settings_get_boolean (self->settings, "ctags-autocompletion")) IDE_GOTO (failure); if (!gtk_source_completion_context_get_iter (context, &iter)) IDE_GOTO (failure); buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (&iter)); allowed = get_allowed_suffixes (buffer); word = get_word_to_cursor (&iter); if (ide_str_empty0 (word) || strlen (word) < self->minimum_word_size) IDE_GOTO (failure); if (strlen (word) < 3) IDE_GOTO (failure); ar = g_ptr_array_new (); IDE_TRACE_MSG ("Searching for %s", word); for (j = 0; j < self->indexes->len; j++) { IdeCtagsIndex *index = g_ptr_array_index (self->indexes, j); entries = ide_ctags_index_lookup_prefix (index, word, &n_entries); if ((entries == NULL) || (n_entries == 0)) continue; for (i = 0; i < n_entries; i++) { const IdeCtagsIndexEntry *entry = &entries [i]; if (is_allowed (entry, allowed)) g_ptr_array_add (ar, (gpointer)entry); } } g_ptr_array_sort (ar, sort_wrapper); for (i = ar->len; i > 0; i--) { GtkSourceCompletionProposal *item; IdeCtagsIndexEntry *entry = g_ptr_array_index (ar, i - 1); /* * NOTE: * * We walk backwards in this ptrarray so that we can use g_list_prepend() for O(1) access. * I think everyone agrees that using GList for passing completion data around was not * a great choice, but it is what we have to work with. */ /* * Ignore this item if the previous one looks really similar. * We take the first item instead of the last since the first item (when walking backwards) * tends to be more likely to be the one we care about (based on lexicographical * ordering. For example, something in "gtk-2.0" is less useful than "gtk-3.0". * * This is done here instead of during our initial object creation so that * we can merge items between different indexes. It often happens that the * same headers are included in multiple tags files. */ if ((last != NULL) && too_similar (entry, last)) continue; /* * NOTE: * * Autocompletion is very performance sensitive code. The smallest amount of * extra work has a very negative impact on interactivity. We are trying to * avoid a couple things here based on how completion works. * * 1) Avoiding referencing or copying things. * Since the provider will always outlive the completion item, we use * borrowed references for as much as we can. * 2) We delay the work of looking up icons until they are requested. * No sense in doing that work before hand. */ item = ide_ctags_completion_item_new (entry, self, context); list = g_list_prepend (list, item); last = entry; } failure: gtk_source_completion_context_add_proposals (context, provider, list, TRUE); g_list_free_full (list, g_object_unref); IDE_EXIT; }
void _ide_source_view_apply_movement (IdeSourceView *self, IdeSourceViewMovement movement, gboolean extend_selection, gboolean exclusive, guint count, gunichar command, gunichar modifier, gunichar search_char, gint *target_offset) { Movement mv = { 0 }; GtkTextBuffer *buffer; GtkTextMark *insert; gsize i; g_return_if_fail (IDE_IS_SOURCE_VIEW (self)); #ifdef IDE_ENABLE_TRACE { GEnumValue *enum_value; GEnumClass *enum_class; enum_class = g_type_class_ref (IDE_TYPE_SOURCE_VIEW_MOVEMENT); enum_value = g_enum_get_value (enum_class, movement); IDE_TRACE_MSG ("movement(%s, extend_selection=%s, exclusive=%s, count=%u)", enum_value->value_nick, extend_selection ? "YES" : "NO", exclusive ? "YES" : "NO", count); g_type_class_unref (enum_class); } #endif buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self)); insert = gtk_text_buffer_get_insert (buffer); mv.self = self; mv.target_offset = target_offset; mv.type = movement; mv.extend_selection = extend_selection; mv.exclusive = exclusive; mv.count = count; mv.ignore_select = FALSE; mv.ignore_target_offset = FALSE; mv.command = command; mv.modifier = modifier; ide_source_view_movements_get_selection (&mv); switch (movement) { case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_OFFSET: gtk_text_iter_backward_chars (&mv.insert, MAX (1, mv.count)); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_OFFSET: gtk_text_iter_forward_chars (&mv.insert, MAX (1, mv.count)); break; case IDE_SOURCE_VIEW_MOVEMENT_NTH_CHAR: ide_source_view_movements_nth_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_CHAR: ide_source_view_movements_previous_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_CHAR: ide_source_view_movements_next_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_FIRST_CHAR: ide_source_view_movements_first_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_FIRST_NONSPACE_CHAR: ide_source_view_movements_first_nonspace_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_MIDDLE_CHAR: ide_source_view_movements_middle_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LAST_CHAR: ide_source_view_movements_last_char (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_FULL_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_full_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_FULL_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_full_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_FULL_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_full_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_FULL_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_full_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_SUB_WORD_START: gtk_text_iter_backward_visible_word_starts (&mv.insert, MAX (1, mv.count)); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_SUB_WORD_START: if (!gtk_text_iter_forward_visible_word_ends (&mv.insert, MAX (1, mv.count))) gtk_text_iter_forward_to_line_end (&mv.insert); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_WORD_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_word_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_WORD_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_word_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SENTENCE_START: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_sentence_start (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SENTENCE_END: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_sentence_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PARAGRAPH_START: for (i = MAX (1, mv.count); i > 0; i--) { mv.exclusive = exclusive && i == 1; ide_source_view_movements_paragraph_start (&mv); } break; case IDE_SOURCE_VIEW_MOVEMENT_PARAGRAPH_END: for (i = MAX (1, mv.count); i > 0; i--) { mv.exclusive = exclusive && i == 1; ide_source_view_movements_paragraph_end (&mv); } break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_LINE: mv.ignore_target_offset = TRUE; mv.ignore_select = TRUE; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_LINE: mv.ignore_target_offset = TRUE; mv.ignore_select = TRUE; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_FIRST_LINE: ide_source_view_movements_first_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_NTH_LINE: ide_source_view_movements_nth_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LAST_LINE: ide_source_view_movements_last_line (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LINE_PERCENTAGE: ide_source_view_movements_line_percentage (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LINE_CHARS: ide_source_view_movements_line_chars (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_LINE_END: ide_source_view_movements_line_end (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_HALF_PAGE_UP: case IDE_SOURCE_VIEW_MOVEMENT_HALF_PAGE_DOWN: case IDE_SOURCE_VIEW_MOVEMENT_PAGE_UP: case IDE_SOURCE_VIEW_MOVEMENT_PAGE_DOWN: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_move_page (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_DOWN: case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_UP: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_scroll (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_TOP: ide_source_view_movements_screen_top (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_MIDDLE: ide_source_view_movements_screen_middle (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCREEN_BOTTOM: ide_source_view_movements_screen_bottom (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_MATCH_SPECIAL: ide_source_view_movements_match_special (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_TOP: case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_CENTER: case IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_BOTTOM: ide_source_view_movements_scroll_center (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_UNMATCHED_BRACE: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_unmatched (&mv, '{', '}'); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_UNMATCHED_BRACE: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_unmatched (&mv, '}', '{'); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_UNMATCHED_PAREN: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_unmatched (&mv, '(', ')'); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_UNMATCHED_PAREN: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_unmatched (&mv, ')', '('); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_MODIFIER: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_next_match_modifier (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_MODIFIER: for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movements_previous_match_modifier (&mv); break; case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_SEARCH_CHAR: mv.modifier = search_char; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movement_match_search_char (&mv, FALSE); break; case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_SEARCH_CHAR: mv.modifier = search_char; for (i = MAX (1, mv.count); i > 0; i--) ide_source_view_movement_match_search_char (&mv, TRUE); break; default: g_return_if_reached (); } if (!mv.ignore_select) ide_source_view_movements_select_range (&mv); if (!mv.ignore_target_offset) *target_offset = gtk_text_iter_get_line_offset (&mv.insert); if (!mv.ignore_scroll_to_insert) ide_source_view_scroll_mark_onscreen (self, insert, TRUE, 0.5, 0.5); }
static void gb_vim_complete_edit_files (GtkSourceView *source_view, const gchar *command, GPtrArray *ar, const gchar *prefix) { GbWorkbench *workbench; IdeContext *context; IdeVcs *vcs; GFile *workdir; g_autoptr(GFile) child = NULL; g_autoptr(GFile) parent = NULL; IDE_ENTRY; g_assert (command); g_assert (ar); g_assert (prefix); if (!(workbench = gb_widget_get_workbench (GTK_WIDGET (source_view))) || !(context = gb_workbench_get_context (workbench)) || !(vcs = ide_context_get_vcs (context)) || !(workdir = ide_vcs_get_working_directory (vcs))) IDE_EXIT; child = g_file_get_child (workdir, prefix); if (g_file_query_exists (child, NULL)) { if (g_file_query_file_type (child, 0, NULL) == G_FILE_TYPE_DIRECTORY) { g_autoptr(GFileEnumerator) fe = NULL; GFileInfo *descendent; if (!g_str_has_suffix (prefix, "/")) { g_ptr_array_add (ar, g_strdup_printf ("%s %s/", command, prefix)); IDE_EXIT; } fe = g_file_enumerate_children (child, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (fe == NULL) IDE_EXIT; while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL))) { const gchar *name; name = g_file_info_get_display_name (descendent); g_ptr_array_add (ar, g_strdup_printf ("%s %s%s", command, prefix, name)); g_object_unref (descendent); } IDE_EXIT; } } parent = g_file_get_parent (child); if (parent != NULL) { g_autoptr(GFileEnumerator) fe = NULL; g_autofree gchar *relpath = NULL; GFileInfo *descendent; const gchar *slash; relpath = g_file_get_relative_path (workdir, parent); if (relpath && g_str_has_prefix (relpath, "./")) { gchar *tmp = relpath; relpath = g_strdup (relpath + 2); g_free (tmp); } #ifdef IDE_ENABLE_TRACE { g_autofree gchar *parent_path = g_file_get_path (parent); IDE_TRACE_MSG ("parent_path: %s", parent_path); } #endif if ((slash = strrchr (prefix, G_DIR_SEPARATOR))) prefix = slash + 1; fe = g_file_enumerate_children (parent, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, G_FILE_QUERY_INFO_NONE, NULL, NULL); if (fe == NULL) IDE_EXIT; while ((descendent = g_file_enumerator_next_file (fe, NULL, NULL))) { const gchar *name; name = g_file_info_get_display_name (descendent); IDE_TRACE_MSG ("name=%s prefix=%s", name, prefix); if (name && g_str_has_prefix (name, prefix)) { gchar *path; if (relpath) path = g_strdup_printf ("%s %s/%s", command, relpath, name); else path = g_strdup_printf ("%s %s", command, name); IDE_TRACE_MSG ("edit completion: %s", path); g_ptr_array_add (ar, path); } g_object_unref (descendent); } IDE_EXIT; } IDE_EXIT; }
static gboolean ide_highlight_engine_tick (IdeHighlightEngine *self) { GtkTextBuffer *buffer; GtkTextIter iter; GtkTextIter invalid_begin; GtkTextIter invalid_end; GSList *tags_iter; IDE_PROBE; g_assert (IDE_IS_HIGHLIGHT_ENGINE (self)); g_assert (self->buffer != NULL); g_assert (self->highlighter != NULL); g_assert (self->invalid_begin != NULL); g_assert (self->invalid_end != NULL); self->quanta_expiration = g_get_monotonic_time () + HIGHLIGHT_QUANTA_USEC; buffer = GTK_TEXT_BUFFER (self->buffer); gtk_text_buffer_get_iter_at_mark (buffer, &invalid_begin, self->invalid_begin); gtk_text_buffer_get_iter_at_mark (buffer, &invalid_end, self->invalid_end); IDE_TRACE_MSG ("Highlight Range [%u:%u,%u:%u] (%s)", gtk_text_iter_get_line (&invalid_begin), gtk_text_iter_get_line_offset (&invalid_begin), gtk_text_iter_get_line (&invalid_end), gtk_text_iter_get_line_offset (&invalid_end), G_OBJECT_TYPE_NAME (self->highlighter)); if (gtk_text_iter_compare (&invalid_begin, &invalid_end) >= 0) IDE_GOTO (up_to_date); /*Clear all our tags*/ for (tags_iter = self->private_tags; tags_iter; tags_iter = tags_iter->next) gtk_text_buffer_remove_tag (buffer, GTK_TEXT_TAG (tags_iter->data), &invalid_begin, &invalid_end); iter = invalid_begin; ide_highlighter_update (self->highlighter, ide_highlight_engine_apply_style, &invalid_begin, &invalid_end, &iter); if (gtk_text_iter_compare (&iter, &invalid_end) >= 0) IDE_GOTO (up_to_date); /* Stop processing until further instruction if no movement was made */ if (gtk_text_iter_equal (&iter, &invalid_begin)) return FALSE; gtk_text_buffer_move_mark (buffer, self->invalid_begin, &iter); return TRUE; up_to_date: gtk_text_buffer_get_start_iter (buffer, &iter); gtk_text_buffer_move_mark (buffer, self->invalid_begin, &iter); gtk_text_buffer_move_mark (buffer, self->invalid_end, &iter); return FALSE; }
static void ide_langserv_symbol_resolver_definition_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeLangservClient *client = (IdeLangservClient *)object; IdeLangservSymbolResolver *self; g_autoptr(GTask) task = user_data; g_autoptr(GError) error = NULL; g_autoptr(GVariant) return_value = NULL; g_autoptr(IdeSymbol) symbol = NULL; g_autoptr(IdeFile) ifile = NULL; g_autoptr(GFile) gfile = NULL; g_autoptr(IdeSourceLocation) location = NULL; g_autoptr(GVariant) variant = NULL; GVariantIter iter; const gchar *uri; struct { gint64 line; gint64 column; } begin, end; gboolean success = FALSE; IDE_ENTRY; g_assert (IDE_IS_LANGSERV_CLIENT (client)); g_assert (G_IS_ASYNC_RESULT (result)); g_assert (G_IS_TASK (task)); self = g_task_get_source_object (task); g_assert (IDE_IS_LANGSERV_SYMBOL_RESOLVER (self)); if (!ide_langserv_client_call_finish (client, result, &return_value, &error)) { g_task_return_error (task, g_steal_pointer (&error)); IDE_EXIT; } #if 0 { g_autofree gchar *str = g_variant_print (return_value, TRUE); IDE_TRACE_MSG ("Got reply: %s", str); } #endif g_variant_iter_init (&iter, return_value); if (g_variant_iter_next (&iter, "v", &variant)) { success = JSONRPC_MESSAGE_PARSE (variant, "uri", JSONRPC_MESSAGE_GET_STRING (&uri), "range", "{", "start", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line), "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column), "}", "end", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&end.line), "character", JSONRPC_MESSAGE_GET_INT64 (&end.column), "}", "}" ); } if (!success) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Got invalid reply for textDocument/definition"); IDE_EXIT; } IDE_TRACE_MSG ("Definition location is %s %d:%d", uri, (gint)begin.line + 1, (gint)begin.column + 1); gfile = g_file_new_for_uri (uri); ifile = ide_file_new (ide_object_get_context (IDE_OBJECT (self)), gfile); location = ide_source_location_new (ifile, begin.line, begin.column, 0); symbol = ide_symbol_new ("", IDE_SYMBOL_NONE, IDE_SYMBOL_FLAGS_NONE, location, location, location); g_task_return_pointer (task, g_steal_pointer (&symbol), (GDestroyNotify)ide_symbol_unref); IDE_EXIT; }
static void ide_clang_service_get_translation_unit_worker (EggTaskCache *cache, gconstpointer key, GTask *task, gpointer user_data) { g_autoptr(GTask) real_task = NULL; IdeClangService *self = user_data; IdeUnsavedFiles *unsaved_files; IdeBuildSystem *build_system; ParseRequest *request; IdeContext *context; const gchar *path; IdeFile *file = (IdeFile *)key; GFile *gfile; g_assert (IDE_IS_CLANG_SERVICE (self)); g_assert (IDE_IS_CLANG_SERVICE (self)); g_assert (IDE_IS_FILE (key)); g_assert (IDE_IS_FILE (file)); g_assert (G_IS_TASK (task)); context = ide_object_get_context (IDE_OBJECT (self)); unsaved_files = ide_context_get_unsaved_files (context); build_system = ide_context_get_build_system (context); gfile = ide_file_get_file (file); if (!gfile || !(path = g_file_get_path (gfile))) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("File must be saved locally to parse.")); return; } request = g_slice_new0 (ParseRequest); request->file = g_object_ref (file); request->index = self->index; request->source_filename = g_strdup (path); request->command_line_args = NULL; request->unsaved_files = ide_unsaved_files_to_array (unsaved_files); request->sequence = ide_unsaved_files_get_sequence (unsaved_files); /* * NOTE: * * I'm torn on this one. It requires a bunch of extra memory, but without it * we don't get information about macros. And since we need that to provide * quality highlighting, I'm going try try enabling it for now and see how * things go. */ request->options = (clang_defaultEditingTranslationUnitOptions () | CXTranslationUnit_DetailedPreprocessingRecord); real_task = g_task_new (self, g_task_get_cancellable (task), ide_clang_service_unit_completed_cb, g_object_ref (task)); g_task_set_task_data (real_task, request, parse_request_free); /* * Request the build flags necessary to build this module from the build system. */ IDE_TRACE_MSG ("Requesting build of translation unit"); ide_build_system_get_build_flags_async (build_system, file, g_task_get_cancellable (task), ide_clang_service__get_build_flags_cb, g_object_ref (real_task)); }
static void ide_langserv_symbol_resolver_document_symbol_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeLangservClient *client = (IdeLangservClient *)object; g_autoptr(GTask) task = user_data; g_autoptr(IdeLangservSymbolTree) tree = NULL; g_autoptr(GError) error = NULL; g_autoptr(GVariant) return_value = NULL; g_autoptr(GPtrArray) symbols = NULL; GVariantIter iter; GVariant *node; IDE_ENTRY; g_assert (IDE_IS_LANGSERV_CLIENT (client)); g_assert (G_IS_TASK (task)); if (!ide_langserv_client_call_finish (client, result, &return_value, &error)) { g_task_return_error (task, g_steal_pointer (&error)); IDE_EXIT; } if (!g_variant_is_of_type (return_value, G_VARIANT_TYPE ("av"))) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Invalid result for textDocument/documentSymbol"); IDE_EXIT; } symbols = g_ptr_array_new_with_free_func (g_object_unref); g_variant_iter_init (&iter, return_value); while (g_variant_iter_loop (&iter, "v", &node)) { g_autoptr(IdeLangservSymbolNode) symbol = NULL; g_autoptr(GFile) file = NULL; const gchar *name = NULL; const gchar *container_name = NULL; const gchar *uri = NULL; gboolean success; gint64 kind = -1; struct { gint64 line; gint64 column; } begin, end; /* Mandatory fields */ success = JSONRPC_MESSAGE_PARSE (node, "name", JSONRPC_MESSAGE_GET_STRING (&name), "kind", JSONRPC_MESSAGE_GET_INT64 (&kind), "location", "{", "uri", JSONRPC_MESSAGE_GET_STRING (&uri), "range", "{", "start", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line), "character", JSONRPC_MESSAGE_GET_INT64 (&begin.column), "}", "end", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&end.line), "character", JSONRPC_MESSAGE_GET_INT64 (&end.column), "}", "}", "}" ); if (!success) { IDE_TRACE_MSG ("Failed to parse reply from language server"); continue; } /* Optional fields */ JSONRPC_MESSAGE_PARSE (node, "containerName", JSONRPC_MESSAGE_GET_STRING (&container_name)); file = g_file_new_for_uri (uri); symbol = ide_langserv_symbol_node_new (file, name, container_name, kind, begin.line, begin.column, end.line, end.column); g_ptr_array_add (symbols, g_steal_pointer (&symbol)); } tree = ide_langserv_symbol_tree_new (g_steal_pointer (&symbols)); g_task_return_pointer (task, g_steal_pointer (&tree), g_object_unref); IDE_EXIT; }