starscope 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.md CHANGED
@@ -1,7 +1,18 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- v0.0.5 (trunk)
4
+ v0.0.6 (trunk)
5
+ -------------------
6
+
7
+ Interface:
8
+ * Table names are now consistently conjugated (def -> defs, assign -> assigns)
9
+ * The `starscope` binary no longer has an unnecessary .rb suffix.
10
+
11
+ Internals:
12
+ * Update to a new version of the ruby parser that is significantly faster.
13
+ * Database is now stored as gzipped JSON for better portability
14
+
15
+ v0.0.5 (2013-06-22)
5
16
  -------------------
6
17
 
7
18
  New Features:
data/Gemfile.lock CHANGED
@@ -1,13 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- starscope (0.0.5)
5
- parser (~> 1.4)
4
+ starscope (0.0.6)
5
+ parser (= 2.0.0.pre2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (1.0.2)
10
+ ast (1.1.0)
11
11
  coderay (1.0.9)
12
12
  columnize (0.3.6)
13
13
  debugger (1.6.0)
@@ -17,9 +17,9 @@ GEM
17
17
  debugger-linecache (1.2.0)
18
18
  debugger-ruby_core_source (1.2.2)
19
19
  method_source (0.8.1)
20
- parser (1.4.1)
21
- ast (~> 1.0)
22
- slop (~> 3.4)
20
+ parser (2.0.0.pre2)
21
+ ast (~> 1.1)
22
+ slop (~> 3.4, >= 3.4.5)
23
23
  pry (0.9.12.2)
24
24
  coderay (~> 1.0.5)
25
25
  method_source (~> 0.8)
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  StarScope
2
2
  =========
3
3
 
4
+ *Note to those users looking at the GitHub language statistics: there is no perl
5
+ here, that is their bug to fix.*
6
+
4
7
  Anyone who has done much programming in C (or C++) on a unix-based OS has come
5
8
  across the fantastic Cscope tool [1]. Sadly, it only works for C (and sort of
6
9
  works for C++).
@@ -17,17 +20,17 @@ $ gem install starscope
17
20
  Build your database, by just running it in the project directory:
18
21
  ```
19
22
  $ cd ~/my-project
20
- $ starscope.rb
23
+ $ starscope
21
24
  ```
22
25
 
23
26
  Ask it things with `-q`
24
27
  ```
25
- $ starscope.rb -q calls,new # Lists all callers of new
28
+ $ starscope -q calls,new # Lists all callers of new
26
29
  ```
27
30
 
28
31
  Export it for use with your editor
29
32
  ```
30
- $ starscope.rb -e ctags
33
+ $ starscope -e ctags
31
34
  ```
32
35
 
33
36
  [1] http://cscope.sourceforge.net/
data/TODO.md ADDED
@@ -0,0 +1,6 @@
1
+ TODO
2
+ =========
3
+
4
+ * Parallelization, perhaps via https://github.com/grosser/parallel
5
+ * Export advanced ctags annotations
6
+ * Export to cscope format
@@ -74,7 +74,7 @@ def run_query(db, table, value)
74
74
  $stderr.puts "Invalid input - no query found."
75
75
  return
76
76
  end
77
- puts db.query(table.to_sym, value)
77
+ puts db.query(table.to_sym, value).map {|val| StarScope::Datum.to_s(val)}
78
78
  return true
79
79
  rescue StarScope::DB::NoTableError
80
80
  $stderr.puts "Table '#{table}' doesn't exist."
@@ -1,42 +1,48 @@
1
1
  class StarScope::Datum
2
- attr_reader :key, :file
3
-
4
- def initialize(fqn, file, line_no)
5
- @key = fqn[-1].to_sym
6
- @scope = fqn[0...-1].map {|x| x.to_sym}
7
- @file = file
8
- @line_no = line_no
9
- @line = File.readlines(file)[line_no-1].chomp
2
+
3
+ def self.build(key, file, args)
4
+ args[:key] = key
5
+ args[:file] = file
6
+
7
+ if args[:line_no]
8
+ args[:line] = File.readlines(file)[args[:line_no]-1].chomp
9
+ end
10
+
11
+ if args[:scope]
12
+ args[:scope] = args[:scope].map {|x| x.to_sym}
13
+ end
14
+
15
+ args
10
16
  end
11
17
 
12
- def score_match(fqn)
18
+ def self.score_match(dat, fqn)
13
19
  score = 0
14
20
 
15
21
  i = -1
16
22
  fqn[0...-1].reverse.each do |test|
17
- if test.to_sym == @scope[i]
23
+ if test.to_sym == dat[:scope][i]
18
24
  score += 5
19
- elsif Regexp.new(test, Regexp::IGNORECASE).match(@scope[i])
25
+ elsif Regexp.new(test, Regexp::IGNORECASE).match(dat[:scope][i])
20
26
  score += 2
21
27
  end
22
28
  i -= 1
23
29
  end
24
30
 
25
- score - @scope.count - i + 1
31
+ score - dat[:scope].count - i + 1
26
32
  end
27
33
 
28
- def location
29
- "#{@file}:#{@line_no}"
34
+ def self.location(dat)
35
+ "#{dat[:file]}:#{dat[:line_no]}"
30
36
  end
31
37
 
32
- def to_s
38
+ def self.to_s(dat)
33
39
  str = ""
34
- str << "#{@scope.join " "} " unless @scope.empty?
35
- str << "#{@key} -- #{location}"
36
- str << " (#{@line.strip})"
40
+ str << "#{dat[:scope].join " "} " unless dat[:scope].empty?
41
+ str << "#{dat[:key]} -- #{location dat}"
42
+ str << " (#{dat[:line].strip})"
37
43
  end
38
44
 
39
- def ctag_line
40
- "#{@key}\t#{@file}\t/^#{@line}$/;"
45
+ def self.ctag_line(dat)
46
+ "#{dat[:key]}\t#{dat[:file]}\t/^#{dat[:line]}$/;"
41
47
  end
42
48
  end
data/lib/starscope/db.rb CHANGED
@@ -1,12 +1,14 @@
1
1
  require 'starscope/langs/ruby'
2
- require "starscope/datum"
2
+ require 'starscope/datum'
3
+ require 'date'
4
+ require 'json'
3
5
  require 'zlib'
4
6
 
5
7
  LANGS = [StarScope::Lang::Ruby]
6
8
 
7
9
  class StarScope::DB
8
10
 
9
- DB_FORMAT = 2
11
+ DB_FORMAT = 3
10
12
 
11
13
  class NoTableError < StandardError; end
12
14
  class UnknownDBFormatError < StandardError; end
@@ -22,12 +24,16 @@ class StarScope::DB
22
24
  Zlib::GzipReader.wrap(file) do |file|
23
25
  format = file.gets.to_i
24
26
  if format == DB_FORMAT
25
- @dirs = load_part(file)
26
- @files = load_part(file)
27
- @tables = load_part(file)
27
+ @dirs = JSON.parse(file.gets, symbolize_names: false)
28
+ @files = JSON.parse(file.gets, symbolize_names: false)
29
+ @tables = JSON.parse(file.gets, symbolize_names: 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_dirs(Marshal::load(file.read(len)))
28
34
  elsif format < DB_FORMAT
29
35
  # Old format, so read the directories segment then rebuild
30
- add_dirs(load_part(file))
36
+ add_dirs(JSON.parse(file.gets, symbolize_names: false))
31
37
  elsif format > DB_FORMAT
32
38
  raise UnknownDBFormatError
33
39
  end
@@ -39,9 +45,9 @@ class StarScope::DB
39
45
  File.open(file, 'w') do |file|
40
46
  Zlib::GzipWriter.wrap(file) do |file|
41
47
  file.puts DB_FORMAT
42
- save_part(file, @dirs)
43
- save_part(file, @files)
44
- save_part(file, @tables)
48
+ file.puts JSON.fast_generate @dirs
49
+ file.puts JSON.fast_generate @files
50
+ file.puts JSON.fast_generate @tables
45
51
  end
46
52
  end
47
53
  end
@@ -90,11 +96,15 @@ class StarScope::DB
90
96
  def query(table, value)
91
97
  fqn = value.split("::")
92
98
  raise NoTableError if not @tables[table]
93
- results = @tables[table][fqn[-1].to_sym]
99
+ results = @tables[table][fqn.last.to_sym]
94
100
  return [] if results.nil? || results.empty?
95
- results.sort! {|a,b| b.score_match(fqn) <=> a.score_match(fqn)}
96
- best_score = results[0].score_match(fqn)
97
- results.select {|result| best_score - result.score_match(fqn) < 4}
101
+ results.sort! do |a,b|
102
+ StarScope::Datum.score_match(b, fqn) <=> StarScope::Datum.score_match(a, fqn)
103
+ end
104
+ best_score = StarScope::Datum.score_match(results[0], fqn)
105
+ results.select do |result|
106
+ best_score - StarScope::Datum.score_match(result, fqn) < 4
107
+ end
98
108
  end
99
109
 
100
110
  def export_ctags(filename)
@@ -107,10 +117,10 @@ class StarScope::DB
107
117
  !_TAG_PROGRAM_URL https://github.com/eapache/starscope //
108
118
  !_TAG_PROGRAM_VERSION #{StarScope::VERSION} //
109
119
  END
110
- defs = (@tables[:def] || []).sort {|a,b| a <=> b}
120
+ defs = (@tables[:defs] || []).sort {|a,b| a <=> b}
111
121
  defs.each do |key, val|
112
122
  val.each do |entry|
113
- file.puts entry.ctag_line
123
+ file.puts StarScope::Datum.ctag_line(entry)
114
124
  end
115
125
  end
116
126
  end
@@ -118,29 +128,17 @@ END
118
128
 
119
129
  private
120
130
 
121
- def load_part(file)
122
- len = file.gets.to_i
123
- Marshal::load(file.read(len))
124
- end
125
-
126
- def save_part(file, val)
127
- dat = Marshal.dump(val)
128
- file.puts dat.length
129
- file.write dat
130
- end
131
-
132
131
  def add_file(file)
133
132
  return if not File.file? file
134
133
 
135
- @files[file] = File.mtime(file)
134
+ @files[file] = File.mtime(file).to_s
136
135
 
137
136
  LANGS.each do |lang|
138
137
  next if not lang.match_file file
139
- lang.extract file do |tblname, fqn, lineno|
140
- datum = StarScope::Datum.new(fqn, file, lineno)
141
- @tables[tblname] ||= {}
142
- @tables[tblname][datum.key] ||= []
143
- @tables[tblname][datum.key] << datum
138
+ lang.extract file do |tbl, key, args|
139
+ @tables[tbl] ||= {}
140
+ @tables[tbl][key] ||= []
141
+ @tables[tbl][key] << StarScope::Datum.build(key, file, args)
144
142
  end
145
143
  end
146
144
  end
@@ -149,7 +147,7 @@ END
149
147
  @files.delete(file)
150
148
  @tables.each do |name, tbl|
151
149
  tbl.each do |key, val|
152
- val.delete_if {|dat| dat.file == file}
150
+ val.delete_if {|dat| dat[:file] == file}
153
151
  end
154
152
  end
155
153
  end
@@ -157,7 +155,7 @@ END
157
155
  def update_file(file)
158
156
  if not File.exists?(file)
159
157
  remove_file(file)
160
- elsif @files[file] < File.mtime(file)
158
+ elsif DateTime.parse(@files[file]).to_time < File.mtime(file)
161
159
  remove_file(file)
162
160
  add_file(file)
163
161
  end
@@ -22,7 +22,7 @@ module StarScope::Lang
22
22
  @ast = ast
23
23
  @scope = []
24
24
  end
25
-
25
+
26
26
  def extract(&block)
27
27
  extract_tree(@ast, &block)
28
28
  end
@@ -45,30 +45,42 @@ module StarScope::Lang
45
45
 
46
46
  def extract_node(node)
47
47
  if node.type == :send
48
- yield :calls, scoped_name(node), node.source_map.expression.line
48
+ fqn = scoped_name(node)
49
+ yield :calls, fqn.last, line_no: node.location.expression.line,
50
+ scope: fqn[0...-1]
49
51
 
50
52
  if node.children[0].nil? and node.children[1] == :require and node.children[2].type == :str
51
- yield :requires, node.children[2].children[0].split("/"), node.source_map.expression.line
53
+ fqn = node.children[2].children[0].split("/")
54
+ yield :requires, fqn.last, line_no: node.location.expression.line,
55
+ scope: fqn[0...-1]
52
56
  end
53
57
  end
54
58
 
55
59
  if node.type == :def
56
- yield :def, @scope + [node.children[0]], node.source_map.expression.line
60
+ yield :defs, node.children[0],
61
+ line_no: node.location.expression.line,
62
+ scope: @scope
57
63
  elsif [:module, :class].include? node.type
58
- yield :def, @scope + scoped_name(node.children[0]), node.source_map.expression.line
64
+ fqn = @scope + scoped_name(node.children[0])
65
+ yield :defs, fqn.last, line_no: node.location.expression.line,
66
+ scope: fqn[0...-1]
59
67
  end
60
68
 
61
- if node.type == :cdecl
62
- yield :assign, scoped_name(node), node.source_map.expression.line
63
- elsif [:lvasgn, :ivasgn, :cvdecl, :cvasgn, :gvasgn].include? node.type
64
- yield :assign, @scope + [node.children[0]], node.source_map.expression.line
69
+ if node.type == :casgn
70
+ fqn = scoped_name(node)
71
+ yield :assigns, fqn.last, line_no: node.location.expression.line,
72
+ scope: fqn[0...-1]
73
+ elsif [:lvasgn, :ivasgn, :cvasgn, :gvasgn].include? node.type
74
+ yield :assigns, node.children[0],
75
+ line_no: node.location.expression.line,
76
+ scope: @scope
65
77
  end
66
78
  end
67
79
 
68
80
  def scoped_name(node)
69
81
  if node.type == :block
70
82
  scoped_name(node.children[0])
71
- elsif [:lvar, :ivar, :cvar, :gvar, :const, :send, :cdecl].include? node.type
83
+ elsif [:lvar, :ivar, :cvar, :gvar, :const, :send, :casgn].include? node.type
72
84
  if node.children[0].is_a? Symbol
73
85
  [node.children[0]]
74
86
  elsif node.children[0].is_a? AST::Node
@@ -1,3 +1,3 @@
1
1
  module StarScope
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
data/starscope.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
12
12
  gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
13
13
  gem.require_paths = ["lib"]
14
14
 
15
- gem.add_dependency 'parser', '~> 1.4'
15
+ gem.add_dependency 'parser', '= 2.0.0.pre2'
16
16
  gem.add_development_dependency 'bundler', '~> 1.3'
17
17
  gem.add_development_dependency 'rake'
18
18
  gem.add_development_dependency 'pry'
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: starscope
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.5
5
+ version: 0.0.6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Evan Huus
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-22 00:00:00.000000000 Z
12
+ date: 2013-07-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  prerelease: false
@@ -17,15 +17,15 @@ dependencies:
17
17
  type: :runtime
18
18
  version_requirements: !ruby/object:Gem::Requirement
19
19
  requirements:
20
- - - ~>
20
+ - - '='
21
21
  - !ruby/object:Gem::Version
22
- version: '1.4'
22
+ version: 2.0.0.pre2
23
23
  none: false
24
24
  requirement: !ruby/object:Gem::Requirement
25
25
  requirements:
26
- - - ~>
26
+ - - '='
27
27
  - !ruby/object:Gem::Version
28
- version: '1.4'
28
+ version: 2.0.0.pre2
29
29
  none: false
30
30
  - !ruby/object:Gem::Dependency
31
31
  prerelease: false
@@ -94,7 +94,7 @@ dependencies:
94
94
  description: A tool like the venerable cscope, but for ruby and other languages
95
95
  email: eapache@gmail.com
96
96
  executables:
97
- - starscope.rb
97
+ - starscope
98
98
  extensions: []
99
99
  extra_rdoc_files: []
100
100
  files:
@@ -105,7 +105,8 @@ files:
105
105
  - LICENSE.txt
106
106
  - README.md
107
107
  - Rakefile
108
- - bin/starscope.rb
108
+ - TODO.md
109
+ - bin/starscope
109
110
  - lib/starscope.rb
110
111
  - lib/starscope/datum.rb
111
112
  - lib/starscope/db.rb
@@ -125,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
126
  - !ruby/object:Gem::Version
126
127
  segments:
127
128
  - 0
128
- hash: -3682950058124738529
129
+ hash: -2937951633006975654
129
130
  version: '0'
130
131
  none: false
131
132
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -134,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
135
  - !ruby/object:Gem::Version
135
136
  segments:
136
137
  - 0
137
- hash: -3682950058124738529
138
+ hash: -2937951633006975654
138
139
  version: '0'
139
140
  none: false
140
141
  requirements: []