1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# pylint: disable=wildcard-import
from py_utils.refactor.annotated_symbol.class_definition import *
from py_utils.refactor.annotated_symbol.function_definition import *
from py_utils.refactor.annotated_symbol.import_statement import *
from py_utils.refactor.annotated_symbol.reference import *
from py_utils.refactor import snippet
__all__ = [
'Annotate',
'Class',
'Function',
'Import',
'Reference',
]
# Specific symbol types with extra methods for manipulating them.
# Python's full grammar is here:
# https://docs.python.org/2/reference/grammar.html
# Annotated Symbols have an Annotate classmethod that takes a symbol type and
# list of children, and returns an instance of that annotated Symbol.
ANNOTATED_SYMBOLS = (
AsName,
Class,
DottedName,
ImportFrom,
ImportName,
Function,
)
# Unfortunately, some logical groupings are not represented by a node in the
# parse tree. To work around this, some annotated Symbols have an Annotate
# classmethod that takes and returns a list of Snippets instead.
ANNOTATED_GROUPINGS = (
Reference,
)
def Annotate(f):
"""Return the syntax tree of the given file."""
return _AnnotateNode(snippet.Snippetize(f))
def _AnnotateNode(node):
if not isinstance(node, snippet.Symbol):
return node
children = map(_AnnotateNode, node.children)
for symbol_type in ANNOTATED_GROUPINGS:
annotated_grouping = symbol_type.Annotate(children)
if annotated_grouping:
children = annotated_grouping
break
for symbol_type in ANNOTATED_SYMBOLS:
annotated_symbol = symbol_type.Annotate(node.type, children)
if annotated_symbol:
return annotated_symbol
return snippet.Symbol(node.type, children)
|