Class: RubyLint::FileScanner
- Inherits:
-
Object
- Object
- RubyLint::FileScanner
- Defined in:
- lib/ruby-lint/file_scanner.rb
Overview
FileScanner is used for finding a list of files that could potentially define a given Ruby constant (path).
Constant Summary
- RUBY_DIRECTORIES =
Array containing names of directories that (often) contain Ruby source files.
%w{app lib}
Instance Attribute Summary collapse
-
#directories ⇒ Array
readonly
-
#ignore ⇒ Array
readonly
Class Method Summary collapse
Instance Method Summary collapse
-
#build_constant_paths_cache(constant) ⇒ Object
Searches all the files that could potentially define the given constant and caches them.
-
#constant_paths_cached?(constant) ⇒ TrueClass|FalseClass
-
#constant_to_dashed_path(constant) ⇒ Object
Returns a path similar to #constant_to_path but using dashes instead of underscores for the first directory.
-
#constant_to_path(constant) ⇒ String
Returns the file path for the given constant.
-
#glob_cache ⇒ Array
-
#glob_ruby_files ⇒ Array
-
#initialize(directories = self.class.default_directories, ignore = []) ⇒ FileScanner
constructor
A new instance of FileScanner.
-
#match_globbed_files(segment) ⇒ Array
-
#scan(constant) ⇒ Array
Tries to find
constant
in one of the directories.
Constructor Details
#initialize(directories = self.class.default_directories, ignore = []) ⇒ FileScanner
Returns a new instance of FileScanner
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ruby-lint/file_scanner.rb', line 42 def initialize(directories = self.class.default_directories, ignore = []) unless directories.respond_to?(:each) raise TypeError, 'Directories must be specified as an Enumerable' end @directories = directories @ignore = ignore || [] # Hash that will contain the matching file paths for a given constant. @constant_paths_cache = {} end |
Instance Attribute Details
#directories ⇒ Array (readonly)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/ruby-lint/file_scanner.rb', line 12 class FileScanner attr_reader :directories, :ignore ## # Array containing names of directories that (often) contain Ruby source # files. # # @return [Array] # RUBY_DIRECTORIES = %w{app lib} ## # @return [Array] # def self.default_directories directories = [] RUBY_DIRECTORIES.each do |dir| path = File.join(Dir.pwd, dir) directories << path if File.directory?(path) end return directories end ## # @param [Array] directories A collection of base directories to search in. # @param [Array] ignore A list of paths to ignore. # def initialize(directories = self.class.default_directories, ignore = []) unless directories.respond_to?(:each) raise TypeError, 'Directories must be specified as an Enumerable' end @directories = directories @ignore = ignore || [] # Hash that will contain the matching file paths for a given constant. @constant_paths_cache = {} end ## # Tries to find `constant` in one of the directories. The return value is # an Array of file paths sorted from top-level to deeply nested structures # (e.g. `a.rb` comes before `foo/a.rb`). # # @param [String] constant # @return [Array] # def scan(constant) unless constant_paths_cached?(constant) build_constant_paths_cache(constant) end return @constant_paths_cache[constant] end ## # @return [Array] # def glob_cache @glob_cache ||= directories.empty? ? [] : glob_ruby_files end ## # @return [Array] # def glob_ruby_files return Dir.glob("{#{directories.join(',')}}/**/*.rb") end ## # Returns the file path for the given constant. # # @example # constant_to_path('FooBar::Baz') # => "foo_bar/baz.rb" # # @param [String] constant # @return [String] # def constant_to_path(constant) return constant.gsub('::', '/').snake_case + '.rb' end ## # Returns a path similar to {#constant_to_path} but using dashes instead of # underscores for the first directory. # # @example # constant_to_dashed_path('FooBar::Baz') # => "foo-bar/baz.rb" # # @see [#constant_to_path] # def constant_to_dashed_path(constant) const_segments = constant.split('::') path_segments = [] const_segments.each_with_index do |segment, index| segment = segment.snake_case # Use dashes for the first segment (= top level directory). if const_segments.length > 1 and index == 0 segment = segment.gsub('_', '-') end path_segments << segment end return path_segments.join('/') + '.rb' end ## # Searches all the files that could potentially define the given constant # and caches them. # # @param [String] constant # def build_constant_paths_cache(constant) paths = match_globbed_files(constant_to_path(constant)) # Lets see if we can find anything when using dashes for the directory # names instead of underscores. if paths.empty? paths = match_globbed_files(constant_to_dashed_path(constant)) end paths.map! { |p| File.(p) } ignore.each do |pattern| paths.reject! do |path| path.include?(pattern) end end # Ensure that the order is from top-level -> deeply nested files # instead of a random order. paths.sort! do |left, right| left.length <=> right.length end @constant_paths_cache[constant] = paths end ## # @return [Array] # def match_globbed_files(segment) # Ensure that we match entire path segments. Just using the segment would # result in partial filename matching (e.g. "foo.rb" matching # "bar_foo.rb"). We don't want that. segment = "/#{segment}" return glob_cache.select { |p| p.include?(segment) } end ## # @return [TrueClass|FalseClass] # def constant_paths_cached?(constant) return @constant_paths_cache.key?(constant) end end |
#ignore ⇒ Array (readonly)
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/ruby-lint/file_scanner.rb', line 12 class FileScanner attr_reader :directories, :ignore ## # Array containing names of directories that (often) contain Ruby source # files. # # @return [Array] # RUBY_DIRECTORIES = %w{app lib} ## # @return [Array] # def self.default_directories directories = [] RUBY_DIRECTORIES.each do |dir| path = File.join(Dir.pwd, dir) directories << path if File.directory?(path) end return directories end ## # @param [Array] directories A collection of base directories to search in. # @param [Array] ignore A list of paths to ignore. # def initialize(directories = self.class.default_directories, ignore = []) unless directories.respond_to?(:each) raise TypeError, 'Directories must be specified as an Enumerable' end @directories = directories @ignore = ignore || [] # Hash that will contain the matching file paths for a given constant. @constant_paths_cache = {} end ## # Tries to find `constant` in one of the directories. The return value is # an Array of file paths sorted from top-level to deeply nested structures # (e.g. `a.rb` comes before `foo/a.rb`). # # @param [String] constant # @return [Array] # def scan(constant) unless constant_paths_cached?(constant) build_constant_paths_cache(constant) end return @constant_paths_cache[constant] end ## # @return [Array] # def glob_cache @glob_cache ||= directories.empty? ? [] : glob_ruby_files end ## # @return [Array] # def glob_ruby_files return Dir.glob("{#{directories.join(',')}}/**/*.rb") end ## # Returns the file path for the given constant. # # @example # constant_to_path('FooBar::Baz') # => "foo_bar/baz.rb" # # @param [String] constant # @return [String] # def constant_to_path(constant) return constant.gsub('::', '/').snake_case + '.rb' end ## # Returns a path similar to {#constant_to_path} but using dashes instead of # underscores for the first directory. # # @example # constant_to_dashed_path('FooBar::Baz') # => "foo-bar/baz.rb" # # @see [#constant_to_path] # def constant_to_dashed_path(constant) const_segments = constant.split('::') path_segments = [] const_segments.each_with_index do |segment, index| segment = segment.snake_case # Use dashes for the first segment (= top level directory). if const_segments.length > 1 and index == 0 segment = segment.gsub('_', '-') end path_segments << segment end return path_segments.join('/') + '.rb' end ## # Searches all the files that could potentially define the given constant # and caches them. # # @param [String] constant # def build_constant_paths_cache(constant) paths = match_globbed_files(constant_to_path(constant)) # Lets see if we can find anything when using dashes for the directory # names instead of underscores. if paths.empty? paths = match_globbed_files(constant_to_dashed_path(constant)) end paths.map! { |p| File.(p) } ignore.each do |pattern| paths.reject! do |path| path.include?(pattern) end end # Ensure that the order is from top-level -> deeply nested files # instead of a random order. paths.sort! do |left, right| left.length <=> right.length end @constant_paths_cache[constant] = paths end ## # @return [Array] # def match_globbed_files(segment) # Ensure that we match entire path segments. Just using the segment would # result in partial filename matching (e.g. "foo.rb" matching # "bar_foo.rb"). We don't want that. segment = "/#{segment}" return glob_cache.select { |p| p.include?(segment) } end ## # @return [TrueClass|FalseClass] # def constant_paths_cached?(constant) return @constant_paths_cache.key?(constant) end end |
Class Method Details
.default_directories ⇒ Array
26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/ruby-lint/file_scanner.rb', line 26 def self.default_directories directories = [] RUBY_DIRECTORIES.each do |dir| path = File.join(Dir.pwd, dir) directories << path if File.directory?(path) end return directories end |
Instance Method Details
#build_constant_paths_cache(constant) ⇒ Object
Searches all the files that could potentially define the given constant and caches them.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/ruby-lint/file_scanner.rb', line 130 def build_constant_paths_cache(constant) paths = match_globbed_files(constant_to_path(constant)) # Lets see if we can find anything when using dashes for the directory # names instead of underscores. if paths.empty? paths = match_globbed_files(constant_to_dashed_path(constant)) end paths.map! { |p| File.(p) } ignore.each do |pattern| paths.reject! do |path| path.include?(pattern) end end # Ensure that the order is from top-level -> deeply nested files # instead of a random order. paths.sort! do |left, right| left.length <=> right.length end @constant_paths_cache[constant] = paths end |
#constant_paths_cached?(constant) ⇒ TrueClass|FalseClass
171 172 173 |
# File 'lib/ruby-lint/file_scanner.rb', line 171 def constant_paths_cached?(constant) return @constant_paths_cache.key?(constant) end |
#constant_to_dashed_path(constant) ⇒ Object
Returns a path similar to #constant_to_path but using dashes instead of underscores for the first directory.
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/ruby-lint/file_scanner.rb', line 106 def constant_to_dashed_path(constant) const_segments = constant.split('::') path_segments = [] const_segments.each_with_index do |segment, index| segment = segment.snake_case # Use dashes for the first segment (= top level directory). if const_segments.length > 1 and index == 0 segment = segment.gsub('_', '-') end path_segments << segment end return path_segments.join('/') + '.rb' end |
#constant_to_path(constant) ⇒ String
Returns the file path for the given constant.
93 94 95 |
# File 'lib/ruby-lint/file_scanner.rb', line 93 def constant_to_path(constant) return constant.gsub('::', '/').snake_case + '.rb' end |
#glob_cache ⇒ Array
73 74 75 |
# File 'lib/ruby-lint/file_scanner.rb', line 73 def glob_cache @glob_cache ||= directories.empty? ? [] : glob_ruby_files end |
#glob_ruby_files ⇒ Array
80 81 82 |
# File 'lib/ruby-lint/file_scanner.rb', line 80 def glob_ruby_files return Dir.glob("{#{directories.join(',')}}/**/*.rb") end |
#match_globbed_files(segment) ⇒ Array
159 160 161 162 163 164 165 166 |
# File 'lib/ruby-lint/file_scanner.rb', line 159 def match_globbed_files(segment) # Ensure that we match entire path segments. Just using the segment would # result in partial filename matching (e.g. "foo.rb" matching # "bar_foo.rb"). We don't want that. segment = "/#{segment}" return glob_cache.select { |p| p.include?(segment) } end |
#scan(constant) ⇒ Array
Tries to find constant
in one of the directories. The return value is
an Array of file paths sorted from top-level to deeply nested structures
(e.g. a.rb
comes before foo/a.rb
).
62 63 64 65 66 67 68 |
# File 'lib/ruby-lint/file_scanner.rb', line 62 def scan(constant) unless constant_paths_cached?(constant) build_constant_paths_cache(constant) end return @constant_paths_cache[constant] end |