striuct 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE.txt +21 -0
- data/README.md +19 -39
- data/lib/striuct.rb +3 -3
- data/lib/striuct/classmethods/README.md +2 -2
- data/lib/striuct/classmethods/adjustment.rb +15 -13
- data/lib/striuct/classmethods/attributes.rb +94 -92
- data/lib/striuct/classmethods/conflict_management.rb +109 -106
- data/lib/striuct/classmethods/constructor.rb +47 -54
- data/lib/striuct/classmethods/copy.rb +45 -43
- data/lib/striuct/classmethods/default.rb +23 -21
- data/lib/striuct/classmethods/enum.rb +46 -44
- data/lib/striuct/classmethods/fix.rb +23 -21
- data/lib/striuct/classmethods/hashdeepdupulicatable.rb +15 -15
- data/lib/striuct/classmethods/inner.rb +57 -55
- data/lib/striuct/classmethods/length.rb +12 -10
- data/lib/striuct/classmethods/macro.rb +110 -106
- data/lib/striuct/classmethods/names.rb +69 -65
- data/lib/striuct/classmethods/predicate.rb +131 -129
- data/lib/striuct/classmethods/requirements.rb +3 -1
- data/lib/striuct/classmethods/to_struct.rb +21 -18
- data/lib/striuct/classmethods/validation.rb +15 -13
- data/lib/striuct/instancemethods/README.md +2 -2
- data/lib/striuct/instancemethods/assign.rb +29 -27
- data/lib/striuct/instancemethods/cast.rb +28 -26
- data/lib/striuct/instancemethods/compare.rb +26 -24
- data/lib/striuct/instancemethods/default.rb +31 -29
- data/lib/striuct/instancemethods/delegate_class_methods.rb +35 -33
- data/lib/striuct/instancemethods/enum.rb +86 -84
- data/lib/striuct/instancemethods/getter.rb +39 -37
- data/lib/striuct/instancemethods/hashy.rb +99 -97
- data/lib/striuct/instancemethods/keyvalidatable.rb +8 -6
- data/lib/striuct/instancemethods/lock.rb +46 -44
- data/lib/striuct/instancemethods/object.rb +50 -48
- data/lib/striuct/instancemethods/requirements.rb +11 -9
- data/lib/striuct/instancemethods/safety.rb +11 -9
- data/lib/striuct/instancemethods/setter.rb +46 -45
- data/lib/striuct/instancemethods/to_s.rb +39 -37
- data/lib/striuct/instancemethods/validation.rb +31 -29
- data/lib/striuct/instancemethods/values.rb +50 -48
- data/lib/striuct/requirements.rb +3 -1
- data/lib/striuct/singleton_class.rb +12 -17
- data/lib/striuct/structs.rb +3 -3
- metadata +33 -178
- data/.gitignore +0 -35
- data/.travis.yml +0 -17
- data/.yardopts +0 -1
- data/Gemfile +0 -11
- data/MIT-LICENSE +0 -22
- data/Rakefile +0 -11
- data/benchmark/basics.rb +0 -56
- data/example/README.rb +0 -50
- data/example/example1.rb +0 -195
- data/example/example2.rb +0 -20
- data/example/see_trace.rb +0 -32
- data/striuct.gemspec +0 -45
- data/test/helper.rb +0 -3
- data/test/test_sglc-constructor.rb +0 -36
- data/test/test_subc-c-add_members.rb +0 -13
- data/test/test_subc-c-close_member.rb +0 -36
- data/test/test_subc-c-constructor.rb +0 -92
- data/test/test_subc-c-copy.rb +0 -71
- data/test/test_subc-c-freeze.rb +0 -36
- data/test/test_subc-c-inheritable.rb +0 -58
- data/test/test_subc-c-safety_naming.rb +0 -73
- data/test/test_subc-f-alias_member.rb +0 -54
- data/test/test_subc-f-enum.rb +0 -159
- data/test/test_subc-f-predicate.rb +0 -647
- data/test/test_subc-f-to_struct.rb +0 -61
- data/test/test_subc-f-validation_util.rb +0 -59
- data/test/test_subc-f_debug.rb +0 -39
- data/test/test_subc-f_name.rb +0 -525
- data/test/test_subc-i-accessor.rb +0 -138
- data/test/test_subc-i-adjuster.rb +0 -95
- data/test/test_subc-i-assign.rb +0 -53
- data/test/test_subc-i-basic.rb +0 -43
- data/test/test_subc-i-cast.rb +0 -27
- data/test/test_subc-i-compare.rb +0 -52
- data/test/test_subc-i-copy.rb +0 -23
- data/test/test_subc-i-default_value.rb +0 -129
- data/test/test_subc-i-freeze.rb +0 -19
- data/test/test_subc-i-hashlike.rb +0 -144
- data/test/test_subc-i-keyvalidatable.rb +0 -25
- data/test/test_subc-i-lock.rb +0 -40
- data/test/test_subc-i-must.rb +0 -30
- data/test/test_subc-i-to_s_family.rb +0 -26
- data/test/test_subc-i-validation_specific_conditions.rb +0 -297
- data/test/test_subc-i-validation_with_getter.rb +0 -33
- data/test/test_version.rb +0 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c59316edafe027980857f258404996caaee0be26a0ad3265acee3cb067477db6
|
4
|
+
data.tar.gz: '086afe2f12bb06050cd7964a774fd087e6a7a710f0d54fe6bb3c4e647490e2d7'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86c436676285e90dbafd4e1f9293b5cccfda99ce060e07a38893f4f0979c4c9f0b7c1c41da63e10ee479ff1323fa0f585c92113929bce766b072e577dc95b8cb
|
7
|
+
data.tar.gz: 0fca1e67d31013254edeb00043cf42699a3845b83bd4979db8623d0ef2786daff07db0ced0dcda068f297e1d577fca063703592f65242c26d793a3e17e9fb786
|
data/MIT-LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011 Kenichi Kamiya
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
striuct
|
2
2
|
=======
|
3
3
|
|
4
|
-
|
4
|
+
![Build Status](https://github.com/kachick/striuct/actions/workflows/test_behaviors.yml/badge.svg?branch=main)
|
5
5
|
[![Gem Version](https://badge.fury.io/rb/striuct.png)](http://badge.fury.io/rb/striuct)
|
6
|
-
[![Dependency Status](https://gemnasium.com/kachick/striuct.svg)](https://gemnasium.com/kachick/striuct)
|
7
6
|
|
8
7
|
Description
|
9
8
|
-----------
|
@@ -26,7 +25,7 @@ Features
|
|
26
25
|
* Member aliasing
|
27
26
|
* Inheritable
|
28
27
|
* Handling between nil <-> unassigned
|
29
|
-
*
|
28
|
+
* Similar API for Hash
|
30
29
|
|
31
30
|
### Onepoint
|
32
31
|
|
@@ -36,17 +35,26 @@ Features
|
|
36
35
|
Usage
|
37
36
|
-----
|
38
37
|
|
38
|
+
Require Ruby 2.6 or later
|
39
|
+
|
40
|
+
Add this line to your `Gemfile`
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
gem 'striuct', '>= 0.7.0', '< 0.8.0'
|
44
|
+
```
|
45
|
+
|
39
46
|
### Overview - Case 1
|
40
47
|
|
41
48
|
```ruby
|
42
49
|
require 'striuct'
|
43
50
|
|
44
51
|
class Person < Striuct
|
45
|
-
member :
|
46
|
-
alias_member :name, :
|
52
|
+
member :full_name, AND(String, /\A.+\z/) # Flexible Validation
|
53
|
+
alias_member :name, :full_name # Use other name
|
47
54
|
end
|
48
55
|
|
49
|
-
|
56
|
+
# Inheritable
|
57
|
+
class User < Person
|
50
58
|
member :id, Integer, # Looks typed validation
|
51
59
|
default_proc: ->{User.next_id} # With default value
|
52
60
|
|
@@ -57,12 +65,13 @@ class User < Person # Inheritable
|
|
57
65
|
end
|
58
66
|
|
59
67
|
john = User.new 'john'
|
60
|
-
john[:name] #=> 'john'
|
68
|
+
john[:name] #=> 'john'
|
61
69
|
john.name = '' #=> Exception # Validate with setter
|
62
70
|
john.id #=> 1
|
63
71
|
ken = User[name: 'ken'] # Construct from hash
|
64
72
|
ken.id #=> 2
|
65
73
|
```
|
74
|
+
|
66
75
|
### Overview - Case 2
|
67
76
|
|
68
77
|
```ruby
|
@@ -75,7 +84,7 @@ end
|
|
75
84
|
|
76
85
|
foo = Foo.new
|
77
86
|
|
78
|
-
# nil <->
|
87
|
+
# nil <-> unassigned
|
79
88
|
foo.foo #=> nil
|
80
89
|
foo.assigned?(:foo) #=> false
|
81
90
|
foo.foo = nil
|
@@ -103,37 +112,8 @@ end
|
|
103
112
|
UseMustOption.new #=> InvalidOperationError "`foo` require a value under `must` option "
|
104
113
|
```
|
105
114
|
|
106
|
-
|
107
|
-
### How to build flexible conditions ?
|
108
|
-
|
109
|
-
* That from validation library.
|
110
|
-
See the [validation-API](http://kachick.github.com/validation/yard/frames.html)
|
111
|
-
|
112
|
-
Requirements
|
113
|
-
-------------
|
114
|
-
|
115
|
-
* Ruby - [2.2 or later](http://travis-ci.org/#!/kachick/striuct)
|
116
|
-
|
117
|
-
Install
|
118
|
-
-------
|
119
|
-
|
120
|
-
```bash
|
121
|
-
gem install striuct
|
122
|
-
```
|
123
|
-
|
124
115
|
Link
|
125
116
|
----
|
126
117
|
|
127
|
-
* [
|
128
|
-
* [
|
129
|
-
* [API](http://www.rubydoc.info/github/kachick/striuct)
|
130
|
-
* [Issues](https://github.com/kachick/striuct/issues)
|
131
|
-
* [CI](http://travis-ci.org/#!/kachick/striuct)
|
132
|
-
* [gem](https://rubygems.org/gems/striuct)
|
133
|
-
|
134
|
-
License
|
135
|
-
--------
|
136
|
-
|
137
|
-
The MIT X11 License
|
138
|
-
Copyright (c) 2011 Kenichi Kamiya
|
139
|
-
See MIT-LICENSE for further details.
|
118
|
+
* [Repository](https://github.com/kachick/striuct)
|
119
|
+
* [API documents](https://kachick.github.io/striuct/)
|
data/lib/striuct.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# striuct - Struct++
|
2
4
|
# Copyright (c) 2011-2012 Kenichi Kamiya
|
3
5
|
|
4
6
|
# @abstract
|
5
7
|
class Striuct
|
6
|
-
|
7
8
|
class Error < StandardError; end
|
8
9
|
class InvalidOperationError < Error; end
|
9
|
-
|
10
10
|
end
|
11
11
|
|
12
|
-
require_relative 'striuct/requirements'
|
12
|
+
require_relative 'striuct/requirements'
|
@@ -1,15 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def adjuster_for(key)
|
7
|
-
autonym = autonym_for_key key
|
8
|
-
raise KeyError unless with_adjuster? autonym
|
9
|
-
|
10
|
-
_attributes_for(autonym).adjuster
|
11
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Striuct
|
4
|
+
module ClassMethods
|
5
|
+
# @group Adjuster
|
12
6
|
|
13
|
-
|
7
|
+
# @param [Symbol, String, #to_sym, Integer, #to_int] key - name / index
|
8
|
+
def adjuster_for(key)
|
9
|
+
autonym = autonym_for_key(key)
|
10
|
+
raise KeyError unless with_adjuster?(autonym)
|
14
11
|
|
15
|
-
|
12
|
+
_attributes_for(autonym).adjuster
|
13
|
+
end
|
14
|
+
|
15
|
+
# @endgroup
|
16
|
+
end
|
17
|
+
end
|
@@ -1,114 +1,116 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
VALUES.each do |role|
|
24
|
-
define_method :"with_#{role}?" do
|
25
|
-
@hash.has_key? role
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Striuct
|
4
|
+
module ClassMethods
|
5
|
+
# Attributes for autonym of each member
|
6
|
+
class Attributes
|
7
|
+
VALUES = [:condition,
|
8
|
+
:adjuster].freeze
|
9
|
+
|
10
|
+
BOOLEANS = [
|
11
|
+
:must,
|
12
|
+
:safety_setter,
|
13
|
+
:safety_getter
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@hash = {
|
18
|
+
must: false,
|
19
|
+
safety_setter: false,
|
20
|
+
safety_getter: false
|
21
|
+
}
|
26
22
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
23
|
+
|
24
|
+
VALUES.each do |role|
|
25
|
+
define_method :"with_#{role}?" do
|
26
|
+
@hash.key?(role)
|
27
|
+
end
|
28
|
+
|
29
|
+
define_method role do
|
30
|
+
@hash.fetch(role)
|
31
|
+
end
|
30
32
|
end
|
31
|
-
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def condition=(condition)
|
35
|
+
unless ::Validation.conditionable?(condition)
|
36
|
+
raise TypeError, 'wrong object for condition'
|
37
|
+
end
|
38
|
+
|
39
|
+
@hash[:condition] = condition
|
36
40
|
end
|
37
41
|
|
38
|
-
|
39
|
-
|
42
|
+
def adjuster=(adjuster)
|
43
|
+
unless ::Validation.adjustable?(adjuster)
|
44
|
+
raise ArgumentError, 'wrong object for adjuster'
|
45
|
+
end
|
40
46
|
|
41
|
-
|
42
|
-
unless ::Validation.adjustable? adjuster
|
43
|
-
raise ArgumentError, 'wrong object for adjuster'
|
47
|
+
@hash[:adjuster] = adjuster
|
44
48
|
end
|
45
49
|
|
46
|
-
|
47
|
-
|
50
|
+
BOOLEANS.each do |role|
|
51
|
+
define_method :"with_#{role}?" do
|
52
|
+
@hash.fetch(role)
|
53
|
+
end
|
54
|
+
|
55
|
+
define_method :"#{role}=" do |arg|
|
56
|
+
raise TypeError unless arg.equal?(true) || arg.equal?(false)
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
@hash.fetch role
|
58
|
+
@hash[role] = arg
|
59
|
+
end
|
52
60
|
end
|
53
|
-
|
54
|
-
define_method :"#{role}=" do |arg|
|
55
|
-
raise TypeError unless arg.equal?(true) or arg.equal?(false)
|
56
61
|
|
57
|
-
|
58
|
-
|
59
|
-
|
62
|
+
def with_default?
|
63
|
+
@hash.key?(:default_value)
|
64
|
+
end
|
60
65
|
|
61
|
-
|
62
|
-
|
63
|
-
|
66
|
+
def default_value
|
67
|
+
@hash.fetch(:default_value)
|
68
|
+
end
|
64
69
|
|
65
|
-
|
66
|
-
|
67
|
-
|
70
|
+
def default_type
|
71
|
+
@hash.fetch(:default_type)
|
72
|
+
end
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
74
|
+
# @param [Symbol] type - :value / :lazy
|
75
|
+
def set_default(value, type)
|
76
|
+
raise TypeError unless type.equal?(:value) || type.equal?(:lazy)
|
72
77
|
|
73
|
-
|
74
|
-
def set_default(value, type)
|
75
|
-
raise TypeError unless type.equal?(:value) or type.equal?(:lazy)
|
76
|
-
check_default_lazy_proc value if type.equal?(:lazy)
|
77
|
-
|
78
|
-
@hash[:default_type] = type
|
79
|
-
@hash[:default_value] = value
|
80
|
-
end
|
78
|
+
check_default_lazy_proc(value) if type.equal?(:lazy)
|
81
79
|
|
82
|
-
|
83
|
-
|
84
|
-
arity = _proc.arity
|
85
|
-
unless arity <= 2
|
86
|
-
raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
|
80
|
+
@hash[:default_type] = type
|
81
|
+
@hash[:default_value] = value
|
87
82
|
end
|
88
|
-
end
|
89
83
|
|
90
|
-
|
91
|
-
|
92
|
-
@hash.freeze
|
93
|
-
ret
|
94
|
-
end
|
84
|
+
def check_default_lazy_proc(proc)
|
85
|
+
raise TypeError unless proc.respond_to?(:call)
|
95
86
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
private
|
103
|
-
|
104
|
-
def initialize_copy(original)
|
105
|
-
ret = super original
|
106
|
-
@hash = @hash.dup
|
107
|
-
ret
|
108
|
-
end
|
87
|
+
arity = proc.arity
|
88
|
+
unless arity <= 2
|
89
|
+
raise ArgumentError, "wrong number of block parameter #{arity} for 0..2"
|
90
|
+
end
|
91
|
+
end
|
109
92
|
|
110
|
-
|
93
|
+
def freeze
|
94
|
+
ret = super
|
95
|
+
@hash.freeze
|
96
|
+
ret
|
97
|
+
end
|
98
|
+
|
99
|
+
def dup
|
100
|
+
ret = super
|
101
|
+
@hash = @hash.dup
|
102
|
+
ret
|
103
|
+
end
|
111
104
|
|
112
|
-
|
105
|
+
private
|
113
106
|
|
114
|
-
|
107
|
+
def initialize_copy(original)
|
108
|
+
ret = super(original)
|
109
|
+
@hash = @hash.dup
|
110
|
+
ret
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
private_constant :Attributes
|
115
|
+
end
|
116
|
+
end
|
@@ -1,112 +1,115 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# @group Member Conflict Management
|
4
|
-
|
5
|
-
# @return [Hash] Symbol => Fixnum
|
6
|
-
NAMING_RISKS = {
|
7
|
-
conflict: 10,
|
8
|
-
no_identifier: 9,
|
9
|
-
bad_manners: 5,
|
10
|
-
no_ascii: 3,
|
11
|
-
strict: 0
|
12
|
-
}.freeze
|
13
|
-
|
14
|
-
# @return [Hash] Symbol => Hash
|
15
|
-
CONFLICT_MANAGEMENT_LEVELS = {
|
16
|
-
struct: {error: 99, warn: 99},
|
17
|
-
warning: {error: 99, warn: 5},
|
18
|
-
error: {error: 9, warn: 5},
|
19
|
-
prevent: {error: 5, warn: 1},
|
20
|
-
nervous: {error: 1, warn: 1}
|
21
|
-
}.each(&:freeze).freeze
|
22
|
-
|
23
|
-
# @return [Symbol]
|
24
|
-
DEFAULT_CONFLICT_MANAGEMENT_LEVEL = :prevent
|
25
|
-
|
26
|
-
# @param [Object] name
|
27
|
-
# accpeptable the name into own member, under protect level of runtime
|
28
|
-
def cname?(name)
|
29
|
-
_check_safety_naming(name.to_sym){|r|r}
|
30
|
-
rescue Exception
|
31
|
-
false
|
32
|
-
end
|
33
|
-
|
34
|
-
attr_reader :conflict_management_level
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
# @param [Symbol, String, #to_sym] level
|
39
|
-
# @return [Symbol] level
|
40
|
-
# change level of management conflict member names
|
41
|
-
def set_conflict_management_level(level)
|
42
|
-
level = level.to_sym
|
43
|
-
raise NameError unless CONFLICT_MANAGEMENT_LEVELS.has_key? level
|
44
|
-
|
45
|
-
@conflict_management_level = level
|
46
|
-
end
|
1
|
+
# frozen_string_literal: true
|
47
2
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
# @return [void]
|
52
|
-
# @raise [ArgumentError] if no block given
|
53
|
-
# temp scope of a conflict_management_level
|
54
|
-
def conflict_management(level=DEFAULT_CONFLICT_MANAGEMENT_LEVEL)
|
55
|
-
before = @conflict_management_level
|
56
|
-
set_conflict_management_level level
|
57
|
-
|
58
|
-
yield
|
59
|
-
ensure
|
60
|
-
@conflict_management_level = before
|
61
|
-
self
|
62
|
-
end
|
63
|
-
|
64
|
-
# @param [Symbol] name
|
65
|
-
# @return [void]
|
66
|
-
# @yieldreturn [Boolean]
|
67
|
-
def _check_safety_naming(name)
|
68
|
-
estimation = _estimate_naming name
|
69
|
-
risk = NAMING_RISKS.fetch estimation
|
70
|
-
plevels = CONFLICT_MANAGEMENT_LEVELS.fetch @conflict_management_level
|
71
|
-
caution = "undesirable naming '#{name}', because #{estimation}"
|
72
|
-
|
73
|
-
r = (
|
74
|
-
case
|
75
|
-
when risk >= plevels.fetch(:error)
|
76
|
-
raise NameError, caution unless block_given?
|
77
|
-
false
|
78
|
-
when risk >= plevels.fetch(:warn)
|
79
|
-
warn caution unless block_given?
|
80
|
-
false
|
81
|
-
else
|
82
|
-
true
|
83
|
-
end
|
84
|
-
)
|
3
|
+
class Striuct
|
4
|
+
module ClassMethods
|
5
|
+
# @group Member Conflict Management
|
85
6
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
7
|
+
# @return [Hash] Symbol => Fixnum
|
8
|
+
NAMING_RISKS = {
|
9
|
+
conflict: 10,
|
10
|
+
no_identifier: 9,
|
11
|
+
bad_manners: 5,
|
12
|
+
no_ascii: 3,
|
13
|
+
strict: 0
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
# @return [Hash] Symbol => Hash
|
17
|
+
CONFLICT_MANAGEMENT_LEVELS = {
|
18
|
+
struct: { error: 99, warn: 99 },
|
19
|
+
warning: { error: 99, warn: 5 },
|
20
|
+
error: { error: 9, warn: 5 },
|
21
|
+
prevent: { error: 5, warn: 1 },
|
22
|
+
nervous: { error: 1, warn: 1 }
|
23
|
+
}.each(&:freeze).freeze
|
24
|
+
|
25
|
+
# @return [Symbol]
|
26
|
+
DEFAULT_CONFLICT_MANAGEMENT_LEVEL = :prevent
|
27
|
+
|
28
|
+
# @param [Object] name
|
29
|
+
# acceptable the name into own member, under protect level of runtime
|
30
|
+
def cname?(name)
|
31
|
+
_check_safety_naming(name.to_sym) { |r| r }
|
32
|
+
rescue Exception
|
33
|
+
false
|
94
34
|
end
|
95
35
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
36
|
+
attr_reader :conflict_management_level
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# @param [Symbol, String, #to_sym] level
|
41
|
+
# @return [Symbol] level
|
42
|
+
# change level of management conflict member names
|
43
|
+
def set_conflict_management_level(level)
|
44
|
+
level = level.to_sym
|
45
|
+
raise NameError unless CONFLICT_MANAGEMENT_LEVELS.key?(level)
|
46
|
+
|
47
|
+
@conflict_management_level = level
|
107
48
|
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# @endgroup
|
111
49
|
|
112
|
-
|
50
|
+
# @param [Symbol, String, #to_sym] level
|
51
|
+
# @see [#set_conflict_management_level]
|
52
|
+
# @yieldreturn [self]
|
53
|
+
# @return [void]
|
54
|
+
# @raise [ArgumentError] if no block given
|
55
|
+
# temp scope of a conflict_management_level
|
56
|
+
def conflict_management(level=DEFAULT_CONFLICT_MANAGEMENT_LEVEL)
|
57
|
+
before = @conflict_management_level
|
58
|
+
set_conflict_management_level(level)
|
59
|
+
|
60
|
+
yield
|
61
|
+
ensure
|
62
|
+
@conflict_management_level = before
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param [Symbol] name
|
67
|
+
# @return [void]
|
68
|
+
# @yieldreturn [Boolean]
|
69
|
+
def _check_safety_naming(name)
|
70
|
+
estimation = _estimate_naming(name)
|
71
|
+
risk = NAMING_RISKS.fetch(estimation)
|
72
|
+
plevels = CONFLICT_MANAGEMENT_LEVELS.fetch(@conflict_management_level)
|
73
|
+
caution = "undesirable naming '#{name}', because #{estimation}"
|
74
|
+
|
75
|
+
r = (
|
76
|
+
case
|
77
|
+
when risk >= plevels.fetch(:error)
|
78
|
+
raise NameError, caution unless block_given?
|
79
|
+
|
80
|
+
false
|
81
|
+
when risk >= plevels.fetch(:warn)
|
82
|
+
warn(caution) unless block_given?
|
83
|
+
false
|
84
|
+
else
|
85
|
+
true
|
86
|
+
end
|
87
|
+
)
|
88
|
+
|
89
|
+
yield r if block_given?
|
90
|
+
end
|
91
|
+
|
92
|
+
# @param [Symbol] name
|
93
|
+
# @return [Symbol]
|
94
|
+
def _estimate_naming(name)
|
95
|
+
if (instance_methods + private_instance_methods).include?(name)
|
96
|
+
return :conflict
|
97
|
+
end
|
98
|
+
|
99
|
+
return :no_ascii unless name.encoding.equal?(Encoding::ASCII)
|
100
|
+
|
101
|
+
case name
|
102
|
+
when /\W/, /\A[^a-zA-Z_]/, :''
|
103
|
+
:no_identifier
|
104
|
+
when /\Aeach/, /\A__[^_]*__\z/, /\A_[^_]*\z/, /[!?]\z/, /\Ato_/
|
105
|
+
:bad_manners
|
106
|
+
when /\A[a-zA-Z_]\w*\z/
|
107
|
+
:strict
|
108
|
+
else
|
109
|
+
raise 'must not happen'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# @endgroup
|
114
|
+
end
|
115
|
+
end
|