starscope 0.1.10 → 1.0.0
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.
- data/.travis.yml +1 -2
- data/CHANGELOG.md +27 -2
- data/Gemfile.lock +8 -8
- data/README.md +5 -8
- data/bin/starscope +98 -62
- data/lib/starscope/db.rb +176 -143
- data/lib/starscope/langs/coffeescript.rb +12 -0
- data/lib/starscope/langs/go.rb +25 -21
- data/lib/starscope/langs/lua.rb +12 -0
- data/lib/starscope/langs/ruby.rb +16 -24
- data/lib/starscope/matcher.rb +44 -0
- data/lib/starscope/output.rb +41 -0
- data/lib/starscope/record.rb +88 -0
- data/lib/starscope/version.rb +1 -1
- data/starscope.gemspec +1 -1
- data/test/files/sample_golang.go +19 -0
- data/test/lib/test_db.rb +80 -16
- data/test/lib/test_golang.rb +16 -13
- data/test/lib/test_matcher.rb +34 -0
- data/test/lib/test_record.rb +20 -0
- data/test/lib/test_ruby.rb +12 -12
- data/test/lib/test_starscope.rb +33 -0
- metadata +16 -8
- data/lib/starscope/datum.rb +0 -91
- data/test/lib/test_version.rb +0 -9
data/lib/starscope/langs/go.rb
CHANGED
@@ -10,7 +10,7 @@ module StarScope::Lang
|
|
10
10
|
CONTROL_KEYS = ['if', 'for', 'switch', 'case']
|
11
11
|
|
12
12
|
def self.match_file(name)
|
13
|
-
name
|
13
|
+
name.end_with?(".go")
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.extract(file, &block)
|
@@ -51,7 +51,7 @@ module StarScope::Lang
|
|
51
51
|
when :struct
|
52
52
|
case line
|
53
53
|
when END_OF_BLOCK
|
54
|
-
yield :end, "}", :line_no => line_no, :
|
54
|
+
yield :end, scope + ["}"], :line_no => line_no, :type => :class
|
55
55
|
stack.pop
|
56
56
|
scope.pop
|
57
57
|
when /(.+)\s+\w+/
|
@@ -60,11 +60,11 @@ module StarScope::Lang
|
|
60
60
|
when :interface
|
61
61
|
case line
|
62
62
|
when END_OF_BLOCK
|
63
|
-
yield :end, "}", :line_no => line_no, :
|
63
|
+
yield :end, scope + ["}"], :line_no => line_no, :type => :class
|
64
64
|
stack.pop
|
65
65
|
scope.pop
|
66
66
|
when /(\w+)\(.*\)\s+/
|
67
|
-
yield :defs, $1, :line_no => line_no
|
67
|
+
yield :defs, scope + [$1], :line_no => line_no
|
68
68
|
end
|
69
69
|
when :def
|
70
70
|
case line
|
@@ -81,7 +81,7 @@ module StarScope::Lang
|
|
81
81
|
stack.pop
|
82
82
|
when /"(.+)"/
|
83
83
|
name = $1.split('/')
|
84
|
-
yield :imports, name
|
84
|
+
yield :imports, name, :line_no => line_no
|
85
85
|
end
|
86
86
|
else
|
87
87
|
if stack[-1] == :func and /^\}/ =~ line
|
@@ -90,46 +90,46 @@ module StarScope::Lang
|
|
90
90
|
end
|
91
91
|
case line
|
92
92
|
when /^func\s+(\w+)\(/
|
93
|
-
yield :defs, $1, :line_no => line_no, :
|
93
|
+
yield :defs, scope + [$1], :line_no => line_no, :type => :func
|
94
94
|
stack.push(:func)
|
95
95
|
when /^func\s+\(\w+\s+\*?(\w+)\)\s*(\w+)\(/
|
96
|
-
yield :defs, $2, :line_no => line_no, :
|
96
|
+
yield :defs, scope + [$1, $2], :line_no => line_no, :type => :func
|
97
97
|
stack.push(:func)
|
98
98
|
when /^package\s+(\w+)/
|
99
|
-
yield :defs, $1, :line_no => line_no, :scope => scope, :type => :package
|
100
99
|
scope.push($1)
|
100
|
+
yield :defs, scope, :line_no => line_no, :type => :package
|
101
101
|
when /^type\s+(\w+)\s+struct\s*\{/
|
102
|
-
yield :defs, $1, :line_no => line_no, :scope => scope, :type => :class
|
103
102
|
scope.push($1)
|
104
103
|
stack.push(:struct)
|
104
|
+
yield :defs, scope, :line_no => line_no, :type => :class
|
105
105
|
when /^type\s+(\w+)\s+interface\s*\{/
|
106
|
-
yield :defs, $1, :line_no => line_no, :scope => scope, :type => :class
|
107
106
|
scope.push($1)
|
108
107
|
stack.push(:interface)
|
108
|
+
yield :defs, scope, :line_no => line_no, :type => :class
|
109
109
|
when /^type\s+(\w+)/
|
110
|
-
yield :defs, $1, :line_no => line_no, :
|
110
|
+
yield :defs, scope + [$1], :line_no => line_no, :type => :type
|
111
111
|
when /^import\s+"(.+)"/
|
112
112
|
name = $1.split('/')
|
113
|
-
yield :imports, name
|
113
|
+
yield :imports, name, :line_no => line_no
|
114
114
|
when /^import\s+\(/
|
115
115
|
stack.push(:import)
|
116
116
|
when /^var\s+\(/
|
117
117
|
stack.push(:def)
|
118
|
-
when /^var\s+(\w+)\s
|
119
|
-
yield :defs, $1, :line_no => line_no
|
118
|
+
when /^var\s+(\w+)\s/
|
119
|
+
yield :defs, scope + [$1], :line_no => line_no
|
120
120
|
when /^const\s+\(/
|
121
121
|
stack.push(:def)
|
122
|
-
when /^const\s+(\w+)\s
|
123
|
-
yield :defs, $1, :line_no => line_no
|
122
|
+
when /^const\s+(\w+)\s/
|
123
|
+
yield :defs, scope + [$1], :line_no => line_no
|
124
124
|
when /^\s+(.*?) :?=[^=]/
|
125
125
|
$1.split(' ').each do |var|
|
126
126
|
next if CONTROL_KEYS.include?(var)
|
127
127
|
name = var.delete(',').split('.')
|
128
128
|
next if name[0] == "_" # assigning to _ is a discard in golang
|
129
129
|
if name.length == 1
|
130
|
-
yield :assigns, name[0], :line_no => line_no
|
130
|
+
yield :assigns, scope + [name[0]], :line_no => line_no
|
131
131
|
else
|
132
|
-
yield :assigns, name
|
132
|
+
yield :assigns, name, :line_no => line_no
|
133
133
|
end
|
134
134
|
end
|
135
135
|
parse_call(line, line_no, scope, &block)
|
@@ -153,17 +153,21 @@ module StarScope::Lang
|
|
153
153
|
if BUILTIN_FUNCS.include?(name[0])
|
154
154
|
yield :calls, name[0], :line_no => line_no
|
155
155
|
else
|
156
|
-
yield :calls, name[0], :line_no => line_no
|
156
|
+
yield :calls, scope + [name[0]], :line_no => line_no
|
157
157
|
end
|
158
158
|
else
|
159
|
-
yield :calls, name
|
159
|
+
yield :calls, name, :line_no => line_no
|
160
160
|
end
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
164
|
def self.parse_def(line, line_no, scope)
|
165
|
+
# if it doesn't start with a valid identifier character, it's probably
|
166
|
+
# part of a multi-line literal and we should skip it
|
167
|
+
return if not line =~ /^\s*[[:alpha:]_]/
|
168
|
+
|
165
169
|
line.split.each do |var|
|
166
|
-
yield :defs, var.delete(','), :line_no => line_no
|
170
|
+
yield :defs, scope + [var.delete(',')], :line_no => line_no
|
167
171
|
break if not var.end_with?(',')
|
168
172
|
end
|
169
173
|
end
|
data/lib/starscope/langs/ruby.rb
CHANGED
@@ -3,12 +3,14 @@ require "parser/current"
|
|
3
3
|
module StarScope::Lang
|
4
4
|
module Ruby
|
5
5
|
def self.match_file(name)
|
6
|
-
return true if name
|
7
|
-
|
6
|
+
return true if name.end_with?(".rb")
|
7
|
+
File.open(name) do |f|
|
8
|
+
head = f.read(2)
|
9
|
+
return false if head.nil? or not head.start_with?("#!")
|
10
|
+
return f.readline.include?("ruby")
|
11
|
+
end
|
8
12
|
rescue ArgumentError # may occur if file is binary (invalid UTF)
|
9
13
|
false
|
10
|
-
rescue EOFError # occurs when file is empty
|
11
|
-
false
|
12
14
|
end
|
13
15
|
|
14
16
|
def self.extract(file, &block)
|
@@ -52,39 +54,29 @@ module StarScope::Lang
|
|
52
54
|
case node.type
|
53
55
|
when :send
|
54
56
|
fqn = scoped_name(node)
|
55
|
-
yield :calls, fqn.
|
56
|
-
:line_no => node.location.expression.line,
|
57
|
-
:scope => fqn[0...-1]
|
57
|
+
yield :calls, fqn, :line_no => node.location.expression.line
|
58
58
|
if node.children[0].nil? and node.children[1] == :require and node.children[2].type == :str
|
59
59
|
fqn = node.children[2].children[0].split("/")
|
60
|
-
yield :requires, fqn.
|
61
|
-
:line_no => node.location.expression.line,
|
62
|
-
:scope => fqn[0...-1]
|
60
|
+
yield :requires, fqn, :line_no => node.location.expression.line
|
63
61
|
end
|
64
62
|
when :def
|
65
|
-
yield :defs, node.children[0],
|
66
|
-
:line_no => node.location.expression.line,
|
67
|
-
:scope => @scope, :type => :func
|
63
|
+
yield :defs, @scope + [node.children[0]],
|
64
|
+
:line_no => node.location.expression.line, :type => :func
|
68
65
|
yield :end, :end, :line_no => node.location.end.line, :type => :func
|
69
66
|
when :defs
|
70
|
-
yield :defs, node.children[1],
|
71
|
-
:line_no => node.location.expression.line,
|
72
|
-
:scope => @scope, :type => :func
|
67
|
+
yield :defs, @scope + [node.children[1]],
|
68
|
+
:line_no => node.location.expression.line, :type => :func
|
73
69
|
yield :end, :end, :line_no => node.location.end.line, :type => :func
|
74
70
|
when :module, :class
|
75
71
|
fqn = @scope + scoped_name(node.children[0])
|
76
|
-
yield :defs, fqn
|
77
|
-
:scope => fqn[0...-1], :type => node.type
|
72
|
+
yield :defs, fqn, :line_no => node.location.expression.line, :type => node.type
|
78
73
|
yield :end, :end, :line_no => node.location.end.line, :type => node.type
|
79
74
|
when :casgn
|
80
75
|
fqn = scoped_name(node)
|
81
|
-
yield :assigns, fqn.
|
82
|
-
|
83
|
-
:scope => fqn[0...-1]
|
76
|
+
yield :assigns, fqn, :line_no => node.location.expression.line
|
77
|
+
yield :defs, fqn, :line_no => node.location.expression.line
|
84
78
|
when :lvasgn, :ivasgn, :cvasgn, :gvasgn
|
85
|
-
yield :assigns, node.children[0],
|
86
|
-
:line_no => node.location.expression.line,
|
87
|
-
:scope => @scope
|
79
|
+
yield :assigns, @scope + [node.children[0]], :line_no => node.location.expression.line
|
88
80
|
end
|
89
81
|
end
|
90
82
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class StarScope::Matcher
|
2
|
+
|
3
|
+
MATCH_TYPES = [:full_match, :simple_match, :simple_regexp, :full_regexp]
|
4
|
+
|
5
|
+
def initialize(query, input)
|
6
|
+
@query = query
|
7
|
+
@input = input
|
8
|
+
@regexp = Regexp.new(query, Regexp::IGNORECASE)
|
9
|
+
rescue RegexpError
|
10
|
+
# not a regex, oh well
|
11
|
+
end
|
12
|
+
|
13
|
+
def match(record)
|
14
|
+
name = record[:name].map {|x| x.to_s}
|
15
|
+
fullname = name.join('::')
|
16
|
+
|
17
|
+
case
|
18
|
+
when fullname == @query
|
19
|
+
:full_match
|
20
|
+
when name[-1] == @query
|
21
|
+
:simple_match
|
22
|
+
when @regexp
|
23
|
+
if @regexp.match(name[-1])
|
24
|
+
:simple_regexp
|
25
|
+
elsif @regexp.match(fullname)
|
26
|
+
:full_regexp
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def query
|
32
|
+
return [] if @input.empty?
|
33
|
+
|
34
|
+
results = @input.group_by {|x| match(x)}
|
35
|
+
|
36
|
+
MATCH_TYPES.each do |type|
|
37
|
+
next if results[type].nil? or results[type].empty?
|
38
|
+
return results[type]
|
39
|
+
end
|
40
|
+
|
41
|
+
return []
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'ruby-progressbar'
|
2
|
+
|
3
|
+
class StarScope::Output
|
4
|
+
|
5
|
+
PBAR_FORMAT = '%t: %c/%C %E ||%b>%i||'
|
6
|
+
|
7
|
+
def initialize(progress, verbose)
|
8
|
+
@progress = progress
|
9
|
+
@verbose = verbose
|
10
|
+
@pbar = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def new_pbar(title, num_items)
|
14
|
+
if @progress
|
15
|
+
@pbar = ProgressBar.create(:title => title, :total => num_items,
|
16
|
+
:format => PBAR_FORMAT, :length => 80)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def inc_pbar
|
21
|
+
@pbar.increment if @pbar
|
22
|
+
end
|
23
|
+
|
24
|
+
def finish_pbar
|
25
|
+
if @pbar
|
26
|
+
@pbar.finish
|
27
|
+
@pbar = nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def log(msg)
|
32
|
+
return if not @verbose
|
33
|
+
|
34
|
+
if @pbar
|
35
|
+
@pbar.log(msg)
|
36
|
+
else
|
37
|
+
puts msg
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class StarScope::Record
|
2
|
+
|
3
|
+
def self.build(file, name, args)
|
4
|
+
args[:file] = file
|
5
|
+
|
6
|
+
if name.is_a? Array
|
7
|
+
args[:name] = name.map {|x| x.to_sym}
|
8
|
+
else
|
9
|
+
args[:name] = [name.to_sym]
|
10
|
+
end
|
11
|
+
|
12
|
+
if args[:line_no]
|
13
|
+
args[:line] = File.readlines(file)[args[:line_no]-1].chomp
|
14
|
+
end
|
15
|
+
|
16
|
+
args
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.format(rec)
|
20
|
+
"#{rec[:name].join " "} -- #{rec[:file]}:#{rec[:line_no]} (#{rec[:line].strip})"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.ctag_line(rec)
|
24
|
+
ret = "#{rec[:name][-1]}\t#{rec[:file]}\t/^#{rec[:line]}$/"
|
25
|
+
|
26
|
+
ext = self.ctag_ext_tags(rec)
|
27
|
+
if not ext.empty?
|
28
|
+
ret << ";\""
|
29
|
+
ext.each do |k, v|
|
30
|
+
ret << "\t#{k}:#{v}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
ret
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.ctag_ext_tags(rec)
|
38
|
+
tag = {}
|
39
|
+
|
40
|
+
# these extensions are documented at http://ctags.sourceforge.net/FORMAT
|
41
|
+
case rec[:type]
|
42
|
+
when :func
|
43
|
+
tag["kind"] = "f"
|
44
|
+
when :module, :class
|
45
|
+
tag["kind"] = "c"
|
46
|
+
end
|
47
|
+
|
48
|
+
tag
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.cscope_mark(tbl, rec)
|
52
|
+
case tbl
|
53
|
+
when :end
|
54
|
+
case rec[:type]
|
55
|
+
when :func
|
56
|
+
ret = "}"
|
57
|
+
else
|
58
|
+
return ""
|
59
|
+
end
|
60
|
+
when :file
|
61
|
+
ret = "@"
|
62
|
+
when :defs
|
63
|
+
case rec[:type]
|
64
|
+
when :func
|
65
|
+
ret = "$"
|
66
|
+
when :class, :module
|
67
|
+
ret = "c"
|
68
|
+
when :type
|
69
|
+
ret = "t"
|
70
|
+
else
|
71
|
+
ret = "g"
|
72
|
+
end
|
73
|
+
when :calls
|
74
|
+
ret = "`"
|
75
|
+
when :requires
|
76
|
+
ret = "~\""
|
77
|
+
when :imports
|
78
|
+
ret = "~<"
|
79
|
+
when :assigns
|
80
|
+
ret = "="
|
81
|
+
else
|
82
|
+
return ""
|
83
|
+
end
|
84
|
+
|
85
|
+
return "\t" + ret
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/starscope/version.rb
CHANGED
data/starscope.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.required_ruby_version = '>= 1.9.3'
|
17
17
|
|
18
|
-
gem.add_dependency 'oj', '~> 2.
|
18
|
+
gem.add_dependency 'oj', '~> 2.7'
|
19
19
|
gem.add_dependency 'parser', '~> 2.1'
|
20
20
|
gem.add_dependency 'ruby-progressbar', '~> 1.4'
|
21
21
|
gem.add_development_dependency 'bundler', '~> 1.5'
|
data/test/files/sample_golang.go
CHANGED
@@ -1,14 +1,28 @@
|
|
1
1
|
package main
|
2
2
|
|
3
|
+
import "fmt"
|
4
|
+
|
3
5
|
var (
|
4
6
|
v1, v2 int = 3, 4
|
7
|
+
raw = []byte{
|
8
|
+
0x00, 0x01,
|
9
|
+
0x02, 0x03,
|
10
|
+
}
|
5
11
|
)
|
6
12
|
|
13
|
+
var single_var = 3
|
14
|
+
|
15
|
+
const single_const = 4
|
16
|
+
|
7
17
|
const (
|
8
18
|
Sunday = iota
|
9
19
|
Monday
|
10
20
|
)
|
11
21
|
|
22
|
+
type foo interface {
|
23
|
+
bar() int
|
24
|
+
}
|
25
|
+
|
12
26
|
func a(c int) int {
|
13
27
|
return 3
|
14
28
|
}
|
@@ -41,4 +55,9 @@ func main() {
|
|
41
55
|
}
|
42
56
|
|
43
57
|
a(c(b(), b()))
|
58
|
+
c(y, z)
|
59
|
+
c(single_var, single_const)
|
60
|
+
|
61
|
+
fmt.Println(n)
|
62
|
+
fmt.Println(t)
|
44
63
|
}
|