src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/DocStyleChecker.py

branch
eric7
changeset 10418
4573827e9815
parent 10069
435cc5875135
child 10439
21c28b0f9e41
diff -r c6011e501282 -r 4573827e9815 src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/DocStyleChecker.py
--- a/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/DocStyleChecker.py	Sun Dec 17 17:15:19 2023 +0100
+++ b/src/eric7/Plugins/CheckerPlugins/CodeStyleChecker/DocStyle/DocStyleChecker.py	Mon Dec 18 16:39:01 2023 +0100
@@ -33,9 +33,12 @@
         """
         Constructor
 
-        @param source source code of the context (list of string or string)
-        @param startLine line number the context starts in the source (integer)
-        @param contextType type of the context object (string)
+        @param source source code of the context
+        @type list of str or str
+        @param startLine line number the context starts in the source
+        @type int
+        @param contextType type of the context object
+        @type str
         """
         if isinstance(source, str):
             self.__source = source.splitlines(True)
@@ -55,7 +58,8 @@
         """
         Public method to get the source.
 
-        @return source (list of string)
+        @return source
+        @rtype list of str
         """
         return self.__source
 
@@ -63,7 +67,8 @@
         """
         Public method to get the joined source lines.
 
-        @return source (string)
+        @return source
+        @rtype str
         """
         return "".join(self.__source)
 
@@ -71,7 +76,8 @@
         """
         Public method to get the start line number.
 
-        @return start line number (integer)
+        @return start line number
+        @rtype int
         """
         return self.__start
 
@@ -79,7 +85,8 @@
         """
         Public method to get the end line number.
 
-        @return end line number (integer)
+        @return end line number
+        @rtype int
         """
         return self.__start + len(self.__source) - 1
 
@@ -87,7 +94,8 @@
         """
         Public method to get the indentation of the first line.
 
-        @return indentation string (string)
+        @return indentation string
+        @rtype str
         """
         return self.__indent
 
@@ -95,7 +103,8 @@
         """
         Public method to get the context type.
 
-        @return context type (string)
+        @return context type
+        @rtype str
         """
         return self.__type
 
@@ -175,6 +184,8 @@
         "D261",
         "D262",
         "D263",
+        "D270",
+        "D271",
     ]
 
     def __init__(
@@ -191,16 +202,22 @@
         """
         Constructor
 
-        @param source source code to be checked (list of string)
-        @param filename name of the source file (string)
-        @param select list of selected codes (list of string)
-        @param ignore list of codes to be ignored (list of string)
-        @param expected list of expected codes (list of string)
+        @param source source code to be checked
+        @type list of str
+        @param filename name of the source file
+        @type str
+        @param select list of selected codes
+        @type list of str
+        @param ignore list of codes to be ignored
+        @type list of str
+        @param expected list of expected codes
+        @type list of str
         @param repeat flag indicating to report each occurrence of a code
-            (boolean)
-        @param maxLineLength allowed line length (integer)
-        @param docType type of the documentation strings
-            (string, one of 'eric' or 'pep257')
+        @type bool
+        @param maxLineLength allowed line length
+        @type int
+        @param docType type of the documentation strings (one of 'eric' or 'pep257')
+        @type str
         """
         self.__select = tuple(select)
         self.__ignore = ("",) if select else tuple(ignore)
@@ -296,6 +313,8 @@
                         ("D244", "D245"),
                     ),
                     (self.__checkEricException, ("D250", "D251", "D252", "D253")),
+                    (self.__checkEricDocumentationSequence, ("D270",)),
+                    (self.__checkEricDocumentationDeprecatedTags, ("D271",)),
                 ],
                 "docstring": [
                     (self.__checkTripleDoubleQuotes, ("D111",)),
@@ -321,8 +340,10 @@
         """
         Private method to check if the error code should be ignored.
 
-        @param code message code to check for (string)
-        @return flag indicating to ignore the given code (boolean)
+        @param code message code to check for
+        @type str
+        @return flag indicating to ignore the given code
+        @rtype bool
         """
         return code.startswith(self.__ignore) and not code.startswith(self.__select)
 
@@ -330,10 +351,14 @@
         """
         Private method to record an issue.
 
-        @param lineNumber line number of the issue (integer)
-        @param offset position within line of the issue (integer)
-        @param code message code (string)
-        @param args arguments for the message (list)
+        @param lineNumber line number of the issue
+        @type int
+        @param offset position within line of the issue
+        @type int
+        @param code message code
+        @type str
+        @param args arguments for the message
+        @type list
         """
         if self.__ignoreCode(code):
             return
@@ -369,7 +394,8 @@
         """
         Private method to get the next line from the source.
 
-        @return next line of source (string)
+        @return next line of source
+        @rtype str
         """
         self.__lineNumber += 1
         if self.__lineNumber > len(self.__source):
@@ -400,8 +426,10 @@
         """
         Private method to extract the summary line.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @return summary line (string) and the line it was found on (integer)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @return summary line (string) and the line it was found on
+        @rtype int
         """
         lines = docstringContext.source()
 
@@ -424,9 +452,10 @@
         """
         Private method to extract the summary lines.
 
-        @param docstringContext docstring context (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
         @return summary lines (list of string) and the line it was found on
-            (integer)
+        @rtype int
         """
         summaries = []
         lines = docstringContext.source()
@@ -473,8 +502,10 @@
         Private method to get the argument names of a function node.
 
         @param node AST node to extract arguments names from
+        @type ast.AST
         @return tuple of two list of argument names, one for arguments
-            and one for keyword arguments (tuple of list of string)
+            and one for keyword arguments
+        @rtype tuple of (list of str, list of str)
         """
         arguments = []
         arguments.extend([arg.arg for arg in node.args.args])
@@ -495,8 +526,10 @@
         """
         Private method to extract a docstring given a module source.
 
-        @param source source to parse (list of string)
-        @return context of extracted docstring (DocStyleContext)
+        @param source source to parse
+        @type list of str
+        @return context of extracted docstring
+        @rtype DocStyleContext
         """
         for kind, value, (line, _char), _, _ in tokenize.generate_tokens(
             StringIO("".join(source)).readline
@@ -514,9 +547,12 @@
         """
         Private method to extract a docstring given `def` or `class` source.
 
-        @param context context data to get the docstring from (DocStyleContext)
-        @param what string denoting what is being parsed (string)
-        @return context of extracted docstring (DocStyleContext)
+        @param context context data to get the docstring from
+        @type DocStyleContext
+        @param what string denoting what is being parsed
+        @type str
+        @return context of extracted docstring
+        @rtype DocStyleContext
         """
         moduleDocstring = self.__parseModuleDocstring(context.source())
         if what.startswith("module") or context.contextType() == "module":
@@ -539,8 +575,10 @@
         """
         Private method to extract top-level functions or classes.
 
-        @param keyword keyword signaling what to extract (string)
-        @return extracted function or class contexts (list of DocStyleContext)
+        @param keyword keyword signaling what to extract
+        @type str
+        @return extracted function or class contexts
+        @rtype list of DocStyleContext
         """
         self.__resetReadline()
         tokenGenerator = tokenize.generate_tokens(self.__readline)
@@ -565,7 +603,8 @@
         """
         Private method to extract top-level functions.
 
-        @return extracted function contexts (list of DocStyleContext)
+        @return extracted function contexts
+        @rtype list of DocStyleContext
         """
         if not self.__functionsCache:
             self.__functionsCache = self.__parseTopLevel("def")
@@ -575,7 +614,8 @@
         """
         Private method to extract top-level classes.
 
-        @return extracted class contexts (list of DocStyleContext)
+        @return extracted class contexts
+        @rtype list of DocStyleContext
         """
         if not self.__classesCache:
             self.__classesCache = self.__parseTopLevel("class")
@@ -586,7 +626,9 @@
         Private method to skip over an indented block of source code.
 
         @param tokenGenerator token generator
+        @type str iterator
         @return last token of the indented block
+        @rtype tuple
         """
         kind, value, start, end, raw = next(tokenGenerator)
         while kind != tokenize.INDENT:
@@ -606,7 +648,8 @@
         """
         Private method to extract methods of all classes.
 
-        @return extracted method contexts (list of DocStyleContext)
+        @return extracted method contexts
+        @rtype list of DocStyleContext
         """
         if not self.__methodsCache:
             contexts = []
@@ -644,8 +687,10 @@
         """
         Private method to extract a context from the source.
 
-        @param kind kind of context to extract (string)
-        @return requested contexts (list of DocStyleContext)
+        @param kind kind of context to extract
+        @type str
+        @return requested contexts
+        @rtype list of DocStyleContext
         """
         if kind == "moduleDocstring":
             return [DocStyleContext(self.__source, 0, "module")]
@@ -674,8 +719,10 @@
         """
         Private method to check, if the module has a docstring.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             self.__error(context.start(), 0, "D101")
@@ -697,8 +744,10 @@
         Private method to check, that all public functions and methods
         have a docstring.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         functionName = context.source()[0].lstrip().split()[1].split("(")[0]
         if functionName.startswith("_") and not functionName.endswith("__"):
@@ -731,8 +780,10 @@
         Private method to check, that all public functions and methods
         have a docstring.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         className = context.source()[0].lstrip().split()[1].split("(")[0]
         if className.startswith("_"):
@@ -764,8 +815,10 @@
         Private method to check, that all docstrings are surrounded
         by triple double quotes.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -779,8 +832,10 @@
         Private method to check, that all docstrings containing
         backslashes are surrounded by raw triple double quotes.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -794,8 +849,10 @@
         Private method to check, that one-liner docstrings fit on
         one line with quotes.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -819,8 +876,10 @@
         """
         Private method to check, that docstrings are properly indented.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -844,8 +903,10 @@
         """
         Private method to check, that docstring summaries contain some text.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -858,8 +919,10 @@
         """
         Private method to check, that docstring summaries end with a period.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -873,8 +936,10 @@
         Private method to check, that docstring summaries are in
         imperative mood.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -890,8 +955,10 @@
         Private method to check, that docstring summaries don't repeat
         the function's signature.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -908,8 +975,10 @@
         """
         Private method to check, that docstrings mention the return value type.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -934,8 +1003,10 @@
         Private method to check, that function/method docstrings are not
         preceded by a blank line.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -957,8 +1028,10 @@
         Private method to check, that class docstrings have one
         blank line around them.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -995,8 +1068,10 @@
         Private method to check, that docstring summaries are followed
         by a blank line.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1015,8 +1090,10 @@
         Private method to check, that the last paragraph of docstrings is
         followed by a blank line.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1038,8 +1115,10 @@
         Private method to check, that leading and trailing quotes are on
         a line by themselves.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1054,8 +1133,10 @@
         """
         Private method to check, that docstring summaries end with a period.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1081,8 +1162,10 @@
         Private method to check, that docstrings contain an @return line
         if they return anything and don't otherwise.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1109,8 +1192,10 @@
         Private method to check, that docstrings contain an @yield line
         if they return anything and don't otherwise.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1131,8 +1216,10 @@
         Private method to check, that docstrings contain an @param and/or
         @keyparam line for each argument.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1153,12 +1240,16 @@
             if "cls" in argNames:
                 argNames.remove("cls")
 
-            docstring = docstringContext.ssource()
-            if docstring.count("@param") + docstring.count("@keyparam") < len(
+            tagstring = "".join(
+                line.lstrip()
+                for line in docstringContext.source()
+                if line.lstrip().startswith("@")
+            )
+            if tagstring.count("@param") + tagstring.count("@keyparam") < len(
                 argNames + kwNames
             ):
                 self.__error(docstringContext.end(), 0, "D236")
-            elif docstring.count("@param") + docstring.count("@keyparam") > len(
+            elif tagstring.count("@param") + tagstring.count("@keyparam") > len(
                 argNames + kwNames
             ):
                 self.__error(docstringContext.end(), 0, "D237")
@@ -1192,8 +1283,10 @@
         completeness (i.e. raised exceptions that are not documented or
         documented exceptions that are not raised)
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1252,8 +1345,10 @@
         completeness (i.e. defined signals that are not documented or
         documented signals that are not defined)
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1300,8 +1395,10 @@
         Private method to check, that docstring summaries are followed
         by a blank line.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1325,8 +1422,10 @@
         Private method to check, that class and function/method docstrings
         have no blank line around them.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1381,8 +1480,10 @@
         Private method to check, that the last paragraph of docstrings is
         not followed by a blank line.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1400,8 +1501,10 @@
         Private method to check, that method docstring summaries start with
         specific words.
 
-        @param docstringContext docstring context (DocStyleContext)
-        @param context context of the docstring (DocStyleContext)
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
         """
         if docstringContext is None:
             return
@@ -1504,3 +1607,84 @@
                     self.__error(
                         docstringContext.start() + lineNumber, 0, "D232", "public"
                     )
+
+    def __checkEricDocumentationSequence(
+        self,
+        docstringContext,
+        context,  # noqa: U100
+    ):
+        """
+        Private method to check, that method docstring follows the correct sequence
+        of entries (e.g. @param is followed by @type).
+
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
+        """
+        if docstringContext is None:
+            return
+
+        docTokens = []
+        for lineno, line in enumerate(docstringContext.source()):
+            strippedLine = line.lstrip()
+            if strippedLine.startswith("@"):
+                docTokens.append((strippedLine.split(None, 1)[0], lineno))
+
+        for index in range(len(docTokens)):
+            docToken, lineno = docTokens[index]
+            try:
+                docToken2, _ = docTokens[index + 1]
+            except IndexError:
+                docToken2 = ""
+
+            if docToken in ("@param", "@keyparam") and docToken2 != "@type":
+                self.__error(
+                    docstringContext.start() + lineno, 0, "D270", docToken, "@type"
+                )
+            elif docToken == "@return" and docToken2 != "@rtype":
+                self.__error(
+                    docstringContext.start() + lineno, 0, "D270", docToken, "@rtype"
+                )
+            elif docToken == "@yield" and docToken2 != "@ytype":
+                self.__error(
+                    docstringContext.start() + lineno, 0, "D270", docToken, "@ytype"
+                )
+
+    def __checkEricDocumentationDeprecatedTags(
+        self,
+        docstringContext,
+        context,  # noqa: U100
+    ):
+        """
+        Private method to check the use of deprecated documentation tags.
+
+        @param docstringContext docstring context
+        @type DocStyleContext
+        @param context context of the docstring
+        @type DocStyleContext
+        """
+        if docstringContext is None:
+            return
+
+        deprecationsList = {
+            # key is deprecated tag, value is the tag to be used
+            "@ireturn": "@return",
+            "@ptype": "@type",
+            "@raise": "@exception",
+            "@throws": "@exception",
+        }
+
+        for lineno, line in enumerate(docstringContext.source()):
+            strippedLine = line.lstrip()
+            if strippedLine.startswith("@"):
+                # it is a tag line
+                tag = strippedLine.split(None, 1)[0]
+                with contextlib.suppress(KeyError):
+                    self.__error(
+                        docstringContext.start() + lineno,
+                        0,
+                        "D271",
+                        tag,
+                        deprecationsList[tag],
+                    )

eric ide

mercurial