1
Jianw
9 天以前 70f29da38121b9a467841253e3268feb5df02902
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
local stage = {}
 
local function get_index_name(base_name, key_node)
   if key_node.tag == "String" then
      return base_name .. "." .. key_node[1]
   end
end
 
local function get_full_field_name(node)
   if node.tag == "Id" then
      return node[1]
   elseif node.tag == "Index" then
      local base_name = get_full_field_name(node[1])
      return base_name and get_index_name(base_name, node[2])
   end
end
 
local handle_node
 
local function handle_nodes(nodes)
   for _, node in ipairs(nodes) do
      if type(node) == "table" then
         handle_node(node)
      end
   end
end
 
function handle_node(node, name)
   if node.tag == "Function" then
      node.name = name
      handle_nodes(node[2])
   elseif node.tag == "Set" or node.tag == "Local" or node.tag == "Localrec" then
      local lhs = node[1]
      local rhs = node[2]
 
      -- No need to handle LHS if there is no RHS, it's always just a list of locals in that case.
      if rhs then
         handle_nodes(lhs)
 
         for index, rhs_node in ipairs(rhs) do
            local lhs_node = lhs[index]
            local field_name = lhs_node and get_full_field_name(lhs_node)
            handle_node(rhs_node, field_name)
         end
      end
   elseif node.tag == "Table" and name then
      for _, pair_node in ipairs(node) do
         if pair_node.tag == "Pair" then
            local key_node = pair_node[1]
            local value_node = pair_node[2]
            handle_node(key_node)
            handle_node(value_node, get_index_name(name, key_node))
         else
            handle_node(pair_node)
         end
      end
   else
      handle_nodes(node)
   end
end
 
-- Adds `name` field to `Function` ast nodes when possible:
-- * Function assigned to a variable (doesn't matter if local or global): "foo".
-- * Function assigned to a field: "foo.bar.baz".
--   Function can be in a table assigned to a variable or a field, e.g. `foo.bar = {baz = function() ... end}`.
-- * Otherwise: `nil`.
function stage.run(chstate)
   handle_nodes(chstate.ast)
end
 
return stage