Home | History | Annotate | Download | only in annotated_symbol
      1 # Copyright 2015 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import itertools
      6 import symbol
      7 import token
      8 
      9 from py_utils.refactor.annotated_symbol import base_symbol
     10 from py_utils.refactor import snippet
     11 
     12 
     13 __all__ = [
     14     'Reference',
     15 ]
     16 
     17 
     18 class Reference(base_symbol.AnnotatedSymbol):
     19   @classmethod
     20   def Annotate(cls, nodes):
     21     if not nodes:
     22       return None
     23     if nodes[0].type != symbol.atom:
     24       return None
     25     if not nodes[0].children or nodes[0].children[0].type != token.NAME:
     26       return None
     27 
     28     for i in xrange(1, len(nodes)):
     29       if not nodes:
     30         break
     31       if nodes[i].type != symbol.trailer:
     32         break
     33       if len(nodes[i].children) != 2:
     34         break
     35       if (nodes[i].children[0].type != token.DOT or
     36           nodes[i].children[1].type != token.NAME):
     37         break
     38     else:
     39       i = len(nodes)
     40 
     41     return [cls(nodes[:i])] + nodes[i:]
     42 
     43   def __init__(self, children):
     44     super(Reference, self).__init__(-1, children)
     45 
     46   @property
     47   def type_name(self):
     48     return 'attribute_reference'
     49 
     50   @property
     51   def value(self):
     52     return ''.join(token_snippet.value
     53                    for child in self.children
     54                    for token_snippet in child.children)
     55 
     56   @value.setter
     57   def value(self, value):
     58     value_parts = value.split('.')
     59 
     60     # If we have too many children, cut the list down to size.
     61     self._children = self._children[:len(value_parts)]
     62 
     63     # Update child nodes.
     64     for child, value_part in itertools.izip_longest(
     65         self._children, value_parts):
     66       if child:
     67         # Modify existing children. This helps preserve comments and spaces.
     68         child.children[-1].value = value_part
     69       else:
     70         # Add children as needed.
     71         token_snippets = [
     72             snippet.TokenSnippet.Create(token.DOT, '.'),
     73             snippet.TokenSnippet.Create(token.NAME, value_part),
     74         ]
     75         self._children.append(snippet.Symbol(symbol.trailer, token_snippets))
     76