示例#1
0
    def skipCodeBlock (self,s,i,kind):

        trace = False ; verbose = True
        # if trace: g.trace('***',g.callers())
        startIndent = self.startSigIndent
        if trace: g.trace('startIndent',startIndent)
        assert startIndent is not None
        i = start = g.skip_ws_and_nl(s,i)
        parenCount = 0
        underIndentedStart = None # The start of trailing underindented blank or comment lines.
        while i < len(s):
            progress = i
            ch = s[i]
            if g.is_nl(s,i):
                if trace and verbose: g.trace(g.get_line(s,i))
                backslashNewline = (i > 0 and g.match(s,i-1,'\\\n'))
                if backslashNewline:
                    # An underindented line, including docstring,
                    # does not end the code block.
                    i += 1 # 2010/11/01
                else:
                    i = g.skip_nl(s,i)
                    j = g.skip_ws(s,i)
                    if g.is_nl(s,j):
                        pass # We have already made progress.
                    else:
                        i,underIndentedStart,breakFlag = self.pythonNewlineHelper(
                            s,i,parenCount,startIndent,underIndentedStart)
                        if breakFlag: break
            elif ch == '#':
                i = g.skip_to_end_of_line(s,i)
            elif ch == '"' or ch == '\'':
                i = g.skip_python_string(s,i)
            elif ch in '[{(':
                i += 1 ; parenCount += 1
                # g.trace('ch',ch,parenCount)
            elif ch in ']})':
                i += 1 ; parenCount -= 1
                # g.trace('ch',ch,parenCount)
            else: i += 1
            assert(progress < i)

        # The actual end of the block.
        if underIndentedStart is not None:
            i = underIndentedStart
            if trace: g.trace('***backtracking to underindent range')
            if trace: g.trace(g.get_line(s,i))

        if 0 < i < len(s) and not g.match(s,i-1,'\n'):
            g.trace('Can not happen: Python block does not end in a newline.')
            g.trace(g.get_line(s,i))
            return i,False

        # 2010/02/19: Include all following material
        # until the next 'def' or 'class'
        i = self.skipToTheNextClassOrFunction(s,i,startIndent)

        if (trace or self.trace) and s[start:i].strip():
            g.trace('%s returns\n' % (kind) + s[start:i])
        return i,True
示例#2
0
 def skipCodeBlock(self, s, i, kind):
     trace = False
     verbose = True
     # if trace: g.trace('***',g.callers())
     startIndent = self.startSigIndent
     if trace: g.trace('startIndent', startIndent)
     assert startIndent is not None
     i = start = g.skip_ws_and_nl(s, i)
     parenCount = 0
     underIndentedStart = None  # The start of trailing underindented blank or comment lines.
     while i < len(s):
         progress = i
         ch = s[i]
         if g.is_nl(s, i):
             if trace and verbose: g.trace(g.get_line(s, i))
             backslashNewline = (i > 0 and g.match(s, i - 1, '\\\n'))
             if backslashNewline:
                 # An underindented line, including docstring,
                 # does not end the code block.
                 i += 1  # 2010/11/01
             else:
                 i = g.skip_nl(s, i)
                 j = g.skip_ws(s, i)
                 if g.is_nl(s, j):
                     pass  # We have already made progress.
                 else:
                     i, underIndentedStart, breakFlag = self.pythonNewlineHelper(
                         s, i, parenCount, startIndent, underIndentedStart)
                     if breakFlag: break
         elif ch == '#':
             i = g.skip_to_end_of_line(s, i)
         elif ch == '"' or ch == '\'':
             i = g.skip_python_string(s, i)
         elif ch in '[{(':
             i += 1
             parenCount += 1
             # g.trace('ch',ch,parenCount)
         elif ch in ']})':
             i += 1
             parenCount -= 1
             # g.trace('ch',ch,parenCount)
         else:
             i += 1
         assert (progress < i)
     # The actual end of the block.
     if underIndentedStart is not None:
         i = underIndentedStart
         if trace: g.trace('***backtracking to underindent range')
         if trace: g.trace(g.get_line(s, i))
     if 0 < i < len(s) and not g.match(s, i - 1, '\n'):
         g.trace('Can not happen: Python block does not end in a newline.')
         g.trace(g.get_line(s, i))
         return i, False
     # 2010/02/19: Include all following material
     # until the next 'def' or 'class'
     i = self.skipToTheNextClassOrFunction(s, i, startIndent)
     if (trace or self.trace) and s[start:i].strip():
         g.trace('%s returns\n' % (kind) + s[start:i])
     return i, True
示例#3
0
 def pythonNewlineHelper(self, s, i, parenCount, startIndent,
                         underIndentedStart):
     trace = False
     breakFlag = False
     j, indent = g.skip_leading_ws_with_indent(s, i, self.tab_width)
     if trace:
         g.trace('startIndent', startIndent, 'indent', indent, 'parenCount',
                 parenCount, 'line', repr(g.get_line(s, j)))
     if indent <= startIndent and parenCount == 0:
         # An underindented line: it ends the block *unless*
         # it is a blank or comment line or (2008/9/1) the end of a triple-quoted string.
         if g.match(s, j, '#'):
             if trace: g.trace('underindent: comment')
             if underIndentedStart is None: underIndentedStart = i
             i = j
         elif g.match(s, j, '\n'):
             if trace: g.trace('underindent: blank line')
             # Blank lines never start the range of underindented lines.
             i = j
         else:
             if trace: g.trace('underindent: end of block')
             breakFlag = True  # The actual end of the block.
     else:
         if underIndentedStart and g.match(s, j, '\n'):
             # Add the blank line to the underindented range.
             if trace:
                 g.trace(
                     'properly indented blank line extends underindent range'
                 )
         elif underIndentedStart and g.match(s, j, '#'):
             # Add the (properly indented!) comment line to the underindented range.
             if trace:
                 g.trace(
                     'properly indented comment line extends underindent range'
                 )
         elif underIndentedStart is None:
             pass
         else:
             # A properly indented non-comment line.
             # Give a message for all underindented comments in underindented range.
             if trace:
                 g.trace(
                     'properly indented line generates underindent errors')
             s2 = s[underIndentedStart:i]
             lines = g.splitlines(s2)
             for line in lines:
                 if line.strip():
                     junk, indent = g.skip_leading_ws_with_indent(
                         line, 0, self.tab_width)
                     if indent <= startIndent:
                         if j not in self.errorLines:  # No error yet given.
                             self.errorLines.append(j)
                             self.underindentedComment(line)
             underIndentedStart = None
     if trace:
         g.trace('breakFlag', breakFlag, 'returns', i, 'underIndentedStart',
                 underIndentedStart)
     return i, underIndentedStart, breakFlag
示例#4
0
    def skipInterface(self, s, i):
        """Skip from the opening delim to *past* the matching closing delim.

        If no matching is found i is set to len(s)"""
        trace = False
        start = i
        delim2 = "end."
        level = 0
        start = i
        startIndent = self.startSigIndent
        if trace:
            g.trace("***", "startIndent", startIndent, g.callers())
        while i < len(s):
            progress = i
            if g.is_nl(s, i):
                backslashNewline = i > 0 and g.match(s, i - 1, "\\\n")
                i = g.skip_nl(s, i)
                if not backslashNewline and not g.is_nl(s, i):
                    j, indent = g.skip_leading_ws_with_indent(s, i, self.tab_width)
                    line = g.get_line(s, j)
                    if trace:
                        g.trace("indent", indent, line)
                    if indent < startIndent and line.strip():
                        # An non-empty underindented line.
                        # Issue an error unless it contains just the closing bracket.
                        if level == 1 and g.match(s, j, delim2):
                            pass
                        else:
                            if j not in self.errorLines:  # No error yet given.
                                self.errorLines.append(j)
                                self.underindentedLine(line)
            elif s[i] in (" ", "\t"):
                i += 1  # speed up the scan.
            elif self.startsComment(s, i):
                i = self.skipComment(s, i)
            elif self.startsString(s, i):
                i = self.skipString(s, i)
            elif g.match(s, i, delim2):
                i += len(delim2)
                if trace:
                    g.trace("returns\n", repr(s[start:i]))
                return i
            else:
                i += 1
            assert progress < i
        self.error("no interface")
        if 1:
            g.pr("** no interface **")
            i, j = g.getLine(s, start)
            g.trace(i, s[i:j])
        else:
            if trace:
                g.trace("** no interface")
        return start
示例#5
0
    def skipInterface(self, s, i):
        '''Skip from the opening delim to *past* the matching closing delim.

        If no matching is found i is set to len(s)'''
        trace = False
        start = i
        delim2 = 'end.'
        level = 0
        start = i
        startIndent = self.startSigIndent
        if trace: g.trace('***', 'startIndent', startIndent, g.callers())
        while i < len(s):
            progress = i
            if g.is_nl(s, i):
                backslashNewline = i > 0 and g.match(s, i - 1, '\\\n')
                i = g.skip_nl(s, i)
                if not backslashNewline and not g.is_nl(s, i):
                    j, indent = g.skip_leading_ws_with_indent(
                        s, i, self.tab_width)
                    line = g.get_line(s, j)
                    if trace: g.trace('indent', indent, line)
                    if indent < startIndent and line.strip():
                        # An non-empty underindented line.
                        # Issue an error unless it contains just the closing bracket.
                        if level == 1 and g.match(s, j, delim2):
                            pass
                        else:
                            if j not in self.errorLines:  # No error yet given.
                                self.errorLines.append(j)
                                self.underindentedLine(line)
            elif s[i] in (
                    ' ',
                    '\t',
            ):
                i += 1  # speed up the scan.
            elif self.startsComment(s, i):
                i = self.skipComment(s, i)
            elif self.startsString(s, i):
                i = self.skipString(s, i)
            elif g.match(s, i, delim2):
                i += len(delim2)
                if trace: g.trace('returns\n', repr(s[start:i]))
                return i
            else:
                i += 1
            assert progress < i
        self.error('no interface')
        if 1:
            g.pr('** no interface **')
            i, j = g.getLine(s, start)
            g.trace(i, s[i:j])
        else:
            if trace: g.trace('** no interface')
        return start
示例#6
0
    def pythonNewlineHelper (self,s,i,parenCount,startIndent,underIndentedStart):

        trace = False
        breakFlag = False
        j, indent = g.skip_leading_ws_with_indent(s,i,self.tab_width)
        if trace: g.trace(
            'startIndent',startIndent,'indent',indent,'parenCount',parenCount,
            'line',repr(g.get_line(s,j)))
        if indent <= startIndent and parenCount == 0:
            # An underindented line: it ends the block *unless*
            # it is a blank or comment line or (2008/9/1) the end of a triple-quoted string.
            if g.match(s,j,'#'):
                if trace: g.trace('underindent: comment')
                if underIndentedStart is None: underIndentedStart = i
                i = j
            elif g.match(s,j,'\n'):
                if trace: g.trace('underindent: blank line')
                # Blank lines never start the range of underindented lines.
                i = j
            else:
                if trace: g.trace('underindent: end of block')
                breakFlag = True # The actual end of the block.
        else:
            if underIndentedStart and g.match(s,j,'\n'):
                # Add the blank line to the underindented range.
                if trace: g.trace('properly indented blank line extends underindent range')
            elif underIndentedStart and g.match(s,j,'#'):
                # Add the (properly indented!) comment line to the underindented range.
                if trace: g.trace('properly indented comment line extends underindent range')
            elif underIndentedStart is None:
                pass
            else:
                # A properly indented non-comment line.
                # Give a message for all underindented comments in underindented range.
                if trace: g.trace('properly indented line generates underindent errors')
                s2 = s[underIndentedStart:i]
                lines = g.splitlines(s2)
                for line in lines:
                    if line.strip():
                        junk, indent = g.skip_leading_ws_with_indent(line,0,self.tab_width)
                        if indent <= startIndent:
                            if j not in self.errorLines: # No error yet given.
                                self.errorLines.append(j)
                                self.underindentedComment(line)
                underIndentedStart = None
        if trace: g.trace('breakFlag',breakFlag,'returns',i,'underIndentedStart',underIndentedStart)
        return i,underIndentedStart,breakFlag
示例#7
0
 def scanFunction(self, parent, s, i):
     '''scan function(args) { body } and then rescan body.'''
     trace = True and not g.unitTesting
     # k1, k2 = g.getLine(s,i)
     # g.trace(s[k1:k2])
     i1 = i
     # Scan backward for '('
     i2 = i - 1
     while 0 <= i2 and s[i2].isspace():
         i2 -= 1
     in_expr = s[i2] == '('
     assert g.match(s, i, 'function')
     i += len('function')
     i = g.skip_ws_and_nl(s, i)
     i = self.skipId(s, i)
     i = g.skip_ws_and_nl(s, i)
     # Skip the argument list.
     if not g.match(s, i, '('):
         if trace: g.trace('syntax error: no argument list', i)
         return i
     i = self.skipBlock(s, i, '(', ')')
     # skipBlock skips the ')'
     if i == len(s):
         g.trace('no args', g.get_line(s, i))
         return i
     # Skip the body.
     i = g.skip_ws_and_nl(s, i)
     if not g.match(s, i, '{'):
         if trace: g.trace('no function body', i)
         return i
     block_i1 = i
     block_i2 = i = self.skipBlock(s, i, '{', '}')
     j = g.skip_ws_and_nl(s, i)
     if g.match(s, j, '('):
         i = g.skip_parens(s, i)
     if in_expr:
         j = g.skip_ws_and_nl(s, i)
         if g.match(s, j, ')'):
             i = j + 1
     assert i > i1
     block_s = s[block_i1 + 1:block_i2 - 1].strip()
     if trace: g.trace('*** rescanning ***\n\n%s\n\n' % block_s)
     self.scanHelper(parent, block_s)
     return i
示例#8
0
 def scanFunction(self, parent, s, i):
     '''scan function(args) { body } and then rescan body.'''
     trace = True and not g.unitTesting
     # k1, k2 = g.getLine(s,i)
     # g.trace(s[k1:k2])
     i1 = i
     # Scan backward for '('
     i2 = i-1
     while 0 <= i2 and s[i2].isspace():
         i2 -= 1
     in_expr = s[i2] == '('
     assert g.match(s, i, 'function')
     i += len('function')
     i = g.skip_ws_and_nl(s, i)
     i = self.skipId(s, i)
     i = g.skip_ws_and_nl(s, i)
     # Skip the argument list.
     if not g.match(s, i, '('):
         if trace: g.trace('syntax error: no argument list',i)
         return i
     i = self.skipBlock(s, i,'(', ')')
         # skipBlock skips the ')'
     if i == len(s):
         g.trace('no args', g.get_line(s, i))
         return i
     # Skip the body.
     i = g.skip_ws_and_nl(s, i)
     if not g.match(s, i, '{'):
         if trace: g.trace('no function body', i)
         return i
     block_i1 = i
     block_i2 = i = self.skipBlock(s, i, '{', '}')
     j = g.skip_ws_and_nl(s,i)
     if g.match(s, j, '('):
         i = g.skip_parens(s, i)
     if in_expr:
         j = g.skip_ws_and_nl(s,i)
         if g.match(s, j, ')'):
             i = j + 1
     assert i > i1
     block_s = s[block_i1+1:block_i2-1].strip()
     if trace: g.trace('*** rescanning ***\n\n%s\n\n' % block_s)
     self.scanHelper(parent, block_s)
     return i
示例#9
0
    def startsHelper(self,s,i,kind,tags,tag=None):
        '''return True if s[i:] starts a class or function.
        Sets sigStart, sigEnd, sigId and codeEnd ivars.'''

        trace = (False and kind == 'class') # and not g.unitTesting
        verbose = True
        self.codeEnd = self.sigEnd = self.sigId = None

        # Underindented lines can happen in any language, not just Python.
        # The skipBlock method of the base class checks for such lines.
        self.startSigIndent = self.getLeadingIndent(s,i)

        # Get the tag that starts the class or function.
        if not g.match(s,i,'<'): return False
        self.sigStart = i
        i += 1
        sigIdStart = j = g.skip_ws_and_nl(s,i)
        i = self.skipId(s,j)

        # Fix bug 501636: Leo's import code should support non-ascii xml tags.
        # The call to g.toUnicode only needed on Python 2.x.
        self.sigId = theId = g.toUnicode(s[j:i].lower())
            # Set sigId ivar 'early' for error messages.
            # Bug fix: html case does not matter.
        if not theId: return False

        if theId not in tags:
            if trace and verbose:
                g.trace('**** %s theId: %s not in tags: %s' % (
                    kind,theId,tags))
            return False

        if trace and verbose: g.trace(theId)
        classId = '' 
        sigId = theId

        # Complete the opening tag.
        i, ok, complete = self.skipToEndOfTag(s,i,start=sigIdStart)
        if not ok:
            if trace and verbose: g.trace('no tail',g.get_line(s,i))
            return False
        sigEnd = i

        # Bug fix: 2011/11/05.
        # For xml/html, make sure the signature includes any trailing whitespace.
        if not g.match(s,sigEnd,'\n') and not g.match(s,sigEnd-1,'\n'):
            # sigEnd = g.skip_line(s,sigEnd)
            sigEnd = g.skip_ws(s,sigEnd)

        if not complete:
            i,ok = self.skipToMatchingTag(s,i,theId,tags,start=sigIdStart)
            if not ok:
                if trace and verbose: g.trace('no matching tag:',theId)
                return False

        # Success: set the ivars.
        # Not used in xml/html.
        # self.sigStart = self.adjustDefStart(s,self.sigStart)
        self.codeEnd = i
        self.sigEnd = sigEnd
        self.sigId = sigId
        self.classId = classId

        # Scan to the start of the next tag.
        done = False
        while not done and i < len(s):
            progress = i
            if self.startsComment(s,i):
                i = self.skipComment(s,i)
            elif self.startsString(s,i):
                i = self.skipString(s,i)
            elif s[i] == '<':
                start = i
                i += 1
                if i < len(s) and s[i] == '/':
                    i += 1
                j = g.skip_ws_and_nl(s,i)
                if self.startsId(s,j):
                    i = self.skipId(s,j)
                    word = s[j:i].lower()
                    if word in tags:
                        self.codeEnd = start
                        done = True
                        break
                else:
                    i = j
            else:
                i += 1

            assert done or progress < i,'i: %d, ch: %s' % (i,repr(s[i]))

        if trace: g.trace(repr(s[self.sigStart:self.codeEnd]))
        return True
示例#10
0
文件: xml.py 项目: pmills/leo-editor
 def startsHelper(self, s, i, kind, tags, tag=None):
     '''return True if s[i:] starts a class or function.
     Sets sigStart, sigEnd, sigId and codeEnd ivars.'''
     trace = (False and kind == 'class')  # and not g.unitTesting
     verbose = True
     self.codeEnd = self.sigEnd = self.sigId = None
     # Underindented lines can happen in any language, not just Python.
     # The skipBlock method of the base class checks for such lines.
     self.startSigIndent = self.getLeadingIndent(s, i)
     # Get the tag that starts the class or function.
     if not g.match(s, i, '<'): return False
     self.sigStart = i
     i += 1
     sigIdStart = j = g.skip_ws_and_nl(s, i)
     i = self.skipId(s, j)
     # Fix bug 501636: Leo's import code should support non-ascii xml tags.
     # The call to g.toUnicode only needed on Python 2.x.
     self.sigId = theId = g.toUnicode(s[j:i].lower())
     # Set sigId ivar 'early' for error messages.
     # Bug fix: html case does not matter.
     if not theId: return False
     if theId not in tags:
         if trace and verbose:
             g.trace('**** %s theId: %s not in tags: %s' %
                     (kind, theId, tags))
         return False
     if trace and verbose: g.trace(theId)
     classId = ''
     sigId = theId
     # Complete the opening tag.
     i, ok, complete = self.skipToEndOfTag(s, i, start=sigIdStart)
     if not ok:
         if trace and verbose: g.trace('no tail', g.get_line(s, i))
         return False
     sigEnd = i
     # Bug fix: 2011/11/05.
     # For xml/html, make sure the signature includes any trailing whitespace.
     if not g.match(s, sigEnd, '\n') and not g.match(s, sigEnd - 1, '\n'):
         # sigEnd = g.skip_line(s,sigEnd)
         sigEnd = g.skip_ws(s, sigEnd)
     if not complete:
         i, ok = self.skipToMatchingTag(s, i, theId, tags, start=sigIdStart)
         if not ok:
             if trace and verbose: g.trace('no matching tag:', theId)
             return False
     # Success: set the ivars.
     # Not used in xml/html.
     # self.sigStart = self.adjustDefStart(s,self.sigStart)
     self.codeEnd = i
     self.sigEnd = sigEnd
     self.sigId = sigId
     self.classId = classId
     # Scan to the start of the next tag.
     done = False
     while not done and i < len(s):
         progress = i
         if self.startsComment(s, i):
             i = self.skipComment(s, i)
         elif self.startsString(s, i):
             i = self.skipString(s, i)
         elif s[i] == '<':
             start = i
             i += 1
             if i < len(s) and s[i] == '/':
                 i += 1
             j = g.skip_ws_and_nl(s, i)
             if self.startsId(s, j):
                 i = self.skipId(s, j)
                 word = s[j:i].lower()
                 if word in tags:
                     self.codeEnd = start
                     done = True
                     break
             else:
                 i = j
         else:
             i += 1
         assert done or progress < i, 'i: %d, ch: %s' % (i, repr(s[i]))
     if trace: g.trace(repr(s[self.sigStart:self.codeEnd]))
     return True