Example #1
0
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_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_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));
}