1717
1818from pylint .interfaces import IRawChecker
1919from pylint .checkers import BaseChecker
20+ from pylint .utils import OPTION_RGX
2021
2122
2223MSGS = {
@@ -50,7 +51,22 @@ class EncodingChecker(BaseChecker):
5051 'help' : ('List of note tags to take in consideration, '
5152 'separated by a comma.' )}),)
5253
53- def _check_note (self , notes , lineno , line ):
54+ def _check_note (self , notes , lineno , line , module_last_lineno ):
55+ """
56+ Add the message 'fixme' in case a note is found in the line.
57+
58+ :param notes: regular expression object matching any notes
59+ (XXX, TODO, FIXME) behind a '#'
60+ :type notes: re.pattern object
61+ :param lineno: line number
62+ :type lineno: int
63+ :param line: line to be checked
64+ :type line: str
65+ :param module_last_lineno: last line number of the module as parsed by astroid
66+ (may be different from real last line number in case
67+ commented lines exist at the end of the module)
68+ :type module_last_lineno: int
69+ """
5470 # First, simply check if the notes are in the line at all. This is an
5571 # optimisation to prevent using the regular expression on every line,
5672 # but rather only on lines which may actually contain one of the notes.
@@ -65,8 +81,25 @@ def _check_note(self, notes, lineno, line):
6581 match = notes .search (line )
6682 if not match :
6783 return
68- self .add_message ('fixme' , args = line [match .start (1 ):].rstrip (),
69- line = lineno )
84+ # In case the module ends with commented lines, the astroid parser
85+ # don't take into account those lines, then:
86+ # - the line number of those lines is greater than the
87+ # module last line number (module.tolineno)
88+ # - astroid module object can't inform pylint
89+ # of disabled messages in those extra lines.
90+ if lineno > module_last_lineno :
91+ disable_option_match = OPTION_RGX .search (line )
92+ if disable_option_match :
93+ try :
94+ _ , value = disable_option_match .group (1 ).split ('=' , 1 )
95+ values = [_val .strip ().upper () for _val in value .split (',' )]
96+ if set (values ) & set (self .config .notes ):
97+ return
98+ except ValueError :
99+ self .add_message ('bad-inline-option' ,
100+ args = disable_option_match .group (1 ).strip (), line = line )
101+ return
102+ self .add_message ('fixme' , args = line [match .start (1 ):].rstrip (), line = lineno )
70103
71104 def _check_encoding (self , lineno , line , file_encoding ):
72105 try :
@@ -100,7 +133,7 @@ def process_module(self, module):
100133 for lineno , line in enumerate (stream ):
101134 line = self ._check_encoding (lineno + 1 , line , encoding )
102135 if line is not None and notes :
103- self ._check_note (notes , lineno + 1 , line )
136+ self ._check_note (notes , lineno + 1 , line , module . tolineno )
104137
105138
106139def register (linter ):
0 commit comments