renamespace 0.1.5
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.
- checksums.yaml +7 -0
- data/README.md +130 -0
- data/exe/renamespace +51 -0
- data/lib/renamespace.rb +60 -0
- data/lib/renamespace/directories.rb +17 -0
- data/lib/renamespace/expand_relative_requires_in_file_content.rb +36 -0
- data/lib/renamespace/expand_relative_requires_within_all_files.rb +33 -0
- data/lib/renamespace/move_and_renamespace_source_file.rb +44 -0
- data/lib/renamespace/move_spec_file.rb +50 -0
- data/lib/renamespace/paths.rb +64 -0
- data/lib/renamespace/rename_within_all_files.rb +41 -0
- data/lib/renamespace/rename_within_file_content.rb +54 -0
- data/lib/renamespace/renamespace_file_content.rb +62 -0
- data/lib/renamespace/replacements_logger.rb +20 -0
- data/lib/renamespace/version.rb +5 -0
- metadata +103 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: baab242cddf012fa2783d62426cafaeb4ed1787f1f00f0008cc4363f0e26c3f2
|
4
|
+
data.tar.gz: f82d644df34a4c2741780ebf3bdb12be61c9ea25a9827183aedad091527cbd99
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 18e11ce64cfbf8bf2fe94561bd768a34c8118a037fe41fe78c07bcddb628297ccfce174b81654a9e11a654763799f77beef47f450fb89e1a45d96fee23194843
|
7
|
+
data.tar.gz: 73e4d9277f5812e7e011411c0af72715381a0be7b7bcd4704d2348dcb987c84fae9234d6cbc02fd128d0d915dc25459f29a3b2ebdc107f026fd48548330f8e76
|
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
# Renamespace
|
2
|
+
|
3
|
+
[](https://buildkite.com/gs/renamespace)
|
4
|
+
|
5
|
+
A command-line tool to help Ruby developers refactor class/module namespacing.
|
6
|
+
|
7
|
+
## Contents
|
8
|
+
|
9
|
+
<!-- MarkdownTOC autolink=true -->
|
10
|
+
|
11
|
+
- [Intro](#intro)
|
12
|
+
- [Installation](#installation)
|
13
|
+
- [Usage](#usage)
|
14
|
+
- [Example](#example)
|
15
|
+
- [More usage info](#more-usage-info)
|
16
|
+
- [Development](#development)
|
17
|
+
- [Pre-push hook](#pre-push-hook)
|
18
|
+
- [Release](#release)
|
19
|
+
|
20
|
+
<!-- /MarkdownTOC -->
|
21
|
+
|
22
|
+
## Intro
|
23
|
+
|
24
|
+
Renamespaces a Ruby source file:
|
25
|
+
|
26
|
+
- Moves the file
|
27
|
+
- Updates, to match the new location, the name of the class/module within the file, including its namespacing
|
28
|
+
- Updates usages of the class/module
|
29
|
+
- Updates the path to the file in all requires
|
30
|
+
- Moves the associated spec file
|
31
|
+
|
32
|
+
Class/module namespaces are derived from the paths provided.
|
33
|
+
|
34
|
+
If you change the number of namespaces, expect to have to run RuboCop autocorrect afterwards to clean up formatting.
|
35
|
+
|
36
|
+
The namespace replacing is not super smart yet, so it might get it wrong sometimes. If it does, see `renamespace --help` for some options that might help.
|
37
|
+
|
38
|
+
## Installation
|
39
|
+
|
40
|
+
The executable is distributed as a gem. You can install it from GitHub Packages directly like so:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
$ gem install renamespace
|
44
|
+
```
|
45
|
+
|
46
|
+
And then if you're using rbenv:
|
47
|
+
|
48
|
+
```bash
|
49
|
+
$ rbenv rehash
|
50
|
+
```
|
51
|
+
|
52
|
+
## Usage
|
53
|
+
|
54
|
+
```bash
|
55
|
+
$ renamespace SOURCE_FILE_PATH DESTINATION_FILE_PATH
|
56
|
+
```
|
57
|
+
|
58
|
+
## Example
|
59
|
+
|
60
|
+
With:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# lib/my_app/models/site.rb
|
64
|
+
|
65
|
+
module MyApp
|
66
|
+
module Models
|
67
|
+
class Site < BaseModel
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
```
|
72
|
+
|
73
|
+
Run:
|
74
|
+
|
75
|
+
```bash
|
76
|
+
$ renamespace lib/my_app/models/site.rb lib/my_app/sites/model.rb
|
77
|
+
```
|
78
|
+
|
79
|
+
Result:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
# lib/my_app/sites/model.rb
|
83
|
+
|
84
|
+
module MyApp
|
85
|
+
module Sites
|
86
|
+
class Model < Models::BaseModel
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
```
|
91
|
+
|
92
|
+
## More usage info
|
93
|
+
|
94
|
+
See:
|
95
|
+
|
96
|
+
```bash
|
97
|
+
$ renamespace --help
|
98
|
+
```
|
99
|
+
|
100
|
+
## Development
|
101
|
+
|
102
|
+
### Pre-push hook
|
103
|
+
|
104
|
+
This hook runs style checks and tests.
|
105
|
+
|
106
|
+
To set up the pre-push hook:
|
107
|
+
|
108
|
+
```bash
|
109
|
+
$ echo -e "#\!/bin/bash\n\$(dirname \$0)/../../auto/pre-push-hook" > .git/hooks/pre-push
|
110
|
+
chmod +x .git/hooks/pre-push
|
111
|
+
```
|
112
|
+
|
113
|
+
### Release
|
114
|
+
|
115
|
+
First, [make sure your credentials are set up for GitHub Package Registry according to the Handbook](https://handbook.greensync.org/product/intro/getting-started/#github-package-registry-and-ruby-gems).
|
116
|
+
|
117
|
+
To release a new version:
|
118
|
+
|
119
|
+
```bash
|
120
|
+
$ auto/release/update-version && auto/release/tag && auto/release/publish
|
121
|
+
```
|
122
|
+
|
123
|
+
This takes care of the whole process:
|
124
|
+
|
125
|
+
- Incrementing the version number (the patch number by default)
|
126
|
+
- Tagging & pushing commits
|
127
|
+
- Publishing the gem to GitHub Packages
|
128
|
+
- Creating a draft GitHub release
|
129
|
+
|
130
|
+
To increment the minor or major versions instead of the patch number, run `auto/release/update-version` with `--minor` or `--major`.
|
data/exe/renamespace
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
$LOAD_PATH << File.expand_path('../lib', __dir__)
|
6
|
+
|
7
|
+
require 'clamp'
|
8
|
+
|
9
|
+
require 'renamespace'
|
10
|
+
|
11
|
+
Clamp.allow_options_after_parameters = true
|
12
|
+
|
13
|
+
Clamp do # rubocop:disable Metrics/BlockLength
|
14
|
+
self.description = <<~TEXT
|
15
|
+
Renamespaces a Ruby source file:
|
16
|
+
|
17
|
+
- Moves the file
|
18
|
+
- Updates, to match the new location, the name of the class/module within the file, including its namespacing
|
19
|
+
- Updates usages of the class/module
|
20
|
+
- Updates the path to the file in all requires
|
21
|
+
- Moves the associated spec file
|
22
|
+
|
23
|
+
Class/module namespaces are derived from the paths provided.
|
24
|
+
|
25
|
+
If you change the number of namespaces, expect to have to run RuboCop autocorrect afterwards to clean up formatting.
|
26
|
+
TEXT
|
27
|
+
|
28
|
+
parameter 'SOURCE_FILE_PATH', 'The current path of the Ruby source code file to renamespace'
|
29
|
+
parameter 'DESTINATION_FILE_PATH', 'The desired desination path of the file'
|
30
|
+
|
31
|
+
option ['-o', '--can-omit-prefixes'], 'COUNT',
|
32
|
+
'How many levels of namespacing to omit up to when replacing usages of the class/module. ' \
|
33
|
+
'Too low, and some cases may be missed; too high, and some incorrect replacements are likely to occur',
|
34
|
+
default: 0, &method(:Integer)
|
35
|
+
|
36
|
+
option '--no-superclass-prefixing', :flag, "Don't prefix superclasses with their previous namespace"
|
37
|
+
|
38
|
+
option '--version', :flag, 'Show version' do
|
39
|
+
puts Renamespace::VERSION
|
40
|
+
exit 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute
|
44
|
+
Renamespace.new(
|
45
|
+
source_file_path: source_file_path,
|
46
|
+
destination_file_path: destination_file_path,
|
47
|
+
can_omit_prefixes_count: can_omit_prefixes,
|
48
|
+
no_superclass_prefixing: no_superclass_prefixing?,
|
49
|
+
).call
|
50
|
+
end
|
51
|
+
end
|
data/lib/renamespace.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
require 'facets/string/camelcase'
|
6
|
+
require 'rainbow'
|
7
|
+
|
8
|
+
require_relative 'renamespace/directories'
|
9
|
+
require_relative 'renamespace/expand_relative_requires_within_all_files'
|
10
|
+
require_relative 'renamespace/move_and_renamespace_source_file'
|
11
|
+
require_relative 'renamespace/move_spec_file'
|
12
|
+
require_relative 'renamespace/rename_within_all_files'
|
13
|
+
require_relative 'renamespace/paths'
|
14
|
+
require_relative 'renamespace/version'
|
15
|
+
|
16
|
+
class Renamespace
|
17
|
+
def initialize(source_file_path:, destination_file_path:, can_omit_prefixes_count:, no_superclass_prefixing:)
|
18
|
+
@paths = Renamespace::Paths.new(
|
19
|
+
source: source_file_path,
|
20
|
+
destination: destination_file_path,
|
21
|
+
)
|
22
|
+
@can_omit_prefixes_count = can_omit_prefixes_count
|
23
|
+
@no_superclass_prefixing = no_superclass_prefixing
|
24
|
+
end
|
25
|
+
|
26
|
+
def call
|
27
|
+
move_and_renamespace_source_file
|
28
|
+
move_spec_file
|
29
|
+
expand_relative_requires_within_all_files
|
30
|
+
rename_within_all_files
|
31
|
+
remove_empty_dirs
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
attr_reader :paths, :can_omit_prefixes_count, :no_superclass_prefixing
|
37
|
+
|
38
|
+
def move_and_renamespace_source_file
|
39
|
+
Renamespace::MoveAndRenamespaceSourceFile.new(
|
40
|
+
paths: paths,
|
41
|
+
no_superclass_prefixing: no_superclass_prefixing,
|
42
|
+
).call
|
43
|
+
end
|
44
|
+
|
45
|
+
def move_spec_file
|
46
|
+
Renamespace::MoveSpecFile.new(paths: paths).call
|
47
|
+
end
|
48
|
+
|
49
|
+
def expand_relative_requires_within_all_files
|
50
|
+
Renamespace::ExpandRelativeRequiresWithinAllFiles.new.call
|
51
|
+
end
|
52
|
+
|
53
|
+
def rename_within_all_files
|
54
|
+
Renamespace::RenameWithinAllFiles.new(paths: paths, can_omit_prefixes_count: can_omit_prefixes_count).call
|
55
|
+
end
|
56
|
+
|
57
|
+
def remove_empty_dirs
|
58
|
+
Renamespace::Directories.remove_empty_dirs
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renamespace
|
4
|
+
module Directories
|
5
|
+
def self.create_directories_to_file(file_path)
|
6
|
+
FileUtils.mkdir_p(dir_for_file_path(file_path))
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.dir_for_file_path(file_path)
|
10
|
+
file_path.sub(%r{/[^/]+$}, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.remove_empty_dirs
|
14
|
+
Dir['**/'].reverse_each { |d| Dir.rmdir(d) if Dir.empty?(d) }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
require_relative 'directories'
|
6
|
+
require_relative 'paths'
|
7
|
+
|
8
|
+
class Renamespace
|
9
|
+
class ExpandRelativeRequiresInFileContent
|
10
|
+
def initialize(content:, path:)
|
11
|
+
@content = content
|
12
|
+
@path = path
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
content
|
17
|
+
.gsub(/require_relative '([^']+)'/) do
|
18
|
+
"require '%s'" % expanded_require_path($1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_reader :content, :path
|
25
|
+
|
26
|
+
def expanded_require_path(relative_require_path)
|
27
|
+
joined_path = File.join(require_dir, relative_require_path)
|
28
|
+
Pathname.new(joined_path).cleanpath
|
29
|
+
end
|
30
|
+
|
31
|
+
def require_dir
|
32
|
+
dir = Renamespace::Directories.dir_for_file_path(path)
|
33
|
+
Renamespace::Paths.require_for_path(dir)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'expand_relative_requires_in_file_content'
|
4
|
+
|
5
|
+
class Renamespace
|
6
|
+
class ExpandRelativeRequiresWithinAllFiles
|
7
|
+
def call
|
8
|
+
all_suitable_ruby_file_paths.each do |path|
|
9
|
+
content_orig = File.read(path)
|
10
|
+
content_new = expand_in_file(content_orig, path)
|
11
|
+
File.write(path, content_new) unless content_orig == content_new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def expand_in_file(content_orig, path)
|
18
|
+
Renamespace::ExpandRelativeRequiresInFileContent.new(content: content_orig, path: path).call
|
19
|
+
end
|
20
|
+
|
21
|
+
def all_suitable_ruby_file_paths
|
22
|
+
Renamespace::Paths.all_ruby_file_paths - exclusions
|
23
|
+
end
|
24
|
+
|
25
|
+
def exclusions
|
26
|
+
%w[
|
27
|
+
spec/spec_helper.rb
|
28
|
+
renamespace_spec.rb
|
29
|
+
lib/bootstrap.rb
|
30
|
+
]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'directories'
|
4
|
+
require_relative 'renamespace_file_content'
|
5
|
+
|
6
|
+
class Renamespace
|
7
|
+
class MoveAndRenamespaceSourceFile
|
8
|
+
def initialize(paths:, no_superclass_prefixing:)
|
9
|
+
@paths = paths
|
10
|
+
@no_superclass_prefixing = no_superclass_prefixing
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
log_source_and_destination_namespaces
|
15
|
+
write_new_file
|
16
|
+
delete_old_file
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :paths, :no_superclass_prefixing
|
22
|
+
|
23
|
+
def log_source_and_destination_namespaces
|
24
|
+
puts '%s -> %s' % [paths.source_namespace, paths.destination_namespace]
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_new_file
|
28
|
+
Renamespace::Directories.create_directories_to_file(paths.destination)
|
29
|
+
File.write(paths.destination, renamespaced_file_content)
|
30
|
+
end
|
31
|
+
|
32
|
+
def delete_old_file
|
33
|
+
File.delete(paths.source) unless paths.same?
|
34
|
+
end
|
35
|
+
|
36
|
+
def renamespaced_file_content
|
37
|
+
content = File.read(paths.source)
|
38
|
+
Renamespace::RenamespaceFileContent.new(
|
39
|
+
paths: paths,
|
40
|
+
no_superclass_prefixing: no_superclass_prefixing,
|
41
|
+
).call(content)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'directories'
|
4
|
+
|
5
|
+
class Renamespace
|
6
|
+
class MoveSpecFile
|
7
|
+
def initialize(paths:)
|
8
|
+
@paths = paths
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
move unless missing? || paths.same?
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
attr_reader :paths
|
18
|
+
|
19
|
+
def move
|
20
|
+
Renamespace::Directories.create_directories_to_file(destination_spec_path)
|
21
|
+
FileUtils.mv(source_spec_path, destination_spec_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def warn_missing
|
25
|
+
puts Rainbow("Warning: spec file missing for #{destination_spec_path}").orange
|
26
|
+
end
|
27
|
+
|
28
|
+
def missing?
|
29
|
+
!(File.exist?(source_spec_path) || warn_missing)
|
30
|
+
end
|
31
|
+
|
32
|
+
def source_spec_path
|
33
|
+
spec_path(paths.source)
|
34
|
+
end
|
35
|
+
|
36
|
+
def destination_spec_path
|
37
|
+
spec_path(paths.destination)
|
38
|
+
end
|
39
|
+
|
40
|
+
def spec_path(path)
|
41
|
+
path
|
42
|
+
.sub('.rb', '_spec.rb')
|
43
|
+
.sub(/^lib/, specs_dir)
|
44
|
+
end
|
45
|
+
|
46
|
+
def specs_dir
|
47
|
+
Dir.exist?('spec/lib') ? 'spec/lib' : 'spec'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renamespace
|
4
|
+
Paths = Struct.new(:source, :destination, keyword_init: true) do
|
5
|
+
def self.namespace_for_path(path)
|
6
|
+
namespace_elements_for_path(path).join('::')
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.require_for_path(path)
|
10
|
+
path_elements_for_require(path).join('/')
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.namespace_elements_for_path(path)
|
14
|
+
path_elements_for_require(path)
|
15
|
+
.map(&method(:namespace_element_from_path_element))
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.path_elements_for_require(path)
|
19
|
+
path.sub(%r{^lib/}, '').chomp('.rb').split('/')
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.namespace_element_from_path_element(path_element)
|
23
|
+
custom_camelcasings.fetch(path_element) { path_element.upper_camelcase }
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.custom_camelcasings
|
27
|
+
{
|
28
|
+
'greensync' => 'GreenSync',
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.all_ruby_file_paths
|
33
|
+
(Dir.glob('**/*.rb') - %w[invert_namespaces.rb renamespace.rb])
|
34
|
+
end
|
35
|
+
|
36
|
+
def source_namespace
|
37
|
+
self.class.namespace_for_path(source)
|
38
|
+
end
|
39
|
+
|
40
|
+
def destination_namespace
|
41
|
+
self.class.namespace_for_path(destination)
|
42
|
+
end
|
43
|
+
|
44
|
+
def source_namespace_elements
|
45
|
+
self.class.namespace_elements_for_path(source)
|
46
|
+
end
|
47
|
+
|
48
|
+
def destination_namespace_elements
|
49
|
+
self.class.namespace_elements_for_path(destination)
|
50
|
+
end
|
51
|
+
|
52
|
+
def source_require_path
|
53
|
+
self.class.require_for_path(source)
|
54
|
+
end
|
55
|
+
|
56
|
+
def destination_require_path
|
57
|
+
self.class.require_for_path(destination)
|
58
|
+
end
|
59
|
+
|
60
|
+
def same?
|
61
|
+
source == destination
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'paths'
|
4
|
+
require_relative 'rename_within_file_content'
|
5
|
+
require_relative 'replacements_logger'
|
6
|
+
|
7
|
+
class Renamespace
|
8
|
+
class RenameWithinAllFiles
|
9
|
+
def initialize(paths:, can_omit_prefixes_count:)
|
10
|
+
@paths = paths
|
11
|
+
@can_omit_prefixes_count = can_omit_prefixes_count
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
Renamespace::Paths.all_ruby_file_paths.each do |path|
|
16
|
+
content_orig = File.read(path)
|
17
|
+
content_new = rename_within_file_content(content_orig)
|
18
|
+
File.write(path, content_new) unless content_orig == content_new
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_reader :can_omit_prefixes_count
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def rename_within_file_content(content)
|
27
|
+
Renamespace::RenameWithinFileContent.new(
|
28
|
+
paths: paths,
|
29
|
+
content: content,
|
30
|
+
replacements_logger: replacements_logger,
|
31
|
+
can_omit_prefixes_count: can_omit_prefixes_count,
|
32
|
+
).call
|
33
|
+
end
|
34
|
+
|
35
|
+
def replacements_logger
|
36
|
+
@replacements_logger ||= Renamespace::ReplacementsLogger.new
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :paths
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'paths'
|
4
|
+
|
5
|
+
class Renamespace
|
6
|
+
class RenameWithinFileContent
|
7
|
+
def initialize(paths:, content:, can_omit_prefixes_count:, replacements_logger:)
|
8
|
+
@paths = paths
|
9
|
+
@content_orig = content
|
10
|
+
@can_omit_prefixes_count = can_omit_prefixes_count
|
11
|
+
@replacements_logger = replacements_logger
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
content_orig
|
16
|
+
.then(&method(:replace_require_paths))
|
17
|
+
.then(&method(:replace_references))
|
18
|
+
end
|
19
|
+
|
20
|
+
def replace_require_paths(content)
|
21
|
+
content.gsub(paths.source_require_path, paths.destination_require_path)
|
22
|
+
end
|
23
|
+
|
24
|
+
def replace_references(content)
|
25
|
+
(1 + can_omit_prefixes_count).times do
|
26
|
+
replacements_logger.log(search_str, replace_str)
|
27
|
+
content = content.gsub(search_str, replace_str)
|
28
|
+
namespace_elements_source.shift
|
29
|
+
namespace_elements_dest.shift
|
30
|
+
end
|
31
|
+
content
|
32
|
+
end
|
33
|
+
|
34
|
+
def search_str
|
35
|
+
namespace_elements_source.join('::')
|
36
|
+
end
|
37
|
+
|
38
|
+
def replace_str
|
39
|
+
namespace_elements_dest.join('::')
|
40
|
+
end
|
41
|
+
|
42
|
+
def namespace_elements_source
|
43
|
+
@namespace_elements_source ||= paths.source_namespace_elements
|
44
|
+
end
|
45
|
+
|
46
|
+
def namespace_elements_dest
|
47
|
+
@namespace_elements_dest ||= paths.destination_namespace_elements
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :paths, :content_orig, :can_omit_prefixes_count, :replacements_logger
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renamespace
|
4
|
+
class RenamespaceFileContent
|
5
|
+
def initialize(paths:, no_superclass_prefixing:)
|
6
|
+
@paths = paths
|
7
|
+
@no_superclass_prefixing = no_superclass_prefixing
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(content) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
11
|
+
content = content.dup
|
12
|
+
source, dest = source_and_dest_namespace_elements_without_common_prefix
|
13
|
+
namespace_element_replacements = dest.reverse.zip(source.reverse)
|
14
|
+
namespace_element_replacements.each_with_index do |(namespace_element_new, namespace_element_old), i|
|
15
|
+
old_parent_namespace = namespace_element_replacements.last(i + 1).map(&:last).reverse.join('::')
|
16
|
+
old_parent_namespace += '::' unless old_parent_namespace.empty?
|
17
|
+
if namespace_element_old
|
18
|
+
# Replacing existing namespace
|
19
|
+
content.sub!(/(class|module) #{namespace_element_old}\b( < (\S+))?/) do
|
20
|
+
klass_line = "#{Regexp.last_match(1)} RENAMESPACED_#{namespace_element_new}"
|
21
|
+
Regexp.last_match(3)&.tap do |superclass_orig|
|
22
|
+
klass_line += ' < '
|
23
|
+
klass_line += old_parent_namespace unless superclass_orig.start_with?('::') || no_superclass_prefixing?
|
24
|
+
klass_line += superclass_orig
|
25
|
+
end
|
26
|
+
klass_line
|
27
|
+
end
|
28
|
+
else
|
29
|
+
# Adding new namespace
|
30
|
+
previous_new_namespace_element = namespace_element_replacements[i - 1].first
|
31
|
+
content.sub!(
|
32
|
+
/((class|module) RENAMESPACED_#{previous_new_namespace_element})/,
|
33
|
+
"module RENAMESPACED_#{namespace_element_new}; \\1",
|
34
|
+
)
|
35
|
+
content.sub!(/^(end)/, "\\1\nend")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
content.gsub!('RENAMESPACED_', '')
|
39
|
+
content
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :paths
|
45
|
+
|
46
|
+
def source_and_dest_namespace_elements_without_common_prefix
|
47
|
+
source = paths.source_namespace_elements
|
48
|
+
dest = paths.destination_namespace_elements
|
49
|
+
source.each do
|
50
|
+
break if source.first != dest.first
|
51
|
+
|
52
|
+
source.shift
|
53
|
+
dest.shift
|
54
|
+
end
|
55
|
+
[source, dest]
|
56
|
+
end
|
57
|
+
|
58
|
+
def no_superclass_prefixing?
|
59
|
+
@no_superclass_prefixing
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Renamespace
|
4
|
+
class ReplacementsLogger
|
5
|
+
def initialize
|
6
|
+
@logged_replacements = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def log(search_str, replace_str)
|
10
|
+
return if logged_replacements.include?([search_str, replace_str])
|
11
|
+
|
12
|
+
logged_replacements << [search_str, replace_str]
|
13
|
+
puts Rainbow('%s -> %s' % [search_str, replace_str]).blue
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_accessor :logged_replacements
|
19
|
+
end
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: renamespace
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brendan Weibrecht
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-04-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: clamp
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.3.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.3.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: facets
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.1.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rainbow
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- brendan@weibrecht.net.au
|
58
|
+
executables:
|
59
|
+
- renamespace
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- README.md
|
64
|
+
- exe/renamespace
|
65
|
+
- lib/renamespace.rb
|
66
|
+
- lib/renamespace/directories.rb
|
67
|
+
- lib/renamespace/expand_relative_requires_in_file_content.rb
|
68
|
+
- lib/renamespace/expand_relative_requires_within_all_files.rb
|
69
|
+
- lib/renamespace/move_and_renamespace_source_file.rb
|
70
|
+
- lib/renamespace/move_spec_file.rb
|
71
|
+
- lib/renamespace/paths.rb
|
72
|
+
- lib/renamespace/rename_within_all_files.rb
|
73
|
+
- lib/renamespace/rename_within_file_content.rb
|
74
|
+
- lib/renamespace/renamespace_file_content.rb
|
75
|
+
- lib/renamespace/replacements_logger.rb
|
76
|
+
- lib/renamespace/version.rb
|
77
|
+
homepage: https://github.com/ZimbiX/renamespace
|
78
|
+
licenses:
|
79
|
+
- GPL-3.0
|
80
|
+
metadata:
|
81
|
+
homepage_uri: https://github.com/ZimbiX/renamespace
|
82
|
+
source_code_uri: https://github.com/ZimbiX/renamespace
|
83
|
+
changelog_uri: https://github.com/ZimbiX/renamespace/releases
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 2.5.0
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
requirements: []
|
99
|
+
rubygems_version: 3.2.16
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: A command-line tool to help Ruby developers refactor class/module namespacing
|
103
|
+
test_files: []
|