diff --git a/lib/parser/pbxproj.js b/lib/parser/pbxproj.js index f5c71d3..4112af1 100644 --- a/lib/parser/pbxproj.js +++ b/lib/parser/pbxproj.js @@ -178,9 +178,47 @@ function peg$parse(input, options) { peg$c6 = function() { return Object.create(null) }, peg$c7 = function(list) { var returnObject = list[0][0]; - for(var i = 1; i < list.length; i++){ + + for (var i = 1; i < list.length; i++) { var another = list[i][0]; - returnObject = Object.assign(returnObject, another); + + /* + * Ensure previously parsed section entries are not lost + * + * Example: + * + * If "returnObject" contains: + * + * { + * PBXTargetDependency: { + * 'A': {}, + * 'A_comment': 'PBXTargetDependency' + * } + * } + * + * And "another" contains: + * + * { + * PBXTargetDependency: { + * 'B': {}, + * 'B_comment': 'PBXTargetDependency' + * } + * } + * + * Using "Object.assign(returnObject, another)" would lose + * "A" as it would replace the entire PBXTargetDependency. + * + * Instead, we will merge each top-level property of the + * objects, if it exists and is an object else add. + */ + for (var key in another) { + returnObject[key] = ( + returnObject[key] && + another[key] && + typeof returnObject[key] === 'object' && + typeof another[key] === 'object' + ) ? Object.assign(returnObject[key], another[key]) : another[key]; + } } return returnObject; }, diff --git a/lib/parser/pbxproj.pegjs b/lib/parser/pbxproj.pegjs index 9897048..f93faed 100644 --- a/lib/parser/pbxproj.pegjs +++ b/lib/parser/pbxproj.pegjs @@ -17,18 +17,6 @@ under the License. */ -{ - function merge_obj(obj, secondObj) { - if (!obj) - return secondObj; - - for(var i in secondObj) - obj[i] = merge_obj(obj[i], secondObj[i]); - - return obj; - } -} - /* * Project: point of entry from pbxproj file */ @@ -60,9 +48,47 @@ AssignmentList = _ list:((a:Assignment / d:DelimitedSection) _)+ { var returnObject = list[0][0]; - for(var i = 1; i < list.length; i++){ + + for (var i = 1; i < list.length; i++) { var another = list[i][0]; - returnObject = merge_obj(returnObject, another); + + /* + * Ensure previously parsed section entries are not lost + * + * Example: + * + * If "returnObject" contains: + * + * { + * PBXTargetDependency: { + * 'A': {}, + * 'A_comment': 'PBXTargetDependency' + * } + * } + * + * And "another" contains: + * + * { + * PBXTargetDependency: { + * 'B': {}, + * 'B_comment': 'PBXTargetDependency' + * } + * } + * + * Using "Object.assign(returnObject, another)" would lose + * "A" as it would replace the entire PBXTargetDependency. + * + * Instead, we will merge each top-level property of the + * objects, if it exists and is an object else add. + */ + for (var key in another) { + returnObject[key] = ( + returnObject[key] && + another[key] && + typeof returnObject[key] === 'object' && + typeof another[key] === 'object' + ) ? Object.assign(returnObject[key], another[key]) : another[key]; + } } return returnObject; }