130 lines
3.0 KiB
Python
130 lines
3.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
lodgeit.lib.compilerparser
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
This module implements parsers for compiler error messages.
|
|
|
|
:copyright: Copyright 2008 by Armin Ronacher.
|
|
:license: BSD
|
|
"""
|
|
import re
|
|
|
|
|
|
_gcc_message_re = re.compile(r'''(?ux)
|
|
^\s*
|
|
(?P<filename>[^:]*)
|
|
:(?P<line>\d*)
|
|
(:(?P<column>\d*))?
|
|
((\s*:)?\s*(?P<level>error|warning)\s*:)?
|
|
\s(?P<message>.*)
|
|
$
|
|
''')
|
|
|
|
_javac_message_re = re.compile(r'''(?ux)
|
|
^\s*
|
|
(?P<filename>[^:]*)
|
|
:(?P<line>\d*)
|
|
(:(?P<column>\d*))?
|
|
\s(?P<message>.*)
|
|
$
|
|
''')
|
|
_javac_prefix_re = re.compile(r'^\s*\[javac\]\s')
|
|
_javac_junk_re = re.compile(r'^((Note:\s+.*?)|(\d+)\s+errors\s*)$')
|
|
|
|
|
|
class Raw(object):
|
|
is_raw = True
|
|
|
|
def __init__(self, raw):
|
|
self.raw = raw
|
|
|
|
|
|
class Message(Raw):
|
|
is_raw = False
|
|
|
|
def __init__(self, raw, filename, lineno, column, message):
|
|
Raw.__init__(self, raw)
|
|
self.filename = filename
|
|
self.lineno = lineno
|
|
self.column = column
|
|
self.message = message
|
|
self.context = ''
|
|
|
|
@property
|
|
def level(self):
|
|
return self.__class__.__name__.lower()
|
|
|
|
|
|
class Warning(Message):
|
|
pass
|
|
|
|
|
|
class Error(Message):
|
|
pass
|
|
|
|
|
|
def make_message(raw, filename=None, line=None, column=None, level='error',
|
|
message=''):
|
|
filename = filename or 'unknown'
|
|
if level == 'error':
|
|
cls = Error
|
|
elif level == 'warning':
|
|
cls = Warning
|
|
else:
|
|
cls = Message
|
|
return cls(raw, filename, line, column, message)
|
|
|
|
|
|
def parse_gcc_messages(data):
|
|
"""Parse gcc messages."""
|
|
result = []
|
|
for line in data.splitlines():
|
|
match = _gcc_message_re.match(line)
|
|
if match is not None:
|
|
result.append(make_message(line, **match.groupdict()))
|
|
return result
|
|
|
|
|
|
def parse_javac_messages(data):
|
|
"""Parse javac messages."""
|
|
result = []
|
|
linebuffer = []
|
|
|
|
def _remove_prefix(line):
|
|
match = _javac_prefix_re.match(line)
|
|
if match is not None:
|
|
line = line[match.end():]
|
|
return line
|
|
|
|
def _append_buffered_lines():
|
|
if not linebuffer:
|
|
return
|
|
if not result:
|
|
result.append(Raw('\n'.join(linebuffer)))
|
|
else:
|
|
last = result[-1]
|
|
last.raw = '\n'.join([last.raw] + linebuffer)
|
|
if not last.is_raw:
|
|
before = last.context and [last.context] or []
|
|
last.context = '\n'.join(before + linebuffer)
|
|
del linebuffer[:]
|
|
|
|
lineiter = iter(data.splitlines())
|
|
for line in lineiter:
|
|
line = _remove_prefix(line)
|
|
match = _javac_junk_re.match(line)
|
|
if match is not None:
|
|
_append_buffered_lines()
|
|
result.append(Raw(line))
|
|
continue
|
|
match = _javac_message_re.match(line)
|
|
if match is None:
|
|
linebuffer.append(line)
|
|
else:
|
|
_append_buffered_lines()
|
|
result.append(make_message(line, **match.groupdict()))
|
|
|
|
_append_buffered_lines()
|
|
return result
|