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
5import itertools
6import symbol
7import token
8
9from py_utils.refactor.annotated_symbol import base_symbol
10from py_utils.refactor import snippet
11
12
13__all__ = [
14    'Reference',
15]
16
17
18class 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