starscope 0.1.6 → 0.1.7

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.
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
@@ -1,11 +1,22 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- v0.1.6 (trunk)
4
+ v0.1.7 (trunk)
5
5
  -------------------
6
6
 
7
- Bug Fixes:
8
- * Much improved recognition of golang function calls.
7
+ Improvements:
8
+ * Much better recognition and parsing of definitions and assignments to
9
+ variables and constants in golang code (fixes #11 among others).
10
+
11
+ Infrastructure:
12
+ * Test suite and continuous integration (via Minitest and Travis-CI).
13
+ * Use github's tickets instead of a TODO file.
14
+
15
+ v0.1.6 (2014-01-10)
16
+ -------------------
17
+
18
+ Improvements:
19
+ * Better recognition of golang function calls.
9
20
 
10
21
  v0.1.5 (2014-01-06)
11
22
  -------------------
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- starscope (0.1.6)
4
+ starscope (0.1.7)
5
5
  oj (~> 2.5)
6
6
  parser (~> 2.1)
7
7
  ruby-progressbar (~> 1.4)
@@ -20,7 +20,7 @@ GEM
20
20
  debugger-ruby_core_source (1.3.1)
21
21
  method_source (0.8.2)
22
22
  oj (2.5.3)
23
- parser (2.1.3)
23
+ parser (2.1.4)
24
24
  ast (~> 1.1)
25
25
  slop (~> 3.4, >= 3.4.5)
26
26
  pry (0.9.12.4)
data/README.md CHANGED
@@ -2,6 +2,7 @@ StarScope
2
2
  =========
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/starscope.png)](http://badge.fury.io/rb/starscope)
5
+ [![Build Status](https://travis-ci.org/eapache/starscope.png?branch=master)](https://travis-ci.org/eapache/starscope)
5
6
 
6
7
  Anyone who has done much programming in C (or C++) on a unix-based OS has come
7
8
  across the fantastic [Cscope](http://cscope.sourceforge.net/) tool. Sadly, it
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib/starscope'
6
+ t.test_files = FileList['test/lib/test_*.rb']
7
+ end
8
+
9
+ desc "Run tests"
10
+ task :default => :test
@@ -1,10 +1,13 @@
1
1
  module StarScope::Lang
2
2
  module Go
3
3
  FUNC_CALL = /([\w\.]*?\w)\(/
4
+ END_OF_BLOCK = /^\s*}\s*$/
5
+ END_OF_GROUP = /^\s*\)\s*$/
4
6
  BUILTIN_FUNCS = ['new', 'make', 'len', 'close', 'copy', 'delete',
5
7
  'int', 'int8', 'int16', 'int32', 'int64',
6
8
  'uint', 'uint8', 'uint16', 'uint32', 'uint64',
7
9
  'string', 'byte']
10
+ CONTROL_KEYS = ['if', 'for', 'switch', 'case']
8
11
 
9
12
  def self.match_file(name)
10
13
  name =~ /.*\.go$/
@@ -47,36 +50,38 @@ module StarScope::Lang
47
50
  case stack[-1]
48
51
  when :struct
49
52
  case line
50
- when /\s*(\w+)\s+\w+/
51
- yield :defs, $1, line_no: line_no, scope: scope
52
- when /}/
53
+ when END_OF_BLOCK
53
54
  yield :end, "}", line_no: line_no, scope: scope, type: :class
54
55
  stack.pop
55
56
  scope.pop
57
+ when /(.+)\s+\w+/
58
+ parse_def($1, line_no, scope, &block)
56
59
  end
57
60
  when :interface
58
61
  case line
59
- when /\s*(\w+)\(.*\)\s+/
60
- yield :defs, $1, line_no: line_no, scope: scope
61
- when /}/
62
+ when END_OF_BLOCK
62
63
  yield :end, "}", line_no: line_no, scope: scope, type: :class
63
64
  stack.pop
64
65
  scope.pop
66
+ when /(\w+)\(.*\)\s+/
67
+ yield :defs, $1, line_no: line_no, scope: scope
65
68
  end
66
69
  when :def
67
70
  case line
68
- when /\s*(\w+)\s+/
69
- yield :defs, $1, line_no: line_no, scope: scope
70
- when /\)/
71
+ when END_OF_GROUP
71
72
  stack.pop
73
+ when /(.+)\s*=.*/
74
+ parse_def($1, line_no, scope, &block)
75
+ else
76
+ parse_def(line, line_no, scope, &block)
72
77
  end
73
78
  when :import
74
79
  case line
80
+ when END_OF_GROUP
81
+ stack.pop
75
82
  when /"(.+)"/
76
83
  name = $1.split('/')
77
84
  yield :imports, name[-1], line_no: line_no, scope: name[0...-1]
78
- when /\)/
79
- stack.pop
80
85
  end
81
86
  else
82
87
  if stack[-1] == :func and /^}/ =~ line
@@ -116,15 +121,15 @@ module StarScope::Lang
116
121
  stack.push(:def)
117
122
  when /^const\s+(\w+)\s+\w+/
118
123
  yield :defs, $1, line_no: line_no, scope: scope
119
- when /^\s+(.*?) :?=.*/
120
- $1.split(',').each do |var|
121
- var = var.strip
122
- name = var.split('.')
123
- case name.length
124
- when 1
124
+ when /^\s+(.*?) :?=[^=]/
125
+ $1.split(' ').each do |var|
126
+ next if CONTROL_KEYS.include?(var)
127
+ name = var.delete(',').split('.')
128
+ next if name[0] == "_" # assigning to _ is a discard in golang
129
+ if name.length == 1
125
130
  yield :assigns, name[0], line_no: line_no, scope: scope
126
- when 2
127
- yield :assigns, name[1], line_no: line_no, scope: [name[0]]
131
+ else
132
+ yield :assigns, name[1], line_no: line_no, scope: name[0..-1]
128
133
  end
129
134
  end
130
135
  parse_call(line, line_no, scope, &block)
@@ -155,5 +160,12 @@ module StarScope::Lang
155
160
  end
156
161
  end
157
162
  end
163
+
164
+ def self.parse_def(line, line_no, scope)
165
+ line.split.each do |var|
166
+ yield :defs, var.delete(','), line_no: line_no, scope: scope
167
+ break if not var.end_with?(',')
168
+ end
169
+ end
158
170
  end
159
171
  end
@@ -1,3 +1,3 @@
1
1
  module StarScope
2
- VERSION = "0.1.6"
2
+ VERSION = "0.1.7"
3
3
  end
@@ -11,6 +11,7 @@ Gem::Specification.new do |gem|
11
11
  gem.license = 'MIT'
12
12
  gem.files = `git ls-files`.split("\n")
13
13
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ gem.test_files = `git ls-files -- test/*`.split("\n")
14
15
  gem.require_paths = ["lib"]
15
16
  gem.required_ruby_version = '>= 1.9.3'
16
17
 
Binary file
@@ -1,5 +1,14 @@
1
1
  package main
2
2
 
3
+ var (
4
+ v1, v2 int = 3, 4
5
+ )
6
+
7
+ const (
8
+ Sunday = iota
9
+ Monday
10
+ )
11
+
3
12
  func a(c int) int {
4
13
  return 3
5
14
  }
@@ -12,6 +21,10 @@ func c(a, b int) int {
12
21
  return 1
13
22
  }
14
23
 
24
+ func ttt() (int, int) {
25
+ return 1, 2
26
+ }
27
+
15
28
  func main() {
16
29
  var (
17
30
  q int
@@ -20,6 +33,12 @@ func main() {
20
33
  x := a(1)
21
34
  y := b()
22
35
  z := c(a(q), b())
36
+ n, m := ttt()
37
+ m, x = ttt()
38
+
39
+ if m == x {
40
+ v1 = v2
41
+ }
23
42
 
24
43
  a(c(b(), b()))
25
44
  }
@@ -0,0 +1,163 @@
1
+ require 'date'
2
+ require 'zlib'
3
+
4
+ LANGS = [
5
+ StarScope::Lang::Go,
6
+ StarScope::Lang::Ruby
7
+ ]
8
+
9
+ class StarScope::DB
10
+
11
+ PBAR_FORMAT = '%t: %c/%C %E ||%b>%i||'
12
+
13
+ class NoTableError < StandardError; end
14
+
15
+ def initialize(progress)
16
+ @progress = progress
17
+ @paths = []
18
+ @files = {}
19
+ @tables = {}
20
+ end
21
+
22
+ def load(file)
23
+ File.open(file, 'r') do |file|
24
+ Zlib::GzipReader.wrap(file) do |file|
25
+ format = file.gets.to_i
26
+ if format == DB_FORMAT
27
+ @paths = Oj.load(file.gets)
28
+ @files = Oj.load(file.gets)
29
+ @tables = Oj.load(file.gets, symbol_keys: true)
30
+ elsif format <= 2
31
+ # Old format (pre-json), so read the directories segment then rebuild
32
+ len = file.gets.to_i
33
+ add_paths(Marshal::load(file.read(len)))
34
+ elsif format < DB_FORMAT
35
+ # Old format, so read the directories segment then rebuild
36
+ add_paths(Oj.load(file.gets))
37
+ elsif format > DB_FORMAT
38
+ raise UnknownDBFormatError
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def save(file)
45
+ File.open(file, 'w') do |file|
46
+ Zlib::GzipWriter.wrap(file) do |file|
47
+ file.puts DB_FORMAT
48
+ file.puts Oj.dump @paths
49
+ file.puts Oj.dump @files
50
+ file.puts Oj.dump @tables
51
+ end
52
+ end
53
+ end
54
+
55
+ def add_paths(paths)
56
+ paths -= @paths
57
+ return if paths.empty?
58
+ @paths += paths
59
+ files = paths.map {|p| self.class.files_from_path(p)}.flatten
60
+ return if files.empty?
61
+ if @progress
62
+ pbar = ProgressBar.create(title: "Building", total: files.length, format: PBAR_FORMAT, length: 80)
63
+ end
64
+ files.each do |f|
65
+ add_file(f)
66
+ pbar.increment if @progress
67
+ end
68
+ end
69
+
70
+ def update
71
+ new_files = (@paths.map {|p| self.class.files_from_path(p)}.flatten) - @files.keys
72
+ if @progress
73
+ pbar = ProgressBar.create(title: "Updating", total: new_files.length + @files.length, format: PBAR_FORMAT, length: 80)
74
+ end
75
+ changed = @files.keys.map do |f|
76
+ changed = update_file(f)
77
+ pbar.increment if @progress
78
+ changed
79
+ end
80
+ new_files.each do |f|
81
+ add_file(f)
82
+ pbar.increment if @progress
83
+ end
84
+ changed.any? || !new_files.empty?
85
+ end
86
+
87
+ def summary
88
+ ret = {}
89
+
90
+ @tables.each_key do |key|
91
+ ret[key] = @tables[key].keys.count
92
+ end
93
+
94
+ ret
95
+ end
96
+
97
+ private
98
+
99
+ def self.files_from_path(path)
100
+ if File.file?(path)
101
+ [path]
102
+ elsif File.directory?(path)
103
+ Dir[File.join(path, "**", "*")].select {|p| File.file?(p)}
104
+ else
105
+ []
106
+ end
107
+ end
108
+
109
+ def db_by_line()
110
+ tmpdb = {}
111
+ @tables.each do |tbl, vals|
112
+ vals.each do |key, val|
113
+ val.each do |entry|
114
+ if entry[:line_no]
115
+ tmpdb[entry[:file]] ||= {}
116
+ tmpdb[entry[:file]][entry[:line_no]] ||= []
117
+ tmpdb[entry[:file]][entry[:line_no]] << {tbl: tbl, key: key, entry: entry}
118
+ end
119
+ end
120
+ end
121
+ end
122
+ return tmpdb
123
+ end
124
+
125
+ def add_file(file)
126
+ return if not File.file? file
127
+
128
+ @files[file] = File.mtime(file).to_s
129
+
130
+ LANGS.each do |lang|
131
+ next if not lang.match_file file
132
+ lang.extract file do |tbl, key, args|
133
+ key = key.to_sym
134
+ @tables[tbl] ||= {}
135
+ @tables[tbl][key] ||= []
136
+ @tables[tbl][key] << StarScope::Datum.build(file, key, args)
137
+ end
138
+ end
139
+ end
140
+
141
+ def remove_file(file)
142
+ @files.delete(file)
143
+ @tables.each do |name, tbl|
144
+ tbl.each do |key, val|
145
+ val.delete_if {|dat| dat[:file] == file}
146
+ end
147
+ end
148
+ end
149
+
150
+ def update_file(file)
151
+ if not File.exists?(file) or not File.file?(file)
152
+ remove_file(file)
153
+ true
154
+ elsif DateTime.parse(@files[file]).to_time < File.mtime(file)
155
+ remove_file(file)
156
+ add_file(file)
157
+ true
158
+ else
159
+ false
160
+ end
161
+ end
162
+
163
+ end
@@ -0,0 +1,44 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe StarScope::DB do
4
+
5
+ before do
6
+ @db = StarScope::DB.new(false)
7
+ end
8
+
9
+ it "must raise on invalid tables" do
10
+ proc {@db.dump_table(:foo)}.must_raise StarScope::DB::NoTableError
11
+ end
12
+
13
+ it "must correctly add paths" do
14
+ paths = [GOLANG_SAMPLE, 'test/files']
15
+ @db.add_paths(paths)
16
+ @db.instance_eval('@paths').must_equal paths
17
+ @db.instance_eval('@files').keys.must_include GOLANG_SAMPLE
18
+ @db.instance_eval('@files').keys.must_include RUBY_SAMPLE
19
+ end
20
+
21
+ it "must correctly pick up new files in old paths" do
22
+ @db.instance_eval('@paths = ["test/files"]')
23
+ @db.update
24
+ files = @db.instance_eval('@files').keys
25
+ files.must_include GOLANG_SAMPLE
26
+ files.must_include RUBY_SAMPLE
27
+ end
28
+
29
+ it "must correctly remove old files in existing paths" do
30
+ @db.instance_eval('@paths = ["test/files"]')
31
+ @db.instance_eval('@files = {"test/files/foo"=>"2012-01-01"}')
32
+ @db.instance_eval('@files').keys.must_include 'test/files/foo'
33
+ @db.update
34
+ @db.instance_eval('@files').keys.wont_include 'test/files/foo'
35
+ end
36
+
37
+ it "must correctly load an old DB file" do
38
+ @db.load('test/files/db_old.json.gz')
39
+ @db.instance_eval('@paths').must_equal ['test/files']
40
+ @db.instance_eval('@files').keys.must_include GOLANG_SAMPLE
41
+ @db.instance_eval('@files').keys.must_include RUBY_SAMPLE
42
+ end
43
+
44
+ end
@@ -0,0 +1,67 @@
1
+ require_relative '../test_helper'
2
+
3
+ class TestGolang < MiniTest::Unit::TestCase
4
+ def setup
5
+ @db = {}
6
+ StarScope::Lang::Go.extract(GOLANG_SAMPLE) do |tbl, key, args|
7
+ key = key.to_sym
8
+ @db[tbl] ||= {}
9
+ @db[tbl][key] ||= []
10
+ @db[tbl][key] << args
11
+ end
12
+ end
13
+
14
+ def test_recognition
15
+ assert StarScope::Lang::Go.match_file(GOLANG_SAMPLE)
16
+ refute StarScope::Lang::Go.match_file('something_else')
17
+ end
18
+
19
+ def test_defs
20
+ assert @db.keys.include? :defs
21
+ defs = @db[:defs].keys
22
+ assert defs.include? :a
23
+ assert defs.include? :b
24
+ assert defs.include? :c
25
+ assert defs.include? :ttt
26
+ assert defs.include? :main
27
+ assert defs.include? :v1
28
+ assert defs.include? :v2
29
+ assert defs.include? :Sunday
30
+ assert defs.include? :Monday
31
+ end
32
+
33
+ def test_function_ends
34
+ assert @db.keys.include? :end
35
+ ends = @db[:end]
36
+ assert ends.keys.count == 1
37
+ assert ends.values.first.count == 5
38
+ end
39
+
40
+ def test_function_calls
41
+ assert @db.keys.include? :calls
42
+ calls = @db[:calls]
43
+ assert calls.keys.include? :a
44
+ assert calls.keys.include? :b
45
+ assert calls.keys.include? :c
46
+ assert calls.keys.include? :ttt
47
+ assert calls[:a].count == 3
48
+ assert calls[:b].count == 4
49
+ assert calls[:c].count == 2
50
+ assert calls[:ttt].count == 2
51
+ end
52
+
53
+ def test_variable_assigns
54
+ assert @db.keys.include? :assigns
55
+ assigns = @db[:assigns]
56
+ assert assigns.keys.include? :x
57
+ assert assigns.keys.include? :y
58
+ assert assigns.keys.include? :z
59
+ assert assigns.keys.include? :n
60
+ assert assigns.keys.include? :m
61
+ assert assigns[:x].count == 2
62
+ assert assigns[:y].count == 1
63
+ assert assigns[:z].count == 1
64
+ assert assigns[:n].count == 1
65
+ assert assigns[:m].count == 2
66
+ end
67
+ end
@@ -0,0 +1,54 @@
1
+ require_relative '../test_helper'
2
+
3
+ class TestRuby < MiniTest::Unit::TestCase
4
+ def setup
5
+ @db = {}
6
+ StarScope::Lang::Ruby.extract(RUBY_SAMPLE) do |tbl, key, args|
7
+ key = key.to_sym
8
+ @db[tbl] ||= {}
9
+ @db[tbl][key] ||= []
10
+ @db[tbl][key] << args
11
+ end
12
+ end
13
+
14
+ def test_recognition
15
+ assert StarScope::Lang::Ruby.match_file(RUBY_SAMPLE)
16
+ assert StarScope::Lang::Ruby.match_file('bin/starscope')
17
+ refute StarScope::Lang::Ruby.match_file('test/files/sample_golang.go')
18
+ end
19
+
20
+ def test_function_defs
21
+ assert @db.keys.include? :defs
22
+ defs = @db[:defs].keys
23
+ assert defs.include? :DB
24
+ assert defs.include? :NoTableError
25
+ assert defs.include? :load
26
+ assert defs.include? :update
27
+ assert defs.include? :files_from_path
28
+ end
29
+
30
+ def test_function_ends
31
+ assert @db.keys.include? :end
32
+ ends = @db[:end]
33
+ assert ends.keys.count == 1
34
+ assert ends.values.first.count == 13
35
+ end
36
+
37
+ def test_function_calls
38
+ assert @db.keys.include? :calls
39
+ calls = @db[:calls]
40
+ assert calls.keys.include? :add_file
41
+ assert calls.keys.include? :each
42
+ assert calls[:add_file].count == 3
43
+ assert calls[:each].count == 8
44
+ end
45
+
46
+ def test_variable_assigns
47
+ assert @db.keys.include? :assigns
48
+ assigns = @db[:assigns]
49
+ assert assigns.keys.include? :pbar
50
+ assert assigns.keys.include? :PBAR_FORMAT
51
+ assert assigns[:pbar].count == 2
52
+ assert assigns[:PBAR_FORMAT].count == 1
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ require_relative '../test_helper'
2
+
3
+ describe StarScope do
4
+
5
+ it "must be defined" do
6
+ StarScope::VERSION.wont_be_nil
7
+ end
8
+
9
+ end
@@ -0,0 +1,6 @@
1
+ require 'minitest/autorun'
2
+ require 'minitest/pride'
3
+ require File.expand_path('../../lib/starscope.rb', __FILE__)
4
+
5
+ GOLANG_SAMPLE = 'test/files/sample_golang.go'
6
+ RUBY_SAMPLE = 'test/files/sample_ruby.rb'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: starscope
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-10 00:00:00.000000000 Z
12
+ date: 2014-01-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: oj
@@ -131,13 +131,13 @@ extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
133
  - .gitignore
134
+ - .travis.yml
134
135
  - CHANGELOG.md
135
136
  - Gemfile
136
137
  - Gemfile.lock
137
138
  - LICENSE.txt
138
139
  - README.md
139
140
  - Rakefile
140
- - TODO.md
141
141
  - bin/starscope
142
142
  - lib/starscope.rb
143
143
  - lib/starscope/datum.rb
@@ -146,7 +146,14 @@ files:
146
146
  - lib/starscope/langs/ruby.rb
147
147
  - lib/starscope/version.rb
148
148
  - starscope.gemspec
149
- - test/test.go
149
+ - test/files/db_old.json.gz
150
+ - test/files/sample_golang.go
151
+ - test/files/sample_ruby.rb
152
+ - test/lib/test_db.rb
153
+ - test/lib/test_golang.rb
154
+ - test/lib/test_ruby.rb
155
+ - test/lib/test_version.rb
156
+ - test/test_helper.rb
150
157
  homepage: https://github.com/eapache/starscope
151
158
  licenses:
152
159
  - MIT
@@ -172,4 +179,12 @@ rubygems_version: 1.8.23
172
179
  signing_key:
173
180
  specification_version: 3
174
181
  summary: A code indexer and analyzer
175
- test_files: []
182
+ test_files:
183
+ - test/files/db_old.json.gz
184
+ - test/files/sample_golang.go
185
+ - test/files/sample_ruby.rb
186
+ - test/lib/test_db.rb
187
+ - test/lib/test_golang.rb
188
+ - test/lib/test_ruby.rb
189
+ - test/lib/test_version.rb
190
+ - test/test_helper.rb
data/TODO.md DELETED
@@ -1,6 +0,0 @@
1
- TODO
2
- =========
3
-
4
- * Parallelization, perhaps via https://github.com/grosser/parallel
5
- * Fuzzy matching, perhaps via https://github.com/seamusabshere/fuzzy_match
6
- * Export advanced ctags annotations