xcodeproj 1.7.0 → 1.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.
- checksums.yaml +4 -4
- data/lib/xcodeproj/command/config_dump.rb +5 -1
- data/lib/xcodeproj/config.rb +3 -1
- data/lib/xcodeproj/config/other_linker_flags_parser.rb +2 -2
- data/lib/xcodeproj/constants.rb +70 -44
- data/lib/xcodeproj/gem_version.rb +1 -1
- data/lib/xcodeproj/project.rb +23 -2
- data/lib/xcodeproj/project/object.rb +3 -1
- data/lib/xcodeproj/project/object/build_configuration.rb +96 -35
- data/lib/xcodeproj/project/object/build_file.rb +9 -1
- data/lib/xcodeproj/project/object/build_phase.rb +45 -4
- data/lib/xcodeproj/project/object/build_rule.rb +12 -0
- data/lib/xcodeproj/project/object/helpers/file_references_factory.rb +11 -4
- data/lib/xcodeproj/project/object/helpers/groupable_helper.rb +13 -6
- data/lib/xcodeproj/project/object/native_target.rb +52 -9
- data/lib/xcodeproj/project/object/root_object.rb +15 -2
- data/lib/xcodeproj/project/object/swift_package_product_dependency.rb +19 -0
- data/lib/xcodeproj/project/object/swift_package_remote_reference.rb +19 -0
- data/lib/xcodeproj/project/object/target_dependency.rb +9 -0
- data/lib/xcodeproj/project/project_helper.rb +2 -1
- data/lib/xcodeproj/project/uuid_generator.rb +41 -19
- data/lib/xcodeproj/scheme.rb +6 -4
- data/lib/xcodeproj/scheme/build_action.rb +21 -0
- data/lib/xcodeproj/scheme/buildable_reference.rb +3 -1
- data/lib/xcodeproj/scheme/launch_action.rb +50 -0
- data/lib/xcodeproj/scheme/test_action.rb +36 -1
- data/lib/xcodeproj/workspace.rb +16 -7
- data/lib/xcodeproj/workspace/file_reference.rb +7 -12
- data/lib/xcodeproj/workspace/group_reference.rb +18 -15
- data/lib/xcodeproj/workspace/reference.rb +40 -0
- metadata +11 -9
@@ -224,8 +224,9 @@ module Xcodeproj
|
|
224
224
|
cl.build_configurations << release_conf
|
225
225
|
cl.build_configurations << debug_conf
|
226
226
|
|
227
|
+
existing_configurations = cl.build_configurations.map(&:name)
|
227
228
|
project.build_configurations.each do |configuration|
|
228
|
-
next if
|
229
|
+
next if existing_configurations.include?(configuration.name)
|
229
230
|
|
230
231
|
new_config = project.new(XCBuildConfiguration)
|
231
232
|
new_config.name = configuration.name
|
@@ -3,43 +3,65 @@ module Xcodeproj
|
|
3
3
|
class UUIDGenerator
|
4
4
|
require 'digest'
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
@
|
8
|
-
@new_objects_by_uuid = {}
|
6
|
+
def initialize(projects)
|
7
|
+
@projects = Array(projects)
|
9
8
|
@paths_by_object = {}
|
10
9
|
end
|
11
10
|
|
12
11
|
def generate!
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
@
|
12
|
+
generate_all_paths_by_objects(@projects)
|
13
|
+
|
14
|
+
new_objects_by_project = Hash[@projects.map do |project|
|
15
|
+
[project, switch_uuids(project)]
|
16
|
+
end]
|
17
|
+
all_new_objects_by_project = new_objects_by_project.values.flat_map(&:values)
|
18
|
+
all_objects_by_uuid = @projects.map(&:objects_by_uuid).inject(:merge)
|
19
|
+
all_objects = @projects.flat_map(&:objects)
|
20
|
+
verify_no_duplicates!(all_objects, all_new_objects_by_project)
|
21
|
+
@projects.each { |project| fixup_uuid_references(project, all_objects_by_uuid) }
|
22
|
+
new_objects_by_project.each do |project, new_objects_by_uuid|
|
23
|
+
project.instance_variable_set(:@generated_uuids, project.instance_variable_get(:@available_uuids))
|
24
|
+
project.instance_variable_set(:@objects_by_uuid, new_objects_by_uuid)
|
25
|
+
end
|
20
26
|
end
|
21
27
|
|
22
28
|
private
|
23
29
|
|
24
30
|
UUID_ATTRIBUTES = [:remote_global_id_string, :container_portal, :target_proxy].freeze
|
25
31
|
|
26
|
-
def verify_no_duplicates!(all_objects)
|
27
|
-
duplicates = all_objects -
|
32
|
+
def verify_no_duplicates!(all_objects, all_new_objects)
|
33
|
+
duplicates = all_objects - all_new_objects
|
28
34
|
UserInterface.warn "[Xcodeproj] Generated duplicate UUIDs:\n\n" <<
|
29
35
|
duplicates.map { |d| "#{d.isa} -- #{@paths_by_object[d]}" }.join("\n") unless duplicates.empty?
|
30
36
|
end
|
31
37
|
|
32
|
-
def fixup_uuid_references
|
38
|
+
def fixup_uuid_references(target_project, all_objects_by_uuid)
|
33
39
|
fixup = ->(object, attr) do
|
34
|
-
if object.respond_to?(attr) && link =
|
40
|
+
if object.respond_to?(attr) && link = all_objects_by_uuid[object.send(attr)]
|
35
41
|
object.send(:"#{attr}=", link.uuid)
|
36
42
|
end
|
37
43
|
end
|
38
|
-
|
44
|
+
target_project.objects.each do |object|
|
39
45
|
UUID_ATTRIBUTES.each do |attr|
|
40
46
|
fixup[object, attr]
|
41
47
|
end
|
42
48
|
end
|
49
|
+
|
50
|
+
if (project_attributes = target_project.root_object.attributes) && project_attributes['TargetAttributes']
|
51
|
+
project_attributes['TargetAttributes'] = Hash[project_attributes['TargetAttributes'].map do |target_uuid, attributes|
|
52
|
+
if test_target_id = attributes['TestTargetID']
|
53
|
+
attributes = attributes.merge('TestTargetID' => all_objects_by_uuid[test_target_id].uuid)
|
54
|
+
end
|
55
|
+
if target_object = all_objects_by_uuid[target_uuid]
|
56
|
+
target_uuid = target_object.uuid
|
57
|
+
end
|
58
|
+
[target_uuid, attributes]
|
59
|
+
end]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def generate_all_paths_by_objects(projects)
|
64
|
+
projects.each { |project| generate_paths(project.root_object, project.path.basename.to_s) }
|
43
65
|
end
|
44
66
|
|
45
67
|
def generate_paths(object, path = '')
|
@@ -67,13 +89,13 @@ module Xcodeproj
|
|
67
89
|
end
|
68
90
|
end
|
69
91
|
|
70
|
-
def switch_uuids(
|
71
|
-
|
72
|
-
objects.
|
92
|
+
def switch_uuids(project)
|
93
|
+
project.mark_dirty!
|
94
|
+
project.objects.each_with_object({}) do |object, hash|
|
73
95
|
next unless path = @paths_by_object[object]
|
74
96
|
uuid = uuid_for_path(path)
|
75
97
|
object.instance_variable_set(:@uuid, uuid)
|
76
|
-
|
98
|
+
hash[uuid] = object
|
77
99
|
end
|
78
100
|
end
|
79
101
|
|
data/lib/xcodeproj/scheme.rb
CHANGED
@@ -31,7 +31,9 @@ module Xcodeproj
|
|
31
31
|
def initialize(file_path = nil)
|
32
32
|
if file_path
|
33
33
|
@file_path = file_path
|
34
|
-
@doc =
|
34
|
+
@doc = File.open(file_path, 'r') do |f|
|
35
|
+
REXML::Document.new(f)
|
36
|
+
end
|
35
37
|
@doc.context[:attribute_quote] = :quote
|
36
38
|
|
37
39
|
@scheme = @doc.elements['Scheme']
|
@@ -193,9 +195,9 @@ module Xcodeproj
|
|
193
195
|
|
194
196
|
entry.build_for_testing = true
|
195
197
|
entry.build_for_running = build_for_running
|
196
|
-
entry.build_for_profiling =
|
197
|
-
entry.build_for_archiving =
|
198
|
-
entry.build_for_analyzing =
|
198
|
+
entry.build_for_profiling = build_for_running
|
199
|
+
entry.build_for_archiving = build_for_running
|
200
|
+
entry.build_for_analyzing = build_for_running
|
199
201
|
|
200
202
|
build_action.add_entry(entry)
|
201
203
|
end
|
@@ -59,6 +59,20 @@ module Xcodeproj
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
# @param [Array<BuildAction::Entry>] entries
|
63
|
+
# Sets the list of BuildActionEntry nodes associated with this Build Action.
|
64
|
+
#
|
65
|
+
def entries=(entries)
|
66
|
+
@xml_element.delete_element('BuildActionEntries')
|
67
|
+
unless entries.empty?
|
68
|
+
entries_element = @xml_element.add_element('BuildActionEntries')
|
69
|
+
entries.each do |entry_node|
|
70
|
+
entries_element.add_element(entry_node.xml_element)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
entries
|
74
|
+
end
|
75
|
+
|
62
76
|
# @param [BuildAction::Entry] entry
|
63
77
|
# The BuildActionEntry to add to the list of targets to build for the various actions
|
64
78
|
#
|
@@ -185,6 +199,13 @@ module Xcodeproj
|
|
185
199
|
def add_buildable_reference(ref)
|
186
200
|
@xml_element.add_element(ref.xml_element)
|
187
201
|
end
|
202
|
+
|
203
|
+
# @param [BuildableReference] ref
|
204
|
+
# The BuildableReference to remove from the list of targets this entry will build
|
205
|
+
#
|
206
|
+
def remove_buildable_reference(ref)
|
207
|
+
@xml_element.delete_element(ref.xml_element)
|
208
|
+
end
|
188
209
|
end
|
189
210
|
end
|
190
211
|
end
|
@@ -59,10 +59,12 @@ module Xcodeproj
|
|
59
59
|
# If true, buildable_name will also be updated by computing a name from the target
|
60
60
|
#
|
61
61
|
def set_reference_target(target, override_buildable_name = false, root_project = nil)
|
62
|
+
# note, the order of assignment here is important, it determines the order of serialization in the xml
|
63
|
+
# this matches the order that Xcode generates
|
62
64
|
@xml_element.attributes['BlueprintIdentifier'] = target.uuid
|
65
|
+
self.buildable_name = construct_buildable_name(target) if override_buildable_name
|
63
66
|
@xml_element.attributes['BlueprintName'] = target.name
|
64
67
|
@xml_element.attributes['ReferencedContainer'] = construct_referenced_container_uri(target, root_project)
|
65
|
-
self.buildable_name = construct_buildable_name(target) if override_buildable_name
|
66
68
|
end
|
67
69
|
|
68
70
|
# @return [String]
|
@@ -47,6 +47,40 @@ module Xcodeproj
|
|
47
47
|
@xml_element.attributes['allowLocationSimulation'] = bool_to_string(flag)
|
48
48
|
end
|
49
49
|
|
50
|
+
# @return [Bool]
|
51
|
+
# Whether this Build Action should disable detection of UI API misuse
|
52
|
+
# from background threads
|
53
|
+
#
|
54
|
+
def disable_main_thread_checker?
|
55
|
+
string_to_bool(@xml_element.attributes['disableMainThreadChecker'])
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param [Bool] flag
|
59
|
+
# Set whether this Build Action should disable detection of UI API misuse
|
60
|
+
# from background threads
|
61
|
+
#
|
62
|
+
def disable_main_thread_checker=(flag)
|
63
|
+
@xml_element.attributes['disableMainThreadChecker'] = bool_to_string(flag)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [Bool]
|
67
|
+
# Whether UI API misuse from background threads detection should pause execution.
|
68
|
+
# This flag is ignored when the thread checker disabled
|
69
|
+
# ([disable_main_thread_checker] flag).
|
70
|
+
#
|
71
|
+
def stop_on_every_main_thread_checker_issue?
|
72
|
+
string_to_bool(@xml_element.attributes['stopOnEveryMainThreadCheckerIssue'])
|
73
|
+
end
|
74
|
+
|
75
|
+
# @param [Bool] flag
|
76
|
+
# Set whether UI API misuse from background threads detection should pause execution.
|
77
|
+
# This flag is ignored when the thread checker disabled
|
78
|
+
# ([disable_main_thread_checker] flag).
|
79
|
+
#
|
80
|
+
def stop_on_every_main_thread_checker_issue=(flag)
|
81
|
+
@xml_element.attributes['stopOnEveryMainThreadCheckerIssue'] = bool_to_string(flag)
|
82
|
+
end
|
83
|
+
|
50
84
|
# @return [String]
|
51
85
|
# The launch automatically substyle
|
52
86
|
#
|
@@ -109,6 +143,22 @@ module Xcodeproj
|
|
109
143
|
@xml_element.add_element(arguments.xml_element) if arguments
|
110
144
|
arguments
|
111
145
|
end
|
146
|
+
|
147
|
+
# @return [Array<MacroExpansion>]
|
148
|
+
# The list of MacroExpansion bound with this LaunchAction
|
149
|
+
#
|
150
|
+
def macro_expansions
|
151
|
+
@xml_element.get_elements('MacroExpansion').map do |node|
|
152
|
+
MacroExpansion.new(node)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# @param [MacroExpansion] macro_expansion
|
157
|
+
# Add a MacroExpansion to this LaunchAction
|
158
|
+
#
|
159
|
+
def add_macro_expansion(macro_expansion)
|
160
|
+
@xml_element.add_element(macro_expansion.xml_element)
|
161
|
+
end
|
112
162
|
end
|
113
163
|
end
|
114
164
|
end
|
@@ -35,6 +35,22 @@ module Xcodeproj
|
|
35
35
|
@xml_element.attributes['shouldUseLaunchSchemeArgsEnv'] = bool_to_string(flag)
|
36
36
|
end
|
37
37
|
|
38
|
+
# @return [Bool]
|
39
|
+
# Whether this Test Action should disable detection of UI API misuse
|
40
|
+
# from background threads
|
41
|
+
#
|
42
|
+
def disable_main_thread_checker?
|
43
|
+
string_to_bool(@xml_element.attributes['disableMainThreadChecker'])
|
44
|
+
end
|
45
|
+
|
46
|
+
# @param [Bool] flag
|
47
|
+
# Set whether this Test Action should disable detection of UI API misuse
|
48
|
+
# from background threads
|
49
|
+
#
|
50
|
+
def disable_main_thread_checker=(flag)
|
51
|
+
@xml_element.attributes['disableMainThreadChecker'] = bool_to_string(flag)
|
52
|
+
end
|
53
|
+
|
38
54
|
# @return [Bool]
|
39
55
|
# Whether Clang Code Coverage is enabled ('Gather coverage data' turned ON)
|
40
56
|
#
|
@@ -42,7 +58,7 @@ module Xcodeproj
|
|
42
58
|
string_to_bool(@xml_element.attributes['codeCoverageEnabled'])
|
43
59
|
end
|
44
60
|
|
45
|
-
# @
|
61
|
+
# @param [Bool] flag
|
46
62
|
# Set whether Clang Code Coverage is enabled ('Gather coverage data' turned ON)
|
47
63
|
#
|
48
64
|
def code_coverage_enabled=(flag)
|
@@ -60,6 +76,18 @@ module Xcodeproj
|
|
60
76
|
end
|
61
77
|
end
|
62
78
|
|
79
|
+
# @param [Array<TestableReference>] testables
|
80
|
+
# Sets the list of TestableReference (test bundles) associated with this Test Action
|
81
|
+
#
|
82
|
+
def testables=(testables)
|
83
|
+
@xml_element.delete_element('Testables')
|
84
|
+
testables_element = @xml_element.add_element('Testables')
|
85
|
+
testables.each do |testable|
|
86
|
+
testables_element.add_element(testable.xml_element)
|
87
|
+
end
|
88
|
+
testables
|
89
|
+
end
|
90
|
+
|
63
91
|
# @param [TestableReference] testable
|
64
92
|
# Add a TestableReference (test bundle) to this Test Action
|
65
93
|
#
|
@@ -203,6 +231,13 @@ module Xcodeproj
|
|
203
231
|
@xml_element.add_element(ref.xml_element)
|
204
232
|
end
|
205
233
|
|
234
|
+
# @param [BuildableReference] ref
|
235
|
+
# The BuildableReference to remove from the list of targets this entry will build
|
236
|
+
#
|
237
|
+
def remove_buildable_reference(ref)
|
238
|
+
@xml_element.delete_element(ref.xml_element)
|
239
|
+
end
|
240
|
+
|
206
241
|
# @return [Array<Test>]
|
207
242
|
# The list of SkippedTest this action will skip.
|
208
243
|
#
|
data/lib/xcodeproj/workspace.rb
CHANGED
@@ -64,7 +64,7 @@ module Xcodeproj
|
|
64
64
|
#
|
65
65
|
def self.new_from_xcworkspace(path)
|
66
66
|
from_s(File.read(File.join(path, 'contents.xcworkspacedata')),
|
67
|
-
File.expand_path(
|
67
|
+
File.expand_path(path))
|
68
68
|
rescue Errno::ENOENT
|
69
69
|
new(nil)
|
70
70
|
end
|
@@ -97,16 +97,19 @@ module Xcodeproj
|
|
97
97
|
#
|
98
98
|
def <<(path_or_reference)
|
99
99
|
return unless @document && @document.respond_to?(:root)
|
100
|
-
|
101
|
-
|
100
|
+
|
101
|
+
case path_or_reference
|
102
|
+
when String
|
102
103
|
project_file_reference = Xcodeproj::Workspace::FileReference.new(path_or_reference)
|
103
|
-
when
|
104
|
+
when Xcodeproj::Workspace::FileReference
|
104
105
|
project_file_reference = path_or_reference
|
105
106
|
projpath = nil
|
106
107
|
else
|
107
|
-
raise ArgumentError,
|
108
|
+
raise ArgumentError, "Input to the << operator must be a file path or FileReference, got #{path_or_reference.inspect}"
|
109
|
+
end
|
110
|
+
unless file_references.any? { |ref| project_file_reference.eql? ref }
|
111
|
+
@document.root.add_element(project_file_reference.to_node)
|
108
112
|
end
|
109
|
-
@document.root.add_element(project_file_reference.to_node)
|
110
113
|
load_schemes_from_project File.expand_path(projpath || project_file_reference.path)
|
111
114
|
end
|
112
115
|
|
@@ -191,8 +194,14 @@ module Xcodeproj
|
|
191
194
|
# @return [void]
|
192
195
|
#
|
193
196
|
def load_schemes(workspace_dir_path)
|
197
|
+
# Normalizes path to directory of workspace needed for file_reference.absolute_path
|
198
|
+
workspaces_dir = workspace_dir_path
|
199
|
+
if File.extname(workspace_dir_path) == '.xcworkspace'
|
200
|
+
workspaces_dir = File.expand_path('..', workspaces_dir)
|
201
|
+
end
|
202
|
+
|
194
203
|
file_references.each do |file_reference|
|
195
|
-
project_full_path = file_reference.absolute_path(
|
204
|
+
project_full_path = file_reference.absolute_path(workspaces_dir)
|
196
205
|
load_schemes_from_project(project_full_path)
|
197
206
|
end
|
198
207
|
|
@@ -1,27 +1,19 @@
|
|
1
|
+
require 'xcodeproj/workspace/reference'
|
2
|
+
|
1
3
|
module Xcodeproj
|
2
4
|
class Workspace
|
3
5
|
# Describes a file reference of a Workspace.
|
4
6
|
#
|
5
|
-
class FileReference
|
7
|
+
class FileReference < Reference
|
6
8
|
# @return [String] the path to the project
|
7
9
|
#
|
8
10
|
attr_reader :path
|
9
11
|
|
10
|
-
# @return [String] the type of reference to the project
|
11
|
-
#
|
12
|
-
# This can be of the following values:
|
13
|
-
# - absolute
|
14
|
-
# - group
|
15
|
-
# - container
|
16
|
-
# - developer (unsupported)
|
17
|
-
#
|
18
|
-
attr_reader :type
|
19
|
-
|
20
12
|
# @param [#to_s] path @see path
|
21
13
|
# @param [#to_s] type @see type
|
22
14
|
#
|
23
15
|
def initialize(path, type = 'group')
|
24
|
-
@path = path.to_s
|
16
|
+
@path = Pathname.new(path.to_s).cleanpath.to_s
|
25
17
|
@type = type.to_s
|
26
18
|
end
|
27
19
|
|
@@ -47,6 +39,9 @@ module Xcodeproj
|
|
47
39
|
#
|
48
40
|
def self.from_node(xml_node)
|
49
41
|
type, path = xml_node.attribute('location').value.split(':', 2)
|
42
|
+
if type == 'group'
|
43
|
+
path = prepend_parent_path(xml_node, path)
|
44
|
+
end
|
50
45
|
new(path, type)
|
51
46
|
end
|
52
47
|
|
@@ -1,41 +1,39 @@
|
|
1
|
+
require 'xcodeproj/workspace/reference'
|
2
|
+
|
1
3
|
module Xcodeproj
|
2
4
|
class Workspace
|
3
5
|
# Describes a group reference of a Workspace.
|
4
6
|
#
|
5
|
-
class GroupReference
|
7
|
+
class GroupReference < Reference
|
6
8
|
# @return [String] the name of the group
|
7
9
|
#
|
8
10
|
attr_reader :name
|
9
11
|
|
10
|
-
# @return [String] the
|
11
|
-
#
|
12
|
-
# This can be of the following values:
|
13
|
-
# - absolute
|
14
|
-
# - group
|
15
|
-
# - container (only supported value)
|
16
|
-
# - developer
|
12
|
+
# @return [String] the location of the group on disk
|
17
13
|
#
|
18
|
-
attr_reader :
|
14
|
+
attr_reader :location
|
19
15
|
|
20
16
|
# @param [#to_s] name @see name
|
21
17
|
# @param [#to_s] type @see type
|
18
|
+
# @param [#to_s] location @see location
|
22
19
|
#
|
23
|
-
def initialize(name, type = 'container')
|
20
|
+
def initialize(name, type = 'container', location = '')
|
24
21
|
@name = name.to_s
|
25
22
|
@type = type.to_s
|
23
|
+
@location = location.to_s
|
26
24
|
end
|
27
25
|
|
28
26
|
# @return [Bool] Whether a group reference is equal to another.
|
29
27
|
#
|
30
28
|
def ==(other)
|
31
|
-
name == other.name && type == other.type
|
29
|
+
name == other.name && type == other.type && location == other.location
|
32
30
|
end
|
33
31
|
alias_method :eql?, :==
|
34
32
|
|
35
33
|
# @return [Fixnum] A hash identical for equals objects.
|
36
34
|
#
|
37
35
|
def hash
|
38
|
-
[name, type].hash
|
36
|
+
[name, type, location].hash
|
39
37
|
end
|
40
38
|
|
41
39
|
# Returns a group reference given XML representation.
|
@@ -46,16 +44,21 @@ module Xcodeproj
|
|
46
44
|
# @return [GroupReference] The new group reference instance.
|
47
45
|
#
|
48
46
|
def self.from_node(xml_node)
|
49
|
-
|
47
|
+
location_array = xml_node.attribute('location').value.split(':', 2)
|
48
|
+
type = location_array.first
|
49
|
+
location = location_array[1] || ''
|
50
|
+
if type == 'group'
|
51
|
+
location = prepend_parent_path(xml_node, location)
|
52
|
+
end
|
50
53
|
name = xml_node.attribute('name').value
|
51
|
-
new(name, type)
|
54
|
+
new(name, type, location)
|
52
55
|
end
|
53
56
|
|
54
57
|
# @return [REXML::Element] the XML representation of the group reference.
|
55
58
|
#
|
56
59
|
def to_node
|
57
60
|
REXML::Element.new('Group').tap do |element|
|
58
|
-
element.add_attribute('location', "#{type}
|
61
|
+
element.add_attribute('location', "#{type}:#{location}")
|
59
62
|
element.add_attribute('name', "#{name}")
|
60
63
|
end
|
61
64
|
end
|