starscope 1.4.1 → 1.5.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.
@@ -0,0 +1,114 @@
1
+ require 'rkelly'
2
+ require 'babel/transpiler'
3
+ require 'sourcemap'
4
+
5
+ module Starscope::Lang
6
+ module Javascript
7
+ VERSION = 0
8
+
9
+ def self.match_file(name)
10
+ name.end_with?('.js')
11
+ end
12
+
13
+ def self.extract(path, contents, &block)
14
+ transform = Babel::Transpiler.transform(contents,
15
+ 'stage' => 0,
16
+ 'blacklist' => ['validation.react'],
17
+ 'externalHelpers' => true,
18
+ 'compact' => false,
19
+ 'sourceMaps' => true)
20
+ map = SourceMap::Map.from_hash(transform['map'])
21
+ ast = RKelly::Parser.new.parse(transform['code'])
22
+ lines = contents.lines.to_a
23
+
24
+ return unless ast
25
+
26
+ found = extract_methods(ast, map, lines, &block)
27
+
28
+ found = extract_var_decls(ast, map, lines, found, &block)
29
+
30
+ extract_var_reads(ast, map, lines, found, &block)
31
+ end
32
+
33
+ def self.extract_methods(ast, map, lines, &block)
34
+ found = {}
35
+
36
+ ast.each do |node|
37
+ case node
38
+ when RKelly::Nodes::FunctionExprNode, RKelly::Nodes::FunctionDeclNode
39
+ line = find_line(node.range.from, map, lines, node.value)
40
+ next unless line
41
+
42
+ type = :func
43
+ type = :class if lines[line - 1].include?("class #{node.value}")
44
+
45
+ yield :defs, node.value, line_no: line, type: type
46
+ found[node.value] ||= Set.new
47
+ found[node.value].add(line)
48
+
49
+ next if type == :class
50
+
51
+ mapping = map.bsearch(SourceMap::Offset.new(node.range.to.line, node.range.to.char))
52
+ yield :end, :'}', line_no: mapping.original.line, type: type
53
+ when RKelly::Nodes::FunctionCallNode
54
+ name = node_name(node.value)
55
+ next unless name
56
+
57
+ line = find_line(node.range.from, map, lines, name)
58
+ next unless line
59
+
60
+ yield :calls, name, line_no: line
61
+ found[name] ||= Set.new
62
+ found[name].add(line)
63
+ end
64
+ end
65
+
66
+ found
67
+ end
68
+
69
+ def self.extract_var_decls(ast, map, lines, found, &block)
70
+ ast.each do |node|
71
+ next unless node.is_a? RKelly::Nodes::VarDeclNode
72
+
73
+ line = find_line(node.range.from, map, lines, node.name)
74
+ next unless line
75
+
76
+ next if found[node.name] && found[node.name].include?(line)
77
+ yield :defs, node.name, line_no: line
78
+ found[node.name] ||= Set.new
79
+ found[node.name].add(line)
80
+ end
81
+
82
+ found
83
+ end
84
+
85
+ def self.extract_var_reads(ast, map, lines, found, &block)
86
+ ast.each do |node|
87
+ name = node_name(node)
88
+ next unless name
89
+
90
+ line = find_line(node.range.from, map, lines, name)
91
+ next unless line
92
+
93
+ next if found[name] && found[name].include?(line)
94
+ yield :reads, name, line_no: line
95
+ end
96
+ end
97
+
98
+ def self.node_name(node)
99
+ case node
100
+ when RKelly::Nodes::DotAccessorNode
101
+ node.accessor
102
+ when RKelly::Nodes::ResolveNode
103
+ node.value
104
+ end
105
+ end
106
+
107
+ def self.find_line(from, map, lines, name)
108
+ mapping = map.bsearch(SourceMap::Offset.new(from.line, from.char))
109
+ return unless mapping
110
+ return unless lines[mapping.original.line - 1].include? name
111
+ mapping.original.line
112
+ end
113
+ end
114
+ end
@@ -18,8 +18,6 @@ module Starscope::Lang
18
18
  extract_tree(ast, [], &block) unless ast.nil?
19
19
  end
20
20
 
21
- private
22
-
23
21
  def self.extract_tree(tree, scope, &block)
24
22
  extract_node(tree, scope, &block)
25
23
 
@@ -40,45 +38,45 @@ module Starscope::Lang
40
38
  case node.type
41
39
  when :send
42
40
  name = scoped_name(node, scope)
43
- yield :calls, name, :line_no => loc.line, :col => loc.column
41
+ yield :calls, name, line_no: loc.line, col: loc.column
44
42
 
45
- if name.last.to_s =~ /\w+=$/
43
+ if name.last =~ /\w+=$/
46
44
  name[-1] = name.last.to_s.chop.to_sym
47
- yield :assigns, name, :line_no => loc.line, :col => loc.column
45
+ yield :assigns, name, line_no: loc.line, col: loc.column
48
46
  elsif node.children[0].nil? && node.children[1] == :require && node.children[2].type == :str
49
47
  yield :requires, node.children[2].children[0].split('/'),
50
- :line_no => loc.line, :col => loc.column
48
+ line_no: loc.line, col: loc.column
51
49
  end
52
50
 
53
51
  when :def
54
52
  yield :defs, scope + [node.children[0]],
55
- :line_no => loc.line, :type => :func, :col => loc.name.column
56
- yield :end, :end, :line_no => loc.end.line, :type => :func, :col => loc.end.column
53
+ line_no: loc.line, type: :func, col: loc.name.column
54
+ yield :end, :end, line_no: loc.end.line, type: :func, col: loc.end.column
57
55
 
58
56
  when :defs
59
57
  yield :defs, scope + [node.children[1]],
60
- :line_no => loc.line, :type => :func, :col => loc.name.column
61
- yield :end, :end, :line_no => loc.end.line, :type => :func, :col => loc.end.column
58
+ line_no: loc.line, type: :func, col: loc.name.column
59
+ yield :end, :end, line_no: loc.end.line, type: :func, col: loc.end.column
62
60
 
63
61
  when :module, :class
64
62
  yield :defs, scope + scoped_name(node.children[0], scope),
65
- :line_no => loc.line, :type => node.type, :col => loc.name.column
66
- yield :end, :end, :line_no => loc.end.line, :type => node.type, :col => loc.end.column
63
+ line_no: loc.line, type: node.type, col: loc.name.column
64
+ yield :end, :end, line_no: loc.end.line, type: node.type, col: loc.end.column
67
65
 
68
66
  when :casgn
69
67
  name = scoped_name(node, scope)
70
- yield :assigns, name, :line_no => loc.line, :col => loc.name.column
71
- yield :defs, name, :line_no => loc.line, :col => loc.name.column
68
+ yield :assigns, name, line_no: loc.line, col: loc.name.column
69
+ yield :defs, name, line_no: loc.line, col: loc.name.column
72
70
 
73
71
  when :lvasgn, :ivasgn, :cvasgn, :gvasgn
74
- yield :assigns, scope + [node.children[0]], :line_no => loc.line, :col => loc.name.column
72
+ yield :assigns, scope + [node.children[0]], line_no: loc.line, col: loc.name.column
75
73
 
76
74
  when :const
77
75
  name = scoped_name(node, scope)
78
- yield :reads, name, :line_no => loc.line, :col => loc.name.column
76
+ yield :reads, name, line_no: loc.line, col: loc.name.column
79
77
 
80
78
  when :lvar, :ivar, :cvar, :gvar
81
- yield :reads, scope + [node.children[0]], :line_no => loc.line, :col => loc.name.column
79
+ yield :reads, scope + [node.children[0]], line_no: loc.line, col: loc.name.column
82
80
 
83
81
  when :sym
84
82
  # handle `:foo` vs `foo: 1`
@@ -87,7 +85,7 @@ module Starscope::Lang
87
85
  else
88
86
  loc.expression.column
89
87
  end
90
- yield :sym, [node.children[0]], :line_no => loc.line, :col => col
88
+ yield :sym, [node.children[0]], line_no: loc.line, col: col
91
89
  end
92
90
  end
93
91
 
@@ -11,9 +11,9 @@ class Starscope::Output
11
11
 
12
12
  def new_pbar(title, num_items)
13
13
  return if @level == :quiet
14
- @pbar = ProgressBar.create(:title => title, :total => num_items,
15
- :format => PBAR_FORMAT, :length => 80,
16
- :out => @out)
14
+ @pbar = ProgressBar.create(title: title, total: num_items,
15
+ format: PBAR_FORMAT, length: 80,
16
+ out: @out)
17
17
  end
18
18
 
19
19
  def inc_pbar
@@ -1,3 +1,3 @@
1
1
  module Starscope
2
- VERSION = '1.4.1'
2
+ VERSION = '1.5.0'
3
3
  end
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
5
5
  gem.version = Starscope::VERSION
6
6
  gem.summary = 'Smart code search and indexing'
7
7
  gem.description = <<-EOF
8
- Starscope is a code indexer, search and navigation tool for Ruby and Go.
8
+ Starscope is a code indexer, search and navigation tool for Ruby, Golang, and JavaScript.
9
9
  Inspired by the extremely popular Ctags and Cscope utilities, Starscope can
10
10
  answer a lot of questions about a lot of code.
11
11
  EOF
@@ -17,15 +17,18 @@ Gem::Specification.new do |gem|
17
17
  gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
18
  gem.test_files = `git ls-files -- test/*`.split("\n")
19
19
  gem.require_paths = ['lib']
20
- gem.required_ruby_version = '>= 1.8.7'
20
+ gem.required_ruby_version = '>= 1.9.3'
21
21
 
22
22
  gem.add_dependency 'oj', '~> 2.9'
23
23
  gem.add_dependency 'parser', '~> 2.2.2'
24
24
  gem.add_dependency 'ruby-progressbar', '~> 1.5'
25
- gem.add_dependency 'backports', '~> 3.6'
26
- gem.add_development_dependency 'bundler', '~> 1.5'
27
- gem.add_development_dependency 'rake'
28
- gem.add_development_dependency 'pry'
29
- gem.add_development_dependency 'minitest'
30
- gem.add_development_dependency 'mocha'
25
+ gem.add_dependency 'rkelly-remix', '~> 0.0.7'
26
+ gem.add_dependency 'babel-transpiler', '~> 0.7'
27
+ gem.add_dependency 'sourcemap', '~> 0.1'
28
+
29
+ gem.add_development_dependency 'bundler', '~> 1.7'
30
+ gem.add_development_dependency 'rake', '~> 10.4'
31
+ gem.add_development_dependency 'pry', '~> 0.10.1'
32
+ gem.add_development_dependency 'minitest', '~> 5.8'
33
+ gem.add_development_dependency 'mocha', '~> 1.1'
31
34
  end
@@ -0,0 +1,117 @@
1
+ /* @flow */
2
+
3
+ import React from 'react-native';
4
+
5
+ var {
6
+ Component,
7
+ StyleSheet,
8
+ } = React;
9
+
10
+ var {NavigationBar} = Navigator;
11
+
12
+ var styles = StyleSheet.create({
13
+ navigatorBar: {
14
+ height: NavigationBar.Styles.General.NavBarHeight,
15
+ justifyContent: 'center',
16
+ alignItems: 'center',
17
+ },
18
+ });
19
+
20
+ var func1 = () => {
21
+ return 1;
22
+ };
23
+
24
+ function foo() {
25
+ return bar;
26
+ }
27
+
28
+ StatusBarIOS.setStyle(1);
29
+ Router.routes = routes;
30
+
31
+ class MyStat {
32
+ static myStatFunc(
33
+ title
34
+ ): void {
35
+ }
36
+ }
37
+
38
+ var NavigatorRouteMapper = {
39
+ LeftButton({route}, navigator, index) {
40
+ if (!index) { return null; } // Nothing below in stack.
41
+
42
+ return (
43
+ <TouchableOpacity onPress={() => navigator.pop()}>
44
+ <Text style={{color: 'white', fontSize: 12, marginLeft: 1}}>‹</Text>
45
+ </TouchableOpacity>
46
+ );
47
+ },
48
+
49
+ RightButton() {
50
+ return null;
51
+ },
52
+ };
53
+
54
+ class Navigation extends Component {
55
+ constructor(props) {
56
+ super(props);
57
+ this.state = {key: 'foo', selectedTab: 'foo'};
58
+ func1();
59
+
60
+ }
61
+
62
+ _tabItem(routeName: string, params: Object, badgeCount?: number) : PropTypes.element {
63
+ var route = routes[routeName];
64
+
65
+ var onTabPress = () => {
66
+ if (this.state.selectedTab === routeName) {
67
+ if (route === Router.currentRoute) {
68
+ Router.navigator._currentQueryFetcherRoot.fetchData();
69
+ } else {
70
+ Router.popToTop();
71
+ }
72
+ } else {
73
+ this.setState({selectedTab: routeName});
74
+ }
75
+ };
76
+
77
+ return (
78
+ <TabBarIOS.Item
79
+ badge={badgeCount}
80
+ selected={this.state.selectedTab === routeName}
81
+ onPress={onTabPress}
82
+ >
83
+ <Navigator
84
+ ref={::this._setCurrentNavigator}
85
+ navigationBar={
86
+ <NavigationBar routeMapper={NavigatorRouteMapper} style={{backgroundColor: Branding.pink}} />
87
+ }
88
+ />
89
+
90
+ </TabBarIOS.Item>
91
+ );
92
+ }
93
+
94
+ _setCurrentNavigator(nav) {
95
+ Router.navigator = nav;
96
+ }
97
+
98
+ _renderTabScene({route, params}, nav) {
99
+ var setRef = (ref) => {
100
+ nav._currentQueryFetcherRoot = ref;
101
+ };
102
+
103
+ return <QueryFetcherRoot ref={setRef} component={route.component} route={route} params={params} />;
104
+ }
105
+
106
+ render() {
107
+ return (
108
+ <TabBarIOS tintColor={Branding.yellow} barTintColor={Branding.green}>
109
+ {this._tabItem('foo', {})}
110
+ {this._tabItem('bar', {})}
111
+ {this._tabItem('baz', {})}
112
+ </TabBarIOS>
113
+ );
114
+ }
115
+ }
116
+
117
+ export default Navigation;
@@ -26,7 +26,7 @@ class Starscope::DB
26
26
  if format == DB_FORMAT
27
27
  @paths = Oj.load(stream.gets)
28
28
  @files = Oj.load(stream.gets)
29
- @tables = Oj.load(stream.gets, :symbol_keys => true)
29
+ @tables = Oj.load(stream.gets, symbol_keys: true)
30
30
  elsif format <= 2
31
31
  # Old format (pre-json), so read the directories segment then rebuild
32
32
  len = stream.gets.to_i
@@ -59,7 +59,7 @@ class Starscope::DB
59
59
  files = paths.map { |p| self.class.files_from_path(p) }.flatten
60
60
  return if files.empty?
61
61
  if @progress
62
- pbar = ProgressBar.create(:title => 'Building', :total => files.length, :format => PBAR_FORMAT, :length => 80)
62
+ pbar = ProgressBar.create(title: 'Building', total: files.length, format: PBAR_FORMAT, length: 80)
63
63
  end
64
64
  files.each do |f|
65
65
  add_file(f)
@@ -70,7 +70,7 @@ class Starscope::DB
70
70
  def update
71
71
  new_files = (@paths.map { |p| self.class.files_from_path(p) }.flatten) - @files.keys
72
72
  if @progress
73
- pbar = ProgressBar.create(:title => 'Updating', :total => new_files.length + @files.length, :format => PBAR_FORMAT, :length => 80)
73
+ pbar = ProgressBar.create(title: 'Updating', total: new_files.length + @files.length, format: PBAR_FORMAT, length: 80)
74
74
  end
75
75
  changed = @files.keys.map do |f|
76
76
  changed = update_file(f)
@@ -114,7 +114,7 @@ class Starscope::DB
114
114
  if entry[:line_no]
115
115
  tmpdb[entry[:file]] ||= {}
116
116
  tmpdb[entry[:file]][entry[:line_no]] ||= []
117
- tmpdb[entry[:file]][entry[:line_no]] << { :tbl => tbl, :key => key, :entry => entry }
117
+ tmpdb[entry[:file]][entry[:line_no]] << { tbl: tbl, key: key, entry: entry }
118
118
  end
119
119
  end
120
120
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe 'starscope executable script' do
4
4
  BASE = 'bundle exec bin/starscope --quiet'
@@ -1,11 +1,12 @@
1
1
  require 'minitest/autorun'
2
2
  require 'minitest/pride'
3
3
  require 'mocha/mini_test'
4
- require File.expand_path('../../lib/starscope.rb', __FILE__)
4
+ require_relative '../lib/starscope'
5
5
 
6
6
  FIXTURES = 'test/fixtures'
7
7
 
8
8
  GOLANG_SAMPLE = "#{FIXTURES}/sample_golang.go"
9
+ JAVASCRIPT_EXAMPLE = "#{FIXTURES}/sample_javascript.js"
9
10
  RUBY_SAMPLE = "#{FIXTURES}/sample_ruby.rb"
10
11
  ERB_SAMPLE = "#{FIXTURES}/sample_erb.erb"
11
12
  EMPTY_FILE = "#{FIXTURES}/empty"
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ require_relative '../test_helper'
2
2
  require 'tempfile'
3
3
 
4
4
  describe Starscope::DB do
@@ -144,7 +144,7 @@ describe Starscope::DB do
144
144
  it 'must run queries on multiple tables' do
145
145
  @db.add_paths([FIXTURES])
146
146
  ret = @db.query([:calls, :defs], 'foo')
147
- ret.length.must_equal 3
147
+ ret.length.must_equal 4
148
148
  ret.first[:name].last.must_equal :foo
149
149
  end
150
150
 
@@ -161,7 +161,7 @@ describe Starscope::DB do
161
161
  it 'must store extractor metadata returned from the `extract` call' do
162
162
  extractor = mock('extractor')
163
163
  extractor.expects(:match_file).with(GOLANG_SAMPLE).returns(true)
164
- extractor.expects(:extract).with(GOLANG_SAMPLE, File.read(GOLANG_SAMPLE)).returns(:a => 1)
164
+ extractor.expects(:extract).with(GOLANG_SAMPLE, File.read(GOLANG_SAMPLE)).returns(a: 1)
165
165
  extractor.expects(:name).returns('Foo')
166
166
  EXTRACTORS.stubs(:each).yields(extractor)
167
167
 
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ require_relative '../test_helper'
2
2
 
3
3
  describe Starscope::Exportable do
4
4
  before do
@@ -10,14 +10,14 @@ describe Starscope::Exportable do
10
10
  it 'must export to ctags' do
11
11
  @db.export_to(:ctags, @buf)
12
12
  @buf.rewind
13
- lines = @buf.lines.to_a
13
+ lines = @buf.each_line.to_a
14
14
  lines.must_include "NoTableError\t#{FIXTURES}/sample_ruby.rb\t/^ class NoTableError < StandardError; end$/;\"\tkind:c\tlanguage:Ruby\n"
15
15
  end
16
16
 
17
17
  it 'must export to cscope' do
18
18
  @db.export_to(:cscope, @buf)
19
19
  @buf.rewind
20
- lines = @buf.lines.to_a
20
+ lines = @buf.each_line.to_a
21
21
 
22
22
  lines.must_include "\t@#{FIXTURES}/sample_golang.go\n"
23
23
  lines.must_include "\tgSunday\n"