nested_inherited_jruby_include_package 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6f84fa63cba7b90887125a367a19fc17af87c88a0d5f783ea40052fc38378a35
4
+ data.tar.gz: 07c16bf6709eff7d1aad7ae47f5ced1c22c83ec07abb1fff73b22059592c40e1
5
+ SHA512:
6
+ metadata.gz: 35d06a985045b47f4edb3308c6257ec55b6b98d53f0d30f5794fd86298735bbcc61cb89659033e50cc6ef01dc0669006d2c75230baab62ab19b28c1db2d16922
7
+ data.tar.gz: 5c57fa8298931eaa9935e935e03a19a94b996ef6959dba90e1c59443677dddc59f4e87a7a9b33a63c3b77bffd323a5ad8cf933fb4cd12d4622b970e9293be246
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2020 Andy Maleh
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.
data/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # nested_inherited_jruby_include_package
2
+
3
+ JRuby's `include_package` (mentioned in https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby) includes Java packages in JRuby on `const_missing`. However, it does not trickle down to subclasses/submodules nor nested-classes/nested-modules.
4
+
5
+ `nested_inherited_jruby_include_package` patches up JRuby to add that capability.
6
+
7
+ Example (nesting):
8
+
9
+ ```ruby
10
+ require 'nested_inherited_jruby_include_package'
11
+
12
+ class OuterClass
13
+ include_package java.util
14
+ class InnerClass
15
+ def initialize
16
+ p Arrays.asList(1, 2, 3)
17
+ end
18
+ end
19
+ end
20
+
21
+ OuterClass::InnerClass.new
22
+ # prints #<Java::JavaUtil::Arrays::ArrayList:0x233fe9b6>
23
+ ```
24
+
25
+ Example (inheritance):
26
+
27
+ ```ruby
28
+ require 'nested_inherited_jruby_include_package'
29
+
30
+ class SuperClass
31
+ include_package java.util
32
+ end
33
+
34
+ class SubClass < SuperClass
35
+ def initialize
36
+ p Arrays.asList(1, 2, 3)
37
+ end
38
+ end
39
+
40
+ SubClass.new
41
+ # prints #<Java::JavaUtil::Arrays::ArrayList:0x7ce3cb8e>
42
+ ```
43
+
44
+ More examples can be found in:
45
+
46
+ [spec/lib/core/src/main/ruby/jruby/java/core_ext/module_spec.rb](spec/lib/core/src/main/ruby/jruby/java/core_ext/module_spec.rb)
47
+
48
+ # Setup
49
+
50
+ Add the following to `Gemfile`:
51
+ ```
52
+ gem 'nested_inherited_jruby_include_package', '~> 0.1.0'
53
+ ```
54
+
55
+ And, then run:
56
+ ```
57
+ jruby -S bundle install
58
+ ```
59
+
60
+ If you are not using Bundler, run:
61
+ ```
62
+ jruby -S gem install nested_inherited_jruby_include_package -v 0.1.0
63
+ ```
64
+
65
+ # Caveats
66
+
67
+ This gem relies on `Module#const_missing` after it aliases it to `Module#const_missing_without_nested_inherited_jruby_include_package`
68
+
69
+ As such, it works optimally if your project and loaded gems do not override `Module#const_missing`
70
+
71
+ # Implementation Note
72
+
73
+ To avoid method and constant pollution in `Module`, the implementation intentionally trades off code clarity for lack of pollution by not relying on methods, yet local lambdas, in modularizing logic.
74
+
75
+ # Issue Reporting
76
+
77
+ This is an early alpha. It has only been used in a couple of projects. As such, there are no guarantees for its functionality. Please report any issues you might discover when using on your own projects.
78
+
79
+ # License
80
+
81
+ The MIT License
82
+
83
+ [LICENSE.txt](LICENSE.txt)
84
+
85
+ # Copyright
86
+
87
+ Copyright (c) 2020 Andy Maleh
@@ -0,0 +1,117 @@
1
+ # Extensions to the standard Module package.
2
+ class Module
3
+
4
+ alias const_missing_without_nested_inherited_jruby_include_package const_missing
5
+
6
+ def const_missing(constant)
7
+ hidden_methods = {
8
+ included_packages_from_ancestors_namespaces: lambda do |m|
9
+ m.ancestors.map do |klass|
10
+ hidden_methods[:included_packages_from_namespaces].call(klass)
11
+ end.map(&:to_a).reduce([], :+).uniq
12
+ end,
13
+
14
+ included_packages_from_namespaces: lambda do |m|
15
+ hidden_methods[:namespaces].call(m).map do |klass|
16
+ hidden_methods[:included_packages].call(klass)
17
+ end.map(&:to_a).reduce([], :+).uniq
18
+ end,
19
+
20
+ included_packages: lambda do |m|
21
+ return [] unless m.respond_to?(:instance_variable_get)
22
+ m.instance_variable_set(:@included_packages, []) unless m.instance_variable_get(:@included_packages)
23
+ m.instance_variable_get(:@included_packages)
24
+ end,
25
+
26
+ java_aliases_from_ancestors_namespaces: lambda do |m|
27
+ m.ancestors.map do |klass|
28
+ hidden_methods[:java_aliases_from_namespaces].call(klass)
29
+ end.reverse.reduce({}, :merge)
30
+ end,
31
+
32
+ java_aliases_from_namespaces: lambda do |m|
33
+ hidden_methods[:namespaces].call(m).map do |klass|
34
+ hidden_methods[:java_aliases].call(klass)
35
+ end.reverse.reduce({}, :merge)
36
+ end,
37
+
38
+ java_aliases: lambda do |m|
39
+ return {} unless m.respond_to?(:instance_variable_get)
40
+ m.instance_variable_set(:@java_aliases, {}) unless m.instance_variable_get(:@java_aliases)
41
+ m.instance_variable_get(:@java_aliases)
42
+ end,
43
+
44
+ # Returns namespaces containing this module/class starting with self.
45
+ # Example: `Outer::Inner::Shape.namespaces` returns:
46
+ # => [Outer::Inner::Shape, Outer::Inner, Outer]
47
+ namespaces: lambda do |m|
48
+ return [m] if m.name.nil?
49
+ namespace_constants = m.name.split(/::/).map(&:to_sym)
50
+ namespace_constants.reduce([Object]) do |output, namespace_constant|
51
+ output += [output.last.const_get(namespace_constant)]
52
+ end[1..-1].uniq.reverse
53
+ end
54
+ }
55
+ all_included_packages = hidden_methods[:included_packages_from_ancestors_namespaces].call(self)
56
+ return const_missing_without_nested_inherited_jruby_include_package(constant) if all_included_packages.empty?
57
+ real_name = hidden_methods[:java_aliases_from_ancestors_namespaces].call(self)[constant] || constant
58
+
59
+ java_class = nil
60
+ last_error = nil
61
+
62
+ all_included_packages.each do |package|
63
+ begin
64
+ java_class = JavaUtilities.get_java_class("#{package}.#{real_name}")
65
+ rescue NameError => e
66
+ # we only rescue NameError, since other errors should bubble out
67
+ last_error = e
68
+ end
69
+ break if java_class
70
+ end
71
+
72
+ if java_class
73
+ return JavaUtilities.create_proxy_class(constant, java_class, self)
74
+ else
75
+ # try to chain to super's const_missing
76
+ begin
77
+ return const_missing_without_nested_inherited_jruby_include_package(constant)
78
+ rescue NameError => e
79
+ # super didn't find anything either, raise our Java error
80
+ raise NameError.new("#{constant} not found in packages #{all_included_packages.join(', ')}; last error: #{(last_error || e).message}")
81
+ end
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ ##
88
+ # Includes a Java package into this class/module. The Java classes in the
89
+ # package will become available in this class/module, unless a constant
90
+ # with the same name as a Java class is already defined.
91
+ #
92
+ def include_package(package)
93
+ hidden_methods = {
94
+ included_packages: lambda do |m|
95
+ return [] unless m.respond_to?(:instance_variable_get)
96
+ m.instance_variable_set(:@included_packages, []) unless m.instance_variable_get(:@included_packages)
97
+ m.instance_variable_get(:@included_packages)
98
+ end,
99
+ }
100
+ package = package.package_name if package.respond_to?(:package_name)
101
+ the_included_packages = hidden_methods[:included_packages].call(self)
102
+ the_included_packages << package unless the_included_packages.include?(package)
103
+ nil
104
+ end
105
+
106
+ def java_alias(new_id, old_id)
107
+ hidden_methods = {
108
+ java_aliases: lambda do |m|
109
+ return {} unless m.respond_to?(:instance_variable_get)
110
+ m.instance_variable_set(:@java_aliases, {}) unless m.instance_variable_get(:@java_aliases)
111
+ m.instance_variable_get(:@java_aliases)
112
+ end,
113
+ }
114
+ hidden_methods[:java_aliases].call(self)[new_id] = old_id
115
+ end
116
+
117
+ end
@@ -0,0 +1 @@
1
+ require_relative 'core/src/main/ruby/jruby/java/core_ext/module.rb'
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nested_inherited_jruby_include_package
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andy Maleh
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-04-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 3.5.0
19
+ name: rspec
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 3.5.0
27
+ - !ruby/object:Gem::Dependency
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '3.12'
33
+ name: rdoc
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.12'
41
+ - !ruby/object:Gem::Dependency
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 2.3.9
47
+ name: jeweler
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.3.9
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ name: simplecov
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: JRuby include_package implementation that works across nested/inherited
70
+ classes/modules
71
+ email: andy.am@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files:
75
+ - LICENSE.txt
76
+ - README.md
77
+ files:
78
+ - LICENSE.txt
79
+ - README.md
80
+ - lib/core/src/main/ruby/jruby/java/core_ext/module.rb
81
+ - lib/nested_inherited_jruby_include_package.rb
82
+ homepage: http://github.com/AndyObtiva/nested_inherited_jruby_include_package
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubygems_version: 3.0.6
102
+ signing_key:
103
+ specification_version: 4
104
+ summary: JRuby include_package implementation that works across nested/inherited classes/modules
105
+ test_files: []