static public bool OnChar(ScintillaNet.ScintillaControl Sci, int Value, int position, int style) { if (style == 3 || style == 124) { switch (Value) { // documentation tag case '@': return HandleDocTagCompletion(Sci); // documentation bloc case '*': if ((position > 2) && (Sci.CharAt(position-3) == '/') && (Sci.CharAt(position-2) == '*') && ((position == 3) || (Sci.BaseStyleAt(position-4) != 3))) HandleBoxCompletion(Sci, position); break; } } return false; }
private static void ConvertToConst(ClassModel inClass, ScintillaNet.ScintillaControl Sci, MemberModel member, bool detach) { String suggestion = "NEW_CONST"; String label = TextHelper.GetString("ASCompletion.Label.ConstName"); String title = TextHelper.GetString("ASCompletion.Title.ConvertToConst"); Hashtable info = new Hashtable(); info["suggestion"] = suggestion; info["label"] = label; info["title"] = title; DataEvent de = new DataEvent(EventType.Command, "LineEntryDialog", info); EventManager.DispatchEvent(null, de); if (!de.Handled) { return; } suggestion = (string)info["suggestion"]; int position = Sci.CurrentPos; MemberModel latest = null; int wordPosEnd = Sci.WordEndPosition(position, true); int wordPosStart = Sci.WordStartPosition(position, true); char cr = (char)Sci.CharAt(wordPosEnd); if (cr == '.') { wordPosEnd = Sci.WordEndPosition(wordPosEnd + 1, true); } else { cr = (char)Sci.CharAt(wordPosStart - 1); if (cr == '.') { wordPosStart = Sci.WordStartPosition(wordPosStart - 1, true); } } Sci.SetSel(wordPosStart, wordPosEnd); string word = Sci.SelText; Sci.ReplaceSel(suggestion); if (member == null) { detach = false; lookupPosition = -1; position = Sci.WordStartPosition(Sci.CurrentPos, true); Sci.SetSel(position, Sci.WordEndPosition(position, true)); } else { latest = FindLatest(FlagType.Constant, GetDefaultVisibility(), inClass) ?? FindLatest(FlagType.Variable, GetDefaultVisibility(), inClass); if (latest != null) { position = FindNewVarPosition(Sci, inClass, latest); } else { position = GetBodyStart(inClass.LineFrom, inClass.LineTo, Sci); detach = false; } if (position <= 0) return; Sci.SetSel(position, position); } contextToken = suggestion + ":Number = " + word + ""; GenerateVariable( NewMember(contextToken, member, FlagType.Variable | FlagType.Constant | FlagType.Static), position, detach); }
static public void ContextualGenerator(ScintillaNet.ScintillaControl Sci) { if (ASContext.Context is ASContext) (ASContext.Context as ASContext).UpdateCurrentFile(false); // update model lookupPosition = -1; int position = Sci.CurrentPos; if (Sci.BaseStyleAt(position) == 19) // on keyword return; int line = Sci.LineFromPosition(position); contextToken = Sci.GetWordFromPosition(position); contextMatch = null; FoundDeclaration found = GetDeclarationAtLine(Sci, line); string text = Sci.GetLine(line); bool suggestItemDeclaration = false; if (!String.IsNullOrEmpty(contextToken) && Char.IsDigit(contextToken[0])) { ShowConvertToConst(found); return; } ASResult resolve = ASComplete.GetExpressionType(Sci, Sci.WordEndPosition(position, true)); contextResolved = resolve; // ignore automatic vars (MovieClip members) if (resolve.Member != null && (((resolve.Member.Flags & FlagType.AutomaticVar) > 0) || (resolve.InClass != null && resolve.InClass.QualifiedName == "Object"))) { resolve.Member = null; resolve.Type = null; } if (found.inClass != ClassModel.VoidClass && contextToken != null) { if (resolve.Member == null && resolve.Type != null && (resolve.Type.Flags & FlagType.Interface) > 0) // implement interface { contextParam = resolve.Type.Type; ShowImplementInterface(found); return; } if (resolve.Member != null && !ASContext.Context.CurrentClass.IsVoid() && (resolve.Member.Flags & FlagType.LocalVar) > 0) // promote to class var { contextMember = resolve.Member; ShowPromoteLocalAndAddParameter(found); return; } } if (contextToken != null) { if (resolve.Member == null && resolve.Type == null) // import declaration { if (CheckAutoImport(found)) { return; } else { int stylemask = (1 << Sci.StyleBits) - 1; if (ASComplete.IsTextStyle(Sci.StyleAt(position - 1) & stylemask)) { suggestItemDeclaration = true; } } } } if (found.member != null) { // private var -> property if ((found.member.Flags & FlagType.Variable) > 0 && (found.member.Flags & FlagType.LocalVar) == 0) { // maybe we just want to import the member's non-imported type Match m = Regex.Match(text, String.Format(patternVarDecl, found.member.Name, contextToken)); if (m.Success) { contextMatch = m; ClassModel type = ASContext.Context.ResolveType(contextToken, ASContext.Context.CurrentModel); if (type.IsVoid() && CheckAutoImport(found)) return; } // create property ShowGetSetList(found); return; } // inside a function else if ((found.member.Flags & (FlagType.Function | FlagType.Getter | FlagType.Setter)) > 0 && resolve.Member == null && resolve.Type == null) { if (contextToken != null) { // "generate event handlers" suggestion string re = String.Format(patternEvent, contextToken); Match m = Regex.Match(text, re, RegexOptions.IgnoreCase); if (m.Success) { contextMatch = m; contextParam = CheckEventType(m.Groups["event"].Value); ShowEventList(found); return; } m = Regex.Match(text, String.Format(patternAS2Delegate, contextToken), RegexOptions.IgnoreCase); if (m.Success) { contextMatch = m; ShowDelegateList(found); return; } // suggest delegate if (ASContext.Context.Features.hasDelegates) { m = Regex.Match(text, @"([a-z0-9_.]+)\s*\+=\s*" + contextToken, RegexOptions.IgnoreCase); if (m.Success) { int offset = Sci.PositionFromLine(Sci.LineFromPosition(position)) + m.Groups[1].Index + m.Groups[1].Length; char c = (char)Sci.CharAt(offset); resolve = ASComplete.GetExpressionType(Sci, offset); if (resolve.Member != null) contextMember = ResolveDelegate(resolve.Member.Type, resolve.InFile); contextMatch = m; ShowDelegateList(found); return; } } } else { // insert a default handler name, then "generate event handlers" suggestion Match m = Regex.Match(text, String.Format(patternEvent, ""), RegexOptions.IgnoreCase); if (m.Success) { int regexIndex = m.Index + Sci.PositionFromLine(Sci.LineFromPosition(Sci.CurrentPos)); GenerateDefaultHandlerName(Sci, position, regexIndex, m.Groups["event"].Value, true); resolve = ASComplete.GetExpressionType(Sci, Sci.CurrentPos); if (resolve.Member == null || (resolve.Member.Flags & FlagType.AutomaticVar) > 0) { contextMatch = m; contextParam = CheckEventType(m.Groups["event"].Value); ShowEventList(found); } return; } // insert default delegate name, then "generate delegate" suggestion if (ASContext.Context.Features.hasDelegates) { m = Regex.Match(text, @"([a-z0-9_.]+)\s*\+=\s*", RegexOptions.IgnoreCase); if (m.Success) { int offset = Sci.PositionFromLine(Sci.LineFromPosition(position)) + m.Groups[1].Index + m.Groups[1].Length; resolve = ASComplete.GetExpressionType(Sci, offset); if (resolve.Member != null) { contextMember = ResolveDelegate(resolve.Member.Type, resolve.InFile); string delegateName = resolve.Member.Name; if (delegateName.StartsWith("on")) delegateName = delegateName.Substring(2); GenerateDefaultHandlerName(Sci, position, offset, delegateName, false); resolve = ASComplete.GetExpressionType(Sci, Sci.CurrentPos); if (resolve.Member == null || (resolve.Member.Flags & FlagType.AutomaticVar) > 0) { contextMatch = m; ShowDelegateList(found); } return; } } } } } // "Generate fields from parameters" suggestion if (found.member != null && (found.member.Flags & FlagType.Function) > 0 && found.member.Parameters != null && (found.member.Parameters.Count > 0) && resolve.Member != null && (resolve.Member.Flags & FlagType.ParameterVar) > 0) { contextMember = resolve.Member; ShowFieldFromParameter(found); return; } // "add to interface" suggestion if (resolve.Member != null && resolve.Member.Name == found.member.Name && line == found.member.LineFrom && ((found.member.Flags & FlagType.Function) > 0 || (found.member.Flags & FlagType.Getter) > 0 || (found.member.Flags & FlagType.Setter) > 0) && found.inClass != null && found.inClass.Implements != null && found.inClass.Implements.Count > 0) { string funcName = found.member.Name; int classPosStart = Sci.PositionFromLine(found.inClass.LineFrom); List<string> interfaces = new List<string>(); foreach (string interf in found.inClass.Implements) { bool skip = false; ClassModel cm = ASContext.Context.ResolveType(interf, ASContext.Context.CurrentModel); MemberList members = cm.Members; foreach (MemberModel m in members) { if (m.Name.Equals(funcName)) { skip = true; break; } } if (!skip) { interfaces.Add(interf); } } if (interfaces.Count > 0) { ShowAddInterfaceDefList(found, interfaces); return; } } // "assign var to statement" siggestion int curLine = Sci.LineFromPosition(Sci.CurrentPos); string ln = Sci.GetLine(curLine); if (ln.Trim().Length > 0 && ln.TrimEnd().Length <= Sci.CurrentPos - Sci.PositionFromLine(curLine)) { Regex re = new Regex("="); Match m = re.Match(ln); if (!m.Success) { ShowAssignStatementToVarList(found); } } } // suggest generate constructor / toString if (found.member == null && found.inClass != ClassModel.VoidClass && contextToken == null) { ClassModel cm = ASContext.Context.CurrentClass; MemberList members = cm.Members; bool hasConstructor = false; bool hasToString = false; foreach (MemberModel m in members) { if ((m.Flags & FlagType.Constructor) > 0) { hasConstructor = true; } if ((m.Flags & FlagType.Function) > 0 && m.Name.Equals("toString")) { hasToString = true; } } if (!hasConstructor || !hasToString) { ShowConstructorAndToStringList(found, hasConstructor, hasToString); return; } } if (resolve.Member != null && resolve.Type != null && resolve.Type.QualifiedName == "String" && found.inClass != null) { int lineStartPos = Sci.PositionFromLine(Sci.LineFromPosition(Sci.CurrentPos)); string lineStart = text.Substring(0, Sci.CurrentPos - lineStartPos); Match m = Regex.Match(lineStart, String.Format(@"new\s+(?<event>\w+)\s*\(\s*\w+", lineStart)); if (m.Success) { Group g = m.Groups["event"]; ASResult eventResolve = ASComplete.GetExpressionType(Sci, lineStartPos + g.Index + g.Length); if (eventResolve != null && eventResolve.Type != null) { ClassModel aType = eventResolve.Type; aType.ResolveExtends(); while (!aType.IsVoid() && aType.QualifiedName != "Object") { if (aType.QualifiedName == "flash.events.Event") { contextParam = eventResolve.Type.QualifiedName; ShowEventMetatagList(found); return; } aType = aType.Extends; } } } } // suggest declaration if (contextToken != null) { if (suggestItemDeclaration) { Match m = Regex.Match(text, String.Format(patternClass, contextToken)); if (m.Success) { contextMatch = m; ShowNewClassList(found); } else if (!found.inClass.IsVoid()) { m = Regex.Match(text, String.Format(patternMethod, contextToken)); if (m.Success) { contextMatch = m; ShowNewMethodList(found); } else ShowNewVarList(found); } } else { if (resolve != null && resolve.InClass != null && resolve.InClass.InFile != null && resolve.Member != null && (resolve.Member.Flags & FlagType.Function) > 0 && File.Exists(resolve.InClass.InFile.FileName) && !resolve.InClass.InFile.FileName.StartsWith(PathHelper.AppDir)) { Match m = Regex.Match(text, String.Format(patternMethodDecl, contextToken)); Match m2 = Regex.Match(text, String.Format(patternMethod, contextToken)); if (!m.Success && m2.Success) { contextMatch = m; ShowChangeMethodDeclList(found); } } else if (resolve != null && resolve.Type != null && resolve.Type.InFile != null && resolve.RelClass != null && File.Exists(resolve.Type.InFile.FileName) && !resolve.Type.InFile.FileName.StartsWith(PathHelper.AppDir)) { Match m = Regex.Match(text, String.Format(patternClass, contextToken)); if (m.Success) { contextMatch = m; ShowChangeConstructorDeclList(found); } } } } // TODO Empty line, show generators list? }
private static StatementReturnType GetStatementReturnType(ScintillaNet.ScintillaControl Sci, ClassModel inClass, string line, int startPos) { Regex target = new Regex(@"[;\s\n\r]*", RegexOptions.RightToLeft); Match m = target.Match(line); if (!m.Success) { return null; } line = line.Substring(0, m.Index); if (line.Length == 0) { return null; } line = ReplaceAllStringContents(line); ASResult resolve = null; int pos = -1; string word = null; int stylemask = (1 << Sci.StyleBits) - 1; ClassModel type = null; if (line[line.Length - 1] == ')') { pos = -1; int lastIndex = 0; int bracesBalance = 0; while (true) { int pos1 = line.IndexOf("(", lastIndex); int pos2 = line.IndexOf(")", lastIndex); if (pos1 != -1 && pos2 != -1) { lastIndex = Math.Min(pos1, pos2); } else if (pos1 != -1 || pos2 != -1) { lastIndex = Math.Max(pos1, pos2); } else { break; } if (lastIndex == pos1) { bracesBalance++; if (bracesBalance == 1) { pos = lastIndex; } } else if (lastIndex == pos2) { bracesBalance--; } lastIndex++; } } else { pos = line.Length; } if (pos != -1) { line = line.Substring(0, pos); pos += startPos; pos -= line.Length - line.TrimEnd().Length + 1; pos = Sci.WordEndPosition(pos, true); resolve = ASComplete.GetExpressionType(Sci, pos); if (resolve.IsNull()) resolve = null; word = Sci.GetWordFromPosition(pos); } IASContext ctx = inClass.InFile.Context; m = Regex.Match(line, "new\\s+([\\w\\d.<>,_$-]+)+(<[^]]+>)|(<[^]]+>)", RegexOptions.IgnoreCase); if (m.Success) { string m1 = m.Groups[1].Value; string m2 = m.Groups[2].Value; string cname; if (string.IsNullOrEmpty(m1) && string.IsNullOrEmpty(m2)) cname = m.Groups[0].Value; else cname = String.Concat(m1, m2); if (cname.StartsWith("<")) cname = "Vector." + cname; // literal vector type = ctx.ResolveType(cname, inClass.InFile); if (!type.IsVoid()) resolve = null; } else { char c = (char)Sci.CharAt(pos); if (c == '"' || c == '\'') { type = ctx.ResolveType("String", inClass.InFile); } else if (c == '}') { type = ctx.ResolveType(ctx.Features.objectKey, inClass.InFile); } else if (c == '>') { type = ctx.ResolveType("XML", inClass.InFile); } else if (c == ']') { resolve = ASComplete.GetExpressionType(Sci, pos + 1); if (resolve.Type != null) type = resolve.Type; else type = ctx.ResolveType(ctx.Features.arrayKey, inClass.InFile); resolve = null; } else if (word != null && Char.IsDigit(word[0])) { type = ctx.ResolveType(ctx.Features.numberKey, inClass.InFile); } else if (word == "true" || word == "false") { type = ctx.ResolveType(ctx.Features.booleanKey, inClass.InFile); } if (type != null && type.IsVoid()) type = null; } if (resolve == null) resolve = new ASResult(); if (resolve.Type == null) resolve.Type = type; return new StatementReturnType(resolve, pos, word); }
static public string GetWordLeft(ScintillaNet.ScintillaControl Sci, ref int position) { string word = ""; string exclude = "(){};,+*/\\=:.%\"<>"; bool skipWS = true; int style; int stylemask = (1 << Sci.StyleBits) -1; char c; while (position >= 0) { style = Sci.StyleAt(position) & stylemask; if (IsTextStyleEx(style)) { c = (char)Sci.CharAt(position); if (c <= ' ') { if (!skipWS) break; } else if (exclude.IndexOf(c) >= 0) break; else if (style != 6) { word = c+word; skipWS = false; } } position--; } return word; }
private static void ConvertToConst(ClassModel inClass, ScintillaNet.ScintillaControl Sci, MemberModel member, bool detach) { String suggestion = "NEW_CONST"; String label = TextHelper.GetString("ASCompletion.Label.ConstName"); String title = TextHelper.GetString("ASCompletion.Title.ConvertToConst"); Hashtable info = new Hashtable(); info["suggestion"] = suggestion; info["label"] = label; info["title"] = title; DataEvent de = new DataEvent(EventType.Command, "ProjectManager.LineEntryDialog", info); EventManager.DispatchEvent(null, de); if (!de.Handled) return; suggestion = (string)info["suggestion"]; int position = Sci.CurrentPos; MemberModel latest = null; int wordPosEnd = Sci.WordEndPosition(position, true); int wordPosStart = Sci.WordStartPosition(position, true); char cr = (char)Sci.CharAt(wordPosEnd); if (cr == '.') { wordPosEnd = Sci.WordEndPosition(wordPosEnd + 1, true); } else { cr = (char)Sci.CharAt(wordPosStart - 1); if (cr == '.') { wordPosStart = Sci.WordStartPosition(wordPosStart - 1, true); } } Sci.SetSel(wordPosStart, wordPosEnd); string word = Sci.SelText; Sci.ReplaceSel(suggestion); if (member == null) { detach = false; lookupPosition = -1; position = Sci.WordStartPosition(Sci.CurrentPos, true); Sci.SetSel(position, Sci.WordEndPosition(position, true)); } else { latest = GetLatestMemberForVariable(GeneratorJobType.Constant, inClass, Visibility.Private, new MemberModel("", "", FlagType.Static, 0)); if (latest != null) { position = FindNewVarPosition(Sci, inClass, latest); } else { position = GetBodyStart(inClass.LineFrom, inClass.LineTo, Sci); detach = false; } if (position <= 0) return; Sci.SetSel(position, position); } MemberModel m = NewMember(suggestion, member, FlagType.Variable | FlagType.Constant | FlagType.Static); m.Type = ASContext.Context.Features.numberKey; m.Value = word; GenerateVariable(m, position, detach); }
private static int GetContextOwnerEndPos(ScintillaNet.ScintillaControl Sci, int worsStartPos) { int pos = worsStartPos - 1; bool dotFound = false; while (pos > 0) { char c = (char) Sci.CharAt(pos); if (c == '.' && !dotFound) dotFound = true; else if (c == '\t' || c == '\n' || c == '\r' || c == ' ') { /* skip */ } else return dotFound ? pos + 1 : -1; pos--; } return pos; }
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> /// Find out in what context is a coma-separated expression /// </summary> /// <returns></returns> private static ComaExpression DisambiguateComa(ScintillaNet.ScintillaControl Sci, int position, int minPos) { ContextFeatures features = ASContext.Context.Features; // find block start '(' or '{' int parCount = 0; int braceCount = 0; int sqCount = 0; char c = (char)Sci.CharAt(position); bool wasPar = false; if (c == '{') { wasPar = true; position--; } while (position > minPos) { c = (char)Sci.CharAt(position); if (c == ';') { return ComaExpression.None; } else if ((c == ',' || c == '=') && wasPar) { return ComaExpression.AnonymousObject; } // var declaration else if (c == ':') { position--; string word = ASComplete.GetWordLeft(Sci, ref position); word = ASComplete.GetWordLeft(Sci, ref position); if (word == features.varKey) return ComaExpression.VarDeclaration; else continue; } // Array values else if (c == '[') { sqCount--; if (sqCount < 0) { return ComaExpression.ArrayValue; } } else if (c == ']') { if (wasPar) return ComaExpression.None; sqCount++; } // function declaration or parameter else if (c == '(') { parCount--; if (parCount < 0) { position--; string word1 = ASComplete.GetWordLeft(Sci, ref position); if (word1 == features.functionKey) return ComaExpression.FunctionDeclaration; // anonymous function string word2 = ASComplete.GetWordLeft(Sci, ref position); if (word2 == features.functionKey || word2 == features.setKey || word2 == features.getKey) return ComaExpression.FunctionDeclaration; // function declaration return ComaExpression.FunctionParameter; // function call } } else if (c == ')') { if (wasPar) return ComaExpression.None; parCount++; } // code block or anonymous object else if (c == '{') { braceCount--; if (braceCount < 0) { position--; string word1 = ASComplete.GetWordLeft(Sci, ref position); c = (word1.Length > 0) ? word1[word1.Length - 1] : (char)Sci.CharAt(position); if (c != ')' && c != '}' && !char.IsLetterOrDigit(c)) return ComaExpression.AnonymousObject; break; } } else if (c == '}') { if (wasPar) return ComaExpression.None; braceCount++; } else if (c == '?') return ComaExpression.AnonymousObject; position--; } return ComaExpression.None; }
/// <summary> /// Display method signature /// </summary> /// <param name="Sci">Scintilla control</param> /// <returns>Auto-completion has been handled</returns> static public bool HandleFunctionCompletion(ScintillaNet.ScintillaControl Sci) { // find method int position = Sci.CurrentPos-1; int parCount = 0; int braCount = 0; int comaCount = 0; int arrCount = 0; int style = 0; int stylemask = (1 << Sci.StyleBits) -1; char c; while (position >= 0) { style = Sci.StyleAt(position) & stylemask; if (style == 19) { string keyword = GetWordLeft(Sci, ref position); DebugConsole.Trace("Keyword "+keyword); if (!"new".StartsWith(keyword)) { position = -1; break; } } if (IsTextStyleEx(style)) { c = (char)Sci.CharAt(position); if (c == ';') { position = -1; break; } // skip {} () [] blocks if ( ((braCount > 0) && (c != '{')) || ((arrCount > 0) && (c != '[')) || ((parCount > 0) && (c != '('))) { position--; continue; } // new block if (c == '}') braCount++; else if (c == ']') arrCount++; else if (c == ')') parCount++; // block closed else if (c == '{') { if (braCount == 0) comaCount = 0; else braCount--; } else if (c == '[') { if (arrCount == 0) comaCount = 0; else arrCount--; } else if (c == '(') { if (--parCount < 0) // function start found break; } // new parameter reached else if (c == ',' && parCount == 0 && Sci.BaseStyleAt(position) != 6) comaCount++; } position--; } // continuing calltip ? if (HasCalltip()) { if (calltipPos == position) { ShowCalltip(Sci, comaCount); return true; } else InfoTip.Hide(); } else if (position < 0) return false; // get expression at cursor position ASExpr expr = GetExpression(Sci, position); DebugConsole.Trace("Expr: "+expr.Value); if (expr.Value == null || expr.Value.Length == 0 || expr.separator == ':' || (expr.Keyword == "function" && expr.separator == ' ')) return false; DebugConsole.Trace("** Display method parameters"); DebugConsole.Trace(expr.Value); // Context expr.LocalVars = ParseLocalVars(expr); ASClass aClass = ASContext.CurrentClass; // Expression before cursor ASResult result = EvalExpression(expr.Value, expr, aClass, true); // Show calltip if (!result.IsNull()) { ASMember method = result.Member; if (method == null) { string constructor = ASContext.GetLastStringToken(result.Class.ClassName,"."); method = result.Class.Methods.Search(constructor, FlagType.Constructor); if (method == null) return true; } else if ((method.Flags & FlagType.Function) == 0) return true; // calltip content calltipPos = position; calltipOffset = method.Name.Length; calltipDef = method.Name+"("+method.Parameters+")"; if (method.Type.Length > 0) calltipDef += " : "+method.Type; calltipMember = method; calltipDetails = UITools.ShowDetails; // show prevParam = ""; ShowCalltip(Sci, comaCount); } return true; }
/// <summary> /// Character written in editor /// </summary> /// <param name="Value">Character inserted</param> static public bool OnChar(ScintillaNet.ScintillaControl Sci, int Value, bool autoHide) { if (autoHide && !ASContext.HelpersEnabled) return false; try { int eolMode = Sci.EOLMode; // code auto if (((Value == 10) && (eolMode != 1)) || ((Value == 13) && (eolMode == 1))) { DebugConsole.Trace("Struct"); HandleStructureCompletion(Sci); return false; } // ignore repeated characters int position = Sci.CurrentPos; if ((Sci.CharAt(position-2) == Value) && (Sci.CharAt(position-1) == Value) && (Value != '*')) return false; // ignore text in comments & quoted text Sci.Colourise(0,-1); int stylemask = (1 << Sci.StyleBits) -1; int style = Sci.StyleAt(position-1) & stylemask; DebugConsole.Trace("style "+style); if (!IsTextStyle(style) && !IsTextStyle(Sci.StyleAt(position) & stylemask)) { // documentation completion if (ASContext.DocumentationCompletionEnabled && IsCommentStyle(style)) return ASDocumentation.OnChar(Sci, Value, position, style); else if (autoHide) return false; } // stop here if the class is not valid if (!ASContext.IsClassValid()) return false; // handle switch (Value) { case '.': return HandleDotCompletion(Sci, autoHide); case ' ': position--; string word = GetWordLeft(Sci, ref position); DebugConsole.Trace("Word? "+word); if (word.Length > 0) switch (word) { case "new": case "extends": case "implements": return HandleNewCompletion(Sci, "", autoHide); case "import": return HandleImportCompletion(Sci, "", autoHide); case "public": return HandleDeclarationCompletion(Sci, "function static var", "", autoHide); case "private": return HandleDeclarationCompletion(Sci, "function static var", "", autoHide); case "static": return HandleDeclarationCompletion(Sci, "function private public var", "", autoHide); } break; case ':': ASContext.UnsetOutOfDate(); bool result = HandleColonCompletion(Sci, "", autoHide); ASContext.SetOutOfDate(); return result; case '(': return HandleFunctionCompletion(Sci); case ')': if (InfoTip.CallTipActive) InfoTip.Hide(); return false; case '*': return CodeAutoOnChar(Sci, Value); } } catch (Exception ex) { ErrorHandler.ShowError("Completion error", ex); } // CodeAuto context if (!PluginCore.Controls.CompletionList.Active) LastExpression = null; return false; }
static private bool HandleDeclarationCompletion(ScintillaNet.ScintillaControl Sci, string words, string tail, bool autoHide) { DebugConsole.Trace("** Complete: declaration <"+words+">"); if (words.Length == 0) return false; int position = Sci.CurrentPos; // concat current word if DotCompletion sent us the previous word if (Sci.CharAt(position-1) <= 32) tail = ""; // does it need a tab? if ((words != "import") && (words.IndexOf("extends") < 0) && (words.IndexOf("implements") < 0)) { if (ASContext.CurrentClass.IsAS3 && words.IndexOf("var") > 0) { words = "const "+words; } int curLine = Sci.LineFromPosition(position); if (Sci.GetLineIndentation(curLine) == 0) { Sci.SetLineIndentation(curLine, Sci.TabWidth); if (Sci.IsUseTabs) position++; else position += Sci.TabWidth; Sci.SelectionStart = Sci.CurrentPos = position; } } // remove keywords already set words = " "+words+" "; string rem = GetWordLeft(Sci, ref position); while (rem.Length > 0) { if ((rem == "var") || (rem == "function") || (ASContext.CurrentClass.IsAS3 && (rem == "const"))) return true; else if (rem == "public") words = words.Replace(" private ", " "); else if (rem == "private") words = words.Replace(" public ", " "); words = words.Replace(" "+rem+" ", " "); rem = GetWordLeft(Sci, ref position); } words = words.Trim(); // build list string[] items = words.Split(' '); ArrayList known = new ArrayList(); foreach(string item in items) known.Add(new TemplateItem(item)); // show CompletionList.Show(known, autoHide, tail); return true; }
static private bool HandleStructureCompletion(ScintillaNet.ScintillaControl Sci) { try { int position = Sci.CurrentPos; int line = Sci.LineFromPosition(position); if (line == 0) return false; string txt = Sci.GetLine(line-1); int style = Sci.BaseStyleAt(position); int eolMode = Sci.EOLMode; // box comments if (IsCommentStyle(style) && (Sci.BaseStyleAt(position+1) == style)) { txt = txt.Trim(); if (txt.StartsWith("/*") || txt.StartsWith("*")) { Sci.ReplaceSel("* "); position = Sci.LineIndentPosition(line)+2; Sci.SetSel(position,position); return true; } } // braces else if (txt.TrimEnd().EndsWith("{") && (line > 1)) { // find matching brace int bracePos = Sci.LineEndPosition(line-1)-1; while ((bracePos > 0) && (Sci.CharAt(bracePos) != '{')) bracePos--; if (bracePos == 0 || Sci.BaseStyleAt(bracePos) != 10) return true; int match = Sci.SafeBraceMatch(bracePos); DebugConsole.Trace("match "+bracePos+" "+match); int start = line; int indent = Sci.GetLineIndentation(start-1); if (match > 0) { int endIndent = Sci.GetLineIndentation(Sci.LineFromPosition(match)); if (endIndent+Sci.TabWidth > indent) return false; } // find where to include the closing brace int startIndent = indent; int newIndent = indent+Sci.TabWidth; int count = Sci.LineCount; int lastLine = line; line++; while (line < count-1) { txt = Sci.GetLine(line).TrimEnd(); if (txt.Length != 0) { indent = Sci.GetLineIndentation(line); DebugConsole.Trace("indent "+(line+1)+" "+indent+" : "+txt); if (indent <= startIndent) break; lastLine = line; } else break; line++; } if (line >= count-1) lastLine = start; // insert closing brace DebugConsole.Trace("Insert at "+position); position = Sci.LineEndPosition(lastLine); Sci.InsertText(position, ASContext.MainForm.GetNewLineMarker(eolMode)+"}"); Sci.SetLineIndentation(lastLine+1, startIndent); return false; } } catch (Exception ex) { ErrorHandler.ShowError(ex.Message, ex); } return false; }
/// <summary> /// Some characters can fire code generation /// </summary> /// <param name="sci">Scintilla control</param> /// <param name="value">Character</param> /// <returns>Code was generated</returns> static private bool CodeAutoOnChar(ScintillaNet.ScintillaControl sci, int value) { if (!ASContext.AutoImportsEnabled) return false; int position = sci.CurrentPos; if (value == '*' && position > 1 && sci.CharAt(position-2) == '.' && LastExpression != null) { // context string key = LastExpression.Keyword; if (key != null && (key == "import" || key == "extends" || key == "implements" || key == "package")) return false; ASResult context = EvalExpression(LastExpression.Value, LastExpression, ASContext.CurrentClass, true); if (context.IsNull() || context.Class.Flags != FlagType.Package) return false; string package = LastExpression.Value; int startPos = LastExpression.Position; string check = ""; char c; while (startPos > LastExpression.PositionExpression && check.Length <= package.Length && check != package) { c = (char)sci.CharAt(--startPos); if (c > 32) check = c+check; } if (check != package) return false; // insert import string statement = "import "+package+"*;"+ASContext.MainForm.GetNewLineMarker(sci.EOLMode); int endPos = sci.CurrentPos; int line = 0; int curLine = sci.LineFromPosition(position); int firstLine = 0; bool found = false; string txt; Match mImport; while (line < curLine) { txt = sci.GetLine(line++).TrimStart(); // HACK insert imports after AS3 package declaration if (txt.StartsWith("package")) { statement = '\t'+statement; firstLine = (txt.IndexOf('{') < 0) ? line+1 : line; } else if (txt.StartsWith("import")) { found = true; // insérer dans l'ordre alphabetique mImport = ASClassParser.re_import.Match(txt); if (mImport.Success && String.Compare(mImport.Groups["package"].Value, package) > 0) { line--; break; } } else if (found) { line--; break; } } if (line == curLine) line = firstLine; position = sci.PositionFromLine(line); line = sci.FirstVisibleLine; sci.SetSel(position, position); sci.ReplaceSel(statement); // prepare insertion of the term as usual startPos += statement.Length; endPos += statement.Length; sci.SetSel(startPos, endPos); sci.ReplaceSel(""); sci.LineScroll(0, line-sci.FirstVisibleLine+1); // create classes list ASClass cClass = ASContext.CurrentClass; ArrayList list = new ArrayList(); foreach(ASMember import in cClass.Imports) if (import.Type.StartsWith(package)) list.Add(new MemberItem(import)); CompletionList.Show(list, false); return true; } return false; }
private static int GetContextOwnerEndPos(ScintillaNet.ScintillaControl Sci, int worsStartPos) { int pos = worsStartPos - 1; bool dotFound = false; while (pos > 0) { char c = (char) Sci.CharAt(pos); if (c == '.' && !dotFound) { dotFound = true; } else if (c == '\t' || c == '\n' || c == '\r' || c == ' ') { } else { if (dotFound) { return pos + 1; } else { return -1; } } pos--; } return pos; }
/// <summary> /// Find Actionscript expression at cursor position /// </summary> /// <param name="sci">Scintilla Control</param> /// <param name="position">Cursor position</param> /// <param name="ignoreWhiteSpace">Skip whitespace at position</param> /// <returns></returns> private static ASExpr GetExpression(ScintillaNet.ScintillaControl Sci, int position, bool ignoreWhiteSpace) { ASExpr expression = new ASExpr(); expression.Position = position; expression.Separator = ' '; // file's member declared at this position expression.ContextMember = ASContext.Context.CurrentMember; int minPos = 0; string body = null; if (expression.ContextMember != null) { minPos = Sci.PositionFromLine(expression.ContextMember.LineFrom); StringBuilder sbBody = new StringBuilder(); for (int i = expression.ContextMember.LineFrom; i <= expression.ContextMember.LineTo; i++) sbBody.Append(Sci.GetLine(i)).Append('\n'); body = sbBody.ToString(); //int tokPos = body.IndexOf(expression.ContextMember.Name); //if (tokPos >= 0) minPos += tokPos + expression.ContextMember.Name.Length; if ((expression.ContextMember.Flags & (FlagType.Function | FlagType.Constructor | FlagType.Getter | FlagType.Setter)) > 0) { expression.ContextFunction = expression.ContextMember; expression.FunctionOffset = expression.ContextMember.LineFrom; Match mStart = Regex.Match(body, "(\\)|[a-z0-9*.,-<>])\\s*{", RegexOptions.IgnoreCase); if (mStart.Success) { // cleanup function body & offset int pos = mStart.Index + mStart.Length; expression.BeforeBody = (position < Sci.PositionFromLine(expression.ContextMember.LineFrom) + pos); string pre = body.Substring(0, pos); for (int i = 0; i < pre.Length - 1; i++) if (pre[i] == '\r') { expression.FunctionOffset++; if (pre[i + 1] == '\n') i++; } else if (pre[i] == '\n') expression.FunctionOffset++; body = body.Substring(pos); } expression.FunctionBody = body; } else { int eqPos = body.IndexOf('='); expression.BeforeBody = (eqPos < 0 || position < Sci.PositionFromLine(expression.ContextMember.LineFrom) + eqPos); } } // get the word characters from the syntax definition string characterClass = ScintillaNet.ScintillaControl.Configuration.GetLanguage(Sci.ConfigurationLanguage).characterclass.Characters; // get expression before cursor ContextFeatures features = ASContext.Context.Features; int stylemask = (1 << Sci.StyleBits) - 1; int style = (position >= minPos) ? Sci.StyleAt(position) & stylemask : 0; StringBuilder sb = new StringBuilder(); StringBuilder sbSub = new StringBuilder(); int subCount = 0; char c = ' '; char c2; int startPos = position; int braceCount = 0; int sqCount = 0; int genCount = 0; bool hasGenerics = features.hasGenerics; bool hadWS = false; bool hadDot = ignoreWhiteSpace; bool inRegex = false; char dot = features.dot[features.dot.Length - 1]; while (position > minPos) { position--; style = Sci.StyleAt(position) & stylemask; if (style == 14) // regex literal { inRegex = true; } else if (!ASComplete.IsCommentStyle(style)) { c2 = c; c = (char)Sci.CharAt(position); // end of regex literal if (inRegex) { inRegex = false; if (expression.SubExpressions == null) expression.SubExpressions = new List<string>(); expression.SubExpressions.Add(""); sb.Insert(0, "RegExp.#" + (subCount++) + "~"); } // array access if (c == '[') { sqCount--; if (sqCount == 0) { if (sbSub.Length > 0) sbSub.Insert(0, '['); if (braceCount == 0) sb.Insert(0, ".[]"); continue; } if (sqCount < 0) { expression.Separator = ';'; break; } } else if (c == ']') { sqCount++; } // else if (c == '<' && hasGenerics) { genCount--; if (genCount < 0) { expression.Separator = ';'; break; } } // ignore sub-expressions (method calls' parameters) else if (c == '(') { braceCount--; if (braceCount == 0) { sbSub.Insert(0, c); expression.SubExpressions.Add(sbSub.ToString()); sb.Insert(0, ".#" + (subCount++) + "~"); // method call or sub expression int testPos = position - 1; string testWord = ASComplete.GetWordLeft(Sci, ref testPos); if (testWord == "return" || testWord == "case" || testWord == "defaut") { // ex: return (a as B).<complete> expression.Separator = ';'; expression.WordBefore = testWord; break; } else continue; } else if (braceCount < 0) { expression.Separator = ';'; int testPos = position - 1; string testWord = ASComplete.GetWordLeft(Sci, ref testPos); // anonymous function string testWord2 = ASComplete.GetWordLeft(Sci, ref testPos) ?? "null"; // regular function if (testWord == features.functionKey || testWord == "catch" || testWord2 == features.functionKey || testWord2 == features.getKey || testWord2 == features.setKey) { expression.Separator = ','; expression.coma = ComaExpression.FunctionDeclaration; } break; } } else if (c == ')') { if (!hadDot) { expression.Separator = ';'; break; } if (braceCount == 0) // start sub-expression { if (expression.SubExpressions == null) expression.SubExpressions = new List<string>(); sbSub = new StringBuilder(); } braceCount++; } else if (c == '>' && hasGenerics) { if (c2 == '.' || c2 == '(') genCount++; else break; } if (braceCount > 0 || sqCount > 0 || genCount > 0) { if (c == ';') // not expected: something's wrong { expression.Separator = ';'; break; } // build sub expression sbSub.Insert(0, c); continue; } // build expression if (c <= 32) { if (genCount == 0) hadWS = true; } else if (c == dot) { if (features.dot.Length == 2) hadDot = position > 0 && Sci.CharAt(position - 1) == features.dot[0]; else hadDot = true; sb.Insert(0, c); } else if (characterClass.IndexOf(c) >= 0) { if (hadWS && !hadDot) { expression.Separator = ' '; break; } hadWS = false; hadDot = false; sb.Insert(0, c); startPos = position; } else if (c == ';') { expression.Separator = ';'; break; } else if (hasGenerics && (genCount > 0 || c == '<')) { sb.Insert(0, c); } else if (c == '{') { expression.coma = DisambiguateComa(Sci, position, minPos); expression.Separator = (expression.coma == ComaExpression.None) ? ';' : ','; break; } else if (c == ',') { expression.coma = DisambiguateComa(Sci, position, minPos); expression.Separator = (expression.coma == ComaExpression.None) ? ';' : ','; break; } else if (c == ':') { expression.Separator = ':'; break; } else if (c == '=') { expression.Separator = '='; break; } else //if (hadWS && !hadDot) { if (c == '\'' || c == '"') expression.Separator = '"'; else expression.Separator = ';'; break; } } // string literals only allowed in sub-expressions else { if (braceCount == 0) // not expected: something's wrong { expression.Separator = ';'; break; } } } // check if there is a particular keyword if (expression.Separator == ' ') { expression.WordBefore = ASComplete.GetWordLeft(Sci, ref position); } // result expression.Value = sb.ToString(); expression.PositionExpression = startPos; return expression; }
private static StatementReturnType GetStatementReturnType(ScintillaNet.ScintillaControl Sci, ClassModel inClass, string line, int startPos) { Regex target = new Regex(@"[;\s\n\r]*", RegexOptions.RightToLeft); Match m = target.Match(line); if (!m.Success) { return null; } line = line.Substring(0, m.Index); if (line.Length == 0) { return null; } line = ReplaceAllStringContents(line); ASResult resolve = null; int pos = -1; string word = null; int stylemask = (1 << Sci.StyleBits) - 1; ClassModel type = null; if (line[line.Length - 1] == ')') { pos = -1; int lastIndex = 0; int bracesBalance = 0; while (true) { int pos1 = line.IndexOf("(", lastIndex); int pos2 = line.IndexOf(")", lastIndex); if (pos1 != -1 && pos2 != -1) { lastIndex = Math.Min(pos1, pos2); } else if (pos1 != -1 || pos2 != -1) { lastIndex = Math.Max(pos1, pos2); } else { break; } if (lastIndex == pos1) { bracesBalance++; if (bracesBalance == 1) { pos = lastIndex; } } else if (lastIndex == pos2) { bracesBalance--; } lastIndex++; } } else { pos = line.Length; } if (pos != -1) { line = line.Substring(0, pos); pos += startPos; pos -= line.Length - line.TrimEnd().Length + 1; pos = Sci.WordEndPosition(pos, true); resolve = ASComplete.GetExpressionType(Sci, pos); word = Sci.GetWordFromPosition(pos); } char c = (char)Sci.CharAt(pos); if (word != null && Char.IsDigit(word[0])) { type = inClass.InFile.Context.ResolveType("Number", inClass.InFile); } else if (word != null && (word == "true" || word == "false")) { type = inClass.InFile.Context.ResolveType("Boolean", inClass.InFile); } else if (!(ASComplete.IsTextStyle(Sci.StyleAt(pos - 1) & stylemask))) { type = inClass.InFile.Context.ResolveType("String", inClass.InFile); } else if (c == '}') { type = inClass.InFile.Context.ResolveType("Object", inClass.InFile); } else if (c == '>') { type = inClass.InFile.Context.ResolveType("XML", inClass.InFile); } else if (c == ']') { type = inClass.InFile.Context.ResolveType("Array", inClass.InFile); } if (resolve == null) { resolve = new ASResult(); } if (resolve.Type == null) { resolve.Type = type; } return new StatementReturnType(resolve, pos, word); }
static private string GetWordLeft(ScintillaNet.ScintillaControl Sci, ref int position) { string word = ""; string exclude = "(){};,+*/\\=:.%\"<>"; char c; while (position >= 0) { c = (char)Sci.CharAt(position); if (c <= ' ') break; else if (exclude.IndexOf(c) >= 0) break; else word = c+word; position--; } return word; }
public static int GetBodyStart(int lineFrom, int lineTo, ScintillaNet.ScintillaControl Sci, int pos) { int posStart = Sci.PositionFromLine(lineFrom); int posEnd = Sci.LineEndPosition(lineTo); Sci.SetSel(posStart, posEnd); List<char> characterClass = new List<char>(new char[] { ' ', '\r', '\n', '\t' }); string currentMethodBody = Sci.SelText; int nCount = 0; int funcBodyStart = pos; int extraLine = 0; if (pos == -1) { funcBodyStart = posStart + currentMethodBody.IndexOf('{'); extraLine = 1; } while (funcBodyStart <= posEnd) { char c = (char)Sci.CharAt(++funcBodyStart); if (c == '}') { int ln = Sci.LineFromPosition(funcBodyStart); int indent = Sci.GetLineIndentation(ln); if (lineFrom == lineTo || lineFrom == ln) { Sci.InsertText(funcBodyStart, Sci.NewLineMarker); Sci.SetLineIndentation(ln + 1, indent); ln++; } Sci.SetLineIndentation(ln, indent + Sci.Indent); Sci.InsertText(funcBodyStart, Sci.NewLineMarker); Sci.SetLineIndentation(ln + 1, indent); Sci.SetLineIndentation(ln, indent + Sci.Indent); funcBodyStart = Sci.LineEndPosition(ln); break; } else if (!characterClass.Contains(c)) { break; } else if (Sci.EOLMode == 1 && c == '\r' && (++nCount) > extraLine) { break; } else if (c == '\n' && (++nCount) > extraLine) { if (Sci.EOLMode != 2) { funcBodyStart--; } break; } } return funcBodyStart; }
private void OnUpdateCallTip(ScintillaNet.ScintillaControl sci, int position) { if (ASComplete.HasCalltip()) { int pos = sci.CurrentPos - 1; char c = (char)sci.CharAt(pos); if ((c == ',' || c == '(') && sci.BaseStyleAt(pos) == 0) sci.Colourise(0, -1); ASComplete.HandleFunctionCompletion(sci, false, true); } }
private static List<FunctionParameter> ParseFunctionParameters(ScintillaNet.ScintillaControl Sci, int p) { List<FunctionParameter> prms = new List<FunctionParameter>(); StringBuilder sb = new StringBuilder(); List<ASResult> types = new List<ASResult>(); bool isFuncStarted = false; bool isDoubleQuote = false; bool isSingleQuote = false; bool wasEscapeChar = false; bool doBreak = false; bool writeParam = false; int subClosuresCount = 0; ASResult result = null; IASContext ctx = ASContext.Context; char[] charsToTrim = new char[] { ' ', '\t', '\r', '\n' }; int counter = Sci.TextLength; // max number of chars in parameters line (to avoid infinitive loop) string characterClass = ScintillaNet.ScintillaControl.Configuration.GetLanguage(Sci.ConfigurationLanguage).characterclass.Characters; int lastMemberPos = p; // add [] and <> while (p < counter && !doBreak) { char c = (char)Sci.CharAt(p++); if (c == '(' && !isFuncStarted) { if (sb.ToString().Trim(charsToTrim).Length == 0) { isFuncStarted = true; } else { break; } } else if (c == ';' && !isFuncStarted) { break; } else if (c == ')' && isFuncStarted && !wasEscapeChar && !isDoubleQuote && !isSingleQuote && subClosuresCount == 0) { isFuncStarted = false; writeParam = true; doBreak = true; } else if ((c == '(' || c == '[' || c == '<' || c == '{') && !wasEscapeChar && !isDoubleQuote && !isSingleQuote) { if (subClosuresCount == 0) { if (c == '{') { if (sb.ToString().TrimStart().Length > 0) { result = new ASResult(); result.Type = ctx.ResolveType("Function", null); types.Insert(0, result); } else { result = new ASResult(); result.Type = ctx.ResolveType(ctx.Features.objectKey, null); types.Insert(0, result); } } else if (c == '(') { result = ASComplete.GetExpressionType(Sci, lastMemberPos + 1); if (!result.IsNull()) { types.Insert(0, result); } } else if (c == '<') { if (sb.ToString().TrimStart().Length == 0) { result = new ASResult(); result.Type = ctx.ResolveType("XML", null); types.Insert(0, result); } } } subClosuresCount++; sb.Append(c); wasEscapeChar = false; } else if ((c == ')' || c == ']' || c == '>' || c == '}') && !wasEscapeChar && !isDoubleQuote && !isSingleQuote) { if (c == ']') { result = ASComplete.GetExpressionType(Sci, p); if (result.Type != null) result.Member = null; else result.Type = ctx.ResolveType(ctx.Features.arrayKey, null); types.Insert(0, result); writeParam = true; } subClosuresCount--; sb.Append(c); wasEscapeChar = false; } else if (c == '\\') { wasEscapeChar = !wasEscapeChar; sb.Append(c); } else if (c == '"' && !wasEscapeChar && !isSingleQuote) { isDoubleQuote = !isDoubleQuote; if (subClosuresCount == 0) { if (isDoubleQuote) { result = new ASResult(); result.Type = ctx.ResolveType("String", null); types.Add(result); } } sb.Append(c); wasEscapeChar = false; } else if (c == '\'' && !wasEscapeChar && !isDoubleQuote) { isSingleQuote = !isSingleQuote; if (subClosuresCount == 0) { if (isSingleQuote) { result = new ASResult(); result.Type = ctx.ResolveType("String", null); types.Add(result); } } sb.Append(c); wasEscapeChar = false; } else if (c == ',' && subClosuresCount == 0) { if (!isSingleQuote && !isDoubleQuote && subClosuresCount == 0) { writeParam = true; } else { sb.Append(c); } wasEscapeChar = false; } else if (isFuncStarted) { sb.Append(c); if (!isSingleQuote && !isDoubleQuote && subClosuresCount == 0 && characterClass.IndexOf(c) > -1) { lastMemberPos = p - 1; } wasEscapeChar = false; } else if (characterClass.IndexOf(c) > -1) { doBreak = true; } if (writeParam) { writeParam = false; string trimmed = sb.ToString().Trim(charsToTrim); if (trimmed.Length > 0) { result = ASComplete.GetExpressionType(Sci, lastMemberPos + 1); if (result != null && !result.IsNull()) { if (characterClass.IndexOf(trimmed[trimmed.Length - 1]) > -1) { types.Insert(0, result); } else { types.Add(result); } } else { double d = double.MaxValue; try { d = double.Parse(trimmed, System.Globalization.CultureInfo.InvariantCulture); } catch (Exception) { } if (d != double.MaxValue && d.ToString().Length == trimmed.Length) { result = new ASResult(); result.Type = ctx.ResolveType(ctx.Features.numberKey, null); types.Insert(0, result); } else if (trimmed.Equals("true") || trimmed.Equals("false")) { result = new ASResult(); result.Type = ctx.ResolveType(ctx.Features.booleanKey, null); types.Insert(0, result); } } if (types.Count == 0) { result = new ASResult(); result.Type = ctx.ResolveType(ctx.Features.objectKey, null); types.Add(result); } result = types[0]; string paramName = null; string paramType = null; string paramQualType = null; if (result.Member == null) { paramType = result.Type.Name; paramQualType = result.Type.QualifiedName; } else { if (result.Member.Name != null) { paramName = result.Member.Name.Trim('@'); } if (result.Member.Type == null || result.Member.Type.Equals("void", StringComparison.OrdinalIgnoreCase)) { paramType = result.Type.Name; paramQualType = result.Type.QualifiedName; } else { paramType = FormatType(GetShortType(result.Member.Type)); if (result.InClass == null) { paramQualType = result.Type.QualifiedName; } else { paramQualType = getQualifiedType(result.Member.Type, result.InClass); } } } prms.Add(new FunctionParameter(paramName, paramType, paramQualType, result)); } types = new List<ASResult>(); sb = new StringBuilder(); } } for (int i = 0; i < prms.Count; i++) { if (prms[i].paramType == "void") { prms[i].paramName = "object"; prms[i].paramType = null; } else prms[i].paramName = GuessVarName(prms[i].paramName, FormatType(GetShortType(prms[i].paramType))); } for (int i = 0; i < prms.Count; i++) { int iterator = -1; bool nameUnique = false; string name = prms[i].paramName; string suggestedName = name; while (!nameUnique) { iterator++; suggestedName = name + (iterator == 0 ? "" : iterator + ""); bool gotMatch = false; for (int j = 0; j < i; j++) { if (prms[j] != prms[i] && prms[j].paramName == suggestedName) { gotMatch = true; break; } } nameUnique = !gotMatch; } prms[i].paramName = suggestedName; } return prms; }
static private bool HandleBoxCompletion(ScintillaNet.ScintillaControl Sci, int position) { // is the block before a function declaration? int len = Sci.TextLength-1; char c; StringBuilder sb = new StringBuilder(); while (position < len) { c = (char)Sci.CharAt(position); sb.Append(c); if (c == '(' || c == ';' || c == '{' || c == '}') break; position++; } string signature = sb.ToString(); if (re_functionDeclaration.IsMatch(signature)) { // get method signature position++; while (position < len) { c = (char)Sci.CharAt(position); sb.Append(c); if (c == ';' || c == '{') break; position++; } signature = sb.ToString(); } else signature = null; // build templates list List<ICompletionListItem> templates = new List<ICompletionListItem>(); if (signature != null) { boxMethodParams.Context = signature; templates.Add(boxMethodParams); } templates.Add(boxSimpleClose); // show CompletionList.Show(templates, true, ""); return true; }
private static void GenerateDefaultHandlerName(ScintillaNet.ScintillaControl Sci, int position, int targetPos, string eventName, bool closeBrace) { string target = null; int contextOwnerPos = GetContextOwnerEndPos(Sci, Sci.WordStartPosition(targetPos, true)); if (contextOwnerPos != -1) { ASResult contextOwnerResult = ASComplete.GetExpressionType(Sci, contextOwnerPos); if (contextOwnerResult != null && !contextOwnerResult.IsNull() && contextOwnerResult.Member != null) { if (contextOwnerResult.Member.Name == "contentLoaderInfo" && Sci.CharAt(contextOwnerPos) == '.') { // we want to name the event from the loader var and not from the contentLoaderInfo parameter contextOwnerPos = GetContextOwnerEndPos(Sci, Sci.WordStartPosition(contextOwnerPos - 1, true)); if (contextOwnerPos != -1) { contextOwnerResult = ASComplete.GetExpressionType(Sci, contextOwnerPos); if (contextOwnerResult != null && !contextOwnerResult.IsNull() && contextOwnerResult.Member != null) { target = contextOwnerResult.Member.Name; } } } else { target = contextOwnerResult.Member.Name; } } } eventName = Camelize(eventName.Substring(eventName.LastIndexOf('.') + 1)); if (target != null) target = target.TrimStart(new char[] { '_' }); switch (ASContext.CommonSettings.HandlerNamingConvention) { case HandlerNamingConventions.handleTargetEventName: if (target == null) contextToken = "handle" + Capitalize(eventName); else contextToken = "handle" + Capitalize(target) + Capitalize(eventName); break; case HandlerNamingConventions.onTargetEventName: if (target == null) contextToken = "on" + Capitalize(eventName); else contextToken = "on" + Capitalize(target) + Capitalize(eventName); break; case HandlerNamingConventions.target_eventNameHandler: if (target == null) contextToken = eventName + "Handler"; else contextToken = target + "_" + eventName + "Handler"; break; default: //HandlerNamingConventions.target_eventName if (target == null) contextToken = eventName; else contextToken = target + "_" + eventName; break; } char c = (char)Sci.CharAt(position - 1); if (c == ',') InsertCode(position, "$(Boundary) " + contextToken + "$(Boundary)"); else InsertCode(position, contextToken); position = Sci.WordEndPosition(position + 1, true); Sci.SetSel(position, position); c = (char)Sci.CharAt(position); if (c <= 32) if (closeBrace) Sci.ReplaceSel(");"); else Sci.ReplaceSel(";"); Sci.SetSel(position, position); }
/// <summary> /// Find Actionscript expression at cursor position /// TODO Improve this method /// </summary> /// <param name="sci">Scintilla Control</param> /// <param name="position">Cursor position</param> /// <returns></returns> static private ASExpr GetExpression(ScintillaNet.ScintillaControl Sci, int position) { ASExpr expression = new ASExpr(); int startPos = position; expression.Position = position; expression.separator = ' '; // get last expression (until ';') excluding comments int stylemask = (1 << Sci.StyleBits) -1; int style = (position > 0) ? Sci.StyleAt(position-1) & stylemask : 0; bool ignoreKey = false; if (style == 19) { DebugConsole.Trace("Ignore keyword"); ignoreKey = true; } StringBuilder sb = new StringBuilder(); char c; while ((position > 0) && (style != 19 || ignoreKey)) { position--; style = Sci.StyleAt(position) & stylemask; if (IsTextStyle(style) || ignoreKey) { c = (char)Sci.CharAt(position); if (c == ';') { expression.separator = c; break; } else if (c == '\n' || c == '\r') { if (sb.ToString().Trim().Length == 0) break; } sb.Insert(0,c); if (ignoreKey && IsTextStyle(style)) ignoreKey = false; } // we found a keyword else if (style == 19) { expression.separator = ' '; int keywordPos = position; string keyword = GetWordLeft(Sci, ref keywordPos); if ((keyword == "function") || (keyword == "get") || (keyword == "set")) { // we found a function declaration string test = sb.ToString().Trim(); // ignore anonymous function if ((keyword == "function") && test.StartsWith("(")) { keyword = null; break; } // guess context more precisely bool hasBraces = (test.IndexOf('{') >= 0); test = re_balancedBraces.Replace(test, ";"); // is it inside the function? if (test.IndexOf('{') >= 0) { c = ' '; while ((position < startPos) && (sb.Length > 0)) { position++; c = (char)Sci.CharAt(position); sb.Remove(0,1); if (c == '{') break; } expression.separator = c; } // is it NOT inside function parameters? else if (test.IndexOf(')') >= 0) { if (hasBraces) { expression.separator = '}'; expression.Value = ""; return expression; } else { // is it before the return type declaration? int colon = test.LastIndexOf(':'); if ((colon < 0) || (colon < test.LastIndexOf(')'))) // this is invalid return expression; } } // inside function parameters? else { int colon = test.LastIndexOf(':'); if ((colon < 0) || (colon < test.LastIndexOf(','))) return expression; } } else expression.Keyword = keyword; // note that we found a "case" statement //else if (keyword == "case") expression.Keyword = "case"; DebugConsole.Trace("Stopped at '"+keyword+"'"); DebugConsole.Trace("Raw '"+sb.ToString()+"'"); break; } } position++; string expr = sb.ToString(); sb = null; if (expr.Length > 0 && (expr[expr.Length-1] <= 32 && Sci.CharAt(startPos) != '(')) { expr = ""; expression.separator = ' '; expression.Position = Sci.CurrentPos; } else expression.PositionExpression = position; // refine last expression if (expr.Length > 0) { expr = re_balancedBraces.Replace(expr, ";"); expression.SubExpressions = ExtractedSubex = new StringCollection(); expr = re_balancedParenthesis.Replace(expr, new MatchEvaluator(ExtractSubex)); //DebugConsole.Trace("Raw '"+expr+"' @"+expression.PositionExpression); Match m = re_refineExpression.Match(expr); if (!m.Success) return expression; if (m.Index > 0) { expression.separator = expr[m.Index-1]; expression.PositionExpression = position += m.Index; // treat ':' as ';' after a case statement if (expression.separator == ':' && expression.Keyword == "case") expression.separator = ';'; expression.Keyword = null; } //DebugConsole.Trace("Refined '"+m.Value+"' @"+m.Index); expr = re_dot.Replace( re_whiteSpace.Replace(m.Value, " ") , "."); expr = re_subexMarker.Replace(expr, "#").Trim(); int space = Math.Max(expr.LastIndexOf(' '), expr.LastIndexOf(';')); if (space > 0) { expression.separator = ' '; expr = expr.Substring(space+1); } //ErrorHandler.ShowInfo("Clean '"+expr+"' @"+expression.PositionExpression); } expression.Value = expr; // get context function body int braceCount = 0; StringBuilder body = new StringBuilder(); StringBuilder context = new StringBuilder(); while (braceCount >= 0) { while (position > 0) { position--; style = Sci.StyleAt(position) & stylemask; if (IsTextStyleEx(style)) { c = (char)Sci.CharAt(position); if (c == '}') { body.Insert(0,c); braceCount++; } else if ((c == '{') && (--braceCount < 0)) break; if (braceCount == 0) body.Insert(0,c); } } if (braceCount >= 0) break; // get context function definition while (position > 0) { position--; style = Sci.StyleAt(position) & stylemask; if (IsTextStyleEx(style)) { c = (char)Sci.CharAt(position); if ((c == ';') || (c == '}') || (c == '{')) break; context.Insert(0,c); } } expression.ContextFunction = context.ToString(); // ignore dynamic function definition if (!re_validFunction.IsMatch(expression.ContextFunction)) { // stop if we reached the class definition if (re_classDefinition.IsMatch(expression.ContextFunction)) { expression.ContextFunction = null; expression.PositionContext = 0; break; } // continue search for function definition body.Insert(0,'{').Insert(0,context.ToString()); context = new StringBuilder(); position++; braceCount++; } else { expression.ContextBody = body.ToString(); expression.PositionContext = position+1; } } // result LastExpression = expression; return expression; }