638 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
		
		
			
		
	
	
			638 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * Copyright (C)2005-2019 Haxe Foundation
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Permission is hereby granted, free of charge, to any person obtaining a
							 | 
						||
| 
								 | 
							
								 * copy of this software and associated documentation files (the "Software"),
							 | 
						||
| 
								 | 
							
								 * to deal in the Software without restriction, including without limitation
							 | 
						||
| 
								 | 
							
								 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
							 | 
						||
| 
								 | 
							
								 * and/or sell copies of the Software, and to permit persons to whom the
							 | 
						||
| 
								 | 
							
								 * Software is furnished to do so, subject to the following conditions:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * The above copyright notice and this permission notice shall be included in
							 | 
						||
| 
								 | 
							
								 * all copies or substantial portions of the Software.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						||
| 
								 | 
							
								 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						||
| 
								 | 
							
								 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
							 | 
						||
| 
								 | 
							
								 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
							 | 
						||
| 
								 | 
							
								 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
							 | 
						||
| 
								 | 
							
								 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
							 | 
						||
| 
								 | 
							
								 * DEALINGS IN THE SOFTWARE.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								package haxe.rtti;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import haxe.rtti.CType;
							 | 
						||
| 
								 | 
							
								import haxe.xml.Access;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
									XmlParser processes the runtime type information (RTTI) which
							 | 
						||
| 
								 | 
							
									is stored as a XML string in a static field `__rtti`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									@see <https://haxe.org/manual/cr-rtti.html>
							 | 
						||
| 
								 | 
							
								**/
							 | 
						||
| 
								 | 
							
								class XmlParser {
							 | 
						||
| 
								 | 
							
									public var root:TypeRoot;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									var curplatform:String;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function new() {
							 | 
						||
| 
								 | 
							
										root = new Array();
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function sort(?l:TypeRoot) {
							 | 
						||
| 
								 | 
							
										if (l == null)
							 | 
						||
| 
								 | 
							
											l = root;
							 | 
						||
| 
								 | 
							
										l.sort(function(e1, e2) {
							 | 
						||
| 
								 | 
							
											var n1 = switch e1 {
							 | 
						||
| 
								 | 
							
												case TPackage(p, _, _): " " + p;
							 | 
						||
| 
								 | 
							
												default: TypeApi.typeInfos(e1).path;
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											var n2 = switch e2 {
							 | 
						||
| 
								 | 
							
												case TPackage(p, _, _): " " + p;
							 | 
						||
| 
								 | 
							
												default: TypeApi.typeInfos(e2).path;
							 | 
						||
| 
								 | 
							
											};
							 | 
						||
| 
								 | 
							
											if (n1 > n2)
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											return -1;
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
										for (x in l)
							 | 
						||
| 
								 | 
							
											switch (x) {
							 | 
						||
| 
								 | 
							
												case TPackage(_, _, l):
							 | 
						||
| 
								 | 
							
													sort(l);
							 | 
						||
| 
								 | 
							
												case TClassdecl(c):
							 | 
						||
| 
								 | 
							
													sortFields(c.fields);
							 | 
						||
| 
								 | 
							
													sortFields(c.statics);
							 | 
						||
| 
								 | 
							
												case TEnumdecl(_):
							 | 
						||
| 
								 | 
							
												case TAbstractdecl(_):
							 | 
						||
| 
								 | 
							
												case TTypedecl(_):
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function sortFields(a:Array<ClassField>) {
							 | 
						||
| 
								 | 
							
										a.sort(function(f1:ClassField, f2:ClassField) {
							 | 
						||
| 
								 | 
							
											var v1 = TypeApi.isVar(f1.type);
							 | 
						||
| 
								 | 
							
											var v2 = TypeApi.isVar(f2.type);
							 | 
						||
| 
								 | 
							
											if (v1 && !v2)
							 | 
						||
| 
								 | 
							
												return -1;
							 | 
						||
| 
								 | 
							
											if (v2 && !v1)
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											if (f1.name == "new")
							 | 
						||
| 
								 | 
							
												return -1;
							 | 
						||
| 
								 | 
							
											if (f2.name == "new")
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											if (f1.name > f2.name)
							 | 
						||
| 
								 | 
							
												return 1;
							 | 
						||
| 
								 | 
							
											return -1;
							 | 
						||
| 
								 | 
							
										});
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function process(x:Xml, platform:String) {
							 | 
						||
| 
								 | 
							
										curplatform = platform;
							 | 
						||
| 
								 | 
							
										xroot(new Access(x));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// merge inline and not inline
							 | 
						||
| 
								 | 
							
									function mergeRights(f1:ClassField, f2:ClassField) {
							 | 
						||
| 
								 | 
							
										if (f1.get == RInline && f1.set == RNo && f2.get == RNormal && f2.set == RMethod) {
							 | 
						||
| 
								 | 
							
											f1.get = RNormal;
							 | 
						||
| 
								 | 
							
											f1.set = RMethod;
							 | 
						||
| 
								 | 
							
											return true;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return Type.enumEq(f1.get, f2.get) && Type.enumEq(f1.set, f2.set);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mergeDoc(f1:ClassField, f2:ClassField) {
							 | 
						||
| 
								 | 
							
										if (f1.doc == null)
							 | 
						||
| 
								 | 
							
											f1.doc = f2.doc;
							 | 
						||
| 
								 | 
							
										else if (f2.doc == null)
							 | 
						||
| 
								 | 
							
											f2.doc = f1.doc;
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mergeFields(f:ClassField, f2:ClassField) {
							 | 
						||
| 
								 | 
							
										return TypeApi.fieldEq(f, f2)
							 | 
						||
| 
								 | 
							
											|| (f.name == f2.name && (mergeRights(f, f2) || mergeRights(f2, f)) && mergeDoc(f, f2) && TypeApi.fieldEq(f, f2));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public dynamic function newField(c:Classdef, f:ClassField) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mergeClasses(c:Classdef, c2:Classdef) {
							 | 
						||
| 
								 | 
							
										// todo : compare supers & interfaces
							 | 
						||
| 
								 | 
							
										if (c.isInterface != c2.isInterface)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										if (curplatform != null)
							 | 
						||
| 
								 | 
							
											c.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										if (c.isExtern != c2.isExtern)
							 | 
						||
| 
								 | 
							
											c.isExtern = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										for (f2 in c2.fields) {
							 | 
						||
| 
								 | 
							
											var found = null;
							 | 
						||
| 
								 | 
							
											for (f in c.fields)
							 | 
						||
| 
								 | 
							
												if (mergeFields(f, f2)) {
							 | 
						||
| 
								 | 
							
													found = f;
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											if (found == null) {
							 | 
						||
| 
								 | 
							
												newField(c, f2);
							 | 
						||
| 
								 | 
							
												c.fields.push(f2);
							 | 
						||
| 
								 | 
							
											} else if (curplatform != null)
							 | 
						||
| 
								 | 
							
												found.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										for (f2 in c2.statics) {
							 | 
						||
| 
								 | 
							
											var found = null;
							 | 
						||
| 
								 | 
							
											for (f in c.statics)
							 | 
						||
| 
								 | 
							
												if (mergeFields(f, f2)) {
							 | 
						||
| 
								 | 
							
													found = f;
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											if (found == null) {
							 | 
						||
| 
								 | 
							
												newField(c, f2);
							 | 
						||
| 
								 | 
							
												c.statics.push(f2);
							 | 
						||
| 
								 | 
							
											} else if (curplatform != null)
							 | 
						||
| 
								 | 
							
												found.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mergeEnums(e:Enumdef, e2:Enumdef) {
							 | 
						||
| 
								 | 
							
										if (e.isExtern != e2.isExtern)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										if (curplatform != null)
							 | 
						||
| 
								 | 
							
											e.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										for (c2 in e2.constructors) {
							 | 
						||
| 
								 | 
							
											var found = null;
							 | 
						||
| 
								 | 
							
											for (c in e.constructors)
							 | 
						||
| 
								 | 
							
												if (TypeApi.constructorEq(c, c2)) {
							 | 
						||
| 
								 | 
							
													found = c;
							 | 
						||
| 
								 | 
							
													break;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											if (found == null)
							 | 
						||
| 
								 | 
							
												e.constructors.push(c2);
							 | 
						||
| 
								 | 
							
											else if (curplatform != null)
							 | 
						||
| 
								 | 
							
												found.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mergeTypedefs(t:Typedef, t2:Typedef) {
							 | 
						||
| 
								 | 
							
										if (curplatform == null)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										t.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										t.types.set(curplatform, t2.type);
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mergeAbstracts(a:Abstractdef, a2:Abstractdef) {
							 | 
						||
| 
								 | 
							
										if (curplatform == null)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										if (a.to.length != a2.to.length || a.from.length != a2.from.length)
							 | 
						||
| 
								 | 
							
											return false;
							 | 
						||
| 
								 | 
							
										for (i in 0...a.to.length)
							 | 
						||
| 
								 | 
							
											if (!TypeApi.typeEq(a.to[i].t, a2.to[i].t))
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
										for (i in 0...a.from.length)
							 | 
						||
| 
								 | 
							
											if (!TypeApi.typeEq(a.from[i].t, a2.from[i].t))
							 | 
						||
| 
								 | 
							
												return false;
							 | 
						||
| 
								 | 
							
										if (a2.impl != null)
							 | 
						||
| 
								 | 
							
											mergeClasses(a.impl, a2.impl);
							 | 
						||
| 
								 | 
							
										a.platforms.push(curplatform);
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function merge(t:TypeTree) {
							 | 
						||
| 
								 | 
							
										var inf = TypeApi.typeInfos(t);
							 | 
						||
| 
								 | 
							
										var pack = inf.path.split(".");
							 | 
						||
| 
								 | 
							
										var cur = root;
							 | 
						||
| 
								 | 
							
										var curpack = new Array();
							 | 
						||
| 
								 | 
							
										pack.pop();
							 | 
						||
| 
								 | 
							
										for (p in pack) {
							 | 
						||
| 
								 | 
							
											var found = false;
							 | 
						||
| 
								 | 
							
											for (pk in cur)
							 | 
						||
| 
								 | 
							
												switch (pk) {
							 | 
						||
| 
								 | 
							
													case TPackage(pname, _, subs):
							 | 
						||
| 
								 | 
							
														if (pname == p) {
							 | 
						||
| 
								 | 
							
															found = true;
							 | 
						||
| 
								 | 
							
															cur = subs;
							 | 
						||
| 
								 | 
							
															break;
							 | 
						||
| 
								 | 
							
														}
							 | 
						||
| 
								 | 
							
													default:
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											curpack.push(p);
							 | 
						||
| 
								 | 
							
											if (!found) {
							 | 
						||
| 
								 | 
							
												var pk = new Array();
							 | 
						||
| 
								 | 
							
												cur.push(TPackage(p, curpack.join("."), pk));
							 | 
						||
| 
								 | 
							
												cur = pk;
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										for (ct in cur) {
							 | 
						||
| 
								 | 
							
											if (ct.match(TPackage(_)))
							 | 
						||
| 
								 | 
							
												continue;
							 | 
						||
| 
								 | 
							
											var tinf = TypeApi.typeInfos(ct);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											// compare params ?
							 | 
						||
| 
								 | 
							
											if (tinf.path == inf.path) {
							 | 
						||
| 
								 | 
							
												var sameType = true;
							 | 
						||
| 
								 | 
							
												if ((tinf.doc == null) != (inf.doc == null)) {
							 | 
						||
| 
								 | 
							
													if (inf.doc == null)
							 | 
						||
| 
								 | 
							
														inf.doc = tinf.doc;
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
														tinf.doc = inf.doc;
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												if (tinf.path == "haxe._Int64.NativeInt64")
							 | 
						||
| 
								 | 
							
													continue;
							 | 
						||
| 
								 | 
							
												if (tinf.module == inf.module && tinf.doc == inf.doc && tinf.isPrivate == inf.isPrivate)
							 | 
						||
| 
								 | 
							
													switch (ct) {
							 | 
						||
| 
								 | 
							
														case TClassdecl(c):
							 | 
						||
| 
								 | 
							
															switch (t) {
							 | 
						||
| 
								 | 
							
																case TClassdecl(c2):
							 | 
						||
| 
								 | 
							
																	if (mergeClasses(c, c2))
							 | 
						||
| 
								 | 
							
																		return;
							 | 
						||
| 
								 | 
							
																default:
							 | 
						||
| 
								 | 
							
																	sameType = false;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														case TEnumdecl(e):
							 | 
						||
| 
								 | 
							
															switch (t) {
							 | 
						||
| 
								 | 
							
																case TEnumdecl(e2):
							 | 
						||
| 
								 | 
							
																	if (mergeEnums(e, e2))
							 | 
						||
| 
								 | 
							
																		return;
							 | 
						||
| 
								 | 
							
																default:
							 | 
						||
| 
								 | 
							
																	sameType = false;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														case TTypedecl(td):
							 | 
						||
| 
								 | 
							
															switch (t) {
							 | 
						||
| 
								 | 
							
																case TTypedecl(td2):
							 | 
						||
| 
								 | 
							
																	if (mergeTypedefs(td, td2))
							 | 
						||
| 
								 | 
							
																		return;
							 | 
						||
| 
								 | 
							
																default:
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														case TAbstractdecl(a):
							 | 
						||
| 
								 | 
							
															switch (t) {
							 | 
						||
| 
								 | 
							
																case TAbstractdecl(a2):
							 | 
						||
| 
								 | 
							
																	if (mergeAbstracts(a, a2))
							 | 
						||
| 
								 | 
							
																		return;
							 | 
						||
| 
								 | 
							
																default:
							 | 
						||
| 
								 | 
							
																	sameType = false;
							 | 
						||
| 
								 | 
							
															}
							 | 
						||
| 
								 | 
							
														case TPackage(_, _, _):
							 | 
						||
| 
								 | 
							
															sameType = false;
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												// we already have a mapping, but which is incompatible
							 | 
						||
| 
								 | 
							
												var msg = if (tinf.module != inf.module) "module " + inf.module + " should be " + tinf.module; else if (tinf.doc != inf.doc)
							 | 
						||
| 
								 | 
							
													"documentation is different";
							 | 
						||
| 
								 | 
							
												else if (tinf.isPrivate != inf.isPrivate)
							 | 
						||
| 
								 | 
							
													"private flag is different";
							 | 
						||
| 
								 | 
							
												else if (!sameType)
							 | 
						||
| 
								 | 
							
													"type kind is different";
							 | 
						||
| 
								 | 
							
												else
							 | 
						||
| 
								 | 
							
													"could not merge definition";
							 | 
						||
| 
								 | 
							
												throw "Incompatibilities between " + tinf.path + " in " + tinf.platforms.join(",") + " and " + curplatform + " (" + msg + ")";
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										cur.push(t);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mkPath(p:String):Path {
							 | 
						||
| 
								 | 
							
										return p;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mkTypeParams(p:String):TypeParams {
							 | 
						||
| 
								 | 
							
										var pl = p.split(":");
							 | 
						||
| 
								 | 
							
										if (pl[0] == "")
							 | 
						||
| 
								 | 
							
											return new Array();
							 | 
						||
| 
								 | 
							
										return pl;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function mkRights(r:String):Rights {
							 | 
						||
| 
								 | 
							
										return switch (r) {
							 | 
						||
| 
								 | 
							
											case "null": RNo;
							 | 
						||
| 
								 | 
							
											case "method": RMethod;
							 | 
						||
| 
								 | 
							
											case "dynamic": RDynamic;
							 | 
						||
| 
								 | 
							
											case "inline": RInline;
							 | 
						||
| 
								 | 
							
											default: RCall(r);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xerror(c:Access):Dynamic {
							 | 
						||
| 
								 | 
							
										return throw "Invalid " + c.name;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xroot(x:Access) {
							 | 
						||
| 
								 | 
							
										for (c in x.x.elements())
							 | 
						||
| 
								 | 
							
											merge(processElement(c));
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									public function processElement(x:Xml) {
							 | 
						||
| 
								 | 
							
										var c = new haxe.xml.Access(x);
							 | 
						||
| 
								 | 
							
										return switch (c.name) {
							 | 
						||
| 
								 | 
							
											case "class": TClassdecl(xclass(c));
							 | 
						||
| 
								 | 
							
											case "enum": TEnumdecl(xenum(c));
							 | 
						||
| 
								 | 
							
											case "typedef": TTypedecl(xtypedef(c));
							 | 
						||
| 
								 | 
							
											case "abstract": TAbstractdecl(xabstract(c));
							 | 
						||
| 
								 | 
							
											default: xerror(c);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xmeta(x:Access):MetaData {
							 | 
						||
| 
								 | 
							
										var ml = [];
							 | 
						||
| 
								 | 
							
										for (m in x.nodes.m) {
							 | 
						||
| 
								 | 
							
											var pl = [];
							 | 
						||
| 
								 | 
							
											for (p in m.nodes.e)
							 | 
						||
| 
								 | 
							
												pl.push(p.innerHTML);
							 | 
						||
| 
								 | 
							
											ml.push({name: m.att.n, params: pl});
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return ml;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xoverloads(x:Access):Array<ClassField> {
							 | 
						||
| 
								 | 
							
										var l = new Array();
							 | 
						||
| 
								 | 
							
										for (m in x.elements) {
							 | 
						||
| 
								 | 
							
											l.push(xclassfield(m));
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return l;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xpath(x:Access):PathParams {
							 | 
						||
| 
								 | 
							
										var path = mkPath(x.att.path);
							 | 
						||
| 
								 | 
							
										var params = new Array();
							 | 
						||
| 
								 | 
							
										for (c in x.elements)
							 | 
						||
| 
								 | 
							
											params.push(xtype(c));
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											path: path,
							 | 
						||
| 
								 | 
							
											params: params,
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xclass(x:Access):Classdef {
							 | 
						||
| 
								 | 
							
										var csuper = null;
							 | 
						||
| 
								 | 
							
										var doc = null;
							 | 
						||
| 
								 | 
							
										var tdynamic = null;
							 | 
						||
| 
								 | 
							
										var interfaces = new Array();
							 | 
						||
| 
								 | 
							
										var fields = new Array();
							 | 
						||
| 
								 | 
							
										var statics = new Array();
							 | 
						||
| 
								 | 
							
										var meta = [];
							 | 
						||
| 
								 | 
							
										var isInterface = x.x.exists("interface");
							 | 
						||
| 
								 | 
							
										for (c in x.elements)
							 | 
						||
| 
								 | 
							
											switch (c.name) {
							 | 
						||
| 
								 | 
							
												case "haxe_doc":
							 | 
						||
| 
								 | 
							
													doc = c.innerData;
							 | 
						||
| 
								 | 
							
												case "extends":
							 | 
						||
| 
								 | 
							
													if (isInterface) {
							 | 
						||
| 
								 | 
							
														interfaces.push(xpath(c));
							 | 
						||
| 
								 | 
							
													} else {
							 | 
						||
| 
								 | 
							
														csuper = xpath(c);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												case "implements":
							 | 
						||
| 
								 | 
							
													interfaces.push(xpath(c));
							 | 
						||
| 
								 | 
							
												case "haxe_dynamic":
							 | 
						||
| 
								 | 
							
													tdynamic = xtype(new Access(c.x.firstElement()));
							 | 
						||
| 
								 | 
							
												case "meta":
							 | 
						||
| 
								 | 
							
													meta = xmeta(c);
							 | 
						||
| 
								 | 
							
												default:
							 | 
						||
| 
								 | 
							
													if (c.x.exists("static"))
							 | 
						||
| 
								 | 
							
														statics.push(xclassfield(c));
							 | 
						||
| 
								 | 
							
													else
							 | 
						||
| 
								 | 
							
														fields.push(xclassfield(c));
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											file: if (x.has.file) x.att.file else null,
							 | 
						||
| 
								 | 
							
											path: mkPath(x.att.path),
							 | 
						||
| 
								 | 
							
											module: if (x.has.module) mkPath(x.att.module) else null,
							 | 
						||
| 
								 | 
							
											doc: doc,
							 | 
						||
| 
								 | 
							
											isPrivate: x.x.exists("private"),
							 | 
						||
| 
								 | 
							
											isExtern: x.x.exists("extern"),
							 | 
						||
| 
								 | 
							
											isFinal: x.x.exists("final"),
							 | 
						||
| 
								 | 
							
											isInterface: isInterface,
							 | 
						||
| 
								 | 
							
											params: mkTypeParams(x.att.params),
							 | 
						||
| 
								 | 
							
											superClass: csuper,
							 | 
						||
| 
								 | 
							
											interfaces: interfaces,
							 | 
						||
| 
								 | 
							
											fields: fields,
							 | 
						||
| 
								 | 
							
											statics: statics,
							 | 
						||
| 
								 | 
							
											tdynamic: tdynamic,
							 | 
						||
| 
								 | 
							
											platforms: defplat(),
							 | 
						||
| 
								 | 
							
											meta: meta,
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xclassfield(x:Access, ?defPublic = false):ClassField {
							 | 
						||
| 
								 | 
							
										var e = x.elements;
							 | 
						||
| 
								 | 
							
										var t = xtype(e.next());
							 | 
						||
| 
								 | 
							
										var doc = null;
							 | 
						||
| 
								 | 
							
										var meta = [];
							 | 
						||
| 
								 | 
							
										var overloads = null;
							 | 
						||
| 
								 | 
							
										for (c in e)
							 | 
						||
| 
								 | 
							
											switch (c.name) {
							 | 
						||
| 
								 | 
							
												case "haxe_doc":
							 | 
						||
| 
								 | 
							
													doc = c.innerData;
							 | 
						||
| 
								 | 
							
												case "meta":
							 | 
						||
| 
								 | 
							
													meta = xmeta(c);
							 | 
						||
| 
								 | 
							
												case "overloads":
							 | 
						||
| 
								 | 
							
													overloads = xoverloads(c);
							 | 
						||
| 
								 | 
							
												default:
							 | 
						||
| 
								 | 
							
													xerror(c);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											name:x.name, type:t, isPublic:x.x.exists("public") || defPublic, isFinal:x.x.exists("final"), isOverride:x.x.exists("override"),
							 | 
						||
| 
								 | 
							
											line:if (x.has.line) Std.parseInt(x.att.line) else null, doc:doc, get:if (x.has.get) mkRights(x.att.get) else RNormal, set:if (x.has.set)
							 | 
						||
| 
								 | 
							
												mkRights(x.att.set)
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												RNormal, params:if (x.has.params) mkTypeParams(x.att.params) else [], platforms:defplat(), meta:meta, overloads:overloads, expr:if (x.has.expr)
							 | 
						||
| 
								 | 
							
												x.att.expr
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												null
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xenum(x:Access):Enumdef {
							 | 
						||
| 
								 | 
							
										var cl = new Array();
							 | 
						||
| 
								 | 
							
										var doc = null;
							 | 
						||
| 
								 | 
							
										var meta = [];
							 | 
						||
| 
								 | 
							
										for (c in x.elements)
							 | 
						||
| 
								 | 
							
											if (c.name == "haxe_doc")
							 | 
						||
| 
								 | 
							
												doc = c.innerData;
							 | 
						||
| 
								 | 
							
											else if (c.name == "meta")
							 | 
						||
| 
								 | 
							
												meta = xmeta(c);
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												cl.push(xenumfield(c));
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											file: if (x.has.file) x.att.file else null,
							 | 
						||
| 
								 | 
							
											path: mkPath(x.att.path),
							 | 
						||
| 
								 | 
							
											module: if (x.has.module) mkPath(x.att.module) else null,
							 | 
						||
| 
								 | 
							
											doc: doc,
							 | 
						||
| 
								 | 
							
											isPrivate: x.x.exists("private"),
							 | 
						||
| 
								 | 
							
											isExtern: x.x.exists("extern"),
							 | 
						||
| 
								 | 
							
											params: mkTypeParams(x.att.params),
							 | 
						||
| 
								 | 
							
											constructors: cl,
							 | 
						||
| 
								 | 
							
											platforms: defplat(),
							 | 
						||
| 
								 | 
							
											meta: meta,
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xenumfield(x:Access):EnumField {
							 | 
						||
| 
								 | 
							
										var args = null;
							 | 
						||
| 
								 | 
							
										var docElements = x.x.elementsNamed("haxe_doc");
							 | 
						||
| 
								 | 
							
										var xdoc = if (docElements.hasNext()) docElements.next() else null;
							 | 
						||
| 
								 | 
							
										var meta = if (x.hasNode.meta) xmeta(x.node.meta) else [];
							 | 
						||
| 
								 | 
							
										if (x.has.a) {
							 | 
						||
| 
								 | 
							
											var names = x.att.a.split(":");
							 | 
						||
| 
								 | 
							
											var elts = x.elements;
							 | 
						||
| 
								 | 
							
											args = new Array();
							 | 
						||
| 
								 | 
							
											for (c in names) {
							 | 
						||
| 
								 | 
							
												var opt = false;
							 | 
						||
| 
								 | 
							
												if (c.charAt(0) == "?") {
							 | 
						||
| 
								 | 
							
													opt = true;
							 | 
						||
| 
								 | 
							
													c = c.substr(1);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												args.push({
							 | 
						||
| 
								 | 
							
													name: c,
							 | 
						||
| 
								 | 
							
													opt: opt,
							 | 
						||
| 
								 | 
							
													t: xtype(elts.next()),
							 | 
						||
| 
								 | 
							
												});
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											name: x.name,
							 | 
						||
| 
								 | 
							
											args: args,
							 | 
						||
| 
								 | 
							
											doc: if (xdoc == null) null else new Access(xdoc).innerData,
							 | 
						||
| 
								 | 
							
											meta: meta,
							 | 
						||
| 
								 | 
							
											platforms: defplat(),
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xabstract(x:Access):Abstractdef {
							 | 
						||
| 
								 | 
							
										var doc = null, impl = null, athis = null;
							 | 
						||
| 
								 | 
							
										var meta = [], to = [], from = [];
							 | 
						||
| 
								 | 
							
										for (c in x.elements)
							 | 
						||
| 
								 | 
							
											switch (c.name) {
							 | 
						||
| 
								 | 
							
												case "haxe_doc":
							 | 
						||
| 
								 | 
							
													doc = c.innerData;
							 | 
						||
| 
								 | 
							
												case "meta":
							 | 
						||
| 
								 | 
							
													meta = xmeta(c);
							 | 
						||
| 
								 | 
							
												case "to":
							 | 
						||
| 
								 | 
							
													for (t in c.elements)
							 | 
						||
| 
								 | 
							
														to.push({t: xtype(new Access(t.x.firstElement())), field: t.has.field ? t.att.field : null});
							 | 
						||
| 
								 | 
							
												case "from":
							 | 
						||
| 
								 | 
							
													for (t in c.elements)
							 | 
						||
| 
								 | 
							
														from.push({t: xtype(new Access(t.x.firstElement())), field: t.has.field ? t.att.field : null});
							 | 
						||
| 
								 | 
							
												case "impl":
							 | 
						||
| 
								 | 
							
													impl = xclass(c.node.resolve("class"));
							 | 
						||
| 
								 | 
							
												case "this":
							 | 
						||
| 
								 | 
							
													athis = xtype(new Access(c.x.firstElement()));
							 | 
						||
| 
								 | 
							
												default:
							 | 
						||
| 
								 | 
							
													xerror(c);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											file: if (x.has.file) x.att.file else null,
							 | 
						||
| 
								 | 
							
											path: mkPath(x.att.path),
							 | 
						||
| 
								 | 
							
											module: if (x.has.module) mkPath(x.att.module) else null,
							 | 
						||
| 
								 | 
							
											doc: doc,
							 | 
						||
| 
								 | 
							
											isPrivate: x.x.exists("private"),
							 | 
						||
| 
								 | 
							
											params: mkTypeParams(x.att.params),
							 | 
						||
| 
								 | 
							
											platforms: defplat(),
							 | 
						||
| 
								 | 
							
											meta: meta,
							 | 
						||
| 
								 | 
							
											athis: athis,
							 | 
						||
| 
								 | 
							
											to: to,
							 | 
						||
| 
								 | 
							
											from: from,
							 | 
						||
| 
								 | 
							
											impl: impl
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xtypedef(x:Access):Typedef {
							 | 
						||
| 
								 | 
							
										var doc = null;
							 | 
						||
| 
								 | 
							
										var t = null;
							 | 
						||
| 
								 | 
							
										var meta = [];
							 | 
						||
| 
								 | 
							
										for (c in x.elements)
							 | 
						||
| 
								 | 
							
											if (c.name == "haxe_doc")
							 | 
						||
| 
								 | 
							
												doc = c.innerData;
							 | 
						||
| 
								 | 
							
											else if (c.name == "meta")
							 | 
						||
| 
								 | 
							
												meta = xmeta(c);
							 | 
						||
| 
								 | 
							
											else
							 | 
						||
| 
								 | 
							
												t = xtype(c);
							 | 
						||
| 
								 | 
							
										var types = new haxe.ds.StringMap();
							 | 
						||
| 
								 | 
							
										if (curplatform != null)
							 | 
						||
| 
								 | 
							
											types.set(curplatform, t);
							 | 
						||
| 
								 | 
							
										return {
							 | 
						||
| 
								 | 
							
											file: if (x.has.file) x.att.file else null,
							 | 
						||
| 
								 | 
							
											path: mkPath(x.att.path),
							 | 
						||
| 
								 | 
							
											module: if (x.has.module) mkPath(x.att.module) else null,
							 | 
						||
| 
								 | 
							
											doc: doc,
							 | 
						||
| 
								 | 
							
											isPrivate: x.x.exists("private"),
							 | 
						||
| 
								 | 
							
											params: mkTypeParams(x.att.params),
							 | 
						||
| 
								 | 
							
											type: t,
							 | 
						||
| 
								 | 
							
											types: types,
							 | 
						||
| 
								 | 
							
											platforms: defplat(),
							 | 
						||
| 
								 | 
							
											meta: meta,
							 | 
						||
| 
								 | 
							
										};
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xtype(x:Access):CType {
							 | 
						||
| 
								 | 
							
										return switch (x.name) {
							 | 
						||
| 
								 | 
							
											case "unknown":
							 | 
						||
| 
								 | 
							
												CUnknown;
							 | 
						||
| 
								 | 
							
											case "e":
							 | 
						||
| 
								 | 
							
												CEnum(mkPath(x.att.path), xtypeparams(x));
							 | 
						||
| 
								 | 
							
											case "c":
							 | 
						||
| 
								 | 
							
												CClass(mkPath(x.att.path), xtypeparams(x));
							 | 
						||
| 
								 | 
							
											case "t":
							 | 
						||
| 
								 | 
							
												CTypedef(mkPath(x.att.path), xtypeparams(x));
							 | 
						||
| 
								 | 
							
											case "x":
							 | 
						||
| 
								 | 
							
												CAbstract(mkPath(x.att.path), xtypeparams(x));
							 | 
						||
| 
								 | 
							
											case "f":
							 | 
						||
| 
								 | 
							
												var args = new Array();
							 | 
						||
| 
								 | 
							
												var aname = x.att.a.split(":");
							 | 
						||
| 
								 | 
							
												var eargs = aname.iterator();
							 | 
						||
| 
								 | 
							
												var evalues = x.has.v ? x.att.v.split(":").iterator() : null;
							 | 
						||
| 
								 | 
							
												for (e in x.elements) {
							 | 
						||
| 
								 | 
							
													var opt = false;
							 | 
						||
| 
								 | 
							
													var a = eargs.hasNext() ? eargs.next() : null;
							 | 
						||
| 
								 | 
							
													if (a == null)
							 | 
						||
| 
								 | 
							
														a = "";
							 | 
						||
| 
								 | 
							
													if (a.charAt(0) == "?") {
							 | 
						||
| 
								 | 
							
														opt = true;
							 | 
						||
| 
								 | 
							
														a = a.substr(1);
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
													var v = evalues == null || !evalues.hasNext() ? null : evalues.next();
							 | 
						||
| 
								 | 
							
													args.push({
							 | 
						||
| 
								 | 
							
														name: a,
							 | 
						||
| 
								 | 
							
														opt: opt,
							 | 
						||
| 
								 | 
							
														t: xtype(e),
							 | 
						||
| 
								 | 
							
														value: v == "" ? null : v
							 | 
						||
| 
								 | 
							
													});
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												var ret = args[args.length - 1];
							 | 
						||
| 
								 | 
							
												args.remove(ret);
							 | 
						||
| 
								 | 
							
												CFunction(args, ret.t);
							 | 
						||
| 
								 | 
							
											case "a":
							 | 
						||
| 
								 | 
							
												var fields = new Array();
							 | 
						||
| 
								 | 
							
												for (f in x.elements) {
							 | 
						||
| 
								 | 
							
													var f = xclassfield(f, true);
							 | 
						||
| 
								 | 
							
													f.platforms = new Array(); // platforms selection are on the type itself, not on fields
							 | 
						||
| 
								 | 
							
													fields.push(f);
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												CAnonymous(fields);
							 | 
						||
| 
								 | 
							
											case "d":
							 | 
						||
| 
								 | 
							
												var t = null;
							 | 
						||
| 
								 | 
							
												var tx = x.x.firstElement();
							 | 
						||
| 
								 | 
							
												if (tx != null)
							 | 
						||
| 
								 | 
							
													t = xtype(new Access(tx));
							 | 
						||
| 
								 | 
							
												CDynamic(t);
							 | 
						||
| 
								 | 
							
											default:
							 | 
						||
| 
								 | 
							
												xerror(x);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function xtypeparams(x:Access):Array<CType> {
							 | 
						||
| 
								 | 
							
										var p = new Array();
							 | 
						||
| 
								 | 
							
										for (c in x.elements)
							 | 
						||
| 
								 | 
							
											p.push(xtype(c));
							 | 
						||
| 
								 | 
							
										return p;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									function defplat() {
							 | 
						||
| 
								 | 
							
										var l = new Array();
							 | 
						||
| 
								 | 
							
										if (curplatform != null)
							 | 
						||
| 
								 | 
							
											l.push(curplatform);
							 | 
						||
| 
								 | 
							
										return l;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 |