[gnome-builder] eslint plugin: add javascript linting using eslint



commit 548fef649755c77856e0dd312d64d25e2426128d
Author: Georg Vienna <georg vienna himbarsoft com>
Date:   Sun Mar 5 19:10:57 2017 +0100

    eslint plugin: add javascript linting using eslint
    
    This adds support for linting javascript files using eslint.
    An eslint configuration file must be present in the project directory.
    
    http://eslint.org/
    
    https://bugzilla.gnome.org/show_bug.cgi?id=779624

 configure.ac                                       |    2 +
 meson_options.txt                                  |    1 +
 plugins/Makefile.am                                |    1 +
 plugins/eslint/Makefile.am                         |   20 ++++
 plugins/eslint/configure.ac                        |   12 ++
 plugins/eslint/eslint.plugin                       |    9 ++
 plugins/eslint/eslint_plugin/__init__.py           |  112 ++++++++++++++++++++
 plugins/eslint/meson.build                         |   10 ++
 .../org.gnome.builder.plugins.eslint.gschema.xml   |    9 ++
 plugins/meson.build                                |    1 +
 10 files changed, 177 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 83f8d97..e246f95 100644
--- a/configure.ac
+++ b/configure.ac
@@ -304,6 +304,7 @@ m4_include([plugins/comment-code/configure.ac])
 m4_include([plugins/create-project/configure.ac])
 m4_include([plugins/ctags/configure.ac])
 m4_include([plugins/devhelp/configure.ac])
+m4_include([plugins/eslint/configure.ac])
 m4_include([plugins/file-search/configure.ac])
 m4_include([plugins/flatpak/configure.ac])
 m4_include([plugins/fpaste/configure.ac])
@@ -588,6 +589,7 @@ echo "  Command Bar .......................... : ${enable_command_bar_plugin}"
 echo "  Comment Code.......................... : ${enable_comment_code_plugin}"
 echo "  Ctags ................................ : ${enable_ctags_plugin}"
 echo "  Devhelp .............................. : ${enable_devhelp_plugin}"
+echo "  ESLint ............................... : ${enable_eslint_plugin}"
 echo "  Editorconfig ......................... : ${enable_editorconfig}"
 echo "  Flatpak .............................. : ${enable_flatpak_plugin}"
 echo "  Fpaste.org ........................... : ${enable_fpaste_plugin}"
diff --git a/meson_options.txt b/meson_options.txt
index fa0c33f..43a22c8 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -28,6 +28,7 @@ option('with_comment_code', type: 'boolean')
 option('with_create_project', type: 'boolean')
 option('with_ctags', type: 'boolean')
 option('with_devhelp', type: 'boolean')
+option('with_eslint', type: 'boolean')
 option('with_file_search', type: 'boolean')
 option('with_flatpak', type: 'boolean')
 option('with_fpaste', type: 'boolean')
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 7f5283e..49a1cfe 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -12,6 +12,7 @@ SUBDIRS =                            \
        create-project               \
        ctags                        \
        devhelp                      \
+       eslint                       \
        file-search                  \
        flatpak                      \
        fpaste                       \
diff --git a/plugins/eslint/Makefile.am b/plugins/eslint/Makefile.am
new file mode 100644
index 0000000..3bbc22c
--- /dev/null
+++ b/plugins/eslint/Makefile.am
@@ -0,0 +1,20 @@
+if ENABLE_ESLINT_PLUGIN
+
+
+plugindir = $(libdir)/gnome-builder/plugins
+dist_plugin_DATA = eslint.plugin
+
+moduledir = $(libdir)/gnome-builder/plugins/eslint_plugin
+dist_module_DATA = eslint_plugin/__init__.py
+
+gsettings_SCHEMAS = org.gnome.builder.plugins.eslint.gschema.xml
+
+.PRECIOUS: $(gsettings_SCHEMAS)
+
+@GSETTINGS_RULES@
+
+EXTRA_DIST = $(gsettings_SCHEMAS) $(plugin_DATA)
+
+endif
+
+-include $(top_srcdir)/git.mk
diff --git a/plugins/eslint/configure.ac b/plugins/eslint/configure.ac
new file mode 100644
index 0000000..17c34ed
--- /dev/null
+++ b/plugins/eslint/configure.ac
@@ -0,0 +1,12 @@
+# --enable-eslint-plugin=yes/no
+AC_ARG_ENABLE([eslint-plugin],
+              [AS_HELP_STRING([--enable-eslint-plugin=@<:@yes/no@:>@],
+                              [Build with support for eslint integration.])],
+              [enable_eslint_plugin=$enableval],
+              [enable_eslint_plugin=yes])
+
+# for if ENABLE_ESLINT_PLUGIN in Makefile.am
+AM_CONDITIONAL(ENABLE_ESLINT_PLUGIN, test x$enable_eslint_plugin = xyes)
+
+# Ensure our makefile is generated by autoconf
+AC_CONFIG_FILES([plugins/eslint/Makefile])
diff --git a/plugins/eslint/eslint.plugin b/plugins/eslint/eslint.plugin
new file mode 100644
index 0000000..1373031
--- /dev/null
+++ b/plugins/eslint/eslint.plugin
@@ -0,0 +1,9 @@
+[Plugin]
+Module=eslint_plugin
+Name=eslint
+Loader=python3
+Description=Provides javascript lints
+Authors=Georg Vienna <georg vienna himbarsoft com>
+Copyright=Copyright © 2017 Georg Vienna <georg vienna himbarsoft com>
+X-Diagnostic-Provider-Languages=js
+X-Diagnostic-Provider-Languages-Priority=100
diff --git a/plugins/eslint/eslint_plugin/__init__.py b/plugins/eslint/eslint_plugin/__init__.py
new file mode 100644
index 0000000..8f28920
--- /dev/null
+++ b/plugins/eslint/eslint_plugin/__init__.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python3
+
+#
+# __init__.py
+#
+# Copyright (C) 2017 Georg Vienna <georg vienna himbarsoft com>
+#
+# 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/>.
+#
+
+import gi
+import re
+
+gi.require_version('Ide', '1.0')
+
+from gi.repository import Egg
+from gi.repository import GObject
+from gi.repository import Gio
+from gi.repository import Gtk
+from gi.repository import Ide
+
+import threading
+
+_ = Ide.gettext
+
+def severtity_from_eslint(severity):
+    if 'Warning' in severity:
+        return Ide.DiagnosticSeverity.WARNING
+    # eslint has only warning and error, so default to error
+    return Ide.DiagnosticSeverity.ERROR
+
+class ESLintDiagnosticProvider(Ide.Object, Ide.DiagnosticProvider):
+    def do_load(self):
+        self.diagnostics_list = []
+
+    def do_diagnose_async(self, file, buffer, cancellable, callback, user_data):
+        self.diagnostics_list = []
+        task = Gio.Task.new(self, cancellable, callback)
+
+        unsaved_files = self.get_context().get_unsaved_files()
+        unsaved_file = unsaved_files.get_unsaved_file (file.get_file ())
+        if unsaved_file:
+            file_content = unsaved_file.get_content().get_data().decode('utf-8')
+        else:
+            file_content = None
+
+        settings = Gio.Settings.new('org.gnome.builder.plugins.eslint')
+        if not settings.get_boolean('enable-eslint'):
+            task.return_boolean(True)
+        else:
+            threading.Thread(target=self.execute, args=[task, file, file_content], 
name='eslint-thread').start()
+
+
+    def execute(self, task, file, file_content):
+        try:
+            launcher = 
Ide.SubprocessLauncher.new(Gio.SubprocessFlags.STDOUT_PIPE|Gio.SubprocessFlags.STDIN_PIPE)
+            launcher.push_argv('eslint')
+            launcher.push_argv('-f')
+            launcher.push_argv('compact')
+            if file_content:
+                launcher.push_argv('--stdin')
+                launcher.push_argv('--stdin-filename=' + file.get_path())
+            else:
+                launcher.push_argv(file.get_path())
+
+            sub_process = launcher.spawn()
+
+            result, stdout, stderr = sub_process.communicate_utf8(file_content, None)
+
+            for line in iter(stdout.splitlines()):
+                m = re.search('.*: line (\d+), col (\d+), (.*) - (.*)', line)
+                if m is None:
+                    break
+                line_number = max(0, int(m.group(1)) - 1)
+                column_number = max(0, int(m.group(2)) - 1)
+                severity = severtity_from_eslint(m.group(3))
+                message = m.group(4)
+                source_location = Ide.SourceLocation.new(file, line_number, column_number, 0)
+                self.diagnostics_list.append(Ide.Diagnostic.new(severity, message, source_location))
+        except Exception as e:
+            pass
+        task.return_boolean(True)
+
+    def do_diagnose_finish(self, result):
+        return Ide.Diagnostics.new(self.diagnostics_list)
+
+class ESLintPreferencesAddin(GObject.Object, Ide.PreferencesAddin):
+    def do_load(self, preferences):
+        self.eslint = preferences.add_switch("code-insight",
+                                             "diagnostics",
+                                             "org.gnome.builder.plugins.eslint",
+                                             "enable-eslint",
+                                             None,
+                                             "false",
+                                             _("ESlint"),
+                                             _("Enable the use of ESLint, which may execute code in your 
project"),
+                                             # translators: these are keywords used to search for preferences
+                                             _("eslint javascript lint code execute execution"),
+                                             500)
+    def do_unload(self, preferences):
+        preferences.remove_id(self.eslint)
diff --git a/plugins/eslint/meson.build b/plugins/eslint/meson.build
new file mode 100644
index 0000000..d175839
--- /dev/null
+++ b/plugins/eslint/meson.build
@@ -0,0 +1,10 @@
+if get_option('with_eslint')
+
+eslint_dir = join_paths(plugindir, 'eslint_plugin')
+install_data('eslint.plugin', install_dir: plugindir)
+install_data('eslint_plugin/__init__.py', install_dir: eslint_dir)
+
+install_data('org.gnome.builder.plugins.eslint.gschema.xml',
+  install_dir: schema_dir)
+
+endif
diff --git a/plugins/eslint/org.gnome.builder.plugins.eslint.gschema.xml 
b/plugins/eslint/org.gnome.builder.plugins.eslint.gschema.xml
new file mode 100644
index 0000000..f9f4b50
--- /dev/null
+++ b/plugins/eslint/org.gnome.builder.plugins.eslint.gschema.xml
@@ -0,0 +1,9 @@
+<schemalist>
+  <schema id="org.gnome.builder.plugins.eslint" path="/org/gnome/builder/plugins/eslint/" 
gettext-domain="gnome-builder">
+    <key name="enable-eslint" type="b">
+      <default>false</default>
+      <summary>Enable ESLint</summary>
+      <description>Enable the use of eslint to find additional diagnostics in JavaScript files. This may 
result in the execution of code in your project.</description>
+    </key>
+  </schema>
+</schemalist>
diff --git a/plugins/meson.build b/plugins/meson.build
index 29f3187..a9f1f33 100644
--- a/plugins/meson.build
+++ b/plugins/meson.build
@@ -23,6 +23,7 @@ subdir('comment-code')
 subdir('create-project')
 subdir('ctags')
 subdir('devhelp')
+subdir('eslint')
 subdir('file-search')
 subdir('flatpak')
 subdir('fpaste')


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