static private bool HandleColonCompletion(ScintillaNet.ScintillaControl Sci, string tail, bool autoHide) { DebugConsole.Trace("** Complete: ':'<class>"); // Context ASClass cClass = ASContext.CurrentClass; // Valid statement int position = Sci.CurrentPos-1; string keyword = null; int stylemask = (1 << Sci.StyleBits) -1; char c; while (position > 0) { position--; c = (char)Sci.CharAt(position); if ((c == '{') || (c == '=')) return false; else if ((Sci.StyleAt(position) & stylemask) == 19) { keyword = GetWordLeft(Sci, ref position); DebugConsole.Trace("'"+keyword+"'"); break; } } if (keyword != "var" && keyword != "function" && keyword != "get" && keyword != "set" && keyword != "const") return false; // Consolidate known classes ASMemberList known = new ASMemberList(); known.Merge(cClass.ToASMember()); known.Merge(cClass.Imports); known.Merge(ASContext.TopLevel.Imports); known.Merge(ASContext.GetBasePackages()); // show ArrayList list = new ArrayList(); foreach(ASMember member in known) list.Add(new MemberItem(member)); CompletionList.Show(list, autoHide, tail); return true; }
/// <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; }
static private bool HandleNewCompletion(ScintillaNet.ScintillaControl Sci, string tail, bool autoHide) { DebugConsole.Trace("** Complete: new <class>"); // Context ASClass cClass = ASContext.CurrentClass; // Consolidate known classes ASMemberList known = new ASMemberList(); known.Merge(cClass.ToASMember()); known.Merge(cClass.Imports); known.Merge(ASContext.TopLevel.Imports); known.Merge(ASContext.GetBasePackages()); // show ArrayList list = new ArrayList(); foreach(ASMember member in known) list.Add(new MemberItem(member)); CompletionList.Show(list, autoHide, tail); return true; }
/// <summary> /// Parse function body for local var definitions /// TODO ASComplete: parse coma separated local vars definitions /// </summary> /// <param name="expression">Expression source</param> /// <returns>Local vars dictionnary (name, type)</returns> static public ASMemberList ParseLocalVars(ASExpr expression) { ASMemberList vars = new ASMemberList(); if ((expression.ContextBody == null) || (expression.ContextBody.Length == 0)) return vars; // parse MatchCollection mcVars = re_variable.Matches(";"+expression.ContextBody); Match mVar; Match mType; string type; ASMember var; foreach(Match m in mcVars) { mVar = re_splitVariable.Match(m.Value); if (!mVar.Success) continue; mType = re_variableType.Match(mVar.Groups["type"].Value); if (mType.Success) type = mType.Groups["type"].Value; else type = "Object"; var = new ASMember(); var.Flags = FlagType.Variable | FlagType.Dynamic; var.Name = mVar.Groups["pname"].Value; var.Type = type; vars.Add(var); } // method parameters vars.Merge( ParseMethodParameters(expression.ContextFunction) ); return vars; }