diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..2b07282
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+node-xcode
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml
new file mode 100644
index 0000000..2339076
--- /dev/null
+++ b/.idea/jsLibraryMappings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/node_xcode_node_modules.xml b/.idea/libraries/node_xcode_node_modules.xml
new file mode 100644
index 0000000..64ce749
--- /dev/null
+++ b/.idea/libraries/node_xcode_node_modules.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..72abef0
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..86e2f7b
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/node-xcode.iml b/.idea/node-xcode.iml
new file mode 100644
index 0000000..395f691
--- /dev/null
+++ b/.idea/node-xcode.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..ab17a1a
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,1055 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Data flow issuesJavaScript
+
+
+ Error handlingJavaScript
+
+
+ JavaScript
+
+
+ JavaScript validity issuesJavaScript
+
+
+
+
+ CoffeeScript
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $PROJECT_DIR$
+ true
+
+ bdd
+
+ DIRECTORY
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1450252970371
+
+ 1450252970371
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1647
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 450
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1625
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1857
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1865
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1871
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 51
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 41
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 37
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1985
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1988
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 2017
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1863
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1842
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 2058
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 2088
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 76
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 185
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 933
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 298
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 299
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 304
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 297
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 179
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 209
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 208
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 606
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 191
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 129
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 119
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 117
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 102
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 112
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 156
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 179
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 236
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 205
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/Integrate.js
+ 233
+
+
+
+ file://$PROJECT_DIR$/test/HTJSGeneratorCode/UpdateNEIProject.js
+ 21
+
+
+
+ file://$PROJECT_DIR$/test/HTTestResources/UpdateNEIProject.js
+ 11
+
+
+
+ file://$PROJECT_DIR$/test/HTTestResources/AddResources.js
+ 463
+
+
+
+ file://$PROJECT_DIR$/test/HTTestResources/AddResources.js
+ 475
+
+
+
+ file://$PROJECT_DIR$/test/HTTestResources/AddResources.js
+ 494
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1723
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1722
+
+
+
+ file://$PROJECT_DIR$/lib/pbxProject.js
+ 1716
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/pbxProject.js b/lib/pbxProject.js
index a295fe2..f993b86 100644
--- a/lib/pbxProject.js
+++ b/lib/pbxProject.js
@@ -928,6 +928,7 @@ pbxProject.prototype.buildPhase = function(group, target) {
pbxProject.prototype.buildPhaseObject = function(name, group, target) {
var section = this.hash.project.objects[name],
obj, sectionKey, key;
+ // TODO: 这里target如果是传的FirstTarget, 会抛出异常,原因未知.
var buildPhase = this.buildPhase(group, target);
for (key in section) {
@@ -1629,8 +1630,22 @@ pbxProject.prototype.removeFromPbxGroup = function (file, groupKey) {
}
}
+pbxProject.prototype.getPBXGroupByPath = function(path) {
+ var groups = this.hash.project.objects['PBXGroup'];
+ for (var key in groups) {
+ var group = groups[key];
+ if (group.path === path) {
+ return group;
+ }
+ }
+
+ return undefined;
+};
+
+
pbxProject.prototype.getPBXGroupByKey = function(key) {
- return this.hash.project.objects['PBXGroup'][key];
+ var group = this.hash.project.objects['PBXGroup'][key];
+ return group;
};
pbxProject.prototype.findPBXGroupKey = function(criteria) {
@@ -1699,7 +1714,9 @@ pbxProject.prototype.addFile = function (path, group, opt) {
var file = new pbxFile(path, opt);
// null is better for early errors
- if (this.hasFile(file.path)) return null;
+ if (this.hasFile(file.path)) {
+ return null;
+ }
file.fileRef = this.generateUuid();
@@ -1806,5 +1823,254 @@ pbxProject.prototype.addDataModelDocument = function(filePath, group, opt) {
return file;
}
+// New Interfaces added by LWANG.
+pbxProject.prototype.removePbxGroupByKey = function (groupKey) {
+ var section = this.hash.project.objects['PBXGroup'],
+ key, itemKey;
+
+ for (key in section) {
+ // only look for comments
+ if (!COMMENT_KEY.test(key)) continue;
+
+ if (key == groupKey) {
+ itemKey = key.split(COMMENT_KEY)[0];
+ delete section[itemKey];
+ }
+ }
+}
+
+pbxProject.prototype.removeGroupFromPbxGroup = function (removeGroupKey, groupKey) {
+ var group = this.getPBXGroupByKey(groupKey);
+ var removeGroup = this.getPBXGroupByKey(removeGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ if(removeGroupKey == groupChildren[i].value && removeGroup != undefined) {
+ groupChildren.splice(i, 1);
+
+ this.clearGroup(removeGroup);
+ break;
+ }
+ }
+ }
+
+ delete removeGroup;
+}
+
+pbxProject.prototype.clearGroup = function (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ this.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ this.removeFromPbxGroup(file, group); // PBXGroup
+ }
+}
+
+pbxProject.prototype.removeGroupByKey = function (key, parentGroupKey) {
+ var group = this.getPBXGroupByKey(key, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ this.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ this.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+// Remove a group and all files in this group.
+pbxProject.prototype.removeGroup = function (groupPath, parentGroupKey) {
+ var group = this.getPBXGroupByPath(groupPath, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ this.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ this.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+
+pbxProject.prototype.getPBXGroupByPath = function(path, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? this.hash.project.objects['PBXGroup'] : this.getPBXGroupByKey(parentGroupKey);
+ for (var key in groups) {
+ var group = groups[key];
+ if (group.path === path) {
+ return group;
+ }
+ }
+
+ return undefined;
+};
+
+pbxProject.prototype.getPBXGroupByKey = function(key, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? this.hash.project.objects['PBXGroup'] : this.getPBXGroupByKey(parentGroupKey);
+ var group = groups[key];
+ return group;
+};
+
+pbxProject.prototype.findPBXGroupInParent = function(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return this.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = this.findPBXGroupKey(parentCriteria);
+ var group = this.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = this.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+pbxProject.prototype.findPBXGroupKeyInParent = function(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return this.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = this.findPBXGroupKey(parentCriteria);
+ var group = this.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = this.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+
+pbxProject.prototype.findPBXGroupKeyInParentGroup = function(criteria, parentGroupKey) {
+ var target;
+ var group = this.getPBXGroupByKey(parentGroupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = this.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+pbxProject.prototype.findPBXGroupInParentGroup = function(criteria, parentGroupKey) {
+ var target;
+ var group = this.getPBXGroupByKey(parentGroupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = this.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ }
+
+ return target;
+}
module.exports = pbxProject;
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.pbxproj b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..062f61c
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.pbxproj
@@ -0,0 +1,560 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+/* Begin PBXBuildFile section */
+ E6AFD0081C1E99040027F340 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD0071C1E99040027F340 /* main.m */; };
+ E6AFD00B1C1E99040027F340 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD00A1C1E99040027F340 /* AppDelegate.m */; };
+ E6AFD00E1C1E99040027F340 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD00D1C1E99040027F340 /* ViewController.m */; };
+ E6AFD0111C1E99040027F340 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E6AFD00F1C1E99040027F340 /* Main.storyboard */; };
+ E6AFD0131C1E99040027F340 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E6AFD0121C1E99040027F340 /* Assets.xcassets */; };
+ E6AFD0161C1E99040027F340 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E6AFD0141C1E99040027F340 /* LaunchScreen.storyboard */; };
+ E6AFD0211C1E99040027F340 /* HTJSGeneratorCodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD0201C1E99040027F340 /* HTJSGeneratorCodeTests.m */; };
+ E6AFD02C1C1E99040027F340 /* HTJSGeneratorCodeUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD02B1C1E99040027F340 /* HTJSGeneratorCodeUITests.m */; };
+ 952203A8DF8C47769600886C /* HTTestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = C8C17D02BCB34BF1AD38DD5A /* HTTestModel.m */; };
+ F72B6E5C0A744352817E3775 /* HTTestRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6266018F1506415BB379C5F0 /* HTTestRequest.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ E6AFD01D1C1E99040027F340 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = E6AFCFFB1C1E99040027F340 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E6AFD0021C1E99040027F340;
+ remoteInfo = HTJSGeneratorCode;
+ };
+ E6AFD0281C1E99040027F340 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = E6AFCFFB1C1E99040027F340 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E6AFD0021C1E99040027F340;
+ remoteInfo = HTJSGeneratorCode;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ E6AFD0031C1E99040027F340 /* HTJSGeneratorCode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HTJSGeneratorCode.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ E6AFD0071C1E99040027F340 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ E6AFD0091C1E99040027F340 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ E6AFD00A1C1E99040027F340 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ E6AFD00C1C1E99040027F340 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
+ E6AFD00D1C1E99040027F340 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
+ E6AFD0101C1E99040027F340 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ E6AFD0121C1E99040027F340 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ E6AFD0151C1E99040027F340 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ E6AFD0171C1E99040027F340 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ E6AFD01C1C1E99040027F340 /* HTJSGeneratorCodeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HTJSGeneratorCodeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E6AFD0201C1E99040027F340 /* HTJSGeneratorCodeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTJSGeneratorCodeTests.m; sourceTree = ""; };
+ E6AFD0221C1E99040027F340 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ E6AFD0271C1E99040027F340 /* HTJSGeneratorCodeUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HTJSGeneratorCodeUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E6AFD02B1C1E99040027F340 /* HTJSGeneratorCodeUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTJSGeneratorCodeUITests.m; sourceTree = ""; };
+ E6AFD02D1C1E99040027F340 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 6EA50EBEEF0E47E2B29194BB /* HTTestModel.h */ = {isa = PBXFileReference; name = "HTTestModel.h"; path = "HTTestModel.h"; sourceTree = ""; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+ C8C17D02BCB34BF1AD38DD5A /* HTTestModel.m */ = {isa = PBXFileReference; name = "HTTestModel.m"; path = "HTTestModel.m"; sourceTree = ""; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; };
+ E8335E76858442108FD3A1B9 /* HTTestRequest.h */ = {isa = PBXFileReference; name = "HTTestRequest.h"; path = "HTTestRequest.h"; sourceTree = ""; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; };
+ 6266018F1506415BB379C5F0 /* HTTestRequest.m */ = {isa = PBXFileReference; name = "HTTestRequest.m"; path = "HTTestRequest.m"; sourceTree = ""; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ E6AFD0001C1E99040027F340 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0191C1E99040027F340 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0241C1E99040027F340 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ BA604265FA2841C1B310F4EB /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ 6EA50EBEEF0E47E2B29194BB /* HTTestModel.h */,
+ C8C17D02BCB34BF1AD38DD5A /* HTTestModel.m */,
+ );
+ path = Models;
+ sourceTree = "";
+ };
+ E6AFCFFA1C1E99040027F340 = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0051C1E99040027F340 /* HTJSGeneratorCode */,
+ E6AFD01F1C1E99040027F340 /* HTJSGeneratorCodeTests */,
+ E6AFD02A1C1E99040027F340 /* HTJSGeneratorCodeUITests */,
+ E6AFD0041C1E99040027F340 /* Products */,
+ );
+ sourceTree = "";
+ };
+ E6AFD0041C1E99040027F340 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0031C1E99040027F340 /* HTJSGeneratorCode.app */,
+ E6AFD01C1C1E99040027F340 /* HTJSGeneratorCodeTests.xctest */,
+ E6AFD0271C1E99040027F340 /* HTJSGeneratorCodeUITests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ E6AFD0051C1E99040027F340 /* HTJSGeneratorCode */ = {
+ isa = PBXGroup;
+ children = (
+ E6B03C021C27F57600450E9E /* hehe */,
+ E6AFD0091C1E99040027F340 /* AppDelegate.h */,
+ E6AFD00A1C1E99040027F340 /* AppDelegate.m */,
+ E6AFD00C1C1E99040027F340 /* ViewController.h */,
+ E6AFD00D1C1E99040027F340 /* ViewController.m */,
+ E6AFD00F1C1E99040027F340 /* Main.storyboard */,
+ E6AFD0121C1E99040027F340 /* Assets.xcassets */,
+ E6AFD0141C1E99040027F340 /* LaunchScreen.storyboard */,
+ E6AFD0171C1E99040027F340 /* Info.plist */,
+ E6AFD0061C1E99040027F340 /* Supporting Files */,
+ BA604265FA2841C1B310F4EB /* Models */,
+ ED6D750F3C0B43478EDB8BE5 /* Requests */,
+ );
+ path = HTJSGeneratorCode;
+ sourceTree = "";
+ };
+ E6AFD0061C1E99040027F340 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0071C1E99040027F340 /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ E6AFD01F1C1E99040027F340 /* HTJSGeneratorCodeTests */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0201C1E99040027F340 /* HTJSGeneratorCodeTests.m */,
+ E6AFD0221C1E99040027F340 /* Info.plist */,
+ );
+ path = HTJSGeneratorCodeTests;
+ sourceTree = "";
+ };
+ E6AFD02A1C1E99040027F340 /* HTJSGeneratorCodeUITests */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD02B1C1E99040027F340 /* HTJSGeneratorCodeUITests.m */,
+ E6AFD02D1C1E99040027F340 /* Info.plist */,
+ );
+ path = HTJSGeneratorCodeUITests;
+ sourceTree = "";
+ };
+ E6B03C021C27F57600450E9E /* hehe */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = hehe;
+ sourceTree = "";
+ };
+ ED6D750F3C0B43478EDB8BE5 /* Requests */ = {
+ isa = PBXGroup;
+ children = (
+ E8335E76858442108FD3A1B9 /* HTTestRequest.h */,
+ 6266018F1506415BB379C5F0 /* HTTestRequest.m */,
+ );
+ path = Requests;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E6AFD0301C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCode" */;
+ buildPhases = (
+ E6AFCFFF1C1E99040027F340 /* Sources */,
+ E6AFD0001C1E99040027F340 /* Frameworks */,
+ E6AFD0011C1E99040027F340 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = HTJSGeneratorCode;
+ productName = HTJSGeneratorCode;
+ productReference = E6AFD0031C1E99040027F340 /* HTJSGeneratorCode.app */;
+ productType = "com.apple.product-type.application";
+ };
+ E6AFD01B1C1E99040027F340 /* HTJSGeneratorCodeTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E6AFD0331C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeTests" */;
+ buildPhases = (
+ E6AFD0181C1E99040027F340 /* Sources */,
+ E6AFD0191C1E99040027F340 /* Frameworks */,
+ E6AFD01A1C1E99040027F340 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E6AFD01E1C1E99040027F340 /* PBXTargetDependency */,
+ );
+ name = HTJSGeneratorCodeTests;
+ productName = HTJSGeneratorCodeTests;
+ productReference = E6AFD01C1C1E99040027F340 /* HTJSGeneratorCodeTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ E6AFD0261C1E99040027F340 /* HTJSGeneratorCodeUITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E6AFD0361C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeUITests" */;
+ buildPhases = (
+ E6AFD0231C1E99040027F340 /* Sources */,
+ E6AFD0241C1E99040027F340 /* Frameworks */,
+ E6AFD0251C1E99040027F340 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E6AFD0291C1E99040027F340 /* PBXTargetDependency */,
+ );
+ name = HTJSGeneratorCodeUITests;
+ productName = HTJSGeneratorCodeUITests;
+ productReference = E6AFD0271C1E99040027F340 /* HTJSGeneratorCodeUITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ E6AFCFFB1C1E99040027F340 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 700;
+ ORGANIZATIONNAME = Netease;
+ TargetAttributes = {
+ E6AFD0021C1E99040027F340 = {
+ CreatedOnToolsVersion = 7.0;
+ DevelopmentTeam = 2D4LEJ8Z2D;
+ };
+ E6AFD01B1C1E99040027F340 = {
+ CreatedOnToolsVersion = 7.0;
+ DevelopmentTeam = 2D4LEJ8Z2D;
+ TestTargetID = E6AFD0021C1E99040027F340;
+ };
+ E6AFD0261C1E99040027F340 = {
+ CreatedOnToolsVersion = 7.0;
+ DevelopmentTeam = 2D4LEJ8Z2D;
+ TestTargetID = E6AFD0021C1E99040027F340;
+ };
+ };
+ };
+ buildConfigurationList = E6AFCFFE1C1E99040027F340 /* Build configuration list for PBXProject "HTJSGeneratorCode" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = E6AFCFFA1C1E99040027F340;
+ productRefGroup = E6AFD0041C1E99040027F340 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */,
+ E6AFD01B1C1E99040027F340 /* HTJSGeneratorCodeTests */,
+ E6AFD0261C1E99040027F340 /* HTJSGeneratorCodeUITests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ E6AFD0011C1E99040027F340 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD0161C1E99040027F340 /* LaunchScreen.storyboard in Resources */,
+ E6AFD0131C1E99040027F340 /* Assets.xcassets in Resources */,
+ E6AFD0111C1E99040027F340 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD01A1C1E99040027F340 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0251C1E99040027F340 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ E6AFCFFF1C1E99040027F340 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD00E1C1E99040027F340 /* ViewController.m in Sources */,
+ E6AFD00B1C1E99040027F340 /* AppDelegate.m in Sources */,
+ E6AFD0081C1E99040027F340 /* main.m in Sources */,
+ 952203A8DF8C47769600886C /* HTTestModel.m in Sources */,
+ F72B6E5C0A744352817E3775 /* HTTestRequest.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0181C1E99040027F340 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD0211C1E99040027F340 /* HTJSGeneratorCodeTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0231C1E99040027F340 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD02C1C1E99040027F340 /* HTJSGeneratorCodeUITests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ E6AFD01E1C1E99040027F340 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */;
+ targetProxy = E6AFD01D1C1E99040027F340 /* PBXContainerItemProxy */;
+ };
+ E6AFD0291C1E99040027F340 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */;
+ targetProxy = E6AFD0281C1E99040027F340 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ E6AFD00F1C1E99040027F340 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ E6AFD0101C1E99040027F340 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ E6AFD0141C1E99040027F340 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ E6AFD0151C1E99040027F340 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ E6AFD02E1C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ E6AFD02F1C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ E6AFD0311C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = HTJSGeneratorCode/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCode;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ E6AFD0321C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = HTJSGeneratorCode/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCode;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ E6AFD0341C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ INFOPLIST_FILE = HTJSGeneratorCodeTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HTJSGeneratorCode.app/HTJSGeneratorCode";
+ };
+ name = Debug;
+ };
+ E6AFD0351C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ INFOPLIST_FILE = HTJSGeneratorCodeTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HTJSGeneratorCode.app/HTJSGeneratorCode";
+ };
+ name = Release;
+ };
+ E6AFD0371C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = HTJSGeneratorCodeUITests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_TARGET_NAME = HTJSGeneratorCode;
+ USES_XCTRUNNER = YES;
+ };
+ name = Debug;
+ };
+ E6AFD0381C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = HTJSGeneratorCodeUITests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_TARGET_NAME = HTJSGeneratorCode;
+ USES_XCTRUNNER = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ E6AFCFFE1C1E99040027F340 /* Build configuration list for PBXProject "HTJSGeneratorCode" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD02E1C1E99040027F340 /* Debug */,
+ E6AFD02F1C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E6AFD0301C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCode" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD0311C1E99040027F340 /* Debug */,
+ E6AFD0321C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E6AFD0331C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD0341C1E99040027F340 /* Debug */,
+ E6AFD0351C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E6AFD0361C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeUITests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD0371C1E99040027F340 /* Debug */,
+ E6AFD0381C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = E6AFCFFB1C1E99040027F340 /* Project object */;
+}
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..74bb09f
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.xcworkspace/xcuserdata/netease.xcuserdatad/UserInterfaceState.xcuserstate b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.xcworkspace/xcuserdata/netease.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..3f0c1c4
Binary files /dev/null and b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/project.xcworkspace/xcuserdata/netease.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/HTJSGeneratorCode.xcscheme b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/HTJSGeneratorCode.xcscheme
new file mode 100644
index 0000000..4aba1fa
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/HTJSGeneratorCode.xcscheme
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/xcschememanagement.plist b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..7062540
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ SchemeUserState
+
+ HTJSGeneratorCode.xcscheme
+
+ orderHint
+ 0
+
+
+ SuppressBuildableAutocreation
+
+ E6AFD0021C1E99040027F340
+
+ primary
+
+
+ E6AFD01B1C1E99040027F340
+
+ primary
+
+
+ E6AFD0261C1E99040027F340
+
+ primary
+
+
+
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/AppDelegate.h b/test/HTJSGeneratorCode/HTJSGeneratorCode/AppDelegate.h
new file mode 100644
index 0000000..45df665
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/AppDelegate.h
@@ -0,0 +1,17 @@
+//
+// AppDelegate.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface AppDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/AppDelegate.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/AppDelegate.m
new file mode 100644
index 0000000..184e6d2
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/AppDelegate.m
@@ -0,0 +1,45 @@
+//
+// AppDelegate.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Assets.xcassets/AppIcon.appiconset/Contents.json b/test/HTJSGeneratorCode/HTJSGeneratorCode/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..118c98f
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,38 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Base.lproj/LaunchScreen.storyboard b/test/HTJSGeneratorCode/HTJSGeneratorCode/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..2e721e1
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Base.lproj/Main.storyboard b/test/HTJSGeneratorCode/HTJSGeneratorCode/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..f56d2f3
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Base.lproj/Main.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Controllers/Test/TestViewController.h b/test/HTJSGeneratorCode/HTJSGeneratorCode/Controllers/Test/TestViewController.h
new file mode 100644
index 0000000..c2087e7
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Controllers/Test/TestViewController.h
@@ -0,0 +1,13 @@
+//
+// TestViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/21.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface TestViewController : UIViewController
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Controllers/Test/TestViewController.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/Controllers/Test/TestViewController.m
new file mode 100644
index 0000000..3e20ad5
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Controllers/Test/TestViewController.m
@@ -0,0 +1,13 @@
+//
+// TestViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/21.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "TestViewController.h"
+
+@implementation TestViewController
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Info.plist b/test/HTJSGeneratorCode/HTJSGeneratorCode/Info.plist
new file mode 100644
index 0000000..6905cc6
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Info.plist
@@ -0,0 +1,40 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Models/HTTestModel.h b/test/HTJSGeneratorCode/HTJSGeneratorCode/Models/HTTestModel.h
new file mode 100644
index 0000000..fa8d336
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Models/HTTestModel.h
@@ -0,0 +1,13 @@
+//
+// HTTestModel.h
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTTestModel : NSObject
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Models/HTTestModel.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/Models/HTTestModel.m
new file mode 100644
index 0000000..f83c855
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Models/HTTestModel.m
@@ -0,0 +1,13 @@
+//
+// HTTestModel.m
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "HTTestModel.h"
+
+@implementation HTTestModel
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Requests/HTTestRequest.h b/test/HTJSGeneratorCode/HTJSGeneratorCode/Requests/HTTestRequest.h
new file mode 100644
index 0000000..6e5ce82
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Requests/HTTestRequest.h
@@ -0,0 +1,13 @@
+//
+// HTTestRequest.h
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTTestRequest : NSObject
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/Requests/HTTestRequest.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/Requests/HTTestRequest.m
new file mode 100644
index 0000000..7b511ca
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/Requests/HTTestRequest.m
@@ -0,0 +1,13 @@
+//
+// HTTestRequest.m
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "HTTestRequest.h"
+
+@implementation HTTestRequest
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/TestViewController.h b/test/HTJSGeneratorCode/HTJSGeneratorCode/TestViewController.h
new file mode 100644
index 0000000..52d6222
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/TestViewController.h
@@ -0,0 +1,13 @@
+//
+// TestViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/17.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface TestViewController : UIViewController
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/TestViewController.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/TestViewController.m
new file mode 100644
index 0000000..5979945
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/TestViewController.m
@@ -0,0 +1,37 @@
+//
+// TestViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/17.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "TestViewController.h"
+
+@interface TestViewController ()
+
+@end
+
+@implementation TestViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ // Get the new view controller using [segue destinationViewController].
+ // Pass the selected object to the new view controller.
+}
+*/
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/ViewController.h b/test/HTJSGeneratorCode/HTJSGeneratorCode/ViewController.h
new file mode 100644
index 0000000..c4f93a3
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/ViewController.h
@@ -0,0 +1,15 @@
+//
+// ViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface ViewController : UIViewController
+
+
+@end
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/ViewController.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/ViewController.m
new file mode 100644
index 0000000..0bbe8c6
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/ViewController.m
@@ -0,0 +1,32 @@
+//
+// ViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "ViewController.h"
+#import "HTTestModel.h"
+#import "HTTestRequest.h"
+
+@interface ViewController ()
+
+@end
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view, typically from a nib.
+
+ HTTestModel *model = [[HTTestModel alloc] init];
+ NSLog(@"%@", model);
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCode/main.m b/test/HTJSGeneratorCode/HTJSGeneratorCode/main.m
new file mode 100644
index 0000000..20ae3c0
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCode/main.m
@@ -0,0 +1,16 @@
+//
+// main.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCodeTests/HTJSGeneratorCodeTests.m b/test/HTJSGeneratorCode/HTJSGeneratorCodeTests/HTJSGeneratorCodeTests.m
new file mode 100644
index 0000000..e0a334c
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCodeTests/HTJSGeneratorCodeTests.m
@@ -0,0 +1,39 @@
+//
+// HTJSGeneratorCodeTests.m
+// HTJSGeneratorCodeTests
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTJSGeneratorCodeTests : XCTestCase
+
+@end
+
+@implementation HTJSGeneratorCodeTests
+
+- (void)setUp {
+ [super setUp];
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+}
+
+- (void)tearDown {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ [super tearDown];
+}
+
+- (void)testExample {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+}
+
+- (void)testPerformanceExample {
+ // This is an example of a performance test case.
+ [self measureBlock:^{
+ // Put the code you want to measure the time of here.
+ }];
+}
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCodeTests/Info.plist b/test/HTJSGeneratorCode/HTJSGeneratorCodeTests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCodeTests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCodeUITests/HTJSGeneratorCodeUITests.m b/test/HTJSGeneratorCode/HTJSGeneratorCodeUITests/HTJSGeneratorCodeUITests.m
new file mode 100644
index 0000000..4a89e3c
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCodeUITests/HTJSGeneratorCodeUITests.m
@@ -0,0 +1,40 @@
+//
+// HTJSGeneratorCodeUITests.m
+// HTJSGeneratorCodeUITests
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTJSGeneratorCodeUITests : XCTestCase
+
+@end
+
+@implementation HTJSGeneratorCodeUITests
+
+- (void)setUp {
+ [super setUp];
+
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+
+ // In UI tests it is usually best to stop immediately when a failure occurs.
+ self.continueAfterFailure = NO;
+ // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
+ [[[XCUIApplication alloc] init] launch];
+
+ // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+}
+
+- (void)tearDown {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ [super tearDown];
+}
+
+- (void)testExample {
+ // Use recording to get started writing UI tests.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+}
+
+@end
diff --git a/test/HTJSGeneratorCode/HTJSGeneratorCodeUITests/Info.plist b/test/HTJSGeneratorCode/HTJSGeneratorCodeUITests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/test/HTJSGeneratorCode/HTJSGeneratorCodeUITests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/test/HTJSGeneratorCode/Integrate.js b/test/HTJSGeneratorCode/Integrate.js
new file mode 100644
index 0000000..3014aef
--- /dev/null
+++ b/test/HTJSGeneratorCode/Integrate.js
@@ -0,0 +1,404 @@
+// API is a bit wonky right now
+var project = require('../../lib/pbxProject.js'),
+ fs = require('fs'),
+ util = require('util'),
+ f = util.format,
+ projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj',
+ myProj = project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+myProj.parseSync();
+
+function test1() {
+ // var requestGroupKey = myProj.findPBXGroupKey({path: 'HTJSGeneratorCode/Request'});
+ // var requestGroupKey = myProj.findPBXGroupKey({path: 'HTJSGeneratorCode/Requests'});
+ // TODO: 如何找到绝对路径下的Group呢?
+ var requestGroupKey = myProj.findPBXGroupKey({path: 'Requests'});
+ if (requestGroupKey === undefined) {
+ var keyByName = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+ var requestGroupKey = myProj.pbxCreateGroup("Requests", "Requests");
+ myProj.addToPbxGroup(requestGroupKey, keyByName, {});
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ } else {
+ console.log("requestGroupKey is found successfullye: " + requestGroupKey);
+ var parentGroupKey = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+
+ // TODO: 这个老的方法只能删除文件,不能删除Group. 要自己重写.
+ // 看情况, 删除Group的时候,还需要自己删除所有的文件.
+ myProj.removeFromPbxGroup(requestGroupKey, parentGroupKey);
+
+ // TODO: 同名的Group也会被删除. 而且只能按照名字来删除,不能按照Key来删除.
+ myProj.removePbxGroup('Requests');
+
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ }
+}
+
+function testRemoveSubGroup() {
+ var requestGroupKey = myProj.findPBXGroupKeyInParent({path: 'Requests'}, {path: 'HTJSGeneratorCode'});
+
+ if (requestGroupKey === undefined) {
+ // Add new group.
+ var keyByName = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+ var requestGroupKey = myProj.pbxCreateGroup("Requests", "Requests");
+ myProj.addToPbxGroup(requestGroupKey, keyByName, {});
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ } else {
+ // Remove group.
+ console.log("requestGroupKey is found successfullye: " + requestGroupKey);
+ var parentGroupKey = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+
+ // TODO: 预期在这个方法中, 1 从Parent中删除该Group. 2 删除所有该Group下的文件 3 从Project中删除该Group.
+ myProj.removeGroupFromPbxGroup(requestGroupKey, parentGroupKey);
+
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ }
+}
+
+// 删除所有同名的Group.
+function testRemoveGroups() {
+ // 删除 Group的时候不会删除Group下添加的文件,但是重新添加新文件的话工程会自动修正.
+ myProj.removePbxGroup("11");
+ fs.writeFileSync(projectPath, myProj.writeSync());
+}
+
+function testworkflow() {
+ console.log("Start update Project " + projectPath + " !");
+
+ // Step 1: Find parent Group Key according to path. This group must be available in the project.
+ // Model files and request files will be added into this group.
+ // TODO: The path should be passed as a param.
+ var parentGroupKey = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+ console.log("parentGroupKey : " + parentGroupKey);
+
+ // Step 2: Create group if it doesn't exist.
+ // TODO: 1 Group name and path should be passed as params. 2 If the group already exists then it is uncessary to create and add them.
+ var modelGroupKey = myProj.findPBXGroupKeyInParentGroup({ path: 'Models'}, parentGroupKey);
+ if (undefined == modelGroupKey) {
+ // Step 2: 不存在则新建Group.
+ modelGroupKey = myProj.pbxCreateGroup("Models", "Models");
+
+ // Add new created groups into parent group.
+ // Step 3: 将Group加到parent Group中
+ myProj.addToPbxGroup(modelGroupKey, parentGroupKey, {});
+ } else {
+ // Step 3: 如果存在,那么删除文件.
+ // TODO: 1 File path may not work if group directory doesn't match. 2 Loop directories to find files automatically.
+ // TODO: 这里不可以直接用removeFile和addFile,一定要区分header和Source.
+ myProj.removeHeaderFile('HTTestModel.h', {}, modelGroupKey);
+ myProj.removeSourceFile('HTTestModel.m', {}, modelGroupKey);
+ }
+
+ myProj.addHeaderFile('HTTestModel.h', {}, modelGroupKey);
+ myProj.addSourceFile('HTTestModel.m', {}, modelGroupKey);
+
+
+ // Step 5: Write back to project.
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated successfully !");
+}
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath() {
+ var fullPath = "HTJSGeneratorCode/Models";
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0) {
+ root = pathList[0];
+ groupKey = myProj.findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ var group = myProj.getPBXGroupByKey(groupKey);
+
+ return groupKey;
+}
+
+//findGroupByAbsolutePath();
+
+// 遍历文件和目录
+function loopFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName || "h" == extensionFileName) {
+ console.log(file);
+ }
+ });
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
+
+//loopFilesInFilePath("HTJSGeneratorCode/Models");
+
+// 添加文件夹到某个Group. 主要是依赖遍历文件和目录.
+//function addFolderToGroup() {
+//
+//}
+
+var groupParentPath = process.argv[2];
+var folderParentPath = process.argv[3];
+function testArgv() {
+ console.log(groupParentPath);
+ console.log(folderParentPath);
+}
+
+testArgv();
+
+// removeFilesInGroup已经OK.
+// Done. 根据FileRef的UUID从Project的File Reference Section中删除.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ // TODO: delete buildFile没有从这个字典中真正删除这个文件.
+ //delete buildFile;
+ delete myProj.pbxBuildFileSection()[uuid];
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return uuid;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 所以这个方法不正确.
+function removeFromPbxSourcesBuildPhaseWithKey (fileRef) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup() {
+ var groupKey = myProj.findPBXGroupKey({ path: 'Models'});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+
+ console.log("finish one file");
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+
+ var length = groupChildren.length;
+ groupChildren = group.children;
+ length = groupChildren.length;
+ console.log(length);
+ }
+}
+
+
+
+
+
+//
+//pbxProject.prototype.removeSourceFile = function (path, opt, group) {
+// var file;
+// if (group) {
+// file = this.removeFile(path, group, opt);
+// }
+// else {
+// file = this.removePluginFile(path, opt);
+// }
+// file.target = opt ? opt.target : undefined;
+// this.removeFromPbxBuildFileSection(file); // PBXBuildFile
+// this.removeFromPbxSourcesBuildPhase(file); // PBXSourcesBuildPhase
+//
+// return file;
+//}
+//
+//pbxProject.prototype.removeFile = function (path, group, opt) {
+// var file = new pbxFile(path, opt);
+//
+// this.removeFromPbxFileReferenceSection(file); // PBXFileReference
+// this.removeFromPbxGroup(file, group); // PBXGroup
+//
+// return file;
+//}
+
+
+
+//testRemoveGroups();
+//testRemoveSubGroup();
+//testworkflow();
+//removeFilesInGroup();
+removeFromPbxBuildFileSectionWithKey('C91E3A4AF2304AB99F4825DB');
+fs.writeFileSync(projectPath, myProj.writeSync());
+
+
+
+
+
+function testRemoveFile() {
+ var modelGroupKey = myProj.findPBXGroupKey({ path: 'Models'});
+ if (undefined != modelGroupKey) {
+ myProj.removeHeaderFile('HTTestModel.h', {}, modelGroupKey);
+ myProj.removeSourceFile('HTTestModel.m', {}, modelGroupKey);
+ }
+
+ // Step 5: Write back to project.
+ //fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated successfully !");
+}
+
+//testRemoveFile();
+
+
+
+
+
+
+
+//
+//exports.findGroupKey = {
+// 'should return a valid group key':function(test) {
+// var keyByName = project.findPBXGroupKey({ name: 'Classes'});
+// var keyByPath = project.findPBXGroupKey({ path: 'icons'});
+// var keyByPathName = project.findPBXGroupKey({ path: '"HelloCordova/Plugins"', name: 'Plugins'});
+// var nonExistingKey = project.findPBXGroupKey({ name: 'Foo'});
+//
+// test.ok(keyByName === '080E96DDFE201D6D7F000001');
+// test.ok(keyByPath === '308D052D1370CCF300D202BF');
+// test.ok(keyByPathName === '307C750510C5A3420062BCA9');
+// test.ok(nonExistingKey === undefined);
+//
+// test.done();
+// }
+//}
+
+// parsing is async, in a different process
+//myProj.parse(function (err) {
+// console.log(myProj);
+//
+// var keyByName = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+// console.log("keyByName" + keyByName);
+// //
+//
+// myProj.removeFile('Models/HTTestModel.h', {}, keyByName);
+// myProj.removeFile('Models/HTTestModel.m', keyByName, {});
+// //
+// myProj.addHeaderFile('Models/HTTestModel.h', {}, keyByName);
+// myProj.addFile('Models/HTTestModel.m', keyByName, {});
+// //
+//
+// //myProj.removeFile('Models/HTTestModel.h', {}, 'HTJSGeneratorCode');
+// //myProj.removeFile('Models/HTTestModel.m', 'HTJSGeneratorCode', {});
+// //
+// //myProj.addHeaderFile('Models/HTTestModel.h', {}, 'HTJSGeneratorCode');
+// //myProj.addFile('Models/HTTestModel.m', 'HTJSGeneratorCode', {});
+//
+// var modelGroupKey = myProj.pbxCreateGroup("Models", "Models");
+// var requestGroupKey = myProj.pbxCreateGroup("Requests", "Requests");
+// console.log("modelGroupKey: " + modelGroupKey + " requestGroupKey: " + requestGroupKey);
+//
+// myProj.addToPbxGroup(requestGroupKey, 'HTJSGeneratorCode', {});
+//
+// //var requestGroupKey = myProj.findPBXGroupKey( {path: "Requests"});
+// myProj.addSourceFile('HTTestRequest.m', requestGroupKey, {});
+//
+// fs.writeFileSync(projectPath, myProj.writeSync());
+// console.log('new project written 111');
+//});
+
+// 正式干净的代码
+//
+//myProj.parse(function (err) {
+// console.log("Start update Project " + projectPath + " !");
+//
+// // Step 1: Find parent Group Key according to path. This group must be available in the project.
+// // Model files and request files will be added into this group.
+// // TODO: The path should be passed as a param.
+// var parentGroupKey = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+// console.log("parentGroupKey : " + parentGroupKey);
+//
+// // Step 2: Create group if it doesn't exist.
+// // TODO: 1 Group name and path should be passed as params. 2 If the group already exists then it is uncessary to create and add them.
+// var modelGroupKey = myProj.pbxCreateGroup("Models", "Models");
+// var requestGroupKey = myProj.pbxCreateGroup("Requests", "Requests");
+//
+// // Step 3: Add new created groups into parent group.
+// // Note: Currently it is not supported to put models and requests into different parent groups.
+// myProj.addToPbxGroup(modelGroupKey, parentGroupKey, {});
+// myProj.addToPbxGroup(requestGroupKey, parentGroupKey, {});
+//
+// // Step 4: Remove files from Group and Add files into Group.
+// // TODO: 1 File path may not work if group directory doesn't match. 2 Loop directories to find files automatically.
+// myProj.removeFile('Models/HTTestModel.h', {}, modelGroupKey);
+// myProj.removeFile('Models/HTTestModel.m', modelGroupKey, {});
+// myProj.addHeaderFile('Models/HTTestModel.h', {}, modelGroupKey);
+// myProj.addSourceFile('Models/HTTestModel.m', {}, modelGroupKey);
+//
+// myProj.removeFile('Requests/HTTestRequest.h', {}, requestGroupKey);
+// myProj.removeFile('Requests/HTTestRequest.m', requestGroupKey, {});
+// myProj.addHeaderFile('Requests/HTTestRequest.h', {}, requestGroupKey);
+// myProj.addSourceFile('Requests/HTTestRequest.m', {}, requestGroupKey);
+//
+//
+// // Step 5: Write back to project.
+// fs.writeFileSync(projectPath, myProj.writeSync());
+// console.log('Project ' + projectPath + " is updated successfully !");
+//});
\ No newline at end of file
diff --git a/test/HTJSGeneratorCode/IntegrateDebug.js b/test/HTJSGeneratorCode/IntegrateDebug.js
new file mode 100644
index 0000000..9dc79d2
--- /dev/null
+++ b/test/HTJSGeneratorCode/IntegrateDebug.js
@@ -0,0 +1,46 @@
+// API is a bit wonky right now
+var project = require('../../lib/pbxProject.js'),
+ fs = require('fs'),
+ projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj',
+ myProj = project(projectPath);
+
+myProj.parseSync();
+
+var keyByName = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+var requestGroupKey = myProj.pbxCreateGroup("Requests", "Requests");
+ group = myProj.addToPbxGroup(requestGroupKey, keyByName, {});
+console.log(group);
+fs.writeFileSync(projectPath, myProj.writeSync());
+
+// parsing is async, in a different process
+//myProj.parse(function (err) {
+// console.log(myProj);
+//
+// //var keyByName = myProj.findPBXGroupKey({ path: 'HTJSGeneratorCode'});
+// //console.log("keyByName" + keyByName);
+// //
+// //myProj.removeFile('Models/HTTestModel.h', {}, keyByName);
+// //myProj.removeFile('Models/HTTestModel.m', keyByName, {});
+// //
+// //myProj.addHeaderFile('Models/HTTestModel.h', {}, keyByName);
+// //myProj.addFile('Models/HTTestModel.m', keyByName, {});
+// //
+//
+// //myProj.removeFile('Models/HTTestModel.h', {}, 'HTJSGeneratorCode');
+// //myProj.removeFile('Models/HTTestModel.m', 'HTJSGeneratorCode', {});
+// //
+// //myProj.addHeaderFile('Models/HTTestModel.h', {}, 'HTJSGeneratorCode');
+// //myProj.addFile('Models/HTTestModel.m', 'HTJSGeneratorCode', {});
+//
+// var modelGroupKey = myProj.pbxCreateGroup("Models", "Models");
+// var requestGroupKey = myProj.pbxCreateGroup("Requests", "Requests");
+// console.log("modelGroupKey: " + modelGroupKey + " requestGroupKey: " + requestGroupKey);
+//
+// myProj.addToPbxGroup(requestGroupKey, 'HTJSGeneratorCode', {});
+//
+// //var requestGroupKey = myProj.findPBXGroupKey( {path: "Requests"});
+// myProj.addSourceFile('HTTestRequest.m', requestGroupKey, {});
+//
+// fs.writeFileSync(projectPath, myProj.writeSync());
+// console.log('new project written 111');
+//});
\ No newline at end of file
diff --git a/test/HTJSGeneratorCode/UpdateModels.js b/test/HTJSGeneratorCode/UpdateModels.js
new file mode 100644
index 0000000..5473bc8
--- /dev/null
+++ b/test/HTJSGeneratorCode/UpdateModels.js
@@ -0,0 +1,224 @@
+// API is a bit wonky right now
+var project = require('../../lib/pbxProject.js'),
+ fs = require('fs'),
+ util = require('util'),
+ f = util.format;
+
+// TODO:参数缺少时, 需要给予警告和提示. 参数的处理需要更灵活
+// node UpdateModels.js projectName groupParentPath folderParentPath
+var projectName = process.argv[2];
+var groupParentPath = process.argv[3];
+var folderParentPath = process.argv[4];
+var projectPath = projectName + '.xcodeproj/project.pbxproj';
+//var projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj';
+
+// Get Project.
+var myProj = project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+// For release version, it is OK to use parse function.
+myProj.parseSync();
+updateCode();
+
+function updateCode () {
+ if (undefined == projectName || undefined == groupParentPath || undefined == folderParentPath || undefined == myProj) {
+ console.log("Please correct parameters, the command is like \r\n node UpdateModels.js projectName groupParentPath folderParentPath, please specify your own projectName, parent group path and pareng folder path");
+ return;
+ }
+
+ // TODO: 现在暂时不支持更换路径,即之前要删除的路径和后面要添加的路径不相同的Case.
+ console.log("Begin to update project " + projectName + ", Models and Requests will be added under group " + groupParentPath);
+
+ // 固定添加Models和Requests, 不需要参数配置
+ var autoGroupNames = ["Models", "Requests"];
+ autoGroupNames.forEach(function (groupName){
+ console.log("Begin to check folder " + groupName);
+
+ // 获取parent Group Key 和 要处理的Group Key
+ var absoluteGroupPath = groupParentPath + "/" + groupName;
+ var parentGroupKey = findGroupByAbsolutePath(groupParentPath);
+ var groupKey = findGroupByAbsolutePath(absoluteGroupPath);
+ if (undefined == groupKey) {
+ // group不存在, 新建Group. GroupName与Path相同.
+ console.log("Group " + groupName + " does not exist, create group " + groupName + " under group " + groupParentPath);
+ groupKey = myProj.pbxCreateGroup(groupName, groupName);
+
+ // Add new created groups into parent group.
+ // 将Group加到parent Group中
+ myProj.addToPbxGroup(groupKey, parentGroupKey, {});
+ } else {
+ // group存在, 删除其中的所有文件.
+ console.log("Group " + groupName + " already exists, remove all files in this group first.");
+ removeFilesInGroup(groupName);
+ }
+
+ // 获取目录下的所有头文件和可执行文件
+ var folderPath = folderParentPath + "/" + groupName;
+ var headerFiles = headerFilesInFilePath(folderPath);
+ var sourceFiles = sourceFilesInFilePath(folderPath);
+
+ // 将头文件添加到group中.
+ headerFiles.forEach(function(headerFile) {
+ myProj.addHeaderFile(headerFile, {}, groupKey);
+ });
+
+ // 将源文件添加到group中
+ sourceFiles.forEach(function(sourceFile) {
+ myProj.addSourceFile(sourceFile, {}, groupKey);
+ });
+
+ console.log("Add Source Files and Header Files from Path " + folderPath + " to group " + absoluteGroupPath + " successfully");
+ });
+
+
+ // 将内容写回到工程文件中.
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated successfully !");
+}
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath(fullPath) {
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0 && undefined != groupKey) {
+ root = pathList[0];
+ groupKey = myProj.findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ // TODO: 下面的代码只用校验是否能够取到正确的Group.
+ if (undefined != groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ }
+
+ return groupKey;
+}
+
+// removeFilesInGroup已经OK.
+// Done. 根据FileRef的UUID从Project的File Reference Section中删除.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ // TODO: delete buildFile没有从这个字典中真正删除这个文件.
+ //delete buildFile;
+ delete myProj.pbxBuildFileSection()[uuid];
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return buildFileUUID;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 所以这个方法不正确.
+function removeFromPbxSourcesBuildPhaseWithKey (fileRef) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup(groupName) {
+ var groupKey = myProj.findPBXGroupKey({ path: groupName});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+ }
+}
+
+// 找到所有的头文件.
+function headerFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("h" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+// 找到所有的源文件
+// TODO: 性能可以改进, 可以一次性找出头文件和源文件,不需要每次都遍历一遍.
+function sourceFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
\ No newline at end of file
diff --git a/test/HTJSGeneratorCode/UpdateNEIProject.js b/test/HTJSGeneratorCode/UpdateNEIProject.js
new file mode 100644
index 0000000..164747e
--- /dev/null
+++ b/test/HTJSGeneratorCode/UpdateNEIProject.js
@@ -0,0 +1,451 @@
+// 这个JS直接引用xcode, 所有额外添加的东西都加在这个JS文件中.
+var xcode = require('xcode'),
+ fs = require('fs'),
+ util = require('util'),
+ COMMENT_KEY = /_comment$/,
+ f = util.format;
+
+// TODO:参数缺少时, 需要给予警告和提示. 参数的处理需要更灵活
+// node UpdateModels.js projectName groupParentPath folderParentPath
+var projectName = process.argv[2];
+var groupParentPath = process.argv[3];
+var folderParentPath = process.argv[4];
+var projectPath = projectName + '.xcodeproj/project.pbxproj';
+//var projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj';
+
+// Get Project.
+var myProj = xcode.project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+// For release version, it is OK to use parse function.
+myProj.parseSync();
+updateCode();
+
+function updateCode () {
+ if (undefined == projectName || undefined == groupParentPath || undefined == folderParentPath || undefined == myProj) {
+ console.log("Please correct parameters, the command is like \r\n node UpdateModels.js projectName groupParentPath folderParentPath, please specify your own projectName, parent group path and pareng folder path");
+ return;
+ }
+
+ // TODO: 现在暂时不支持更换路径,即之前要删除的路径和后面要添加的路径不相同的Case.
+ console.log("Begin to update project " + projectName + ", Models and Requests will be added under group " + groupParentPath);
+
+ // 固定添加Models和Requests, 不需要参数配置
+ var autoGroupNames = ["Models", "Requests"];
+ autoGroupNames.forEach(function (groupName){
+ console.log("Begin to check folder " + groupName);
+
+ // 获取parent Group Key 和 要处理的Group Key
+ var absoluteGroupPath = groupParentPath + "/" + groupName;
+ var parentGroupKey = findGroupByAbsolutePath(groupParentPath);
+ var groupKey = findGroupByAbsolutePath(absoluteGroupPath);
+ if (undefined == groupKey) {
+ // group不存在, 新建Group. GroupName与Path相同.
+ console.log("Group " + groupName + " does not exist, create group " + groupName + " under group " + groupParentPath);
+ groupKey = myProj.pbxCreateGroup(groupName, groupName);
+
+ // Add new created groups into parent group.
+ // 将Group加到parent Group中
+ myProj.addToPbxGroup(groupKey, parentGroupKey, {});
+ } else {
+ // group存在, 删除其中的所有文件.
+ console.log("Group " + groupName + " already exists, remove all files in this group first.");
+ removeFilesInGroup(groupName);
+ }
+
+ // 获取目录下的所有头文件和可执行文件
+ var folderPath = folderParentPath + "/" + groupName;
+ var headerFiles = headerFilesInFilePath(folderPath);
+ var sourceFiles = sourceFilesInFilePath(folderPath);
+
+ // 将头文件添加到group中.
+ headerFiles.forEach(function(headerFile) {
+ myProj.addHeaderFile(headerFile, {}, groupKey);
+ });
+
+ // 将源文件添加到group中
+ sourceFiles.forEach(function(sourceFile) {
+ myProj.addSourceFile(sourceFile, {}, groupKey);
+ });
+
+ console.log("Add Source Files and Header Files from Path " + folderPath + " to group " + absoluteGroupPath + " successfully");
+ });
+
+
+ // 将内容写回到工程文件中.
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated successfully !");
+}
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath(fullPath) {
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0 && undefined != groupKey) {
+ root = pathList[0];
+ groupKey = findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ // TODO: 下面的代码只用校验是否能够取到正确的Group.
+ if (undefined != groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ }
+
+ return groupKey;
+}
+
+// removeFilesInGroup已经OK.
+// Done. 根据FileRef的UUID从Project的File Reference Section中删除.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ // TODO: delete buildFile没有从这个字典中真正删除这个文件.
+ //delete buildFile;
+ delete myProj.pbxBuildFileSection()[uuid];
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return buildFileUUID;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 所以这个方法不正确.
+function removeFromPbxSourcesBuildPhaseWithKey (fileRef) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup(groupName) {
+ var groupKey = myProj.findPBXGroupKey({ path: groupName});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+ }
+}
+
+// 找到所有的头文件.
+function headerFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("h" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+// 找到所有的源文件
+// TODO: 性能可以改进, 可以一次性找出头文件和源文件,不需要每次都遍历一遍.
+function sourceFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
+
+
+
+
+
+
+
+
+
+
+
+// Projects Extension
+// 这些最好添加到pbxProject.js中, 仅供当前流程使用.
+function removePbxGroupByKey(groupKey) {
+ var section = myProj.hash.project.objects['PBXGroup'],
+ key, itemKey;
+
+ for (key in section) {
+ // only look for comments
+ if (!COMMENT_KEY.test(key)) continue;
+
+ if (key == groupKey) {
+ itemKey = key.split(COMMENT_KEY)[0];
+ delete section[itemKey];
+ }
+ }
+}
+
+function removeGroupFromPbxGroup(removeGroupKey, groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var removeGroup = myProj.getPBXGroupByKey(removeGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ if(removeGroupKey == groupChildren[i].value && removeGroup != undefined) {
+ groupChildren.splice(i, 1);
+
+ clearGroup(removeGroup);
+ break;
+ }
+ }
+ }
+
+ delete removeGroup;
+}
+
+function clearGroup(group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+}
+
+function removeGroupByKey(key, parentGroupKey) {
+ var group = getPBXGroupByKey(key, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+// Remove a group and all files in this group.
+function removeGroup(groupPath, parentGroupKey) {
+ var group = getPBXGroupByPath(groupPath, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+
+function getPBXGroupByPath(path, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? myProj.hash.project.objects['PBXGroup'] : myProj.getPBXGroupByKey(parentGroupKey);
+ for (var key in groups) {
+ var group = groups[key];
+ if (group.path === path) {
+ return group;
+ }
+ }
+
+ return undefined;
+};
+
+function getPBXGroupByKey(key, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? myProj.hash.project.objects['PBXGroup'] : myProj.getPBXGroupByKey(parentGroupKey);
+ var group = groups[key];
+ return group;
+};
+
+function findPBXGroupInParent(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return myProj.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = myProj.findPBXGroupKey(parentCriteria);
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+function findPBXGroupKeyInParent(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return myProj.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = myProj.findPBXGroupKey(parentCriteria);
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+
+function findPBXGroupKeyInParentGroup(criteria, parentGroupKey) {
+ var target;
+ var group = getPBXGroupByKey(parentGroupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
diff --git a/test/HTJSGeneratorCode/pbxProjectWrap.js b/test/HTJSGeneratorCode/pbxProjectWrap.js
new file mode 100644
index 0000000..9fe5412
--- /dev/null
+++ b/test/HTJSGeneratorCode/pbxProjectWrap.js
@@ -0,0 +1,144 @@
+// API is a bit wonky right now
+var project = require('../../lib/pbxProject.js'),
+ fs = require('fs'),
+ util = require('util'),
+ f = util.format,
+ projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj',
+ myProj = project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+myProj.parseSync();
+
+// Done. 根据uuid从Project的File Reference Section中删除某个文件.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// Done. 根据uuid从Project的Build File Section中删除某个文件.
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ delete buildFile;
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return uuid;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 这里必须传递biuldFile 的Key而不是File Reference的Key.
+function removeFromPbxSourcesBuildPhaseWithKey (buildFileKey) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup() {
+ var groupKey = myProj.findPBXGroupKey({ path: 'Models'});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+
+ console.log("finish one file");
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+
+ //var length = groupChildren.length;
+ //groupChildren = group.children;
+ //length = groupChildren.length;
+ //console.log(length);
+ }
+}
+
+// 遍历文件和目录
+function loopFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName || "h" == extensionFileName) {
+ console.log(file);
+ }
+ });
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
+
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath() {
+ var fullPath = "HTJSGeneratorCode/Models";
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0) {
+ root = pathList[0];
+ groupKey = myProj.findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ var group = myProj.getPBXGroupByKey(groupKey);
+
+ return groupKey;
+}
\ No newline at end of file
diff --git a/test/HTTestResources/AddResources.js b/test/HTTestResources/AddResources.js
new file mode 100644
index 0000000..131ae5c
--- /dev/null
+++ b/test/HTTestResources/AddResources.js
@@ -0,0 +1,534 @@
+// 这个JS直接引用xcode, 所有额外添加的东西都加在这个JS文件中.
+//var xcode = require('xcode'),
+var project = require('../../lib/pbxProject.js'),
+ fs = require('fs'),
+ util = require('util'),
+ COMMENT_KEY = /_comment$/,
+ f = util.format;
+
+// TODO:参数缺少时, 需要给予警告和提示. 参数的处理需要更灵活
+// node UpdateModels.js projectName groupParentPath folderParentPath
+//var projectName = process.argv[2];
+//var groupParentPath = process.argv[3];
+//var folderParentPath = process.argv[4];
+var projectName = 'HTJSGeneratorCode';
+var groupParentPath = 'HTJSGeneratorCode';
+var folderParentPath = 'HTJSGeneratorCode';
+var projectPath = projectName + '.xcodeproj/project.pbxproj';
+//var projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj';
+
+// Get Project.
+//var myProj = xcode.project(projectPath);
+var myProj = project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+// For release version, it is OK to use parse function.
+myProj.parseSync();
+//updateCode();
+addResources();
+
+//
+//function updateCode () {
+// if (undefined == projectName || undefined == groupParentPath || undefined == folderParentPath || undefined == myProj) {
+// console.log("Please correct parameters, the command is like \r\n node UpdateModels.js projectName groupParentPath folderParentPath, please specify your own projectName, parent group path and pareng folder path");
+// return;
+// }
+//
+// // TODO: 现在暂时不支持更换路径,即之前要删除的路径和后面要添加的路径不相同的Case.
+// console.log("Begin to update project " + projectName + ", Models and Requests will be added under group " + groupParentPath);
+//
+// // 固定添加Models和Requests, 不需要参数配置
+// var autoGroupNames = ["Models", "Requests"];
+// autoGroupNames.forEach(function (groupName){
+// console.log("Begin to check folder " + groupName);
+//
+// // 获取parent Group Key 和 要处理的Group Key
+// var absoluteGroupPath = groupParentPath + "/" + groupName;
+// var parentGroupKey = findGroupByAbsolutePath(groupParentPath);
+// var groupKey = findGroupByAbsolutePath(absoluteGroupPath);
+// if (undefined == groupKey) {
+// // group不存在, 新建Group. GroupName与Path相同.
+// console.log("Group " + groupName + " does not exist, create group " + groupName + " under group " + groupParentPath);
+// groupKey = myProj.pbxCreateGroup(groupName, groupName);
+//
+// // Add new created groups into parent group.
+// // 将Group加到parent Group中
+// myProj.addToPbxGroup(groupKey, parentGroupKey, {});
+// } else {
+// // group存在, 删除其中的所有文件.
+// console.log("Group " + groupName + " already exists, remove all files in this group first.");
+// removeFilesInGroup(groupName);
+// }
+//
+// // 获取目录下的所有头文件和可执行文件
+// var folderPath = folderParentPath + "/" + groupName;
+// var headerFiles = headerFilesInFilePath(folderPath);
+// var sourceFiles = sourceFilesInFilePath(folderPath);
+//
+// // 将头文件添加到group中.
+// headerFiles.forEach(function(headerFile) {
+// myProj.addHeaderFile(headerFile, {}, groupKey);
+// });
+//
+// // 将源文件添加到group中
+// sourceFiles.forEach(function(sourceFile) {
+// myProj.addSourceFile(sourceFile, {}, groupKey);
+// });
+//
+// console.log("Add Source Files and Header Files from Path " + folderPath + " to group " + absoluteGroupPath + " successfully");
+// });
+//
+//
+// // 将内容写回到工程文件中.
+// fs.writeFileSync(projectPath, myProj.writeSync());
+// console.log('Project ' + projectPath + " is updated successfully !");
+//}
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath(fullPath) {
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0 && undefined != groupKey) {
+ root = pathList[0];
+ groupKey = findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ // TODO: 下面的代码只用校验是否能够取到正确的Group.
+ if (undefined != groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ }
+
+ return groupKey;
+}
+
+// removeFilesInGroup已经OK.
+// Done. 根据FileRef的UUID从Project的File Reference Section中删除.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ // TODO: delete buildFile没有从这个字典中真正删除这个文件.
+ //delete buildFile;
+ delete myProj.pbxBuildFileSection()[uuid];
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return buildFileUUID;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 所以这个方法不正确.
+function removeFromPbxSourcesBuildPhaseWithKey (fileRef) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup(groupName) {
+ var groupKey = myProj.findPBXGroupKey({ path: groupName});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+ }
+}
+
+// 找到所有的头文件.
+function headerFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("h" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+// 找到所有的源文件
+// TODO: 性能可以改进, 可以一次性找出头文件和源文件,不需要每次都遍历一遍.
+function sourceFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
+
+
+
+
+
+
+
+
+
+
+
+// Projects Extension
+// 这些最好添加到pbxProject.js中, 仅供当前流程使用.
+function removePbxGroupByKey(groupKey) {
+ var section = myProj.hash.project.objects['PBXGroup'],
+ key, itemKey;
+
+ for (key in section) {
+ // only look for comments
+ if (!COMMENT_KEY.test(key)) continue;
+
+ if (key == groupKey) {
+ itemKey = key.split(COMMENT_KEY)[0];
+ delete section[itemKey];
+ }
+ }
+}
+
+function removeGroupFromPbxGroup(removeGroupKey, groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var removeGroup = myProj.getPBXGroupByKey(removeGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ if(removeGroupKey == groupChildren[i].value && removeGroup != undefined) {
+ groupChildren.splice(i, 1);
+
+ clearGroup(removeGroup);
+ break;
+ }
+ }
+ }
+
+ delete removeGroup;
+}
+
+function clearGroup(group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+}
+
+function removeGroupByKey(key, parentGroupKey) {
+ var group = getPBXGroupByKey(key, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+// Remove a group and all files in this group.
+function removeGroup(groupPath, parentGroupKey) {
+ var group = getPBXGroupByPath(groupPath, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+
+function getPBXGroupByPath(path, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? myProj.hash.project.objects['PBXGroup'] : myProj.getPBXGroupByKey(parentGroupKey);
+ for (var key in groups) {
+ var group = groups[key];
+ if (group.path === path) {
+ return group;
+ }
+ }
+
+ return undefined;
+};
+
+function getPBXGroupByKey(key, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? myProj.hash.project.objects['PBXGroup'] : myProj.getPBXGroupByKey(parentGroupKey);
+ var group = groups[key];
+ return group;
+};
+
+function findPBXGroupInParent(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return myProj.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = myProj.findPBXGroupKey(parentCriteria);
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+function findPBXGroupKeyInParent(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return myProj.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = myProj.findPBXGroupKey(parentCriteria);
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+
+function findPBXGroupKeyInParentGroup(criteria, parentGroupKey) {
+ var target;
+ var group = getPBXGroupByKey(parentGroupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+
+
+
+function addResources () {
+ if (undefined == projectName || undefined == groupParentPath || undefined == folderParentPath || undefined == myProj) {
+ console.log("Please correct parameters, the command is like \r\n node UpdateModels.js projectName groupParentPath folderParentPath, please specify your own projectName, parent group path and pareng folder path");
+ return;
+ }
+
+ var parentGroupKey = findGroupByAbsolutePath(groupParentPath);
+ if (undefined == parentGroupKey) {
+ console.log("Could not find group to add resource file");
+ }
+
+
+ //addXcassets("Assets.xcassets", parentGroupKey);
+ //addPlistFile("Info.plist", parentGroupKey, {});
+
+ // 将内容写回到工程文件中.
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated with Info.plist successfully !");
+}
+
+
+
+function addXibFile(path, opt) {
+ myProj.addResourceFile(path, opt);
+}
+
+function addStoryboardFile(path, opt) {
+ myProj.addResourceFile(path, opt);
+}
+
+// 测试通过.
+function addPlistFile(path, group, opt) {
+ myProj.addFile(path, group, opt);
+}
+
+
+function addXcassets(path, group, opt) {
+ myProj.addResourceFile(path, opt);
+}
+
+//
+//pbxProject.prototype.addResourceFile = function(path, opt) {
+// opt = opt || {};
+//
+// var file;
+//
+// if (opt.plugin) {
+// file = this.addPluginFile(path, opt);
+// if (!file) return false;
+// } else {
+// file = new pbxFile(path, opt);
+// if (this.hasFile(file.path)) return false;
+// }
+//
+// file.uuid = this.generateUuid();
+// file.target = opt ? opt.target : undefined;
+//
+// if (!opt.plugin) {
+// correctForResourcesPath(file, this);
+// file.fileRef = this.generateUuid();
+// }
+//
+// this.addToPbxBuildFileSection(file); // PBXBuildFile
+// this.addToPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase
+//
+// if (!opt.plugin) {
+// this.addToPbxFileReferenceSection(file); // PBXFileReference
+// this.addToResourcesPbxGroup(file); // PBXGroup
+// }
+//
+// return file;
+//}
diff --git a/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.pbxproj b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..69126ba
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.pbxproj
@@ -0,0 +1,595 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1633717AA6294BD4B13F3ED7 /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C091F8560FBB4B8693F87C1F /* TestViewController.m */; };
+ 70459B39CB83470FAEC65357 /* HTTestRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = B96CF0CB8B164CA7B961B7C8 /* HTTestRequest.m */; };
+ 7068F19789004D5D81E338AD /* HTTestModel1.m in Sources */ = {isa = PBXBuildFile; fileRef = C986780B42C44F2598E4E234 /* HTTestModel1.m */; };
+ 7134CF06962A4FE08E75D36B /* TestViewController1.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E124782988F4EA8A210945F /* TestViewController1.m */; };
+ D4224B2B6F6443B5BAA60C2B /* HTTestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF6840A3E42462796687B18 /* HTTestModel.m */; };
+ E63CC7931C2CEB1E0092683A /* HTTestModel1.m in Sources */ = {isa = PBXBuildFile; fileRef = E63CC7921C2CEB1E0092683A /* HTTestModel1.m */; settings = {ASSET_TAGS = (); }; };
+ E63CC7961C2CEB6F0092683A /* TestViewController1.m in Sources */ = {isa = PBXBuildFile; fileRef = E63CC7951C2CEB6F0092683A /* TestViewController1.m */; settings = {ASSET_TAGS = (); }; };
+ E6AFD0081C1E99040027F340 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD0071C1E99040027F340 /* main.m */; };
+ E6AFD00B1C1E99040027F340 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD00A1C1E99040027F340 /* AppDelegate.m */; };
+ E6AFD00E1C1E99040027F340 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD00D1C1E99040027F340 /* ViewController.m */; };
+ E6AFD0111C1E99040027F340 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E6AFD00F1C1E99040027F340 /* Main.storyboard */; };
+ E6AFD0131C1E99040027F340 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E6AFD0121C1E99040027F340 /* Assets.xcassets */; };
+ E6AFD0161C1E99040027F340 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E6AFD0141C1E99040027F340 /* LaunchScreen.storyboard */; };
+ E6AFD0211C1E99040027F340 /* HTJSGeneratorCodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD0201C1E99040027F340 /* HTJSGeneratorCodeTests.m */; };
+ E6AFD02C1C1E99040027F340 /* HTJSGeneratorCodeUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E6AFD02B1C1E99040027F340 /* HTJSGeneratorCodeUITests.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ E6AFD01D1C1E99040027F340 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = E6AFCFFB1C1E99040027F340 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E6AFD0021C1E99040027F340;
+ remoteInfo = HTJSGeneratorCode;
+ };
+ E6AFD0281C1E99040027F340 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = E6AFCFFB1C1E99040027F340 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = E6AFD0021C1E99040027F340;
+ remoteInfo = HTJSGeneratorCode;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 31D0B9D061014AAF95C2A624 /* HTTestModel1.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; path = HTTestModel1.h; sourceTree = ""; };
+ 4BF6840A3E42462796687B18 /* HTTestModel.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; path = HTTestModel.m; sourceTree = ""; };
+ 7988091A02B246179926A120 /* Info.plist */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 7DA58FFAAE624AC88D81D21B /* TestViewController.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = ""; };
+ 9477E58C648F4B9CBF695A18 /* TestViewController1.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; path = TestViewController1.h; sourceTree = ""; };
+ 9E124782988F4EA8A210945F /* TestViewController1.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; path = TestViewController1.m; sourceTree = ""; };
+ AF82B515094B4A86B9276616 /* HTTestModel.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; path = HTTestModel.h; sourceTree = ""; };
+ B96CF0CB8B164CA7B961B7C8 /* HTTestRequest.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; path = HTTestRequest.m; sourceTree = ""; };
+ C091F8560FBB4B8693F87C1F /* TestViewController.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = ""; };
+ C986780B42C44F2598E4E234 /* HTTestModel1.m */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.objc; path = HTTestModel1.m; sourceTree = ""; };
+ D06C33858A124437A6D331E1 /* HTTestRequest.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; path = HTTestRequest.h; sourceTree = ""; };
+ E63CC7911C2CEB1E0092683A /* HTTestModel1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTestModel1.h; path = Models/HTTestModel1.h; sourceTree = ""; };
+ E63CC7921C2CEB1E0092683A /* HTTestModel1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTestModel1.m; path = Models/HTTestModel1.m; sourceTree = ""; };
+ E63CC7941C2CEB6F0092683A /* TestViewController1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TestViewController1.h; path = Requests/TestViewController1.h; sourceTree = ""; };
+ E63CC7951C2CEB6F0092683A /* TestViewController1.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestViewController1.m; path = Requests/TestViewController1.m; sourceTree = ""; };
+ E6AFD0031C1E99040027F340 /* HTJSGeneratorCode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HTJSGeneratorCode.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ E6AFD0071C1E99040027F340 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
+ E6AFD0091C1E99040027F340 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; };
+ E6AFD00A1C1E99040027F340 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; };
+ E6AFD00C1C1E99040027F340 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; };
+ E6AFD00D1C1E99040027F340 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; };
+ E6AFD0101C1E99040027F340 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ E6AFD0121C1E99040027F340 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ E6AFD0151C1E99040027F340 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ E6AFD01C1C1E99040027F340 /* HTJSGeneratorCodeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HTJSGeneratorCodeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E6AFD0201C1E99040027F340 /* HTJSGeneratorCodeTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTJSGeneratorCodeTests.m; sourceTree = ""; };
+ E6AFD0271C1E99040027F340 /* HTJSGeneratorCodeUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HTJSGeneratorCodeUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ E6AFD02B1C1E99040027F340 /* HTJSGeneratorCodeUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HTJSGeneratorCodeUITests.m; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ E6AFD0001C1E99040027F340 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0191C1E99040027F340 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0241C1E99040027F340 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ BA604265FA2841C1B310F4EB /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ AF82B515094B4A86B9276616 /* HTTestModel.h */,
+ 31D0B9D061014AAF95C2A624 /* HTTestModel1.h */,
+ 4BF6840A3E42462796687B18 /* HTTestModel.m */,
+ C986780B42C44F2598E4E234 /* HTTestModel1.m */,
+ );
+ path = Models;
+ sourceTree = "";
+ };
+ E63CC7901C2CE8430092683A /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ E63CC7941C2CEB6F0092683A /* TestViewController1.h */,
+ E63CC7951C2CEB6F0092683A /* TestViewController1.m */,
+ E63CC7911C2CEB1E0092683A /* HTTestModel1.h */,
+ E63CC7921C2CEB1E0092683A /* HTTestModel1.m */,
+ );
+ name = Models;
+ sourceTree = "";
+ };
+ E6AFCFFA1C1E99040027F340 = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0051C1E99040027F340 /* HTJSGeneratorCode */,
+ E6AFD01F1C1E99040027F340 /* HTJSGeneratorCodeTests */,
+ E6AFD02A1C1E99040027F340 /* HTJSGeneratorCodeUITests */,
+ E6AFD0041C1E99040027F340 /* Products */,
+ );
+ sourceTree = "";
+ };
+ E6AFD0041C1E99040027F340 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0031C1E99040027F340 /* HTJSGeneratorCode.app */,
+ E6AFD01C1C1E99040027F340 /* HTJSGeneratorCodeTests.xctest */,
+ E6AFD0271C1E99040027F340 /* HTJSGeneratorCodeUITests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ E6AFD0051C1E99040027F340 /* HTJSGeneratorCode */ = {
+ isa = PBXGroup;
+ children = (
+ E6B03C021C27F57600450E9E /* Network */,
+ E6AFD0091C1E99040027F340 /* AppDelegate.h */,
+ E6AFD00A1C1E99040027F340 /* AppDelegate.m */,
+ E6AFD00C1C1E99040027F340 /* ViewController.h */,
+ E6AFD00D1C1E99040027F340 /* ViewController.m */,
+ E6AFD00F1C1E99040027F340 /* Main.storyboard */,
+ E6AFD0121C1E99040027F340 /* Assets.xcassets */,
+ E6AFD0141C1E99040027F340 /* LaunchScreen.storyboard */,
+ E6AFD0061C1E99040027F340 /* Supporting Files */,
+ BA604265FA2841C1B310F4EB /* Models */,
+ ED6D750F3C0B43478EDB8BE5 /* Requests */,
+ 7988091A02B246179926A120 /* Info.plist */,
+ );
+ path = HTJSGeneratorCode;
+ sourceTree = "";
+ };
+ E6AFD0061C1E99040027F340 /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0071C1E99040027F340 /* main.m */,
+ );
+ name = "Supporting Files";
+ sourceTree = "";
+ };
+ E6AFD01F1C1E99040027F340 /* HTJSGeneratorCodeTests */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD0201C1E99040027F340 /* HTJSGeneratorCodeTests.m */,
+ );
+ path = HTJSGeneratorCodeTests;
+ sourceTree = "";
+ };
+ E6AFD02A1C1E99040027F340 /* HTJSGeneratorCodeUITests */ = {
+ isa = PBXGroup;
+ children = (
+ E6AFD02B1C1E99040027F340 /* HTJSGeneratorCodeUITests.m */,
+ );
+ path = HTJSGeneratorCodeUITests;
+ sourceTree = "";
+ };
+ E6B03C021C27F57600450E9E /* Network */ = {
+ isa = PBXGroup;
+ children = (
+ E63CC7901C2CE8430092683A /* Models */,
+ );
+ name = Network;
+ sourceTree = "";
+ };
+ ED6D750F3C0B43478EDB8BE5 /* Requests */ = {
+ isa = PBXGroup;
+ children = (
+ D06C33858A124437A6D331E1 /* HTTestRequest.h */,
+ 7DA58FFAAE624AC88D81D21B /* TestViewController.h */,
+ 9477E58C648F4B9CBF695A18 /* TestViewController1.h */,
+ B96CF0CB8B164CA7B961B7C8 /* HTTestRequest.m */,
+ C091F8560FBB4B8693F87C1F /* TestViewController.m */,
+ 9E124782988F4EA8A210945F /* TestViewController1.m */,
+ );
+ path = Requests;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E6AFD0301C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCode" */;
+ buildPhases = (
+ E6AFCFFF1C1E99040027F340 /* Sources */,
+ E6AFD0001C1E99040027F340 /* Frameworks */,
+ E6AFD0011C1E99040027F340 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = HTJSGeneratorCode;
+ productName = HTJSGeneratorCode;
+ productReference = E6AFD0031C1E99040027F340 /* HTJSGeneratorCode.app */;
+ productType = "com.apple.product-type.application";
+ };
+ E6AFD01B1C1E99040027F340 /* HTJSGeneratorCodeTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E6AFD0331C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeTests" */;
+ buildPhases = (
+ E6AFD0181C1E99040027F340 /* Sources */,
+ E6AFD0191C1E99040027F340 /* Frameworks */,
+ E6AFD01A1C1E99040027F340 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E6AFD01E1C1E99040027F340 /* PBXTargetDependency */,
+ );
+ name = HTJSGeneratorCodeTests;
+ productName = HTJSGeneratorCodeTests;
+ productReference = E6AFD01C1C1E99040027F340 /* HTJSGeneratorCodeTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ E6AFD0261C1E99040027F340 /* HTJSGeneratorCodeUITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = E6AFD0361C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeUITests" */;
+ buildPhases = (
+ E6AFD0231C1E99040027F340 /* Sources */,
+ E6AFD0241C1E99040027F340 /* Frameworks */,
+ E6AFD0251C1E99040027F340 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ E6AFD0291C1E99040027F340 /* PBXTargetDependency */,
+ );
+ name = HTJSGeneratorCodeUITests;
+ productName = HTJSGeneratorCodeUITests;
+ productReference = E6AFD0271C1E99040027F340 /* HTJSGeneratorCodeUITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ E6AFCFFB1C1E99040027F340 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 700;
+ ORGANIZATIONNAME = Netease;
+ TargetAttributes = {
+ E6AFD0021C1E99040027F340 = {
+ CreatedOnToolsVersion = 7.0;
+ DevelopmentTeam = 2D4LEJ8Z2D;
+ };
+ E6AFD01B1C1E99040027F340 = {
+ CreatedOnToolsVersion = 7.0;
+ DevelopmentTeam = 2D4LEJ8Z2D;
+ TestTargetID = E6AFD0021C1E99040027F340;
+ };
+ E6AFD0261C1E99040027F340 = {
+ CreatedOnToolsVersion = 7.0;
+ DevelopmentTeam = 2D4LEJ8Z2D;
+ TestTargetID = E6AFD0021C1E99040027F340;
+ };
+ };
+ };
+ buildConfigurationList = E6AFCFFE1C1E99040027F340 /* Build configuration list for PBXProject "HTJSGeneratorCode" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = E6AFCFFA1C1E99040027F340;
+ productRefGroup = E6AFD0041C1E99040027F340 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */,
+ E6AFD01B1C1E99040027F340 /* HTJSGeneratorCodeTests */,
+ E6AFD0261C1E99040027F340 /* HTJSGeneratorCodeUITests */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ E6AFD0011C1E99040027F340 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD0161C1E99040027F340 /* LaunchScreen.storyboard in Resources */,
+ E6AFD0131C1E99040027F340 /* Assets.xcassets in Resources */,
+ E6AFD0111C1E99040027F340 /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD01A1C1E99040027F340 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0251C1E99040027F340 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ E6AFCFFF1C1E99040027F340 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E63CC7961C2CEB6F0092683A /* TestViewController1.m in Sources */,
+ E6AFD00E1C1E99040027F340 /* ViewController.m in Sources */,
+ E6AFD00B1C1E99040027F340 /* AppDelegate.m in Sources */,
+ E6AFD0081C1E99040027F340 /* main.m in Sources */,
+ E63CC7931C2CEB1E0092683A /* HTTestModel1.m in Sources */,
+ D4224B2B6F6443B5BAA60C2B /* HTTestModel.m in Sources */,
+ 7068F19789004D5D81E338AD /* HTTestModel1.m in Sources */,
+ 70459B39CB83470FAEC65357 /* HTTestRequest.m in Sources */,
+ 1633717AA6294BD4B13F3ED7 /* TestViewController.m in Sources */,
+ 7134CF06962A4FE08E75D36B /* TestViewController1.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0181C1E99040027F340 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD0211C1E99040027F340 /* HTJSGeneratorCodeTests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ E6AFD0231C1E99040027F340 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ E6AFD02C1C1E99040027F340 /* HTJSGeneratorCodeUITests.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ E6AFD01E1C1E99040027F340 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */;
+ targetProxy = E6AFD01D1C1E99040027F340 /* PBXContainerItemProxy */;
+ };
+ E6AFD0291C1E99040027F340 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = E6AFD0021C1E99040027F340 /* HTJSGeneratorCode */;
+ targetProxy = E6AFD0281C1E99040027F340 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ E6AFD00F1C1E99040027F340 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ E6AFD0101C1E99040027F340 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ E6AFD0141C1E99040027F340 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ E6AFD0151C1E99040027F340 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ E6AFD02E1C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ E6AFD02F1C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ E6AFD0311C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = HTJSGeneratorCode/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCode;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ E6AFD0321C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ INFOPLIST_FILE = HTJSGeneratorCode/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCode;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ E6AFD0341C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ INFOPLIST_FILE = HTJSGeneratorCodeTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HTJSGeneratorCode.app/HTJSGeneratorCode";
+ };
+ name = Debug;
+ };
+ E6AFD0351C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ BUNDLE_LOADER = "$(TEST_HOST)";
+ INFOPLIST_FILE = HTJSGeneratorCodeTests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HTJSGeneratorCode.app/HTJSGeneratorCode";
+ };
+ name = Release;
+ };
+ E6AFD0371C1E99040027F340 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = HTJSGeneratorCodeUITests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_TARGET_NAME = HTJSGeneratorCode;
+ USES_XCTRUNNER = YES;
+ };
+ name = Debug;
+ };
+ E6AFD0381C1E99040027F340 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INFOPLIST_FILE = HTJSGeneratorCodeUITests/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ PRODUCT_BUNDLE_IDENTIFIER = Netease.HTJSGeneratorCodeUITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TEST_TARGET_NAME = HTJSGeneratorCode;
+ USES_XCTRUNNER = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ E6AFCFFE1C1E99040027F340 /* Build configuration list for PBXProject "HTJSGeneratorCode" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD02E1C1E99040027F340 /* Debug */,
+ E6AFD02F1C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E6AFD0301C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCode" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD0311C1E99040027F340 /* Debug */,
+ E6AFD0321C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E6AFD0331C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD0341C1E99040027F340 /* Debug */,
+ E6AFD0351C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ E6AFD0361C1E99040027F340 /* Build configuration list for PBXNativeTarget "HTJSGeneratorCodeUITests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ E6AFD0371C1E99040027F340 /* Debug */,
+ E6AFD0381C1E99040027F340 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = E6AFCFFB1C1E99040027F340 /* Project object */;
+}
diff --git a/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..74bb09f
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.xcworkspace/xcuserdata/netease.xcuserdatad/UserInterfaceState.xcuserstate b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.xcworkspace/xcuserdata/netease.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..129806a
Binary files /dev/null and b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/project.xcworkspace/xcuserdata/netease.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/test/HTTestResources/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/HTJSGeneratorCode.xcscheme b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/HTJSGeneratorCode.xcscheme
new file mode 100644
index 0000000..4aba1fa
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/HTJSGeneratorCode.xcscheme
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/xcschememanagement.plist b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..7062540
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode.xcodeproj/xcuserdata/netease.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ SchemeUserState
+
+ HTJSGeneratorCode.xcscheme
+
+ orderHint
+ 0
+
+
+ SuppressBuildableAutocreation
+
+ E6AFD0021C1E99040027F340
+
+ primary
+
+
+ E6AFD01B1C1E99040027F340
+
+ primary
+
+
+ E6AFD0261C1E99040027F340
+
+ primary
+
+
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/AppDelegate.h b/test/HTTestResources/HTJSGeneratorCode/AppDelegate.h
new file mode 100644
index 0000000..45df665
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/AppDelegate.h
@@ -0,0 +1,17 @@
+//
+// AppDelegate.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface AppDelegate : UIResponder
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/AppDelegate.m b/test/HTTestResources/HTJSGeneratorCode/AppDelegate.m
new file mode 100644
index 0000000..184e6d2
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/AppDelegate.m
@@ -0,0 +1,45 @@
+//
+// AppDelegate.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "AppDelegate.h"
+
+@interface AppDelegate ()
+
+@end
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // Override point for customization after application launch.
+ return YES;
+}
+
+- (void)applicationWillResignActive:(UIApplication *)application {
+ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
+ // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
+ // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
+}
+
+- (void)applicationDidBecomeActive:(UIApplication *)application {
+ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
+}
+
+- (void)applicationWillTerminate:(UIApplication *)application {
+ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
+}
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Assets.xcassets/AppIcon.appiconset/Contents.json b/test/HTTestResources/HTJSGeneratorCode/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..118c98f
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,38 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "60x60",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
\ No newline at end of file
diff --git a/test/HTTestResources/HTJSGeneratorCode/Base.lproj/LaunchScreen.storyboard b/test/HTTestResources/HTJSGeneratorCode/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..2e721e1
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/Base.lproj/Main.storyboard b/test/HTTestResources/HTJSGeneratorCode/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..f56d2f3
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Base.lproj/Main.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/Controllers/Test/TestViewController.h b/test/HTTestResources/HTJSGeneratorCode/Controllers/Test/TestViewController.h
new file mode 100644
index 0000000..c2087e7
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Controllers/Test/TestViewController.h
@@ -0,0 +1,13 @@
+//
+// TestViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/21.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface TestViewController : UIViewController
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Controllers/Test/TestViewController.m b/test/HTTestResources/HTJSGeneratorCode/Controllers/Test/TestViewController.m
new file mode 100644
index 0000000..3e20ad5
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Controllers/Test/TestViewController.m
@@ -0,0 +1,13 @@
+//
+// TestViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/21.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "TestViewController.h"
+
+@implementation TestViewController
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Info.plist b/test/HTTestResources/HTJSGeneratorCode/Info.plist
new file mode 100644
index 0000000..6905cc6
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Info.plist
@@ -0,0 +1,40 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel.h b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel.h
new file mode 100644
index 0000000..fa8d336
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel.h
@@ -0,0 +1,13 @@
+//
+// HTTestModel.h
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTTestModel : NSObject
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel.m b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel.m
new file mode 100644
index 0000000..f83c855
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel.m
@@ -0,0 +1,13 @@
+//
+// HTTestModel.m
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "HTTestModel.h"
+
+@implementation HTTestModel
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel1.h b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel1.h
new file mode 100644
index 0000000..fa8d336
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel1.h
@@ -0,0 +1,13 @@
+//
+// HTTestModel.h
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTTestModel : NSObject
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel1.m b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel1.m
new file mode 100644
index 0000000..f83c855
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Models/HTTestModel1.m
@@ -0,0 +1,13 @@
+//
+// HTTestModel.m
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "HTTestModel.h"
+
+@implementation HTTestModel
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Requests/HTTestRequest.h b/test/HTTestResources/HTJSGeneratorCode/Requests/HTTestRequest.h
new file mode 100644
index 0000000..6e5ce82
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Requests/HTTestRequest.h
@@ -0,0 +1,13 @@
+//
+// HTTestRequest.h
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTTestRequest : NSObject
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Requests/HTTestRequest.m b/test/HTTestResources/HTJSGeneratorCode/Requests/HTTestRequest.m
new file mode 100644
index 0000000..7b511ca
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Requests/HTTestRequest.m
@@ -0,0 +1,13 @@
+//
+// HTTestRequest.m
+// HTSingleCodeGenerator
+//
+// Created by Wangliping on 15/12/11.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "HTTestRequest.h"
+
+@implementation HTTestRequest
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController.h b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController.h
new file mode 100644
index 0000000..52d6222
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController.h
@@ -0,0 +1,13 @@
+//
+// TestViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/17.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface TestViewController : UIViewController
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController.m b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController.m
new file mode 100644
index 0000000..5979945
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController.m
@@ -0,0 +1,37 @@
+//
+// TestViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/17.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "TestViewController.h"
+
+@interface TestViewController ()
+
+@end
+
+@implementation TestViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ // Get the new view controller using [segue destinationViewController].
+ // Pass the selected object to the new view controller.
+}
+*/
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController1.h b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController1.h
new file mode 100644
index 0000000..52d6222
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController1.h
@@ -0,0 +1,13 @@
+//
+// TestViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/17.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface TestViewController : UIViewController
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController1.m b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController1.m
new file mode 100644
index 0000000..5979945
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/Requests/TestViewController1.m
@@ -0,0 +1,37 @@
+//
+// TestViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/17.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "TestViewController.h"
+
+@interface TestViewController ()
+
+@end
+
+@implementation TestViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view.
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+ // Get the new view controller using [segue destinationViewController].
+ // Pass the selected object to the new view controller.
+}
+*/
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/TestXib.xib b/test/HTTestResources/HTJSGeneratorCode/TestXib.xib
new file mode 100644
index 0000000..f897fa7
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/TestXib.xib
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/ViewController.h b/test/HTTestResources/HTJSGeneratorCode/ViewController.h
new file mode 100644
index 0000000..c4f93a3
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/ViewController.h
@@ -0,0 +1,15 @@
+//
+// ViewController.h
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface ViewController : UIViewController
+
+
+@end
+
diff --git a/test/HTTestResources/HTJSGeneratorCode/ViewController.m b/test/HTTestResources/HTJSGeneratorCode/ViewController.m
new file mode 100644
index 0000000..0bbe8c6
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/ViewController.m
@@ -0,0 +1,32 @@
+//
+// ViewController.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import "ViewController.h"
+#import "HTTestModel.h"
+#import "HTTestRequest.h"
+
+@interface ViewController ()
+
+@end
+
+@implementation ViewController
+
+- (void)viewDidLoad {
+ [super viewDidLoad];
+ // Do any additional setup after loading the view, typically from a nib.
+
+ HTTestModel *model = [[HTTestModel alloc] init];
+ NSLog(@"%@", model);
+}
+
+- (void)didReceiveMemoryWarning {
+ [super didReceiveMemoryWarning];
+ // Dispose of any resources that can be recreated.
+}
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCode/main.m b/test/HTTestResources/HTJSGeneratorCode/main.m
new file mode 100644
index 0000000..20ae3c0
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCode/main.m
@@ -0,0 +1,16 @@
+//
+// main.m
+// HTJSGeneratorCode
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/test/HTTestResources/HTJSGeneratorCodeTests/HTJSGeneratorCodeTests.m b/test/HTTestResources/HTJSGeneratorCodeTests/HTJSGeneratorCodeTests.m
new file mode 100644
index 0000000..e0a334c
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCodeTests/HTJSGeneratorCodeTests.m
@@ -0,0 +1,39 @@
+//
+// HTJSGeneratorCodeTests.m
+// HTJSGeneratorCodeTests
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTJSGeneratorCodeTests : XCTestCase
+
+@end
+
+@implementation HTJSGeneratorCodeTests
+
+- (void)setUp {
+ [super setUp];
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+}
+
+- (void)tearDown {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ [super tearDown];
+}
+
+- (void)testExample {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+}
+
+- (void)testPerformanceExample {
+ // This is an example of a performance test case.
+ [self measureBlock:^{
+ // Put the code you want to measure the time of here.
+ }];
+}
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCodeTests/Info.plist b/test/HTTestResources/HTJSGeneratorCodeTests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCodeTests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/test/HTTestResources/HTJSGeneratorCodeUITests/HTJSGeneratorCodeUITests.m b/test/HTTestResources/HTJSGeneratorCodeUITests/HTJSGeneratorCodeUITests.m
new file mode 100644
index 0000000..4a89e3c
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCodeUITests/HTJSGeneratorCodeUITests.m
@@ -0,0 +1,40 @@
+//
+// HTJSGeneratorCodeUITests.m
+// HTJSGeneratorCodeUITests
+//
+// Created by Wangliping on 15/12/14.
+// Copyright © 2015年 Netease. All rights reserved.
+//
+
+#import
+
+@interface HTJSGeneratorCodeUITests : XCTestCase
+
+@end
+
+@implementation HTJSGeneratorCodeUITests
+
+- (void)setUp {
+ [super setUp];
+
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+
+ // In UI tests it is usually best to stop immediately when a failure occurs.
+ self.continueAfterFailure = NO;
+ // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
+ [[[XCUIApplication alloc] init] launch];
+
+ // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
+}
+
+- (void)tearDown {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ [super tearDown];
+}
+
+- (void)testExample {
+ // Use recording to get started writing UI tests.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+}
+
+@end
diff --git a/test/HTTestResources/HTJSGeneratorCodeUITests/Info.plist b/test/HTTestResources/HTJSGeneratorCodeUITests/Info.plist
new file mode 100644
index 0000000..ba72822
--- /dev/null
+++ b/test/HTTestResources/HTJSGeneratorCodeUITests/Info.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ BNDL
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1
+
+
diff --git a/test/HTTestResources/UpdateModels.js b/test/HTTestResources/UpdateModels.js
new file mode 100644
index 0000000..5473bc8
--- /dev/null
+++ b/test/HTTestResources/UpdateModels.js
@@ -0,0 +1,224 @@
+// API is a bit wonky right now
+var project = require('../../lib/pbxProject.js'),
+ fs = require('fs'),
+ util = require('util'),
+ f = util.format;
+
+// TODO:参数缺少时, 需要给予警告和提示. 参数的处理需要更灵活
+// node UpdateModels.js projectName groupParentPath folderParentPath
+var projectName = process.argv[2];
+var groupParentPath = process.argv[3];
+var folderParentPath = process.argv[4];
+var projectPath = projectName + '.xcodeproj/project.pbxproj';
+//var projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj';
+
+// Get Project.
+var myProj = project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+// For release version, it is OK to use parse function.
+myProj.parseSync();
+updateCode();
+
+function updateCode () {
+ if (undefined == projectName || undefined == groupParentPath || undefined == folderParentPath || undefined == myProj) {
+ console.log("Please correct parameters, the command is like \r\n node UpdateModels.js projectName groupParentPath folderParentPath, please specify your own projectName, parent group path and pareng folder path");
+ return;
+ }
+
+ // TODO: 现在暂时不支持更换路径,即之前要删除的路径和后面要添加的路径不相同的Case.
+ console.log("Begin to update project " + projectName + ", Models and Requests will be added under group " + groupParentPath);
+
+ // 固定添加Models和Requests, 不需要参数配置
+ var autoGroupNames = ["Models", "Requests"];
+ autoGroupNames.forEach(function (groupName){
+ console.log("Begin to check folder " + groupName);
+
+ // 获取parent Group Key 和 要处理的Group Key
+ var absoluteGroupPath = groupParentPath + "/" + groupName;
+ var parentGroupKey = findGroupByAbsolutePath(groupParentPath);
+ var groupKey = findGroupByAbsolutePath(absoluteGroupPath);
+ if (undefined == groupKey) {
+ // group不存在, 新建Group. GroupName与Path相同.
+ console.log("Group " + groupName + " does not exist, create group " + groupName + " under group " + groupParentPath);
+ groupKey = myProj.pbxCreateGroup(groupName, groupName);
+
+ // Add new created groups into parent group.
+ // 将Group加到parent Group中
+ myProj.addToPbxGroup(groupKey, parentGroupKey, {});
+ } else {
+ // group存在, 删除其中的所有文件.
+ console.log("Group " + groupName + " already exists, remove all files in this group first.");
+ removeFilesInGroup(groupName);
+ }
+
+ // 获取目录下的所有头文件和可执行文件
+ var folderPath = folderParentPath + "/" + groupName;
+ var headerFiles = headerFilesInFilePath(folderPath);
+ var sourceFiles = sourceFilesInFilePath(folderPath);
+
+ // 将头文件添加到group中.
+ headerFiles.forEach(function(headerFile) {
+ myProj.addHeaderFile(headerFile, {}, groupKey);
+ });
+
+ // 将源文件添加到group中
+ sourceFiles.forEach(function(sourceFile) {
+ myProj.addSourceFile(sourceFile, {}, groupKey);
+ });
+
+ console.log("Add Source Files and Header Files from Path " + folderPath + " to group " + absoluteGroupPath + " successfully");
+ });
+
+
+ // 将内容写回到工程文件中.
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated successfully !");
+}
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath(fullPath) {
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0 && undefined != groupKey) {
+ root = pathList[0];
+ groupKey = myProj.findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ // TODO: 下面的代码只用校验是否能够取到正确的Group.
+ if (undefined != groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ }
+
+ return groupKey;
+}
+
+// removeFilesInGroup已经OK.
+// Done. 根据FileRef的UUID从Project的File Reference Section中删除.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ // TODO: delete buildFile没有从这个字典中真正删除这个文件.
+ //delete buildFile;
+ delete myProj.pbxBuildFileSection()[uuid];
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return buildFileUUID;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 所以这个方法不正确.
+function removeFromPbxSourcesBuildPhaseWithKey (fileRef) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup(groupName) {
+ var groupKey = myProj.findPBXGroupKey({ path: groupName});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+ }
+}
+
+// 找到所有的头文件.
+function headerFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("h" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+// 找到所有的源文件
+// TODO: 性能可以改进, 可以一次性找出头文件和源文件,不需要每次都遍历一遍.
+function sourceFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
\ No newline at end of file
diff --git a/test/HTTestResources/UpdateNEIProject.js b/test/HTTestResources/UpdateNEIProject.js
new file mode 100644
index 0000000..164747e
--- /dev/null
+++ b/test/HTTestResources/UpdateNEIProject.js
@@ -0,0 +1,451 @@
+// 这个JS直接引用xcode, 所有额外添加的东西都加在这个JS文件中.
+var xcode = require('xcode'),
+ fs = require('fs'),
+ util = require('util'),
+ COMMENT_KEY = /_comment$/,
+ f = util.format;
+
+// TODO:参数缺少时, 需要给予警告和提示. 参数的处理需要更灵活
+// node UpdateModels.js projectName groupParentPath folderParentPath
+var projectName = process.argv[2];
+var groupParentPath = process.argv[3];
+var folderParentPath = process.argv[4];
+var projectPath = projectName + '.xcodeproj/project.pbxproj';
+//var projectPath = 'HTJSGeneratorCode.xcodeproj/project.pbxproj';
+
+// Get Project.
+var myProj = xcode.project(projectPath);
+
+// Debug with parseSync as it is impossible to debug async parsing.
+// For release version, it is OK to use parse function.
+myProj.parseSync();
+updateCode();
+
+function updateCode () {
+ if (undefined == projectName || undefined == groupParentPath || undefined == folderParentPath || undefined == myProj) {
+ console.log("Please correct parameters, the command is like \r\n node UpdateModels.js projectName groupParentPath folderParentPath, please specify your own projectName, parent group path and pareng folder path");
+ return;
+ }
+
+ // TODO: 现在暂时不支持更换路径,即之前要删除的路径和后面要添加的路径不相同的Case.
+ console.log("Begin to update project " + projectName + ", Models and Requests will be added under group " + groupParentPath);
+
+ // 固定添加Models和Requests, 不需要参数配置
+ var autoGroupNames = ["Models", "Requests"];
+ autoGroupNames.forEach(function (groupName){
+ console.log("Begin to check folder " + groupName);
+
+ // 获取parent Group Key 和 要处理的Group Key
+ var absoluteGroupPath = groupParentPath + "/" + groupName;
+ var parentGroupKey = findGroupByAbsolutePath(groupParentPath);
+ var groupKey = findGroupByAbsolutePath(absoluteGroupPath);
+ if (undefined == groupKey) {
+ // group不存在, 新建Group. GroupName与Path相同.
+ console.log("Group " + groupName + " does not exist, create group " + groupName + " under group " + groupParentPath);
+ groupKey = myProj.pbxCreateGroup(groupName, groupName);
+
+ // Add new created groups into parent group.
+ // 将Group加到parent Group中
+ myProj.addToPbxGroup(groupKey, parentGroupKey, {});
+ } else {
+ // group存在, 删除其中的所有文件.
+ console.log("Group " + groupName + " already exists, remove all files in this group first.");
+ removeFilesInGroup(groupName);
+ }
+
+ // 获取目录下的所有头文件和可执行文件
+ var folderPath = folderParentPath + "/" + groupName;
+ var headerFiles = headerFilesInFilePath(folderPath);
+ var sourceFiles = sourceFilesInFilePath(folderPath);
+
+ // 将头文件添加到group中.
+ headerFiles.forEach(function(headerFile) {
+ myProj.addHeaderFile(headerFile, {}, groupKey);
+ });
+
+ // 将源文件添加到group中
+ sourceFiles.forEach(function(sourceFile) {
+ myProj.addSourceFile(sourceFile, {}, groupKey);
+ });
+
+ console.log("Add Source Files and Header Files from Path " + folderPath + " to group " + absoluteGroupPath + " successfully");
+ });
+
+
+ // 将内容写回到工程文件中.
+ fs.writeFileSync(projectPath, myProj.writeSync());
+ console.log('Project ' + projectPath + " is updated successfully !");
+}
+
+// 根据完整路径获取到对应的Group.
+function findGroupByAbsolutePath(fullPath) {
+ var pathList = fullPath.split('/');
+ if (pathList.length == 0) {
+ return;
+ }
+
+ var root = pathList[0];
+ var groupKey = myProj.findPBXGroupKey({ path: root});
+ pathList.splice(0, 1);
+ while (pathList.length > 0 && undefined != groupKey) {
+ root = pathList[0];
+ groupKey = findPBXGroupKeyInParentGroup({path: root}, groupKey);
+ pathList.splice(0, 1);
+ }
+
+ // TODO: 下面的代码只用校验是否能够取到正确的Group.
+ if (undefined != groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ }
+
+ return groupKey;
+}
+
+// removeFilesInGroup已经OK.
+// Done. 根据FileRef的UUID从Project的File Reference Section中删除.
+function removeFromPbxFileReferenceSectionWithKey (fileRef) {
+ for (i in myProj.pbxFileReferenceSection()) {
+ if (i == fileRef) {
+ delete myProj.pbxFileReferenceSection()[i];
+ break;
+ }
+ }
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxFileReferenceSection()[commentKey] != undefined) {
+ delete myProj.pbxFileReferenceSection()[commentKey];
+ }
+}
+
+// TODO: 这里必须返回BuildFileUUID. 否则的话,无法从BuildPhase中删除.
+function removeFromPbxBuildFileSectionWithKey (fileRef) {
+ var uuid;
+ var buildFileUUID;
+ for (uuid in myProj.pbxBuildFileSection()) {
+ var buildFile = myProj.pbxBuildFileSection()[uuid];
+ if (buildFile.fileRef == fileRef) {
+ // TODO: delete buildFile没有从这个字典中真正删除这个文件.
+ //delete buildFile;
+ delete myProj.pbxBuildFileSection()[uuid];
+ buildFileUUID = uuid;
+ break;
+ }
+ }
+
+ var commentKey = f("%s_comment", fileRef);
+ if (myProj.pbxBuildFileSection()[commentKey] != undefined) {
+ delete myProj.pbxBuildFileSection()[commentKey];
+ }
+
+ return buildFileUUID;
+}
+
+// Note: 这里只取了firstTarget, 理论上所有的Target都需要获取. 这里所有的参数都是fileRef的uuid.
+// Note: File Reference里面的uuid和BuildPhase中的uuid不相同. 所以这个方法不正确.
+function removeFromPbxSourcesBuildPhaseWithKey (fileRef) {
+ // var target = myProj.getFirstTarget();
+ // TODO: 用FirstTarget会抛出异常,原因未知.
+ var target = undefined;
+ var sources = myProj.pbxSourcesBuildPhaseObj(target), i;
+ for (i in sources.files) {
+ if (sources.files[i].value == fileRef) {
+ sources.files.splice(i, 1);
+ break;
+ }
+ }
+}
+
+function removeFilesInGroup(groupName) {
+ var groupKey = myProj.findPBXGroupKey({ path: groupName});
+ var group = myProj.getPBXGroupByKey(groupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ var uuid = file.value;
+ if (uuid != undefined) {
+ removeFromPbxFileReferenceSectionWithKey(uuid); // PBXFileReference
+ }
+
+ // 从当前Group中删除. TODO: 这里删除了后不可以继续遍历了.
+ //groupChildren.splice(i, 1);
+ // TODO: 如果是子Group, 还要继续删除. 暂时不考虑文件夹.
+ //myProj.removeFromPbxGroup(file, group); // PBXGroup
+
+ // 从Build File Ref中删除
+ var buildFileUUID = removeFromPbxBuildFileSectionWithKey(uuid);
+
+ // 从Build Phase中删除
+ if (undefined != buildFileUUID) {
+ removeFromPbxSourcesBuildPhaseWithKey(buildFileUUID);
+ }
+ }
+
+ // 删除groupChildren.
+ groupChildren.splice(0, groupChildren.length);
+ }
+}
+
+// 找到所有的头文件.
+function headerFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("h" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+// 找到所有的源文件
+// TODO: 性能可以改进, 可以一次性找出头文件和源文件,不需要每次都遍历一遍.
+function sourceFilesInFilePath(root) {
+ var res = [];
+ var files = fs.readdirSync(root);
+ files.forEach(function(file) {
+ var extensionFileName = GetExtensionFileName(file);
+ if ("m" == extensionFileName) {
+ res.push(file);
+ }
+ });
+
+ return res;
+}
+
+function GetExtensionFileName(pathfilename)
+{
+ var reg = /(\\+)/g;
+ var pfn = pathfilename.replace(reg, "#");
+ var arrpfn = pfn.split("#");
+ var fn = arrpfn[arrpfn.length - 1];
+ var arrfn = fn.split(".");
+ return arrfn[arrfn.length - 1];
+}
+
+
+
+
+
+
+
+
+
+
+
+// Projects Extension
+// 这些最好添加到pbxProject.js中, 仅供当前流程使用.
+function removePbxGroupByKey(groupKey) {
+ var section = myProj.hash.project.objects['PBXGroup'],
+ key, itemKey;
+
+ for (key in section) {
+ // only look for comments
+ if (!COMMENT_KEY.test(key)) continue;
+
+ if (key == groupKey) {
+ itemKey = key.split(COMMENT_KEY)[0];
+ delete section[itemKey];
+ }
+ }
+}
+
+function removeGroupFromPbxGroup(removeGroupKey, groupKey) {
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var removeGroup = myProj.getPBXGroupByKey(removeGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ if(removeGroupKey == groupChildren[i].value && removeGroup != undefined) {
+ groupChildren.splice(i, 1);
+
+ clearGroup(removeGroup);
+ break;
+ }
+ }
+ }
+
+ delete removeGroup;
+}
+
+function clearGroup(group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+}
+
+function removeGroupByKey(key, parentGroupKey) {
+ var group = getPBXGroupByKey(key, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+// Remove a group and all files in this group.
+function removeGroup(groupPath, parentGroupKey) {
+ var group = getPBXGroupByPath(groupPath, parentGroupKey);
+ if (group) {
+ var groupChildren = group.children, i;
+ for (i in groupChildren) {
+ file = groupChildren[i];
+ if (file.fileRef != undefined) {
+ myProj.removeFromPbxFileReferenceSection(file); // PBXFileReference
+ }
+
+ // TODO: 如果是子Group, 还要继续删除.
+ myProj.removeFromPbxGroup(file, group); // PBXGroup
+ }
+ }
+}
+
+
+function getPBXGroupByPath(path, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? myProj.hash.project.objects['PBXGroup'] : myProj.getPBXGroupByKey(parentGroupKey);
+ for (var key in groups) {
+ var group = groups[key];
+ if (group.path === path) {
+ return group;
+ }
+ }
+
+ return undefined;
+};
+
+function getPBXGroupByKey(key, parentGroupKey) {
+ var groups = (undefined == parentGroupKey) ? myProj.hash.project.objects['PBXGroup'] : myProj.getPBXGroupByKey(parentGroupKey);
+ var group = groups[key];
+ return group;
+};
+
+function findPBXGroupInParent(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return myProj.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = myProj.findPBXGroupKey(parentCriteria);
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = childGroup;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = childGroup;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+function findPBXGroupKeyInParent(criteria, parentCriteria) {
+ if (undefined == parentCriteria) {
+ return myProj.findPBXGroupKey(criteria);
+ }
+
+ var target;
+ var groupKey = myProj.findPBXGroupKey(parentCriteria);
+ var group = myProj.getPBXGroupByKey(groupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}
+
+
+function findPBXGroupKeyInParentGroup(criteria, parentGroupKey) {
+ var target;
+ var group = getPBXGroupByKey(parentGroupKey);
+ var groupChildren = group.children, i;
+ for(i in groupChildren) {
+ var child = groupChildren[i];
+ var childGroup = myProj.getPBXGroupByKey(child.value);
+ if (undefined == childGroup) {
+ // 这不是一个对应的Group.
+ continue;
+ }
+
+ if (criteria && criteria.path && criteria.name) {
+ if (criteria.path === childGroup.path && criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.path) {
+ if (criteria.path === childGroup.path) {
+ target = child.value;
+ break
+ }
+ }
+ else if (criteria && criteria.name) {
+ if (criteria.name === childGroup.name) {
+ target = child.value;
+ break
+ }
+ }
+ }
+
+ return target;
+}