renamespace 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build status](https://badge.buildkite.com/96fe2532aa6c155b7efc6adc355a6aa58c704c29df1a739df2.svg?branch=master)](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: []
|