示例#1
0
		/// <summary>
		/// Find expression type in function context
		/// </summary>
		/// <param name="expression">To evaluate</param>
		/// <param name="context">In context</param>
		/// <param name="inClass">In class</param>
		/// <param name="complete">Complete (sub-expression) or partial (dot-completion) evaluation</param>
		/// <returns>Class/member struct</returns>
		static private ASResult EvalExpression(string expression, ASExpr context, ASClass inClass, bool complete)
		{
			DebugConsole.Trace("** EvalExpression");
			DebugConsole.Trace(expression);
			ASResult notFound = new ASResult();
			Match mSub = null;
			string[] tokens = expression.Split('.');
			
			// eval first token
			string token = tokens[0];
			ASResult head;
			if (token.StartsWith("#"))
			{
				mSub = re_sub.Match(token);
				if (mSub.Success)
				{
					string subExpr = context.SubExpressions[ Convert.ToInt16(mSub.Groups["index"].Value) ];
					// parse sub expression
					subExpr = subExpr.Substring(1,subExpr.Length-2).Trim();
					ASExpr subContext = new ASExpr();
					subContext.SubExpressions = ExtractedSubex = new StringCollection();
					subExpr = re_balancedParenthesis.Replace(subExpr, new MatchEvaluator(ExtractSubex));
					Match m = re_refineExpression.Match(subExpr);
					if (!m.Success) return notFound;
					subExpr = re_dot.Replace( re_whiteSpace.Replace(m.Value, " ") , ".").Trim();
					int space = subExpr.LastIndexOf(' ');
					if (space > 0) subExpr = subExpr.Substring(space+1);
					// eval sub expression
					head = EvalExpression(subExpr, subContext, inClass, true);
					if (head.Member != null) 
						head.Class = ASContext.FindClassFromName(head.Member.Type, head.Class);
				}
				else 
				{
					token = token.Substring(token.IndexOf('~')+1);
					head = EvalVariable(token, context, inClass);
				}
			}
			else head = EvalVariable(token, context, inClass);
			
			// no head, exit
			if (head.IsNull()) return notFound;
			if (!head.IsStatic)
				DebugConsole.Trace(0+" "+token+":"+head.Class.ClassName);
			else if (head.Member != null)
				DebugConsole.Trace(0+" "+token+":"+head.Class.ClassName);
			else 
				DebugConsole.Trace(0+" "+token+"="+head.Class.ClassName);
			
			// eval tail
			int n = tokens.Length;
			if (!complete) n--;
			// context
			ASResult step = head;
			ASClass resultClass = head.Class;
			// look for static or dynamic members?
			FlagType mask = (head.IsStatic) ? FlagType.Static : FlagType.Dynamic;
			// look for public only members?
			ASClass curClass = ASContext.CurrentClass;
			if (!FriendClasses(curClass, step.Class)) 
				mask |= FlagType.Public;
			
			// explore
			for (int i=1; i<n; i++)
			{
				resultClass = step.Class;
				token = tokens[i];
				DebugConsole.Trace(i+" "+token+" "+mask);
				FindMember(token, resultClass, step, mask);
				if (step.Class == null)
					return step;
				if (!step.IsStatic) //(resultClass.Flags != FlagType.Package) && ((step.Class.Flags & FlagType.Class) == 0))
				{
					if ((mask & FlagType.Static) > 0) 
					{
						mask -= FlagType.Static;
						mask |= FlagType.Dynamic;
					}
				}
				if (!FriendClasses(curClass, step.Class))
				    mask |= FlagType.Public;
			}
			// eval package
			if (step.Class.Flags == FlagType.Package)
			{
				DebugConsole.Trace("Complete package "+step.Class.ClassName);
				step.Class.Package = ASContext.FindPackage(step.Class.ClassName, true);
			}
			return step;
		}
示例#2
0
		/// <summary>
		/// Complete object member
		/// </summary>
		/// <param name="Sci">Scintilla control</param>
		/// <param name="autoHide">Don't keep the list open if the word does not match</param>
		/// <returns>Auto-completion has been handled</returns>
		static private bool HandleDotCompletion(ScintillaNet.ScintillaControl Sci, bool autoHide)
		{
			// get expression at cursor position
			int position = Sci.CurrentPos;
			ASExpr expr = GetExpression(Sci, position);
			if (expr.Value == null)
				return true;
			int dotIndex = expr.Value.LastIndexOf('.');
			if (dotIndex == 0) return true;
			string tail = (dotIndex >= 0) ? expr.Value.Substring(dotIndex+1) : expr.Value;
			
			DebugConsole.Trace("? "+dotIndex+" '"+expr.separator+"' "+expr.Keyword+" ."+tail);
			// complete keyword
			if (dotIndex < 0)
			{
				if (expr.Keyword == "new") return HandleNewCompletion(Sci, expr.Value, autoHide);
				else if (expr.separator == ':') {
					if (HandleColonCompletion(Sci, expr.Value, autoHide)) return true;
				}
				else if (expr.Keyword == "import")
					return HandleImportCompletion(Sci, expr.Value, autoHide);
				else if ((expr.Keyword == "extends") || (expr.Keyword == "implements"))
					return HandleNewCompletion(Sci, expr.Value, autoHide);
			}
			else if ((expr.ContextBody == null) && (expr.separator != ':') && (expr.separator != '=')
			         && (expr.Keyword != "import") && (expr.Keyword != "extends") && (expr.Keyword != "implements") )
				return true;
			
			// complete declaration
			if ((expr.ContextBody == null) && 
			    ((expr.separator == ';') || (expr.separator == ' ') || (expr.separator == '}') || (expr.separator == '{')))
			{
				if (expr.Value.IndexOf('#') >= 0) return true;
				else 
				{
					string text = " "+ASClassParser.CleanClassSource(Sci.GetText(Sci.CurrentPos), null)+" ";
					if (Regex.IsMatch(text, "[\\s](class|interface)[\\s]"))
					{
						DebugConsole.Trace("Match class");
						Match m = Regex.Match(text, "[\\s](class|interface)[\\s]+"+ASContext.CurrentClass.ClassName+"[\\s{]");
						if (m.Success)
						{
							if (text.Substring(m.Index).IndexOf('{') > 0)
								return HandleDeclarationCompletion(Sci, "function private public static var", tail, autoHide);
							else if ((expr.Keyword != "extends") && (expr.Keyword != "implements"))
								return HandleDeclarationCompletion(Sci, "extends implements", tail, autoHide);
						}
						else return true;
					}
					else if (expr.Keyword == "class") return true;
					else if (dotIndex < 0) return HandleDeclarationCompletion(Sci, "import", tail, autoHide);
				}
			}
			
			DebugConsole.Trace("** Complete expression '"+expr.separator+"' "+expr.Value.Length);
			DebugConsole.Trace(expr.Value);
			
			// Context
			expr.LocalVars = ParseLocalVars(expr);
			ASClass cClass = ASContext.CurrentClass; 
			ASResult result;
			ASClass tmpClass;
			if (dotIndex > 0)
			{
				// Expression before cursor
				result = EvalExpression(expr.Value, expr, cClass, false);
				if (result.IsNull())
					return true;
				tmpClass = result.Class;
			}
			else 
			{
				result = new ASResult();
				tmpClass = cClass;
			}
			ASMemberList mix = new ASMemberList();
			// local vars are the first thing to try
			if ((result.IsNull() || (dotIndex < 0)) && (expr.ContextFunction != null)) 
				mix.Merge(expr.LocalVars);
			
			// packages
			if (tmpClass.Package != null)
				mix.Merge(tmpClass.Package);
			
			// get all members
			FlagType mask = 0;
			if ((expr.ContextFunction != null) || (expr.separator != ':'))
			{
				// user setting may ask to hide some members
				bool limitMembers = ASContext.HideIntrinsicMembers || (autoHide && !ASContext.AlwaysShowIntrinsicMembers);
				// static or dynamic members?
				if (!result.IsNull()) 
					mask = (result.IsStatic) ? FlagType.Static : FlagType.Dynamic;
				// show private member of current class only only 
				if (!FriendClasses(cClass, tmpClass))
					mask |= FlagType.Public;
				DebugConsole.Trace("Filter members by: "+mask);
				
				// explore members
				bool classExtend = false;
				if (!limitMembers || (tmpClass.ClassName != "Object"))
				while ((tmpClass != null) && (!tmpClass.IsVoid()))
				{
					tmpClass.Sort();
					// add members
					mix.Merge(tmpClass.Methods, mask, classExtend);
					// remove constructor methods
					foreach(ASMember meth in tmpClass.Methods)
					if ((meth.Flags & FlagType.Constructor) > 0) {
						mix.Remove(meth);
						break;
					}
					mix.Merge(tmpClass.Properties, mask, classExtend);
					mix.Merge(tmpClass.Vars, mask, classExtend);
					if (result.IsStatic && (tmpClass.Package != null))
					{
						DebugConsole.Trace("Class is package "+tmpClass.ClassName);
						mix.Merge(tmpClass.Package, 0);
					}
					tmpClass = tmpClass.Extends;
					if (tmpClass != null)
					{
						// static members not inherited in AS3 
						classExtend = tmpClass.IsAS3;

						if (((tmpClass.Flags & FlagType.Intrinsic) == FlagType.Intrinsic)
					    	&& (tmpClass.FileName.StartsWith(ASContext.TopLevelClassPath)))
						{
							if (limitMembers)
								tmpClass = null;
						}
					}
				}
			}
			// known classes / toplevel vars/methods
			if (result.IsNull() || (dotIndex < 0))
			{
				mix.Merge(cClass.ToASMember());
				mix.Merge(cClass.Imports);
				mix.Merge(ASContext.TopLevel.Imports);
				mix.Merge(ASContext.TopLevel.Methods);
				mix.Merge(ASContext.TopLevel.Vars);
				mix.Merge(ASContext.GetBasePackages());
			}
			
			// show
			ArrayList list = new ArrayList();
			foreach(ASMember member in mix)
				list.Add(new MemberItem(member));
			CompletionList.Show(list, autoHide, tail);
			return true;
		}
示例#3
0
		/// <summary>
		/// Match token to a class' member
		/// </summary>
		/// <param name="token">To match</param>
		/// <param name="inClass">In given class</param>
		/// <param name="result">Class/Member struct</param>
		static private void FindMember(string token, ASClass inClass, ASResult result, FlagType mask)
		{
			DebugConsole.Trace("FindMember "+token+" "+mask);
			ASMember found = null;
			ASClass tmpClass = inClass;
			if (inClass == null) return;
			// variable
			int p = token.IndexOf('#');
			if (p < 0)
			{
				// member
				while ((tmpClass != null) && !tmpClass.IsVoid())
				{
					found = tmpClass.Properties.Search(token, mask);
					if (found != null) break;
					found = tmpClass.Vars.Search(token, mask);
					if (found != null) break;
					found = tmpClass.Methods.Search(token, mask);
					if (found != null) 
					{
						// static members not inherited in AS3
						if (tmpClass != inClass && (found.Flags & FlagType.Static) > 0 && inClass.IsAS3)
							return;
						//DebugConsole.Trace("Method of "+tmpClass.ClassName);
						result.Member = found;
						if ((result.Member.Flags & FlagType.Constructor) > 0)
						{
							result.Class = tmpClass;
							result.IsStatic = true;
						}
						else 
						{
							result.inClass = tmpClass;
							result.Class = ASContext.FindClassFromName("Function", null);
							result.IsStatic = false; //((found.Flags & FlagType.Static) > 0);
						}
						//DebugConsole.Trace("Found static "+found.Name+":"+result.Class.ClassName+" in "+tmpClass.ClassName);
						return;
					}
					tmpClass = tmpClass.Extends;
				}
			}
			// method
			else 
			{
				token = token.Substring(0,p);
				while ((tmpClass != null) && !tmpClass.IsVoid())
				{
					found = tmpClass.Methods.Search(token, mask);
					if (found != null) 
					{
						// static members not inherited in AS3
						if (tmpClass != inClass && (found.Flags & FlagType.Static) > 0 && inClass.IsAS3)
							return;
						
						if ((found.Flags & FlagType.Constructor) > 0)
						{
							result.Class = tmpClass;
							result.Member = found;
							result.IsStatic = false;
							return;
						}
						break;
					}
					tmpClass = tmpClass.Extends;
				}
			}
			
			// result found!
			if (found != null)
			{
				result.inClass = tmpClass;
				result.Class = ASContext.FindClassFromName(found.Type, tmpClass);
				result.Member = found;
				result.IsStatic = false; //((found.Flags & FlagType.Static) > 0);
				DebugConsole.Trace("Found "+found.Name+":"+result.Class.ClassName+" in "+tmpClass.ClassName);
				return;
			}
			// try subpackages
			else if (inClass.Package != null)
			{
				DebugConsole.Trace("Find "+token+" as "+inClass.ClassName+"."+token);
				result.Class = ASContext.FindClassFromName(inClass.ClassName.Replace(System.IO.Path.DirectorySeparatorChar,'.')+"."+token, null);
				if (!result.Class.IsVoid()) 
					return;
				
				// sub packages?
				ASMemberList list = ASContext.FindPackage(inClass.ClassName, false);
				if (list != null || inClass.Flags == FlagType.Package)
				{
					result.Class = new ASClass();
					result.Class.ClassName = inClass.ClassName+System.IO.Path.DirectorySeparatorChar+token;
					result.Class.Flags = FlagType.Package;
					result.Class.Package = list;
					result.IsStatic = true;
					return;
				}
			}
			
			// not found
			result.Class = null;
			result.Member = null;
			DebugConsole.Trace(token+" not found in "+inClass.ClassName);
		}
示例#4
0
		/*/// <summary>
		/// List implicit known classes to a class: ie. the class, the extended class, implemented classes
		/// UPDATE: MTASC doesn't automatically known the extended classes
		/// </summary>
		/// <param name="cClass">Reference</param>
		/// <returns>List of members</returns>
		static private ASMemberList GetContextClassesList(ASClass cClass)
		{
			// current class
			ASMemberList list = new ASMemberList();
			list.Add(cClass.ToASMember());
			
			// inheritance
			ASClass tmpClass = cClass.Extends;
			while(tmpClass != null && !tmpClass.IsVoid() 
			    && !tmpClass.FileName.StartsWith(ASContext.TopLevelClassPath))
			{
				list.Add(tmpClass.ToASMember());
				tmpClass = tmpClass.Extends;
			}
			if (list.Count > 1) 
				list.Sort();
			
			// TODO  add other implicitly known classes from the classpath, like interfaces
			return list;
		}*/
		#endregion
		
		#region tooltips formatting
		static public string GetToolTipText(ASResult result)
		{
			if ((result.Member != null) && (result.inClass != null))
				{
					string text = MemberTooltipText(result.Member, result.inClass);
					if (result.inClass == ASContext.TopLevel)
						text = text.Substring(0, text.IndexOf('\n'));
					return text;
				}
				else if ((result.Member != null) && ((result.Member.Flags & FlagType.Constructor) != FlagType.Constructor))
				{
					return ASClass.MemberDeclaration(result.Member);
				}
				else if (result.inClass != null)
				{
					return ASClass.ClassDeclaration(result.inClass);
				}
				else if (result.Class != null) 
				{
					return ASClass.ClassDeclaration(result.Class);
				}
				else return null;
		}
示例#5
0
		/// <summary>
		/// Find variable type in function context 
		/// </summary>
		/// <param name="token">Variable name</param>
		/// <param name="context">In context</param>
		/// <param name="inClass">In class</param>
		/// <returns>Class/member struct</returns>
		static private ASResult EvalVariable(string token, ASExpr context, ASClass inClass)
		{
			DebugConsole.Trace("EvalVariable "+token);
			ASResult result = new ASResult();
			
			// local vars
			if (context.LocalVars != null)
			foreach(ASMember var in context.LocalVars)
			{
				if (var.Name == token)
				{
					result.inClass = null;
					result.Class = ASContext.FindClassFromName(var.Type, inClass);
					result.Member = var;
					return result;
				}
			}
			
			// method parameters
			if (context.ContextFunction != null)
			{
				Match param = Regex.Match(context.ContextFunction, "[(,][\\s]*"+Regex.Escape(token)+"[\\s:,)]");
				if (param.Success)
				{
					//DebugConsole.Trace("Method param "+token);
					param = Regex.Match(context.ContextFunction, "[(,][\\s]*"+Regex.Escape(token)+"[\\s]*:[\\s]*(?<type>[^\\s,)]*)");
					if (param.Success && (param.Groups["type"].Value.Length > 0))
					{
						//DebugConsole.Trace("Type "+param.Groups["type"].Value);
						result.Class = ASContext.FindClassFromName(param.Groups["type"].Value, inClass);
					}
					return result;
				}
			}
			
			// class members
			FindMember(token, inClass, result, 0);
			if (!result.IsNull())
				return result;
			
			// top-level elements
			if (!ASContext.TopLevel.IsVoid())
			{
				FindMember(token, ASContext.TopLevel, result, 0);
				if (!result.IsNull())
					return result;
				// special _levelN
				if (token.StartsWith("_") && re_level.IsMatch(token))
				{
					result.Class = ASContext.FindClassFromName("MovieClip", null);
					return result;
				}
			}
			
			// classes
			int p = token.IndexOf('#');
			string ctoken = (p > 0) ? token.Substring(0,p) : token;
			ASClass aClass = ASContext.FindClassFromName(ctoken, inClass);
			if (!aClass.IsVoid())
			{
				result.Class = aClass;
				result.IsStatic = (p < 0);
				return result;
			}
			
			// packages folders
			ASMemberList package = ASContext.FindPackage(token, false);
			if (package != null)
			{
				result.Class = new ASClass();
				result.Class.ClassName = token;
				result.Class.Flags = FlagType.Package;
				result.Class.Package = package;
				result.IsStatic = true;
			}
			return result;
		}