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

branch
eric7
changeset 10418
4573827e9815
parent 10069
435cc5875135
child 10439
21c28b0f9e41
equal deleted inserted replaced
10417:c6011e501282 10418:4573827e9815
31 31
32 def __init__(self, source, startLine, contextType): 32 def __init__(self, source, startLine, contextType):
33 """ 33 """
34 Constructor 34 Constructor
35 35
36 @param source source code of the context (list of string or string) 36 @param source source code of the context
37 @param startLine line number the context starts in the source (integer) 37 @type list of str or str
38 @param contextType type of the context object (string) 38 @param startLine line number the context starts in the source
39 @type int
40 @param contextType type of the context object
41 @type str
39 """ 42 """
40 if isinstance(source, str): 43 if isinstance(source, str):
41 self.__source = source.splitlines(True) 44 self.__source = source.splitlines(True)
42 else: 45 else:
43 self.__source = source[:] 46 self.__source = source[:]
53 56
54 def source(self): 57 def source(self):
55 """ 58 """
56 Public method to get the source. 59 Public method to get the source.
57 60
58 @return source (list of string) 61 @return source
62 @rtype list of str
59 """ 63 """
60 return self.__source 64 return self.__source
61 65
62 def ssource(self): 66 def ssource(self):
63 """ 67 """
64 Public method to get the joined source lines. 68 Public method to get the joined source lines.
65 69
66 @return source (string) 70 @return source
71 @rtype str
67 """ 72 """
68 return "".join(self.__source) 73 return "".join(self.__source)
69 74
70 def start(self): 75 def start(self):
71 """ 76 """
72 Public method to get the start line number. 77 Public method to get the start line number.
73 78
74 @return start line number (integer) 79 @return start line number
80 @rtype int
75 """ 81 """
76 return self.__start 82 return self.__start
77 83
78 def end(self): 84 def end(self):
79 """ 85 """
80 Public method to get the end line number. 86 Public method to get the end line number.
81 87
82 @return end line number (integer) 88 @return end line number
89 @rtype int
83 """ 90 """
84 return self.__start + len(self.__source) - 1 91 return self.__start + len(self.__source) - 1
85 92
86 def indent(self): 93 def indent(self):
87 """ 94 """
88 Public method to get the indentation of the first line. 95 Public method to get the indentation of the first line.
89 96
90 @return indentation string (string) 97 @return indentation string
98 @rtype str
91 """ 99 """
92 return self.__indent 100 return self.__indent
93 101
94 def contextType(self): 102 def contextType(self):
95 """ 103 """
96 Public method to get the context type. 104 Public method to get the context type.
97 105
98 @return context type (string) 106 @return context type
107 @rtype str
99 """ 108 """
100 return self.__type 109 return self.__type
101 110
102 def setSpecial(self, special): 111 def setSpecial(self, special):
103 """ 112 """
173 "D253", 182 "D253",
174 "D260", 183 "D260",
175 "D261", 184 "D261",
176 "D262", 185 "D262",
177 "D263", 186 "D263",
187 "D270",
188 "D271",
178 ] 189 ]
179 190
180 def __init__( 191 def __init__(
181 self, 192 self,
182 source, 193 source,
189 docType="pep257", 200 docType="pep257",
190 ): 201 ):
191 """ 202 """
192 Constructor 203 Constructor
193 204
194 @param source source code to be checked (list of string) 205 @param source source code to be checked
195 @param filename name of the source file (string) 206 @type list of str
196 @param select list of selected codes (list of string) 207 @param filename name of the source file
197 @param ignore list of codes to be ignored (list of string) 208 @type str
198 @param expected list of expected codes (list of string) 209 @param select list of selected codes
210 @type list of str
211 @param ignore list of codes to be ignored
212 @type list of str
213 @param expected list of expected codes
214 @type list of str
199 @param repeat flag indicating to report each occurrence of a code 215 @param repeat flag indicating to report each occurrence of a code
200 (boolean) 216 @type bool
201 @param maxLineLength allowed line length (integer) 217 @param maxLineLength allowed line length
202 @param docType type of the documentation strings 218 @type int
203 (string, one of 'eric' or 'pep257') 219 @param docType type of the documentation strings (one of 'eric' or 'pep257')
220 @type str
204 """ 221 """
205 self.__select = tuple(select) 222 self.__select = tuple(select)
206 self.__ignore = ("",) if select else tuple(ignore) 223 self.__ignore = ("",) if select else tuple(ignore)
207 self.__expected = expected[:] 224 self.__expected = expected[:]
208 self.__repeat = repeat 225 self.__repeat = repeat
294 ( 311 (
295 self.__checkEricNoBlankBeforeAndAfterClassOrFunction, 312 self.__checkEricNoBlankBeforeAndAfterClassOrFunction,
296 ("D244", "D245"), 313 ("D244", "D245"),
297 ), 314 ),
298 (self.__checkEricException, ("D250", "D251", "D252", "D253")), 315 (self.__checkEricException, ("D250", "D251", "D252", "D253")),
316 (self.__checkEricDocumentationSequence, ("D270",)),
317 (self.__checkEricDocumentationDeprecatedTags, ("D271",)),
299 ], 318 ],
300 "docstring": [ 319 "docstring": [
301 (self.__checkTripleDoubleQuotes, ("D111",)), 320 (self.__checkTripleDoubleQuotes, ("D111",)),
302 (self.__checkBackslashes, ("D112",)), 321 (self.__checkBackslashes, ("D112",)),
303 (self.__checkIndent, ("D122",)), 322 (self.__checkIndent, ("D122",)),
319 338
320 def __ignoreCode(self, code): 339 def __ignoreCode(self, code):
321 """ 340 """
322 Private method to check if the error code should be ignored. 341 Private method to check if the error code should be ignored.
323 342
324 @param code message code to check for (string) 343 @param code message code to check for
325 @return flag indicating to ignore the given code (boolean) 344 @type str
345 @return flag indicating to ignore the given code
346 @rtype bool
326 """ 347 """
327 return code.startswith(self.__ignore) and not code.startswith(self.__select) 348 return code.startswith(self.__ignore) and not code.startswith(self.__select)
328 349
329 def __error(self, lineNumber, offset, code, *args): 350 def __error(self, lineNumber, offset, code, *args):
330 """ 351 """
331 Private method to record an issue. 352 Private method to record an issue.
332 353
333 @param lineNumber line number of the issue (integer) 354 @param lineNumber line number of the issue
334 @param offset position within line of the issue (integer) 355 @type int
335 @param code message code (string) 356 @param offset position within line of the issue
336 @param args arguments for the message (list) 357 @type int
358 @param code message code
359 @type str
360 @param args arguments for the message
361 @type list
337 """ 362 """
338 if self.__ignoreCode(code): 363 if self.__ignoreCode(code):
339 return 364 return
340 365
341 if code in self.counters: 366 if code in self.counters:
367 392
368 def __readline(self): 393 def __readline(self):
369 """ 394 """
370 Private method to get the next line from the source. 395 Private method to get the next line from the source.
371 396
372 @return next line of source (string) 397 @return next line of source
398 @rtype str
373 """ 399 """
374 self.__lineNumber += 1 400 self.__lineNumber += 1
375 if self.__lineNumber > len(self.__source): 401 if self.__lineNumber > len(self.__source):
376 return "" 402 return ""
377 return self.__source[self.__lineNumber - 1] 403 return self.__source[self.__lineNumber - 1]
398 424
399 def __getSummaryLine(self, docstringContext): 425 def __getSummaryLine(self, docstringContext):
400 """ 426 """
401 Private method to extract the summary line. 427 Private method to extract the summary line.
402 428
403 @param docstringContext docstring context (DocStyleContext) 429 @param docstringContext docstring context
404 @return summary line (string) and the line it was found on (integer) 430 @type DocStyleContext
431 @return summary line (string) and the line it was found on
432 @rtype int
405 """ 433 """
406 lines = docstringContext.source() 434 lines = docstringContext.source()
407 435
408 line = ( 436 line = (
409 lines[0] 437 lines[0]
422 450
423 def __getSummaryLines(self, docstringContext): 451 def __getSummaryLines(self, docstringContext):
424 """ 452 """
425 Private method to extract the summary lines. 453 Private method to extract the summary lines.
426 454
427 @param docstringContext docstring context (DocStyleContext) 455 @param docstringContext docstring context
456 @type DocStyleContext
428 @return summary lines (list of string) and the line it was found on 457 @return summary lines (list of string) and the line it was found on
429 (integer) 458 @rtype int
430 """ 459 """
431 summaries = [] 460 summaries = []
432 lines = docstringContext.source() 461 lines = docstringContext.source()
433 462
434 line0 = ( 463 line0 = (
471 def __getArgNames(self, node): 500 def __getArgNames(self, node):
472 """ 501 """
473 Private method to get the argument names of a function node. 502 Private method to get the argument names of a function node.
474 503
475 @param node AST node to extract arguments names from 504 @param node AST node to extract arguments names from
505 @type ast.AST
476 @return tuple of two list of argument names, one for arguments 506 @return tuple of two list of argument names, one for arguments
477 and one for keyword arguments (tuple of list of string) 507 and one for keyword arguments
508 @rtype tuple of (list of str, list of str)
478 """ 509 """
479 arguments = [] 510 arguments = []
480 arguments.extend([arg.arg for arg in node.args.args]) 511 arguments.extend([arg.arg for arg in node.args.args])
481 if node.args.vararg is not None: 512 if node.args.vararg is not None:
482 arguments.append(node.args.vararg.arg) 513 arguments.append(node.args.vararg.arg)
493 524
494 def __parseModuleDocstring(self, source): 525 def __parseModuleDocstring(self, source):
495 """ 526 """
496 Private method to extract a docstring given a module source. 527 Private method to extract a docstring given a module source.
497 528
498 @param source source to parse (list of string) 529 @param source source to parse
499 @return context of extracted docstring (DocStyleContext) 530 @type list of str
531 @return context of extracted docstring
532 @rtype DocStyleContext
500 """ 533 """
501 for kind, value, (line, _char), _, _ in tokenize.generate_tokens( 534 for kind, value, (line, _char), _, _ in tokenize.generate_tokens(
502 StringIO("".join(source)).readline 535 StringIO("".join(source)).readline
503 ): 536 ):
504 if kind in [tokenize.COMMENT, tokenize.NEWLINE, tokenize.NL]: 537 if kind in [tokenize.COMMENT, tokenize.NEWLINE, tokenize.NL]:
512 545
513 def __parseDocstring(self, context, what=""): 546 def __parseDocstring(self, context, what=""):
514 """ 547 """
515 Private method to extract a docstring given `def` or `class` source. 548 Private method to extract a docstring given `def` or `class` source.
516 549
517 @param context context data to get the docstring from (DocStyleContext) 550 @param context context data to get the docstring from
518 @param what string denoting what is being parsed (string) 551 @type DocStyleContext
519 @return context of extracted docstring (DocStyleContext) 552 @param what string denoting what is being parsed
553 @type str
554 @return context of extracted docstring
555 @rtype DocStyleContext
520 """ 556 """
521 moduleDocstring = self.__parseModuleDocstring(context.source()) 557 moduleDocstring = self.__parseModuleDocstring(context.source())
522 if what.startswith("module") or context.contextType() == "module": 558 if what.startswith("module") or context.contextType() == "module":
523 return moduleDocstring 559 return moduleDocstring
524 if moduleDocstring: 560 if moduleDocstring:
537 573
538 def __parseTopLevel(self, keyword): 574 def __parseTopLevel(self, keyword):
539 """ 575 """
540 Private method to extract top-level functions or classes. 576 Private method to extract top-level functions or classes.
541 577
542 @param keyword keyword signaling what to extract (string) 578 @param keyword keyword signaling what to extract
543 @return extracted function or class contexts (list of DocStyleContext) 579 @type str
580 @return extracted function or class contexts
581 @rtype list of DocStyleContext
544 """ 582 """
545 self.__resetReadline() 583 self.__resetReadline()
546 tokenGenerator = tokenize.generate_tokens(self.__readline) 584 tokenGenerator = tokenize.generate_tokens(self.__readline)
547 kind, value, char = None, None, None 585 kind, value, char = None, None, None
548 contexts = [] 586 contexts = []
563 601
564 def __parseFunctions(self): 602 def __parseFunctions(self):
565 """ 603 """
566 Private method to extract top-level functions. 604 Private method to extract top-level functions.
567 605
568 @return extracted function contexts (list of DocStyleContext) 606 @return extracted function contexts
607 @rtype list of DocStyleContext
569 """ 608 """
570 if not self.__functionsCache: 609 if not self.__functionsCache:
571 self.__functionsCache = self.__parseTopLevel("def") 610 self.__functionsCache = self.__parseTopLevel("def")
572 return self.__functionsCache 611 return self.__functionsCache
573 612
574 def __parseClasses(self): 613 def __parseClasses(self):
575 """ 614 """
576 Private method to extract top-level classes. 615 Private method to extract top-level classes.
577 616
578 @return extracted class contexts (list of DocStyleContext) 617 @return extracted class contexts
618 @rtype list of DocStyleContext
579 """ 619 """
580 if not self.__classesCache: 620 if not self.__classesCache:
581 self.__classesCache = self.__parseTopLevel("class") 621 self.__classesCache = self.__parseTopLevel("class")
582 return self.__classesCache 622 return self.__classesCache
583 623
584 def __skipIndentedBlock(self, tokenGenerator): 624 def __skipIndentedBlock(self, tokenGenerator):
585 """ 625 """
586 Private method to skip over an indented block of source code. 626 Private method to skip over an indented block of source code.
587 627
588 @param tokenGenerator token generator 628 @param tokenGenerator token generator
629 @type str iterator
589 @return last token of the indented block 630 @return last token of the indented block
631 @rtype tuple
590 """ 632 """
591 kind, value, start, end, raw = next(tokenGenerator) 633 kind, value, start, end, raw = next(tokenGenerator)
592 while kind != tokenize.INDENT: 634 while kind != tokenize.INDENT:
593 kind, value, start, end, raw = next(tokenGenerator) 635 kind, value, start, end, raw = next(tokenGenerator)
594 indent = 1 636 indent = 1
604 646
605 def __parseMethods(self): 647 def __parseMethods(self):
606 """ 648 """
607 Private method to extract methods of all classes. 649 Private method to extract methods of all classes.
608 650
609 @return extracted method contexts (list of DocStyleContext) 651 @return extracted method contexts
652 @rtype list of DocStyleContext
610 """ 653 """
611 if not self.__methodsCache: 654 if not self.__methodsCache:
612 contexts = [] 655 contexts = []
613 for classContext in self.__parseClasses(): 656 for classContext in self.__parseClasses():
614 tokenGenerator = tokenize.generate_tokens( 657 tokenGenerator = tokenize.generate_tokens(
642 685
643 def __parseContexts(self, kind): 686 def __parseContexts(self, kind):
644 """ 687 """
645 Private method to extract a context from the source. 688 Private method to extract a context from the source.
646 689
647 @param kind kind of context to extract (string) 690 @param kind kind of context to extract
648 @return requested contexts (list of DocStyleContext) 691 @type str
692 @return requested contexts
693 @rtype list of DocStyleContext
649 """ 694 """
650 if kind == "moduleDocstring": 695 if kind == "moduleDocstring":
651 return [DocStyleContext(self.__source, 0, "module")] 696 return [DocStyleContext(self.__source, 0, "module")]
652 if kind == "functionDocstring": 697 if kind == "functionDocstring":
653 return self.__parseFunctions() 698 return self.__parseFunctions()
672 717
673 def __checkModulesDocstrings(self, docstringContext, context): 718 def __checkModulesDocstrings(self, docstringContext, context):
674 """ 719 """
675 Private method to check, if the module has a docstring. 720 Private method to check, if the module has a docstring.
676 721
677 @param docstringContext docstring context (DocStyleContext) 722 @param docstringContext docstring context
678 @param context context of the docstring (DocStyleContext) 723 @type DocStyleContext
724 @param context context of the docstring
725 @type DocStyleContext
679 """ 726 """
680 if docstringContext is None: 727 if docstringContext is None:
681 self.__error(context.start(), 0, "D101") 728 self.__error(context.start(), 0, "D101")
682 return 729 return
683 730
695 def __checkFunctionDocstring(self, docstringContext, context): 742 def __checkFunctionDocstring(self, docstringContext, context):
696 """ 743 """
697 Private method to check, that all public functions and methods 744 Private method to check, that all public functions and methods
698 have a docstring. 745 have a docstring.
699 746
700 @param docstringContext docstring context (DocStyleContext) 747 @param docstringContext docstring context
701 @param context context of the docstring (DocStyleContext) 748 @type DocStyleContext
749 @param context context of the docstring
750 @type DocStyleContext
702 """ 751 """
703 functionName = context.source()[0].lstrip().split()[1].split("(")[0] 752 functionName = context.source()[0].lstrip().split()[1].split("(")[0]
704 if functionName.startswith("_") and not functionName.endswith("__"): 753 if functionName.startswith("_") and not functionName.endswith("__"):
705 if self.__docType == "eric": 754 if self.__docType == "eric":
706 code = "D203" 755 code = "D203"
729 def __checkClassDocstring(self, docstringContext, context): 778 def __checkClassDocstring(self, docstringContext, context):
730 """ 779 """
731 Private method to check, that all public functions and methods 780 Private method to check, that all public functions and methods
732 have a docstring. 781 have a docstring.
733 782
734 @param docstringContext docstring context (DocStyleContext) 783 @param docstringContext docstring context
735 @param context context of the docstring (DocStyleContext) 784 @type DocStyleContext
785 @param context context of the docstring
786 @type DocStyleContext
736 """ 787 """
737 className = context.source()[0].lstrip().split()[1].split("(")[0] 788 className = context.source()[0].lstrip().split()[1].split("(")[0]
738 if className.startswith("_"): 789 if className.startswith("_"):
739 if self.__docType == "eric": 790 if self.__docType == "eric":
740 code = "D205" 791 code = "D205"
762 def __checkTripleDoubleQuotes(self, docstringContext, context): # noqa: U100 813 def __checkTripleDoubleQuotes(self, docstringContext, context): # noqa: U100
763 """ 814 """
764 Private method to check, that all docstrings are surrounded 815 Private method to check, that all docstrings are surrounded
765 by triple double quotes. 816 by triple double quotes.
766 817
767 @param docstringContext docstring context (DocStyleContext) 818 @param docstringContext docstring context
768 @param context context of the docstring (DocStyleContext) 819 @type DocStyleContext
820 @param context context of the docstring
821 @type DocStyleContext
769 """ 822 """
770 if docstringContext is None: 823 if docstringContext is None:
771 return 824 return
772 825
773 docstring = docstringContext.ssource().strip() 826 docstring = docstringContext.ssource().strip()
777 def __checkBackslashes(self, docstringContext, context): # noqa: U100 830 def __checkBackslashes(self, docstringContext, context): # noqa: U100
778 """ 831 """
779 Private method to check, that all docstrings containing 832 Private method to check, that all docstrings containing
780 backslashes are surrounded by raw triple double quotes. 833 backslashes are surrounded by raw triple double quotes.
781 834
782 @param docstringContext docstring context (DocStyleContext) 835 @param docstringContext docstring context
783 @param context context of the docstring (DocStyleContext) 836 @type DocStyleContext
837 @param context context of the docstring
838 @type DocStyleContext
784 """ 839 """
785 if docstringContext is None: 840 if docstringContext is None:
786 return 841 return
787 842
788 docstring = docstringContext.ssource().strip() 843 docstring = docstringContext.ssource().strip()
792 def __checkOneLiner(self, docstringContext, context): 847 def __checkOneLiner(self, docstringContext, context):
793 """ 848 """
794 Private method to check, that one-liner docstrings fit on 849 Private method to check, that one-liner docstrings fit on
795 one line with quotes. 850 one line with quotes.
796 851
797 @param docstringContext docstring context (DocStyleContext) 852 @param docstringContext docstring context
798 @param context context of the docstring (DocStyleContext) 853 @type DocStyleContext
854 @param context context of the docstring
855 @type DocStyleContext
799 """ 856 """
800 if docstringContext is None: 857 if docstringContext is None:
801 return 858 return
802 859
803 lines = docstringContext.source() 860 lines = docstringContext.source()
817 874
818 def __checkIndent(self, docstringContext, context): 875 def __checkIndent(self, docstringContext, context):
819 """ 876 """
820 Private method to check, that docstrings are properly indented. 877 Private method to check, that docstrings are properly indented.
821 878
822 @param docstringContext docstring context (DocStyleContext) 879 @param docstringContext docstring context
823 @param context context of the docstring (DocStyleContext) 880 @type DocStyleContext
881 @param context context of the docstring
882 @type DocStyleContext
824 """ 883 """
825 if docstringContext is None: 884 if docstringContext is None:
826 return 885 return
827 886
828 lines = docstringContext.source() 887 lines = docstringContext.source()
842 901
843 def __checkSummary(self, docstringContext, context): # noqa: U100 902 def __checkSummary(self, docstringContext, context): # noqa: U100
844 """ 903 """
845 Private method to check, that docstring summaries contain some text. 904 Private method to check, that docstring summaries contain some text.
846 905
847 @param docstringContext docstring context (DocStyleContext) 906 @param docstringContext docstring context
848 @param context context of the docstring (DocStyleContext) 907 @type DocStyleContext
908 @param context context of the docstring
909 @type DocStyleContext
849 """ 910 """
850 if docstringContext is None: 911 if docstringContext is None:
851 return 912 return
852 913
853 summary, lineNumber = self.__getSummaryLine(docstringContext) 914 summary, lineNumber = self.__getSummaryLine(docstringContext)
856 917
857 def __checkEndsWithPeriod(self, docstringContext, context): # noqa: U100 918 def __checkEndsWithPeriod(self, docstringContext, context): # noqa: U100
858 """ 919 """
859 Private method to check, that docstring summaries end with a period. 920 Private method to check, that docstring summaries end with a period.
860 921
861 @param docstringContext docstring context (DocStyleContext) 922 @param docstringContext docstring context
862 @param context context of the docstring (DocStyleContext) 923 @type DocStyleContext
924 @param context context of the docstring
925 @type DocStyleContext
863 """ 926 """
864 if docstringContext is None: 927 if docstringContext is None:
865 return 928 return
866 929
867 summary, lineNumber = self.__getSummaryLine(docstringContext) 930 summary, lineNumber = self.__getSummaryLine(docstringContext)
871 def __checkImperativeMood(self, docstringContext, context): # noqa: U100 934 def __checkImperativeMood(self, docstringContext, context): # noqa: U100
872 """ 935 """
873 Private method to check, that docstring summaries are in 936 Private method to check, that docstring summaries are in
874 imperative mood. 937 imperative mood.
875 938
876 @param docstringContext docstring context (DocStyleContext) 939 @param docstringContext docstring context
877 @param context context of the docstring (DocStyleContext) 940 @type DocStyleContext
941 @param context context of the docstring
942 @type DocStyleContext
878 """ 943 """
879 if docstringContext is None: 944 if docstringContext is None:
880 return 945 return
881 946
882 summary, lineNumber = self.__getSummaryLine(docstringContext) 947 summary, lineNumber = self.__getSummaryLine(docstringContext)
888 def __checkNoSignature(self, docstringContext, context): 953 def __checkNoSignature(self, docstringContext, context):
889 """ 954 """
890 Private method to check, that docstring summaries don't repeat 955 Private method to check, that docstring summaries don't repeat
891 the function's signature. 956 the function's signature.
892 957
893 @param docstringContext docstring context (DocStyleContext) 958 @param docstringContext docstring context
894 @param context context of the docstring (DocStyleContext) 959 @type DocStyleContext
960 @param context context of the docstring
961 @type DocStyleContext
895 """ 962 """
896 if docstringContext is None: 963 if docstringContext is None:
897 return 964 return
898 965
899 functionName = context.source()[0].lstrip().split()[1].split("(")[0] 966 functionName = context.source()[0].lstrip().split()[1].split("(")[0]
906 973
907 def __checkReturnType(self, docstringContext, context): 974 def __checkReturnType(self, docstringContext, context):
908 """ 975 """
909 Private method to check, that docstrings mention the return value type. 976 Private method to check, that docstrings mention the return value type.
910 977
911 @param docstringContext docstring context (DocStyleContext) 978 @param docstringContext docstring context
912 @param context context of the docstring (DocStyleContext) 979 @type DocStyleContext
980 @param context context of the docstring
981 @type DocStyleContext
913 """ 982 """
914 if docstringContext is None: 983 if docstringContext is None:
915 return 984 return
916 985
917 if "return" not in docstringContext.ssource().lower(): 986 if "return" not in docstringContext.ssource().lower():
932 def __checkNoBlankLineBefore(self, docstringContext, context): 1001 def __checkNoBlankLineBefore(self, docstringContext, context):
933 """ 1002 """
934 Private method to check, that function/method docstrings are not 1003 Private method to check, that function/method docstrings are not
935 preceded by a blank line. 1004 preceded by a blank line.
936 1005
937 @param docstringContext docstring context (DocStyleContext) 1006 @param docstringContext docstring context
938 @param context context of the docstring (DocStyleContext) 1007 @type DocStyleContext
1008 @param context context of the docstring
1009 @type DocStyleContext
939 """ 1010 """
940 if docstringContext is None: 1011 if docstringContext is None:
941 return 1012 return
942 1013
943 contextLines = context.source() 1014 contextLines = context.source()
955 def __checkBlankBeforeAndAfterClass(self, docstringContext, context): 1026 def __checkBlankBeforeAndAfterClass(self, docstringContext, context):
956 """ 1027 """
957 Private method to check, that class docstrings have one 1028 Private method to check, that class docstrings have one
958 blank line around them. 1029 blank line around them.
959 1030
960 @param docstringContext docstring context (DocStyleContext) 1031 @param docstringContext docstring context
961 @param context context of the docstring (DocStyleContext) 1032 @type DocStyleContext
1033 @param context context of the docstring
1034 @type DocStyleContext
962 """ 1035 """
963 if docstringContext is None: 1036 if docstringContext is None:
964 return 1037 return
965 1038
966 contextLines = context.source() 1039 contextLines = context.source()
993 def __checkBlankAfterSummary(self, docstringContext, context): # noqa: U100 1066 def __checkBlankAfterSummary(self, docstringContext, context): # noqa: U100
994 """ 1067 """
995 Private method to check, that docstring summaries are followed 1068 Private method to check, that docstring summaries are followed
996 by a blank line. 1069 by a blank line.
997 1070
998 @param docstringContext docstring context (DocStyleContext) 1071 @param docstringContext docstring context
999 @param context context of the docstring (DocStyleContext) 1072 @type DocStyleContext
1073 @param context context of the docstring
1074 @type DocStyleContext
1000 """ 1075 """
1001 if docstringContext is None: 1076 if docstringContext is None:
1002 return 1077 return
1003 1078
1004 docstrings = docstringContext.source() 1079 docstrings = docstringContext.source()
1013 def __checkBlankAfterLastParagraph(self, docstringContext, context): # noqa: U100 1088 def __checkBlankAfterLastParagraph(self, docstringContext, context): # noqa: U100
1014 """ 1089 """
1015 Private method to check, that the last paragraph of docstrings is 1090 Private method to check, that the last paragraph of docstrings is
1016 followed by a blank line. 1091 followed by a blank line.
1017 1092
1018 @param docstringContext docstring context (DocStyleContext) 1093 @param docstringContext docstring context
1019 @param context context of the docstring (DocStyleContext) 1094 @type DocStyleContext
1095 @param context context of the docstring
1096 @type DocStyleContext
1020 """ 1097 """
1021 if docstringContext is None: 1098 if docstringContext is None:
1022 return 1099 return
1023 1100
1024 docstrings = docstringContext.source() 1101 docstrings = docstringContext.source()
1036 def __checkEricQuotesOnSeparateLines(self, docstringContext, context): # noqa: U100 1113 def __checkEricQuotesOnSeparateLines(self, docstringContext, context): # noqa: U100
1037 """ 1114 """
1038 Private method to check, that leading and trailing quotes are on 1115 Private method to check, that leading and trailing quotes are on
1039 a line by themselves. 1116 a line by themselves.
1040 1117
1041 @param docstringContext docstring context (DocStyleContext) 1118 @param docstringContext docstring context
1042 @param context context of the docstring (DocStyleContext) 1119 @type DocStyleContext
1120 @param context context of the docstring
1121 @type DocStyleContext
1043 """ 1122 """
1044 if docstringContext is None: 1123 if docstringContext is None:
1045 return 1124 return
1046 1125
1047 lines = docstringContext.source() 1126 lines = docstringContext.source()
1052 1131
1053 def __checkEricEndsWithPeriod(self, docstringContext, context): # noqa: U100 1132 def __checkEricEndsWithPeriod(self, docstringContext, context): # noqa: U100
1054 """ 1133 """
1055 Private method to check, that docstring summaries end with a period. 1134 Private method to check, that docstring summaries end with a period.
1056 1135
1057 @param docstringContext docstring context (DocStyleContext) 1136 @param docstringContext docstring context
1058 @param context context of the docstring (DocStyleContext) 1137 @type DocStyleContext
1138 @param context context of the docstring
1139 @type DocStyleContext
1059 """ 1140 """
1060 if docstringContext is None: 1141 if docstringContext is None:
1061 return 1142 return
1062 1143
1063 summaryLines, lineNumber = self.__getSummaryLines(docstringContext) 1144 summaryLines, lineNumber = self.__getSummaryLines(docstringContext)
1079 def __checkEricReturn(self, docstringContext, context): 1160 def __checkEricReturn(self, docstringContext, context):
1080 """ 1161 """
1081 Private method to check, that docstrings contain an @return line 1162 Private method to check, that docstrings contain an @return line
1082 if they return anything and don't otherwise. 1163 if they return anything and don't otherwise.
1083 1164
1084 @param docstringContext docstring context (DocStyleContext) 1165 @param docstringContext docstring context
1085 @param context context of the docstring (DocStyleContext) 1166 @type DocStyleContext
1167 @param context context of the docstring
1168 @type DocStyleContext
1086 """ 1169 """
1087 if docstringContext is None: 1170 if docstringContext is None:
1088 return 1171 return
1089 1172
1090 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline)) 1173 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline))
1107 def __checkEricYield(self, docstringContext, context): 1190 def __checkEricYield(self, docstringContext, context):
1108 """ 1191 """
1109 Private method to check, that docstrings contain an @yield line 1192 Private method to check, that docstrings contain an @yield line
1110 if they return anything and don't otherwise. 1193 if they return anything and don't otherwise.
1111 1194
1112 @param docstringContext docstring context (DocStyleContext) 1195 @param docstringContext docstring context
1113 @param context context of the docstring (DocStyleContext) 1196 @type DocStyleContext
1197 @param context context of the docstring
1198 @type DocStyleContext
1114 """ 1199 """
1115 if docstringContext is None: 1200 if docstringContext is None:
1116 return 1201 return
1117 1202
1118 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline)) 1203 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline))
1129 def __checkEricFunctionArguments(self, docstringContext, context): 1214 def __checkEricFunctionArguments(self, docstringContext, context):
1130 """ 1215 """
1131 Private method to check, that docstrings contain an @param and/or 1216 Private method to check, that docstrings contain an @param and/or
1132 @keyparam line for each argument. 1217 @keyparam line for each argument.
1133 1218
1134 @param docstringContext docstring context (DocStyleContext) 1219 @param docstringContext docstring context
1135 @param context context of the docstring (DocStyleContext) 1220 @type DocStyleContext
1221 @param context context of the docstring
1222 @type DocStyleContext
1136 """ 1223 """
1137 if docstringContext is None: 1224 if docstringContext is None:
1138 return 1225 return
1139 1226
1140 try: 1227 try:
1151 if "self" in argNames: 1238 if "self" in argNames:
1152 argNames.remove("self") 1239 argNames.remove("self")
1153 if "cls" in argNames: 1240 if "cls" in argNames:
1154 argNames.remove("cls") 1241 argNames.remove("cls")
1155 1242
1156 docstring = docstringContext.ssource() 1243 tagstring = "".join(
1157 if docstring.count("@param") + docstring.count("@keyparam") < len( 1244 line.lstrip()
1245 for line in docstringContext.source()
1246 if line.lstrip().startswith("@")
1247 )
1248 if tagstring.count("@param") + tagstring.count("@keyparam") < len(
1158 argNames + kwNames 1249 argNames + kwNames
1159 ): 1250 ):
1160 self.__error(docstringContext.end(), 0, "D236") 1251 self.__error(docstringContext.end(), 0, "D236")
1161 elif docstring.count("@param") + docstring.count("@keyparam") > len( 1252 elif tagstring.count("@param") + tagstring.count("@keyparam") > len(
1162 argNames + kwNames 1253 argNames + kwNames
1163 ): 1254 ):
1164 self.__error(docstringContext.end(), 0, "D237") 1255 self.__error(docstringContext.end(), 0, "D237")
1165 else: 1256 else:
1166 # extract @param and @keyparam from docstring 1257 # extract @param and @keyparam from docstring
1190 1281
1191 Note: This method also checks the raised and documented exceptions for 1282 Note: This method also checks the raised and documented exceptions for
1192 completeness (i.e. raised exceptions that are not documented or 1283 completeness (i.e. raised exceptions that are not documented or
1193 documented exceptions that are not raised) 1284 documented exceptions that are not raised)
1194 1285
1195 @param docstringContext docstring context (DocStyleContext) 1286 @param docstringContext docstring context
1196 @param context context of the docstring (DocStyleContext) 1287 @type DocStyleContext
1288 @param context context of the docstring
1289 @type DocStyleContext
1197 """ 1290 """
1198 if docstringContext is None: 1291 if docstringContext is None:
1199 return 1292 return
1200 1293
1201 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline)) 1294 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline))
1250 1343
1251 Note: This method also checks the defined and documented signals for 1344 Note: This method also checks the defined and documented signals for
1252 completeness (i.e. defined signals that are not documented or 1345 completeness (i.e. defined signals that are not documented or
1253 documented signals that are not defined) 1346 documented signals that are not defined)
1254 1347
1255 @param docstringContext docstring context (DocStyleContext) 1348 @param docstringContext docstring context
1256 @param context context of the docstring (DocStyleContext) 1349 @type DocStyleContext
1350 @param context context of the docstring
1351 @type DocStyleContext
1257 """ 1352 """
1258 if docstringContext is None: 1353 if docstringContext is None:
1259 return 1354 return
1260 1355
1261 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline)) 1356 tokens = list(tokenize.generate_tokens(StringIO(context.ssource()).readline))
1298 def __checkEricBlankAfterSummary(self, docstringContext, context): # noqa: U100 1393 def __checkEricBlankAfterSummary(self, docstringContext, context): # noqa: U100
1299 """ 1394 """
1300 Private method to check, that docstring summaries are followed 1395 Private method to check, that docstring summaries are followed
1301 by a blank line. 1396 by a blank line.
1302 1397
1303 @param docstringContext docstring context (DocStyleContext) 1398 @param docstringContext docstring context
1304 @param context context of the docstring (DocStyleContext) 1399 @type DocStyleContext
1400 @param context context of the docstring
1401 @type DocStyleContext
1305 """ 1402 """
1306 if docstringContext is None: 1403 if docstringContext is None:
1307 return 1404 return
1308 1405
1309 docstrings = docstringContext.source() 1406 docstrings = docstringContext.source()
1323 ): 1420 ):
1324 """ 1421 """
1325 Private method to check, that class and function/method docstrings 1422 Private method to check, that class and function/method docstrings
1326 have no blank line around them. 1423 have no blank line around them.
1327 1424
1328 @param docstringContext docstring context (DocStyleContext) 1425 @param docstringContext docstring context
1329 @param context context of the docstring (DocStyleContext) 1426 @type DocStyleContext
1427 @param context context of the docstring
1428 @type DocStyleContext
1330 """ 1429 """
1331 if docstringContext is None: 1430 if docstringContext is None:
1332 return 1431 return
1333 1432
1334 contextLines = context.source() 1433 contextLines = context.source()
1379 ): 1478 ):
1380 """ 1479 """
1381 Private method to check, that the last paragraph of docstrings is 1480 Private method to check, that the last paragraph of docstrings is
1382 not followed by a blank line. 1481 not followed by a blank line.
1383 1482
1384 @param docstringContext docstring context (DocStyleContext) 1483 @param docstringContext docstring context
1385 @param context context of the docstring (DocStyleContext) 1484 @type DocStyleContext
1485 @param context context of the docstring
1486 @type DocStyleContext
1386 """ 1487 """
1387 if docstringContext is None: 1488 if docstringContext is None:
1388 return 1489 return
1389 1490
1390 docstrings = docstringContext.source() 1491 docstrings = docstringContext.source()
1398 def __checkEricSummary(self, docstringContext, context): 1499 def __checkEricSummary(self, docstringContext, context):
1399 """ 1500 """
1400 Private method to check, that method docstring summaries start with 1501 Private method to check, that method docstring summaries start with
1401 specific words. 1502 specific words.
1402 1503
1403 @param docstringContext docstring context (DocStyleContext) 1504 @param docstringContext docstring context
1404 @param context context of the docstring (DocStyleContext) 1505 @type DocStyleContext
1506 @param context context of the docstring
1507 @type DocStyleContext
1405 """ 1508 """
1406 if docstringContext is None: 1509 if docstringContext is None:
1407 return 1510 return
1408 1511
1409 summary, lineNumber = self.__getSummaryLine(docstringContext) 1512 summary, lineNumber = self.__getSummaryLine(docstringContext)
1502 else: 1605 else:
1503 if firstWord != "public": 1606 if firstWord != "public":
1504 self.__error( 1607 self.__error(
1505 docstringContext.start() + lineNumber, 0, "D232", "public" 1608 docstringContext.start() + lineNumber, 0, "D232", "public"
1506 ) 1609 )
1610
1611 def __checkEricDocumentationSequence(
1612 self,
1613 docstringContext,
1614 context, # noqa: U100
1615 ):
1616 """
1617 Private method to check, that method docstring follows the correct sequence
1618 of entries (e.g. @param is followed by @type).
1619
1620 @param docstringContext docstring context
1621 @type DocStyleContext
1622 @param context context of the docstring
1623 @type DocStyleContext
1624 """
1625 if docstringContext is None:
1626 return
1627
1628 docTokens = []
1629 for lineno, line in enumerate(docstringContext.source()):
1630 strippedLine = line.lstrip()
1631 if strippedLine.startswith("@"):
1632 docTokens.append((strippedLine.split(None, 1)[0], lineno))
1633
1634 for index in range(len(docTokens)):
1635 docToken, lineno = docTokens[index]
1636 try:
1637 docToken2, _ = docTokens[index + 1]
1638 except IndexError:
1639 docToken2 = ""
1640
1641 if docToken in ("@param", "@keyparam") and docToken2 != "@type":
1642 self.__error(
1643 docstringContext.start() + lineno, 0, "D270", docToken, "@type"
1644 )
1645 elif docToken == "@return" and docToken2 != "@rtype":
1646 self.__error(
1647 docstringContext.start() + lineno, 0, "D270", docToken, "@rtype"
1648 )
1649 elif docToken == "@yield" and docToken2 != "@ytype":
1650 self.__error(
1651 docstringContext.start() + lineno, 0, "D270", docToken, "@ytype"
1652 )
1653
1654 def __checkEricDocumentationDeprecatedTags(
1655 self,
1656 docstringContext,
1657 context, # noqa: U100
1658 ):
1659 """
1660 Private method to check the use of deprecated documentation tags.
1661
1662 @param docstringContext docstring context
1663 @type DocStyleContext
1664 @param context context of the docstring
1665 @type DocStyleContext
1666 """
1667 if docstringContext is None:
1668 return
1669
1670 deprecationsList = {
1671 # key is deprecated tag, value is the tag to be used
1672 "@ireturn": "@return",
1673 "@ptype": "@type",
1674 "@raise": "@exception",
1675 "@throws": "@exception",
1676 }
1677
1678 for lineno, line in enumerate(docstringContext.source()):
1679 strippedLine = line.lstrip()
1680 if strippedLine.startswith("@"):
1681 # it is a tag line
1682 tag = strippedLine.split(None, 1)[0]
1683 with contextlib.suppress(KeyError):
1684 self.__error(
1685 docstringContext.start() + lineno,
1686 0,
1687 "D271",
1688 tag,
1689 deprecationsList[tag],
1690 )

eric ide

mercurial