3 # GObject-Introspection - a framework for introspecting GObject libraries
4 # Copyright (C) 2010 Red Hat, Inc.
5 # Copyright (C) 2010 Johan Dahlin
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
33 class Position(object):
34 """Represents a position in the source file which we
37 def __init__(self, filename=None, line=None, column=None):
38 self.filename = filename
42 def __cmp__(self, other):
43 return cmp((self.filename, self.line, self.column),
44 (other.filename, other.line, other.column))
47 return '<Position %s:%d:%d>' % (
48 os.path.basename(self.filename),
52 def format(self, cwd):
53 filename = self.filename
54 if filename.startswith(cwd):
55 filename = filename[len(cwd):]
56 if self.column is not None:
57 return '%s:%d:%d' % (filename, self.line, self.column)
58 elif self.line is not None:
59 return '%s:%d' % (filename, self.line, )
61 return '%s:' % (filename, )
63 def offset(self, offset):
64 return Position(self.filename, self.line+offset, self.column)
67 class MessageLogger(object):
70 def __init__(self, namespace, output=None):
73 self._cwd = os.getcwd() + os.sep
75 self._namespace = namespace
76 self._enable_warnings = False
77 self._warning_count = 0
80 def get(cls, *args, **kwargs):
81 if cls._instance is None:
82 cls._instance = cls(*args, **kwargs)
85 def enable_warnings(self, enable):
86 self._enable_warnings = enable
88 def get_warning_count(self):
89 return self._warning_count
91 def log(self, log_type, text, positions=None, prefix=None):
92 """Log a warning, using optional file positioning information.
93 If the warning is related to a ast.Node type, see log_node_warning()."""
94 utils.break_on_debug_flag('warning')
96 self._warning_count += 1
98 if not self._enable_warnings and log_type != FATAL:
101 # Always drop through on fatal
103 if type(positions) == set:
104 positions = list(positions)
105 if isinstance(positions, Position):
106 positions = [positions]
109 positions = [Position('<unknown>')]
111 for position in positions[:-1]:
112 self._output.write("%s:\n" % (position.format(cwd=self._cwd), ))
113 last_position = positions[-1].format(cwd=self._cwd)
115 if log_type == WARNING:
116 error_type = "Warning"
117 elif log_type == ERROR:
119 elif log_type == FATAL:
123 '''%s: %s: %s: %s: %s\n''' % (last_position, error_type, self._namespace.name,
127 '''%s: %s: %s: %s\n''' % (last_position, error_type, self._namespace.name, text))
129 self._output.write(text)
130 if log_type == FATAL:
131 utils.break_on_debug_flag('fatal')
132 raise SystemExit(text)
134 def log_node(self, log_type, node, text, context=None, positions=None):
135 """Log a warning, using information about file positions from
136 the given node. The optional context argument, if given, should be
137 another ast.Node type which will also be displayed. If no file position
138 information is available from the node, the position data from the
139 context will be used."""
142 elif getattr(node, 'file_positions', None):
143 positions = node.file_positions
144 elif context and context.file_positions:
145 positions = context.file_positions
149 text = "context=%r %s" % (node, text)
152 text = "%s: %s" % (getattr(context, 'symbol', context.name), text)
153 elif not positions and hasattr(node, 'name'):
154 text = "(%s)%s: %s" % (node.__class__.__name__, node.name, text)
156 self.log(log_type, text, positions)
158 def log_symbol(self, log_type, symbol, text):
159 """Log a warning in the context of the given symbol."""
160 self.log(log_type, text, symbol.position,
161 prefix="symbol=%r" % (symbol.ident, ))
164 def log_node(log_type, node, text, context=None, positions=None):
165 ml = MessageLogger.get()
166 ml.log_node(log_type, node, text, context=context, positions=positions)
168 def warn(text, positions=None, prefix=None):
169 ml = MessageLogger.get()
170 ml.log(WARNING, text, positions, prefix)
172 def warn_node(node, text, context=None, positions=None):
173 log_node(WARNING, node, text, context=context, positions=positions)
175 def warn_symbol(symbol, text):
176 ml = MessageLogger.get()
177 ml.log_symbol(WARNING, symbol, text)
179 def fatal(text, positions=None, prefix=None):
180 ml = MessageLogger.get()
181 ml.log(FATAL, text, positions, prefix)