IdeSourceLocation * ide_source_location_new_for_path (IdeContext *context, const gchar *path, guint line, guint line_offset) { g_autoptr(IdeFile) ifile = NULL; g_return_val_if_fail (!context || IDE_IS_CONTEXT (context), NULL); ifile = ide_file_new_for_path (context, path); return ide_source_location_new (ifile, line, line_offset, 0); }
static void ide_langserv_rename_provider_rename_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeLangservClient *client = (IdeLangservClient *)object; IdeLangservRenameProvider *self; g_autoptr(JsonNode) return_value = NULL; g_autoptr(GError) error = NULL; g_autoptr(GTask) task = user_data; g_autoptr(GPtrArray) ret = NULL; JsonObject *changes_by_uri = NULL; JsonObjectIter iter; const gchar *uri; IdeContext *context; JsonNode *changes; 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_RENAME_PROVIDER (self)); if (!ide_langserv_client_call_finish (client, result, &return_value, &error)) { g_task_return_error (task, g_steal_pointer (&error)); IDE_EXIT; } if (!JCON_EXTRACT (return_value, "changes", JCONE_OBJECT (changes_by_uri))) IDE_EXIT; context = ide_object_get_context (IDE_OBJECT (self)); ret = g_ptr_array_new_with_free_func (g_object_unref); json_object_iter_init (&iter, changes_by_uri); while (json_object_iter_next (&iter, &uri, &changes)) { g_autoptr(GFile) gfile = g_file_new_for_uri (uri); g_autoptr(IdeFile) ifile = ide_file_new (context, gfile); JsonArray *array; guint length; if (!JSON_NODE_HOLDS_ARRAY (changes)) continue; array = json_node_get_array (changes); length = json_array_get_length (array); for (guint i = 0; i < length; i++) { JsonNode *change = json_array_get_element (array, i); g_autoptr(IdeSourceLocation) begin_location = NULL; g_autoptr(IdeSourceLocation) end_location = NULL; g_autoptr(IdeSourceRange) range = NULL; g_autoptr(IdeProjectEdit) edit = NULL; const gchar *new_text = NULL; gboolean success; struct { gint line; gint column; } begin, end; success = JCON_EXTRACT (change, "range", "{", "start", "{", "line", JCONE_INT (begin.line), "character", JCONE_INT (begin.column), "}", "end", "{", "line", JCONE_INT (end.line), "character", JCONE_INT (end.column), "}", "}", "newText", JCONE_STRING (new_text) ); if (!success) continue; begin_location = ide_source_location_new (ifile, begin.line, begin.column, 0); end_location = ide_source_location_new (ifile, end.line, end.column, 0); range = ide_source_range_new (begin_location, end_location); edit = g_object_new (IDE_TYPE_PROJECT_EDIT, "range", range, "replacement", new_text, NULL); g_ptr_array_add (ret, g_steal_pointer (&edit)); } } g_task_return_pointer (task, g_steal_pointer (&ret), (GDestroyNotify)g_ptr_array_unref); IDE_EXIT; }
static void ide_langserv_symbol_resolver_find_references_cb (GObject *object, GAsyncResult *result, gpointer user_data) { IdeLangservClient *client = (IdeLangservClient *)object; g_autoptr(GTask) task = user_data; g_autoptr(GVariant) reply = NULL; g_autoptr(GPtrArray) references = NULL; g_autoptr(GError) error = NULL; IdeLangservSymbolResolver *self; GVariant *locationv; GVariantIter iter; 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); if (!ide_langserv_client_call_finish (client, result, &reply, &error)) { g_task_return_error (task, g_steal_pointer (&error)); IDE_EXIT; } if (!g_variant_is_of_type (reply, G_VARIANT_TYPE ("av"))) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Invalid reply type from peer: %s", g_variant_get_type_string (reply)); IDE_EXIT; } references = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_source_range_unref); g_variant_iter_init (&iter, reply); while (g_variant_iter_loop (&iter, "v", &locationv)) { g_autoptr(IdeSourceLocation) begin_loc = NULL; g_autoptr(IdeSourceLocation) end_loc = NULL; g_autoptr(IdeSourceRange) range = NULL; g_autoptr(IdeFile) ifile = NULL; const gchar *uri = NULL; GFile *gfile; gboolean success; struct { gint64 line; gint64 line_offset; } begin, end; success = JSONRPC_MESSAGE_PARSE (locationv, "uri", JSONRPC_MESSAGE_GET_STRING (&uri), "range", "{", "start", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&begin.line), "character", JSONRPC_MESSAGE_GET_INT64 (&begin.line_offset), "}", "end", "{", "line", JSONRPC_MESSAGE_GET_INT64 (&end.line), "character", JSONRPC_MESSAGE_GET_INT64 (&end.line_offset), "}", "}" ); if (!success) { g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, "Failed to parse location object"); IDE_EXIT; } gfile = g_file_new_for_uri (uri); ifile = ide_file_new (ide_object_get_context (IDE_OBJECT (self)), gfile); begin_loc = ide_source_location_new (ifile, begin.line, begin.line_offset, 0); end_loc = ide_source_location_new (ifile, end.line, end.line_offset, 0); range = ide_source_range_new (begin_loc, end_loc); g_ptr_array_add (references, g_steal_pointer (&range)); } g_task_return_pointer (task, g_steal_pointer (&references), (GDestroyNotify)g_ptr_array_unref); IDE_EXIT; }
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 subprocess_wait_cb (GObject *object, GAsyncResult *res, gpointer user_data) { GSubprocess *subprocess = (GSubprocess *)object; g_autofree gchar *input_prefix = NULL; g_autoptr(IdeDiagnostics) local_diags = NULL; g_autoptr(GTask) task = user_data; g_autoptr(GPtrArray) array = NULL; g_autoptr(GDataInputStream) stderr_data_input = NULL; GInputStream *stderr_input = NULL; g_autoptr(IdeGettextDiagnostics) diags = NULL; TranslationUnit *unit; GError *error = NULL; g_assert (G_IS_SUBPROCESS (subprocess)); g_assert (G_IS_TASK (task)); unit = g_task_get_task_data (task); g_assert (unit != NULL); if (!g_subprocess_wait_finish (subprocess, res, &error)) { g_task_return_error (task, error); return; } array = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_diagnostic_unref); if (g_subprocess_get_exit_status (subprocess) == 0) goto out; stderr_input = g_subprocess_get_stderr_pipe (subprocess); stderr_data_input = g_data_input_stream_new (stderr_input); input_prefix = g_strdup_printf ("%s:", ide_unsaved_file_get_temp_path (unit->unsaved_file)); for (;;) { g_autofree gchar *line = NULL; gsize length; line = g_data_input_stream_read_line (stderr_data_input, &length, g_task_get_cancellable (task), &error); if (line == NULL) break; if (g_str_has_prefix (line, input_prefix)) { gchar *p = line + strlen (input_prefix); if (g_ascii_isdigit (*p)) { gulong line_number = strtoul (p, &p, 10); IdeSourceLocation *loc; IdeDiagnostic *diag; loc = ide_source_location_new (unit->file, line_number - 1, 0, 0); diag = ide_diagnostic_new (IDE_DIAGNOSTIC_WARNING, g_strstrip (p + 1), loc); g_ptr_array_add (array, diag); } } } out: local_diags = ide_diagnostics_new (g_steal_pointer (&array)); diags = g_object_new (IDE_TYPE_GETTEXT_DIAGNOSTICS, "diagnostics", local_diags, "sequence", ide_unsaved_file_get_sequence (unit->unsaved_file), NULL); g_task_return_pointer (task, g_steal_pointer (&diags), g_object_unref); }