Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > fish_r

Оценить эту запись

Универсальный трейсер.

Запись от fish_r размещена 21.05.2012 в 11:39
Обновил(-а) fish_r 29.05.2012 в 05:33

Недавно был здесь ( на флешере ) блог MikroAcse на тему трейсов непростых объектов ( или объектов непростого типа). Там он приводил сыренький скрипт такого трейса, а в постах были интересные комментарии и подсказки. Блога нет, и скрипт он кажется до ума не довёл.

Когда я начал работать с социальными сетями такой плагинчик мне стал нужен, т.к. не все объекты можно "пощупать" через консоли, ведь консоли обычно привязаны к отображаемым объектам, а у меня, например, вьюер не имеет ссылки на контроллер и провайдер данных, ну и прочее. В общем нужен стал. Чужое во-первых искать не охота, во-вторых юзать незнакомый плагин не комфортно, в-третьих интересно было самому сделать
такой, хоть и "велосипед" - да, да, я знаю ).

Ниже код того, что у меня получилось. Можно регулировать "глубину просмотра" объектов соотв. параметром,
можно запретить "парсить" экземпляры классов (т.к. нативные классы содержат много, возможно, ненужной информации - если таких объектов много, то это просто катастрофа будет), если парсинг экземпляров классов отключен, то парситься будет лишь тот экземпляр класса который и был передан в аргументах вызова метода Dumper.dump(). Можно включать/отключать определение простых типов. XML- объекты не парсятся, лишь обозначаются, т.к. хмл документы могут быть ( и обычно бывают ) достаточно большими, и помимо этого они простым трейсом хорошо просматриваются я решил исключить их содержимое из выдачи, может быть потом передумаю - опыт покажет ).


И кстати, трейсер этот ничего, на самом деле, не трейсит. Он возвращает отформатированную строку, с переносами и табуляцией. Во-первых это удобно мне, т.к. я использую для установки трейса в программе снипет такого вида:

Код:
///TODO trace
////////////////////////// T R A C E ///////////////////////////////
var d:Date = new Date();
trace(d.valueOf() + ". $(TypName)::$(MbrName)()  : " + $(EntryPoint));
//////////////////////// E N D  T R A C E //////////////////////////
где указано место в котором происходит вызов trace, потом удобно искать и убирать трейсы ставшие не нужными, кроме того он легко визуально находится в тексте программы. Если же трейсить прямо из Dumper-a
то будет непонятно - где именно происходит обращение. Ну и во-вторых, такую строку не обязательно выводить в трейс, можно и в консоль отправить если с ней удобнее работать.

Из косяков: немного "едет" табуляция, попозже проверю, уже сейчас некогда, и я не уверен что правильно
расчитывается "глубина" просмотра когда дело касается экземпляров классов на которые ссылаются перем.
изучаемого объекта, это тоже попозже хочу проверить...

Внимание! Класс не умеет обрабатывать объекты с циклическими ссылками ( когда объект ссылается сам на себя в своих полях и подобное ).

update 28.05.12

Код AS3:
///********************************************************************
///* Copyright © 2012 fishr (fishr.flash@gmail.com)  
///********************************************************************
 
 
package su.fishr.utils 
{
	import flash.utils.*;
 
	/**
	 * Возвращает форматированную строку, с перечислением
	 * доступных полей, акцессоров и их значений объекта ссылка на который
	 * получена в аргументах единственного публичного метода.
	 * 
	 * @playerversion          Flash 10
	 * @langversion            3.0
	 * @author                 fishr
	 * @created                20.05.2012 1:11
	 * @since                  20.05.2012 1:11
	 */
	final public class Dumper
	{
		static private var _timeDie:int;
		static private const _MAX_TIME_DIE:int = 200;
 
	/**-------------------------------------------------------------------------------
	* 
	*								P U B L I C 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		public function Dumper()
		{
			throw( new Error( "Not create exemplar this" ) );
		}	
 
		/**
		 * Имеет один обязательный параметр - объект любого сложного или простого типа.
		 * Возвращает форматированную строку, с переносами и табуляцей, в которой перечислены
		 * все доступные поля, акцессоры и их значения обнаруженные в полученном по ссылке в 
		 * аргументах вызова объекте.
		 * 
		 * <P>
		 * <P>
		 * <B>Важно!</B> 
		 * <I>Класс не умеет обрабатывать циклические ссылки ( когда объект ссылается сам на себя в своих
		 * полях и т.п. ). Для предотвращения зацикливания время непрерывной работы скрипта ограничивается
		 * значением константы _MAX_TIME_DIE
		 * </I>
		 * </P>
		 * 
		 * <P>
		 * <B>Примечание.</B> Так как переменные числовых типов утрачивают первоначальный тип.
		 * Обнаруженные поля числовых типов описываются следующим образом:
		 *  - если значение - целое число в диапазоне <CODE>int</CODE> оно характерезуется типом <CODE>int</CODE>,
		 *  - если значение - целое положительное число за диапазоном <CODE>int</CODE> (но меньше <CODE>uint.MAX_VALUE</CODE> )оно характерезуется типом <CODE>uint</CODE>,
		 *  - во всех остальных случаях числа описываются типом <CODE>number</CODE>.
		 * </P>
		 * 
		 * <B>Примечание.</B> Данные xml-типов не разбираются, только указывается тип таких данных.
		 * 
		 * <P>
		 * 
		 * <B>Примечание.</B> В круглых скобках указывается тип поля, если этот тип - строка или числовой тип далее
		 * следуют цифры, которые при строковом типе указывают длину строки, в числовом кол-во цифр целой и дробной части числа
		 * в формате: целая_часть[.дробная_часть].
		 * </P>
		 * 
		 * <P>
		 * 
		 * <B>Примечание.</B> Максимальная длительность непрерывной обработки - 0.512 секунды. Максимальная длина возвращаемой строки - 1024 символов.
		 * </P>
		 * 
		 * <P>
		 * 
		 * <B>Примечание.</B> Парсинг ссылок на классы в полях DisplayObject-ов находящихся в списке отображения не выполняется.
		 * </P>
		 * 
		 * @param	arg объект любого типа информацию о доступных полях которого нужно получить
		 * @param	onType ( default: true ) флаг указывающий следует ли указывать тип возвращаемых данных
		 * @param	level ( default: -1 ) "глубина" просмотра вложенных объектов обнаруженных в разбираемом объекте
		 * @param	openClasses ( default: false ) нужно ли разбирать поля вложенных объектов со статическим типом данных,
		 * 			т.к. экземпляры нативных классов могут содержать данные о своих полях довольно внушительного объёма
		 * 			этот параметр по умолчанию отключен.
		 * @return  форматированную строку содержащую инофрмацию об обнаруженных доступных полях объекта переданного
		 *          в аргументах вызова метода.
		 */
		static public function dump( arg:*, level:int = -1, onType:Boolean = true, openClasses:Boolean = false ):String
		{
			if ( !arg ) return "No object body";
 
			var result:String;
 
			if( !_timeDie ) _timeDie = getTimer();
 
			if ( typeof arg !== "object" )
			{
				result = " value = ( " + analisisSimple( arg ) +  " ) "  + arg;
				_timeDie = 0;
				return  result;
			}
			else
			{
				if (  arg.hasOwnProperty( "stage" ) && arg.stage !== null) openClasses = false;
 
				result = analisisObject( arg, onType, level, "\r", openClasses, true);
				_timeDie = 0;
				return result;
			}
 
		}
	//}
 
	/**-------------------------------------------------------------------------------
	* 
	*								P R I V A T E 	
	* 
	* --------------------------------------------------------------------------------
	*/	
	//{
 
		static private function dumpArray( arr:Array, onType:Boolean, level:int, space:String, openClasses:Boolean ):String
		{
			if ( level === 0 ) return   "Array " + ( onType?"( " + arr.length +  " )":"" ) + " /limiting level.../" ;
			else level --;
 
			const timer:int = getTimer(); 
			if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... ";
 
			var parseArray:String = "Array" + ( onType?"(" + arr.length +  "):":":"  );
			var stepSpace:String = space + "\t";
			var type:String;
			var descript:String;
 
			for ( var nm:String in arr )
			{
				if ( typeof arr[ nm ] !== "object" )
				{
					const typingValue:String = analisisSimple( arr[ nm ] );
					descript = stepSpace +  "[" + nm + "] => " + ( onType?"(" + typingValue + ") ":"" );
 
					parseArray += descript + ( ( typingValue === "xml" )?"/not shown.../":arr[ nm ] );
				}
				else
				{
 
					descript = stepSpace +  "[" + nm + "] => ";
					parseArray += descript + analisisObject( arr[ nm ], onType, level, stepSpace, openClasses  ) ;
				}
			}
 
			return parseArray;
		}
 
		static private function dumpObject( arg:Object , onType:Boolean, level:int, space:String, openClasses:Boolean  ):String
		{
			if ( level === 0 ) return   "Object /limiting level.../" ;
			else level --;
 
			const timer:int = getTimer(); 
			if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... ";
 
			var parseObject:String = "Object";
			var parseContent:String = "";
 
			var stepSpace:String = space +  "\t";
			var type:String;
			var descript:String;
			var countElems:int = 0;
 
			for ( var nm:String in arg )
			{
				if ( typeof arg[ nm ] !== "object" )
				{
					const typingValue:String = analisisSimple( arg[ nm ] );
					descript = stepSpace +  "" + nm + ":" + ( onType?"(" + typingValue + ") ":"" )
 
					parseContent += descript + ( ( typingValue === "xml" )?"/not shown.../":arg[ nm ] );
				}
				else
				{
					descript = stepSpace +  "" + nm + ":";
					parseContent += descript + analisisObject( arg[ nm ], onType, level, stepSpace, openClasses  ) ;
				}
 
				countElems++;
			}
 
			parseObject += " (" + countElems + "): " + parseContent;
 
			return parseObject;
		}
 
		static private function dumpClass( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean  ):String
		{
 
 
 
			if ( level === 0 ) return   arg.toString() + " /limiting level.../";
			else level--;
 
			const timer:int = getTimer(); 
			if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... ";
 
			var parseClass:String =  arg.toString() + ": ";
			var stepSpace:String = space +  "\t";
			var type:String;
 
 
			const xmlDescription:XML = describeType( arg );
			const variables:XMLList = xmlDescription.variable;
			const accessors:XMLList = xmlDescription.accessor;
			const constant:XMLList = xmlDescription.constant;
			const method:XMLList = xmlDescription.method;
 
			///variables
			var descript:String = "variables";
			parseClass += stepSpace + descript;
 
			stepSpace += "\t";
 
			var contenVar:String = "";
			var countElems:int = 0;
 
			for each ( var publicVar:XML in variables )
			{
				if ( typeof arg[ publicVar.@name ] !== "object" )
				{
					const typeVar:String = analisisSimple( arg[ publicVar.@name ] );
					descript = stepSpace +  "" + publicVar.@name + " = " + ( onType?"(" + typeVar + ") ":"" )
					contenVar += descript  + ( ( typeVar === "xml" )?"/not shown.../":( arg[ publicVar.@name ] ) );
				}
				else
				{
					descript = stepSpace +  " " + publicVar.@name + " = ";
					contenVar += 
						( arg[ publicVar.@name ] === null || arg[ publicVar.@name ] === undefined)?
							descript +  ( onType?"(" + publicVar.@type + ",0)":"" ) + arg[ publicVar.@name ]:
							descript + analisisObject( arg[ publicVar.@name ], onType, level, stepSpace, openClasses);
				}
 
				countElems++;
 
			}
 
			parseClass += " (" + countElems + "): " + contenVar;
 
 
 
			///constants
			descript = "constants";
 
			stepSpace = space +  "\t";
			parseClass += stepSpace + descript;
			var contentConst:String = "";
			countElems = 0;
 
 
			stepSpace += new Array( descript.length ).join( " " );
 
			for each ( var publicConst:XML in constant )
			{
				if ( typeof arg[ publicConst.@name ] !== "object" )
				{
					const typeConst:String = analisisSimple( arg[ publicConst.@name ] );
					descript = stepSpace +  "" + publicConst.@name + " = " + ( onType?"(" + typeConst + ") ":"" )
					contentConst += descript  + ( ( typeConst === "xml" )?"/not shown.../":( arg[ publicConst.@name ] ) );
				}
				else
				{
					descript = stepSpace +  " " + publicConst.@name + " = ";
					contentConst += 
						( arg[ publicConst.@name ] === null || arg[ publicConst.@name ] === undefined)?
							descript +  ( onType?"(" + publicConst.@type + ",0)":"" ) + arg[ publicConst.@name ]:
							descript + analisisObject( arg[ publicConst.@name ], onType, level, stepSpace + "\t", openClasses);
				}
 
				countElems++;
			}
 
			parseClass += " (" + countElems + "): " + contentConst;
 
			///accessors
			stepSpace = space +  "\t";
			descript = "accessors";
			parseClass += stepSpace + descript;
			stepSpace  += "\t";
 
			var contentAcc:String = "";
			countElems = 0;
 
			for each ( var publicAcc:XML in accessors )
			{
				if ( publicAcc.@access == "writeonly" ) continue;
 
				if ( typeof arg[ publicAcc.@name ] !== "object" )
				{
					const typeAcc:String = analisisSimple( arg[ publicAcc.@name ] );
					descript = stepSpace + publicAcc.@access +  " " + publicAcc.@name + " = " + ( onType?"(" + typeAcc + ") ":"" );
					contentAcc += descript + ( ( typeAcc === "xml" )?"/not shown.../":( arg[ publicAcc.@name ] ) );
 
				}
				else
				{
					descript = stepSpace + publicAcc.@access + " " + publicAcc.@name + " = ";
 
					contentAcc +=
						( arg[ publicAcc.@name ] === null || arg[ publicAcc.@name ] === undefined)? 
						descript +  ( onType?"(" +  publicAcc.@type + ",0)":"" ) + arg[ publicAcc.@name ]:
						descript + analisisObject( arg[ publicAcc.@name ], onType, level, stepSpace + "\t", openClasses);
 
 
				}
 
				countElems++;
 
			}
 
			parseClass += " (" + countElems + ") " + contentAcc;
 
			///methods
			stepSpace = space + "\t";
			descript = "methods";
			parseClass += stepSpace + descript;
			stepSpace  += "\t";
			var contentMethods:String = "";
			countElems = 0;
			for each ( var publicMethod:XML in method )
			{
				contentMethods += stepSpace + publicMethod.@name + ":" + publicMethod.@returnType;
				countElems++;
			}
 
			parseClass += " (" + countElems + ") " + contentMethods;
 
 
			return parseClass;
		}
 
		static private function dumpVector( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean  ):String
		{
			if ( level === 0 ) return   getQualifiedClassName( arg ) + " /limiting level.../";
			else level--;
 
			const timer:int = getTimer(); 
			if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... ";
 
			var parseVector:String = "( " + arg.length + " )";
			var stepSpace:String = space +  "\t";
			var type:String;
			var descript:String;
 
			for ( var nm:String in arg )
			{
				if ( typeof arg[ nm ] !== "object" )
				{
					const typingValue:String = analisisSimple( arg[ nm ] );
					descript = stepSpace +  "[" + nm + "] => " + ( onType?"(" + typingValue + ") ":"" )
 
					parseVector += descript +( ( typingValue === "xml" )?"/not shown.../":arg[ nm ] );
				}
				else
				{
					descript = stepSpace +  "[" + nm + "] => ";
					parseVector += descript + analisisObject( arg[ nm ], onType, level, stepSpace + "\t", openClasses  ) ;
				}
			}
 
			return parseVector;
		}
 
 
		static private function dumpDictionary( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean  ):String
		{
			if ( level === 0 ) return   getQualifiedClassName( arg ) + " /limiting level.../";
			else level--;
 
			const timer:int = getTimer(); 
			if ( timer > _timeDie + _MAX_TIME_DIE ) return " too long processing... ";
 
			var parseDict:String = getQualifiedClassName( arg );
			var parseContent:String = "";
			var stepSpace:String = space + "\t";
			var type:String;
			var descript:String;
			var countElem:int = 0;
 
			for ( var nm:* in arg )
			{
				if ( typeof arg[ nm ] !== "object" )
				{
					const typingValue:String = analisisSimple( arg[ nm ] );
					descript = stepSpace +  "[" + getQualifiedClassName( nm )+ "] => " + ( onType?"(" + typingValue + ") ":"" )
 
					parseContent += descript + ( ( typingValue === "xml" )?"/not shown.../":arg[ nm ] );
				}
				else
				{
					descript = stepSpace +  "[" + getQualifiedClassName( nm ) + "] => ";
					parseContent += descript + analisisObject( arg[ nm ], onType, level, stepSpace , openClasses  ) ;
				}
 
				countElem++;
			}
 
			parseDict += " (" + countElem +"): " + parseContent;
 
			return parseDict;
 
 
		}
 
 
		static private function analisisObject( arg:*, onType:Boolean, level:int, space:String, openClasses:Boolean, firstFlag:Boolean = false  ):String
		{
			var parseData:String;
 
			const classType:String = getQualifiedClassName( arg );
 
			switch ( classType ) 
			{
				case "flash.utils::Dictionary":
					parseData = dumpDictionary( arg, onType, level, space, openClasses );
				break;
 
				case "Object": 
 
					parseData = dumpObject( arg, onType, level, space, openClasses );
				break;
 
				case "Array":
					parseData =  dumpArray( arg as Array, onType, level, space, openClasses );
				break;
 
				case ( classType.indexOf( "Vector" ) !== -1 )?classType:"":
 
					parseData = dumpVector( arg, onType, level, space, openClasses );
 
					break;
 
				default:
 
					if ( firstFlag && !( openClasses ) || openClasses &&  !(  arg.hasOwnProperty( "stage" ) && arg.stage !== null)) parseData = dumpClass( arg, onType, level, space, openClasses );
					else parseData = arg;
			}
 
			return parseData;
		}
 
		static private function analisisSimple( arg:* ):String
		{
			var type:String;
 
			if ( typeof arg === "xml" )
			{
				type = "xml";
			}
			else if ( typeof arg === "string" )
			{
				String( arg );
				type = "str" + "," + String( arg ).length;
			}
			else if ( typeof arg === "number" )
			{
				if ( arg is int ) 
				{
					type = "int";
					type += "," + String( arg + "").length;
				}
				else if ( arg as uint ) 
				{
					type = "uint";
					type += "," + String( arg + "").length;
				}
				else 
				{
					type = "number";
					const floor:int =  String( Math.floor( arg ) ).length;
					const fract:Array = ( arg + "" ).split( "." );
					const fractional:int = fract.length > 1?fract[ 1 ].length:0;
 
					type += "," + String( floor + "." + fractional);
				}
 
 
			}
			else if ( typeof arg === "boolean" ) type = "bool";
			else type = "";
 
			return type;
		}
	//}
 
 
	}
 
}
Тигра посетовал, что нет примера работы, ну может в этом и есть смысл. Пример работы:

Описание тестового класса:

Код AS3:
///********************************************************************
///* Copyright © 2012 fishr (fishr.flash@gmail.com)  
///********************************************************************
 
 
package  
{
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.utils.Dictionary;
	import su.fishr.utils.Dumper;
 
 
 
	/**
	 *  Для тестирования трейсера Dumper()
	 * 
	 * @playerversion          Flash 9
	 * @langversion            3.0
	 * @author                 fishr
	 * @created                24.05.2012 22:05
	 * @since                  24.05.2012 22:05
	 */
	public  class Demo
	{
 
	/**-------------------------------------------------------------------------------
	* 
	*								P U B L I C 	
	* 
	* --------------------------------------------------------------------------------
	*/
	//{
		public function Demo()
		{
 
			init();
		}
	//}
 
	/**-------------------------------------------------------------------------------
	* 
	*								P R I V A T E 	
	* 
	* --------------------------------------------------------------------------------
	*/	
	//{
		private function init():void
		{
			const xmlNodes:XML = <data> <some_node> "some_value"</some_node> <some_node> anower_value </some_node></data>;
			const pseudoXML:String = '<data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>';
			const xmlList:XMLList = xmlNodes.some_node;
			const nmbr:Number = 3094530495.394304999303300;
			const sprite:Sprite = new Sprite();
			const movie:MovieClip = new MovieClip();
			movie.addChild( sprite );
			const array:Array = [ "abc", "bcd", "cde", "def", nmbr, xmlNodes, pseudoXML ];
			const obj:Object = { someElem:"String Elem", someArray:array, someNm:nmbr, xml:xmlNodes };
 
			const vect:Vector.<*> = new Vector.<*>;
			vect.push( nmbr );
			vect.push( array );
			vect.push(  obj );
			vect.push( xmlNodes );
 
			const dictionary:Dictionary = new Dictionary();
			dictionary[ nmbr ] = nmbr;
			dictionary[ array ] = [ array, array, array, { array:array, array1:array } ];
			dictionary[ vect ] = vect;
			dictionary[ movie ] = movie;
			dictionary[ xmlNodes ] = xmlNodes;
 
 
			///TODO trace
			////////////////////////// T R A C E ///////////////////////////////
			var d:Date = new Date();
			trace(d.valueOf() + ". Demo::init()  : \r\r"  + Dumper.dump( [ dictionary, dictionary , { dictionary:dictionary } ], -1, true));
			//////////////////////// E N D  T R A C E //////////////////////////
 
 
 
 
		}
	//}
 
 
	}
 
}

Результат работы:

Код:
1338214593171. Demo::init()  : 

Array(3):
	[0] => flash.utils::Dictionary (5): 
		[String] => (number,10.6) 3094530495.394305
		[__AS3__.vec::Vector.<*>] => ( 4 )
			[0] => (number,10.6) 3094530495.394305
			[1] => Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[2] => Object (4): 
					someElem:(str,11) String Elem
					someArray:Array(7):
						[0] => (str,3) abc
						[1] => (str,3) bcd
						[2] => (str,3) cde
						[3] => (str,3) def
						[4] => (number,10.6) 3094530495.394305
						[5] => (xml) /not shown.../
						[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
					someNm:(number,10.6) 3094530495.394305
					xml:(xml) /not shown.../
			[3] => (xml) /not shown.../
		[flash.display::MovieClip] => [object MovieClip]
		[Array] => Array(4):
			[0] => Array(7):
				[0] => (str,3) abc
				[1] => (str,3) bcd
				[2] => (str,3) cde
				[3] => (str,3) def
				[4] => (number,10.6) 3094530495.394305
				[5] => (xml) /not shown.../
				[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[1] => Array(7):
				[0] => (str,3) abc
				[1] => (str,3) bcd
				[2] => (str,3) cde
				[3] => (str,3) def
				[4] => (number,10.6) 3094530495.394305
				[5] => (xml) /not shown.../
				[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[2] => Array(7):
				[0] => (str,3) abc
				[1] => (str,3) bcd
				[2] => (str,3) cde
				[3] => (str,3) def
				[4] => (number,10.6) 3094530495.394305
				[5] => (xml) /not shown.../
				[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[3] => Object (2): 
				array:Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
				array1:Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
		[XML] => (xml) /not shown.../
	[1] => flash.utils::Dictionary (5): 
		[String] => (number,10.6) 3094530495.394305
		[__AS3__.vec::Vector.<*>] => ( 4 )
			[0] => (number,10.6) 3094530495.394305
			[1] => Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[2] => Object (4): 
					someElem:(str,11) String Elem
					someArray:Array(7):
						[0] => (str,3) abc
						[1] => (str,3) bcd
						[2] => (str,3) cde
						[3] => (str,3) def
						[4] => (number,10.6) 3094530495.394305
						[5] => (xml) /not shown.../
						[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
					someNm:(number,10.6) 3094530495.394305
					xml:(xml) /not shown.../
			[3] => (xml) /not shown.../
		[flash.display::MovieClip] => [object MovieClip]
		[Array] => Array(4):
			[0] => Array(7):
				[0] => (str,3) abc
				[1] => (str,3) bcd
				[2] => (str,3) cde
				[3] => (str,3) def
				[4] => (number,10.6) 3094530495.394305
				[5] => (xml) /not shown.../
				[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[1] => Array(7):
				[0] => (str,3) abc
				[1] => (str,3) bcd
				[2] => (str,3) cde
				[3] => (str,3) def
				[4] => (number,10.6) 3094530495.394305
				[5] => (xml) /not shown.../
				[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[2] => Array(7):
				[0] => (str,3) abc
				[1] => (str,3) bcd
				[2] => (str,3) cde
				[3] => (str,3) def
				[4] => (number,10.6) 3094530495.394305
				[5] => (xml) /not shown.../
				[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[3] => Object (2): 
				array:Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
				array1:Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
		[XML] => (xml) /not shown.../
	[2] => Object (1): 
		dictionary:flash.utils::Dictionary (5): 
			[String] => (number,10.6) 3094530495.394305
			[__AS3__.vec::Vector.<*>] => ( 4 )
				[0] => (number,10.6) 3094530495.394305
				[1] => Array(7):
						[0] => (str,3) abc
						[1] => (str,3) bcd
						[2] => (str,3) cde
						[3] => (str,3) def
						[4] => (number,10.6) 3094530495.394305
						[5] => (xml) /not shown.../
						[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
				[2] => Object (4): 
						someElem:(str,11) String Elem
						someArray:Array(7):
							[0] => (str,3) abc
							[1] => (str,3) bcd
							[2] => (str,3) cde
							[3] => (str,3) def
							[4] => (number,10.6) 3094530495.394305
							[5] => (xml) /not shown.../
							[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
						someNm:(number,10.6) 3094530495.394305
						xml:(xml) /not shown.../
				[3] => (xml) /not shown.../
			[flash.display::MovieClip] => [object MovieClip]
			[Array] => Array(4):
				[0] => Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
				[1] => Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
				[2] => Array(7):
					[0] => (str,3) abc
					[1] => (str,3) bcd
					[2] => (str,3) cde
					[3] => (str,3) def
					[4] => (number,10.6) 3094530495.394305
					[5] => (xml) /not shown.../
					[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
				[3] => Object (2): 
					array:Array(7):
						[0] => (str,3) abc
						[1] => (str,3) bcd
						[2] => (str,3) cde
						[3] => (str,3) def
						[4] => (number,10.6) 3094530495.394305
						[5] => (xml) /not shown.../
						[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
					array1:Array(7):
						[0] => (str,3) abc
						[1] => (str,3) bcd
						[2] => (str,3) cde
						[3] => (str,3) def
						[4] => (number,10.6) 3094530495.394305
						[5] => (xml) /not shown.../
						[6] => (str,85) <data><some_node>"some_value"</some_node><some_node> anower_value </some_node></data>
			[XML] => (xml) /not shown.../
Всего комментариев 30

Комментарии

Старый 22.05.2012 21:16 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
Из косяков: немного "едет" табуляция, попозже проверю, уже сейчас некогда, и я не уверен что правильно
расчитывается "глубина" просмотра когда дело касается экземпляров классов на которые ссылаются перем.
изучаемого объекта, это тоже попозже хочу проверить...
Конечно, это мелочи, но... немного иногда непонятно, откуда находится время на оформление статьи, в то время пока это время можно было бы потратить на поиск и исправление этих багов.
И всегда хочется видеть пример. Когда есть голый код и нечего пощупать - это... грустно.
Старый 22.05.2012 23:54 fish_r вне форума
fish_r
 
Аватар для fish_r
Статья ерунда - она ошибки стерпит. Код нет. Насчет пощупать - сам сейчас ещё щупаю. Но, с другой стороны: а что здесь щупать? Бери - пробуй. Не понравится выбросишь. Это ведь достаточно примитивная вещь. Т.е. я хочу сказать, что особого эффекта от демонстрации всё равно не будет.
Старый 23.05.2012 10:16 etc вне форума
etc
 
Аватар для etc
Обновил(-а) fish_r 23.05.2012 в 13:27
Старый 23.05.2012 12:57 Inet_PC вне форума
Inet_PC
Если Flex проект, то есть ObjectUtil.toString.
Код AS3:
var obj:Object = {};
obj.next = obj;
trace(Dumper.dump(obj));
Тупо зацикливается и падает.

Код AS3:
var obj:Object = {};
obj.next = 5;
obj.spr = new Sprite();
obj.spr.addChild(new Sprite());
 
trace(Dumper.dump(obj,true, -1, true));
Да табуляция явно узкое место, прочитать вообще ничего не возможно, имхо.
Обновил(-а) Inet_PC 23.05.2012 в 13:06
Старый 23.05.2012 13:27 fish_r вне форума
fish_r
 
Аватар для fish_r
Выгрузил себе его библиотеку полностью. Попробовал traceObject(). Сначала ругалось на
Цитата:
1120: Access of undefined property ByteArrayUtils,
такой класс есть, только там есть имена и атрибуты методов, а тел у них нет
( алхимия? хаксе? незнаю) - заккоментил.

Затем получил такую ошибку:

Цитата:
Недопустимое чтение свойства "только для записи" blendShader
у меня такое тоже было пока не отключил запрос к акцессорам "только для записи"...

Попробовал ещё в двух других проектах... но так у меня ничего и не вышло.

Вообще библиотека очень интересная, там есть что почитать. Но для парсинга объектов
надо всю её подключать. Один класс не получится - он хоть и небольшой но связан с кучей других
предоставляющих ту или иную информацию и возможности. Это неудобно. А уж о том, чтобы "заточить
под себя" и думать не моги )
Старый 23.05.2012 13:48 fish_r вне форума
fish_r
 
Аватар для fish_r
Цитата:
Код AS3:
var obj:Object = {};
obj.next = obj;
trace(Dumper.dump(obj));
Тупо зацикливается и падает.
Не, а чего вы ждете от него если вы замкнули объект сам на себя?
Это исправляться не будет, т.к. это статический класс и состояний у него быть не должно,
поэтому никакая информация им запоминаться не будет в принципе.

Посмотрим на практике, если слишком часто буду на эти грабли наступать может что то и придумаю.
Объект делать очень не хочется ибо нужен глобальный доступ, может стек?... Не знаю пока.
Обновил(-а) fish_r 23.05.2012 в 14:29
Старый 23.05.2012 13:54 fish_r вне форума
fish_r
 
Аватар для fish_r
* и ещё нашёл просто эпический баг...

Когда делал его - смотрел в сторону DataObject и очень не внимательно в сторону DisplayObject. А ведь
последний может быть на сцене, а значит его свойства рут, парент и стейдж будут не пустыми, а значит... ну вы понимаете

Короче - пофиксил. Теперь поля ( и акцессоры конечно), ссылающиеся на эк-ры классов, объекта лежащего на сцене не парсятся, а лишь указывается их тип.
Старый 23.05.2012 14:37 fish_r вне форума
fish_r
 
Аватар для fish_r
Цитата:
Да табуляция явно узкое место, прочитать вообще ничего не возможно, имхо.
Проблема не в табуляции именно этого класса, там расхождения +-2-3 символа, это не очень эстетично, но совершенно не запутывает, и легко определить что к чему относится.

Просто строки данных могут быть довольно длинными, а если трейсы у вас выводятся с переносом строки (как это обычно и бывает), то действительно - получается каша. Если эти данные просматривать без переноса, то всё вполне нормально выглядит ( структурно ). Как решить это? Это вообще кто-нибудь решил? Похоже нет
Старый 23.05.2012 17:33 Inet_PC вне форума
Inet_PC
Цитата:
Не, а чего вы ждете от него если вы замкнули объект сам на себя?
Я ничего не жду, но по идее Dumper должен разруливать такие ситуации. У Вас не бывает, что в A есть ссылка на B, а в B есть ссылка на С, а в ней на A? (или более длинная цепочка). Не думаю, что кто-то хочет получить такую ошибку и сидеть разбираться.
Старый 23.05.2012 20:26 fish_r вне форума
fish_r
 
Аватар для fish_r
Для реализации такого контроля нужно чтобы объект запоминал все те объекты которые он уже разбирал
и сравнивал с вновь поступающими на разбор. Реализация такой штуки лишит смысла статический характер класса, а объекту надо будет предоставлять глобальный доступ каким то иным способом.
Можно обернуть такой объект в статик, но тогда уже ему нужно будет давать каллбэк, или разрешать самому трейсить... В общем пока нет достойных идей - как это контролировать. Пока - есть уровень просмотра, есть запрет на разбор классов...

Цитата:
Не думаю, что кто-то хочет получить такую ошибку и сидеть разбираться.
Разбираться там особо не надо. В этих случаях плеер исключение выкидывает с указанием места где закольцевалось.
Обновил(-а) fish_r 23.05.2012 в 20:30
Старый 24.05.2012 09:27 Inet_PC вне форума
Inet_PC
Цитата:
Реализация такой штуки лишит смысла статический характер класса, а объекту надо будет предоставлять глобальный доступ каким то иным способом.
Не понимаю в чем проблема, почему нельзя просто в массив запоминать всех тех, кого уже разобрали и перед разбором очередного объекта проверять, есть ли он в этом массиве или нет?.
Цитата:
Разбираться там особо не надо. В этих случаях плеер исключение выкидывает с указанием места где закольцевалось.
Ну, а дальше то, что делать? Убирать закольцованность? или что Вы предлагаете? Я думаю проще заменить Dumper, чем что-то в своем коде (а может и не своем) переписывать.
Обновил(-а) Inet_PC 24.05.2012 в 09:29
Старый 24.05.2012 11:58 fish_r вне форума
fish_r
 
Аватар для fish_r
Цитата:
Не понимаю в чем проблема, почему нельзя просто в массив запоминать всех тех, кого уже разобрали и перед разбором очередного объекта проверять, есть ли он в этом массиве или нет?.
А если во время обработки одного запроса поступит другой, третий, пятый и т.д. Это статик. Он в единственном числе.
Старый 24.05.2012 12:08 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
Вы еще и меня в это вмешали!
Цитата:
Недавно был здесь ( на флешере ) блог MikroAcse на тему трейсов непростых объектов ( или объектов непростого типа). Там он приводил сыренький скрипт такого трейса, а в постах были интересные комментарии и подсказки. Блога нет, и скрипт он кажется до ума не довёл.
Старый 24.05.2012 12:23 fish_r вне форума
fish_r
 
Аватар для fish_r
Цитата:
Вы еще и меня в это вмешали!
Вмешали . Ну был же? И не довёл же? ( я у тебя на сайте смотрел )
Старый 24.05.2012 12:41 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
Цитата:
И не довёл же?
Да, не довел. А все потому, что для меня функционала достаточно.
Цитата:
( я у тебя на сайте смотрел )
Ты про блог?
Я его уже давно забросил!
Сейчас я дорабатываю версию MikroAcse ActionScript 3.0 Library 0.7, а в блоге все еще версия 0.3
Старый 24.05.2012 12:48 Inet_PC вне форума
Inet_PC
Цитата:
А если во время обработки одного запроса поступит другой, третий, пятый и т.д. Это статик. Он в единственном числе.
Ничего не понял, можно пример?
Старый 24.05.2012 14:34 fish_r вне форума
fish_r
 
Аватар для fish_r
Не знаю, какой пример нужен. Объекты придется хранить в поле класса, так? А при повторном вызове, когда предыдущая процедура разбора ещё не закончена, содержимое этого поля будет содержать объекты относящиеся к предыдущему вызову, а пополняться объектами текущего и предыдущего, каша будет.
Старый 24.05.2012 14:55 etc вне форума
etc
 
Аватар для etc
Замкнутые ссылки можно было у Блуда посмотреть, как решаются.
Старый 24.05.2012 15:10 fish_r вне форума
fish_r
 
Аватар для fish_r
Цитата:
Замкнутые ссылки можно было у Блуда посмотреть, как решаются.
Кстати, да. Спасибо. Просто я ещё не уверен, что проблема действительно критическая.
У Блуда, скорее всего, тоже всё не просто, а усложнять очень не хочется.
Старый 24.05.2012 15:30 TanaTiX вне форума
TanaTiX
 
Аватар для TanaTiX
fish_r, ИМХО надуманная проблема.
Старый 25.05.2012 01:29 fish_r вне форума
fish_r
 
Аватар для fish_r
update

Класс по прежнему не умеет обрабатывать объекты с циклическими ссылками. Но непрерывная его
работа ограничена 0.228 частью секунды ( потом правда ещё минуту выводится трейс, если пользоваться ИДЕ, но зато лог файл не усекается)

Это конечно можно произвольно изменять.
Обновил(-а) fish_r 28.05.2012 в 19:26
Старый 25.05.2012 10:38 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
У тебя все так запутанно.

Объекты внутри объектов.
Код AS3:
import com.mikroacse.utils.log.Tracer;
var o:Object = { num:1, str:'hello', arr:['hi', 'welcome'], obj:{ num:1, str:'hello', arr:['hi', 'welcome'] }, num2:1, str2:'2' };
Tracer.viewObject(o, false);
Код AS3:
[1] arr is Array:
	[1]  hi  > [class String]
	[2]  welcome  > [class String]
[2] obj is Object:
	[1] arr is Array:
		[1]  hi  > [class String]
		[2]  welcome  > [class String]
	[2] str: hello > [class String]
	[3] num: 1 > [class Number]
[3] num2: 1 > [class Number]
[4] str: hello > [class String]
[5] str2: 2 > [class String]
[6] num: 1 > [class Number]
Обновил(-а) MikroAcse 25.05.2012 в 13:46
Старый 25.05.2012 10:42 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
Многомерные массивы.
Код AS3:
import com.mikroacse.utils.log.Tracer;
var a:Array = [['hello', ['welcome', [1, [2, [3, ['hi', ['i am', ['mikroacse']]]]]]]]];
Tracer.viewArray(a, false);
Код AS3:
[1]  [hello,welcome,1,2,3,hi,i am,mikroacse] is Array:
	[1]  hello  > [class String]
	[2]  [welcome,1,2,3,hi,i am,mikroacse] is Array:
		[1]  welcome  > [class String]
		[2]  [1,2,3,hi,i am,mikroacse] is Array:
			[1]  1  > [class Number]
			[2]  [2,3,hi,i am,mikroacse] is Array:
				[1]  2  > [class Number]
				[2]  [3,hi,i am,mikroacse] is Array:
					[1]  3  > [class Number]
					[2]  [hi,i am,mikroacse] is Array:
						[1]  hi  > [class String]
						[2]  [i am,mikroacse] is Array:
							[1]  i am  > [class String]
							[2]  [mikroacse] is Array:
								[1]  mikroacse  > [class String]
Обновил(-а) MikroAcse 25.05.2012 в 10:49
Старый 25.05.2012 11:41 fish_r вне форума
fish_r
 
Аватар для fish_r
У тебя аккуратнее, есть похоже смысл отказаться от длины строки и разносить табом...
Старый 25.05.2012 13:52 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
Цитата:
Класс не умеет обрабатывать объекты с циклическими ссылками.
Код AS3:
var o:Object = { };
o.o = o;
Tracer.viewObject(o, false);
Вывод:
Код AS3:
[1] o: [object Object] > [class Object]
Для этого достаточно одной лишь проверки:
Код AS3:
if(ДанныйОбъект[параметр] != ДанныйОбъект)
Обновил(-а) MikroAcse 25.05.2012 в 13:56
Старый 25.05.2012 14:10 ChuwY вне форума
ChuwY
 
Аватар для ChuwY
Окей а если ссылка на ДанныйОбъект не у параметра, а у параметра параметра?
Старый 25.05.2012 14:26 gloomyBrain вне форума
gloomyBrain
 
Аватар для gloomyBrain
Да все уже описали выше, у blooddy отличное решение - создать слварь и каждый объект пихать в него. Если объект в словаре уже есть - то это ссылка и трейсить его не нужно.
Старый 25.05.2012 14:28 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
Цитата:
Окей а если ссылка на ДанныйОбъект не у параметра, а у параметра параметра?
Вот это уже проблема. Но разве это встречается в реальной жизни?
Старый 25.05.2012 15:52 TanaTiX вне форума
TanaTiX
 
Аватар для TanaTiX
MikroAcse, постоянно.
Старый 25.05.2012 17:17 MikroAcse вне форума
MikroAcse
 
Аватар для MikroAcse
Цитата:
MikroAcse, постоянно.
Ок. Воспользуюсь способом blooddy.
 

 


Часовой пояс GMT +4, время: 19:41.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2022, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.