Commit 723b4d30 authored by Christian Hergert's avatar Christian Hergert
Browse files

libide: add plumbing for c language support

Lot's to do to fill in the cracks here, but this gets the structure in
place. Next up is the clang service, which will be accessed by all of
the other services.
parent 83d852b0
......@@ -7,6 +7,16 @@ libide_la_SOURCES = \
libide/autotools/ide-autotools-build-task.h \
libide/autotools/ide-autotools-builder.c \
libide/autotools/ide-autotools-builder.h \
libide/c/ide-c-language.c \
libide/c/ide-c-language.h \
libide/c/ide-c-indenter.c \
libide/c/ide-c-indenter.h \
libide/clang/ide-clang-service.c \
libide/clang/ide-clang-service.h \
libide/clang/ide-clang-diagnostic-provider.c \
libide/clang/ide-clang-diagnostic-provider.h \
libide/clang/ide-clang-symbol-resolver.c \
libide/clang/ide-clang-symbol-resolver.h \
libide/directory/ide-directory-build-system.c \
libide/directory/ide-directory-build-system.h \
libide/directory/ide-directory-vcs.c \
......@@ -90,6 +100,8 @@ libide_la_SOURCES = \
libide_la_CFLAGS = \
-I$(top_srcdir)/libide \
-I$(top_srcdir)/libide/autotools \
-I$(top_srcdir)/libide/c \
-I$(top_srcdir)/libide/clang \
-I$(top_srcdir)/libide/directory \
-I$(top_srcdir)/libide/git \
-I$(top_srcdir)/libide/local \
......
/* ide-c-indenter.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_C_INDENTER_H
#define IDE_C_INDENTER_H
#include "ide-indenter.h"
G_BEGIN_DECLS
#define IDE_TYPE_C_INDENTER (ide_c_indenter_get_type())
G_DECLARE_DERIVABLE_TYPE (IdeCIndenter, ide_c_indenter, IDE, C_INDENTER, IdeIndenter)
struct _IdeCIndenterClass
{
IdeIndenterClass parent;
};
G_END_DECLS
#endif /* IDE_C_INDENTER_H */
/* ide-c-language.c
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <glib/gi18n.h>
#include "ide-c-indenter.h"
#include "ide-c-language.h"
#include "ide-clang-diagnostic-provider.h"
#include "ide-clang-highlighter.h"
#include "ide-clang-symbol-resolver.h"
#include "ide-diagnostician.h"
typedef struct
{
IdeDiagnostician *diagnostician;
IdeHighlighter *highlighter;
IdeIndenter *indenter;
IdeRefactory *refactory;
IdeSymbolResolver *symbol_resolver;
} IdeCLanguagePrivate;
static void _g_initable_iface_init (GInitableIface *iface);
G_DEFINE_TYPE_EXTENDED (IdeCLanguage, ide_c_language, IDE_TYPE_LANGUAGE, 0,
G_ADD_PRIVATE (IdeCLanguage)
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
_g_initable_iface_init))
static IdeDiagnostician *
ide_c_language_get_diagnostician (IdeLanguage *language)
{
IdeCLanguage *self = (IdeCLanguage *)language;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), NULL);
return priv->diagnostician;
}
static IdeHighlighter *
ide_c_language_get_highlighter (IdeLanguage *language)
{
IdeCLanguage *self = (IdeCLanguage *)language;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), NULL);
return priv->highlighter;
}
static IdeIndenter *
ide_c_language_get_indenter (IdeLanguage *language)
{
IdeCLanguage *self = (IdeCLanguage *)language;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), NULL);
return priv->indenter;
}
static IdeRefactory *
ide_c_language_get_refactory (IdeLanguage *language)
{
IdeCLanguage *self = (IdeCLanguage *)language;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), NULL);
return priv->refactory;
}
static IdeSymbolResolver *
ide_c_language_get_symbol_resolver (IdeLanguage *language)
{
IdeCLanguage *self = (IdeCLanguage *)language;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), NULL);
return priv->symbol_resolver;
}
static void
ide_c_language_dispose (GObject *object)
{
IdeCLanguage *self = (IdeCLanguage *)object;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
g_clear_object (&priv->diagnostician);
g_clear_object (&priv->highlighter);
g_clear_object (&priv->indenter);
g_clear_object (&priv->refactory);
g_clear_object (&priv->symbol_resolver);
G_OBJECT_CLASS (ide_c_language_parent_class)->dispose (object);
}
static void
ide_c_language_class_init (IdeCLanguageClass *klass)
{
IdeLanguageClass *language_class = IDE_LANGUAGE_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
language_class->get_diagnostician = ide_c_language_get_diagnostician;
language_class->get_highlighter = ide_c_language_get_highlighter;
language_class->get_indenter = ide_c_language_get_indenter;
language_class->get_refactory = ide_c_language_get_refactory;
language_class->get_symbol_resolver = ide_c_language_get_symbol_resolver;
object_class->dispose = ide_c_language_dispose;
}
static void
ide_c_language_init (IdeCLanguage *self)
{
}
static gboolean
ide_c_language_initiable_init (GInitable *initable,
GCancellable *cancellable,
GError **error)
{
IdeCLanguage *self = (IdeCLanguage *)initable;
IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
const gchar *id;
g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), FALSE);
g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
id = ide_language_get_id (IDE_LANGUAGE (self));
if ((g_strcmp0 (id, "c") == 0) || (g_strcmp0 (id, "chdr") == 0))
{
IdeContext *context;
IdeDiagnosticProvider *provider;
context = ide_object_get_context (IDE_OBJECT (initable));
/*
* Create our diagnostician using clang as a backend.
*/
priv->diagnostician = g_object_new (IDE_TYPE_DIAGNOSTICIAN,
"context", context,
NULL);
provider = g_object_new (IDE_TYPE_CLANG_DIAGNOSTIC_PROVIDER,
"context", context,
NULL);
ide_diagnostician_add_provider (priv->diagnostician, provider);
g_clear_object (&provider);
/*
* Create our highlighter that will use clang for semantic highlighting.
*/
priv->highlighter = g_object_new (IDE_TYPE_CLANG_HIGHLIGHTER,
"context", context,
NULL);
/*
* Create our indenter to provide as-you-type indentation.
*/
priv->indenter = g_object_new (IDE_TYPE_C_INDENTER,
"context", context,
NULL);
/*
* TODO: Refactory design (rename local, extract method, etc).
*/
/*
* Create our symbol resolver to help discover symbols within a file
* as well as what symbol is at "location X".
*/
priv->symbol_resolver = g_object_new (IDE_TYPE_CLANG_SYMBOL_RESOLVER,
"context", context,
NULL);
return TRUE;
}
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_NOT_SUPPORTED,
_("Language id does not match a C language."));
return FALSE;
}
static void
_g_initable_iface_init (GInitableIface *iface)
{
iface->init = ide_c_language_initiable_init;
}
/* ide-c-language.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_C_LANGUAGE_H
#define IDE_C_LANGUAGE_H
#include "ide-language.h"
G_BEGIN_DECLS
#define IDE_TYPE_C_LANGUAGE (ide_c_language_get_type())
G_DECLARE_DERIVABLE_TYPE (IdeCLanguage, ide_c_language, IDE, C_LANGUAGE, IdeLanguage)
struct _IdeCLanguageClass
{
IdeObjectClass parent;
};
G_END_DECLS
#endif /* IDE_C_LANGUAGE_H */
/* ide-clang-diagnostic-provider.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_CLANG_DIAGNOSTIC_PROVIDER_H
#define IDE_CLANG_DIAGNOSTIC_PROVIDER_H
#include "ide-diagnostic-provider.h"
G_BEGIN_DECLS
#define IDE_TYPE_CLANG_DIAGNOSTIC_PROVIDER (ide_clang_diagnostic_provider_get_type())
G_DECLARE_FINAL_TYPE (IdeClangDiagnosticProvider,
ide_clang_diagnostic_provider,
IDE, CLANG_DIAGNOSTIC_PROVIDER,
IdeDiagnosticProvider)
struct _IdeClangDiagnosticProvider
{
IdeDiagnosticProvider parent_instance;
};
G_END_DECLS
#endif /* IDE_CLANG_DIAGNOSTIC_PROVIDER_H */
/* ide-clang-highlighter.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_CLANG_HIGHLIGHTER_H
#define IDE_CLANG_HIGHLIGHTER_H
#include "ide-highlighter.h"
G_BEGIN_DECLS
#define IDE_TYPE_CLANG_HIGHLIGHTER (ide_clang_highlighter_get_type())
G_DECLARE_FINAL_TYPE (IdeClangHighlighter, ide_clang_highlighter, IDE, CLANG_HIGHLIGHTER, IdeHighlighter)
struct _IdeClangHighlighter
{
IdeHighlighter parent_instance;
};
G_END_DECLS
#endif /* IDE_CLANG_HIGHLIGHTER_H */
/* ide-clang-service.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_CLANG_SERVICE_H
#define IDE_CLANG_SERVICE_H
#include "ide-service.h"
G_BEGIN_DECLS
#define IDE_TYPE_CLANG_SERVICE (ide_clang_service_get_type())
G_DECLARE_DERIVABLE_TYPE (IdeClangService, ide_clang_service, IDE, CLANG_SERVICE, IdeService)
struct _IdeClangServiceClass
{
IdeServiceClass parent;
};
G_END_DECLS
#endif /* IDE_CLANG_SERVICE_H */
/* ide-clang-symbol-resolver.h
*
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
*
* This file is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This file is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDE_CLANG_SYMBOL_RESOLVER_H
#define IDE_CLANG_SYMBOL_RESOLVER_H
#include "ide-symbol-resolver.h"
G_BEGIN_DECLS
#define IDE_TYPE_CLANG_SYMBOL_RESOLVER (ide_clang_symbol_resolver_get_type())
G_DECLARE_FINAL_TYPE (IdeClangSymbolResolver, ide_clang_symbol_resolver, IDE, CLANG_SYMBOL_RESOLVER, IdeSymbolResolver)
struct _IdeClangSymbolResolver
{
IdeSymbolResolver parent_instance;
};
G_END_DECLS
#endif /* IDE_CLANG_SYMBOL_RESOLVER_H */
......@@ -42,6 +42,8 @@ typedef struct
GHashTable *services;
IdeUnsavedFiles *unsaved_files;
IdeVcs *vcs;
guint services_started : 1;
} IdeContextPrivate;
static void async_initable_init (GAsyncInitableIface *);
......@@ -305,12 +307,13 @@ ide_context_create_service (IdeContext *context,
"context", context,
NULL);
ide_service_start (service);
g_hash_table_insert (priv->services,
GINT_TO_POINTER (service_type),
service);
if (priv->services_started)
ide_service_start (service);
return service;
}
......@@ -795,6 +798,69 @@ ide_context_init_back_forward_list (gpointer source_object,
g_task_return_boolean (task, TRUE); /* TODO: implement loading */
}
static void
ide_context_init_services (gpointer source_object,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GIOExtensionPoint *point;
IdeContext *self = source_object;
IdeContextPrivate *priv = ide_context_get_instance_private (self);
g_autoptr(GTask) task = NULL;
const GList *extensions;
const GList *iter;
GHashTableIter hiter;
gpointer v;
g_return_if_fail (IDE_IS_CONTEXT (self));
task = g_task_new (self, cancellable, callback, user_data);
point = g_io_extension_point_lookup (IDE_SERVICE_EXTENSION_POINT);
extensions = g_io_extension_point_get_extensions (point);
for (iter = extensions; iter; iter = iter->next)
{
GIOExtension *extension = iter->data;
IdeService *service;
GType type_id;
type_id = g_io_extension_get_type (extension);
if (!g_type_is_a (type_id, IDE_TYPE_SERVICE))
{
g_warning (_("\"%s\" is not a service, ignoring extension point."),
g_type_name (type_id));
continue;
}
service = ide_context_get_service_typed (self, type_id);
if (!service)
{
g_warning (_("Failed to create service of type \"%s\"."),
g_type_name (type_id));
continue;
}
g_debug (_("Service of type \"%s\" registered."), g_type_name (type_id));
}
priv->services_started = TRUE;
g_hash_table_iter_init (&hiter, priv->services);
while (g_hash_table_iter_next (&hiter, NULL, &v))
{
IdeService *service = v;
if (!ide_service_get_running (service))
ide_service_start (service);
}
g_task_return_boolean (task, TRUE);
}
static void
ide_context_init_async (GAsyncInitable *initable,
int io_priority,
......@@ -812,6 +878,7 @@ ide_context_init_async (GAsyncInitable *initable,
cancellable,
callback,
user_data,
ide_context_init_services,
ide_context_init_build_system,
ide_context_init_vcs,
ide_context_init_project_name,
......
......@@ -19,22 +19,21 @@
#ifndef IDE_DIAGNOSTIC_PROVIDER_H
#define IDE_DIAGNOSTIC_PROVIDER_H
#include <glib-object.h>
#include "ide-object.h"
G_BEGIN_DECLS
#define IDE_TYPE_DIAGNOSTIC_PROVIDER (ide_diagnostic_provider_get_type ())
#define IDE_DIAGNOSTIC_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), IDE_TYPE_DIAGNOSTIC_PROVIDER, IdeDiagnosticProvider))
#define IDE_IS_DIAGNOSTIC_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IDE_TYPE_DIAGNOSTIC_PROVIDER))
#define IDE_DIAGNOSTIC_PROVIDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), IDE_TYPE_DIAGNOSTIC_PROVIDER, IdeDiagnosticProviderInterface))
#define IDE_TYPE_DIAGNOSTIC_PROVIDER (ide_diagnostic_provider_get_type())
struct _IdeDiagnosticProviderInterface
G_DECLARE_DERIVABLE_TYPE (IdeDiagnosticProvider, ide_diagnostic_provider,
IDE, DIAGNOSTIC_PROVIDER,
IdeObject)
struct _IdeDiagnosticProviderClass
{
GTypeInterface parent;
IdeObjectClass parent;
};
GType ide_diagnostic_provider_get_type (void);
G_END_DECLS
#endif /* IDE_DIAGNOSTIC_PROVIDER_H */
......@@ -25,13 +25,18 @@ G_BEGIN_DECLS
#define IDE_TYPE_DIAGNOSTICIAN (ide_diagnostician_get_type())
G_DECLARE_DERIVABLE_TYPE (IdeDiagnostician, ide_diagnostician, IDE, DIAGNOSTICIAN, IdeObject)
G_DECLARE_FINAL_TYPE (IdeDiagnostician, ide_diagnostician, IDE, DIAGNOSTICIAN, IdeObject)
struct _IdeDiagnosticianClass
struct _IdeDiagnostician
{
GObjectClass parent;
IdeObject parent_instance;
};
void ide_diagnostician_add_provider (IdeDiagnostician *self,