[gobject-introspection/file-positions-wip] [scanner] Add a Position class



commit 0ef7b5047fb8004ddd3ba4f977f386536d445ce6
Author: Johan Dahlin <johan gnome org>
Date:   Mon Sep 20 17:17:20 2010 -0300

    [scanner] Add a Position class
    
    Add a position class which will make it easier to
    send filename/line/column information to the message
    class.

 giscanner/annotationparser.py |   14 ++----
 giscanner/ast.py              |    7 ++-
 giscanner/maintransformer.py  |    4 +-
 giscanner/message.py          |  103 ++++++++++++++++++++++-------------------
 giscanner/sourcescanner.py    |    7 ++-
 5 files changed, 72 insertions(+), 63 deletions(-)
---
diff --git a/giscanner/annotationparser.py b/giscanner/annotationparser.py
index ba70c3e..aad17e8 100644
--- a/giscanner/annotationparser.py
+++ b/giscanner/annotationparser.py
@@ -22,6 +22,7 @@
 
 import re
 
+from .message import Position
 from .odict import odict
 
 # All gtk-doc comments needs to start with this:
@@ -75,8 +76,6 @@ class DocBlock(object):
         self.tags = odict()
         self.comment = None
         self.params = []
-        self.filename = None
-        self.lineno = -1
 
     def __repr__(self):
         return '<DocBlock %r %r>' % (self.name, self.options)
@@ -93,8 +92,6 @@ class DocTag(object):
         self.options = {}
         self.comment = None
         self.value = ''
-        self.filename = None
-        self.lineno = -1
 
     def __repr__(self):
         return '<DocTag %r %r>' % (self.name, self.options)
@@ -179,8 +176,7 @@ class AnnotationParser(object):
         if cpos:
             block_name = block_name[:cpos]
         block = DocBlock(block_name)
-        block.lineno = lineno
-        block.filename = filename
+        block.position = Position(filename, lineno)
         if cpos:
             block.options = self.parse_options(block, block_header[cpos+2:])
         comment_lines = []
@@ -227,8 +223,7 @@ class AnnotationParser(object):
                 else:
                     argname = TAG_RETURNS
                 tag = DocTag(block, argname)
-                tag.filename = block.filename
-                tag.lineno = block.lineno + lineno
+                tag.position = block.position.offset(lineno)
                 second_colon_index = line.rfind(':')
                 found_options = False
                 if second_colon_index > first_colonspace_index:
@@ -268,8 +263,7 @@ class AnnotationParser(object):
                     tag_name = tag_name.lower()
                     tag = DocTag(block, tag_name)
                     tag.value = line[first_colonspace_index+2:]
-                    tag.filename = block.filename
-                    tag.lineno = block.lineno + lineno
+                    tag.filename = block.position.offset(lineno)
                     block.tags[tag_name] = tag
                 else:
                     comment_lines.append(line)
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 8ff61e1..08129cb 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -19,6 +19,7 @@
 # Boston, MA 02111-1307, USA.
 #
 
+from .message import Position
 from .odict import odict
 from .utils import to_underscores
 
@@ -487,12 +488,12 @@ GIName.  It's possible for nodes to contain or point to other nodes."""
     def inherit_file_positions(self, node):
         self.file_positions.update(node.file_positions)
 
-    def add_file_position(self, filename, line, column):
-        self.file_positions.add((filename, line, column))
+    def add_file_position(self, position):
+        self.file_positions.add(position)
 
     def add_symbol_reference(self, symbol):
         if symbol.source_filename:
-            self.add_file_position(symbol.source_filename, symbol.line, -1)
+            self.add_file_position(Position(symbol.source_filename, symbol.line))
 
     def walk(self, callback, chain):
         res = callback(self, chain)
diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index 533db8f..47014ef 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -544,7 +544,7 @@ usage is void (*_gtk_reserved1)(void);"""
                     message.warn(
                         "Invalid scope %r for parameter %r" % (scope,
                         param.argname),
-                        [(tag.filename, tag.lineno, -1)])
+                        tag.position)
                 else:
                     param.scope = scope
                     param.transfer = ast.PARAM_TRANSFER_NONE
@@ -616,7 +616,7 @@ usage is void (*_gtk_reserved1)(void);"""
             message.warn(
                 '%s: unknown parameter %r in documentation comment%s' % (
                 block.name, doc_name, text),
-                [(block.filename, tag.lineno, -1)])
+                tag.position)
 
     def _apply_annotations_callable(self, node, chain, block):
         self._apply_annotations_annotated(node, block)
diff --git a/giscanner/message.py b/giscanner/message.py
index 3db31e3..baac036 100644
--- a/giscanner/message.py
+++ b/giscanner/message.py
@@ -23,13 +23,41 @@
 import os
 import sys
 
-from . import ast
 from . import utils
 
 (WARNING,
  ERROR,
  FATAL) = range(3)
 
+
+class Position(object):
+    """Represents a position in the source file which we
+    want to inform about.
+    """
+    def __init__(self, filename=None, line=None, column=None):
+        self.filename = filename
+        self.line = line
+        self.column = column
+
+    def __cmp__(self, other):
+        return cmp((self.filename, self.line, self.column),
+                   (other.filename, other.line, other.column))
+
+    def format(self, cwd):
+        filename = self.filename
+        if filename.startswith(cwd):
+            filename = filename[len(cwd):]
+        if self.column is not None:
+            return '%s:%d:%d' % (filename, self.line, self.column)
+        elif self.line is not None:
+            return '%s:%d' % (filename, self.line, )
+        else:
+            return '%s:' % (filename, )
+
+    def offset(self, offset):
+        return Position(self.filename, self.line+offset, self.column)
+
+
 class MessageLogger(object):
     _instance = None
 
@@ -54,7 +82,7 @@ class MessageLogger(object):
     def did_warn(self):
         return self._warned
 
-    def log(self, log_type, text, file_positions=None, prefix=None):
+    def log(self, log_type, text, positions=None, prefix=None):
         """Log a warning, using optional file positioning information.
 If the warning is related to a ast.Node type, see log_node_warning()."""
         utils.break_on_debug_flag('warning')
@@ -66,26 +94,17 @@ If the warning is related to a ast.Node type, see log_node_warning()."""
 
         self._warned = True
 
-        if file_positions is None or len(file_positions) == 0:
-            target_file_positions = [('<unknown>', -1, -1)]
-        else:
-            target_file_positions = file_positions
-
-        position_strings = []
-        for (filename, line, column) in target_file_positions:
-            if filename.startswith(self._cwd):
-                filename = filename[len(self._cwd):]
-            if column != -1:
-                position = '%s:%d:%d' % (filename, line, column)
-            elif line != -1:
-                position = '%s:%d' % (filename, line, )
-            else:
-                position = '%s:' % (filename, )
-            position_strings.append(position)
-
-        for position in position_strings[:-1]:
-            self._output.write("%s:\n" % (position, ))
-        last_position = position_strings[-1]
+        if type(positions) == set:
+            positions = list(positions)
+        if isinstance(positions, Position):
+            positions = [positions]
+
+        if not positions:
+            positions = [Position('<unknown>')]
+
+        for position in positions[:-1]:
+            self._output.write("%s:\n" % (position.format(cwd=self._cwd), ))
+        last_position = positions[-1].format(cwd=self._cwd)
 
         if log_type == WARNING:
             error_type = "Warning"
@@ -111,45 +130,35 @@ the given node.  The optional context argument, if given, should be
 another ast.Node type which will also be displayed.  If no file position
 information is available from the node, the position data from the
 context will be used."""
-        if hasattr(node, 'file_positions'):
-            if (len(node.file_positions) == 0 and
-                (context is not None) and len(context.file_positions) > 0):
-                file_positions = context.file_positions
-            else:
-                file_positions = node.file_positions
+        if getattr(node, 'file_positions', None):
+            positions = node.file_positions
+        elif context and context.file_positions:
+            positions = context.file_positions
         else:
-            file_positions = []
+            positions = []
             if not context:
                 text = "context=%r %s" % (node, text)
 
         if context:
-            if isinstance(context, ast.Function):
-                name = context.symbol
-            else:
-                name = context.name
-            text = "%s: %s" % (name, text)
-        elif len(file_positions) == 0 and hasattr(node, 'name'):
+            text = "%s: %s" % (getattr(context, 'symbol', context.name), text)
+        elif not positions and hasattr(node, 'name'):
             text = "(%s)%s: %s" % (node.__class__.__name__, node.name, text)
 
-        self.log(log_type, text, file_positions)
+        self.log(log_type, text, positions)
 
-    def log_symbol(self, log_type, symbol, text, **kwargs):
+    def log_symbol(self, log_type, symbol, text):
         """Log a warning in the context of the given symbol."""
-        if symbol.source_filename:
-            file_positions = [(symbol.source_filename, symbol.line, -1)]
-        else:
-            file_positions = None
-        prefix = "symbol=%r" % (symbol.ident, )
-        self.log(log_type, text, file_positions, prefix=prefix, **kwargs)
+        self.log(log_type, text, symbol.position,
+                 prefix="symbol=%r" % (symbol.ident, ))
 
 
 def log_node(log_type, node, text, context=None):
     ml = MessageLogger.get()
     ml.log_node(log_type, node, text, context=context)
 
-def warn(text, file_positions=None, prefix=None):
+def warn(text, positions=None, prefix=None):
     ml = MessageLogger.get()
-    ml.log(WARNING, text, file_positions, prefix)
+    ml.log(WARNING, text, positions, prefix)
 
 def warn_node(node, text, context=None):
     log_node(WARNING, node, text, context=context)
@@ -158,6 +167,6 @@ def warn_symbol(symbol, text):
     ml = MessageLogger.get()
     ml.log_symbol(WARNING, symbol, text)
 
-def fatal(text, file_positions=None, prefix=None):
+def fatal(text, positions=None, prefix=None):
     ml = MessageLogger.get()
-    ml.log(FATAL, text, file_positions, prefix)
+    ml.log(FATAL, text, positions, prefix)
diff --git a/giscanner/sourcescanner.py b/giscanner/sourcescanner.py
index a2db2e7..e4c670b 100644
--- a/giscanner/sourcescanner.py
+++ b/giscanner/sourcescanner.py
@@ -24,7 +24,7 @@ import subprocess
 import tempfile
 
 from .libtoolimporter import LibtoolImporter
-
+from .message import Position
 
 (CSYMBOL_TYPE_INVALID,
  CSYMBOL_TYPE_ELLIPSIS,
@@ -198,6 +198,11 @@ class SourceSymbol(object):
     def line(self):
         return self._symbol.line
 
+    @property
+    def position(self):
+        return Position(self._symbol.source_filename,
+                        self._symbol.line)
+
 
 class SourceScanner(object):
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]