Fixed an issue causing eric to freeze if a file had a certain contents by replacing the use of Python re with QRegularExpression. eric7

Thu, 12 Jan 2023 11:41:48 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 12 Jan 2023 11:41:48 +0100
branch
eric7
changeset 9693
a7e9fd398e5a
parent 9692
a0be29ab700a
child 9694
90a7081e2837

Fixed an issue causing eric to freeze if a file had a certain contents by replacing the use of Python re with QRegularExpression.

src/eric7/Utilities/ClassBrowsers/pyclbr.py file | annotate | diff | comparison | revisions
src/eric7/Utilities/ClassBrowsers/rbclbr.py file | annotate | diff | comparison | revisions
src/eric7/Utilities/ModuleParser.py file | annotate | diff | comparison | revisions
--- a/src/eric7/Utilities/ClassBrowsers/pyclbr.py	Thu Jan 12 11:01:36 2023 +0100
+++ b/src/eric7/Utilities/ClassBrowsers/pyclbr.py	Thu Jan 12 11:41:48 2023 +0100
@@ -16,6 +16,8 @@
 from dataclasses import dataclass
 from functools import reduce
 
+from PyQt6.QtCore import QRegularExpression
+
 from eric7 import Utilities
 from eric7.Utilities import ClassBrowsers
 
@@ -25,7 +27,7 @@
 
 SUPPORTED_TYPES = [ClassBrowsers.PY_SOURCE, ClassBrowsers.PTL_SOURCE]
 
-_getnext = re.compile(
+_getnext = QRegularExpression(
     r"""
    (?P<CodingLine>
         ^ \# \s* [*_-]* \s* coding[:=] \s* (?P<Coding> [-\w_.]+ ) \s* [*_-]* $
@@ -135,8 +137,11 @@
             |
             (?: [^#;\\\n]* (?: \\\n )* )* )
     )""",
-    re.VERBOSE | re.DOTALL | re.MULTILINE,
-).search
+    QRegularExpression.PatternOption.MultilineOption
+    | QRegularExpression.PatternOption.DotMatchesEverythingOption
+    | QRegularExpression.PatternOption.ExtendedPatternSyntaxOption
+    | QRegularExpression.PatternOption.UseUnicodePropertiesOption,
+).match
 
 _commentsub = re.compile(r"""#[^\n]*\n|#[^\n]*$""").sub
 
@@ -445,22 +450,22 @@
     modifierIndent = -1
     while True:
         m = _getnext(src, i)
-        if not m:
+        if not m.hasMatch():
             break
-        start, i = m.span()
+        start, i = m.capturedStart(), m.capturedEnd()
 
-        if m.start("MethodModifier") >= 0:
-            modifierIndent = _indent(m.group("MethodModifierIndent"))
-            modifierType = m.group("MethodModifierType")
+        if m.hasCaptured("MethodModifier"):
+            modifierIndent = _indent(m.captured("MethodModifierIndent"))
+            modifierType = m.captured("MethodModifierType")
 
-        elif m.start("Method") >= 0:
+        elif m.hasCaptured("Method"):
             # found a method definition or function
-            thisindent = _indent(m.group("MethodIndent"))
-            meth_name = m.group("MethodName")
-            meth_sig = m.group("MethodSignature")
+            thisindent = _indent(m.captured("MethodIndent"))
+            meth_name = m.captured("MethodName")
+            meth_sig = m.captured("MethodSignature")
             meth_sig = meth_sig.replace("\\\n", "")
             meth_sig = _commentsub("", meth_sig)
-            meth_ret = m.group("MethodReturnAnnotation")
+            meth_ret = m.captured("MethodReturnAnnotation")
             meth_ret = meth_ret.replace("\\\n", "")
             meth_ret = _commentsub("", meth_ret)
             lineno += src.count("\n", last_lineno_pos, start)
@@ -534,19 +539,19 @@
             modifierType = ClbrBaseClasses.Function.General
             modifierIndent = -1
 
-        elif m.start("String") >= 0:
+        elif m.hasCaptured("String"):
             pass
 
-        elif m.start("Class") >= 0:
+        elif m.hasCaptured("Class"):
             # we found a class definition
-            thisindent = _indent(m.group("ClassIndent"))
+            thisindent = _indent(m.captured("ClassIndent"))
             # close all classes indented at least as much
             while classstack and classstack[-1][1] >= thisindent:
                 del classstack[-1]
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
-            class_name = m.group("ClassName")
-            inherit = m.group("ClassSupers")
+            class_name = m.captured("ClassName")
+            inherit = m.captured("ClassSupers")
             if inherit:
                 # the class inherits from other classes
                 inherit = inherit[1:-1].strip()
@@ -601,7 +606,7 @@
                 classstack[-1][0]._addclass(class_name, cur_class)
             classstack.append((cur_class, thisindent))
 
-        elif m.start("Attribute") >= 0:
+        elif m.hasCaptured("Attribute"):
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             index = -1
@@ -609,21 +614,21 @@
                 if classstack[index][0] is not None and not isinstance(
                     classstack[index][0], Function
                 ):
-                    attr = Attribute(module, m.group("AttributeName"), file, lineno)
+                    attr = Attribute(module, m.captured("AttributeName"), file, lineno)
                     classstack[index][0]._addattribute(attr)
                     break
                 else:
                     index -= 1
 
-        elif m.start("Main") >= 0:
+        elif m.hasCaptured("Main"):
             # 'main' part of the script, reset class stack
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             classstack = []
 
-        elif m.start("Variable") >= 0:
-            thisindent = _indent(m.group("VariableIndent"))
-            variable_name = m.group("VariableName")
+        elif m.hasCaptured("Variable"):
+            thisindent = _indent(m.captured("VariableIndent"))
+            variable_name = m.captured("VariableName")
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             if thisindent == 0 or not classstack:
@@ -649,8 +654,8 @@
                             )
                         break
 
-        elif m.start("Publics") >= 0:
-            idents = m.group("Identifiers")
+        elif m.hasCaptured("Publics"):
+            idents = m.captured("Identifiers")
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             pubs = Publics(
@@ -664,11 +669,11 @@
             )
             dictionary["__all__"] = pubs
 
-        elif m.start("Import") >= 0:
+        elif m.hasCaptured("Import"):
             # - import module
             names = [
                 n.strip()
-                for n in "".join(m.group("ImportList").splitlines())
+                for n in "".join(m.captured("ImportList").splitlines())
                 .replace("\\", "")
                 .split(",")
             ]
@@ -679,11 +684,11 @@
             for name in names:
                 dictionary["@@Import@@"].addImport(name, [], lineno)
 
-        elif m.start("ImportFrom") >= 0:
+        elif m.hasCaptured("ImportFrom"):
             # - from module import stuff
-            mod = m.group("ImportFromPath")
+            mod = m.captured("ImportFromPath")
             namesLines = (
-                m.group("ImportFromList")
+                m.captured("ImportFromList")
                 .replace("(", "")
                 .replace(")", "")
                 .replace("\\", "")
@@ -698,9 +703,9 @@
                 dictionary["@@Import@@"] = Imports(module, file)
             dictionary["@@Import@@"].addImport(mod, names, lineno)
 
-        elif m.start("ConditionalDefine") >= 0:
+        elif m.hasCaptured("ConditionalDefine"):
             # a conditional function/method definition
-            thisindent = _indent(m.group("ConditionalDefineIndent"))
+            thisindent = _indent(m.captured("ConditionalDefineIndent"))
             while conditionalsstack and conditionalsstack[-1] >= thisindent:
                 del conditionalsstack[-1]
                 if deltastack:
@@ -708,9 +713,9 @@
             conditionalsstack.append(thisindent)
             deltaindentcalculated = False
 
-        elif m.start("CodingLine") >= 0:
+        elif m.hasCaptured("CodingLine"):
             # a coding statement
-            coding = m.group("Coding")
+            coding = m.captured("Coding")
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             if "@@Coding@@" not in dictionary:
--- a/src/eric7/Utilities/ClassBrowsers/rbclbr.py	Thu Jan 12 11:01:36 2023 +0100
+++ b/src/eric7/Utilities/ClassBrowsers/rbclbr.py	Thu Jan 12 11:41:48 2023 +0100
@@ -14,6 +14,8 @@
 
 import re
 
+from PyQt6.QtCore import QRegularExpression
+
 from eric7 import Utilities
 from eric7.Utilities import ClassBrowsers
 
@@ -21,7 +23,7 @@
 
 SUPPORTED_TYPES = [ClassBrowsers.RB_SOURCE]
 
-_getnext = re.compile(
+_getnext = QRegularExpression(
     r"""
     (?P<String>
         =begin .*? =end
@@ -157,8 +159,11 @@
             end \b [^_]
         )
     )""",
-    re.VERBOSE | re.DOTALL | re.MULTILINE,
-).search
+    QRegularExpression.PatternOption.MultilineOption
+    | QRegularExpression.PatternOption.DotMatchesEverythingOption
+    | QRegularExpression.PatternOption.ExtendedPatternSyntaxOption
+    | QRegularExpression.PatternOption.UseUnicodePropertiesOption,
+).match
 
 _commentsub = re.compile(r"""#[^\n]*\n|#[^\n]*$""").sub
 
@@ -314,20 +319,20 @@
     i = 0
     while True:
         m = _getnext(src, i)
-        if not m:
+        if not m.hasMatch():
             break
-        start, i = m.span()
+        start, i = m.capturedStart(), m.capturedEnd()
 
-        if m.start("Method") >= 0:
+        if m.hasCaptured("Method"):
             # found a method definition or function
             thisindent = indent
             indent += 1
             meth_name = (
-                m.group("MethodName")
-                or m.group("MethodName2")
-                or m.group("MethodName3")
+                m.captured("MethodName")
+                or m.captured("MethodName2")
+                or m.captured("MethodName3")
             )
-            meth_sig = m.group("MethodSignature")
+            meth_sig = m.captured("MethodSignature")
             meth_sig = meth_sig and meth_sig.replace("\\\n", "") or ""
             meth_sig = _commentsub("", meth_sig)
             lineno += src.count("\n", last_lineno_pos, start)
@@ -382,14 +387,14 @@
             classstack.append((f, thisindent))  # Marker for nested fns
 
         elif (
-            m.start("String") >= 0
-            or m.start("Comment") >= 0
-            or m.start("ClassIgnored") >= 0
-            or m.start("BeginEnd") >= 0
+            m.hasCaptured("String")
+            or m.hasCaptured("Comment")
+            or m.hasCaptured("ClassIgnored")
+            or m.hasCaptured("BeginEnd")
         ):
             pass
 
-        elif m.start("Class") >= 0:
+        elif m.hasCaptured("Class"):
             # we found a class definition
             thisindent = indent
             indent += 1
@@ -401,8 +406,8 @@
                     # record the end line
                     classstack[-1][0].setEndLine(lineno - 1)
                 del classstack[-1]
-            class_name = m.group("ClassName") or m.group("ClassName2")
-            inherit = m.group("ClassSupers")
+            class_name = m.captured("ClassName") or m.captured("ClassName2")
+            inherit = m.captured("ClassSupers")
             if inherit:
                 # the class inherits from other classes
                 inherit = inherit[1:].strip()
@@ -433,7 +438,7 @@
             acstack.append(["public", thisindent])
             # default access control is 'public'
 
-        elif m.start("Module") >= 0:
+        elif m.hasCaptured("Module"):
             # we found a module definition
             thisindent = indent
             indent += 1
@@ -445,7 +450,7 @@
                     # record the end line
                     classstack[-1][0].setEndLine(lineno - 1)
                 del classstack[-1]
-            module_name = m.group("ModuleName")
+            module_name = m.captured("ModuleName")
             # remember this class
             cur_class = Module(module, module_name, file, lineno)
             if not classstack:
@@ -472,15 +477,15 @@
             acstack.append(["public", thisindent])
             # default access control is 'public'
 
-        elif m.start("AccessControl") >= 0:
-            aclist = m.group("AccessControlList")
-            if aclist is None:
+        elif m.hasCaptured("AccessControl"):
+            aclist = m.captured("AccessControlList")
+            if not aclist:
                 index = -1
                 while index >= -len(acstack):
                     if acstack[index][1] < indent:
                         actype = (
-                            m.group("AccessControlType")
-                            or m.group("AccessControlType2").split("_")[0]
+                            m.captured("AccessControlType")
+                            or m.captured("AccessControlType2").split("_")[0]
                         )
                         acstack[index][0] = actype.lower()
                         break
@@ -496,8 +501,8 @@
                     ):
                         parent = classstack[index][0]
                         actype = (
-                            m.group("AccessControlType")
-                            or m.group("AccessControlType2").split("_")[0]
+                            m.captured("AccessControlType")
+                            or m.captured("AccessControlType2").split("_")[0]
                         )
                         actype = actype.lower()
                         for name in aclist.split(","):
@@ -515,7 +520,7 @@
                     else:
                         index -= 1
 
-        elif m.start("Attribute") >= 0:
+        elif m.hasCaptured("Attribute"):
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             index = -1
@@ -525,7 +530,7 @@
                     and not isinstance(classstack[index][0], Function)
                     and classstack[index][1] < indent
                 ):
-                    attr = Attribute(module, m.group("AttributeName"), file, lineno)
+                    attr = Attribute(module, m.captured("AttributeName"), file, lineno)
                     classstack[index][0]._addattribute(attr)
                     break
                 else:
@@ -534,7 +539,7 @@
                         lastGlobalEntry.setEndLine(lineno - 1)
                     lastGlobalEntry = None
 
-        elif m.start("Attr") >= 0:
+        elif m.hasCaptured("Attr"):
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             index = -1
@@ -545,8 +550,8 @@
                     and classstack[index][1] < indent
                 ):
                     parent = classstack[index][0]
-                    if m.group("AttrType") is None:
-                        nv = m.group("AttrList").split(",")
+                    if not m.captured("AttrType"):
+                        nv = m.captured("AttrList").split(",")
                         if not nv:
                             break
                         name = nv[0].strip()[1:]  # get rid of leading ':'
@@ -561,8 +566,8 @@
                             attr.setPublic()
                         parent._addattribute(attr)
                     else:
-                        access = m.group("AttrType")
-                        for name in m.group("AttrList").split(","):
+                        access = m.captured("AttrType")
+                        for name in m.captured("AttrList").split(","):
                             name = name.strip()[1:]  # get rid of leading ':'
                             attr = (
                                 parent._getattribute("@" + name)
@@ -581,11 +586,11 @@
                 else:
                     index -= 1
 
-        elif m.start("Begin") >= 0:
+        elif m.hasCaptured("Begin"):
             # a begin of a block we are not interested in
             indent += 1
 
-        elif m.start("End") >= 0:
+        elif m.hasCaptured("End"):
             # an end of a block
             indent -= 1
             if indent < 0:
@@ -596,9 +601,9 @@
                 else:
                     indent = 0
 
-        elif m.start("CodingLine") >= 0:
+        elif m.hasCaptured("CodingLine"):
             # a coding statement
-            coding = m.group("Coding")
+            coding = m.captured("Coding")
             lineno += src.count("\n", last_lineno_pos, start)
             last_lineno_pos = start
             if "@@Coding@@" not in dictionary:
--- a/src/eric7/Utilities/ModuleParser.py	Thu Jan 12 11:01:36 2023 +0100
+++ b/src/eric7/Utilities/ModuleParser.py	Thu Jan 12 11:41:48 2023 +0100
@@ -22,6 +22,8 @@
 
 from functools import reduce
 
+from PyQt6.QtCore import QRegularExpression
+
 from eric7 import Utilities
 
 __all__ = [
@@ -64,7 +66,7 @@
         return -1
 
 
-_py_getnext = re.compile(
+_py_getnext = QRegularExpression(
     r"""
     (?P<Comment>
         \# .*? $   # ignore everything in comments
@@ -212,10 +214,13 @@
         (?: (?: if | elif ) [ \t]+ [^:]* | else [ \t]* ) :
         (?= \s* (?: async [ \t]+ )? def)
     )""",
-    re.VERBOSE | re.DOTALL | re.MULTILINE,
-).search
+    QRegularExpression.PatternOption.MultilineOption
+    | QRegularExpression.PatternOption.DotMatchesEverythingOption
+    | QRegularExpression.PatternOption.ExtendedPatternSyntaxOption
+    | QRegularExpression.PatternOption.UseUnicodePropertiesOption,
+).match
 
-_rb_getnext = re.compile(
+_rb_getnext = QRegularExpression(
     r"""
     (?P<Docstring>
         =begin [ \t]+ edoc (?P<DocstringContents> .*? ) =end
@@ -350,8 +355,11 @@
             end \b [^_]
         )
     )""",
-    re.VERBOSE | re.DOTALL | re.MULTILINE,
-).search
+    QRegularExpression.PatternOption.MultilineOption
+    | QRegularExpression.PatternOption.DotMatchesEverythingOption
+    | QRegularExpression.PatternOption.ExtendedPatternSyntaxOption
+    | QRegularExpression.PatternOption.UseUnicodePropertiesOption,
+).match
 
 _hashsub = re.compile(r"""^([ \t]*)#[ \t]?""", re.MULTILINE).sub
 
@@ -581,25 +589,25 @@
         modifierIndent = -1
         while True:
             m = self._getnext(src, i)
-            if not m:
+            if not m.hasMatch():
                 break
-            start, i = m.span()
+            start, i = m.capturedStart(), m.capturedEnd()
 
-            if m.start("MethodModifier") >= 0:
-                modifierIndent = _indent(m.group("MethodModifierIndent"))
-                modifierType = m.group("MethodModifierType")
+            if m.hasCaptured("MethodModifier"):
+                modifierIndent = _indent(m.captured("MethodModifierIndent"))
+                modifierType = m.captured("MethodModifierType")
 
-            elif m.start("Method") >= 0:
+            elif m.hasCaptured("Method"):
                 # found a method definition or function
-                thisindent = _indent(m.group("MethodIndent"))
-                meth_name = m.group("MethodName")
-                meth_sig = m.group("MethodSignature")
+                thisindent = _indent(m.captured("MethodIndent"))
+                meth_name = m.captured("MethodName")
+                meth_sig = m.captured("MethodSignature")
                 meth_sig = meth_sig.replace("\\\n", "")
-                meth_ret = m.group("MethodReturnAnnotation")
+                meth_ret = m.captured("MethodReturnAnnotation")
                 meth_ret = meth_ret.replace("\\\n", "")
-                if m.group("MethodPyQtSignature") is not None:
+                if m.captured("MethodPyQtSignature"):
                     meth_pyqtSig = (
-                        m.group("MethodPyQtSignature")
+                        m.captured("MethodPyQtSignature")
                         .replace("\\\n", "")
                         .split("result")[0]
                         .split("name")[0]
@@ -696,49 +704,49 @@
                 modifierType = Function.General
                 modifierIndent = -1
 
-            elif m.start("Docstring") >= 0:
-                contents = m.group("DocstringContents3")
-                if contents is not None:
+            elif m.hasCaptured("Docstring"):
+                contents = m.captured("DocstringContents3")
+                if contents:
                     contents = _hashsub(r"\1", contents)
                 else:
                     if self.file.lower().endswith(".ptl"):
                         contents = ""
                     else:
-                        contents = m.group("DocstringContents1") or m.group(
+                        contents = m.captured("DocstringContents1") or m.captured(
                             "DocstringContents2"
                         )
                 if cur_obj:
                     cur_obj.addDescription(contents)
 
-            elif m.start("String") >= 0:
+            elif m.hasCaptured("String"):
                 if modulelevel and (
                     src[start - len("\r\n") : start] == "\r\n"
                     or src[start - len("\n") : start] == "\n"
                     or src[start - len("\r") : start] == "\r"
                 ):
-                    contents = m.group("StringContents3")
-                    if contents is not None:
+                    contents = m.captured("StringContents3")
+                    if contents:
                         contents = _hashsub(r"\1", contents)
                     else:
                         if self.file.lower().endswith(".ptl"):
                             contents = ""
                         else:
-                            contents = m.group("StringContents1") or m.group(
+                            contents = m.captured("StringContents1") or m.captured(
                                 "StringContents2"
                             )
                     if cur_obj:
                         cur_obj.addDescription(contents)
 
-            elif m.start("Class") >= 0:
+            elif m.hasCaptured("Class"):
                 # we found a class definition
-                thisindent = _indent(m.group("ClassIndent"))
+                thisindent = _indent(m.captured("ClassIndent"))
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
                 # close all classes indented at least as much
                 while classstack and classstack[-1][1] >= thisindent:
                     del classstack[-1]
-                class_name = m.group("ClassName")
-                inherit = m.group("ClassSupers")
+                class_name = m.captured("ClassName")
+                inherit = m.captured("ClassSupers")
                 if inherit:
                     # the class inherits from other classes
                     inherit = inherit[1:-1].strip()
@@ -787,13 +795,13 @@
                 # add nested classes to the module
                 classstack.append((cur_class, thisindent))
 
-            elif m.start("Attribute") >= 0:
+            elif m.hasCaptured("Attribute"):
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
                 index = -1
                 while index >= -len(classstack):
                     if classstack[index][0] is not None:
-                        attrName = m.group("AttributeName")
+                        attrName = m.captured("AttributeName")
                         attr = Attribute(self.name, attrName, self.file, lineno)
                         self.__py_setVisibility(attr)
                         classstack[index][0].addAttribute(attrName, attr)
@@ -801,16 +809,16 @@
                     else:
                         index -= 1
 
-            elif m.start("Main") >= 0:
+            elif m.hasCaptured("Main"):
                 # 'main' part of the script, reset class stack
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
                 classstack = []
 
-            elif m.start("Variable") >= 0:
-                thisindent = _indent(m.group("VariableIndent"))
-                variable_name = m.group("VariableName")
-                isSignal = m.group("VariableSignal") != ""
+            elif m.hasCaptured("Variable"):
+                thisindent = _indent(m.captured("VariableIndent"))
+                variable_name = m.captured("VariableName")
+                isSignal = m.captured("VariableSignal") != ""
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
                 if thisindent == 0:
@@ -840,11 +848,11 @@
                                 classstack[index][0].addGlobal(variable_name, attr)
                             break
 
-            elif m.start("Import") >= 0:
+            elif m.hasCaptured("Import"):
                 # - import module
                 names = [
                     n.strip()
-                    for n in "".join(m.group("ImportList").splitlines())
+                    for n in "".join(m.captured("ImportList").splitlines())
                     .replace("\\", "")
                     .split(",")
                 ]
@@ -852,11 +860,11 @@
                     [name for name in names if name not in self.imports]
                 )
 
-            elif m.start("ImportFrom") >= 0:
+            elif m.hasCaptured("ImportFrom"):
                 # - from module import stuff
-                mod = m.group("ImportFromPath")
+                mod = m.captured("ImportFromPath")
                 namesLines = (
-                    m.group("ImportFromList")
+                    m.captured("ImportFromList")
                     .replace("(", "")
                     .replace(")", "")
                     .replace("\\", "")
@@ -871,9 +879,9 @@
                     [name for name in names if name not in self.from_imports[mod]]
                 )
 
-            elif m.start("ConditionalDefine") >= 0:
+            elif m.hasCaptured("ConditionalDefine"):
                 # a conditional function/method definition
-                thisindent = _indent(m.group("ConditionalDefineIndent"))
+                thisindent = _indent(m.captured("ConditionalDefineIndent"))
                 while conditionalsstack and conditionalsstack[-1] >= thisindent:
                     del conditionalsstack[-1]
                     if deltastack:
@@ -881,7 +889,7 @@
                 conditionalsstack.append(thisindent)
                 deltaindentcalculated = 0
 
-            elif m.start("Comment") >= 0 and modulelevel:
+            elif m.hasCaptured("Comment") and modulelevel:
                 continue
 
             modulelevel = False
@@ -903,20 +911,20 @@
         lastGlobalEntry = None
         while True:
             m = self._getnext(src, i)
-            if not m:
+            if not m.hasMatch():
                 break
-            start, i = m.span()
+            start, i = m.capturedStart(), m.capturedEnd()
 
-            if m.start("Method") >= 0:
+            if m.hasCaptured("Method"):
                 # found a method definition or function
                 thisindent = indent
                 indent += 1
                 meth_name = (
-                    m.group("MethodName")
-                    or m.group("MethodName2")
-                    or m.group("MethodName3")
+                    m.captured("MethodName")
+                    or m.captured("MethodName2")
+                    or m.captured("MethodName3")
                 )
-                meth_sig = m.group("MethodSignature")
+                meth_sig = m.captured("MethodSignature")
                 meth_sig = meth_sig and meth_sig.replace("\\\n", "") or ""
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
@@ -974,14 +982,14 @@
                 cur_obj = f
                 classstack.append((None, thisindent))  # Marker for nested fns
 
-            elif m.start("Docstring") >= 0:
-                contents = m.group("DocstringContents")
-                if contents is not None:
+            elif m.hasCaptured("Docstring"):
+                contents = m.captured("DocstringContents")
+                if contents:
                     contents = _hashsub(r"\1", contents)
                 if cur_obj:
                     cur_obj.addDescription(contents)
 
-            elif m.start("Class") >= 0:
+            elif m.hasCaptured("Class"):
                 # we found a class definition
                 thisindent = indent
                 indent += 1
@@ -995,8 +1003,8 @@
                         # record the end line of this class, function or module
                         classstack[-1][0].setEndLine(lineno - 1)
                     del classstack[-1]
-                class_name = m.group("ClassName") or m.group("ClassName2")
-                inherit = m.group("ClassSupers")
+                class_name = m.captured("ClassName") or m.captured("ClassName2")
+                inherit = m.captured("ClassSupers")
                 if inherit:
                     # the class inherits from other classes
                     inherit = inherit[1:].strip()
@@ -1029,7 +1037,7 @@
                 acstack.append(["public", thisindent])
                 # default access control is 'public'
 
-            elif m.start("Module") >= 0:
+            elif m.hasCaptured("Module"):
                 # we found a module definition
                 thisindent = indent
                 indent += 1
@@ -1043,7 +1051,7 @@
                         # record the end line of this class, function or module
                         classstack[-1][0].setEndLine(lineno - 1)
                     del classstack[-1]
-                module_name = m.group("ModuleName")
+                module_name = m.captured("ModuleName")
                 # remember this class
                 cur_class = RbModule(self.name, module_name, self.file, lineno)
                 # add nested Ruby modules to the file
@@ -1062,15 +1070,15 @@
                 acstack.append(["public", thisindent])
                 # default access control is 'public'
 
-            elif m.start("AccessControl") >= 0:
-                aclist = m.group("AccessControlList")
-                if aclist is None:
+            elif m.hasCaptured("AccessControl"):
+                aclist = m.captured("AccessControlList")
+                if not aclist:
                     index = -1
                     while index >= -len(acstack):
                         if acstack[index][1] < indent:
                             actype = (
-                                m.group("AccessControlType")
-                                or m.group("AccessControlType2").split("_")[0]
+                                m.captured("AccessControlType")
+                                or m.captured("AccessControlType2").split("_")[0]
                             )
                             acstack[index][0] = actype.lower()
                             break
@@ -1086,8 +1094,8 @@
                         ):
                             parent = classstack[index][0]
                             actype = (
-                                m.group("AccessControlType")
-                                or m.group("AccessControlType2").split("_")[0]
+                                m.captured("AccessControlType")
+                                or m.captured("AccessControlType2").split("_")[0]
                             )
                             actype = actype.lower()
                             for name in aclist.split(","):
@@ -1106,7 +1114,7 @@
                         else:
                             index -= 1
 
-            elif m.start("Attribute") >= 0:
+            elif m.hasCaptured("Attribute"):
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
                 index = -1
@@ -1116,7 +1124,7 @@
                         and not isinstance(classstack[index][0], Function)
                         and classstack[index][1] < indent
                     ):
-                        attrName = m.group("AttributeName")
+                        attrName = m.captured("AttributeName")
                         attr = Attribute(self.name, attrName, self.file, lineno)
                         if attrName.startswith("@@") or attrName[0].isupper():
                             classstack[index][0].addGlobal(attrName, attr)
@@ -1126,7 +1134,7 @@
                     else:
                         index -= 1
                 else:
-                    attrName = m.group("AttributeName")
+                    attrName = m.captured("AttributeName")
                     if attrName[0] != "@":
                         attr = Attribute(self.name, attrName, self.file, lineno)
                         self.addGlobal(attrName, attr)
@@ -1134,7 +1142,7 @@
                         lastGlobalEntry.setEndLine(lineno - 1)
                     lastGlobalEntry = None
 
-            elif m.start("Attr") >= 0:
+            elif m.hasCaptured("Attr"):
                 lineno += src.count("\n", last_lineno_pos, start)
                 last_lineno_pos = start
                 index = -1
@@ -1145,8 +1153,8 @@
                         and classstack[index][1] < indent
                     ):
                         parent = classstack[index][0]
-                        if m.group("AttrType") is None:
-                            nv = m.group("AttrList").split(",")
+                        if not m.captured("AttrType"):
+                            nv = m.captured("AttrList").split(",")
                             if not nv:
                                 break
                             # get rid of leading ':'
@@ -1162,8 +1170,8 @@
                                 attr.setPublic()
                             parent.addAttribute(attr.name, attr)
                         else:
-                            access = m.group("AttrType")
-                            for name in m.group("AttrList").split(","):
+                            access = m.captured("AttrType")
+                            for name in m.captured("AttrList").split(","):
                                 # get rid of leading ':'
                                 name = name.strip()[1:]
                                 attr = (
@@ -1185,11 +1193,11 @@
                     else:
                         index -= 1
 
-            elif m.start("Begin") >= 0:
+            elif m.hasCaptured("Begin"):
                 # a begin of a block we are not interested in
                 indent += 1
 
-            elif m.start("End") >= 0:
+            elif m.hasCaptured("End"):
                 # an end of a block
                 indent -= 1
                 if indent < 0:
@@ -1201,10 +1209,10 @@
                         indent = 0
 
             elif (
-                m.start("String") >= 0
-                or m.start("Comment") >= 0
-                or m.start("ClassIgnored") >= 0
-                or m.start("BeginEnd") >= 0
+                m.hasCaptured("String")
+                or m.hasCaptured("Comment")
+                or m.hasCaptured("ClassIgnored")
+                or m.hasCaptured("BeginEnd")
             ):
                 pass
 

eric ide

mercurial