summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Reiter <reiter.christoph@gmail.com>2018-12-08 22:01:12 +0000
committerChristoph Reiter <reiter.christoph@gmail.com>2018-12-08 22:01:12 +0000
commiteb9b263589f78e245c8b374467707ce2abe570d2 (patch)
tree71b78f9ddc8cc45198ce560acded84da90b094cb
parent0f4dd5e39a86e9ae749b3b4627488e19d18dd8a5 (diff)
parentf9a873a0881e189a2d20e4904d40bb0c5cbf0d94 (diff)
downloadgobject-introspection-eb9b263589f78e245c8b374467707ce2abe570d2.tar.gz
Merge branch 'sourcescanner-get-errors' into 'master'
sourcescanner: collect error messages and expose them See merge request GNOME/gobject-introspection!83
-rw-r--r--giscanner/giscannermodule.c23
-rw-r--r--giscanner/scannerlexer.l3
-rw-r--r--giscanner/scannermain.py8
-rw-r--r--giscanner/scannerparser.y11
-rw-r--r--giscanner/sourcescanner.c14
-rw-r--r--giscanner/sourcescanner.h2
-rw-r--r--giscanner/sourcescanner.py3
-rw-r--r--tests/scanner/test_sourcescanner.py61
8 files changed, 98 insertions, 27 deletions
diff --git a/giscanner/giscannermodule.c b/giscanner/giscannermodule.c
index 45701d17..24b84050 100644
--- a/giscanner/giscannermodule.c
+++ b/giscanner/giscannermodule.c
@@ -81,7 +81,7 @@ typedef struct {
NEW_CLASS (PyGISourceSymbol, "SourceSymbol", GISourceSymbol, 10);
NEW_CLASS (PyGISourceType, "SourceType", GISourceType, 9);
-NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner, 8);
+NEW_CLASS (PyGISourceScanner, "SourceScanner", GISourceScanner, 9);
/* Symbol */
@@ -508,6 +508,26 @@ pygi_source_scanner_get_symbols (PyGISourceScanner *self, G_GNUC_UNUSED PyObject
}
static PyObject *
+pygi_source_scanner_get_errors (PyGISourceScanner *self, G_GNUC_UNUSED PyObject *unused)
+{
+ GSList *l, *errors;
+ PyObject *list;
+ int i = 0;
+
+ errors = gi_source_scanner_get_errors (self->scanner);
+ list = PyList_New (g_slist_length (errors));
+
+ for (l = errors; l; l = l->next)
+ {
+ PyObject *item = PyUnicode_FromString (l->data);
+ PyList_SetItem (list, i++, item);
+ }
+
+ g_slist_free (errors);
+ return list;
+}
+
+static PyObject *
pygi_source_scanner_get_comments (PyGISourceScanner *self, G_GNUC_UNUSED PyObject *unused)
{
GSList *l, *comments;
@@ -563,6 +583,7 @@ pygi_source_scanner_get_comments (PyGISourceScanner *self, G_GNUC_UNUSED PyObjec
}
static const PyMethodDef _PyGISourceScanner_methods[] = {
+ { "get_errors", (PyCFunction) pygi_source_scanner_get_errors, METH_NOARGS },
{ "get_comments", (PyCFunction) pygi_source_scanner_get_comments, METH_NOARGS },
{ "get_symbols", (PyCFunction) pygi_source_scanner_get_symbols, METH_NOARGS },
{ "append_filename", (PyCFunction) pygi_source_scanner_append_filename, METH_VARARGS },
diff --git a/giscanner/scannerlexer.l b/giscanner/scannerlexer.l
index 971b3a73..c2fb7234 100644
--- a/giscanner/scannerlexer.l
+++ b/giscanner/scannerlexer.l
@@ -513,7 +513,8 @@ print_error (GISourceScanner *scanner)
{
if (yytext[0]) {
char *filename = g_file_get_parse_name (scanner->current_file);
- fprintf(stderr, "%s:%d: unexpected character `%c'\n", filename, lineno, yytext[0]);
+ gchar *error = g_strdup_printf ("%s:%d: unexpected character `%c'", filename, lineno, yytext[0]);
+ scanner->errors = g_slist_prepend (scanner->errors, error);
g_free (filename);
}
}
diff --git a/giscanner/scannermain.py b/giscanner/scannermain.py
index ceca66f4..c2c1ac3d 100644
--- a/giscanner/scannermain.py
+++ b/giscanner/scannermain.py
@@ -444,8 +444,12 @@ def create_source_scanner(options, args):
options.cpp_defines,
options.cpp_undefines,
cflags=options.cflags)
- ss.parse_files(filenames)
- ss.parse_macros(filenames)
+ try:
+ ss.parse_files(filenames)
+ ss.parse_macros(filenames)
+ finally:
+ for error in ss.get_errors():
+ print(error, file=sys.stderr)
return ss, filenames
diff --git a/giscanner/scannerparser.y b/giscanner/scannerparser.y
index bf7bb37f..72c17ec3 100644
--- a/giscanner/scannerparser.y
+++ b/giscanner/scannerparser.y
@@ -165,7 +165,8 @@ pop_conditional (GISourceScanner *scanner)
if (type == 0)
{
gchar *filename = g_file_get_path (scanner->current_file);
- fprintf (stderr, "%s:%d: mismatched %s", filename, lineno, yytext);
+ gchar *error = g_strdup_printf ("%s:%d: mismatched %s", filename, lineno, yytext);
+ scanner->errors = g_slist_prepend (scanner->errors, error);
g_free (filename);
}
@@ -180,8 +181,9 @@ warn_if_cond_has_gi_scanner (GISourceScanner *scanner,
if (strstr (text, "__GI_SCANNER__"))
{
gchar *filename = g_file_get_path (scanner->current_file);
- fprintf (stderr, "%s:%d: the __GI_SCANNER__ constant should only be used with simple #ifdef or #endif: %s",
+ gchar *error = g_strdup_printf ("%s:%d: the __GI_SCANNER__ constant should only be used with simple #ifdef or #endif: %s",
filename, lineno, text);
+ scanner->errors = g_slist_prepend (scanner->errors, error);
g_free (filename);
}
}
@@ -1567,8 +1569,9 @@ yyerror (GISourceScanner *scanner, const char *s)
* have valid expressions */
if (!scanner->macro_scan)
{
- fprintf(stderr, "%s:%d: %s in '%s' at '%s'\n",
- g_file_get_parse_name (scanner->current_file), lineno, s, linebuf, yytext);
+ gchar *error = g_strdup_printf ("%s:%d: %s in '%s' at '%s'",
+ g_file_get_parse_name (scanner->current_file), lineno, s, linebuf, yytext);
+ scanner->errors = g_slist_prepend (scanner->errors, error);
}
}
diff --git a/giscanner/sourcescanner.c b/giscanner/sourcescanner.c
index 464e4695..4d10c88b 100644
--- a/giscanner/sourcescanner.c
+++ b/giscanner/sourcescanner.c
@@ -246,6 +246,7 @@ gi_source_scanner_free (GISourceScanner *scanner)
g_slist_free (scanner->comments);
g_slist_foreach (scanner->symbols, (GFunc)(void *)gi_source_symbol_unref, NULL);
g_slist_free (scanner->symbols);
+ g_slist_free_full (scanner->errors, g_free);
g_hash_table_unref (scanner->files);
@@ -326,6 +327,19 @@ gi_source_scanner_get_symbols (GISourceScanner *scanner)
}
/**
+ * gi_source_scanner_get_errors:
+ * @scanner: scanner instance
+ *
+ * Returns: (transfer container): List of strings.
+ * Free resulting list with g_slist_free().
+ */
+GSList *
+gi_source_scanner_get_errors (GISourceScanner *scanner)
+{
+ return g_slist_reverse (g_slist_copy (scanner->errors));
+}
+
+/**
* gi_source_scanner_get_comments:
* @scanner: scanner instance
*
diff --git a/giscanner/sourcescanner.h b/giscanner/sourcescanner.h
index e9fa5421..bcf1afc4 100644
--- a/giscanner/sourcescanner.h
+++ b/giscanner/sourcescanner.h
@@ -118,6 +118,7 @@ struct _GISourceScanner
GHashTable *const_table;
gboolean skipping;
GQueue conditionals;
+ GSList *errors;
};
struct _GISourceSymbol
@@ -162,6 +163,7 @@ void gi_source_scanner_set_macro_scan (GISourceScanner *scanne
gboolean macro_scan);
GSList * gi_source_scanner_get_symbols (GISourceScanner *scanner);
GSList * gi_source_scanner_get_comments (GISourceScanner *scanner);
+GSList * gi_source_scanner_get_errors (GISourceScanner *scanner);
void gi_source_scanner_free (GISourceScanner *scanner);
GISourceSymbol * gi_source_symbol_new (GISourceSymbolType type, GFile *file, int line);
diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py
index d867a4e9..6a0bace7 100644
--- a/giscanner/sourcescanner.py
+++ b/giscanner/sourcescanner.py
@@ -274,6 +274,9 @@ class SourceScanner(object):
def get_comments(self):
return self._scanner.get_comments()
+ def get_errors(self):
+ return self._scanner.get_errors()
+
def dump(self):
print('-' * 30)
for symbol in self._scanner.get_symbols():
diff --git a/tests/scanner/test_sourcescanner.py b/tests/scanner/test_sourcescanner.py
index 831af486..624d9df9 100644
--- a/tests/scanner/test_sourcescanner.py
+++ b/tests/scanner/test_sourcescanner.py
@@ -10,7 +10,20 @@ import os
from giscanner.sourcescanner import SourceScanner
-two_typedefs_source = """
+class Test(unittest.TestCase):
+
+ def _parse_files(self, code, header=True):
+ scanner = SourceScanner()
+ tmp_fd, tmp_name = tempfile.mkstemp(suffix=".h" if header else ".c")
+ fileobj = os.fdopen(tmp_fd, 'wb')
+ with fileobj:
+ fileobj.write(code.encode("utf-8"))
+ scanner.parse_files([tmp_name])
+ os.unlink(tmp_name)
+ return scanner
+
+ def test_length_consistency(self):
+ scanner = self._parse_files("""
/**
* Spam:
*/
@@ -20,26 +33,36 @@ typedef struct _spam Spam;
* Eggs:
*/
typedef struct _eggs Eggs;
-"""
+""")
+ self.assertEqual(len(list(scanner.get_symbols())), 2)
+ self.assertEqual(len(list(scanner.get_symbols())), 2)
+ self.assertEqual(len(list(scanner.get_comments())), 2)
+ self.assertEqual(len(list(scanner.get_comments())), 2)
+ self.assertFalse(scanner.get_errors())
-class Test(unittest.TestCase):
- def setUp(self):
- self.ss = SourceScanner()
- tmp_fd, tmp_name = tempfile.mkstemp()
- file = os.fdopen(tmp_fd, 'wt')
- file.write(two_typedefs_source)
- file.close()
-
- self.ss.parse_files([tmp_name])
-
- def test_get_symbols_length_consistency(self):
- self.assertEqual(len(list(self.ss.get_symbols())), 2)
- self.assertEqual(len(list(self.ss.get_symbols())), 2)
-
- def test_get_comments_length_consistency(self):
- self.assertEqual(len(list(self.ss.get_comments())), 2)
- self.assertEqual(len(list(self.ss.get_comments())), 2)
+ def test_parser_error(self):
+ scanner = self._parse_files("""
+void foo() {
+ a =
+}""")
+
+ errors = scanner.get_errors()
+ self.assertEqual(len(errors), 1)
+ self.assertTrue("syntax error" in errors[0])
+
+ def test_ignore_typeof(self):
+ # https://gitlab.gnome.org/GNOME/gobject-introspection/merge_requests/71
+ scanner = self._parse_files("""
+/**
+* foo:
+*/
+void foo(int bar) {
+ bar = ((__typeof__(bar)) (foo) (bar));
+}
+""")
+ self.assertEqual(len(list(scanner.get_comments())), 1)
+ self.assertFalse(scanner.get_errors())
if __name__ == '__main__':