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.
Files changed (48) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +56 -0
  4. data/Guardfile +9 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +151 -0
  7. data/Rakefile +1 -0
  8. data/bin/defgen +5 -0
  9. data/defgen.gemspec +24 -0
  10. data/lib/defgen/.DS_Store +0 -0
  11. data/lib/defgen/cli.rb +47 -0
  12. data/lib/defgen/decorators/getter_decorator.rb +17 -0
  13. data/lib/defgen/decorators/setter_decorator.rb +11 -0
  14. data/lib/defgen/decorators.rb +2 -0
  15. data/lib/defgen/defaultfile.rb +65 -0
  16. data/lib/defgen/defaultfile_builder.rb +14 -0
  17. data/lib/defgen/defaultfile_parser.rb +41 -0
  18. data/lib/defgen/generators/.DS_Store +0 -0
  19. data/lib/defgen/generators/template/template_generator.rb +38 -0
  20. data/lib/defgen/generators/template/templates/constant.erb +1 -0
  21. data/lib/defgen/generators/template/templates/getter.erb +4 -0
  22. data/lib/defgen/generators/template/templates/implementation.erb +19 -0
  23. data/lib/defgen/generators/template/templates/interface.erb +17 -0
  24. data/lib/defgen/generators/template/templates/property.erb +1 -0
  25. data/lib/defgen/generators/template/templates/setter.erb +4 -0
  26. data/lib/defgen/generators/template.rb +1 -0
  27. data/lib/defgen/generators.rb +1 -0
  28. data/lib/defgen/installer.rb +75 -0
  29. data/lib/defgen/property/attributes.rb +29 -0
  30. data/lib/defgen/property.rb +30 -0
  31. data/lib/defgen/string_ext.rb +5 -0
  32. data/lib/defgen/version.rb +3 -0
  33. data/lib/defgen/xcodeproj_adapter.rb +48 -0
  34. data/lib/defgen.rb +14 -0
  35. data/spec/integration/defaultfile_parse_spec.rb +28 -0
  36. data/spec/support/property_accessor_examples.rb +12 -0
  37. data/spec/support/property_examples.rb +58 -0
  38. data/spec/support/spec_helper.rb +2 -0
  39. data/spec/unit/decorators/getter_decorator_spec.rb +31 -0
  40. data/spec/unit/decorators/setter_decorator_spec.rb +42 -0
  41. data/spec/unit/defaultfile_builder_spec.rb +12 -0
  42. data/spec/unit/defaultfile_parser_spec.rb +42 -0
  43. data/spec/unit/defautfile_spec.rb +11 -0
  44. data/spec/unit/property/attributes_spec.rb +48 -0
  45. data/spec/unit/property/property_spec.rb +10 -0
  46. data/spec/unit/string_ext_spec.rb +17 -0
  47. data/spec/unit/xcodeproj_adapter_spec.rb +10 -0
  48. 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,5 @@
1
+ class String
2
+ def upcase_first
3
+ self.dup.tap { |string| string[0] = string[0].upcase }
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Defgen
2
+ VERSION = "0.0.1"
3
+ end
@@ -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,2 @@
1
+ require 'bundler/setup'
2
+ require 'defgen'
@@ -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,11 @@
1
+ require 'support/spec_helper'
2
+ require 'defgen/defaultfile'
3
+
4
+ module Defgen
5
+ describe Defaultfile do
6
+ subject(:defaultfile) { Defaultfile.new [], nil }
7
+
8
+ it { should respond_to :to_iface }
9
+ it { should respond_to :to_imp }
10
+ end
11
+ 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,10 @@
1
+ require 'support/spec_helper'
2
+ require 'support/property_examples'
3
+ require 'defgen/property'
4
+
5
+ module Defgen
6
+ describe Property do
7
+ it_behaves_like "a property"
8
+ subject(:property) { Property.new }
9
+ end
10
+ 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
@@ -0,0 +1,10 @@
1
+ require 'support/spec_helper'
2
+ require 'defgen/xcodeproj_adapter'
3
+
4
+ module Defgen
5
+ describe XcodeprojAdapter do
6
+ it "takes a name, or" do
7
+
8
+ end
9
+ end
10
+ end