[gnome-builder] codespell: add codespell integration



commit 9404c715ab7e84e2177ef84165827abd928a8de4
Author: Günther Wagner <info gunibert de>
Date:   Sun Jun 28 13:30:43 2020 +0200

    codespell: add codespell integration
    
    Fixes #1237

 build-aux/flatpak/python-deps.json                 |   9 +-
 meson_options.txt                                  |   1 +
 src/plugins/codespell/codespell-plugin.c           |  34 ++++
 src/plugins/codespell/codespell.gresource.xml      |   6 +
 src/plugins/codespell/codespell.plugin             |  11 ++
 .../codespell/ide-codespell-diagnostic-provider.c  | 192 +++++++++++++++++++++
 .../codespell/ide-codespell-diagnostic-provider.h  |  31 ++++
 src/plugins/codespell/meson.build                  |  16 ++
 src/plugins/meson.build                            |   2 +
 9 files changed, 300 insertions(+), 2 deletions(-)
---
diff --git a/build-aux/flatpak/python-deps.json b/build-aux/flatpak/python-deps.json
index 4732a9317..de155386d 100644
--- a/build-aux/flatpak/python-deps.json
+++ b/build-aux/flatpak/python-deps.json
@@ -2,7 +2,7 @@
     "name": "python3-jedi",
     "buildsystem": "simple",
     "build-commands": [
-        "pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} jedi sphinx 
sphinx_rtd_theme lxml docutils"
+        "pip3 install --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} jedi sphinx 
sphinx_rtd_theme lxml docutils codespell"
     ],
     "sources": [
         {
@@ -119,6 +119,11 @@
             "type": "file",
             "url": 
"https://files.pythonhosted.org/packages/e4/83/4c05db437252694660c972b5374b35a68a8a0a8cd012dc95e5fd4d7e71b0/jedi-0.13.2.tar.gz";,
             "sha256": "571702b5bd167911fe9036e5039ba67f820d6502832285cde8c881ab2b2149fd"
+        },
+        {
+            "type": "file",
+            "url": 
"https://files.pythonhosted.org/packages/7e/37/b15b4133e90bbef5acecfd2f3f3871c1352ee281c042fd64a22a72735fb8/codespell-1.17.1.tar.gz";,
+            "sha256": "25a2ecd86b9cdc111dc40a30d0ed28c578e13a0ce158d1c383f9d47811bfcd23"
         }
     ]
-}
\ No newline at end of file
+}
diff --git a/meson_options.txt b/meson_options.txt
index 352a91dad..bdf157b46 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -23,6 +23,7 @@ option('plugin_c_pack', type: 'boolean')
 option('plugin_cargo', type: 'boolean')
 option('plugin_clang', type: 'boolean')
 option('plugin_cmake', type: 'boolean')
+option('plugin_codespell', type: 'boolean')
 option('plugin_code_index', type: 'boolean')
 option('plugin_color_picker', type: 'boolean')
 option('plugin_copyright', type: 'boolean')
diff --git a/src/plugins/codespell/codespell-plugin.c b/src/plugins/codespell/codespell-plugin.c
new file mode 100644
index 000000000..c9e6c46a3
--- /dev/null
+++ b/src/plugins/codespell/codespell-plugin.c
@@ -0,0 +1,34 @@
+/* codespell-plugin.c
+ *
+ * Copyright 2020 Günther Wagner <info gunibert de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+#include <libide-code.h>
+
+#include "ide-codespell-diagnostic-provider.h"
+
+_IDE_EXTERN void
+_ide_codespell_register_types (PeasObjectModule *module)
+{
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_DIAGNOSTIC_PROVIDER,
+                                              IDE_TYPE_CODESPELL_DIAGNOSTIC_PROVIDER);
+}
diff --git a/src/plugins/codespell/codespell.gresource.xml b/src/plugins/codespell/codespell.gresource.xml
new file mode 100644
index 000000000..8362d3d2d
--- /dev/null
+++ b/src/plugins/codespell/codespell.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/plugins/codespell">
+    <file>codespell.plugin</file>
+  </gresource>
+</gresources>
diff --git a/src/plugins/codespell/codespell.plugin b/src/plugins/codespell/codespell.plugin
new file mode 100644
index 000000000..ae8b31255
--- /dev/null
+++ b/src/plugins/codespell/codespell.plugin
@@ -0,0 +1,11 @@
+[Plugin]
+Authors=Günther Wagner <info gunibert de>
+Builtin=true
+Copyright=Copyright © 2020 Günther Wagner
+Depends=editor;
+Description=Provides integration with Codespell
+Embedded=_ide_codespell_register_types
+Module=codespell
+Name=Codespell
+X-Diagnostic-Provider-Languages-Priority=100
+X-Diagnostic-Provider-Languages=c,chdr,cpp,js,python,vala
diff --git a/src/plugins/codespell/ide-codespell-diagnostic-provider.c 
b/src/plugins/codespell/ide-codespell-diagnostic-provider.c
new file mode 100644
index 000000000..84639d3d7
--- /dev/null
+++ b/src/plugins/codespell/ide-codespell-diagnostic-provider.c
@@ -0,0 +1,192 @@
+/* ide-codespell-diagnostic-provider.c
+ *
+ * Copyright 2020 Günther Wagner <info gunibert de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "ide-codespell-diagnostic-provider.h"
+
+struct _IdeCodespellDiagnosticProvider
+{
+  IdeObject parent_instance;
+};
+
+static void diagnostic_provider_iface_init (IdeDiagnosticProviderInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (IdeCodespellDiagnosticProvider,
+                         ide_codespell_diagnostic_provider,
+                         IDE_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (IDE_TYPE_DIAGNOSTIC_PROVIDER,
+                                                diagnostic_provider_iface_init))
+
+IdeCodespellDiagnosticProvider *
+ide_codespell_diagnostic_provider_new (void)
+{
+  return g_object_new (IDE_TYPE_CODESPELL_DIAGNOSTIC_PROVIDER, NULL);
+}
+
+static void
+ide_codespell_diagnostic_provider_class_init (IdeCodespellDiagnosticProviderClass *klass)
+{
+}
+
+static void
+ide_codespell_diagnostic_provider_init (IdeCodespellDiagnosticProvider *self)
+{
+}
+
+static void
+ide_codespell_diagnostic_provider_communicate_cb (GObject      *object,
+                                                  GAsyncResult *result,
+                                                  gpointer      user_data)
+{
+  IdeSubprocess *subprocess = (IdeSubprocess *)object;
+  g_autoptr(IdeTask) task = user_data;
+  g_autoptr(IdeDiagnostics) ret = NULL;
+  g_autoptr(GError) error = NULL;
+  g_autofree gchar *stderr_buf = NULL;
+  g_autofree gchar *stdout_buf = NULL;
+  IdeLineReader reader;
+  GFile *file;
+  gchar *line;
+  gsize len;
+
+  g_assert (IDE_IS_SUBPROCESS (subprocess));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_TASK (task));
+
+  if (!ide_subprocess_communicate_utf8_finish (subprocess, result, &stdout_buf, &stderr_buf, &error))
+    {
+      ide_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  file = ide_task_get_task_data (task);
+  g_assert (file != NULL);
+  g_assert (G_IS_FILE (file));
+
+  ret = ide_diagnostics_new ();
+
+  ide_line_reader_init (&reader, stdout_buf, -1);
+
+  while (NULL != (line = ide_line_reader_next (&reader, &len)))
+    {
+      g_autoptr(IdeDiagnostic) diag = NULL;
+      g_autoptr(IdeLocation) loc = NULL;
+      g_autoptr(IdeLocation) loc_end = NULL;
+      guint64 lineno;
+
+      /* Lines that we want to parse should look something like this:
+       * filename:42: misspelled word ==> correct word
+       */
+      if (!g_str_has_prefix (line, g_file_get_path (file)))
+        continue;
+
+      line += strlen (g_file_get_path (file)) + 1;
+      if (!g_ascii_isdigit (*line))
+        continue;
+
+      lineno = g_ascii_strtoull (line, &line, 10);
+      if ((lineno == G_MAXUINT64 && errno == ERANGE) || ((lineno == 0) && errno == EINVAL))
+        continue;
+      if (lineno > 0)
+        lineno--;
+
+      if (!g_str_has_prefix (line, ": "))
+        continue;
+
+      line += strlen (": ");
+
+      /* As we don't get a column information out of codespell mark the full line */
+      loc = ide_location_new (file, lineno, -1);
+      loc_end = ide_location_new (file, lineno, G_MAXINT);
+      diag = ide_diagnostic_new (IDE_DIAGNOSTIC_NOTE, line, loc);
+      ide_diagnostic_add_range (diag, ide_range_new (loc, loc_end));
+      ide_diagnostics_add (ret, diag);
+    }
+
+  ide_task_return_pointer (task,
+                           g_steal_pointer (&ret),
+                           g_object_unref);
+
+}
+
+static void
+ide_codespell_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider,
+                                                  GFile                 *file,
+                                                  GBytes                *contents,
+                                                  const gchar           *lang_id,
+                                                  GCancellable          *cancellable,
+                                                  GAsyncReadyCallback    callback,
+                                                  gpointer               user_data)
+{
+  IdeCodespellDiagnosticProvider *self = (IdeCodespellDiagnosticProvider *)provider;
+  g_autoptr(IdeTask) task = NULL;
+  g_autoptr(IdeSubprocessLauncher) launcher = NULL;
+  g_autoptr(IdeSubprocess) subprocess = NULL;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (IDE_IS_CODESPELL_DIAGNOSTIC_PROVIDER (self));
+  g_assert (G_IS_FILE (file));
+  g_assert (contents != NULL);
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (self, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, ide_codespell_diagnostic_provider_diagnose_async);
+  ide_task_set_priority (task, G_PRIORITY_LOW);
+  ide_task_set_task_data (task, g_object_ref (file), g_object_unref);
+
+  launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDIN_PIPE |
+                                          G_SUBPROCESS_FLAGS_STDOUT_PIPE |
+                                          G_SUBPROCESS_FLAGS_STDERR_SILENCE);
+
+  ide_subprocess_launcher_push_argv (launcher, "codespell");
+  ide_subprocess_launcher_push_argv (launcher, "-d");
+  ide_subprocess_launcher_push_argv (launcher, g_file_get_path (file));
+
+  /* Spawn the process of fail immediately */
+  if (!(subprocess = ide_subprocess_launcher_spawn (launcher, cancellable, &error)))
+    {
+      ide_task_return_error (task, g_steal_pointer (&error));
+      return;
+    }
+
+  ide_subprocess_communicate_utf8_async (subprocess,
+                                         NULL,
+                                         cancellable,
+                                         ide_codespell_diagnostic_provider_communicate_cb,
+                                         g_steal_pointer (&task));
+}
+
+static IdeDiagnostics *
+ide_codespell_diagnostic_provider_diagnose_finish (IdeDiagnosticProvider  *provider,
+                                                   GAsyncResult           *result,
+                                                   GError                **error)
+{
+  g_assert (IDE_IS_CODESPELL_DIAGNOSTIC_PROVIDER (provider));
+  g_assert (IDE_IS_TASK (result));
+  g_assert (ide_task_is_valid (IDE_TASK (result), provider));
+
+  return ide_task_propagate_pointer (IDE_TASK (result), error);
+}
+
+static void
+diagnostic_provider_iface_init (IdeDiagnosticProviderInterface *iface)
+{
+  iface->diagnose_async = ide_codespell_diagnostic_provider_diagnose_async;
+  iface->diagnose_finish = ide_codespell_diagnostic_provider_diagnose_finish;
+}
diff --git a/src/plugins/codespell/ide-codespell-diagnostic-provider.h 
b/src/plugins/codespell/ide-codespell-diagnostic-provider.h
new file mode 100644
index 000000000..1271abcdb
--- /dev/null
+++ b/src/plugins/codespell/ide-codespell-diagnostic-provider.h
@@ -0,0 +1,31 @@
+/* ide-codespell-diagnostic-provider.h
+ *
+ * Copyright 2020 Günther Wagner <info gunibert de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-code.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_CODESPELL_DIAGNOSTIC_PROVIDER (ide_codespell_diagnostic_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeCodespellDiagnosticProvider, ide_codespell_diagnostic_provider, IDE, 
CODESPELL_DIAGNOSTIC_PROVIDER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/codespell/meson.build b/src/plugins/codespell/meson.build
new file mode 100644
index 000000000..39eb91436
--- /dev/null
+++ b/src/plugins/codespell/meson.build
@@ -0,0 +1,16 @@
+if get_option('plugin_codespell')
+
+plugins_sources += files([
+  'codespell-plugin.c',
+  'ide-codespell-diagnostic-provider.c',
+])
+
+plugin_codespell_resources = gnome.compile_resources(
+  'codespell-resources',
+  'codespell.gresource.xml',
+  c_name: 'gbp_codespell',
+)
+
+plugins_sources += plugin_codespell_resources
+
+endif
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index bee20b6fd..d07027da2 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -43,6 +43,7 @@ subdir('buffer-monitor')
 subdir('cargo')
 subdir('clang')
 subdir('cmake')
+subdir('codespell')
 subdir('code-index')
 subdir('codeui')
 subdir('color-picker')
@@ -147,6 +148,7 @@ status += [
   'Cargo ................. : @0@'.format(get_option('plugin_cargo')),
   'Clang ................. : @0@'.format(get_option('plugin_clang')),
   'CMake ................. : @0@'.format(get_option('plugin_cmake')),
+  'Codespell ............. : @0@'.format(get_option('plugin_codespell')),
   'Code Index ............ : @0@'.format(get_option('plugin_code_index')),
   'Color Pickr ........... : @0@'.format(get_option('plugin_color_picker')),
   'CTags ................. : @0@'.format(get_option('plugin_ctags')),


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]