ruby-debug-base 0.10.4-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2007-2008, debug-commons team
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README ADDED
@@ -0,0 +1,61 @@
1
+ = ruby-debug-base for JRuby
2
+
3
+ == Overview
4
+
5
+ (j)ruby-debug-base provides the fast debugger extension for JRuby interpreter.
6
+ It is the same as ruby-debug-base native C extension from ruby-debug project
7
+ (http://rubyforge.org/projects/ruby-debug/), but for JRuby.
8
+
9
+ == Install
10
+
11
+ (j)ruby-debug-base is available as a RubyGem. Unfortunately it is still not
12
+ installable remotely. But installation is easy enough:
13
+
14
+ - manually download the ruby-debug-base-0.10.3-java.gem to local directory from
15
+ here: http://rubyforge.org/frs/?group_id=3085
16
+
17
+ - install the Gem into your JRuby Gem repository:
18
+
19
+ jruby -S gem install ruby-debug-base-0.10.3-java.gem
20
+
21
+ - now install ruby-debug with:
22
+
23
+ jruby -S gem install --ignore-dependencies ruby-debug
24
+
25
+ See also: http://wiki.jruby.org/wiki/Using_the_JRuby_Debugger
26
+
27
+ == Installation of trunk version
28
+
29
+ Handy for developers or users living on the cutting-edge.
30
+
31
+ $ cd ~/tmp
32
+ $ svn co svn://rubyforge.org/var/svn/debug-commons/jruby-debug/trunk jruby-debug
33
+ $ cd jruby-debug
34
+ $ rake gem
35
+ $ jruby -S gem install -l pkg/ruby-debug-base-0.10.3-java.gem
36
+ $ jruby -S gem install columnize
37
+ $ jruby -S gem install -r ruby-debug -v 0.10.3 --ignore-dependencies
38
+
39
+ == Usage
40
+
41
+ The usage is then the same as with native ruby-debugger, but you might need to
42
+ force JRuby which has to run in interpreted mode. Simplest usage is:
43
+
44
+ $ jruby --debug -S rdebug <your-script>
45
+
46
+ Or easier, you might create 'jruby-dm' ('dm' for 'debugger-mode'):
47
+
48
+ $ cat ~/bin/jruby-dm
49
+ #!/bin/bash
50
+ jruby --debug "$@"
51
+
52
+ Then you may run just as you used to:
53
+
54
+ $ jruby-dm -S rdebug <your-script>
55
+
56
+ For more information see: http://bashdb.sourceforge.net/ruby-debug.html
57
+
58
+ == License
59
+
60
+ See MIT-LICENSE for license information.
61
+
@@ -0,0 +1,174 @@
1
+ require 'rake'
2
+ require 'rubygems'
3
+ require 'rake/clean'
4
+ require 'rake/gempackagetask'
5
+ require 'rake/testtask'
6
+ require 'rake/rdoctask'
7
+
8
+ GEM_NAME='ruby-debug-base'
9
+ GEM_VERSION='0.10.4'
10
+
11
+ RUBY_DEBUG_JAR='ext/ruby_debug.jar'
12
+
13
+ CLEAN.include('ext')
14
+ CLEAN.include('lib/ruby_debug.jar')
15
+
16
+ DIST_FILES = FileList[
17
+ 'AUTHORS',
18
+ 'ChangeLog',
19
+ 'lib/linecache.rb',
20
+ 'lib/linecache-ruby.rb',
21
+ 'lib/ruby-debug-base.rb',
22
+ 'lib/ruby_debug.jar',
23
+ 'lib/tracelines.rb',
24
+ 'MIT-LICENSE',
25
+ 'Rakefile',
26
+ 'README'
27
+ ]
28
+
29
+ BASE_TEST_FILE_LIST = %w(
30
+ test/base/base.rb
31
+ test/base/binding.rb
32
+ test/base/catchpoint.rb)
33
+
34
+ task :default => :package
35
+
36
+ CLI_TEST_FILE_LIST = 'test/test-*.rb'
37
+
38
+ desc "Test ruby-debug-base."
39
+ task :test_base => :lib do
40
+ Rake::TestTask.new(:test_base) do |t|
41
+ t.libs << './ext'
42
+ t.libs << './lib'
43
+ t.test_files = FileList[BASE_TEST_FILE_LIST]
44
+ t.verbose = true
45
+ end
46
+ end
47
+
48
+ desc "Test everything."
49
+ task :test => :test_base do
50
+ Rake::TestTask.new(:test) do |t|
51
+ t.libs << './ext'
52
+ t.libs << './lib'
53
+ t.libs << './cli'
54
+ t.pattern = CLI_TEST_FILE_LIST
55
+ t.verbose = true
56
+ end
57
+ end
58
+
59
+ desc "Helps to setup the project to be able to run tests"
60
+ task :prepare_tests do
61
+ # needed to run CLI test. Unable to use svn:externals yet:
62
+ # http://subversion.tigris.org/issues/show_bug.cgi?id=937
63
+
64
+ # rdbg.rb
65
+ sh "svn cat svn://rubyforge.org/var/svn/ruby-debug/tags/ruby-debug-#{GEM_VERSION}/rdbg.rb > rdbg.rb" unless File.exists?('rdbg.rb')
66
+
67
+ # runner.sh
68
+ runner = 'runner.sh'
69
+ sh "svn cat svn://rubyforge.org/var/svn/ruby-debug/tags/ruby-debug-#{GEM_VERSION}/runner.sh > #{runner}" unless File.exists?(runner)
70
+ text = File.read('runner.sh')
71
+ File.open(runner, 'w') {|f| f.write(text.gsub(/-ruby/ , '-jruby --debug'))}
72
+ File.chmod(0755, runner)
73
+
74
+ File.open('test/config.private.yaml', 'w') do |f|
75
+ f.write <<EOF
76
+ # either should be on the $PATH or use full path
77
+ ruby: jruby
78
+
79
+ # possibility to specify interpreter parameters
80
+ ruby_params: --debug
81
+ EOF
82
+ end
83
+
84
+ # - prepare default customized test/config.private.yaml suitable for JRuby
85
+ # - tweak test suite to be able to pass for jruby-debug-base which does not
86
+ # support e.g. TraceLineNumbers yet.
87
+ sh "patch -p0 < patch-#{GEM_VERSION}.diff"
88
+ end
89
+
90
+ desc "Create the core ruby-debug shared library extension"
91
+ task :lib do
92
+ compile_java
93
+ make_jar
94
+ end
95
+
96
+ file RUBY_DEBUG_JAR => :lib
97
+
98
+ spec = Gem::Specification.new do |s|
99
+ s.platform = "java"
100
+ s.summary = "Java implementation of Fast Ruby Debugger"
101
+ s.name = GEM_NAME
102
+ s.version = GEM_VERSION
103
+ s.require_path = 'lib'
104
+ s.files = DIST_FILES
105
+ s.description = <<-EOF
106
+ Java extension to make fast ruby debugger run on JRuby.
107
+ It is the same what ruby-debug-base is for native Ruby.
108
+ EOF
109
+ s.author = 'debug-commons team'
110
+ s.homepage = 'http://rubyforge.org/projects/debug-commons/'
111
+ s.has_rdoc = true
112
+ s.rubyforge_project = 'debug-commons'
113
+ end
114
+
115
+ gem_name = "#{GEM_NAME}-#{GEM_VERSION}-#{spec.platform}.gem"
116
+
117
+ desc "Build the gem file #{gem_name}"
118
+ task :gem => :lib do
119
+ gem_task = Rake::GemPackageTask.new(spec)
120
+ current_dir = File.expand_path(File.dirname(__FILE__))
121
+ source = File.join(current_dir, RUBY_DEBUG_JAR)
122
+ target = File.join(current_dir, "lib", "ruby_debug.jar")
123
+ cp(source, target)
124
+ # Create the gem, then move it to pkg.
125
+ Gem::Builder.new(spec).build
126
+ gem_file = "#{spec.name}-#{spec.version}-#{spec.platform}.gem"
127
+ mv(gem_task.gem_file, "pkg/#{gem_task.gem_file}")
128
+ # Delete the temporary target
129
+ rm target
130
+ end
131
+
132
+ desc 'Build all the packages'
133
+ task :package => :gem
134
+
135
+ Rake::RDocTask.new do |t|
136
+ t.main = 'README'
137
+ t.rdoc_files.include 'README'
138
+ end
139
+
140
+
141
+ desc "Create a GNU-style ChangeLog via svn2cl"
142
+ task :ChangeLog do
143
+ system("svn2cl --authors=svn2cl_usermap svn://rubyforge.org/var/svn/debug-commons/jruby-debug/trunk")
144
+ end
145
+
146
+ # Builds classpath containing needed JRuby's jars (like jruby.jar).
147
+ def jruby_classpath
148
+ begin
149
+ require 'java'
150
+ classpath = java.lang.System.getProperty('java.class.path')
151
+ rescue LoadError
152
+ end
153
+
154
+ unless classpath
155
+ classpath = FileList["#{ENV['JRUBY_HOME']}/lib/*.jar"].join(File::PATH_SEPARATOR)
156
+ end
157
+
158
+ classpath ? "-cp #{classpath}" : ""
159
+ end
160
+
161
+ # Compiles Java classes into the pkg/classes directory.
162
+ def compile_java
163
+ mkdir_p "pkg/classes"
164
+ sh "javac -Xlint -Xlint:-serial -g -target 1.5 -source 1.5 -d pkg/classes #{jruby_classpath} #{FileList['src/**/*.java'].join(' ')}"
165
+ end
166
+
167
+ def make_jar
168
+ require 'fileutils'
169
+ ext = File.join(File.dirname(__FILE__), 'ext')
170
+ FileUtils.mkdir_p(ext)
171
+ separator = File::ALT_SEPARATOR || File::SEPARATOR
172
+ sh "jar cf #{RUBY_DEBUG_JAR} -C pkg#{separator}classes ."
173
+ end
174
+
@@ -0,0 +1,12 @@
1
+ # Provides alternative to native TraceLineNumbers.lnums_for_str implemented
2
+ # currently only for C Ruby in linecache gem, ext/trace_nums.c
3
+
4
+ module TraceLineNumbers
5
+
6
+ # Trivial implementation allowing to stop on every line.
7
+ def lnums_for_str(code)
8
+ (1..code.entries.size).to_a
9
+ end
10
+ module_function :lnums_for_str
11
+
12
+ end
@@ -0,0 +1,408 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Temporary solution. Copy-pasted from rocky-hacks/linecache project.
4
+ # Will/should be solved generally in the future.
5
+
6
+ # Copyright (C) 2007, 2008 Rocky Bernstein <rockyb@rubyforge.net>
7
+ #
8
+ # This program is free software; you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation; either version 2 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program; if not, write to the Free Software
20
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
+ # 02110-1301 USA.
22
+ #
23
+
24
+ # Author:: Rocky Bernstein (mailto:rockyb@rubyforge.net)
25
+ #
26
+ # = linecache
27
+ # Module to read and cache lines of a file
28
+ # == Version
29
+ # :include:VERSION
30
+
31
+ # == SYNOPSIS
32
+ #
33
+ # The LineCache module allows one to get any line from any file,
34
+ # caching lines of the file on first access to the file. The may be is
35
+ # useful when a small random sets of lines are read from a single
36
+ # file, in particular in a debugger to show source lines.
37
+ #
38
+ # require 'linecache'
39
+ # lines = LineCache::getlines('/tmp/myruby.rb')
40
+ # # The following lines have same effect as the above.
41
+ # $: << '/tmp'
42
+ # Dir.chdir('/tmp') {lines = LineCache::getlines('myruby.rb')
43
+ #
44
+ # line = LineCache::getline('/tmp/myruby.rb', 6)
45
+ # # Note lines[6] == line (if /tmp/myruby.rb has 6 lines)
46
+ #
47
+ # LineCache::clear_file_cache
48
+ # LineCache::clear_file_cache('/tmp/myruby.rb')
49
+ # LineCache::update_cache # Check for modifications of all cached files.
50
+ #
51
+ # Some parts of the interface is derived from the Python module of the
52
+ # same name.
53
+ #
54
+
55
+ # Defining SCRIPT_LINES__ causes Ruby to cache the lines of files
56
+ # it reads. The key the setting of __FILE__ at the time when Ruby does
57
+ # its read. LineCache keeps a separate copy of the lines elsewhere
58
+ # and never destroys SCRIPT_LINES__
59
+ SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
60
+
61
+ require 'linecache-ruby'
62
+
63
+ require 'digest/sha1'
64
+ require 'set'
65
+
66
+ begin require 'rubygems' rescue LoadError end
67
+ require 'tracelines'
68
+ # require 'ruby-debug' ; Debugger.start
69
+
70
+ # = module LineCache
71
+ # Module caching lines of a file
72
+ module LineCache
73
+ LineCacheInfo = Struct.new(:stat, :line_numbers, :lines, :path, :sha1) unless
74
+ defined?(LineCacheInfo)
75
+
76
+ # The file cache. The key is a name as would be given by Ruby for
77
+ # __FILE__. The value is a LineCacheInfo object.
78
+ @@file_cache = {}
79
+
80
+ # Maps a string filename (a String) to a key in @@file_cache (a
81
+ # String).
82
+ #
83
+ # One important use of @@file2file_remap is mapping the a full path
84
+ # of a file into the name stored in @@file_cache or given by Ruby's
85
+ # __FILE__. Applications such as those that get input from users,
86
+ # may want canonicalize a file name before looking it up. This map
87
+ # gives a way to do that.
88
+ #
89
+ # Another related use is when a template system is used. Here we'll
90
+ # probably want to remap not only the file name but also line
91
+ # ranges. Will probably use this for that, but I'm not sure.
92
+ @@file2file_remap = {}
93
+ @@file2file_remap_lines = {}
94
+
95
+ # Clear the file cache entirely.
96
+ def clear_file_cache()
97
+ @@file_cache = {}
98
+ @@file2file_remap = {}
99
+ @@file2file_remap_lines = {}
100
+ end
101
+ module_function :clear_file_cache
102
+
103
+ # Return an array of cached file names
104
+ def cached_files()
105
+ @@file_cache.keys
106
+ end
107
+ module_function :cached_files
108
+
109
+ # Discard cache entries that are out of date. If +filename+ is +nil+
110
+ # all entries in the file cache +@@file_cache+ are checked.
111
+ # If we don't have stat information about a file which can happen
112
+ # if the file was read from __SCRIPT_LINES but no corresponding file
113
+ # is found, it will be kept. Return a list of invalidated filenames.
114
+ # nil is returned if a filename was given but not found cached.
115
+ def checkcache(filename=nil, use_script_lines=false)
116
+
117
+ if !filename
118
+ filenames = @@file_cache.keys()
119
+ elsif @@file_cache.member?(filename)
120
+ filenames = [filename]
121
+ else
122
+ return nil
123
+ end
124
+
125
+ result = []
126
+ for filename in filenames
127
+ next unless @@file_cache.member?(filename)
128
+ path = @@file_cache[filename].path
129
+ if File.exist?(path)
130
+ cache_info = @@file_cache[filename]
131
+ stat = File.stat(path)
132
+ if stat &&
133
+ (cache_info.size != stat.size or cache_info.mtime != stat.mtime)
134
+ result << filename
135
+ update_cache(filename, use_script_lines)
136
+ end
137
+ end
138
+ end
139
+ return result
140
+ end
141
+ module_function :checkcache
142
+
143
+ # Cache filename if it's not already cached.
144
+ # Return the expanded filename for it in the cache
145
+ # or nil if we can't find the file.
146
+ def cache(filename, reload_on_change=false)
147
+ if @@file_cache.member?(filename)
148
+ checkcache(filename) if reload_on_change
149
+ else
150
+ update_cache(filename, true)
151
+ end
152
+ if @@file_cache.member?(filename)
153
+ @@file_cache[filename].path
154
+ else
155
+ nil
156
+ end
157
+ end
158
+ module_function :cache
159
+
160
+ # Return true if filename is cached
161
+ def cached?(filename)
162
+ @@file_cache.member?(unmap_file(filename))
163
+ end
164
+ module_function :cached?
165
+
166
+ def cached_script?(filename)
167
+ SCRIPT_LINES__.member?(unmap_file(filename))
168
+ end
169
+ module_function :cached_script?
170
+
171
+ def empty?(filename)
172
+ filename=unmap_file(filename)
173
+ @@file_cache[filename].lines.empty?
174
+ end
175
+ module_function :empty?
176
+
177
+ # Get line +line_number+ from file named +filename+. Return nil if
178
+ # there was a problem. If a file named filename is not found, the
179
+ # function will look for it in the $: path array.
180
+ #
181
+ # Examples:
182
+ #
183
+ # lines = LineCache::getline('/tmp/myfile.rb)
184
+ # # Same as above
185
+ # $: << '/tmp'
186
+ # lines = Dir.chdir('/tmp') do
187
+ # lines = LineCache::getlines ('myfile.rb')
188
+ # end
189
+ #
190
+ def getline(filename, line_number, reload_on_change=true)
191
+ filename = unmap_file(filename)
192
+ filename, line_number = unmap_file_line(filename, line_number)
193
+ lines = getlines(filename, reload_on_change)
194
+ if lines and (1..lines.size) === line_number
195
+ return lines[line_number-1]
196
+ else
197
+ return nil
198
+ end
199
+ end
200
+ module_function :getline
201
+
202
+ # Read lines of +filename+ and cache the results. However +filename+ was
203
+ # previously cached use the results from the cache. Return nil
204
+ # if we can't get lines
205
+ def getlines(filename, reload_on_change=false)
206
+ filename = unmap_file(filename)
207
+ checkcache(filename) if reload_on_change
208
+ if @@file_cache.member?(filename)
209
+ return @@file_cache[filename].lines
210
+ else
211
+ update_cache(filename, true)
212
+ return @@file_cache[filename].lines if @@file_cache.member?(filename)
213
+ end
214
+ end
215
+ module_function :getlines
216
+
217
+ # Return full filename path for filename
218
+ def path(filename)
219
+ filename = unmap_file(filename)
220
+ return nil unless @@file_cache.member?(filename)
221
+ @@file_cache[filename].path
222
+ end
223
+ module_function :path
224
+
225
+ def remap_file(from_file, to_file)
226
+ @@file2file_remap[to_file] = from_file
227
+ end
228
+ module_function :remap_file
229
+
230
+ def remap_file_lines(from_file, to_file, range, start)
231
+ range = (range..range) if range.is_a?(Fixnum)
232
+ to_file = from_file unless to_file
233
+ if @@file2file_remap_lines[to_file]
234
+ # FIXME: need to check for overwriting ranges: whether
235
+ # they intersect or one encompasses another.
236
+ @@file2file_remap_lines[to_file] << [from_file, range, start]
237
+ else
238
+ @@file2file_remap_lines[to_file] = [[from_file, range, start]]
239
+ end
240
+ end
241
+ module_function :remap_file_lines
242
+
243
+ # Return SHA1 of filename.
244
+ def sha1(filename)
245
+ filename = unmap_file(filename)
246
+ return nil unless @@file_cache.member?(filename)
247
+ return @@file_cache[filename].sha1.hexdigest if
248
+ @@file_cache[filename].sha1
249
+ sha1 = Digest::SHA1.new
250
+ @@file_cache[filename].lines.each do |line|
251
+ sha1 << line
252
+ end
253
+ @@file_cache[filename].sha1 = sha1
254
+ sha1.hexdigest
255
+ end
256
+ module_function :sha1
257
+
258
+ # Return the number of lines in filename
259
+ def size(filename)
260
+ filename = unmap_file(filename)
261
+ return nil unless @@file_cache.member?(filename)
262
+ @@file_cache[filename].lines.length
263
+ end
264
+ module_function :size
265
+
266
+ # Return File.stat in the cache for filename.
267
+ def stat(filename)
268
+ return nil unless @@file_cache.member?(filename)
269
+ @@file_cache[filename].stat
270
+ end
271
+ module_function :stat
272
+
273
+ # Return an Array of breakpoints in filename.
274
+ # The list will contain an entry for each distinct line event call
275
+ # so it is possible (and possibly useful) for a line number appear more
276
+ # than once.
277
+ def trace_line_numbers(filename, reload_on_change=false)
278
+ fullname = cache(filename, reload_on_change)
279
+ return nil unless fullname
280
+ e = @@file_cache[filename]
281
+ unless e.line_numbers
282
+ e.line_numbers =
283
+ TraceLineNumbers.lnums_for_str_array(e.lines)
284
+ e.line_numbers = false unless e.line_numbers
285
+ end
286
+ e.line_numbers
287
+ end
288
+ module_function :trace_line_numbers
289
+
290
+ def unmap_file(file)
291
+ @@file2file_remap[file] ? @@file2file_remap[file] : file
292
+ end
293
+ module_function :unmap_file
294
+
295
+ def unmap_file_line(file, line)
296
+ if @@file2file_remap_lines[file]
297
+ @@file2file_remap_lines[file].each do |from_file, range, start|
298
+ if range === line
299
+ from_file = from_file || file
300
+ return [from_file, start+line-range.begin]
301
+ end
302
+ end
303
+ end
304
+ return [file, line]
305
+ end
306
+ module_function :unmap_file_line
307
+
308
+ # Update a cache entry. If something's
309
+ # wrong, return nil. Return true if the cache was updated and false
310
+ # if not. If use_script_lines is true, use that as the source for the
311
+ # lines of the file
312
+ def update_cache(filename, use_script_lines=false)
313
+
314
+ return nil unless filename
315
+
316
+ @@file_cache.delete(filename)
317
+ path = File.expand_path(filename)
318
+
319
+ if use_script_lines
320
+ list = [filename]
321
+ list << @@file2file_remap[path] if @@file2file_remap[path]
322
+ list.each do |name|
323
+ if !SCRIPT_LINES__[name].nil? && SCRIPT_LINES__[name] != true
324
+ begin
325
+ stat = File.stat(name)
326
+ rescue
327
+ stat = nil
328
+ end
329
+ lines = SCRIPT_LINES__[name]
330
+
331
+ # Temporary workaround for bug in the JRuby: http://jira.codehaus.org/browse/JRUBY-2442
332
+ # Chop last two redundant empty lines
333
+ lines = lines[0..-3] if (lines.length >= 2 && lines.last(2).join == '')
334
+
335
+ @@file_cache[filename] = LineCacheInfo.new(stat, nil, lines, path, nil)
336
+ @@file2file_remap[path] = filename
337
+ return true
338
+ end
339
+ end
340
+ end
341
+
342
+ if File.exist?(path)
343
+ stat = File.stat(path)
344
+ elsif File.basename(filename) == filename
345
+ # try looking through the search path.
346
+ stat = nil
347
+ for dirname in $:
348
+ path = File.join(dirname, filename)
349
+ if File.exist?(path)
350
+ stat = File.stat(path)
351
+ break
352
+ end
353
+ end
354
+ return false unless stat
355
+ end
356
+ begin
357
+ fp = File.open(path, 'r')
358
+ lines = fp.readlines()
359
+ fp.close()
360
+ rescue
361
+ ## print '*** cannot open', path, ':', msg
362
+ return nil
363
+ end
364
+ @@file_cache[filename] = LineCacheInfo.new(File.stat(path), nil, lines,
365
+ path, nil)
366
+ @@file2file_remap[path] = filename
367
+ return true
368
+ end
369
+
370
+ module_function :update_cache
371
+
372
+ end
373
+
374
+ # example usage
375
+ if __FILE__ == $0
376
+ def yes_no(var)
377
+ return var ? "" : "not "
378
+ end
379
+
380
+ lines = LineCache::getlines(__FILE__)
381
+ puts "#{__FILE__} has #{LineCache.size(__FILE__)} lines"
382
+ line = LineCache::getline(__FILE__, 6)
383
+ puts "The 6th line is\n#{line}"
384
+ line = LineCache::remap_file(__FILE__, 'another_name')
385
+ puts LineCache::getline('another_name', 7)
386
+
387
+ puts("Files cached: #{LineCache::cached_files.inspect}")
388
+ LineCache::update_cache(__FILE__)
389
+ LineCache::checkcache(__FILE__)
390
+ puts "#{__FILE__} has #{LineCache::size(__FILE__)} lines"
391
+ puts "#{__FILE__} trace line numbers:\n" +
392
+ "#{LineCache::trace_line_numbers(__FILE__).to_a.sort.inspect}"
393
+ puts("#{__FILE__} is %scached." %
394
+ yes_no(LineCache::cached?(__FILE__)))
395
+ puts LineCache::stat(__FILE__).inspect
396
+ puts "Full path: #{LineCache::path(__FILE__)}"
397
+ LineCache::checkcache # Check all files in the cache
398
+ LineCache::clear_file_cache
399
+ puts("#{__FILE__} is now %scached." %
400
+ yes_no(LineCache::cached?(__FILE__)))
401
+ digest = SCRIPT_LINES__.select{|k,v| k =~ /digest.rb$/}
402
+ puts digest.first[0] if digest
403
+ line = LineCache::getline(__FILE__, 7)
404
+ puts "The 7th line is\n#{line}"
405
+ LineCache::remap_file_lines(__FILE__, 'test2', (10..20), 6)
406
+ puts LineCache::getline('test2', 10)
407
+ puts "Remapped 10th line of test2 is\n#{line}"
408
+ end