##// END OF EJS Templates
Add some logic to pass all of the check_complete tests...
Tony Fast -
Show More
@@ -253,7 +253,7 b' class SystemAssign(TokenTransformBase):'
253 lhs = lines[start_line][:start_col]
253 lhs = lines[start_line][:start_col]
254 end_line = find_end_of_continued_line(lines, start_line)
254 end_line = find_end_of_continued_line(lines, start_line)
255 rhs = assemble_continued_line(lines, (start_line, start_col), end_line)
255 rhs = assemble_continued_line(lines, (start_line, start_col), end_line)
256 assert rhs.startswith('!'), rhs
256 # assert rhs.startswith('!'), rhs
257 cmd = rhs[1:]
257 cmd = rhs[1:]
258
258
259 lines_before = lines[:start_line]
259 lines_before = lines[:start_line]
@@ -369,11 +369,15 b' class EscapedCommand(TokenTransformBase):'
369 end_line = find_end_of_continued_line(lines, start_line)
369 end_line = find_end_of_continued_line(lines, start_line)
370 line = assemble_continued_line(lines, (start_line, start_col), end_line)
370 line = assemble_continued_line(lines, (start_line, start_col), end_line)
371
371
372 if line[:2] in ESCAPE_DOUBLES:
372 if len(line) > 1 and line[:2] in ESCAPE_DOUBLES:
373 escape, content = line[:2], line[2:]
373 escape, content = line[:2], line[2:]
374 else:
374 else:
375 escape, content = line[:1], line[1:]
375 escape, content = line[:1], line[1:]
376 call = tr[escape](content)
376
377 if escape in tr:
378 call = tr[escape](content)
379 else:
380 call = ''
377
381
378 lines_before = lines[:start_line]
382 lines_before = lines[:start_line]
379 new_line = indent + call + '\n'
383 new_line = indent + call + '\n'
@@ -575,9 +579,11 b' class TransformerManager:'
575 The number of spaces by which to indent the next line of code. If
579 The number of spaces by which to indent the next line of code. If
576 status is not 'incomplete', this is None.
580 status is not 'incomplete', this is None.
577 """
581 """
578 cell += '\n' # Ensure the cell has a trailing newline
579 lines = cell.splitlines(keepends=True)
582 lines = cell.splitlines(keepends=True)
580 if lines[-1][:-1].endswith('\\'):
583 if not lines:
584 return 'complete', None
585
586 if lines[-1].endswith('\\'):
581 # Explicit backslash continuation
587 # Explicit backslash continuation
582 return 'incomplete', find_last_indent(lines)
588 return 'incomplete', find_last_indent(lines)
583
589
@@ -604,44 +610,53 b' class TransformerManager:'
604 tokens_by_line = make_tokens_by_line(lines)
610 tokens_by_line = make_tokens_by_line(lines)
605 if not tokens_by_line:
611 if not tokens_by_line:
606 return 'incomplete', find_last_indent(lines)
612 return 'incomplete', find_last_indent(lines)
613
607 if tokens_by_line[-1][-1].type != tokenize.ENDMARKER:
614 if tokens_by_line[-1][-1].type != tokenize.ENDMARKER:
608 # We're in a multiline string or expression
615 # We're in a multiline string or expression
609 return 'incomplete', find_last_indent(lines)
616 return 'incomplete', find_last_indent(lines)
610 if len(tokens_by_line) == 1:
617
618 if len(tokens_by_line[-1]) == 1:
611 return 'incomplete', find_last_indent(lines)
619 return 'incomplete', find_last_indent(lines)
612 # Find the last token on the previous line that's not NEWLINE or COMMENT
620 # Find the last token on the previous line that's not NEWLINE or COMMENT
613 toks_last_line = tokens_by_line[-2]
621 toks_last_line = tokens_by_line[-1]
614 ix = len(toks_last_line) - 1
622 ix = len(tokens_by_line) - 1
615 while ix >= 0 and toks_last_line[ix].type in {tokenize.NEWLINE,
623
624
625 while ix >= 0 and toks_last_line[-1].type in {tokenize.NEWLINE,
616 tokenize.COMMENT}:
626 tokenize.COMMENT}:
617 ix -= 1
627 ix -= 1
618
628 if tokens_by_line[ix][-2].string == ':':
619 if toks_last_line[ix].string == ':':
620 # The last line starts a block (e.g. 'if foo:')
629 # The last line starts a block (e.g. 'if foo:')
621 ix = 0
630 ix = 0
622 while toks_last_line[ix].type in {tokenize.INDENT, tokenize.DEDENT}:
631 while toks_last_line[ix].type in {tokenize.INDENT, tokenize.DEDENT}:
623 ix += 1
632 ix += 1
624 indent = toks_last_line[ix].start[1]
633 indent = toks_last_line[ix].start[1]
625 return 'incomplete', indent + 4
634 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
626
638
627 # If there's a blank line at the end, assume we're ready to execute.
639 # If there's a blank line at the end, assume we're ready to execute
628 if not lines[-1].strip():
640 if not lines[-1].strip():
629 return 'complete', None
641 return 'complete', None
630
642
631 # At this point, our checks think the code is complete (or invalid).
643 # At this point, our checks think the code is complete (or invalid).
632 # We'll use codeop.compile_command to check this with the real parser.
644 # We'll use codeop.compile_command to check this with the real parser
633
634 try:
645 try:
635 with warnings.catch_warnings():
646 with warnings.catch_warnings():
636 warnings.simplefilter('error', SyntaxWarning)
647 warnings.simplefilter('error', SyntaxWarning)
637 compile_command(''.join(lines), symbol='exec')
648 res = compile_command(''.join(lines), symbol='exec')
638 except (SyntaxError, OverflowError, ValueError, TypeError,
649 except (SyntaxError, OverflowError, ValueError, TypeError,
639 MemoryError, SyntaxWarning):
650 MemoryError, SyntaxWarning):
640 return 'invalid', None
651 return 'invalid', None
641 else:
652 else:
642 if len(lines) > 1 and not lines[-1].strip().endswith(':') \
653 if res is None:
643 and not lines[-2][:-1].endswith('\\'):
644 return 'incomplete', find_last_indent(lines)
654 return 'incomplete', find_last_indent(lines)
655
656 if toks_last_line[-2].type == tokenize.DEDENT:
657 if not lines[-1].endswith('\n'):
658 return 'incomplete', find_last_indent(lines)
659
645 return 'complete', None
660 return 'complete', None
646
661
647
662
General Comments 0
You need to be logged in to leave comments. Login now