[gnome-builder] build-result: add basic errorformat extraction
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] build-result: add basic errorformat extraction
- Date: Mon, 21 Dec 2015 08:08:11 +0000 (UTC)
commit 2dcaa242ad975e4aab1f400bdd25c67e9f1de32b
Author: Christian Hergert <chergert redhat com>
Date: Fri Dec 18 03:59:04 2015 -0800
build-result: add basic errorformat extraction
This needs to be abstractd into log observers, but this lets us make
forward progress on the build panel for error viewing.
libide/ide-build-result.c | 217 ++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 204 insertions(+), 13 deletions(-)
---
diff --git a/libide/ide-build-result.c b/libide/ide-build-result.c
index 0daa132..ca37b64 100644
--- a/libide/ide-build-result.c
+++ b/libide/ide-build-result.c
@@ -19,8 +19,11 @@
#include <gio/gunixoutputstream.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
+#include <libpeas/peas.h>
#include "ide-build-result.h"
+#include "ide-file.h"
+#include "ide-source-location.h"
typedef struct
{
@@ -35,9 +38,17 @@ typedef struct
GTimer *timer;
gchar *mode;
+ gchar *current_dir;
+
guint running : 1;
} IdeBuildResultPrivate;
+typedef struct
+{
+ IdeBuildResult *self;
+ GOutputStream *writer;
+} Tail;
+
G_DEFINE_TYPE_WITH_PRIVATE (IdeBuildResult, ide_build_result, IDE_TYPE_OBJECT)
enum {
@@ -54,6 +65,164 @@ enum {
static GParamSpec *properties [LAST_PROP];
static guint signals [LAST_SIGNAL];
+static GPtrArray *errorformats;
+
+static void
+ide_build_result_add_error_format (const gchar *format)
+{
+ g_autoptr(GError) error = NULL;
+ GRegex *regex;
+
+ g_assert (format != NULL);
+
+ regex = g_regex_new (format, G_REGEX_OPTIMIZE | G_REGEX_CASELESS, 0, &error);
+
+ if (regex == NULL)
+ g_warning ("%s", error->message);
+ else
+ g_ptr_array_add (errorformats, regex);
+}
+
+static IdeDiagnosticSeverity
+parse_severity (const gchar *str)
+{
+ g_autofree gchar *lower = NULL;
+
+ if (str == NULL)
+ return IDE_DIAGNOSTIC_WARNING;
+
+ lower = g_utf8_strdown (str, -1);
+
+ if (strstr (lower, "fatal") != NULL)
+ return IDE_DIAGNOSTIC_FATAL;
+
+ if (strstr (lower, "error") != NULL)
+ return IDE_DIAGNOSTIC_ERROR;
+
+ if (strstr (lower, "warning") != NULL)
+ return IDE_DIAGNOSTIC_WARNING;
+
+ if (strstr (lower, "ignored") != NULL)
+ return IDE_DIAGNOSTIC_IGNORED;
+
+ if (strstr (lower, "deprecated") != NULL)
+ return IDE_DIAGNOSTIC_DEPRECATED;
+
+ if (strstr (lower, "note") != NULL)
+ return IDE_DIAGNOSTIC_NOTE;
+
+ return IDE_DIAGNOSTIC_WARNING;
+}
+
+static IdeDiagnostic *
+ide_build_result_create_diagnostic (IdeBuildResult *self,
+ GMatchInfo *match_info)
+{
+ IdeBuildResultPrivate *priv = ide_build_result_get_instance_private (self);
+ g_autofree gchar *filename = NULL;
+ g_autofree gchar *line = NULL;
+ g_autofree gchar *column = NULL;
+ g_autofree gchar *message = NULL;
+ g_autofree gchar *level = NULL;
+ g_autoptr(IdeFile) file = NULL;
+ g_autoptr(IdeSourceLocation) location = NULL;
+ IdeDiagnostic *diagnostic;
+ IdeContext *context;
+ struct {
+ gint64 line;
+ gint64 column;
+ IdeDiagnosticSeverity severity;
+ } parsed;
+
+ g_assert (IDE_IS_BUILD_RESULT (self));
+ g_assert (match_info != NULL);
+
+ filename = g_match_info_fetch_named (match_info, "filename");
+ line = g_match_info_fetch_named (match_info, "line");
+ column = g_match_info_fetch_named (match_info, "column");
+ message = g_match_info_fetch_named (match_info, "message");
+ level = g_match_info_fetch_named (match_info, "level");
+
+ parsed.line = g_ascii_strtoll (line, NULL, 10);
+ if (parsed.line < 1 || parsed.line > G_MAXINT32)
+ return NULL;
+ parsed.line--;
+
+ parsed.column = g_ascii_strtoll (column, NULL, 10);
+ if (parsed.column < 1 || parsed.column > G_MAXINT32)
+ return NULL;
+ parsed.column--;
+
+ parsed.severity = parse_severity (level);
+
+ context = ide_object_get_context (IDE_OBJECT (self));
+
+ if (priv->current_dir)
+ {
+ gchar *path;
+
+ path = g_build_filename (priv->current_dir, filename, NULL);
+ g_free (filename);
+ filename = path;
+ }
+
+ file = ide_file_new_for_path (context, filename);
+ location = ide_source_location_new (file, parsed.line, parsed.column, 0);
+ diagnostic = ide_diagnostic_new (parsed.severity, message, location);
+
+ return diagnostic;
+}
+
+static void
+_ide_build_result_extract (IdeBuildResult *self,
+ const gchar *line)
+{
+ IdeBuildResultPrivate *priv = ide_build_result_get_instance_private (self);
+ const gchar *enterdir;
+ guint i;
+
+ g_assert (IDE_IS_BUILD_RESULT (self));
+ g_assert (line != NULL);
+
+ /*
+ * TODO: This should all be abstracted into log observers. Various build
+ * systems will need to do different tricks to track the current dir,
+ * as well as errorformat extractions.
+ */
+
+ if ((enterdir = strstr (line, "Entering directory '")))
+ {
+ gsize len;
+
+ enterdir += IDE_LITERAL_LENGTH ("Entering directory '");
+ len = strlen (enterdir);
+
+ if (len > 0)
+ {
+ g_free (priv->current_dir);
+ priv->current_dir = g_strndup (enterdir, len - 1);
+ }
+ }
+
+ for (i = 0; i < errorformats->len; i++)
+ {
+ GRegex *regex = g_ptr_array_index (errorformats, i);
+ GMatchInfo *match_info = NULL;
+
+ if (g_regex_match (regex, line, 0, &match_info))
+ {
+ IdeDiagnostic *diagnostic;
+
+ if ((diagnostic = ide_build_result_create_diagnostic (self, match_info)))
+ {
+ g_signal_emit (self, signals [DIAGNOSTIC], 0, diagnostic);
+ ide_diagnostic_unref (diagnostic);
+ }
+ }
+
+ g_match_info_free (match_info);
+ }
+}
static gboolean
_ide_build_result_open_log (IdeBuildResult *self,
@@ -86,13 +255,16 @@ _ide_build_result_open_log (IdeBuildResult *self,
}
static void
-_ide_build_result_log (GOutputStream *stream,
+_ide_build_result_log (IdeBuildResult *self,
+ GOutputStream *stream,
const gchar *message)
{
g_autofree gchar *buffer = NULL;
- g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
- g_return_if_fail (message);
+ g_assert (G_IS_OUTPUT_STREAM (stream));
+ g_assert (message != NULL);
+
+ _ide_build_result_extract (self, message);
/*
* TODO: Is there a better way we can do this to just add a newline
@@ -125,7 +297,7 @@ ide_build_result_log_stdout (IdeBuildResult *self,
msg = g_strdup_vprintf (format, args);
va_end (args);
- _ide_build_result_log (priv->stdout_writer, msg);
+ _ide_build_result_log (self, priv->stdout_writer, msg);
}
}
@@ -147,7 +319,7 @@ ide_build_result_log_stderr (IdeBuildResult *self,
msg = g_strdup_vprintf (format, args);
va_end (args);
- _ide_build_result_log (priv->stderr_writer, msg);
+ _ide_build_result_log (self, priv->stderr_writer, msg);
}
}
@@ -217,25 +389,31 @@ ide_build_result_tail_cb (GObject *object,
gpointer user_data)
{
GDataInputStream *reader = (GDataInputStream *)object;
- g_autoptr(GOutputStream) writer = user_data;
g_autofree gchar *line = NULL;
g_autoptr(GError) error = NULL;
+ Tail *tail = user_data;
gsize n_read;
- g_return_if_fail (G_IS_INPUT_STREAM (reader));
- g_return_if_fail (G_IS_OUTPUT_STREAM (writer));
+ g_assert (G_IS_INPUT_STREAM (reader));
+ g_assert (tail != NULL);
+ g_assert (G_IS_OUTPUT_STREAM (tail->writer));
- line = g_data_input_stream_read_line_finish_utf8 (reader, result, &n_read,
- &error);
+ line = g_data_input_stream_read_line_finish_utf8 (reader, result, &n_read, &error);
if (line)
{
- _ide_build_result_log (writer, line);
+ _ide_build_result_log (tail->self, tail->writer, line);
g_data_input_stream_read_line_async (reader,
G_PRIORITY_DEFAULT,
NULL,
ide_build_result_tail_cb,
- g_object_ref (writer));
+ tail);
+ }
+ else
+ {
+ g_object_unref (tail->self);
+ g_object_unref (tail->writer);
+ g_slice_free1 (sizeof *tail, tail);
}
}
@@ -245,6 +423,7 @@ ide_build_result_tail_into (IdeBuildResult *self,
GOutputStream *writer)
{
g_autoptr(GDataInputStream) data_reader = NULL;
+ Tail *tail;
g_return_if_fail (IDE_IS_BUILD_RESULT (self));
g_return_if_fail (G_IS_INPUT_STREAM (reader));
@@ -252,11 +431,15 @@ ide_build_result_tail_into (IdeBuildResult *self,
data_reader = g_data_input_stream_new (reader);
+ tail = g_slice_alloc0 (sizeof *tail);
+ tail->self = g_object_ref (self);
+ tail->writer = g_object_ref (writer);
+
g_data_input_stream_read_line_async (data_reader,
G_PRIORITY_DEFAULT,
NULL,
ide_build_result_tail_cb,
- g_object_ref (writer));
+ tail);
}
void
@@ -381,6 +564,14 @@ ide_build_result_class_init (IdeBuildResultClass *klass)
G_STRUCT_OFFSET (IdeBuildResultClass, diagnostic),
NULL, NULL, NULL,
G_TYPE_NONE, 1, IDE_TYPE_DIAGNOSTIC);
+
+ errorformats = g_ptr_array_new ();
+
+ ide_build_result_add_error_format ("(?<filename>[a-zA-Z0-9\\-\\.]+):"
+ "(?<line>\\d+):"
+ "(?<column>\\d+): "
+ "(?<level>[\\w\\s]+): "
+ "(?<message>.*)");
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]