starscope 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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