5 |
5 |
6 """ |
6 """ |
7 Module implementing a class to fix certain code style issues. |
7 Module implementing a class to fix certain code style issues. |
8 """ |
8 """ |
9 |
9 |
10 from __future__ import unicode_literals |
10 try: |
11 |
11 # Python 2 |
|
12 from StringIO import StringIO # __IGNORE_EXCEPTION__ |
|
13 except ImportError: |
|
14 # Python 3 |
|
15 from io import StringIO # __IGNORE_WARNING__ |
12 import os |
16 import os |
13 import re |
17 import re |
|
18 import sys |
14 import tokenize |
19 import tokenize |
15 import io |
20 |
16 |
21 import pep8 |
17 from PyQt4.QtCore import QObject |
22 |
18 |
23 # Tell 'lupdate' which strings to keep for translation. |
19 from E5Gui import E5MessageBox |
24 QT_TRANSLATE_NOOP = lambda mod, txt: txt |
20 |
|
21 from . import pep8 |
|
22 |
|
23 import Utilities |
|
24 |
25 |
25 FixableCodeStyleIssues = [ |
26 FixableCodeStyleIssues = [ |
26 "D111", "D112", "D113", "D121", "D131", "D141", |
27 "D111", "D112", "D113", "D121", "D131", "D141", |
27 "D142", "D143", "D144", "D145", |
28 "D142", "D143", "D144", "D145", |
28 "D221", "D222", "D231", "D242", "D243", "D244", |
29 "D221", "D222", "D231", "D242", "D243", "D244", |
38 "N804", "N805", "N806", |
39 "N804", "N805", "N806", |
39 "W191", "W291", "W292", "W293", "W391", "W603", |
40 "W191", "W291", "W292", "W293", "W391", "W603", |
40 ] |
41 ] |
41 |
42 |
42 |
43 |
43 class CodeStyleFixer(QObject): |
44 class CodeStyleFixer(object): |
44 """ |
45 """ |
45 Class implementing a fixer for certain code style issues. |
46 Class implementing a fixer for certain code style issues. |
46 """ |
47 """ |
47 def __init__(self, project, filename, sourceLines, fixCodes, noFixCodes, |
48 def __init__(self, filename, sourceLines, fixCodes, noFixCodes, |
48 maxLineLength, inPlace): |
49 maxLineLength, inPlace, eol): |
49 """ |
50 """ |
50 Constructor |
51 Constructor |
51 |
52 |
52 @param project reference to the project object (Project) |
|
53 @param filename name of the file to be fixed (string) |
53 @param filename name of the file to be fixed (string) |
54 @param sourceLines list of source lines including eol marker |
54 @param sourceLines list of source lines including eol marker |
55 (list of string) |
55 (list of string) |
56 @param fixCodes list of codes to be fixed as a comma separated |
56 @param fixCodes list of codes to be fixed as a comma separated |
57 string (string) |
57 string (string) |
58 @param noFixCodes list of codes not to be fixed as a comma |
58 @param noFixCodes list of codes not to be fixed as a comma |
59 separated string (string) |
59 separated string (string) |
60 @param maxLineLength maximum allowed line length (integer) |
60 @param maxLineLength maximum allowed line length (integer) |
61 @param inPlace flag indicating to modify the file in place (boolean) |
61 @param inPlace flag indicating to modify the file in place (boolean) |
|
62 @param eol end of line character(s) (string) |
62 """ |
63 """ |
63 super(CodeStyleFixer, self).__init__() |
64 super(CodeStyleFixer, self).__init__() |
64 |
65 |
65 self.__project = project |
|
66 self.__filename = filename |
66 self.__filename = filename |
67 self.__origName = "" |
67 self.__origName = "" |
68 self.__source = sourceLines[:] # save a copy |
68 self.__source = sourceLines[:] # save a copy |
69 self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] |
69 self.__fixCodes = [c.strip() for c in fixCodes.split(",") if c.strip()] |
70 self.__noFixCodes = [ |
70 self.__noFixCodes = [ |
71 c.strip() for c in noFixCodes.split(",") if c.strip()] |
71 c.strip() for c in noFixCodes.split(",") if c.strip()] |
72 self.__maxLineLength = maxLineLength |
72 self.__maxLineLength = maxLineLength |
73 self.fixed = 0 |
73 self.fixed = 0 |
74 |
74 |
75 self.__reindenter = None |
75 self.__reindenter = None |
76 self.__eol = "" |
|
77 self.__indentWord = self.__getIndentWord() |
76 self.__indentWord = self.__getIndentWord() |
78 |
77 |
79 if not inPlace: |
78 if inPlace: |
|
79 # TODO: Do a backup before any changes |
|
80 pass |
|
81 else: |
80 self.__origName = self.__filename |
82 self.__origName = self.__filename |
81 self.__filename = os.path.join( |
83 self.__filename = os.path.join( |
82 os.path.dirname(self.__filename), |
84 os.path.dirname(self.__filename), |
83 "fixed_" + os.path.basename(self.__filename)) |
85 "fixed_" + os.path.basename(self.__filename)) |
84 |
86 self.__eol = eol |
|
87 |
85 self.__fixes = { |
88 self.__fixes = { |
86 "D111": self.__fixD111, |
89 "D111": self.__fixD111, |
87 "D112": self.__fixD112, |
90 "D112": self.__fixD112, |
88 "D113": self.__fixD112, |
91 "D113": self.__fixD112, |
89 "D121": self.__fixD121, |
92 "D121": self.__fixD121, |
174 Public method to save the modified file. |
177 Public method to save the modified file. |
175 |
178 |
176 @param encoding encoding of the source file (string) |
179 @param encoding encoding of the source file (string) |
177 @return flag indicating success (boolean) |
180 @return flag indicating success (boolean) |
178 """ |
181 """ |
|
182 import codecs |
|
183 |
179 if not self.__modified: |
184 if not self.__modified: |
180 # no need to write |
185 # no need to write |
181 return True |
186 return True |
182 |
187 |
183 txt = "".join(self.__source) |
188 txt = "".join(self.__source) |
184 try: |
189 try: |
185 Utilities.writeEncodedFile(self.__filename, txt, encoding) |
190 if sys.version_info[0] == 3: |
186 except (IOError, Utilities.CodingError, UnicodeError) as err: |
191 txt = txt.encode(encoding) |
187 E5MessageBox.critical( |
192 if encoding == 'utf-8-bom': |
188 self, |
193 txt = codecs.BOM_UTF8 + txt |
189 self.trUtf8("Fix Code Style Issues"), |
194 |
190 self.trUtf8( |
195 with open(self.__filename, "wb") as fp: |
191 """<p>Could not save the file <b>{0}</b>.""" |
196 fp.write(txt) |
192 """ Skipping it.</p><p>Reason: {1}</p>""") |
197 except (IOError, UnicodeError): # as err: |
193 .format(self.__filename, str(err)) |
198 # E5MessageBox.critical( |
194 ) |
199 # self, |
|
200 # self.trUtf8("Fix Code Style Issues"), |
|
201 # self.trUtf8( |
|
202 # """<p>Could not save the file <b>{0}</b>.""" |
|
203 # """ Skipping it.</p><p>Reason: {1}</p>""") |
|
204 # .format(self.__filename, str(err)) |
|
205 # ) |
195 return False |
206 return False |
196 |
207 |
197 return True |
208 return True |
198 |
209 |
199 def __codeMatch(self, code): |
210 def __codeMatch(self, code): |
403 string and a set of line numbers belonging to a multi line |
396 string and a set of line numbers belonging to a multi line |
404 documentation string (tuple of two set of integer) |
397 documentation string (tuple of two set of integer) |
405 """ |
398 """ |
406 if self.__multiLineNumbers is None: |
399 if self.__multiLineNumbers is None: |
407 source = "".join(self.__source) |
400 source = "".join(self.__source) |
408 sio = io.StringIO(source) |
401 sio = StringIO(source) |
409 self.__multiLineNumbers = set() |
402 self.__multiLineNumbers = set() |
410 self.__docLineNumbers = set() |
403 self.__docLineNumbers = set() |
411 previousTokenType = '' |
404 previousTokenType = '' |
412 try: |
405 try: |
413 for t in tokenize.generate_tokens(sio.readline): |
406 for t in tokenize.generate_tokens(sio.readline): |
539 return (0, "", 0) |
530 return (0, "", 0) |
540 |
531 |
541 newText = self.__getIndent(self.__source[line]) + \ |
532 newText = self.__getIndent(self.__source[line]) + \ |
542 insertChar + self.__source[line].lstrip() |
533 insertChar + self.__source[line].lstrip() |
543 self.__source[line] = newText |
534 self.__source[line] = newText |
544 return ( |
535 return (1, QT_TRANSLATE_NOOP( |
545 1, |
536 'CodeStyleFixer', |
546 self.trUtf8('Introductory quotes corrected to be {0}"""') |
537 'Introductory quotes corrected to be {0}"""') + |
547 .format(insertChar), |
538 '@@{0}'.format(insertChar), 0) |
548 0) |
|
549 |
539 |
550 def __fixD121(self, code, line, pos, apply=False): |
540 def __fixD121(self, code, line, pos, apply=False): |
551 """ |
541 """ |
552 Private method to fix a single line docstring on multiple lines. |
542 Private method to fix a single line docstring on multiple lines. |
553 |
543 |
570 return (0, "", 0) |
560 return (0, "", 0) |
571 |
561 |
572 docstring = self.__source[line].rstrip() + \ |
562 docstring = self.__source[line].rstrip() + \ |
573 self.__source[line + 1].strip() |
563 self.__source[line + 1].strip() |
574 if docstring.endswith('"""'): |
564 if docstring.endswith('"""'): |
575 docstring += self.__getEol() |
565 docstring += self.__eol |
576 else: |
566 else: |
577 docstring += self.__source[line + 2].lstrip() |
567 docstring += self.__source[line + 2].lstrip() |
578 self.__source[line + 2] = "" |
568 self.__source[line + 2] = "" |
579 |
569 |
580 self.__source[line] = docstring |
570 self.__source[line] = docstring |
581 self.__source[line + 1] = "" |
571 self.__source[line + 1] = "" |
582 return ( |
572 return ( |
583 1, |
573 1, |
584 self.trUtf8("Single line docstring put on one line."), |
574 QT_TRANSLATE_NOOP( |
|
575 'CodeStyleFixer', |
|
576 "Single line docstring put on one line."), |
585 0) |
577 0) |
586 else: |
578 else: |
587 id = self.__getID() |
579 id = self.__getID() |
588 self.__stack.append((id, code, line, pos)) |
580 self.__stack.append((id, code, line, pos)) |
589 return (-1, "", id) |
581 return (-1, "", id) |
606 newText = "" |
598 newText = "" |
607 if self.__source[line].rstrip().endswith(('"""', "'''")) and \ |
599 if self.__source[line].rstrip().endswith(('"""', "'''")) and \ |
608 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')): |
600 self.__source[line].lstrip().startswith(('"""', 'r"""', 'u"""')): |
609 # it is a one-liner |
601 # it is a one-liner |
610 newText = self.__source[line].rstrip()[:-3].rstrip() + "." + \ |
602 newText = self.__source[line].rstrip()[:-3].rstrip() + "." + \ |
611 self.__source[line].rstrip()[-3:] + self.__getEol() |
603 self.__source[line].rstrip()[-3:] + self.__eol |
612 else: |
604 else: |
613 if line < len(self.__source) - 1 and \ |
605 if line < len(self.__source) - 1 and \ |
614 (not self.__source[line + 1].strip() or |
606 (not self.__source[line + 1].strip() or |
615 self.__source[line + 1].lstrip().startswith("@") or |
607 self.__source[line + 1].lstrip().startswith("@") or |
616 (self.__source[line + 1].strip() in ('"""', "'''") and |
608 (self.__source[line + 1].strip() in ('"""', "'''") and |
617 not self.__source[line].lstrip().startswith("@"))): |
609 not self.__source[line].lstrip().startswith("@"))): |
618 newText = self.__source[line].rstrip() + "." + self.__getEol() |
610 newText = self.__source[line].rstrip() + "." + self.__eol |
619 |
611 |
620 if newText: |
612 if newText: |
621 self.__source[line] = newText |
613 self.__source[line] = newText |
622 return (1, self.trUtf8("Period added to summary line."), 0) |
614 return ( |
|
615 1, |
|
616 QT_TRANSLATE_NOOP( |
|
617 'CodeStyleFixer', |
|
618 "Period added to summary line."), |
|
619 0) |
623 else: |
620 else: |
624 return (0, "", 0) |
621 return (0, "", 0) |
625 |
622 |
626 def __fixD141(self, code, line, pos, apply=False): |
623 def __fixD141(self, code, line, pos, apply=False): |
627 """ |
624 """ |
796 else: |
789 else: |
797 first, second = source[:3], source[3:].strip() |
790 first, second = source[:3], source[3:].strip() |
798 else: |
791 else: |
799 # trailing |
792 # trailing |
800 first, second = source[:-3].strip(), source[-3:] |
793 first, second = source[:-3].strip(), source[-3:] |
801 newText = indent + first + self.__getEol() + \ |
794 newText = indent + first + self.__eol + \ |
802 indent + second + self.__getEol() |
795 indent + second + self.__eol |
803 self.__source[line] = newText |
796 self.__source[line] = newText |
804 if code == "D221": |
797 if code == "D221": |
805 msg = self.trUtf8("Leading quotes put on separate line.") |
798 msg = QT_TRANSLATE_NOOP( |
|
799 'CodeStyleFixer', "Leading quotes put on separate line.") |
806 else: |
800 else: |
807 msg = self.trUtf8("Trailing quotes put on separate line.") |
801 msg = QT_TRANSLATE_NOOP( |
|
802 'CodeStyleFixer', "Trailing quotes put on separate line.") |
808 return (1, msg, 0) |
803 return (1, msg, 0) |
809 else: |
804 else: |
810 id = self.__getID() |
805 id = self.__getID() |
811 self.__stack.append((id, code, line, pos)) |
806 self.__stack.append((id, code, line, pos)) |
812 return (-1, "", id) |
807 return (-1, "", id) |
917 self.__reindenter.run() |
917 self.__reindenter.run() |
918 fixedLine = self.__reindenter.fixedLine(line - 1) |
918 fixedLine = self.__reindenter.fixedLine(line - 1) |
919 if fixedLine is not None and fixedLine != self.__source[line - 1]: |
919 if fixedLine is not None and fixedLine != self.__source[line - 1]: |
920 self.__source[line - 1] = fixedLine |
920 self.__source[line - 1] = fixedLine |
921 if code in ["E101", "W191"]: |
921 if code in ["E101", "W191"]: |
922 msg = self.trUtf8("Tab converted to 4 spaces.") |
922 msg = QT_TRANSLATE_NOOP( |
|
923 'CodeStyleFixer', "Tab converted to 4 spaces.") |
923 else: |
924 else: |
924 msg = self.trUtf8( |
925 msg = QT_TRANSLATE_NOOP( |
|
926 'CodeStyleFixer', |
925 "Indentation adjusted to be a multiple of four.") |
927 "Indentation adjusted to be a multiple of four.") |
926 return (1, msg, 0) |
928 return (1, msg, 0) |
927 else: |
929 else: |
928 return (0, "", 0) |
930 return (0, "", 0) |
929 |
931 |
987 line = line - 1 |
991 line = line - 1 |
988 text = self.__source[line] |
992 text = self.__source[line] |
989 indentation = self.__getIndent(text) |
993 indentation = self.__getIndent(text) |
990 self.__source[line] = indentation + \ |
994 self.__source[line] = indentation + \ |
991 self.__indentWord + text.lstrip() |
995 self.__indentWord + text.lstrip() |
992 return ( |
996 return (1, QT_TRANSLATE_NOOP( |
993 1, |
997 'CodeStyleFixer', "Missing indentation of continuation" |
994 self.trUtf8( |
998 " line corrected."), 0) |
995 "Missing indentation of continuation line corrected."), |
|
996 0) |
|
997 return (0, "", 0) |
999 return (0, "", 0) |
998 else: |
1000 else: |
999 id = self.__getID() |
1001 id = self.__getID() |
1000 self.__stackLogical.append((id, code, line, pos)) |
1002 self.__stackLogical.append((id, code, line, pos)) |
1001 return (-1, "", id) |
1003 return (-1, "", id) |
1218 if newText == text: |
1224 if newText == text: |
1219 return (0, "", 0) |
1225 return (0, "", 0) |
1220 |
1226 |
1221 self.__source[line] = newText |
1227 self.__source[line] = newText |
1222 if code in ["E225", "E226", "E227", "E228"]: |
1228 if code in ["E225", "E226", "E227", "E228"]: |
1223 return (1, self.trUtf8("Missing whitespace added."), 0) |
1229 return (1, QT_TRANSLATE_NOOP( |
1224 else: |
1230 'CodeStyleFixer', "Missing whitespace added."), 0) |
1225 return (1, self.trUtf8("Extraneous whitespace removed."), 0) |
1231 else: |
|
1232 return (1, QT_TRANSLATE_NOOP( |
|
1233 'CodeStyleFixer', "Extraneous whitespace removed."), 0) |
1226 |
1234 |
1227 def __fixE231(self, code, line, pos): |
1235 def __fixE231(self, code, line, pos): |
1228 """ |
1236 """ |
1229 Private method to fix missing whitespace after ',;:'. |
1237 Private method to fix missing whitespace after ',;:'. |
1230 |
1238 |
1239 """ |
1247 """ |
1240 line = line - 1 |
1248 line = line - 1 |
1241 pos = pos + 1 |
1249 pos = pos + 1 |
1242 self.__source[line] = self.__source[line][:pos] + \ |
1250 self.__source[line] = self.__source[line][:pos] + \ |
1243 " " + self.__source[line][pos:] |
1251 " " + self.__source[line][pos:] |
1244 return (1, self.trUtf8("Missing whitespace added."), 0) |
1252 return (1, QT_TRANSLATE_NOOP( |
|
1253 'CodeStyleFixer', "Missing whitespace added."), 0) |
1245 |
1254 |
1246 def __fixE251(self, code, line, pos): |
1255 def __fixE251(self, code, line, pos): |
1247 """ |
1256 """ |
1248 Private method to fix extraneous whitespace around keyword and |
1257 Private method to fix extraneous whitespace around keyword and |
1249 default parameter equals. |
1258 default parameter equals. |
1276 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): |
1285 if newText.endswith(('=\\\n', '=\\\r\n', '=\\\r')): |
1277 self.__source[line] = newText.rstrip("\n\r \t\\") |
1286 self.__source[line] = newText.rstrip("\n\r \t\\") |
1278 self.__source[line + 1] = self.__source[line + 1].lstrip() |
1287 self.__source[line + 1] = self.__source[line + 1].lstrip() |
1279 else: |
1288 else: |
1280 self.__source[line] = newText |
1289 self.__source[line] = newText |
1281 return (1, self.trUtf8("Extraneous whitespace removed."), 0) |
1290 return (1, QT_TRANSLATE_NOOP( |
|
1291 'CodeStyleFixer', "Extraneous whitespace removed."), 0) |
1282 |
1292 |
1283 def __fixE261(self, code, line, pos): |
1293 def __fixE261(self, code, line, pos): |
1284 """ |
1294 """ |
1285 Private method to fix whitespace before or after inline comment. |
1295 Private method to fix whitespace before or after inline comment. |
1286 |
1296 |
1297 text = self.__source[line] |
1307 text = self.__source[line] |
1298 left = text[:pos].rstrip(' \t#') |
1308 left = text[:pos].rstrip(' \t#') |
1299 right = text[pos:].lstrip(' \t#') |
1309 right = text[pos:].lstrip(' \t#') |
1300 newText = left + (" # " + right if right.strip() else right) |
1310 newText = left + (" # " + right if right.strip() else right) |
1301 self.__source[line] = newText |
1311 self.__source[line] = newText |
1302 return (1, self.trUtf8("Whitespace around comment sign corrected."), 0) |
1312 return (1, QT_TRANSLATE_NOOP( |
|
1313 'CodeStyleFixer', "Whitespace around comment sign corrected."), |
|
1314 0) |
1303 |
1315 |
1304 def __fixE301(self, code, line, pos, apply=False): |
1316 def __fixE301(self, code, line, pos, apply=False): |
1305 """ |
1317 """ |
1306 Private method to fix the need for one blank line. |
1318 Private method to fix the need for one blank line. |
1307 |
1319 |
1315 @return value indicating an applied/deferred fix (-1, 0, 1), |
1327 @return value indicating an applied/deferred fix (-1, 0, 1), |
1316 a message for the fix (string) and an ID for a deferred |
1328 a message for the fix (string) and an ID for a deferred |
1317 fix (integer) |
1329 fix (integer) |
1318 """ |
1330 """ |
1319 if apply: |
1331 if apply: |
1320 self.__source.insert(line - 1, self.__getEol()) |
1332 self.__source.insert(line - 1, self.__eol) |
1321 return (1, self.trUtf8("One blank line inserted."), 0) |
1333 return (1, QT_TRANSLATE_NOOP( |
|
1334 'CodeStyleFixer', "One blank line inserted."), 0) |
1322 else: |
1335 else: |
1323 id = self.__getID() |
1336 id = self.__getID() |
1324 self.__stack.append((id, code, line, pos)) |
1337 self.__stack.append((id, code, line, pos)) |
1325 return (-1, "", id) |
1338 return (-1, "", id) |
1326 |
1339 |
1470 # statement followed by a semicolon and some unrelated |
1487 # statement followed by a semicolon and some unrelated |
1471 # statement with commas in it. |
1488 # statement with commas in it. |
1472 if ';' in text: |
1489 if ';' in text: |
1473 return (0, "", 0) |
1490 return (0, "", 0) |
1474 |
1491 |
1475 newText = text[:pos].rstrip("\t ,") + self.__getEol() + \ |
1492 newText = text[:pos].rstrip("\t ,") + self.__eol + \ |
1476 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,") |
1493 self.__getIndent(text) + "import " + text[pos:].lstrip("\t ,") |
1477 self.__source[line] = newText |
1494 self.__source[line] = newText |
1478 return (1, self.trUtf8("Imports were put on separate lines."), 0) |
1495 return (1, QT_TRANSLATE_NOOP( |
|
1496 'CodeStyleFixer', "Imports were put on separate lines."), |
|
1497 0) |
1479 else: |
1498 else: |
1480 id = self.__getID() |
1499 id = self.__getID() |
1481 self.__stack.append((id, code, line, pos)) |
1500 self.__stack.append((id, code, line, pos)) |
1482 return (-1, "", id) |
1501 return (-1, "", id) |
1483 |
1502 |
1510 nextText = self.__source[line + 1] |
1529 nextText = self.__source[line + 1] |
1511 else: |
1530 else: |
1512 nextText = "" |
1531 nextText = "" |
1513 shortener = LineShortener( |
1532 shortener = LineShortener( |
1514 text, prevText, nextText, |
1533 text, prevText, nextText, |
1515 maxLength=self.__maxLineLength, eol=self.__getEol(), |
1534 maxLength=self.__maxLineLength, eol=self.__eol, |
1516 indentWord=self.__indentWord, isDocString=isDocString) |
1535 indentWord=self.__indentWord, isDocString=isDocString) |
1517 changed, newText, newNextText = shortener.shorten() |
1536 changed, newText, newNextText = shortener.shorten() |
1518 if changed: |
1537 if changed: |
1519 if newText != text: |
1538 if newText != text: |
1520 self.__source[line] = newText |
1539 self.__source[line] = newText |
1521 if newNextText and newNextText != nextText: |
1540 if newNextText and newNextText != nextText: |
1522 if newNextText == " ": |
1541 if newNextText == " ": |
1523 newNextText = "" |
1542 newNextText = "" |
1524 self.__source[line + 1] = newNextText |
1543 self.__source[line + 1] = newNextText |
1525 return (1, self.trUtf8("Long lines have been shortened."), 0) |
1544 return (1, QT_TRANSLATE_NOOP( |
|
1545 'CodeStyleFixer', "Long lines have been shortened."), |
|
1546 0) |
1526 else: |
1547 else: |
1527 return (0, "", 0) |
1548 return (0, "", 0) |
1528 else: |
1549 else: |
1529 id = self.__getID() |
1550 id = self.__getID() |
1530 self.__stack.append((id, code, line, pos)) |
1551 self.__stack.append((id, code, line, pos)) |
1542 @return value indicating an applied/deferred fix (-1, 0, 1), |
1563 @return value indicating an applied/deferred fix (-1, 0, 1), |
1543 a message for the fix (string) and an ID for a deferred |
1564 a message for the fix (string) and an ID for a deferred |
1544 fix (integer) |
1565 fix (integer) |
1545 """ |
1566 """ |
1546 self.__source[line - 1] = \ |
1567 self.__source[line - 1] = \ |
1547 self.__source[line - 1].rstrip("\n\r \t\\") + self.__getEol() |
1568 self.__source[line - 1].rstrip("\n\r \t\\") + self.__eol |
1548 return (1, self.trUtf8("Redundant backslash in brackets removed."), 0) |
1569 return (1, QT_TRANSLATE_NOOP( |
|
1570 'CodeStyleFixer', "Redundant backslash in brackets removed."), |
|
1571 0) |
1549 |
1572 |
1550 def __fixE701(self, code, line, pos, apply=False): |
1573 def __fixE701(self, code, line, pos, apply=False): |
1551 """ |
1574 """ |
1552 Private method to fix colon-separated compound statements. |
1575 Private method to fix colon-separated compound statements. |
1553 |
1576 |
1565 if apply: |
1588 if apply: |
1566 line = line - 1 |
1589 line = line - 1 |
1567 text = self.__source[line] |
1590 text = self.__source[line] |
1568 pos = pos + 1 |
1591 pos = pos + 1 |
1569 |
1592 |
1570 newText = text[:pos] + self.__getEol() + self.__getIndent(text) + \ |
1593 newText = text[:pos] + self.__eol + self.__getIndent(text) + \ |
1571 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \ |
1594 self.__indentWord + text[pos:].lstrip("\n\r \t\\") + \ |
1572 self.__getEol() |
1595 self.__eol |
1573 self.__source[line] = newText |
1596 self.__source[line] = newText |
1574 return (1, self.trUtf8("Compound statement corrected."), 0) |
1597 return (1, QT_TRANSLATE_NOOP( |
|
1598 'CodeStyleFixer', "Compound statement corrected."), 0) |
1575 else: |
1599 else: |
1576 id = self.__getID() |
1600 id = self.__getID() |
1577 self.__stack.append((id, code, line, pos)) |
1601 self.__stack.append((id, code, line, pos)) |
1578 return (-1, "", id) |
1602 return (-1, "", id) |
1579 |
1603 |
1599 if text.rstrip().endswith("\\"): |
1623 if text.rstrip().endswith("\\"): |
1600 # normalize '1; \\\n2' into '1; 2' |
1624 # normalize '1; \\\n2' into '1; 2' |
1601 self.__source[line] = text.rstrip("\n\r \t\\") |
1625 self.__source[line] = text.rstrip("\n\r \t\\") |
1602 self.__source[line + 1] = self.__source[line + 1].lstrip() |
1626 self.__source[line + 1] = self.__source[line + 1].lstrip() |
1603 elif text.rstrip().endswith(";"): |
1627 elif text.rstrip().endswith(";"): |
1604 self.__source[line] = text.rstrip("\n\r \t;") + self.__getEol() |
1628 self.__source[line] = text.rstrip("\n\r \t;") + self.__eol |
1605 else: |
1629 else: |
1606 first = text[:pos].rstrip("\n\r \t;") + self.__getEol() |
1630 first = text[:pos].rstrip("\n\r \t;") + self.__eol |
1607 second = text[pos:].lstrip("\n\r \t;") |
1631 second = text[pos:].lstrip("\n\r \t;") |
1608 self.__source[line] = first + self.__getIndent(text) + second |
1632 self.__source[line] = first + self.__getIndent(text) + second |
1609 return (1, self.trUtf8("Compound statement corrected."), 0) |
1633 return (1, QT_TRANSLATE_NOOP( |
|
1634 'CodeStyleFixer', "Compound statement corrected."), 0) |
1610 else: |
1635 else: |
1611 id = self.__getID() |
1636 id = self.__getID() |
1612 self.__stack.append((id, code, line, pos)) |
1637 self.__stack.append((id, code, line, pos)) |
1613 return (-1, "", id) |
1638 return (-1, "", id) |
1614 |
1639 |
1673 else: |
1700 else: |
1674 arg = "self" |
1701 arg = "self" |
1675 |
1702 |
1676 if text.rstrip().endswith("("): |
1703 if text.rstrip().endswith("("): |
1677 newText = text + self.__getIndent(text) + \ |
1704 newText = text + self.__getIndent(text) + \ |
1678 self.__indentWord + arg + "," + self.__getEol() |
1705 self.__indentWord + arg + "," + self.__eol |
1679 else: |
1706 else: |
1680 index = text.find("(") + 1 |
1707 index = text.find("(") + 1 |
1681 left = text[:index] |
1708 left = text[:index] |
1682 right = text[index:] |
1709 right = text[index:] |
1683 if right.startswith(")"): |
1710 if right.startswith(")"): |
1684 center = arg |
1711 center = arg |
1685 else: |
1712 else: |
1686 center = arg + ", " |
1713 center = arg + ", " |
1687 newText = left + center + right |
1714 newText = left + center + right |
1688 self.__source[line] = newText |
1715 self.__source[line] = newText |
1689 return (1, self.trUtf8("'{0}' argument added.").format(arg), 0) |
1716 return (1, QT_TRANSLATE_NOOP( |
|
1717 'CodeStyleFixer', "'{0}' argument added.") + |
|
1718 '@@{0}'.format(arg), 0) |
1690 else: |
1719 else: |
1691 id = self.__getID() |
1720 id = self.__getID() |
1692 self.__stack.append((id, code, line, pos)) |
1721 self.__stack.append((id, code, line, pos)) |
1693 return (-1, "", id) |
1722 return (-1, "", id) |
1694 |
1723 |
1765 a message for the fix (string) and an ID for a deferred |
1796 a message for the fix (string) and an ID for a deferred |
1766 fix (integer) |
1797 fix (integer) |
1767 """ |
1798 """ |
1768 self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1", |
1799 self.__source[line - 1] = re.sub(r'[\t ]+(\r?)$', r"\1", |
1769 self.__source[line - 1]) |
1800 self.__source[line - 1]) |
1770 return (1, self.trUtf8("Whitespace stripped from end of line."), 0) |
1801 return (1, QT_TRANSLATE_NOOP( |
|
1802 'CodeStyleFixer', "Whitespace stripped from end of line."), 0) |
1771 |
1803 |
1772 def __fixW292(self, code, line, pos): |
1804 def __fixW292(self, code, line, pos): |
1773 """ |
1805 """ |
1774 Private method to fix a missing newline at the end of file. |
1806 Private method to fix a missing newline at the end of file. |
1775 |
1807 |
1780 @param pos position inside line (integer) |
1812 @param pos position inside line (integer) |
1781 @return value indicating an applied/deferred fix (-1, 0, 1), |
1813 @return value indicating an applied/deferred fix (-1, 0, 1), |
1782 a message for the fix (string) and an ID for a deferred |
1814 a message for the fix (string) and an ID for a deferred |
1783 fix (integer) |
1815 fix (integer) |
1784 """ |
1816 """ |
1785 self.__source[line - 1] += self.__getEol() |
1817 self.__source[line - 1] += self.__eol |
1786 return (1, self.trUtf8("newline added to end of file."), 0) |
1818 return (1, QT_TRANSLATE_NOOP( |
|
1819 'CodeStyleFixer', "newline added to end of file."), 0) |
1787 |
1820 |
1788 def __fixW391(self, code, line, pos): |
1821 def __fixW391(self, code, line, pos): |
1789 """ |
1822 """ |
1790 Private method to fix trailing blank lines. |
1823 Private method to fix trailing blank lines. |
1791 |
1824 |
1820 @return value indicating an applied/deferred fix (-1, 0, 1), |
1855 @return value indicating an applied/deferred fix (-1, 0, 1), |
1821 a message for the fix (string) and an ID for a deferred |
1856 a message for the fix (string) and an ID for a deferred |
1822 fix (integer) |
1857 fix (integer) |
1823 """ |
1858 """ |
1824 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") |
1859 self.__source[line - 1] = self.__source[line - 1].replace("<>", "!=") |
1825 return (1, self.trUtf8("'<>' replaced by '!='."), 0) |
1860 return (1, QT_TRANSLATE_NOOP( |
|
1861 'CodeStyleFixer', "'<>' replaced by '!='."), 0) |
1826 |
1862 |
1827 |
1863 |
1828 class Reindenter(object): |
1864 class Reindenter(object): |
1829 """ |
1865 """ |
1830 Class to reindent badly-indented code to uniformly use four-space |
1866 Class to reindent badly-indented code to uniformly use four-space |
2336 return True, newText, newNext |
2372 return True, newText, newNext |
2337 |
2373 |
2338 indent = self.__getIndent(self.__text) |
2374 indent = self.__getIndent(self.__text) |
2339 source = self.__text[len(indent):] |
2375 source = self.__text[len(indent):] |
2340 assert source.lstrip() == source |
2376 assert source.lstrip() == source |
2341 sio = io.StringIO(source) |
2377 sio = StringIO(source) |
2342 |
2378 |
2343 # Check for multi line string. |
2379 # Check for multi line string. |
2344 try: |
2380 try: |
2345 tokens = list(tokenize.generate_tokens(sio.readline)) |
2381 tokens = list(tokenize.generate_tokens(sio.readline)) |
2346 except (SyntaxError, tokenize.TokenError): |
2382 except (SyntaxError, tokenize.TokenError): |