##// END OF EJS Templates
A refactor to check_complete to pass the test cases.
Tony Fast -
Show More
@@ -470,9 +470,12 b' def make_tokens_by_line(lines):'
470 470 except tokenize.TokenError:
471 471 # Input ended in a multiline string or expression. That's OK for us.
472 472 pass
473
474
473 475 if not tokens_by_line[-1]:
474 476 tokens_by_line.pop()
475 477
478
476 479 return tokens_by_line
477 480
478 481 def show_linewise_tokens(s: str):
@@ -579,7 +582,24 b' class TransformerManager:'
579 582 The number of spaces by which to indent the next line of code. If
580 583 status is not 'incomplete', this is None.
581 584 """
585 # Remember if the lines ends in a new line.
586 ends_with_newline = False
587 for character in reversed(cell):
588 if character == '\n':
589 ends_with_newline = True
590 break
591 elif character.strip():
592 break
593 else:
594 continue
595
596 if ends_with_newline:
597 # Append an newline for consistent tokenization
598 # See https://bugs.python.org/issue33899
599 cell += '\n'
600
582 601 lines = cell.splitlines(keepends=True)
602
583 603 if not lines:
584 604 return 'complete', None
585 605
@@ -608,6 +628,7 b' class TransformerManager:'
608 628 return 'invalid', None
609 629
610 630 tokens_by_line = make_tokens_by_line(lines)
631
611 632 if not tokens_by_line:
612 633 return 'incomplete', find_last_indent(lines)
613 634
@@ -615,30 +636,33 b' class TransformerManager:'
615 636 # We're in a multiline string or expression
616 637 return 'incomplete', find_last_indent(lines)
617 638
618 if len(tokens_by_line[-1]) == 1:
619 return 'incomplete', find_last_indent(lines)
620 # Find the last token on the previous line that's not NEWLINE or COMMENT
621 toks_last_line = tokens_by_line[-1]
622 ix = len(tokens_by_line) - 1
639 newline_types = {tokenize.NEWLINE, tokenize.COMMENT, tokenize.ENDMARKER}
640
641 # Remove newline_types for the list of tokens
642 while len(tokens_by_line) > 1 and len(tokens_by_line[-1]) == 1 \
643 and tokens_by_line[-1][-1].type in newline_types:
644 tokens_by_line.pop()
623 645
646 last_line_token = tokens_by_line[-1]
624 647
625 while ix >= 0 and toks_last_line[-1].type in {tokenize.NEWLINE,
626 tokenize.COMMENT}:
627 ix -= 1
628 if tokens_by_line[ix][-2].string == ':':
648 while tokens_by_line[-1][-1].type in newline_types:
649 last_line_token = tokens_by_line[-1].pop()
650
651 if len(last_line_token) == 1 and not last_line_token[-1]:
652 return 'incomplete', 0
653
654 if last_line_token[-1].string == ':':
629 655 # The last line starts a block (e.g. 'if foo:')
630 656 ix = 0
631 while toks_last_line[ix].type in {tokenize.INDENT, tokenize.DEDENT}:
657 while last_line_token[ix].type \
658 in {tokenize.INDENT, tokenize.DEDENT}:
632 659 ix += 1
633 indent = toks_last_line[ix].start[1]
660
661 indent = last_line_token[ix].start[1]
634 662 return 'incomplete', indent + 4
635 if tokens_by_line[ix][-2].string == '\\':
636 if not tokens_by_line[ix][-2].line.endswith('\\'):
637 return 'invalid', None
638 663
639 # If there's a blank line at the end, assume we're ready to execute
640 if not lines[-1].strip():
641 return 'complete', None
664 if last_line_token[-1].line.endswith('\\'):
665 return 'incomplete', None
642 666
643 667 # At this point, our checks think the code is complete (or invalid).
644 668 # We'll use codeop.compile_command to check this with the real parser
@@ -653,12 +677,13 b' class TransformerManager:'
653 677 if res is None:
654 678 return 'incomplete', find_last_indent(lines)
655 679
656 if toks_last_line[-2].type in {tokenize.NEWLINE, tokenize.NL}:
657 return 'complete', None
680 if last_line_token[-1].type == tokenize.DEDENT:
681 if ends_with_newline:
682 return 'complete', None
683 return 'incomplete', find_last_indent(lines)
658 684
659 if toks_last_line[-2].type == tokenize.DEDENT:
660 if not lines[-1].endswith('\n'):
661 return 'incomplete', find_last_indent(lines)
685 if len(last_line_token) <= 1:
686 return 'incomplete', find_last_indent(lines)
662 687
663 688 return 'complete', None
664 689
General Comments 0
You need to be logged in to leave comments. Login now