defgen 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|