defgen 0.0.1
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.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +151 -0
- data/Rakefile +1 -0
- data/bin/defgen +5 -0
- data/defgen.gemspec +24 -0
- data/lib/defgen/.DS_Store +0 -0
- data/lib/defgen/cli.rb +47 -0
- data/lib/defgen/decorators/getter_decorator.rb +17 -0
- data/lib/defgen/decorators/setter_decorator.rb +11 -0
- data/lib/defgen/decorators.rb +2 -0
- data/lib/defgen/defaultfile.rb +65 -0
- data/lib/defgen/defaultfile_builder.rb +14 -0
- data/lib/defgen/defaultfile_parser.rb +41 -0
- data/lib/defgen/generators/.DS_Store +0 -0
- data/lib/defgen/generators/template/template_generator.rb +38 -0
- data/lib/defgen/generators/template/templates/constant.erb +1 -0
- data/lib/defgen/generators/template/templates/getter.erb +4 -0
- data/lib/defgen/generators/template/templates/implementation.erb +19 -0
- data/lib/defgen/generators/template/templates/interface.erb +17 -0
- data/lib/defgen/generators/template/templates/property.erb +1 -0
- data/lib/defgen/generators/template/templates/setter.erb +4 -0
- data/lib/defgen/generators/template.rb +1 -0
- data/lib/defgen/generators.rb +1 -0
- data/lib/defgen/installer.rb +75 -0
- data/lib/defgen/property/attributes.rb +29 -0
- data/lib/defgen/property.rb +30 -0
- data/lib/defgen/string_ext.rb +5 -0
- data/lib/defgen/version.rb +3 -0
- data/lib/defgen/xcodeproj_adapter.rb +48 -0
- data/lib/defgen.rb +14 -0
- data/spec/integration/defaultfile_parse_spec.rb +28 -0
- data/spec/support/property_accessor_examples.rb +12 -0
- data/spec/support/property_examples.rb +58 -0
- data/spec/support/spec_helper.rb +2 -0
- data/spec/unit/decorators/getter_decorator_spec.rb +31 -0
- data/spec/unit/decorators/setter_decorator_spec.rb +42 -0
- data/spec/unit/defaultfile_builder_spec.rb +12 -0
- data/spec/unit/defaultfile_parser_spec.rb +42 -0
- data/spec/unit/defautfile_spec.rb +11 -0
- data/spec/unit/property/attributes_spec.rb +48 -0
- data/spec/unit/property/property_spec.rb +10 -0
- data/spec/unit/string_ext_spec.rb +17 -0
- data/spec/unit/xcodeproj_adapter_spec.rb +10 -0
- metadata +186 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
module Defgen
|
2
|
+
class Installer
|
3
|
+
def self.install(path, defaultfile, proj)
|
4
|
+
new(path, defaultfile, proj).install
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize path, defaultfile, proj
|
8
|
+
self.path, self.defaultfile, self.proj = path, defaultfile, proj
|
9
|
+
end
|
10
|
+
|
11
|
+
def install
|
12
|
+
install_files
|
13
|
+
configure_xcode
|
14
|
+
proj.save
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_accessor :path, :defaultfile, :proj
|
20
|
+
|
21
|
+
def install_files
|
22
|
+
FileUtils.mkdir_p properties_path
|
23
|
+
|
24
|
+
{ '.h' => defaultfile.to_iface, '.m' => defaultfile.to_imp }.each do |ext, content|
|
25
|
+
File.open("#{file_path}#{ext}", 'w') do |f|
|
26
|
+
f.puts content
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def configure_xcode
|
32
|
+
return if proj.objects.map { |o| o.name if o.respond_to? :name }.include? "#{file_name}.h"
|
33
|
+
|
34
|
+
main_group.new_file "#{file_path}.h", properties_group
|
35
|
+
implementation = main_group.new_file "#{file_path}.m", properties_group
|
36
|
+
main_target.source_build_phase.add_file_reference implementation
|
37
|
+
end
|
38
|
+
|
39
|
+
def properties_path
|
40
|
+
"#{File.dirname(path)}/#{target_name}/#{prefix}Properties"
|
41
|
+
end
|
42
|
+
|
43
|
+
def properties_group
|
44
|
+
"#{prefix}Properties"
|
45
|
+
end
|
46
|
+
|
47
|
+
def properties_group_path
|
48
|
+
"#{main_target_name}/#{properties_group}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_path
|
52
|
+
"#{properties_path}/#{file_name}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def file_name
|
56
|
+
"NSUserDefaults+#{prefix}Properties"
|
57
|
+
end
|
58
|
+
|
59
|
+
def prefix
|
60
|
+
proj.prefix.upcase
|
61
|
+
end
|
62
|
+
|
63
|
+
def main_group
|
64
|
+
proj.main_group
|
65
|
+
end
|
66
|
+
|
67
|
+
def main_target
|
68
|
+
proj.main_target
|
69
|
+
end
|
70
|
+
|
71
|
+
def target_name
|
72
|
+
main_target.name
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Defgen
|
2
|
+
class Property
|
3
|
+
class UnsupportedOwnershipError < ArgumentError; end
|
4
|
+
class Attributes
|
5
|
+
VALID_OWNERSHIPS = [:strong, :weak, :assign, :unsafe_unretained, :retain, :copy]
|
6
|
+
attr_accessor :ownership
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@ownership = :strong
|
10
|
+
end
|
11
|
+
|
12
|
+
def ownership= ownership
|
13
|
+
raise UnsupportedOwnershipError unless ownership.nil? || VALID_OWNERSHIPS.include?(ownership)
|
14
|
+
@ownership = ownership
|
15
|
+
end
|
16
|
+
|
17
|
+
VALID_OWNERSHIPS.each do |ownership|
|
18
|
+
# Turn valid ownerships into predicate methods. e.g. strong?
|
19
|
+
define_method "#{ownership}?" do
|
20
|
+
instance_variable_get("@ownership") == ownership
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"(#{['nonatomic', ownership].compact.join(', ')})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Defgen
|
2
|
+
class Property
|
3
|
+
VALID_TYPES = ['NSData *', 'NSArray *', 'BOOL ', 'NSDictionary *', 'float ', 'NSInteger ', 'id ', 'NSString *', 'double ', 'NSURL *']
|
4
|
+
attr_accessor :name, :objc_type, :message_prefix, :prefix, :attributes, :object_setter
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
self.attributes = Attributes.new
|
8
|
+
yield self, attributes if block_given?
|
9
|
+
end
|
10
|
+
|
11
|
+
def objc_type= objc_type
|
12
|
+
raise ArgumentError unless VALID_TYPES.include? objc_type
|
13
|
+
@objc_type = objc_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def key
|
17
|
+
"#{prefix.upcase}#{name.upcase_first}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def parameter
|
21
|
+
name
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_binding
|
25
|
+
binding
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'defgen/property/attributes'
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module Defgen
|
4
|
+
class XcodeprojAdapter
|
5
|
+
def initialize proj, path
|
6
|
+
@proj, @path = proj, path
|
7
|
+
end
|
8
|
+
|
9
|
+
def name
|
10
|
+
@proj.targets.first.name
|
11
|
+
end
|
12
|
+
|
13
|
+
def prefix
|
14
|
+
prefix = root_object.attributes['CLASSPREFIX']
|
15
|
+
if prefix.nil? || prefix.empty?
|
16
|
+
'PS'
|
17
|
+
else
|
18
|
+
prefix.upcase
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def objects
|
23
|
+
@proj.objects
|
24
|
+
end
|
25
|
+
|
26
|
+
def organization
|
27
|
+
root_object.attributes['ORGANIZATIONNAME']
|
28
|
+
end
|
29
|
+
|
30
|
+
def main_group
|
31
|
+
root_object.main_group.groups.first
|
32
|
+
end
|
33
|
+
|
34
|
+
def main_target
|
35
|
+
root_object.targets.first
|
36
|
+
end
|
37
|
+
|
38
|
+
def save
|
39
|
+
@proj.save_as @path
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def root_object
|
45
|
+
@proj.root_object
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/defgen.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Defgen
|
2
|
+
end
|
3
|
+
|
4
|
+
require 'defgen/string_ext'
|
5
|
+
require 'defgen/cli'
|
6
|
+
require 'defgen/decorators'
|
7
|
+
require 'defgen/defaultfile'
|
8
|
+
require 'defgen/defaultfile_builder'
|
9
|
+
require 'defgen/defaultfile_parser'
|
10
|
+
require 'defgen/installer'
|
11
|
+
require 'defgen/generators'
|
12
|
+
require 'defgen/property'
|
13
|
+
require 'defgen/version'
|
14
|
+
require 'defgen/xcodeproj_adapter'
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'defgen/defaultfile'
|
3
|
+
|
4
|
+
module Defgen
|
5
|
+
describe 'Defaultfile.parse' do
|
6
|
+
|
7
|
+
# [
|
8
|
+
# { prefix: 'bool', name: 'valid', objc_type: 'BOOL', ownership: :assign },
|
9
|
+
# { prefix: 'array', name: 'collection', objc_type: 'NSArray *', ownership: :strong },
|
10
|
+
# { prefix: 'data', name: 'someData', objc_type: 'NSData *', ownership: :strong },
|
11
|
+
# { prefix: 'dictionary', name: 'options', objc_type: 'NSDictionary *', ownership: :strong },
|
12
|
+
# { prefix: 'float', name: 'ratio', objc_type: 'float', ownership: :assign },
|
13
|
+
# { prefix: 'integer', name: 'count', objc_type: 'NSInteger', ownership: :assign },
|
14
|
+
# { prefix: 'object', name: 'someObject', objc_type: 'id', ownership: :strong },
|
15
|
+
# { prefix: 'string', name: 'user_name', objc_type: 'NSString *', ownership: :copy },
|
16
|
+
# { prefix: 'double', name: 'ratio', objc_type: 'double', ownership: :assign },
|
17
|
+
# { prefix: 'url', name: 'someWebsite', objc_type: 'NSURL *', ownership: :strong },
|
18
|
+
# ].each do |options|
|
19
|
+
# it "creates a valid #{options[:prefix]}" do
|
20
|
+
# result = Defaultfile.parse "#{options[:prefix]} '#{options[:name]}'"
|
21
|
+
# result.name.should eq(options[:name])
|
22
|
+
# result.message_prefix.should eq(options[:prefix])
|
23
|
+
# result.objc_type.should eq(options[:objc_type])
|
24
|
+
# result.attributes.ownership.should eq(options[:ownership])
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
|
3
|
+
module Defgen
|
4
|
+
shared_examples "property accessors" do
|
5
|
+
it { should respond_to :name }
|
6
|
+
it { should respond_to :objc_type }
|
7
|
+
it { should respond_to :message_prefix }
|
8
|
+
it { should respond_to :attributes }
|
9
|
+
it { should respond_to :object_setter }
|
10
|
+
it { should respond_to :parameter }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'defgen/property'
|
3
|
+
|
4
|
+
module Defgen
|
5
|
+
shared_examples "a property" do
|
6
|
+
let(:property) { described_class.new }
|
7
|
+
|
8
|
+
it { should respond_to :name }
|
9
|
+
it { should respond_to :objc_type }
|
10
|
+
it { should respond_to :message_prefix }
|
11
|
+
it { should respond_to :attributes }
|
12
|
+
it { should respond_to :object_setter }
|
13
|
+
it { should respond_to :parameter }
|
14
|
+
|
15
|
+
specify { expect { |b| described_class.new(&b) }.to yield_control }
|
16
|
+
|
17
|
+
it "should be able to yield on new" do
|
18
|
+
expect {
|
19
|
+
described_class.new do |property, attributes|
|
20
|
+
property.objc_type = 'NSData *'
|
21
|
+
end
|
22
|
+
}.to_not raise_error
|
23
|
+
|
24
|
+
described_class.new do |property, attributes|
|
25
|
+
property.should respond_to :name
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "objc_type=" do
|
30
|
+
good_types = Property::VALID_TYPES
|
31
|
+
bad_types = ['Test *', 'NSURLConnection *']
|
32
|
+
|
33
|
+
good_types.each do |type|
|
34
|
+
it "should allow the objc_type #{type}" do
|
35
|
+
expect { property.objc_type = type }.to_not raise_error
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
bad_types.each do |type|
|
40
|
+
it "should not allow the objc_type #{type}" do
|
41
|
+
expect { property.objc_type = type }.to raise_error ArgumentError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
[
|
47
|
+
[ 'test', 'PSTest'],
|
48
|
+
[ 'isValid', 'PSIsValid'],
|
49
|
+
[ 'under_score', 'PSUnder_score']
|
50
|
+
].each do |name, expected|
|
51
|
+
it "returns an appropriate key for #{name}" do
|
52
|
+
property.name = name
|
53
|
+
property.prefix = 'ps'
|
54
|
+
property.key.should eq(expected)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'support/property_accessor_examples'
|
3
|
+
require 'defgen/property'
|
4
|
+
require 'defgen/decorators/getter_decorator'
|
5
|
+
|
6
|
+
module Defgen
|
7
|
+
describe GetterDecorator do
|
8
|
+
include_examples "property accessors"
|
9
|
+
|
10
|
+
before do
|
11
|
+
@property = Property.new
|
12
|
+
end
|
13
|
+
|
14
|
+
subject(:decorator) { GetterDecorator.new(@property) }
|
15
|
+
|
16
|
+
[
|
17
|
+
['NSData *', 'NSData *'],
|
18
|
+
['BOOL ', 'BOOL']
|
19
|
+
].each do |input, output|
|
20
|
+
it "strips white space from the objc_type" do
|
21
|
+
@property.objc_type = input
|
22
|
+
decorator.objc_type.should eq(output)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
it "downcases the prefix" do
|
27
|
+
@property.prefix = 'PS'
|
28
|
+
decorator.prefix.should eq('ps')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'support/property_accessor_examples'
|
3
|
+
require 'defgen/property'
|
4
|
+
require 'defgen/decorators/setter_decorator'
|
5
|
+
|
6
|
+
module Defgen
|
7
|
+
describe SetterDecorator do
|
8
|
+
include_examples "property accessors"
|
9
|
+
|
10
|
+
before do
|
11
|
+
@property = Property.new
|
12
|
+
end
|
13
|
+
|
14
|
+
subject(:decorator) { SetterDecorator.new(@property) }
|
15
|
+
|
16
|
+
[
|
17
|
+
['ps', 'Ps'],
|
18
|
+
['PS', 'Ps']
|
19
|
+
].each do |input, expected|
|
20
|
+
it "camelizes prefix" do
|
21
|
+
@property.prefix = input
|
22
|
+
decorator.prefix.should eq(expected)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
[
|
27
|
+
['data', 'Data'],
|
28
|
+
['bool', 'Bool']
|
29
|
+
].each do |message_prefix, expected|
|
30
|
+
it "generates a camalized message_prefix '#{expected}" do
|
31
|
+
@property.message_prefix = message_prefix
|
32
|
+
decorator.message_prefix.should eq(expected)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "uses an Object setter" do
|
37
|
+
@property.object_setter = true
|
38
|
+
@property.message_prefix = 'Bool'
|
39
|
+
decorator.message_prefix.should eq('Object')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'defgen/defaultfile_builder'
|
3
|
+
|
4
|
+
module Defgen
|
5
|
+
describe DefaultfileBuilder do
|
6
|
+
subject(:builder) { DefaultfileBuilder.new }
|
7
|
+
|
8
|
+
it { should respond_to :parser }
|
9
|
+
# it { should respond_to :project_settings }
|
10
|
+
it { should respond_to :build }
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'defgen/defaultfile_parser'
|
3
|
+
require 'defgen/defaultfile'
|
4
|
+
|
5
|
+
module Defgen
|
6
|
+
describe DefaultfileParser do
|
7
|
+
subject(:defaultfile_parser) { DefaultfileParser.new }
|
8
|
+
|
9
|
+
it { DefaultfileParser.should respond_to :parse }
|
10
|
+
|
11
|
+
%w(array bool data dictionary float integer object string double url).each do |method|
|
12
|
+
it { should respond_to method }
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns a Enumerable" do
|
16
|
+
DefaultfileParser.parse('').should be_a_kind_of Enumerable
|
17
|
+
end
|
18
|
+
|
19
|
+
[
|
20
|
+
[ 'array', 'array', 'NSArray *', :strong, true ],
|
21
|
+
[ 'bool', 'bool', 'BOOL ', :assign, false ],
|
22
|
+
[ 'data', 'data', 'NSData *', :strong, true ],
|
23
|
+
[ 'dictionary', 'dictionary', 'NSDictionary *', :strong, true ],
|
24
|
+
[ 'float', 'float', 'float ', :assign, false ],
|
25
|
+
[ 'integer', 'integer', 'NSInteger ', :assign, false ],
|
26
|
+
[ 'object', 'object', 'id ', :strong, true ],
|
27
|
+
[ 'string', 'string', 'NSString *', :copy, true ],
|
28
|
+
[ 'double', 'double', 'double ', :assign, false ],
|
29
|
+
[ 'url', 'URL', 'NSURL *', :strong, false ]
|
30
|
+
].each do |method_name, prefix, objc_type, ownership, object_setter|
|
31
|
+
it "parses the string #{method_name} 'iVar'" do
|
32
|
+
property = defaultfile_parser.parse("#{method_name} 'iVar'").first
|
33
|
+
|
34
|
+
property.name.should eq('iVar')
|
35
|
+
property.object_setter.should eq(object_setter)
|
36
|
+
property.message_prefix.should eq(prefix)
|
37
|
+
property.objc_type.should eq(objc_type)
|
38
|
+
property.attributes.ownership.should eq(ownership)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'defgen/property/attributes'
|
3
|
+
|
4
|
+
module Defgen
|
5
|
+
class Property
|
6
|
+
describe Attributes do
|
7
|
+
subject(:attributes) { Attributes.new }
|
8
|
+
|
9
|
+
it { should respond_to :ownership }
|
10
|
+
|
11
|
+
Attributes::VALID_OWNERSHIPS.each do |semantic|
|
12
|
+
it "creates the predicate method #{semantic}?" do
|
13
|
+
should respond_to "#{semantic}?"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "uses strong as the default ownership" do
|
18
|
+
attributes.ownership.should == :strong
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "ownerships=" do
|
22
|
+
specify { expect { attributes.ownership = :a }.to raise_error UnsupportedOwnershipError }
|
23
|
+
|
24
|
+
Attributes::VALID_OWNERSHIPS.each do |semantic|
|
25
|
+
it "allows an ownership type of #{semantic}" do
|
26
|
+
expect { attributes.ownership = semantic }.to_not raise_error
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "to_s" do
|
32
|
+
it "should default to (nonatomic, strong)" do
|
33
|
+
attributes.to_s.should eq('(nonatomic, strong)')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should include correct ownership" do
|
37
|
+
attributes.ownership = :weak
|
38
|
+
attributes.to_s.should eq('(nonatomic, weak)')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should allow nil setter semantic" do
|
42
|
+
attributes.ownership = nil
|
43
|
+
attributes.to_s.should eq('(nonatomic)')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'support/spec_helper'
|
2
|
+
require 'defgen/string_ext'
|
3
|
+
|
4
|
+
module Defgen
|
5
|
+
describe String do
|
6
|
+
[
|
7
|
+
[ 'HEY', 'HEY' ],
|
8
|
+
[ 'Hey', 'Hey' ],
|
9
|
+
[ 'hey', 'Hey' ],
|
10
|
+
[ 'hEy', 'HEy' ]
|
11
|
+
].each do |input, expected|
|
12
|
+
it "upcases the first letter of #{input}" do
|
13
|
+
input.upcase_first.should eq(expected)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|