[gnome-builder] rstcheck: add diagnostic plugin for reStructuredText
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] rstcheck: add diagnostic plugin for reStructuredText
- Date: Sat, 22 Jan 2022 20:49:00 +0000 (UTC)
commit 99d1548585464badd4c79c052c63a2c0f84a2db5
Author: Veli Tasalı <veli tasali gmail com>
Date: Sat Jan 22 20:48:59 2022 +0000
rstcheck: add diagnostic plugin for reStructuredText
build-aux/flatpak/python-deps.json | 5 ++
meson_options.txt | 1 +
src/plugins/meson.build | 2 +
src/plugins/rstcheck/meson.build | 13 ++++
src/plugins/rstcheck/rstcheck.plugin | 11 +++
src/plugins/rstcheck/rstcheck_plugin.py | 116 ++++++++++++++++++++++++++++++++
6 files changed, 148 insertions(+)
---
diff --git a/build-aux/flatpak/python-deps.json b/build-aux/flatpak/python-deps.json
index 23f77c260..fceffa62c 100644
--- a/build-aux/flatpak/python-deps.json
+++ b/build-aux/flatpak/python-deps.json
@@ -149,6 +149,11 @@
"type": "file",
"url":
"https://files.pythonhosted.org/packages/08/41/f01bb2d95f207a6563b5942a506a29f2e6508bd1bd9ec04d70e04b3a0eae/gi_docgen-2021.6-py2.py3-none-any.whl",
"sha256": "2d5cfdf45f4d12816902cfe7e38474032779133bbb41e321fe0ec46e42726b6a"
+ },
+ {
+ "type": "file",
+ "url":
"https://files.pythonhosted.org/packages/81/3f/42c187b6e0840145a45021ceb1a2c83697b9aa41068add75d1fa6757bdca/rstcheck-3.3.1.tar.gz",
+ "sha256": "92c4f79256a54270e0402ba16a2f92d0b3c15c8f4410cb9c57127067c215741f"
}
]
}
diff --git a/meson_options.txt b/meson_options.txt
index d6171d7d9..f6c5113ba 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -71,6 +71,7 @@ option('plugin_qemu', type: 'boolean')
option('plugin_quick_highlight', type: 'boolean')
option('plugin_retab', type: 'boolean')
option('plugin_rls', type: 'boolean', value: false)
+option('plugin_rstcheck', type: 'boolean')
option('plugin_rubocop', type: 'boolean')
option('plugin_rust_analyzer', type: 'boolean')
option('plugin_shellcmd', type: 'boolean')
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index 0e69cafd5..1823c6491 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -117,6 +117,7 @@ subdir('recent')
subdir('restore-cursor')
subdir('retab')
subdir('rls')
+subdir('rstcheck')
subdir('rubocop')
subdir('rust-analyzer')
subdir('shellcmd')
@@ -220,6 +221,7 @@ status += [
'intelephense ....................(PHP) : @0@'.format(get_option('plugin_intelephense')),
'jedi-language-server ........ (Python) : @0@'.format(get_option('plugin_jedi_language_server')),
'rls ........................... (Rust) : @0@ (Not Suggested)'.format(get_option('plugin_rls')),
+ 'rstcheck ...........(reStructuredText) : @0@'.format(get_option('plugin_rstcheck')),
'rust-analyzer ................. (Rust) : @0@'.format(get_option('plugin_rust_analyzer')),
'ts-language-server ... (JS/TypeScript) : @0@'.format(get_option('plugin_ts_language_server')),
'gvls .......................... (Vala) : @0@'.format(get_option('plugin_gvls')),
diff --git a/src/plugins/rstcheck/meson.build b/src/plugins/rstcheck/meson.build
new file mode 100644
index 000000000..799ff1d1e
--- /dev/null
+++ b/src/plugins/rstcheck/meson.build
@@ -0,0 +1,13 @@
+if get_option('plugin_rstcheck')
+
+install_data('rstcheck_plugin.py', install_dir: plugindir)
+
+configure_file(
+ input: 'rstcheck.plugin',
+ output: 'rstcheck.plugin',
+ configuration: config_h,
+ install: true,
+ install_dir: plugindir,
+)
+
+endif
diff --git a/src/plugins/rstcheck/rstcheck.plugin b/src/plugins/rstcheck/rstcheck.plugin
new file mode 100644
index 000000000..3696685f6
--- /dev/null
+++ b/src/plugins/rstcheck/rstcheck.plugin
@@ -0,0 +1,11 @@
+[Plugin]
+Authors=Veli Tasalı <me velitasali com>
+Builtin=true
+Copyright=Copyright © 2022 Veli Tasalı
+Description=Provides reStructuredText linting using rstcheck
+Loader=python3
+Module=rstcheck_plugin
+Name=Rstcheck
+X-Diagnostic-Provider-Languages-Priority=100
+X-Diagnostic-Provider-Languages=rst
+X-Builder-ABI=@PACKAGE_ABI@
diff --git a/src/plugins/rstcheck/rstcheck_plugin.py b/src/plugins/rstcheck/rstcheck_plugin.py
new file mode 100644
index 000000000..2de0f6c09
--- /dev/null
+++ b/src/plugins/rstcheck/rstcheck_plugin.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python3
+
+import gi
+import re
+import threading
+import time
+
+from gi.repository import GLib, Gio, Ide
+
+
+THRESHOLD_CHOICES = {
+ 'INFO': Ide.DiagnosticSeverity.NOTE,
+ 'WARNING': Ide.DiagnosticSeverity.WARNING,
+ 'ERROR': Ide.DiagnosticSeverity.ERROR,
+ 'SEVERE': Ide.DiagnosticSeverity.FATAL,
+ 'NONE': Ide.DiagnosticSeverity.NOTE,
+}
+
+class RstcheckDiagnosticProvider(Ide.Object, Ide.DiagnosticProvider):
+ has_rstcheck = False
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.has_rstcheck = GLib.find_program_in_path('rstcheck')
+
+
+ def create_launcher(self):
+ context = self.get_context()
+ srcdir = context.ref_workdir().get_path()
+ launcher = None
+
+ if context.has_project():
+ build_manager = Ide.BuildManager.from_context(context)
+ pipeline = build_manager.get_pipeline()
+ if pipeline is not None:
+ srcdir = pipeline.get_srcdir()
+ runtime = pipeline.get_config().get_runtime()
+ if runtime.contains_program_in_path('rstcheck'):
+ launcher = runtime.create_launcher()
+
+ if launcher is None:
+ if not self.has_rstcheck:
+ return None
+
+ launcher = Ide.SubprocessLauncher.new(0)
+
+ launcher.set_flags(Gio.SubprocessFlags.STDIN_PIPE | Gio.SubprocessFlags.STDERR_PIPE)
+ launcher.set_cwd(srcdir)
+
+ return launcher
+
+
+ def do_diagnose_async(self, file, file_content, lang_id, cancellable, callback, user_data):
+ task = Gio.Task.new(self, cancellable, callback)
+
+ launcher = self.create_launcher()
+ if launcher is None:
+ task.return_error(Ide.NotSupportedError())
+ return
+
+ task.diagnostics_list = []
+
+ threading.Thread(target=self.execute,
+ args=(task, launcher, file, file_content, cancellable),
+ name='rstcheck-thread').start()
+
+
+ def do_diagnose_finish(self, result: Gio.Task) -> Ide.Diagnostics:
+ if result.propagate_boolean():
+ diagnostics = Ide.Diagnostics()
+ for diagnostic in result.diagnostics_list:
+ diagnostics.add(diagnostic)
+ return diagnostics
+
+
+ def execute(self, task, launcher, file, file_content, cancellable):
+ try:
+ # rstcheck reads from stdin when the input file name is '-'.
+ launcher.push_args(('rstcheck', '-'))
+
+ sub_process = launcher.spawn()
+ stdin = file_content.get_data().decode('UTF-8')
+ success, stdout, stderr = sub_process.communicate_utf8(stdin, cancellable)
+
+ if stderr is None or len(stderr) < 1:
+ task.return_boolean(True)
+ return
+
+ diagnostics = stderr.strip().split('\n')
+
+ for diagnostic in diagnostics:
+ # Example diagnostic text is:
+ # '-:4: (WARNING/2) Inline strong start-string without end-string.'
+ #
+ # And this regex operation turns it into:
+ # ['-', '4', 'WARNING', '2', 'Inline strong start-string without end-string.']
+ diagnostic_text = re.split('\:([0-9]+)\:\s\(([A-Z]+)\/([0-9]{1})\)\s', diagnostic)
+
+ file_name = diagnostic_text[0]
+ on_line = int(diagnostic_text[1]) - 1
+ warning_level = diagnostic_text[2]
+ message = diagnostic_text[4]
+
+ start = Ide.Location.new(file, on_line, 0)
+ severity = THRESHOLD_CHOICES[warning_level]
+ diagnostic = Ide.Diagnostic.new(severity, message, start)
+
+ task.diagnostics_list.append(diagnostic)
+ except GLib.Error as err:
+ task.return_error(err)
+ except Exception as e:
+ task.return_error(GLib.Error('Failed to analyze reStructuredText content: {}'.format(e)))
+ else:
+ task.return_boolean(True)
+
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]