xcodeproj 0.18.0 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/bin/xcodeproj +5 -5
  3. data/lib/xcodeproj.rb +0 -2
  4. data/lib/xcodeproj/command.rb +26 -17
  5. data/lib/xcodeproj/command/project_diff.rb +8 -11
  6. data/lib/xcodeproj/command/show.rb +8 -10
  7. data/lib/xcodeproj/command/sort.rb +4 -7
  8. data/lib/xcodeproj/command/target_diff.rb +4 -5
  9. data/lib/xcodeproj/config.rb +64 -57
  10. data/lib/xcodeproj/config/other_linker_flags_parser.rb +62 -0
  11. data/lib/xcodeproj/constants.rb +31 -30
  12. data/lib/xcodeproj/differ.rb +5 -9
  13. data/lib/xcodeproj/gem_version.rb +1 -2
  14. data/lib/xcodeproj/helper.rb +5 -4
  15. data/lib/xcodeproj/plist_helper.rb +46 -11
  16. data/lib/xcodeproj/project.rb +16 -20
  17. data/lib/xcodeproj/project/case_converter.rb +59 -0
  18. data/lib/xcodeproj/project/object.rb +40 -30
  19. data/lib/xcodeproj/project/object/build_configuration.rb +1 -5
  20. data/lib/xcodeproj/project/object/build_file.rb +1 -4
  21. data/lib/xcodeproj/project/object/build_phase.rb +2 -13
  22. data/lib/xcodeproj/project/object/build_rule.rb +0 -3
  23. data/lib/xcodeproj/project/object/configuration_list.rb +0 -4
  24. data/lib/xcodeproj/project/object/container_item_proxy.rb +2 -4
  25. data/lib/xcodeproj/project/object/file_reference.rb +3 -6
  26. data/lib/xcodeproj/project/object/group.rb +6 -14
  27. data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +64 -13
  28. data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +4 -6
  29. data/lib/xcodeproj/project/object/native_target.rb +18 -29
  30. data/lib/xcodeproj/project/object/reference_proxy.rb +0 -4
  31. data/lib/xcodeproj/project/object/root_object.rb +4 -8
  32. data/lib/xcodeproj/project/object/target_dependency.rb +1 -4
  33. data/lib/xcodeproj/project/object_attributes.rb +76 -33
  34. data/lib/xcodeproj/project/object_dictionary.rb +76 -63
  35. data/lib/xcodeproj/project/object_list.rb +5 -9
  36. data/lib/xcodeproj/project/project_helper.rb +2 -7
  37. data/lib/xcodeproj/project/xcproj_helper.rb +0 -2
  38. data/lib/xcodeproj/scheme.rb +12 -15
  39. data/lib/xcodeproj/user_interface.rb +0 -4
  40. data/lib/xcodeproj/workspace.rb +36 -23
  41. data/lib/xcodeproj/workspace/file_reference.rb +3 -3
  42. data/lib/xcodeproj/xcodebuild_helper.rb +0 -6
  43. metadata +20 -18
@@ -1,14 +1,12 @@
1
1
  module Xcodeproj
2
2
  class Project
3
3
  module Object
4
-
5
4
  # Apparently a proxy for a reference object which might belong another
6
5
  # project contained in the same workspace of the project document.
7
6
  #
8
7
  # This class is used for referencing the products of another project.
9
8
  #
10
9
  class PBXReferenceProxy < AbstractObject
11
-
12
10
  # @!group Attributes
13
11
 
14
12
  # @return [String] the path of the referenced filed.
@@ -46,9 +44,7 @@ module Xcodeproj
46
44
  end
47
45
 
48
46
  #---------------------------------------------------------------------#
49
-
50
47
  end
51
48
  end
52
49
  end
53
50
  end
54
-
@@ -1,11 +1,9 @@
1
1
  module Xcodeproj
2
2
  class Project
3
3
  module Object
4
-
5
4
  # This class represents the root object of a project document.
6
5
  #
7
6
  class PBXProject < AbstractObject
8
-
9
7
  # @!group Attributes
10
8
 
11
9
  # @return [ObjectList<PBXNativeTarget>] a list of all the targets in
@@ -22,7 +20,7 @@ module Xcodeproj
22
20
  # - `LastUpgradeCheck`
23
21
  # - `ORGANIZATIONNAME`
24
22
  #
25
- attribute :attributes, Hash, {'LastUpgradeCheck' => Constants::LAST_UPGRADE_CHECK }
23
+ attribute :attributes, Hash, 'LastUpgradeCheck' => Constants::LAST_UPGRADE_CHECK
26
24
 
27
25
  # @return [XCConfigurationList] the configuration list of the project.
28
26
  #
@@ -64,11 +62,9 @@ module Xcodeproj
64
62
 
65
63
  # @return [Array<ObjectDictionary>] any reference to other projects.
66
64
  #
67
- has_many_references_by_keys :project_references, {
68
- :project_ref => PBXFileReference,
69
- :product_group => PBXGroup
70
- }
71
-
65
+ has_many_references_by_keys :project_references,
66
+ :project_ref => PBXFileReference,
67
+ :product_group => PBXGroup
72
68
  end
73
69
  end
74
70
  end
@@ -1,11 +1,9 @@
1
1
  module Xcodeproj
2
2
  class Project
3
3
  module Object
4
-
5
4
  # Represents a dependency of a target on another one.
6
5
  #
7
6
  class PBXTargetDependency < AbstractObject
8
-
9
7
  # @!group Attributes
10
8
 
11
9
  # @return [PBXNativeTarget] the target that needs to be built to
@@ -28,7 +26,6 @@ module Xcodeproj
28
26
  #
29
27
  attribute :name, String
30
28
 
31
-
32
29
  public
33
30
 
34
31
  # @!group AbstractObject Hooks
@@ -47,7 +44,7 @@ module Xcodeproj
47
44
  #
48
45
  # @see AbstractObject#sort_recursively
49
46
  #
50
- def sort_recursively(options = nil)
47
+ def sort_recursively(_options = nil)
51
48
  end
52
49
  end
53
50
  end
@@ -1,7 +1,6 @@
1
1
  module Xcodeproj
2
2
  class Project
3
3
  module Object
4
-
5
4
  # This class represents an attribute of {AbstractObject} subclasses.
6
5
  # Attributes are created by the {AbstractObject} DSL methods and allow to
7
6
  # mirror the underlying attributes of the xcodeproj document model.
@@ -13,7 +12,6 @@ module Xcodeproj
13
12
  # validated before serialization ?
14
13
  #
15
14
  class AbstractObjectAttribute
16
-
17
15
  require 'active_support/inflector'
18
16
 
19
17
  # @return [Symbol] the type of the attribute. It can be `:simple`,
@@ -49,27 +47,14 @@ module Xcodeproj
49
47
  @owner = owner
50
48
  end
51
49
 
52
- # @return[String] The name of the attribute in camel case.
50
+ # @return [String] The name of the attribute in camel case.
53
51
  #
54
52
  # @example
55
53
  # attribute.new(:simple, :project_root)
56
54
  # attribute.plist_name #=> projectRoot
57
55
  #
58
56
  def plist_name
59
- case name
60
- when :remote_global_id_string
61
- # `_id_` would become `Id`
62
- 'remoteGlobalIDString'
63
- else
64
- self.class.plist_name_store[name] ||= name.to_s.camelize(:lower)
65
- end
66
- end
67
-
68
- # @return [Hash] a shared store which caches the plist name of the
69
- # attributes.
70
- #
71
- def self.plist_name_store
72
- @plist_name_store ||= {}
57
+ CaseConverter.convert_to_plist(name, :lower)
73
58
  end
74
59
 
75
60
  # @return [Array<Class>] the list of the classes accepted by the
@@ -77,6 +62,11 @@ module Xcodeproj
77
62
  #
78
63
  attr_accessor :classes
79
64
 
65
+ # @return [{Symbol, Array<Class>}] the list of the classes accepted by
66
+ # each key for attributes which store a dictionary.
67
+ #
68
+ attr_accessor :classes_by_key
69
+
80
70
  # @return [String, Array, Hash] the default value, if any, for simple
81
71
  # attributes.
82
72
  #
@@ -110,7 +100,9 @@ module Xcodeproj
110
100
  # @return [void]
111
101
  #
112
102
  def set_value(object, new_value)
113
- raise "[Xcodeproj] Set value called for a to-many attribute" if type == :to_many
103
+ if type == :to_many
104
+ raise '[Xcodeproj] Set value called for a to-many attribute'
105
+ end
114
106
  object.send("#{name}=", new_value)
115
107
  end
116
108
 
@@ -127,7 +119,9 @@ module Xcodeproj
127
119
  # @return [void]
128
120
  #
129
121
  def set_default(object)
130
- raise "[Xcodeproj] Set value called for a #{type} attribute" unless type == :simple
122
+ unless type == :simple
123
+ raise "[Xcodeproj] Set value called for a #{type} attribute"
124
+ end
131
125
  set_value(object, default_value.dup) if default_value
132
126
  end
133
127
 
@@ -144,23 +138,57 @@ module Xcodeproj
144
138
  return unless object
145
139
  acceptable = classes.find { |klass| object.class == klass || object.class < klass }
146
140
  if type == :simple
147
- raise "[Xcodeproj] Type checking error: got `#{object.class}` for attribute: #{inspect}" unless acceptable
141
+ raise "[Xcodeproj] Type checking error: got `#{object.class}` " \
142
+ "for attribute: #{inspect}" unless acceptable
148
143
  else
149
- raise "[Xcodeproj] Type checking error: got `#{object.isa}` for attribute: #{inspect}" unless acceptable
144
+ raise "[Xcodeproj] Type checking error: got `#{object.isa}` for " \
145
+ "attribute: #{inspect}" unless acceptable
146
+ end
147
+ end
148
+
149
+ # Checks that a given value is compatible with a key for attributes
150
+ # which store references by key.
151
+ #
152
+ # This method is used by the #{ObjectDictionary} class.
153
+ #
154
+ # @raise If the class of the value is not compatible with the given
155
+ # key.
156
+ #
157
+ def validate_value_for_key(object, key)
158
+ unless type == :references_by_keys
159
+ raise '[Xcodeproj] This method should be called only for ' \
160
+ 'attributes of type `references_by_keys`'
161
+ end
162
+
163
+ unless classes_by_key.keys.include?(key)
164
+ raise "[Xcodeproj] unsupported key `#{key}` " \
165
+ "(accepted `#{classes_by_key.keys}`) for attribute `#{inspect}`"
166
+ end
167
+
168
+ return unless object
169
+ classes = Array(classes_by_key[key])
170
+ acceptable = classes.find { |klass| object.class == klass || object.class < klass }
171
+ unless acceptable
172
+ raise "[Xcodeproj] Type checking error: got `#{object.isa}` " \
173
+ "for key `#{key}` (which accepts `#{classes}`) of " \
174
+ "attribute: `#{inspect}`"
150
175
  end
151
176
  end
152
177
 
178
+ # @return [String] A string suitable for debugging the object.
179
+ #
153
180
  def inspect
154
181
  if type == :simple
155
- "Attribute `#{plist_name}` (type: `#{type}`, classes: `#{classes}`, owner class: `#{owner.isa}`)"
182
+ "Attribute `#{plist_name}` (type: `#{type}`, classes: " \
183
+ "`#{classes}`, owner class: `#{owner.isa}`)"
156
184
  else
157
- "Attribute `#{plist_name}` (type: `#{type}`, classes: `#{classes.map(&:isa)}`, owner class: `#{owner.isa}`)"
185
+ "Attribute `#{plist_name}` (type: `#{type}`, classes: " \
186
+ "`#{classes.map(&:isa)}`, owner class: `#{owner.isa}`)"
158
187
  end
159
188
  end
160
189
  end
161
190
 
162
191
  class AbstractObject
163
-
164
192
  # The {AbstractObject} DSL methods allow to specify with fidelity the
165
193
  # underlying model of the xcodeproj document format. {AbstractObject}
166
194
  # subclasses should specify their attributes through the following
@@ -177,7 +205,6 @@ module Xcodeproj
177
205
  # @note Attributes are typed and are validated at runtime.
178
206
  #
179
207
  class << self
180
-
181
208
  # @return [Array<AbstractObjectAttribute>] the attributes associated
182
209
  # with the class.
183
210
  #
@@ -191,9 +218,14 @@ module Xcodeproj
191
218
  def attributes
192
219
  unless @full_attributes
193
220
  attributes = @attributes || []
194
- super_attributes = superclass.respond_to?(:attributes) ? superclass.attributes : []
221
+ if superclass.respond_to?(:attributes)
222
+ super_attributes = superclass.attributes
223
+ else
224
+ super_attributes = []
225
+ end
195
226
  # The uniqueness of the attributes is very important because the
196
- # initialization from plist deletes the values from the dictionary.
227
+ # initialization from plist deletes the values from the
228
+ # dictionary.
197
229
  @full_attributes = attributes.concat(super_attributes).uniq
198
230
  end
199
231
  @full_attributes
@@ -288,6 +320,8 @@ module Xcodeproj
288
320
  end
289
321
  end
290
322
 
323
+ # rubocop:disable Style/PredicateName
324
+
291
325
  # Defines a new relationship to a single and synthesises the
292
326
  # corresponding methods.
293
327
  #
@@ -373,16 +407,17 @@ module Xcodeproj
373
407
  # @param [String] plural_name
374
408
  # the name of the relationship.
375
409
  #
376
- # @param [Class, Array<Class>] isas_hash
410
+ # @param [{Symbol, Array<Class>}] classes_by_key
377
411
  # the list of the classes corresponding to the accepted isas for
378
412
  # this relationship.
379
413
  #
380
414
  # @macro [attach] has_many
381
415
  # @!attribute [r] $1
382
416
  #
383
- def has_many_references_by_keys(plural_name, isas_hash)
417
+ def has_many_references_by_keys(plural_name, classes_by_key)
384
418
  attrb = AbstractObjectAttribute.new(:references_by_keys, plural_name, self)
385
- attrb.classes = isas_hash.values
419
+ attrb.classes = classes_by_key.values
420
+ attrb.classes_by_key = classes_by_key
386
421
  add_attribute(attrb)
387
422
 
388
423
  define_method(attrb.name) do
@@ -396,6 +431,8 @@ module Xcodeproj
396
431
  end
397
432
  end
398
433
 
434
+ # rubocop:enable Style/PredicateName
435
+
399
436
  protected
400
437
 
401
438
  # Adds an attribute to the list of attributes of the class.
@@ -406,8 +443,14 @@ module Xcodeproj
406
443
  # @return [void]
407
444
  #
408
445
  def add_attribute(attribute)
409
- raise "[Xcodeproj] BUG - missing classes for #{attribute.inspect}" unless attribute.classes
410
- raise "[Xcodeproj] BUG - classes:#{attribute.classes} for #{attribute.inspect}" unless attribute.classes.all? { |klass| klass.is_a?(Class) }
446
+ unless attribute.classes
447
+ raise "[Xcodeproj] BUG - missing classes for #{attribute.inspect}"
448
+ end
449
+
450
+ unless attribute.classes.all? { |klass| klass.is_a?(Class) }
451
+ raise "[Xcodeproj] BUG - classes:#{attribute.classes} for #{attribute.inspect}"
452
+ end
453
+
411
454
  @attributes ||= []
412
455
  @attributes << attribute
413
456
  end
@@ -462,7 +505,7 @@ module Xcodeproj
462
505
  def references_by_keys_attributes
463
506
  self.class.references_by_keys_attributes
464
507
  end
465
- end # AbstractObject
508
+ end
466
509
  end
467
510
  end
468
511
  end
@@ -1,6 +1,5 @@
1
1
  module Xcodeproj
2
2
  class Project
3
-
4
3
  # This class represents relationships to other objects stored in a
5
4
  # Dictionary.
6
5
  #
@@ -8,10 +7,7 @@ module Xcodeproj
8
7
  # the project is not serialized with unreachable objects by updating the
9
8
  # with reference count on modifications.
10
9
  #
11
- # @note This class is a stub currently only being used by
12
- # {PBXProject#project_references}. It doesn't perform type cheeking
13
- # and the keys of the dictionary are in camel-case. To provide full
14
- # support as the other classes the dictionary should be able to
10
+ # @note To provide full support as the other classes the dictionary should:
15
11
  #
16
12
  # Give the following attribute:
17
13
  #
@@ -28,7 +24,7 @@ module Xcodeproj
28
24
  # #=> This should raise:
29
25
  # root_object.project_references.product_group = file
30
26
  #
31
- # generate setters and getters from the specification hash.
27
+ # I.e. generate setters and getters from the specification hash.
32
28
  #
33
29
  # Also the interface is a dirty hybrid between the
34
30
  # {AbstractObjectAttribute} and the {ObjectList}.
@@ -37,110 +33,119 @@ module Xcodeproj
37
33
  # which are overridden to inform objects reference count. Ideally all
38
34
  # the hash methods should be covered, but this is not done yet.
39
35
  # Moreover it is a moving target because the methods of array
40
- # usually are implemented in C
36
+ # usually are implemented in C.
41
37
  #
42
- # @todo Cover all the mutations methods of the {Hash} class.
38
+ # @todo This class should use a {Hash} as a backing store instead of
39
+ # inheriting from it. This would prevent the usage of methods which
40
+ # don't notify the objects.
43
41
  #
44
42
  class ObjectDictionary < Hash
45
-
46
- # {Xcodeproj} clients are not expected to create instances of
47
- # {ObjectDictionary}, it is always initialized empty and automatically by
48
- # the synthesized methods generated by {AbstractObject.has_many}.
43
+ # @param [Object::AbstractObjectAttribute] attribute @see #attribute
44
+ # @param [Object] owner @see #owner
49
45
  #
50
46
  def initialize(attribute, owner)
51
47
  @attribute = attribute
52
48
  @owner = owner
53
49
  end
54
50
 
55
- # @return [Array<Class>] The attribute that generated the list.
51
+ # @return [Object::AbstractObjectAttribute] The attribute that generated
52
+ # the list.
56
53
  #
57
54
  attr_reader :attribute
58
55
 
59
- # @return [Array<Class>] The object that owns the list.
56
+ # @return [Object] The object that owns the list.
60
57
  #
61
58
  attr_reader :owner
62
59
 
63
- #------------------------------------------------------------------------#
60
+ # @return [Array<Symbol>] The list of the allowed keys.
61
+ #
62
+ def allowed_keys
63
+ attribute.classes_by_key.keys
64
+ end
64
65
 
65
- # @!group Notification enabled methods
66
+ # @return [String] A string suitable for debugging.
67
+ #
68
+ def inspect
69
+ "<ObjectDictionary attribute:`#{@attribute.name}` " \
70
+ "owner:`#{@owner.display_name}` values:#{super.inspect}>"
71
+ end
66
72
 
67
- # TODO: the overridden methods are incomplete.
73
+ # @!group Notification enabled methods
74
+ #------------------------------------------------------------------------#
68
75
 
69
76
  # Associates an object to the given key and updates its references count.
70
77
  #
71
- # @param [String] key
72
- # the key
78
+ # @param [String] key
79
+ # The key.
73
80
  #
74
- # @param [AbstractObject] object
75
- # the object to add to the dictionary.
81
+ # @param [AbstractObject] object
82
+ # The object to add to the dictionary.
76
83
  #
77
- # @return [void]
84
+ # @return [AbstractObject] The given object.
78
85
  #
79
86
  def []=(key, object)
87
+ key = normalize_key(key)
80
88
  if object
81
- perform_additions_operations(object)
89
+ perform_additions_operations(object, key)
82
90
  else
83
91
  perform_deletion_operations(self[key])
84
92
  end
85
- super
93
+ super(key, object)
86
94
  end
87
95
 
88
96
  # Removes the given key from the dictionary and informs the object that
89
97
  # is not longer referenced by the owner.
90
98
  #
91
- # @param [String] key
92
- # the key
93
- #
94
- # @return [void]
99
+ # @param [String] key
100
+ # The key.
95
101
  #
96
102
  def delete(key)
103
+ key = normalize_key(key)
97
104
  object = self[key]
98
105
  perform_deletion_operations(object)
99
106
  super
100
107
  end
101
108
 
102
- #------------------------------------------------------------------------#
103
-
104
- # @!group AbstractObject
109
+ # @!group AbstractObject Methods
110
+ #-----------------------------------------------------------------------#
105
111
 
106
- # The plist representation of the dictionary where the objects are
107
- # replaced by their UUIDs.
108
- #
109
- # @return [Hash<String => String>]
112
+ # @return [Hash<String => String>] The plist representation of the
113
+ # dictionary where the objects are replaced by their UUIDs.
110
114
  #
111
115
  def to_hash
112
116
  result = {}
113
- each { |key, obj| result[key] = obj.uuid }
117
+ each do |key, obj|
118
+ if obj
119
+ plist_key = Object::CaseConverter.convert_to_plist(key, nil)
120
+ result[plist_key] = obj.uuid
121
+ end
122
+ end
114
123
  result
115
124
  end
116
125
 
117
- # Returns a cascade representation of the object without UUIDs.
118
- #
119
- # @return [Hash<String => String>]
126
+ # @return [Hash<String => String>] Returns a cascade representation of
127
+ # the object without UUIDs.
120
128
  #
121
129
  def to_tree_hash
122
130
  result = {}
123
- each { |key, obj| result[key] = obj.to_tree_hash }
131
+ each do |key, obj|
132
+ if obj
133
+ plist_key = Object::CaseConverter.convert_to_plist(key, nil)
134
+ result[plist_key] = obj.to_tree_hash
135
+ end
136
+ end
124
137
  result
125
138
  end
126
139
 
127
140
  # Removes all the references to a given object.
128
141
  #
129
- # @return [void]
130
- #
131
142
  def remove_reference(object)
132
143
  each { |key, obj| self[key] = nil if obj == object }
133
144
  end
134
145
 
135
- #------------------------------------------------------------------------#
136
-
137
- # @!group ObjectList
138
-
139
146
  # Informs the objects contained in the dictionary that another object is
140
147
  # referencing them.
141
148
  #
142
- # @return [void]
143
- #
144
149
  def add_referrer(referrer)
145
150
  values.each { |obj| obj.add_referrer(referrer) }
146
151
  end
@@ -148,17 +153,32 @@ module Xcodeproj
148
153
  # Informs the objects contained in the dictionary that another object
149
154
  # stopped referencing them.
150
155
  #
151
- # @return [void]
152
- #
153
156
  def remove_referrer(referrer)
154
157
  values.each { |obj| obj.remove_referrer(referrer) }
155
158
  end
156
159
 
160
+ private
161
+
162
+ # @!group Private helpers
157
163
  #------------------------------------------------------------------------#
158
164
 
159
- # @!group Notification Methods
165
+ # @return [Symbol] Normalizes a key to a symbol converting the camel case
166
+ # format with underscores.
167
+ #
168
+ # @param [String, Symbol] key
169
+ # The key to normalize.
170
+ #
171
+ def normalize_key(key)
172
+ if key.is_a?(String)
173
+ key = Object::CaseConverter.convert_to_ruby(key)
174
+ end
160
175
 
161
- private
176
+ unless allowed_keys.include?(key)
177
+ raise "[Xcodeproj] Unsupported key `#{key}` (allowed " \
178
+ "`#{allowed_keys}`) for `#{inspect}`"
179
+ end
180
+ key
181
+ end
162
182
 
163
183
  # Informs an object that it was added to the dictionary. In practice it
164
184
  # adds the owner of the list as referrer to the objects. It also
@@ -166,12 +186,9 @@ module Xcodeproj
166
186
  #
167
187
  # @return [void]
168
188
  #
169
- def perform_additions_operations(objects)
170
- objects = [objects] unless objects.is_a?(Array)
171
- objects.each do |obj|
172
- obj.add_referrer(owner)
173
- attribute.validate_value(obj)
174
- end
189
+ def perform_additions_operations(object, key)
190
+ object.add_referrer(owner)
191
+ attribute.validate_value_for_key(object, key)
175
192
  end
176
193
 
177
194
  # Informs an object that it was removed from to the dictionary, so it can
@@ -180,12 +197,8 @@ module Xcodeproj
180
197
  # @return [void]
181
198
  #
182
199
  def perform_deletion_operations(objects)
183
- objects = [objects] unless objects.is_a?(Array)
184
- objects.each do |obj|
185
- obj.remove_referrer(owner)
186
- end
200
+ objects.remove_referrer(owner)
187
201
  end
188
202
  end
189
203
  end
190
204
  end
191
-