diff --git a/build-aux/flatpak/python-deps.json b/build-aux/flatpak/python-deps.json index 4732a9317831e59e6e23bffe7f43ceb9a50dc00c..de155386da140f5276db3524fb5aaba850d8175f 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 352a91dad7d491bdbefde30da6fe6eda7dd8f776..bdf157b4641fdcbf44e355feb49dd68241021afc 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 0000000000000000000000000000000000000000..c9e6c46a35e476ac95b88659f266cba2f437acf1 --- /dev/null +++ b/src/plugins/codespell/codespell-plugin.c @@ -0,0 +1,34 @@ +/* codespell-plugin.c + * + * Copyright 2020 Günther Wagner + * + * 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include "config.h" + +#include +#include + +#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 0000000000000000000000000000000000000000..8362d3d2d9cf7ce70eeb01182aeee250750813ac --- /dev/null +++ b/src/plugins/codespell/codespell.gresource.xml @@ -0,0 +1,6 @@ + + + + codespell.plugin + + diff --git a/src/plugins/codespell/codespell.plugin b/src/plugins/codespell/codespell.plugin new file mode 100644 index 0000000000000000000000000000000000000000..ae8b31255960426cafe00b81c0474adecfa638eb --- /dev/null +++ b/src/plugins/codespell/codespell.plugin @@ -0,0 +1,11 @@ +[Plugin] +Authors=Günther Wagner +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 0000000000000000000000000000000000000000..0cfbc8761f75f2cff4de1d6cd55504e74c774ed4 --- /dev/null +++ b/src/plugins/codespell/ide-codespell-diagnostic-provider.c @@ -0,0 +1,194 @@ +/* ide-codespell-diagnostic-provider.c + * + * Copyright 2020 Günther Wagner + * + * 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 . + * + * 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; + + line[len] = '\0'; + + /* 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 || lineno == 0) + 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_INHERIT | + G_SUBPROCESS_FLAGS_STDOUT_PIPE | + G_SUBPROCESS_FLAGS_STDERR_PIPE); + + 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 0000000000000000000000000000000000000000..1271abcdb154b34b9fef9b9a076f32e1f4ea73b2 --- /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 + * + * 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 . + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#pragma once + +#include + +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 0000000000000000000000000000000000000000..39eb91436c6bc6b32bb8fe9c1e6434d59e437cd1 --- /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 bee20b6fd32eba648937e9dc84137dcced2be5fe..d07027da29d0e550c34aa324b385601514696a7e 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')),