Started improving JavaScript support.

Wed, 26 Mar 2014 20:03:25 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 26 Mar 2014 20:03:25 +0100
changeset 3438
29717a5e8b97
parent 3435
e4db9c0c7e94
child 3439
08aa0cef69e3

Started improving JavaScript support.

DataViews/PyProfileDialog.py file | annotate | diff | comparison | revisions
Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py file | annotate | diff | comparison | revisions
Plugins/PluginSyntaxChecker.py file | annotate | diff | comparison | revisions
Project/Project.py file | annotate | diff | comparison | revisions
Project/ProjectBrowser.py file | annotate | diff | comparison | revisions
Project/ProjectSourcesBrowser.py file | annotate | diff | comparison | revisions
QScintilla/Editor.py file | annotate | diff | comparison | revisions
Utilities/__init__.py file | annotate | diff | comparison | revisions
diff -r e4db9c0c7e94 -r 29717a5e8b97 DataViews/PyProfileDialog.py
--- a/DataViews/PyProfileDialog.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/DataViews/PyProfileDialog.py	Wed Mar 26 20:03:25 2014 +0100
@@ -53,7 +53,7 @@
 
 class PyProfileDialog(QDialog, Ui_PyProfileDialog):
     """
-    Class implementing a dialog to display the results of a syntax check run.
+    Class implementing a dialog to display the results of a profiling run.
     """
     def __init__(self, parent=None):
         """
diff -r e4db9c0c7e94 -r 29717a5e8b97 Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py
--- a/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py	Wed Mar 26 20:03:25 2014 +0100
@@ -155,6 +155,7 @@
             for ext in Preferences.getPython("PythonExtensions"):
                 files.extend(
                     Utilities.direntries(fn, 1, '*{0}'.format(ext), 0))
+            files.extend(Utilities.direntries(fn, 1, '*.js', 0))
         else:
             files = [fn]
         
@@ -166,15 +167,19 @@
         py2files = [f for f in files
                     if f.endswith(
                         tuple(Preferences.getPython("PythonExtensions")))]
+        jsfiles = [f for f in files if f.endswith(".js")]
         
         if (codestring and len(py3files) == 1) or \
            (codestring and len(py2files) == 1) or \
-           (not codestring and len(py3files) + len(py2files) > 0):
-            self.checkProgress.setMaximum(len(py3files) + len(py2files))
+           (codestring and len(jsfiles) == 1) or \
+           (not codestring and 
+                len(py3files) + len(py2files) + len(jsfiles) > 0):
+            self.checkProgress.setMaximum(
+                len(py3files) + len(py2files) + len(jsfiles))
             self.checkProgressLabel.setVisible(
-                len(py3files) + len(py2files) > 1)
+                len(py3files) + len(py2files) + len(jsfiles) > 1)
             self.checkProgress.setVisible(
-                len(py3files) + len(py2files) > 1)
+                len(py3files) + len(py2files) + len(jsfiles) > 1)
             QApplication.processEvents()
             
             ignoreStarImportWarnings = \
@@ -182,7 +187,7 @@
             
             # now go through all the files
             progress = 0
-            for file in py3files + py2files:
+            for file in py3files + py2files + jsfiles:
                 self.checkProgress.setValue(progress)
                 self.checkProgressLabel.setPath(file)
                 QApplication.processEvents()
@@ -226,6 +231,11 @@
                             file,
                             checkFlakes=Preferences.getFlakes(
                                 "IncludeInSyntaxCheck"))
+                elif file in jsfiles:
+                    nok, fname, line, error = \
+                        Utilities.jsCheckSyntax(file, source)
+                    index = 0
+                    code = source[line - 1]
                 else:
                     isPy3 = True
                     nok, fname, line, index, code, error = \
@@ -234,7 +244,8 @@
                     self.noResults = False
                     self.__createResultItem(fname, line, index, error, code)
                 else:
-                    if Preferences.getFlakes("IncludeInSyntaxCheck"):
+                    if file not in jsfiles and \
+                            Preferences.getFlakes("IncludeInSyntaxCheck"):
                         if isPy3:
                             try:
                                 from Utilities.pyflakes.checker import Checker
diff -r e4db9c0c7e94 -r 29717a5e8b97 Plugins/PluginSyntaxChecker.py
--- a/Plugins/PluginSyntaxChecker.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/Plugins/PluginSyntaxChecker.py	Wed Mar 26 20:03:25 2014 +0100
@@ -150,7 +150,7 @@
         if menuName == "Checks" and self.__projectAct is not None:
             self.__projectAct.setEnabled(
                 e5App().getObject("Project").getProjectLanguage() in
-                ["Python3", "Python2", "Python"])
+                ["Python3", "Python2", "Python", "JavaScript"])
     
     def __projectBrowserShowMenu(self, menuName, menu):
         """
@@ -162,7 +162,7 @@
         """
         if menuName == "Checks" and \
            e5App().getObject("Project").getProjectLanguage() in \
-                ["Python3", "Python2", "Python"]:
+                ["Python3", "Python2", "Python", "JavaScript"]:
             self.__projectBrowserMenu = menu
             if self.__projectBrowserAct is None:
                 self.__projectBrowserAct = E5Action(
@@ -189,7 +189,8 @@
                  for file in project.pdata["SOURCES"]
                  if file.endswith(
                      tuple(Preferences.getPython("Python3Extensions")) +
-                     tuple(Preferences.getPython("PythonExtensions")))]
+                     tuple(Preferences.getPython("PythonExtensions")) +
+                     (".js", ))]
         
         from CheckerPlugins.SyntaxChecker.SyntaxCheckerDialog import \
             SyntaxCheckerDialog
@@ -252,7 +253,10 @@
             if not self.__editorAct in menu.actions():
                 menu.addAction(self.__editorAct)
             self.__editorAct.setEnabled(
-                editor.isPy3File() or editor.isPy2File())
+                editor.isPy3File() or 
+                editor.isPy2File() or 
+                editor.isJavascriptFile()
+            )
     
     def __editorSyntaxCheck(self):
         """
@@ -261,9 +265,13 @@
         """
         editor = e5App().getObject("ViewManager").activeWindow()
         if editor is not None:
-                from CheckerPlugins.SyntaxChecker.SyntaxCheckerDialog import \
-                    SyntaxCheckerDialog
-                self.__editorSyntaxCheckerDialog = SyntaxCheckerDialog()
-                self.__editorSyntaxCheckerDialog.show()
-                self.__editorSyntaxCheckerDialog.start(
-                    editor.getFileName() or "Unnamed.py", editor.text())
+            from CheckerPlugins.SyntaxChecker.SyntaxCheckerDialog import \
+                SyntaxCheckerDialog
+            self.__editorSyntaxCheckerDialog = SyntaxCheckerDialog()
+            self.__editorSyntaxCheckerDialog.show()
+            if editor.isJavascriptFile():
+                unnamed = "Unnamed.js"
+            else:
+                unnamed = "Unnamed.py"
+            self.__editorSyntaxCheckerDialog.start(
+                editor.getFileName() or unnamed, editor.text())
diff -r e4db9c0c7e94 -r 29717a5e8b97 Project/Project.py
--- a/Project/Project.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/Project/Project.py	Wed Mar 26 20:03:25 2014 +0100
@@ -168,12 +168,14 @@
         
         self.ui = parent
         
+        # TODO: add JavaScript below
         self.__progLanguages = [
             "Python2",
             "Python3",
             "Ruby",
         ]
         
+        # TODO: add JavaScript below
         self.sourceExtensions = {
             "Python2": Preferences.getPython("PythonExtensions"),
             "Python3": Preferences.getPython("Python3Extensions"),
diff -r e4db9c0c7e94 -r 29717a5e8b97 Project/ProjectBrowser.py
--- a/Project/ProjectBrowser.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/Project/ProjectBrowser.py	Wed Mar 26 20:03:25 2014 +0100
@@ -297,6 +297,7 @@
                     icon = UI.PixmapCache.getIcon("projectSourcesRbMixed.png")
                 else:
                     icon = UI.PixmapCache.getIcon("projectSourcesRb.png")
+            # TODO: add icon for JavaScript
             else:
                 icon = UI.PixmapCache.getIcon("projectSources.png")
         self.setTabIcon(self.indexOf(self.psBrowser), icon)
diff -r e4db9c0c7e94 -r 29717a5e8b97 Project/ProjectSourcesBrowser.py
--- a/Project/ProjectSourcesBrowser.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/Project/ProjectSourcesBrowser.py	Wed Mar 26 20:03:25 2014 +0100
@@ -108,6 +108,7 @@
             self.__createPythonPopupMenus()
         elif self.project.pdata["PROGLANGUAGE"][0] == "Ruby":
             self.__createRubyPopupMenus()
+        # TODO: add JavaScript menu
         
     def __createPythonPopupMenus(self):
         """
diff -r e4db9c0c7e94 -r 29717a5e8b97 QScintilla/Editor.py
--- a/QScintilla/Editor.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/QScintilla/Editor.py	Wed Mar 26 20:03:25 2014 +0100
@@ -538,6 +538,8 @@
                 bindName = "dummy.d"
             elif self.filetype == "Properties":
                 bindName = "dummy.ini"
+            elif self.filetype == "JavaScript":
+                bindName = "dummy.js"
         
         # #! marker detection
         if not bindName and line0.startswith("#!"):
@@ -1881,6 +1883,23 @@
                 return True
         
         return False
+
+    def isJavascriptFile(self):
+        """
+        Public method to return a flag indicating a Javascript file.
+        
+        @return flag indicating a Javascript file (boolean)
+        """
+        if self.filetype == "JavaScript":
+            return True
+        
+        if self.filetype == "":
+            if self.fileName is not None and \
+               os.path.splitext(self.fileName)[1] == ".js":
+                self.filetype = "JavaScript"
+                return True
+        
+        return False
     
     def highlightVisible(self):
         """
@@ -5176,6 +5195,13 @@
                         else:
                             msg = warning[2]
                         self.toggleWarning(int(warning[1]), True, msg)
+            elif self.isJavascriptFile():
+                syntaxError, _fn, errorline, _error = \
+                    Utilities.jsCheckSyntax(self.fileName or "(Unnamed)",
+                                            self.text())
+                if syntaxError:
+                    self.toggleSyntaxError(
+                        int(errorline), 0, True, _error)
         
     def __initOnlineSyntaxCheck(self):
         """
diff -r e4db9c0c7e94 -r 29717a5e8b97 Utilities/__init__.py
--- a/Utilities/__init__.py	Tue Mar 25 19:36:31 2014 +0100
+++ b/Utilities/__init__.py	Wed Mar 26 20:03:25 2014 +0100
@@ -1810,4 +1810,45 @@
     GetUserNameEx(NameDisplay, nameBuffer, size)
     return nameBuffer.value
 
-# TODO: add support for JavaScript syntac check using jasy
+###############################################################################
+# Javascript related functions below
+###############################################################################
+
+
+def jsCheckSyntax(file, codestring=""):
+    """
+    Function to check a Javascript source file for syntax errors.
+    
+    @param file source filename (string)
+    @param codestring string containing the code to check (string)
+    @return A tuple indicating status (True = an error was found), the
+        file name, the line number and the error message (boolean, string,
+        string, string). The values are only valid, if the status is True.
+    """
+    import jasy.js.parse.Parser as jsParser
+    import jasy.js.tokenize.Tokenizer as jsTokenizer
+    
+    if not codestring:
+        try:
+            codestring = readEncodedFile(file)[0]
+        except (UnicodeDecodeError, IOError):
+            return (False, None, None, None)
+    
+    # normalize line endings
+    codestring = codestring.replace("\r\n", "\n")
+    codestring = codestring.replace("\r", "\n")
+    
+    # ensure source ends with an eol
+    if codestring and codestring[-1] != '\n':
+        codestring = codestring + '\n'
+    
+    try:
+        jsParser.parse(codestring, file)
+    except (jsParser.SyntaxError, jsTokenizer.ParseError) as exc:
+        details = exc.args[0]
+        error, details = details.splitlines()
+        fn, line = details.strip().rsplit(":", 1)
+        error = error.split(":", 1)[1].strip()
+        return (True, fn, line, error)
+    
+    return (False, None, None, None)

eric ide

mercurial