Wed, 09 Sep 2020 18:07:21 +0200
pyclbr: improved determination of the last line of a class, method or function.
--- a/eric6/APIs/Python3/eric6.api Wed Sep 09 18:05:58 2020 +0200 +++ b/eric6/APIs/Python3/eric6.api Wed Sep 09 18:07:21 2020 +0200 @@ -9225,6 +9225,7 @@ eric6.Utilities.ClassBrowsers.pyclbr._getnext?8 eric6.Utilities.ClassBrowsers.pyclbr._indent?5(ws) eric6.Utilities.ClassBrowsers.pyclbr._modules?8 +eric6.Utilities.ClassBrowsers.pyclbr.calculateEndline?4(lineno, lines, indent) eric6.Utilities.ClassBrowsers.pyclbr.readmodule_ex?4(module, path=None, inpackage=False, isPyFile=False) eric6.Utilities.ClassBrowsers.pyclbr.scan?4(src, file, module) eric6.Utilities.ClassBrowsers.rbclbr.Attribute?1(module, name, file, lineno)
--- a/eric6/Documentation/Help/source.qhp Wed Sep 09 18:05:58 2020 +0200 +++ b/eric6/Documentation/Help/source.qhp Wed Sep 09 18:07:21 2020 +0200 @@ -16978,6 +16978,7 @@ <keyword name="blank_lines" id="blank_lines" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#blank_lines" /> <keyword name="break_after_binary_operator" id="break_after_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#break_after_binary_operator" /> <keyword name="break_before_binary_operator" id="break_before_binary_operator" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#break_before_binary_operator" /> + <keyword name="calculateEndline" id="calculateEndline" ref="eric6.Utilities.ClassBrowsers.pyclbr.html#calculateEndline" /> <keyword name="certificateValidation (Module)" id="certificateValidation (Module)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.Security.Checks.certificateValidation.html" /> <keyword name="changeRememberedMaster" id="changeRememberedMaster" ref="eric6.Utilities.crypto.__init__.html#changeRememberedMaster" /> <keyword name="checkAssertUsed" id="checkAssertUsed" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.Security.Checks.assert.html#checkAssertUsed" />
--- a/eric6/Documentation/Source/eric6.Utilities.ClassBrowsers.pyclbr.html Wed Sep 09 18:05:58 2020 +0200 +++ b/eric6/Documentation/Source/eric6.Utilities.ClassBrowsers.pyclbr.html Wed Sep 09 18:07:21 2020 +0200 @@ -76,6 +76,10 @@ <td>Module function to return the indentation depth.</td> </tr> <tr> +<td><a href="#calculateEndline">calculateEndline</a></td> +<td>Function to calculate the end line of a class or method/function.</td> +</tr> +<tr> <td><a href="#readmodule_ex">readmodule_ex</a></td> <td>Read a module file and return a dictionary of classes.</td> </tr> @@ -622,6 +626,43 @@ <div align="right"><a href="#top">Up</a></div> <hr /> <hr /> +<a NAME="calculateEndline" ID="calculateEndline"></a> +<h2>calculateEndline</h2> +<b>calculateEndline</b>(<i>lineno, lines, indent</i>) + +<p> + Function to calculate the end line of a class or method/function. +</p> +<dl> + +<dt><i>lineno</i> (int)</dt> +<dd> +line number to start at +</dd> +<dt><i>lines</i> (list of str)</dt> +<dd> +list of source lines +</dd> +<dt><i>indent</i> (int)</dt> +<dd> +indent length the class/method/function definition +</dd> +</dl> +<dl> +<dt>Returns:</dt> +<dd> +end line of the class/method/function +</dd> +</dl> +<dl> +<dt>Return Type:</dt> +<dd> +int +</dd> +</dl> +<div align="right"><a href="#top">Up</a></div> +<hr /> +<hr /> <a NAME="readmodule_ex" ID="readmodule_ex"></a> <h2>readmodule_ex</h2> <b>readmodule_ex</b>(<i>module, path=None, inpackage=False, isPyFile=False</i>)
--- a/eric6/Utilities/ClassBrowsers/pyclbr.py Wed Sep 09 18:05:58 2020 +0200 +++ b/eric6/Utilities/ClassBrowsers/pyclbr.py Wed Sep 09 18:07:21 2020 +0200 @@ -400,8 +400,35 @@ @return dictionary containing the extracted data @rtype dict """ + def calculateEndline(lineno, lines, indent): + """ + Function to calculate the end line of a class or method/function. + + @param lineno line number to start at + @type int + @param lines list of source lines + @type list of str + @param indent indent length the class/method/function definition + @type int + @return end line of the class/method/function + @rtype int + """ + # start with zero based line after start line + while lineno < len(lines): + line = lines[lineno] + if line.strip(): + # line contains some text + lineIndent = _indent(line.replace(line.lstrip(), "")) + if lineIndent <= indent: + return lineno + lineno += 1 + + # nothing found + return -1 + # convert eol markers the Python style src = src.replace("\r\n", "\n").replace("\r", "\n") + srcLines = src.splitlines() dictionary = {} dict_counts = {} @@ -413,7 +440,6 @@ deltaindentcalculated = 0 lineno, last_lineno_pos = 1, 0 - lastGlobalEntry = None cur_obj = None i = 0 modifierType = ClbrBaseClasses.Function.General @@ -493,10 +519,8 @@ else: dict_counts[meth_name] = 0 dictionary[meth_name] = f - if not classstack: - if lastGlobalEntry: - lastGlobalEntry.setEndLine(lineno - 1) - lastGlobalEntry = f + endlineno = calculateEndline(lineno, srcLines, thisindent) + f.setEndLine(endlineno) if cur_obj and isinstance(cur_obj, Function): cur_obj.setEndLine(lineno - 1) cur_obj = f @@ -551,6 +575,8 @@ # remember this class cur_class = Class(module, class_name, inherit, file, lineno) + endlineno = calculateEndline(lineno, srcLines, thisindent) + cur_class.setEndLine(endlineno) if not classstack: if class_name in dict_counts: dict_counts[class_name] += 1 @@ -561,10 +587,6 @@ dictionary[class_name] = cur_class else: classstack[-1][0]._addclass(class_name, cur_class) - if not classstack: - if lastGlobalEntry: - lastGlobalEntry.setEndLine(lineno - 1) - lastGlobalEntry = cur_class classstack.append((cur_class, thisindent)) elif m.start("Attribute") >= 0: @@ -603,9 +625,6 @@ module, "Globals", file, lineno) dictionary["@@Globals@@"]._addglobal( Attribute(module, variable_name, file, lineno)) - if lastGlobalEntry: - lastGlobalEntry.setEndLine(lineno - 1) - lastGlobalEntry = None else: index = -1 while index >= -len(classstack):