starscope 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .starscope.db
4
+ .bundle
5
+ .config
6
+ coverage
7
+ InstalledFiles
8
+ lib/bundler/man
9
+ pkg
10
+ rdoc
11
+ spec/reports
12
+ test/tmp
13
+ test/version_tmp
14
+ tmp
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,35 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ ast (1.0.2)
5
+ coderay (1.0.9)
6
+ columnize (0.3.6)
7
+ debugger (1.6.0)
8
+ columnize (>= 0.3.1)
9
+ debugger-linecache (~> 1.2.0)
10
+ debugger-ruby_core_source (~> 1.2.1)
11
+ debugger-linecache (1.2.0)
12
+ debugger-ruby_core_source (1.2.2)
13
+ method_source (0.8.1)
14
+ parser (1.4.1)
15
+ ast (~> 1.0)
16
+ slop (~> 3.4)
17
+ pry (0.9.12.2)
18
+ coderay (~> 1.0.5)
19
+ method_source (~> 0.8)
20
+ slop (~> 3.4)
21
+ pry-debugger (0.2.2)
22
+ debugger (~> 1.3)
23
+ pry (~> 0.9.10)
24
+ rake (10.0.4)
25
+ slop (3.4.5)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ bundler (~> 1.3)
32
+ parser
33
+ pry
34
+ pry-debugger
35
+ rake
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Evan Huus
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,11 @@
1
+ StarScope
2
+ =========
3
+
4
+ Anyone who has done much programming in C (or C++) on a unix-based OS has come
5
+ across the fantastic Cscope tool [1]. Sadly, it only works for C (and sort of
6
+ works for C++).
7
+
8
+ StarScope is a similar tool for Ruby, with a design intended to make it easy to
9
+ add support for other languages at some point within the same framework.
10
+
11
+ [1] http://cscope.sourceforge.net/
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/starscope.rb ADDED
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib = File.expand_path('../../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require 'optparse'
7
+ require "starscope"
8
+
9
+ options = {auto: true}
10
+ DEFAULT_DB=".starscope.db"
11
+
12
+ # Options Parsing
13
+ OptionParser.new do |opts|
14
+ opts.banner = "Usage: starscope.rb [options] [PATHS]"
15
+
16
+ opts.on("-d", "--dump [TABLE]", "Dumps the DB or specified table to standard-out") do |tbl|
17
+ options[:dump] = tbl || true
18
+ end
19
+
20
+ opts.on("-n", "--no-auto", "Don't automatically create or update the database") do
21
+ options[:auto] = false
22
+ end
23
+
24
+ opts.on("-q", "--query QUERY", "Queries the database") do |query|
25
+ options[:query] = query
26
+ end
27
+
28
+ opts.on("-r", "--read-db READ", "Reads the database from PATH instead of #{DEFAULT_DB}") do |path|
29
+ options[:read] = path
30
+ end
31
+
32
+ opts.on("-s", "--summary", "Print a database summary to standard-out") do
33
+ options[:summary] = true
34
+ end
35
+
36
+ opts.on("-w", "--write-db PATH", "Writes the database to PATH instead of #{DEFAULT_DB}") do |path|
37
+ options[:write] = path
38
+ end
39
+
40
+ end.parse!
41
+
42
+ # Load the database
43
+ db = StarScope::DB.new
44
+ new = true
45
+ if options[:read]
46
+ db.load(options[:read])
47
+ new = false
48
+ elsif File.exists?(DEFAULT_DB)
49
+ db.load(DEFAULT_DB)
50
+ new = false
51
+ end
52
+
53
+ if ARGV.empty?
54
+ db.add_dirs(['.']) if new
55
+ else
56
+ db.add_dirs(ARGV)
57
+ end
58
+
59
+ # Update it
60
+ db.update if options[:auto] and not new
61
+
62
+ # Write it
63
+ if options[:auto] || options[:write]
64
+ db.save(options[:write] || DEFAULT_DB)
65
+ end
66
+
67
+ if options[:query]
68
+ table, value = options[:query].split(',', 2)
69
+ db.query(table.to_sym, value)
70
+ end
71
+
72
+ if options[:summary]
73
+ db.print_summary
74
+ end
75
+
76
+ if options[:dump]
77
+ if options[:dump].is_a? String
78
+ db.dump_table(options[:dump].to_sym)
79
+ else
80
+ db.dump_all
81
+ end
82
+ end
data/lib/starscope.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "starscope/version"
2
+ require "starscope/db"
@@ -0,0 +1,40 @@
1
+ class StarScope::Datum
2
+ attr_reader :key, :scope, :file, :line
3
+
4
+ def initialize(fqn, file, line)
5
+ @key = fqn[-1].to_sym
6
+ @scope = fqn[0...-1].map {|x| x.to_sym}
7
+ @file = file
8
+ @line = line
9
+ end
10
+
11
+ def score_match(fqn)
12
+ score = 0
13
+
14
+ i = -1
15
+ fqn[0...-1].reverse.each do |test|
16
+ if test.to_sym == @scope[i]
17
+ score += 5
18
+ elsif Regexp.new(test).match(@scope[i])
19
+ score += 3
20
+ elsif Regexp.new(test, Regexp::IGNORECASE).match(@scope[i])
21
+ score += 1
22
+ end
23
+ i -= 1
24
+ end
25
+
26
+ score - @scope.count - i + 1
27
+ end
28
+
29
+ def location
30
+ "#{file}:#{line}"
31
+ end
32
+
33
+ def to_s
34
+ if @scope.empty?
35
+ "#{key} -- #{location}"
36
+ else
37
+ "#{@scope.join " "} #{@key} -- #{location}"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,126 @@
1
+ require 'starscope/langs/ruby'
2
+ require "starscope/datum"
3
+ require 'zlib'
4
+
5
+ LANGS = [StarScope::Lang::Ruby]
6
+
7
+ class StarScope::DB
8
+
9
+ def initialize
10
+ @dirs = []
11
+ @files = {}
12
+ @tables = {}
13
+ end
14
+
15
+ def load(file)
16
+ File.open(file, 'r') do |file|
17
+ Zlib::GzipReader.wrap(file) do |file|
18
+ raise "File version doesn't match" if StarScope::VERSION != file.gets.chomp
19
+ @dirs = load_part(file)
20
+ @files = load_part(file)
21
+ @tables = load_part(file)
22
+ end
23
+ end
24
+ end
25
+
26
+ def save(file)
27
+ File.open(file, 'w') do |file|
28
+ Zlib::GzipWriter.wrap(file) do |file|
29
+ file.puts StarScope::VERSION
30
+ save_part(file, @dirs)
31
+ save_part(file, @files)
32
+ save_part(file, @tables)
33
+ end
34
+ end
35
+ end
36
+
37
+ def add_dirs(dirs)
38
+ @dirs << dirs
39
+ dirs.each do |dir|
40
+ Dir["#{dir}/**/*"].each do |file|
41
+ add_file(file)
42
+ end
43
+ end
44
+ end
45
+
46
+ def update
47
+ @files.keys.each {|f| update_file(f)}
48
+ cur_files = @dirs.each {|d| Dir["#{d}/**/*"]}.flatten
49
+ (cur_files - @files.keys).each {|f| add_file(f)}
50
+ end
51
+
52
+ def dump_table(table)
53
+ puts "== Table: #{table} =="
54
+ @tables[table].each do |val, data|
55
+ puts "#{val}"
56
+ data.each do |datum|
57
+ print "\t"
58
+ puts datum
59
+ end
60
+ end
61
+ end
62
+
63
+ def dump_all
64
+ @tables.keys.each {|tbl| dump_table(tbl)}
65
+ end
66
+
67
+ def print_summary
68
+ @tables.each do |name, tbl|
69
+ puts "#{name} - #{tbl.keys.count} entries"
70
+ end
71
+ end
72
+
73
+ def query(table, value)
74
+ fqn = value.split("::")
75
+ results = @tables[table][fqn[-1].to_sym]
76
+ puts results.sort {|a,b| b.score_match(fqn) <=> a.score_match(fqn)}
77
+ end
78
+
79
+ private
80
+
81
+ def load_part(file)
82
+ len = file.gets.to_i
83
+ Marshal::load(file.read(len))
84
+ end
85
+
86
+ def save_part(file, val)
87
+ dat = Marshal.dump(val)
88
+ file.puts dat.length
89
+ file.write dat
90
+ end
91
+
92
+ def add_file(file)
93
+ return if not File.file? file
94
+
95
+ @files[file] = File.mtime(file)
96
+
97
+ LANGS.each do |lang|
98
+ next if not lang.match_file file
99
+ lang.extract file do |tblname, fqn, lineno|
100
+ datum = StarScope::Datum.new(fqn, file, lineno)
101
+ @tables[tblname] ||= {}
102
+ @tables[tblname][datum.key] ||= []
103
+ @tables[tblname][datum.key] << datum
104
+ end
105
+ end
106
+ end
107
+
108
+ def remove_file(file)
109
+ @files.delete(file)
110
+ @tables.each do |name, tbl|
111
+ tbl.each do |key, val|
112
+ val.delete_if {|dat| dat.file == file}
113
+ end
114
+ end
115
+ end
116
+
117
+ def update_file(file)
118
+ if not File.exists?(file)
119
+ remove_file(file)
120
+ elsif @files[file] < File.mtime(file)
121
+ remove_file(file)
122
+ add_file(file)
123
+ end
124
+ end
125
+
126
+ end
@@ -0,0 +1,89 @@
1
+ require "parser/current"
2
+
3
+ module StarScope::Lang
4
+ module Ruby
5
+ def self.match_file(name)
6
+ name =~ /.*\.rb/
7
+ end
8
+
9
+ def self.extract(file, &block)
10
+ begin
11
+ ast = Parser::CurrentRuby.parse_file(file)
12
+ rescue
13
+ else
14
+ Extractor.new(ast).extract &block
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ class Extractor
21
+ def initialize(ast)
22
+ @ast = ast
23
+ @scope = []
24
+ end
25
+
26
+ def extract(&block)
27
+ extract_tree(@ast, &block)
28
+ end
29
+
30
+ private
31
+
32
+ def extract_tree(tree, &block)
33
+ extract_node tree, &block
34
+
35
+ new_scope = []
36
+ if [:class, :module].include? tree.type
37
+ new_scope = scoped_name(tree.children[0])
38
+ @scope += new_scope
39
+ end
40
+
41
+ tree.children.each {|node| extract_tree node, &block if node.is_a? AST::Node}
42
+
43
+ @scope.pop(new_scope.count)
44
+ end
45
+
46
+ def extract_node(node)
47
+ if node.type == :send
48
+ yield :calls, scoped_name(node), node.source_map.expression.line
49
+
50
+ if node.children[0].nil? and node.children[1] == :require and node.children[2].type == :str
51
+ yield :includes, node.children[2].children[0].split("/"), node.source_map.expression.line
52
+ end
53
+ end
54
+
55
+ if node.type == :def
56
+ yield :def, @scope + [node.children[0]], node.source_map.expression.line
57
+ elsif [:module, :class].include? node.type
58
+ yield :def, @scope + scoped_name(node.children[0]), node.source_map.expression.line
59
+ end
60
+
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
65
+ end
66
+ end
67
+
68
+ def scoped_name(node)
69
+ if node.type == :block
70
+ scoped_name(node.children[0])
71
+ elsif [:lvar, :ivar, :cvar, :gvar, :const, :send, :cdecl].include? node.type
72
+ if node.children[0].is_a? Symbol
73
+ [node.children[0]]
74
+ elsif node.children[0].is_a? AST::Node
75
+ scoped_name(node.children[0]) << node.children[1]
76
+ elsif node.children[0].nil?
77
+ if node.type == :const
78
+ [node.children[1]]
79
+ else
80
+ @scope + [node.children[1]]
81
+ end
82
+ end
83
+ else
84
+ [node.type]
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,7 @@
1
+ class StarScope::Value
2
+ attr_reader :simple
3
+
4
+ def initialize(simple)
5
+ @simple = simple
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module StarScope
2
+ VERSION = "0.0.1"
3
+ end
data/starscope.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require 'starscope/version.rb'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'starscope'
8
+ s.version = StarScope::VERSION
9
+ s.date = '2013-06-07'
10
+ s.summary = "A code indexer and analyzer"
11
+ s.description = "A tool like the venerable cscope, but for ruby and other languages"
12
+ s.authors = ["Evan Huus"]
13
+ s.homepage = 'https://github.com/eapache/starscope'
14
+ s.email = 'evan.huus@jadedpixel.com'
15
+ s.files = `git ls-files`.split("\n")
16
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.require_paths = ["lib"]
18
+
19
+ s.add_dependency 'parser'
20
+ s.add_development_dependency 'bundler', '~> 1.3'
21
+ s.add_development_dependency 'rake'
22
+ s.add_development_dependency 'pry'
23
+ s.add_development_dependency 'pry-debugger'
24
+ end
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: starscope
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Evan Huus
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-06-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ none: false
21
+ name: parser
22
+ type: :runtime
23
+ prerelease: false
24
+ requirement: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ! '>='
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: '1.3'
36
+ none: false
37
+ name: bundler
38
+ type: :development
39
+ prerelease: false
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: '1.3'
45
+ none: false
46
+ - !ruby/object:Gem::Dependency
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ none: false
53
+ name: rake
54
+ type: :development
55
+ prerelease: false
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ none: false
62
+ - !ruby/object:Gem::Dependency
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ none: false
69
+ name: pry
70
+ type: :development
71
+ prerelease: false
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ none: false
78
+ - !ruby/object:Gem::Dependency
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ none: false
85
+ name: pry-debugger
86
+ type: :development
87
+ prerelease: false
88
+ requirement: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ none: false
94
+ description: A tool like the venerable cscope, but for ruby and other languages
95
+ email: evan.huus@jadedpixel.com
96
+ executables:
97
+ - starscope.rb
98
+ extensions: []
99
+ extra_rdoc_files: []
100
+ files:
101
+ - .gitignore
102
+ - Gemfile
103
+ - Gemfile.lock
104
+ - LICENSE.txt
105
+ - README.md
106
+ - Rakefile
107
+ - bin/starscope.rb
108
+ - lib/starscope.rb
109
+ - lib/starscope/datum.rb
110
+ - lib/starscope/db.rb
111
+ - lib/starscope/langs/ruby.rb
112
+ - lib/starscope/value.rb
113
+ - lib/starscope/version.rb
114
+ - starscope.gemspec
115
+ homepage: https://github.com/eapache/starscope
116
+ licenses: []
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ none: false
127
+ required_rubygems_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ! '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ none: false
133
+ requirements: []
134
+ rubyforge_project:
135
+ rubygems_version: 1.8.23
136
+ signing_key:
137
+ specification_version: 3
138
+ summary: A code indexer and analyzer
139
+ test_files: []