micropython

Changeset

536:897aa8ac4729
2012-06-10 Paul Boddie raw files shortlog changelog graph Introduced attribute target reporting with links to attribute definitions.
micropython/report.py (file)
     1.1 --- a/micropython/report.py	Sat Jun 09 23:24:18 2012 +0200
     1.2 +++ b/micropython/report.py	Sun Jun 10 01:49:51 2012 +0200
     1.3 @@ -76,6 +76,7 @@
     1.4        z-index: 3;
     1.5      }
     1.6  
     1.7 +    .attributes-popup,
     1.8      .types-popup {
     1.9        display: none;
    1.10        position: absolute;
    1.11 @@ -91,6 +92,7 @@
    1.12        color: white;
    1.13      }
    1.14  
    1.15 +    .attr,
    1.16      .accessor,
    1.17      .name,
    1.18      .operation {
    1.19 @@ -99,6 +101,7 @@
    1.20        color: white;
    1.21      }
    1.22  
    1.23 +    .attr:hover,
    1.24      .accessor:hover,
    1.25      .name:hover,
    1.26      .operation:hover {
    1.27 @@ -108,6 +111,7 @@
    1.28        z-index: 2;
    1.29      }
    1.30  
    1.31 +    .attr:hover .attributes-popup,
    1.32      .accessor:hover .types-popup,
    1.33      .name:hover .popup,
    1.34      .operation:hover .popup {
    1.35 @@ -122,6 +126,7 @@
    1.36        background-color: #700;
    1.37      }
    1.38  
    1.39 +    .attrnames a,
    1.40      .opnames a {
    1.41        color: white;
    1.42      }
    1.43 @@ -304,20 +309,26 @@
    1.44          if trailing:
    1.45              self.stream.write(" ")
    1.46  
    1.47 +    def _names_list_start(self, label, classes):
    1.48 +        self.stream.write("<div class='%s'><span class='label'>%s</span><br />" % (classes, label))
    1.49 +
    1.50 +    def _names_list_end(self):
    1.51 +        self.stream.write("</div>\n")
    1.52 +
    1.53      def _names_list(self, names, label, classes):
    1.54          if not names:
    1.55              return
    1.56          names = list(names)
    1.57          names.sort()
    1.58  
    1.59 -        self.stream.write("<div class='%s'><span class='label'>%s</span><br />" % (classes, label))
    1.60 +        self._names_list_start(label, classes)
    1.61          first = 1
    1.62          for name in names:
    1.63              if not first:
    1.64                  self.stream.write("<br />")
    1.65              self.stream.write(name)
    1.66              first = 0
    1.67 -        self.stream.write("</div>\n")
    1.68 +        self._names_list_end()
    1.69  
    1.70      def _attrcombined(self, name, node):
    1.71          attrcombined = hasattr(node, "_attrcombined") and node._attrcombined.get(name) or []
    1.72 @@ -354,6 +365,59 @@
    1.73          if target_names:
    1.74              self._span_end()
    1.75  
    1.76 +    def _attribute_start(self, attrname, attributes):
    1.77 +        if attributes:
    1.78 +            attributes.sort(key=lambda t: t[2])
    1.79 +
    1.80 +            self._span_start("attr")
    1.81 +            self._popup_start("attributes-popup")
    1.82 +            self._names_list_start("attributes", "attrnames")
    1.83 +
    1.84 +            # Mix links to attributes with labels indicating undetermined
    1.85 +            # attributes.
    1.86 +
    1.87 +            last = None
    1.88 +            for value, target, target_name in attributes:
    1.89 +                if value and not isinstance(value, Instance):
    1.90 +                    fullname = value.full_name()
    1.91 +                    current = (value, fullname)
    1.92 +                    if current != last:
    1.93 +                        if last is not None:
    1.94 +                            self.stream.write("<br />")
    1.95 +                        self._object_name_ref(value.module, value, fullname, classes="attribute-name")
    1.96 +                else:
    1.97 +                    fullname = target_name + "." + attrname
    1.98 +                    current = (None, fullname)
    1.99 +                    if current != last:
   1.100 +                        if last is not None:
   1.101 +                            self.stream.write("<br />")
   1.102 +                        self.stream.write(fullname)
   1.103 +                last = current
   1.104 +
   1.105 +            self._names_list_end()
   1.106 +            self._popup_end()
   1.107 +
   1.108 +    def _attribute_end(self, attributes):
   1.109 +        if attributes:
   1.110 +            self._span_end()
   1.111 +
   1.112 +    def _get_attributes(self, possible_types, attrname):
   1.113 +        objtable = self.program.get_object_table()
   1.114 +        attributes = []
   1.115 +        for target_name, is_static in possible_types:
   1.116 +            target = objtable.get_object(target_name)
   1.117 +            try:
   1.118 +                attr = objtable.access(target_name, attrname)
   1.119 +            except TableError:
   1.120 +                continue
   1.121 +            if attr.is_static_attribute():
   1.122 +                for v in attr.get_values():
   1.123 +                    attributes.append((v, target, target_name))
   1.124 +            else:
   1.125 +                attributes.append((None, target, target_name))
   1.126 +
   1.127 +        return attributes
   1.128 +
   1.129  # Summary classes.
   1.130  
   1.131  class Summary(Writer):
   1.132 @@ -510,8 +574,6 @@
   1.133          self.visitor = self
   1.134          self.module = module
   1.135          self.program = program
   1.136 -        self.objtable = self.program.get_object_table()
   1.137 -        self.paramtable = self.program.get_parameter_table()
   1.138  
   1.139      def to_stream(self, stream):
   1.140  
   1.141 @@ -918,16 +980,19 @@
   1.142          self._span_end()
   1.143  
   1.144      def visitAssAttr(self, node):
   1.145 +        possible_types = self.possible_accessor_types(node, defining_users=0)
   1.146          target_names = ["%s%s" % (is_static and "static " or "", target_name)
   1.147 -            for target_name, is_static in self.possible_accessor_types(node, defining_users=0)]
   1.148 +            for target_name, is_static in possible_types]
   1.149 +        attributes = self._get_attributes(possible_types, node.attrname)
   1.150 +
   1.151          self._span_start("assattr")
   1.152          self._accessor_start(target_names)
   1.153          self.dispatch(node.expr)
   1.154          self._accessor_end(target_names)
   1.155 -        self._span_start("attr")
   1.156          self.stream.write(".")
   1.157 +        self._attribute_start(node.attrname, attributes)
   1.158          self._span(node.attrname, "attrname" + (not target_names and " no-targets" or ""))
   1.159 -        self._span_end()
   1.160 +        self._attribute_end(attributes)
   1.161          self._span_end()
   1.162  
   1.163      def visitAssList(self, node):
   1.164 @@ -1010,16 +1075,19 @@
   1.165          self._visitBinary(node, "floordiv", "//")
   1.166  
   1.167      def visitGetattr(self, node):
   1.168 +        possible_types = self.possible_accessor_types(node, defining_users=0)
   1.169          target_names = ["%s%s" % (is_static and "static " or "", target_name)
   1.170 -            for target_name, is_static in self.possible_accessor_types(node, defining_users=0)]
   1.171 +            for target_name, is_static in possible_types]
   1.172 +        attributes = self._get_attributes(possible_types, node.attrname)
   1.173 +
   1.174          self._span_start("getattr")
   1.175          self._accessor_start(target_names)
   1.176          self.dispatch(node.expr)
   1.177          self._accessor_end(target_names)
   1.178 -        self._span_start("attr")
   1.179          self.stream.write(".")
   1.180 +        self._attribute_start(node.attrname, attributes)
   1.181          self._span(node.attrname, "attrname" + (not target_names and " no-targets" or ""))
   1.182 -        self._span_end()
   1.183 +        self._attribute_end(attributes)
   1.184          self._span_end()
   1.185  
   1.186      def visitGenExpr(self, node):