starscope 1.5.3 → 1.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,138 +2,140 @@ require 'rkelly'
2
2
  require 'babel/transpiler'
3
3
  require 'sourcemap'
4
4
 
5
- module Starscope::Lang
6
- module Javascript
7
- VERSION = 1
5
+ module Starscope
6
+ module Lang
7
+ module Javascript
8
+ VERSION = 1
8
9
 
9
- def self.match_file(name)
10
- name.end_with?('.js')
11
- end
10
+ def self.match_file(name)
11
+ name.end_with?('.js')
12
+ end
12
13
 
13
- def self.extract(path, contents, &block)
14
- return if path.end_with?('.min.js')
14
+ def self.extract(path, contents, &block)
15
+ return if path.end_with?('.min.js')
15
16
 
16
- transform = Babel::Transpiler.transform(contents,
17
- 'stage' => 0,
18
- 'blacklist' => ['validation.react'],
19
- 'externalHelpers' => true,
20
- 'compact' => false,
21
- 'sourceMaps' => true)
22
- map = SourceMap::Map.from_hash(transform['map'])
23
- ast = RKelly::Parser.new.parse(transform['code'])
24
- lines = contents.lines.to_a
17
+ transform = Babel::Transpiler.transform(contents,
18
+ 'stage' => 0,
19
+ 'blacklist' => ['validation.react'],
20
+ 'externalHelpers' => true,
21
+ 'compact' => false,
22
+ 'sourceMaps' => true)
23
+ map = SourceMap::Map.from_hash(transform['map'])
24
+ ast = RKelly::Parser.new.parse(transform['code'])
25
+ lines = contents.lines.to_a
25
26
 
26
- return unless ast
27
+ return unless ast
27
28
 
28
- found = extract_methods(ast, map, lines, &block)
29
+ found = extract_methods(ast, map, lines, &block)
29
30
 
30
- found = extract_var_decls(ast, map, lines, found, &block)
31
+ found = extract_var_decls(ast, map, lines, found, &block)
31
32
 
32
- extract_var_reads(ast, map, lines, found, &block)
33
- end
33
+ extract_var_reads(ast, map, lines, found, &block)
34
+ end
34
35
 
35
- def self.extract_methods(ast, map, lines, &block)
36
- found = {}
36
+ def self.extract_methods(ast, map, lines)
37
+ found = {}
37
38
 
38
- ast.each do |node|
39
- case node
40
- when RKelly::Nodes::FunctionExprNode, RKelly::Nodes::FunctionDeclNode
41
- line = find_line(node.range.from, map, lines, node.value)
42
- next unless line
39
+ ast.each do |node|
40
+ case node
41
+ when RKelly::Nodes::FunctionExprNode, RKelly::Nodes::FunctionDeclNode
42
+ line = find_line(node.range.from, map, lines, node.value)
43
+ next unless line
43
44
 
44
- type = :func
45
- type = :class if lines[line - 1].include?("class #{node.value}")
45
+ type = :func
46
+ type = :class if lines[line - 1].include?("class #{node.value}")
46
47
 
47
- yield :defs, node.value, line_no: line, type: type
48
- found[node.value] ||= Set.new
49
- found[node.value].add(line)
48
+ yield :defs, node.value, line_no: line, type: type
49
+ found[node.value] ||= Set.new
50
+ found[node.value].add(line)
50
51
 
51
- next if type == :class
52
+ next if type == :class
52
53
 
53
- mapping = map.bsearch(SourceMap::Offset.new(node.range.to.line, node.range.to.char))
54
- if lines[mapping.original.line - 1].include? '}'
55
- yield :end, '}', line_no: mapping.original.line, type: type
56
- else
57
- yield :end, '', line_no: mapping.original.line, type: type, col: mapping.original.column
58
- end
59
- when RKelly::Nodes::FunctionCallNode
60
- name = node_name(node.value)
61
- next unless name
54
+ mapping = map.bsearch(SourceMap::Offset.new(node.range.to.line, node.range.to.char))
55
+ if lines[mapping.original.line - 1].include? '}'
56
+ yield :end, '}', line_no: mapping.original.line, type: type
57
+ else
58
+ yield :end, '', line_no: mapping.original.line, type: type, col: mapping.original.column
59
+ end
60
+ when RKelly::Nodes::FunctionCallNode
61
+ name = node_name(node.value)
62
+ next unless name
62
63
 
63
- node = node.arguments.value[0] if name == 'require' && !node.value.is_a?(RKelly::Nodes::DotAccessorNode)
64
+ node = node.arguments.value[0] if name == 'require' && !node.value.is_a?(RKelly::Nodes::DotAccessorNode)
64
65
 
65
- line = find_line(node.range.from, map, lines, name)
66
- next unless line
66
+ line = find_line(node.range.from, map, lines, name)
67
+ next unless line
67
68
 
68
- found[name] ||= Set.new
69
- found[name].add(line)
69
+ found[name] ||= Set.new
70
+ found[name].add(line)
70
71
 
71
- if name == 'require' && node.is_a?(RKelly::Nodes::StringNode)
72
- yield :requires, node.value[1...-1], line_no: line
73
- else
74
- yield :calls, name, line_no: line
72
+ if name == 'require' && node.is_a?(RKelly::Nodes::StringNode)
73
+ yield :requires, node.value[1...-1], line_no: line
74
+ else
75
+ yield :calls, name, line_no: line
76
+ end
75
77
  end
76
78
  end
79
+
80
+ found
77
81
  end
78
82
 
79
- found
80
- end
83
+ def self.extract_var_decls(ast, map, lines, found)
84
+ ast.each do |node|
85
+ next unless node.is_a? RKelly::Nodes::VarDeclNode
81
86
 
82
- def self.extract_var_decls(ast, map, lines, found, &block)
83
- ast.each do |node|
84
- next unless node.is_a? RKelly::Nodes::VarDeclNode
87
+ line = find_line(node.range.from, map, lines, node.name)
88
+ next unless line
85
89
 
86
- line = find_line(node.range.from, map, lines, node.name)
87
- next unless line
90
+ if node.value.is_a?(RKelly::Nodes::AssignExprNode) &&
91
+ node.value.value.is_a?(RKelly::Nodes::FunctionCallNode) &&
92
+ node.value.value.value.is_a?(RKelly::Nodes::ResolveNode) &&
93
+ node.value.value.value.value == 'require'
94
+ found[node.name] ||= Set.new
95
+ found[node.name].add(line)
96
+ next
97
+ end
88
98
 
89
- if node.value.is_a?(RKelly::Nodes::AssignExprNode) &&
90
- node.value.value.is_a?(RKelly::Nodes::FunctionCallNode) &&
91
- node.value.value.value.is_a?(RKelly::Nodes::ResolveNode) &&
92
- node.value.value.value.value == 'require'
99
+ next if found[node.name] && found[node.name].include?(line)
100
+ yield :defs, node.name, line_no: line
93
101
  found[node.name] ||= Set.new
94
102
  found[node.name].add(line)
95
- next
96
103
  end
97
104
 
98
- next if found[node.name] && found[node.name].include?(line)
99
- yield :defs, node.name, line_no: line
100
- found[node.name] ||= Set.new
101
- found[node.name].add(line)
105
+ found
102
106
  end
103
107
 
104
- found
105
- end
106
-
107
- def self.extract_var_reads(ast, map, lines, found, &block)
108
- ast.each do |node|
109
- name = node_name(node)
110
- next unless name
108
+ def self.extract_var_reads(ast, map, lines, found)
109
+ ast.each do |node|
110
+ name = node_name(node)
111
+ next unless name
111
112
 
112
- line = find_line(node.range.from, map, lines, name)
113
- next unless line
113
+ line = find_line(node.range.from, map, lines, name)
114
+ next unless line
114
115
 
115
- next if found[name] && found[name].include?(line)
116
- yield :reads, name, line_no: line
116
+ next if found[name] && found[name].include?(line)
117
+ yield :reads, name, line_no: line
118
+ end
117
119
  end
118
- end
119
120
 
120
- def self.node_name(node)
121
- case node
122
- when RKelly::Nodes::DotAccessorNode
123
- node.accessor
124
- when RKelly::Nodes::ResolveNode
125
- node.value
121
+ def self.node_name(node)
122
+ case node
123
+ when RKelly::Nodes::DotAccessorNode
124
+ node.accessor
125
+ when RKelly::Nodes::ResolveNode
126
+ node.value
127
+ end
126
128
  end
127
- end
128
129
 
129
- def self.find_line(from, map, lines, name)
130
- mapping = map.bsearch(SourceMap::Offset.new(from.line, from.char))
131
- return unless mapping
130
+ def self.find_line(from, map, lines, name)
131
+ mapping = map.bsearch(SourceMap::Offset.new(from.line, from.char))
132
+ return unless mapping
132
133
 
133
- line = lines[mapping.original.line - 1]
134
- return unless line.include?(name) || (name == 'require' && line.include?('import'))
134
+ line = lines[mapping.original.line - 1]
135
+ return unless line.include?(name) || (name == 'require' && line.include?('import'))
135
136
 
136
- mapping.original.line
137
+ mapping.original.line
138
+ end
137
139
  end
138
140
  end
139
141
  end
@@ -1,111 +1,129 @@
1
1
  require 'parser/current'
2
2
 
3
- module Starscope::Lang
4
- module Ruby
5
- VERSION = 2
6
-
7
- def self.match_file(name)
8
- return true if name.end_with?('.rb', '.rake')
9
- File.open(name) do |f|
10
- head = f.read(2)
11
- return false if head.nil? || !head.start_with?('#!')
12
- return f.readline.include?('ruby')
3
+ module Starscope
4
+ module Lang
5
+ module Ruby
6
+ # This class exists solely to workaround/suppress issues from upstream's handling of invalid unicode.
7
+ # See https://github.com/whitequark/parser/issues/283; workaround borrowed from
8
+ # https://github.com/bbatsov/rubocop/commit/5e820eb5cfddf5e0f7efd2c0fa99e6b8a4c7b7e0
9
+ class Builder < Parser::Builders::Default
10
+ def string_value(token)
11
+ value(token)
12
+ end
13
13
  end
14
- end
15
-
16
- def self.extract(path, contents, &block)
17
- ast = Parser::CurrentRuby.parse(contents)
18
- extract_tree(ast, [], &block) unless ast.nil?
19
- end
20
14
 
21
- def self.extract_tree(tree, scope, &block)
22
- extract_node(tree, scope, &block)
15
+ VERSION = 2
23
16
 
24
- new_scope = []
25
- if [:class, :module].include? tree.type
26
- new_scope = scoped_name(tree.children[0], scope)
27
- scope += new_scope
17
+ def self.match_file(name)
18
+ return true if name.end_with?('.rb', '.rake')
19
+ File.open(name) do |f|
20
+ head = f.read(2)
21
+ return false if head.nil? || !head.start_with?('#!')
22
+ return f.readline.include?('ruby')
23
+ end
28
24
  end
29
25
 
30
- tree.children.each { |node| extract_tree(node, scope, &block) if node.is_a? AST::Node }
26
+ def self.extract(path, contents, &block)
27
+ buffer = Parser::Source::Buffer.new(path, 1)
28
+ buffer.source = contents.force_encoding(Encoding::UTF_8)
31
29
 
32
- scope.pop(new_scope.count)
33
- end
30
+ parser = Parser::CurrentRuby.new(Builder.new)
31
+ parser.diagnostics.ignore_warnings = true
32
+ parser.diagnostics.all_errors_are_fatal = false
34
33
 
35
- def self.extract_node(node, scope)
36
- loc = node.location
34
+ ast = parser.parse(buffer)
35
+ extract_tree(ast, [], &block) unless ast.nil?
36
+ end
37
37
 
38
- case node.type
39
- when :send
40
- name = scoped_name(node, scope)
41
- yield :calls, name, line_no: loc.line, col: loc.column
38
+ def self.extract_tree(tree, scope, &block)
39
+ extract_node(tree, scope, &block)
42
40
 
43
- if name.last =~ /\w+=$/
44
- name[-1] = name.last.to_s.chop.to_sym
45
- yield :assigns, name, line_no: loc.line, col: loc.column
46
- elsif node.children[0].nil? && node.children[1] == :require && node.children[2].type == :str
47
- yield :requires, node.children[2].children[0].split('/'),
48
- line_no: loc.line, col: loc.column
41
+ new_scope = []
42
+ if [:class, :module].include? tree.type
43
+ new_scope = scoped_name(tree.children[0], scope)
44
+ scope += new_scope
49
45
  end
50
46
 
51
- when :def
52
- yield :defs, scope + [node.children[0]],
53
- line_no: loc.line, type: :func, col: loc.name.column
54
- yield :end, :end, line_no: loc.end.line, type: :func, col: loc.end.column
55
-
56
- when :defs
57
- yield :defs, scope + [node.children[1]],
58
- line_no: loc.line, type: :func, col: loc.name.column
59
- yield :end, :end, line_no: loc.end.line, type: :func, col: loc.end.column
60
-
61
- when :module, :class
62
- yield :defs, scope + scoped_name(node.children[0], scope),
63
- line_no: loc.line, type: node.type, col: loc.name.column
64
- yield :end, :end, line_no: loc.end.line, type: node.type, col: loc.end.column
65
-
66
- when :casgn
67
- name = scoped_name(node, scope)
68
- yield :assigns, name, line_no: loc.line, col: loc.name.column
69
- yield :defs, name, line_no: loc.line, col: loc.name.column
70
-
71
- when :lvasgn, :ivasgn, :cvasgn, :gvasgn
72
- yield :assigns, scope + [node.children[0]], line_no: loc.line, col: loc.name.column
73
-
74
- when :const
75
- name = scoped_name(node, scope)
76
- yield :reads, name, line_no: loc.line, col: loc.name.column
77
-
78
- when :lvar, :ivar, :cvar, :gvar
79
- yield :reads, scope + [node.children[0]], line_no: loc.line, col: loc.name.column
80
-
81
- when :sym
82
- # handle `:foo` vs `foo: 1`
83
- col = if loc.begin
84
- loc.begin.column + 1
85
- else
86
- loc.expression.column
87
- end
88
- yield :sym, [node.children[0]], line_no: loc.line, col: col
47
+ tree.children.each { |node| extract_tree(node, scope, &block) if node.is_a? AST::Node }
48
+
49
+ scope.pop(new_scope.count)
50
+ end
51
+
52
+ def self.extract_node(node, scope)
53
+ loc = node.location
54
+
55
+ case node.type
56
+ when :send
57
+ name = scoped_name(node, scope)
58
+ yield :calls, name, line_no: loc.line, col: loc.column
59
+
60
+ if name.last =~ /\w+=$/
61
+ name[-1] = name.last.to_s.chop.to_sym
62
+ yield :assigns, name, line_no: loc.line, col: loc.column
63
+ elsif node.children[0].nil? && node.children[1] == :require && node.children[2].type == :str
64
+ yield :requires, node.children[2].children[0].split('/'),
65
+ line_no: loc.line, col: loc.column
66
+ end
67
+
68
+ when :def
69
+ yield :defs, scope + [node.children[0]],
70
+ line_no: loc.line, type: :func, col: loc.name.column
71
+ yield :end, :end, line_no: loc.end.line, type: :func, col: loc.end.column
72
+
73
+ when :defs
74
+ yield :defs, scope + [node.children[1]],
75
+ line_no: loc.line, type: :func, col: loc.name.column
76
+ yield :end, :end, line_no: loc.end.line, type: :func, col: loc.end.column
77
+
78
+ when :module, :class
79
+ yield :defs, scope + scoped_name(node.children[0], scope),
80
+ line_no: loc.line, type: node.type, col: loc.name.column
81
+ yield :end, :end, line_no: loc.end.line, type: node.type, col: loc.end.column
82
+
83
+ when :casgn
84
+ name = scoped_name(node, scope)
85
+ yield :assigns, name, line_no: loc.line, col: loc.name.column
86
+ yield :defs, name, line_no: loc.line, col: loc.name.column
87
+
88
+ when :lvasgn, :ivasgn, :cvasgn, :gvasgn
89
+ yield :assigns, scope + [node.children[0]], line_no: loc.line, col: loc.name.column
90
+
91
+ when :const
92
+ name = scoped_name(node, scope)
93
+ yield :reads, name, line_no: loc.line, col: loc.name.column
94
+
95
+ when :lvar, :ivar, :cvar, :gvar
96
+ yield :reads, scope + [node.children[0]], line_no: loc.line, col: loc.name.column
97
+
98
+ when :sym
99
+ # handle `:foo` vs `foo: 1`
100
+ col = if loc.begin
101
+ loc.begin.column + 1
102
+ else
103
+ loc.expression.column
104
+ end
105
+ yield :sym, [node.children[0]], line_no: loc.line, col: col
106
+ end
89
107
  end
90
- end
91
108
 
92
- def self.scoped_name(node, scope)
93
- if node.type == :block
94
- scoped_name(node.children[0], scope)
95
- elsif [:lvar, :ivar, :cvar, :gvar, :const, :send, :casgn].include? node.type
96
- if node.children[0].is_a? Symbol
97
- [node.children[0]]
98
- elsif node.children[0].is_a? AST::Node
99
- scoped_name(node.children[0], scope) << node.children[1]
100
- elsif node.children[0].nil?
101
- if node.type == :const
102
- [node.children[1]]
103
- else
104
- scope + [node.children[1]]
109
+ def self.scoped_name(node, scope)
110
+ if node.type == :block
111
+ scoped_name(node.children[0], scope)
112
+ elsif [:lvar, :ivar, :cvar, :gvar, :const, :send, :casgn].include? node.type
113
+ if node.children[0].is_a? Symbol
114
+ [node.children[0]]
115
+ elsif node.children[0].is_a? AST::Node
116
+ scoped_name(node.children[0], scope) << node.children[1]
117
+ elsif node.children[0].nil?
118
+ if node.type == :const
119
+ [node.children[1]]
120
+ else
121
+ scope + [node.children[1]]
122
+ end
105
123
  end
124
+ else
125
+ [node.type]
106
126
  end
107
- else
108
- [node.type]
109
127
  end
110
128
  end
111
129
  end