xcodeproj 0.18.0 → 0.19.0

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 (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
-