src/eric7/Utilities/ClassBrowsers/__init__.py

branch
eric7
changeset 9612
93b496cc3c88
parent 9609
c2f9c10c47cc
child 9653
e67609152c5e
--- a/src/eric7/Utilities/ClassBrowsers/__init__.py	Sun Dec 11 18:24:41 2022 +0100
+++ b/src/eric7/Utilities/ClassBrowsers/__init__.py	Mon Dec 12 16:35:21 2022 +0100
@@ -18,39 +18,83 @@
 </ul>
 """
 
-# TODO: move the IDL and Protobuf class browsers to the plugins.
-
 import importlib
 import os
 
 from eric7 import Preferences
 
+# The class browser registry
+# Dictionary with class browser name as key. Each entry is a dictionary with
+#       0. 'Extensions': list of associated file extensions with leading dot
+#       1. 'ReadModule': function to read and parse a module file
+#       2. 'Scan': function to parse a given source text
+#       3. 'FileIcon': function to get an icon name for the file type
+ClassBrowserRegistry = {}
+
 PY_SOURCE = 1
 PTL_SOURCE = 128
 RB_SOURCE = 129
-IDL_SOURCE = 130
-JS_SOURCE = 131
-PROTO_SOURCE = 132
+JS_SOURCE = 130
 UNKNOWN_SOURCE = 255
 
 SUPPORTED_TYPES = [
     PY_SOURCE,
     PTL_SOURCE,
     RB_SOURCE,
-    IDL_SOURCE,
     JS_SOURCE,
-    PROTO_SOURCE,
 ]
 
 __extensions = {
-    "IDL": [".idl"],
     "Python": [".py", ".pyw", ".ptl"],  # currently not used
     "Ruby": [".rb"],
     "JavaScript": [".js"],
-    "ProtoBuf": [".proto"],
 }
 
 
+def registerClassBrowser(name, readModuleFunc, scanFunc, iconFunc, extensions):
+    """
+    Function to register a class browser type.
+
+    @param name name of the class browser
+    @type str
+    @param readModuleFunc function to read and parse a file returning  a dictionary
+        with the parsing result
+    @type function
+    @param scanFunc function to scan a given source text returning  a dictionary with
+        the parsing result
+    @type function
+    @param iconFunc function returning an icon name for the supported files
+    @type function
+    @param extensions list of associated file extensions
+    @type list of str
+    @exception KeyError raised if the class browser to be registered is already
+    """
+    global ClassBrowserRegistry
+
+    if name in ClassBrowserRegistry:
+        raise KeyError('Class Browser "{0}" already registered.'.format(name))
+    else:
+        ClassBrowserRegistry[name] = {
+            "ReadModule": readModuleFunc,
+            "Scan": scanFunc,
+            "FileIcon": iconFunc,
+            "Extensions": extensions,
+        }
+
+
+def unregisterClassBrowser(name):
+    """
+    Function to unregister a class browser type.
+
+    @param name name of the class browser
+    @type str
+    """
+    global ClassBrowserRegistry
+
+    if name in ClassBrowserRegistry:
+        del ClassBrowserRegistry[name]
+
+
 def getClassBrowserModule(moduleType):
     """
     Function to import a class browser module.
@@ -61,9 +105,7 @@
     @rtype module
     """
     typeMapping = {
-        "idl": ".idlclbr",
         "javascript": ".jsclbr",
-        "protobuf": ".protoclbr",
         "python": ".pyclbr",
         "ruby": ".rbclbr",
     }
@@ -95,11 +137,14 @@
     ext = os.path.splitext(module)[1].lower()
     path = [] if path is None else path[:]
 
-    if ext in __extensions["IDL"]:
-        moduleType = "idl"
-    elif ext in __extensions["ProtoBuf"]:
-        moduleType = "protobuf"
-    elif ext in __extensions["Ruby"]:
+    if not isPyFile:
+        for classBrowserName in ClassBrowserRegistry:
+            if ext in ClassBrowserRegistry[classBrowserName]["Extensions"]:
+                return ClassBrowserRegistry[classBrowserName]["ReadModule"](
+                    module, path
+                )
+
+    if ext in __extensions["Ruby"]:
         moduleType = "ruby"
     elif ext in __extensions["JavaScript"]:
         moduleType = "javascript"
@@ -110,11 +155,49 @@
         moduleType = "python"
 
     classBrowserModule = getClassBrowserModule(moduleType)
-    if classBrowserModule:
-        dictionary = classBrowserModule.readmodule_ex(module, path, isTypeFile=isPyFile)
-        classBrowserModule.clearModulesCache()
+    dictionary = (
+        classBrowserModule.readmodule_ex(module, path, isTypeFile=isPyFile)
+        if classBrowserModule
+        else {}
+    )
+
+    return dictionary
+
+
+def scan(src, filename, module, isPyFile=False):
+    """
+    Function to scan the given source text.
+
+    @param src source text to be scanned
+    @type str
+    @param filename file name associated with the source text
+    @type str
+    @param module module name associated with the source text
+    @type str
+    @param isPyFile flag indicating a Python file
+    @type bool
+    @return dictionary containing the extracted data
+    @rtype dict
+    """
+    ext = os.path.splitext(filename)[1]
+    for classBrowserName in ClassBrowserRegistry:
+        if ext in ClassBrowserRegistry[classBrowserName]["Extensions"]:
+            return ClassBrowserRegistry[classBrowserName]["Scan"](src, filename, module)
+
+    if ext in __extensions["Ruby"]:
+        moduleType = "ruby"
+    elif ext in __extensions["JavaScript"]:
+        moduleType = "javascript"
+    elif ext in Preferences.getPython("Python3Extensions") or isPyFile:
+        moduleType = "python"
     else:
-        dictionary = {}
+        # try Python if it is without extension
+        moduleType = "python"
+
+    classBrowserModule = getClassBrowserModule(moduleType)
+    dictionary = (
+        classBrowserModule.scan(src, filename, module) if classBrowserModule else None
+    )
 
     return dictionary
 
@@ -143,10 +226,6 @@
 
     if ext in __extensions["Ruby"]:
         sourceType = RB_SOURCE
-    elif ext in __extensions["IDL"]:
-        sourceType = IDL_SOURCE
-    elif ext in __extensions["ProtoBuf"]:
-        sourceType = PROTO_SOURCE
     elif ext in __extensions["JavaScript"]:
         sourceType = JS_SOURCE
     elif ext == ".ptl":
@@ -180,3 +259,38 @@
             # __IGNORE_WARNING_Y115__
 
     raise ImportError
+
+
+def getIcon(filename):
+    """
+    Function to get an icon name for the given file (only for class browsers provided
+    via plugins).
+
+    @param filename name of the file
+    @type str
+    @return icon name
+    @rtype str
+    """
+    ext = os.path.splitext(filename)[1].lower()
+
+    for classBrowserRegistryEntry in ClassBrowserRegistry.values():
+        if ext in classBrowserRegistryEntry["Extensions"]:
+            return classBrowserRegistryEntry["FileIcon"](filename)
+
+    return "fileMisc"
+
+
+def isSupportedType(fileext):
+    """
+    Function to check, if the given file extension indicates a supported file type.
+
+    @param fileext file extension
+    @type str
+    @return flag indicating a supported file type
+    @rtype bool
+    """
+    supported = any(fileext in exts for exts in __extensions.values())
+    supported |= any(
+        fileext in cb["Extensions"] for cb in ClassBrowserRegistry.values()
+    )
+    return supported

eric ide

mercurial