starscope 1.5.3 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,22 +1,24 @@
1
- class Starscope::FragmentExtractor
2
- def initialize(lang, frags)
3
- @child = Starscope::Lang.const_get(lang)
4
- @frags = frags
5
- end
1
+ module Starscope
2
+ class FragmentExtractor
3
+ def initialize(lang, frags)
4
+ @child = Starscope::Lang.const_get(lang)
5
+ @frags = frags
6
+ end
6
7
 
7
- def extract(path, text)
8
- text = @frags.map { |f| f.delete(:frag).strip }.join("\n")
8
+ def extract(path, text)
9
+ text = @frags.map { |f| f.delete(:frag).strip }.join("\n")
9
10
 
10
- extractor_metadata = @child.extract(path, text) do |tbl, name, args|
11
- args.merge!(@frags[args[:line_no] - 1]) if args[:line_no]
12
- yield tbl, name, args
13
- end
11
+ extractor_metadata = @child.extract(path, text) do |tbl, name, args|
12
+ args.merge!(@frags[args[:line_no] - 1]) if args[:line_no]
13
+ yield tbl, name, args
14
+ end
14
15
 
15
- # TODO: translate metadata?
16
- extractor_metadata
17
- end
16
+ # TODO: translate metadata?
17
+ extractor_metadata
18
+ end
18
19
 
19
- def name
20
- @child.name
20
+ def name
21
+ @child.name
22
+ end
21
23
  end
22
24
  end
@@ -1,44 +1,46 @@
1
- module Starscope::Lang
2
- module ERB
3
- VERSION = 1
1
+ module Starscope
2
+ module Lang
3
+ module ERB
4
+ VERSION = 1
4
5
 
5
- ERB_START = /<%(?:-|={1,4})?/
6
- ERB_END = /-?%>/
6
+ ERB_START = /<%(?:-|={1,4})?/
7
+ ERB_END = /-?%>/
7
8
 
8
- def self.match_file(name)
9
- name.end_with?('.erb')
10
- end
11
-
12
- def self.extract(path, contents, &block)
13
- multiline = false # true when parsing a multiline <% ... %> block
14
-
15
- contents.lines.each_with_index do |line, line_no|
16
- line_no += 1 # zero-index to one-index
9
+ def self.match_file(name)
10
+ name.end_with?('.erb')
11
+ end
17
12
 
18
- if multiline
19
- term = line.index(ERB_END)
20
- if term
21
- yield Starscope::DB::FRAGMENT, :Ruby, frag: line[0...term], line_no: line_no
22
- line = line[term + 1..-1]
23
- multiline = false
24
- else
25
- yield Starscope::DB::FRAGMENT, :Ruby, frag: line, line_no: line_no
13
+ def self.extract(_path, contents)
14
+ multiline = false # true when parsing a multiline <% ... %> block
15
+
16
+ contents.lines.each_with_index do |line, line_no|
17
+ line_no += 1 # zero-index to one-index
18
+
19
+ if multiline
20
+ term = line.index(ERB_END)
21
+ if term
22
+ yield Starscope::DB::FRAGMENT, :Ruby, frag: line[0...term], line_no: line_no
23
+ line = line[term + 1..-1]
24
+ multiline = false
25
+ else
26
+ yield Starscope::DB::FRAGMENT, :Ruby, frag: line, line_no: line_no
27
+ end
26
28
  end
27
- end
28
29
 
29
- next if multiline
30
+ next if multiline
30
31
 
31
- line.scan(/#{ERB_START}(.*?)#{ERB_END}/) do |match|
32
- yield Starscope::DB::FRAGMENT, :Ruby, frag: match[0], line_no: line_no
33
- end
32
+ line.scan(/#{ERB_START}(.*?)#{ERB_END}/) do |match|
33
+ yield Starscope::DB::FRAGMENT, :Ruby, frag: match[0], line_no: line_no
34
+ end
34
35
 
35
- line.gsub!(/<%.*?%>/, '')
36
+ line.gsub!(/<%.*?%>/, '')
36
37
 
37
- match = /#{ERB_START}(.*)$/.match(line)
38
- next unless match
38
+ match = /#{ERB_START}(.*)$/.match(line)
39
+ next unless match
39
40
 
40
- yield Starscope::DB::FRAGMENT, :Ruby, frag: match[1], line_no: line_no
41
- multiline = true
41
+ yield Starscope::DB::FRAGMENT, :Ruby, frag: match[1], line_no: line_no
42
+ multiline = true
43
+ end
42
44
  end
43
45
  end
44
46
  end
@@ -1,206 +1,208 @@
1
- module Starscope::Lang
2
- module Golang
3
- VERSION = 1
1
+ module Starscope
2
+ module Lang
3
+ module Golang
4
+ VERSION = 1
4
5
 
5
- FUNC_CALL = /([\w\.]*?\w)\(/
6
- END_OF_BLOCK = /^\s*\}\s*$/
7
- END_OF_GROUP = /^\s*\)\s*$/
8
- STRING_LITERAL = /".+?"/
9
- BUILTIN_FUNCS = %w(new make len close copy delete int int8 int16 int32 int64
10
- uint uint8 uint16 uint32 uint64 string byte).freeze
11
- CONTROL_KEYS = %w(if for switch case).freeze
6
+ FUNC_CALL = /([\w\.]*?\w)\(/
7
+ END_OF_BLOCK = /^\s*\}\s*$/
8
+ END_OF_GROUP = /^\s*\)\s*$/
9
+ STRING_LITERAL = /".+?"/
10
+ BUILTIN_FUNCS = %w(new make len close copy delete int int8 int16 int32 int64
11
+ uint uint8 uint16 uint32 uint64 string byte).freeze
12
+ CONTROL_KEYS = %w(if for switch case).freeze
12
13
 
13
- def self.match_file(name)
14
- name.end_with?('.go')
15
- end
16
-
17
- def self.extract(path, contents, &block)
18
- stack = []
19
- scope = []
20
- contents.lines.each_with_index do |line, line_no|
21
- line_no += 1 # zero-index to one-index
22
-
23
- # strip single-line comments like // foo
24
- match = %r{//}.match(line)
25
- line = match.pre_match if match
26
- # strip single-line comments like foo /* foo */ foo
27
- match = %r{/\*.*\*/}.match(line)
28
- line = match.pre_match + match.post_match if match
29
- # strip end-of-line comment starters like foo /* foo \n
30
- match = %r{/\*}.match(line)
31
- line = match.pre_match if match
32
- ends_with_comment = !match.nil?
14
+ def self.match_file(name)
15
+ name.end_with?('.go')
16
+ end
33
17
 
34
- # if we're in a block comment, wait for it to end
35
- if stack[-1] == :comment
36
- match = %r{\*/(.*)}.match(line)
37
- next unless match
38
- line = match[1]
39
- stack.pop
40
- end
18
+ def self.extract(_path, contents, &block)
19
+ stack = []
20
+ scope = []
21
+ contents.lines.each_with_index do |line, line_no|
22
+ line_no += 1 # zero-index to one-index
41
23
 
42
- if stack[-1] != :import && !line.start_with?('import')
43
- # strip string literals like "foo" unless they're part of an import
44
- pos = 0
45
- while (match = STRING_LITERAL.match(line, pos))
46
- eos = find_end_of_string(line, match.begin(0))
47
- line = line[0..match.begin(0)] + line[eos..-1]
48
- pos = match.begin(0) + 2
49
- end
50
- end
24
+ # strip single-line comments like // foo
25
+ match = %r{//}.match(line)
26
+ line = match.pre_match if match
27
+ # strip single-line comments like foo /* foo */ foo
28
+ match = %r{/\*.*\*/}.match(line)
29
+ line = match.pre_match + match.post_match if match
30
+ # strip end-of-line comment starters like foo /* foo \n
31
+ match = %r{/\*}.match(line)
32
+ line = match.pre_match if match
33
+ ends_with_comment = !match.nil?
51
34
 
52
- # poor-man's parser
53
- case stack[-1]
54
- when :struct
55
- case line
56
- when END_OF_BLOCK
57
- end_block(line_no, scope, stack, &block)
58
- when /(.+)\s+\w+/
59
- parse_def(Regexp.last_match(1), line_no, scope, &block)
60
- end
61
- when :interface
62
- case line
63
- when END_OF_BLOCK
64
- end_block(line_no, scope, stack, &block)
65
- when /(\w+)\(.*\)\s+/
66
- yield :defs, scope + [Regexp.last_match(1)], line_no: line_no
67
- end
68
- when :def
69
- case line
70
- when END_OF_GROUP
35
+ # if we're in a block comment, wait for it to end
36
+ if stack[-1] == :comment
37
+ match = %r{\*/(.*)}.match(line)
38
+ next unless match
39
+ line = match[1]
71
40
  stack.pop
72
- when /(.+)\s*=.*/
73
- parse_def(Regexp.last_match(1), line_no, scope, &block)
74
- parse_call(line, line_no, scope, &block)
75
- else
76
- parse_def(line, line_no, scope, &block)
77
41
  end
78
- when :import
79
- case line
80
- when END_OF_GROUP
81
- stack.pop
82
- when /"(.+)"/
83
- name = Regexp.last_match(1).split('/')
84
- yield :imports, name, line_no: line_no
42
+
43
+ if stack[-1] != :import && !line.start_with?('import')
44
+ # strip string literals like "foo" unless they're part of an import
45
+ pos = 0
46
+ while (match = STRING_LITERAL.match(line, pos))
47
+ eos = find_end_of_string(line, match.begin(0))
48
+ line = line[0..match.begin(0)] + line[eos..-1]
49
+ pos = match.begin(0) + 2
50
+ end
85
51
  end
86
- when :func
87
- case line
88
- when /^\}/
89
- yield :end, '}', line_no: line_no, type: :func
90
- stack.pop
52
+
53
+ # poor-man's parser
54
+ case stack[-1]
55
+ when :struct
56
+ case line
57
+ when END_OF_BLOCK
58
+ end_block(line_no, scope, stack, &block)
59
+ when /(.+)\s+\w+/
60
+ parse_def(Regexp.last_match(1), line_no, scope, &block)
61
+ end
62
+ when :interface
63
+ case line
64
+ when END_OF_BLOCK
65
+ end_block(line_no, scope, stack, &block)
66
+ when /(\w+)\(.*\)\s+/
67
+ yield :defs, scope + [Regexp.last_match(1)], line_no: line_no
68
+ end
69
+ when :def
70
+ case line
71
+ when END_OF_GROUP
72
+ stack.pop
73
+ when /(.+)\s*=.*/
74
+ parse_def(Regexp.last_match(1), line_no, scope, &block)
75
+ parse_call(line, line_no, scope, &block)
76
+ else
77
+ parse_def(line, line_no, scope, &block)
78
+ end
79
+ when :import
80
+ case line
81
+ when END_OF_GROUP
82
+ stack.pop
83
+ when /"(.+)"/
84
+ name = Regexp.last_match(1).split('/')
85
+ yield :imports, name, line_no: line_no
86
+ end
87
+ when :func
88
+ case line
89
+ when /^\}/
90
+ yield :end, '}', line_no: line_no, type: :func
91
+ stack.pop
92
+ else
93
+ parse_new_line(line, line_no, scope, stack, &block)
94
+ end
91
95
  else
92
96
  parse_new_line(line, line_no, scope, stack, &block)
93
97
  end
94
- else
95
- parse_new_line(line, line_no, scope, stack, &block)
96
- end
97
98
 
98
- # if the line looks like "foo /* foo" then we enter the comment state
99
- # after parsing the usable part of the line
100
- stack.push(:comment) if ends_with_comment
99
+ # if the line looks like "foo /* foo" then we enter the comment state
100
+ # after parsing the usable part of the line
101
+ stack.push(:comment) if ends_with_comment
102
+ end
101
103
  end
102
- end
103
104
 
104
- # handles new lines (when not in the middle of an existing definition)
105
- def self.parse_new_line(line, line_no, scope, stack, &block)
106
- case line
107
- when /^func\s+(\w+)\(/
108
- yield :defs, scope + [Regexp.last_match(1)], line_no: line_no, type: :func
109
- stack.push(:func)
110
- when /^func\s+\(\w+\s+\*?(\w+)\)\s*(\w+)\(/
111
- yield :defs, scope + [Regexp.last_match(1), Regexp.last_match(2)], line_no: line_no, type: :func
112
- stack.push(:func)
113
- when /^package\s+(\w+)/
114
- scope.push(Regexp.last_match(1))
115
- yield :defs, scope, line_no: line_no, type: :package
116
- when /^type\s+(\w+)\s+struct\s*\{/
117
- scope.push(Regexp.last_match(1))
118
- stack.push(:struct)
119
- yield :defs, scope, line_no: line_no, type: :class
120
- when /^type\s+(\w+)\s+interface\s*\{/
121
- scope.push(Regexp.last_match(1))
122
- stack.push(:interface)
123
- yield :defs, scope, line_no: line_no, type: :class
124
- when /^type\s+(\w+)/
125
- yield :defs, scope + [Regexp.last_match(1)], line_no: line_no, type: :type
126
- when /^import\s+"(.+)"/
127
- name = Regexp.last_match(1).split('/')
128
- yield :imports, name, line_no: line_no
129
- when /^import\s+\(/
130
- stack.push(:import)
131
- when /^var\s+\(/
132
- stack.push(:def)
133
- when /^var\s+(\w+)\s/
134
- yield :defs, scope + [Regexp.last_match(1)], line_no: line_no
135
- parse_call(line, line_no, scope, &block)
136
- when /^const\s+\(/
137
- stack.push(:def)
138
- when /^const\s+(\w+)\s/
139
- yield :defs, scope + [Regexp.last_match(1)], line_no: line_no
140
- parse_call(line, line_no, scope, &block)
141
- when /^\s+(.*?) :?=[^=]/
142
- Regexp.last_match(1).split(' ').each do |var|
143
- next if CONTROL_KEYS.include?(var)
144
- name = var.delete(',').split('.')
145
- next if name[0] == '_' # assigning to _ is a discard in golang
146
- if name.length == 1
147
- yield :assigns, scope + [name[0]], line_no: line_no
148
- else
149
- yield :assigns, name, line_no: line_no
105
+ # handles new lines (when not in the middle of an existing definition)
106
+ def self.parse_new_line(line, line_no, scope, stack, &block)
107
+ case line
108
+ when /^func\s+(\w+)\(/
109
+ yield :defs, scope + [Regexp.last_match(1)], line_no: line_no, type: :func
110
+ stack.push(:func)
111
+ when /^func\s+\(\w+\s+\*?(\w+)\)\s*(\w+)\(/
112
+ yield :defs, scope + [Regexp.last_match(1), Regexp.last_match(2)], line_no: line_no, type: :func
113
+ stack.push(:func)
114
+ when /^package\s+(\w+)/
115
+ scope.push(Regexp.last_match(1))
116
+ yield :defs, scope, line_no: line_no, type: :package
117
+ when /^type\s+(\w+)\s+struct\s*\{/
118
+ scope.push(Regexp.last_match(1))
119
+ stack.push(:struct)
120
+ yield :defs, scope, line_no: line_no, type: :class
121
+ when /^type\s+(\w+)\s+interface\s*\{/
122
+ scope.push(Regexp.last_match(1))
123
+ stack.push(:interface)
124
+ yield :defs, scope, line_no: line_no, type: :class
125
+ when /^type\s+(\w+)/
126
+ yield :defs, scope + [Regexp.last_match(1)], line_no: line_no, type: :type
127
+ when /^import\s+"(.+)"/
128
+ name = Regexp.last_match(1).split('/')
129
+ yield :imports, name, line_no: line_no
130
+ when /^import\s+\(/
131
+ stack.push(:import)
132
+ when /^var\s+\(/
133
+ stack.push(:def)
134
+ when /^var\s+(\w+)\s/
135
+ yield :defs, scope + [Regexp.last_match(1)], line_no: line_no
136
+ parse_call(line, line_no, scope, &block)
137
+ when /^const\s+\(/
138
+ stack.push(:def)
139
+ when /^const\s+(\w+)\s/
140
+ yield :defs, scope + [Regexp.last_match(1)], line_no: line_no
141
+ parse_call(line, line_no, scope, &block)
142
+ when /^\s+(.*?) :?=[^=]/
143
+ Regexp.last_match(1).split(' ').each do |var|
144
+ next if CONTROL_KEYS.include?(var)
145
+ name = var.delete(',').split('.')
146
+ next if name[0] == '_' # assigning to _ is a discard in golang
147
+ if name.length == 1
148
+ yield :assigns, scope + [name[0]], line_no: line_no
149
+ else
150
+ yield :assigns, name, line_no: line_no
151
+ end
150
152
  end
153
+ parse_call(line, line_no, scope, &block)
154
+ else
155
+ parse_call(line, line_no, scope, &block)
151
156
  end
152
- parse_call(line, line_no, scope, &block)
153
- else
154
- parse_call(line, line_no, scope, &block)
155
157
  end
156
- end
157
158
 
158
- def self.parse_call(line, line_no, scope)
159
- line.scan(FUNC_CALL) do |match|
160
- name = match[0].split('.').select { |chunk| !chunk.empty? }
161
- if name.length == 1
162
- next if name[0] == 'func'
163
- if BUILTIN_FUNCS.include?(name[0])
164
- yield :calls, name[0], line_no: line_no
159
+ def self.parse_call(line, line_no, scope)
160
+ line.scan(FUNC_CALL) do |match|
161
+ name = match[0].split('.').select { |chunk| !chunk.empty? }
162
+ if name.length == 1
163
+ next if name[0] == 'func'
164
+ if BUILTIN_FUNCS.include?(name[0])
165
+ yield :calls, name[0], line_no: line_no
166
+ else
167
+ yield :calls, scope + [name[0]], line_no: line_no
168
+ end
165
169
  else
166
- yield :calls, scope + [name[0]], line_no: line_no
170
+ yield :calls, name, line_no: line_no
167
171
  end
168
- else
169
- yield :calls, name, line_no: line_no
170
172
  end
171
173
  end
172
- end
173
174
 
174
- def self.parse_def(line, line_no, scope)
175
- # if it doesn't start with a valid identifier character, it's probably
176
- # part of a multi-line literal and we should skip it
177
- return unless line =~ /^\s*[[:alpha:]_]/
175
+ def self.parse_def(line, line_no, scope)
176
+ # if it doesn't start with a valid identifier character, it's probably
177
+ # part of a multi-line literal and we should skip it
178
+ return unless line =~ /^\s*[[:alpha:]_]/
178
179
 
179
- line.split.each do |var|
180
- yield :defs, scope + [var.delete(',')], line_no: line_no
181
- break unless var.end_with?(',')
180
+ line.split.each do |var|
181
+ yield :defs, scope + [var.delete(',')], line_no: line_no
182
+ break unless var.end_with?(',')
183
+ end
182
184
  end
183
- end
184
185
 
185
- def self.end_block(line_no, scope, stack)
186
- yield :end, scope + ['}'], line_no: line_no, type: :class
187
- stack.pop
188
- scope.pop
189
- end
186
+ def self.end_block(line_no, scope, stack)
187
+ yield :end, scope + ['}'], line_no: line_no, type: :class
188
+ stack.pop
189
+ scope.pop
190
+ end
190
191
 
191
- def self.find_end_of_string(line, start)
192
- escape = false
193
- (start + 1...line.length).each do |i|
194
- if escape
195
- escape = false
196
- elsif line[i] == '\\'
197
- escape = true
198
- elsif line[i] == '"'
199
- return i
192
+ def self.find_end_of_string(line, start)
193
+ escape = false
194
+ (start + 1...line.length).each do |i|
195
+ if escape
196
+ escape = false
197
+ elsif line[i] == '\\'
198
+ escape = true
199
+ elsif line[i] == '"'
200
+ return i
201
+ end
200
202
  end
201
- end
202
203
 
203
- line.length
204
+ line.length
205
+ end
204
206
  end
205
207
  end
206
208
  end