/// <summary> /// Update document bookmarks /// </summary> /// <param name="sender"></param> private void UpdateMarkers( ScintillaNet.ScintillaControl sender ) { ITabbedDocument document = (ITabbedDocument)sender.Parent; List<int> markers = GetMarkers(sender); ListViewGroup group = FindGroup(document); if (group != null) { if (true) { this.RemoveItemsFromGroup(group); ListViewItem[] items = new ListViewItem[markers.Count]; ListViewItem item; int index = 0; foreach (int marker in markers) { item = new ListViewItem(new string[]{ (marker+1).ToString(), sender.GetLine(marker).TrimStart() }, -1); item.Group = group; item.Tag = marker; item.Name = (string)((Hashtable)group.Tag)["FileName"]; items[index] = item; index++; } this.listView1.BeginUpdate(); this.listView1.Items.AddRange(items); ((Hashtable)group.Tag)["Markers"] = markers; this.listView1.EndUpdate(); } else { } } }
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; }
private string LineIndentPosition(ScintillaNet.ScintillaControl sci, int line) { string txt = sci.GetLine(line); for (int i = 0; i < txt.Length; i++) if (txt[i] > 32) return txt.Substring(0, i); return ""; }
public static bool MakePrivate(ScintillaNet.ScintillaControl Sci, MemberModel member) { ContextFeatures features = ASContext.Context.Features; string visibility = GetPrivateKeyword(); if (features.publicKey == null || visibility == null) return false; Regex rePublic = new Regex(String.Format(@"\s*({0})\s+", features.publicKey)); string line; Match m; int index, position; for (int i = member.LineFrom; i <= member.LineTo; i++) { line = Sci.GetLine(i); m = rePublic.Match(line); if (m.Success) { index = Sci.MBSafeTextLength(line.Substring(0, m.Groups[1].Index)); position = Sci.PositionFromLine(i) + index; Sci.SetSel(position, position + features.publicKey.Length); Sci.ReplaceSel(visibility); UpdateLookupPosition(position, features.publicKey.Length - visibility.Length); return true; } } return false; }
static public void GenerateOverride(ScintillaNet.ScintillaControl Sci, ClassModel ofClass, MemberModel member, int position) { ContextFeatures features = ASContext.Context.Features; List<string> typesUsed = new List<string>(); bool isProxy = (member.Namespace == "flash_proxy"); if (isProxy) typesUsed.Add("flash.utils.flash_proxy"); bool isAS2Event = ASContext.Context.Settings.LanguageId == "AS2" && member.Name.StartsWith("on"); bool isObjectMethod = ofClass.QualifiedName == "Object"; int line = Sci.LineFromPosition(position); string currentText = Sci.GetLine(line); int startPos = currentText.Length; GetStartPos(currentText, ref startPos, features.privateKey); GetStartPos(currentText, ref startPos, features.protectedKey); GetStartPos(currentText, ref startPos, features.internalKey); GetStartPos(currentText, ref startPos, features.publicKey); GetStartPos(currentText, ref startPos, features.staticKey); GetStartPos(currentText, ref startPos, features.overrideKey); startPos += Sci.PositionFromLine(line); FlagType flags = member.Flags; string acc = ""; string decl = ""; if (features.hasNamespaces && !string.IsNullOrEmpty(member.Namespace) && member.Namespace != "internal") acc = member.Namespace; else if ((member.Access & Visibility.Public) > 0) acc = features.publicKey; else if ((member.Access & Visibility.Internal) > 0) acc = features.internalKey; else if ((member.Access & Visibility.Protected) > 0) acc = features.protectedKey; else if ((member.Access & Visibility.Private) > 0 && features.methodModifierDefault != Visibility.Private) acc = features.privateKey; bool isStatic = (flags & FlagType.Static) > 0; if (isStatic) acc = features.staticKey + " " + acc; if (!isAS2Event && !isObjectMethod) acc = features.overrideKey + " " + acc; acc = Regex.Replace(acc, "[ ]+", " ").Trim(); if ((flags & (FlagType.Getter | FlagType.Setter)) > 0) { string type = member.Type; string name = member.Name; if (member.Parameters != null && member.Parameters.Count == 1) type = member.Parameters[0].Type; type = FormatType(type); if (type == null && !features.hasInference) type = features.objectKey; bool genGetter = ofClass.Members.Search(name, FlagType.Getter, 0) != null; bool genSetter = ofClass.Members.Search(name, FlagType.Setter, 0) != null; if (isHaxe) { // property is public but not the methods acc = features.overrideKey; } if (genGetter) { string tpl = TemplateUtils.GetTemplate("OverrideGetter", "Getter"); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Modifiers", acc); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Name", name); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Type", type); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Member", "super." + name); decl += tpl; } if (genSetter) { string tpl = TemplateUtils.GetTemplate("OverrideSetter", "Setter"); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Modifiers", acc); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Name", name); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Type", type); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Member", "super." + name); tpl = TemplateUtils.ReplaceTemplateVariable(tpl, "Void", ASContext.Context.Features.voidKey ?? "void"); if (decl.Length > 0) { tpl = "\n\n" + tpl.Replace("$(EntryPoint)", ""); } decl += tpl; } decl = TemplateUtils.ReplaceTemplateVariable(decl, "BlankLine", ""); } else { string type = FormatType(member.Type); //if (type == null) type = features.objectKey; decl = acc + features.functionKey + " "; bool noRet = type == null || type.Equals("void", StringComparison.OrdinalIgnoreCase); type = (noRet && type != null) ? ASContext.Context.Features.voidKey : type; if (!noRet) { string qType = getQualifiedType(type, ofClass); typesUsed.Add(qType); if (qType == type) { ClassModel rType = ASContext.Context.ResolveType(type, ofClass.InFile); if (!rType.IsVoid()) type = rType.Name; } } string action = (isProxy || isAS2Event) ? "" : GetSuperCall(member, typesUsed, ofClass); string template = TemplateUtils.GetTemplate("MethodOverride"); // fix parameters if needed if (member.Parameters != null) foreach (MemberModel para in member.Parameters) if (para.Type == "any") para.Type = "*"; template = TemplateUtils.ReplaceTemplateVariable(template, "Modifiers", acc); template = TemplateUtils.ReplaceTemplateVariable(template, "Name", member.Name); template = TemplateUtils.ReplaceTemplateVariable(template, "Arguments", TemplateUtils.ParametersString(member, true)); template = TemplateUtils.ReplaceTemplateVariable(template, "Type", type); template = TemplateUtils.ReplaceTemplateVariable(template, "Method", action); decl = template; } Sci.BeginUndoAction(); try { if (ASContext.Context.Settings.GenerateImports && typesUsed.Count > 0) { int offset = AddImportsByName(typesUsed, line); position += offset; startPos += offset; } Sci.SetSel(startPos, position + member.Name.Length); InsertCode(startPos, decl); } finally { Sci.EndUndoAction(); } }
private static void EventMetatag(ClassModel inClass, ScintillaNet.ScintillaControl Sci, MemberModel member) { ASResult resolve = ASComplete.GetExpressionType(Sci, Sci.WordEndPosition(Sci.CurrentPos, true)); string line = Sci.GetLine(inClass.LineFrom); int position = Sci.PositionFromLine(inClass.LineFrom) + (line.Length - line.TrimStart().Length); string value = resolve.Member.Value; if (value != null) { if (value.StartsWith("\"")) { value = value.Trim(new char[] { '"' }); } else if (value.StartsWith("'")) { value = value.Trim(new char[] { '\'' }); } } else value = resolve.Member.Type; if (value == "" || value == null) return; Regex re1 = new Regex("'(?:[^'\\\\]|(?:\\\\\\\\)|(?:\\\\\\\\)*\\\\.{1})*'"); Regex re2 = new Regex("\"(?:[^\"\\\\]|(?:\\\\\\\\)|(?:\\\\\\\\)*\\\\.{1})*\""); Match m1 = re1.Match(value); Match m2 = re2.Match(value); if (m1.Success || m2.Success) { Match m = null; if (m1.Success && m2.Success) m = m1.Index > m2.Index ? m2 : m1; else if (m1.Success) m = m1; else m = m2; value = value.Substring(m.Index + 1, m.Length - 2); } string template = TemplateUtils.GetTemplate("EventMetatag"); template = TemplateUtils.ReplaceTemplateVariable(template, "Name", value); template = TemplateUtils.ReplaceTemplateVariable(template, "Type", contextParam); template += "\n$(Boundary)"; AddLookupPosition(); Sci.CurrentPos = position; Sci.SetSel(position, position); InsertCode(position, template); }
private static int FindNewVarPosition(ScintillaNet.ScintillaControl Sci, ClassModel inClass, MemberModel latest) { firstVar = false; // found a var? if ((latest.Flags & FlagType.Variable) > 0) return Sci.PositionFromLine(latest.LineTo + 1) - ((Sci.EOLMode == 0) ? 2 : 1); // add as first member int line = 0; int maxLine = Sci.LineCount; if (inClass != null) { line = inClass.LineFrom; maxLine = inClass.LineTo; } else if (ASContext.Context.InPrivateSection) line = ASContext.Context.CurrentModel.PrivateSectionIndex; else maxLine = ASContext.Context.CurrentModel.PrivateSectionIndex; while (line < maxLine) { string text = Sci.GetLine(line++); if (text.IndexOf('{') >= 0) { firstVar = true; return Sci.PositionFromLine(line) - ((Sci.EOLMode == 0) ? 2 : 1); } } return -1; }
static public void GenerateOverride(ScintillaNet.ScintillaControl Sci, ClassModel ofClass, MemberModel member, int position) { ContextFeatures features = ASContext.Context.Features; List<string> typesUsed = new List<string>(); bool isProxy = (member.Namespace == "flash_proxy"); if (isProxy) typesUsed.Add("flash.utils.flash_proxy"); bool isAS2Event = ASContext.Context.Settings.LanguageId == "AS2" && member.Name.StartsWith("on"); bool isObjectMethod = ofClass.QualifiedName == "Object"; int line = Sci.LineFromPosition(position); string currentText = Sci.GetLine(line); int startPos = currentText.Length; GetStartPos(currentText, ref startPos, features.privateKey); GetStartPos(currentText, ref startPos, features.protectedKey); GetStartPos(currentText, ref startPos, features.internalKey); GetStartPos(currentText, ref startPos, features.publicKey); GetStartPos(currentText, ref startPos, features.staticKey); GetStartPos(currentText, ref startPos, features.overrideKey); startPos += Sci.PositionFromLine(line); FlagType flags = member.Flags; string acc = ""; string decl = ""; if (features.hasNamespaces && member.Namespace != null && member.Namespace.Length > 0 && member.Namespace != "internal") acc = member.Namespace; else if ((member.Access & Visibility.Public) > 0) acc = features.publicKey; else if ((member.Access & Visibility.Internal) > 0) acc = features.internalKey; else if ((member.Access & Visibility.Protected) > 0) acc = features.protectedKey; else if ((member.Access & Visibility.Private) > 0) acc = features.privateKey; bool isStatic = (flags & FlagType.Static) > 0; if (isStatic) acc = features.staticKey + " " + acc; if (!isAS2Event && !isObjectMethod) acc = features.overrideKey + " " + acc; if ((flags & (FlagType.Getter | FlagType.Setter)) > 0) { string type = member.Type; string name = member.Name; if (member.Parameters != null && member.Parameters.Count > 0) type = member.Parameters[0].Type; type = FormatType(type); if (type == null) { string message = String.Format(TextHelper.GetString("Info.TypeDeclMissing"), member.Name); ErrorManager.ShowInfo(message); return; } if (ofClass.Members.Search(name, FlagType.Getter, 0) != null) { decl += String.Format(GetTemplate("Getter"), acc, name, type, "super." + name); } if (ofClass.Members.Search(name, FlagType.Setter, 0) != null) { string tpl = GetTemplate("Setter"); if (decl.Length > 0) { decl += "\n\n"; tpl = tpl.Replace("$(EntryPoint)", ""); } decl += String.Format(tpl, acc, name, type, "super." + name, ASContext.Context.Features.voidKey ?? "void"); } } else { string type = FormatType(member.Type); if (type == null) { string message = String.Format(TextHelper.GetString("Info.TypeDeclMissing"), member.Name); ErrorManager.ShowInfo(message); return; } if (acc.Length > 0) acc += " "; decl = acc + features.functionKey + " "; bool noRet = type.Equals("void", StringComparison.OrdinalIgnoreCase); type = (noRet) ? ASContext.Context.Features.voidKey : type; if (!noRet) typesUsed.Add(getQualifiedType(type, ofClass)); string action = (isProxy || isAS2Event) ? "" : GetSuperCall(member, typesUsed, ofClass); decl += member.Name + String.Format(GetTemplate("MethodOverride"), member.ParametersString(true), type, action); } Sci.BeginUndoAction(); try { if (ASContext.Context.Settings.GenerateImports && typesUsed.Count > 0) { int offset = AddImportsByName(typesUsed, line); position += offset; startPos += offset; } Sci.SetSel(startPos, position + member.Name.Length); InsertCode(startPos, decl); } finally { Sci.EndUndoAction(); } }
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)); // 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 (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 Match m = Regex.Match(text, String.Format(patternEvent, contextToken), RegexOptions.IgnoreCase); if (m.Success) { contextMatch = m; contextParam = CheckEventType(m.Groups["event"].Value); ShowEventList(found); return; } m = Regex.Match(text, String.Format(patternDelegate, contextToken), RegexOptions.IgnoreCase); if (m.Success) { contextMatch = m; ShowDelegateList(found); return; } } } // "Generate fields from parameters" suggestion if (found.member != null && (found.member.Flags & FlagType.Function) > 0 && (found.member.Flags & FlagType.Static) == 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 && (found.member.Flags & FlagType.Function) > 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); bool skip = false; foreach (string interf in found.inClass.Implements) { if (skip) { break; } ClassModel cm = ASContext.Context.ResolveType(interf, ASContext.Context.CurrentModel); contextParam = cm.Type; MemberList members = cm.Members; foreach (MemberModel m in members) { if (m.Name.Equals(funcName)) { skip = true; break; } } } if (!skip && contextParam != null) { ShowAddInterfaceDefList(found); 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 { 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); } } } } // TODO Empty line, show generators list? }
static private bool HandleDocTagCompletion(ScintillaNet.ScintillaControl Sci) { if (ASContext.CommonSettings.JavadocTags == null || ASContext.CommonSettings.JavadocTags.Length == 0) return false; string txt = Sci.GetLine(Sci.LineFromPosition(Sci.CurrentPos)).TrimStart(); if (!Regex.IsMatch(txt, "^\\*[\\s]*\\@")) return false; // build tag list if (docVariables == null) { docVariables = new List<ICompletionListItem>(); TagItem item; foreach (string tag in ASContext.CommonSettings.JavadocTags) { item = new TagItem(tag); docVariables.Add(item); } } // show CompletionList.Show(docVariables, true, ""); return true; }
private static void AssignStatementToVar(ClassModel inClass, ScintillaNet.ScintillaControl Sci, MemberModel member) { int lineNum = Sci.LineFromPosition(Sci.CurrentPos); string line = Sci.GetLine(lineNum); StatementReturnType returnType = GetStatementReturnType(Sci, inClass, line, Sci.PositionFromLine(lineNum)); if (returnType == null) { return; } IASContext cntx = inClass.InFile.Context; bool isAs3 = cntx.Settings.LanguageId == "AS3"; string voidWord = isAs3 ? "void" : "Void"; string type = null; string varname = null; string cleanType = null; ASResult resolve = returnType.resolve; int pos = returnType.position; string word = returnType.word; if (resolve != null && !resolve.IsNull()) { if (resolve.Member != null && resolve.Member.Type != null) { type = resolve.Member.Type; } else if (resolve.Type != null && resolve.Type.Name != null) { type = returnType.resolve.Type.QualifiedName; } if (resolve.Member != null && resolve.Member.Name != null) { varname = GuessVarName(resolve.Member.Name, type); } } if (word != null && Char.IsDigit(word[0])) word = null; if (type == voidWord) type = null; if (varname == null) varname = GuessVarName(word, type); if (varname != null && varname == word) varname = varname.Length == 1 ? varname + "1" : varname[0] + ""; if (type != null) cleanType = FormatType(GetShortType(type)); string template = TemplateUtils.GetTemplate("AssignVariable"); if (varname != null) template = TemplateUtils.ReplaceTemplateVariable(template, "Name", varname); else template = TemplateUtils.ReplaceTemplateVariable(template, "Name", null); if (cleanType != null) template = TemplateUtils.ReplaceTemplateVariable(template, "Type", cleanType); else template = TemplateUtils.ReplaceTemplateVariable(template, "Type", null); int indent = Sci.GetLineIndentation(lineNum); pos = Sci.PositionFromLine(lineNum) + indent / Sci.Indent; Sci.CurrentPos = pos; Sci.SetSel(pos, pos); InsertCode(pos, template); if (type != null) { ClassModel inClassForImport = null; if (resolve.InClass != null) { inClassForImport = resolve.InClass; } else if (resolve.RelClass != null) { inClassForImport = resolve.RelClass; } else { inClassForImport = inClass; } List<string> l = new List<string>(); l.Add(getQualifiedType(type, inClassForImport)); pos += AddImportsByName(l, Sci.LineFromPosition(pos)); } }
static private bool HandleDocTagCompletion(ScintillaNet.ScintillaControl Sci) { string txt = Sci.GetLine(Sci.LineFromPosition(Sci.CurrentPos)).TrimStart(); if (!Regex.IsMatch(txt, "^\\*[\\s]*\\@")) return false; DebugConsole.Trace("Documentation tag completion"); // build tag list if (docVariables == null) { docVariables = new ArrayList(); TagItem item; string[] tags = ASContext.DocumentationTags.Split(' '); foreach(string tag in tags) { item = new TagItem(tag); docVariables.Add(item); } } // show CompletionList.Show(docVariables, true, ""); return true; }
public override bool OnCompletionInsert(ScintillaNet.ScintillaControl sci, int position, string text) { bool isVector = false; if (text == "Vector") { isVector = true; } if (isVector) { string insert = null; string line = sci.GetLine(sci.LineFromPosition(position)); Match m = Regex.Match(line, @"\svar\s+(?<varname>.+)\s*:\s*Vector\.<(?<indextype>.+)(?=(>\s*=))"); if (m.Success) { insert = String.Format(".<{0}>()", m.Groups["indextype"].Value); sci.InsertText(position + text.Length, insert); sci.CurrentPos = position + text.Length + insert.Length; sci.SetSel(sci.CurrentPos, sci.CurrentPos); } else { m = Regex.Match(line, @"\s*="); if (m.Success) { ASResult result = ASComplete.GetExpressionType(sci, sci.PositionFromLine(sci.LineFromPosition(position)) + m.Index); if (result != null && !result.IsNull() && result.Member != null && result.Member.Type != null) { m = Regex.Match(result.Member.Type, @"(?<=<).+(?=>)"); if (m.Success) { insert = String.Format(".<{0}>()", m.Value); sci.InsertText(position + text.Length, insert); sci.CurrentPos = position + text.Length + insert.Length; sci.SetSel(sci.CurrentPos, sci.CurrentPos); return true; } } } insert = ".<>"; sci.InsertText(position + text.Length, insert); sci.CurrentPos = position + text.Length + 2; sci.SetSel(sci.CurrentPos, sci.CurrentPos); ASComplete.HandleAllClassesCompletion(sci, "", false, true); } return true; } return false; }
/// <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; }
public override bool OnCompletionInsert(ScintillaNet.ScintillaControl sci, int position, string text, char trigger) { if (text == "Dictionary") { string insert = null; string line = sci.GetLine(sci.LineFromPosition(position)); Match m = Regex.Match(line, @"\svar\s+(?<varname>.+)\s*:\s*Dictionary\.<(?<indextype>.+)(?=(>\s*=))"); if (m.Success) { insert = String.Format(".<{0}>", m.Groups["indextype"].Value); } else { m = Regex.Match(line, @"\s*=\s*new"); if (m.Success) { ASResult result = ASComplete.GetExpressionType(sci, sci.PositionFromLine(sci.LineFromPosition(position)) + m.Index); if (result != null && !result.IsNull() && result.Member != null && result.Member.Type != null) { m = Regex.Match(result.Member.Type, @"(?<=<).+(?=>)"); if (m.Success) { insert = String.Format(".<{0}>", m.Value); } } } if (insert == null) { if (trigger == '.' || trigger == '(') return true; insert = ".<>"; sci.InsertText(position + text.Length, insert); sci.CurrentPos = position + text.Length + 2; sci.SetSel(sci.CurrentPos, sci.CurrentPos); ASComplete.HandleAllClassesCompletion(sci, "", false, true); return true; } } if (insert == null) return false; if (trigger == '.') { sci.InsertText(position + text.Length, insert.Substring(1)); sci.CurrentPos = position + text.Length; } else { sci.InsertText(position + text.Length, insert); sci.CurrentPos = position + text.Length + insert.Length; } sci.SetSel(sci.CurrentPos, sci.CurrentPos); return true; } return base.OnCompletionInsert(sci, position, text, trigger); }
private static void AssignStatementToVar(ClassModel inClass, ScintillaNet.ScintillaControl Sci, MemberModel member) { int lineNum = Sci.LineFromPosition(Sci.CurrentPos); string line = Sci.GetLine(lineNum); StatementReturnType returnType = GetStatementReturnType(Sci, inClass, line, Sci.PositionFromLine(lineNum)); if (returnType == null) { return; } IASContext cntx = inClass.InFile.Context; bool isAs3 = cntx.Settings.LanguageId == "AS3"; string voidWord = isAs3 ? "void" : "Void"; string type = null; string varname = null; string cleanType = null; ASResult resolve = returnType.resolve; int pos = returnType.position; string word = returnType.word; if (resolve != null && !resolve.IsNull()) { if (resolve.Member != null && resolve.Member.Type != null) { type = resolve.Member.Type; } else if (resolve.Type != null && resolve.Type.Name != null) { type = returnType.resolve.Type.QualifiedName; } if (resolve.Member != null && resolve.Member.Name != null) { varname = GuessVarName(resolve.Member.Name, type); } } if (word != null && Char.IsDigit(word[0])) { word = null; } if (type == voidWord) { type = null; } if (varname == null) { varname = GuessVarName(word, type); } if (varname != null && varname == word) { if (varname.Length == 1) { varname = varname + "1"; } else { varname = varname[0] + ""; } } if (type != null) { cleanType = FormatType(GetShortType(type)); } StringBuilder sb = new StringBuilder(); sb.Append("var "); if (varname != null) { sb.Append(varname); sb.Append(":"); } if (cleanType != null) { sb.Append(cleanType); } else { sb.Append("$(EntryPoint)"); } sb.Append(" = $(Boundary)"); int indent = Sci.GetLineIndentation(lineNum); pos = Sci.PositionFromLine(lineNum) + indent / Sci.Indent; Sci.CurrentPos = pos; Sci.SetSel(pos, pos); InsertCode(pos, sb.ToString()); if (type != null) { ClassModel inClassForImport = null; if (resolve.inClass != null) { inClassForImport = resolve.inClass; } else if (resolve.relClass != null) { inClassForImport = resolve.relClass; } else { inClassForImport = inClass; } List<string> l = new List<string>(); l.Add(getQualifiedType(type, inClassForImport)); pos += AddImportsByName(l, Sci.LineFromPosition(pos)); } }
private static void AssignStatementToVar(ClassModel inClass, ScintillaNet.ScintillaControl Sci, MemberModel member) { int lineNum = Sci.CurrentLine; string line = Sci.GetLine(lineNum); StatementReturnType returnType = GetStatementReturnType(Sci, inClass, line, Sci.PositionFromLine(lineNum)); if (returnType == null) return; string type = null; string varname = null; ASResult resolve = returnType.resolve; string word = returnType.word; if (resolve != null && !resolve.IsNull()) { if (resolve.Member != null && resolve.Member.Type != null) { type = resolve.Member.Type; } else if (resolve.Type != null && resolve.Type.Name != null) { type = resolve.Type.QualifiedName; } if (resolve.Member != null && resolve.Member.Name != null) { varname = GuessVarName(resolve.Member.Name, type); } } if (!string.IsNullOrEmpty(word) && Char.IsDigit(word[0])) word = null; if (!string.IsNullOrEmpty(word) && (string.IsNullOrEmpty(type) || Regex.IsMatch(type, "(<[^]]+>)"))) word = null; if (!string.IsNullOrEmpty(type) && type.Equals("void", StringComparison.OrdinalIgnoreCase)) type = null; if (varname == null) varname = GuessVarName(word, type); if (varname != null && varname == word) varname = varname.Length == 1 ? varname + "1" : varname[0] + ""; string cleanType = null; if (type != null) cleanType = FormatType(GetShortType(type)); string template = TemplateUtils.GetTemplate("AssignVariable"); template = TemplateUtils.ReplaceTemplateVariable(template, "Name", varname); template = TemplateUtils.ReplaceTemplateVariable(template, "Type", cleanType); int indent = Sci.GetLineIndentation(lineNum); int pos = Sci.PositionFromLine(lineNum) + indent / Sci.Indent; Sci.CurrentPos = pos; Sci.SetSel(pos, pos); InsertCode(pos, template); if (type != null) { ClassModel inClassForImport = null; if (resolve.InClass != null) { inClassForImport = resolve.InClass; } else if (resolve.RelClass != null) { inClassForImport = resolve.RelClass; } else { inClassForImport = inClass; } List<string> l = new List<string>(); l.Add(getQualifiedType(type, inClassForImport)); pos += AddImportsByName(l, Sci.LineFromPosition(pos)); } }
/// <summary> /// Convert multibyte column to byte length /// </summary> private int MBSafeColumn(ScintillaNet.ScintillaControl sci, int line, int length) { String text = sci.GetLine(line) ?? ""; length = Math.Min(length, text.Length); return sci.MBSafeTextLength(text.Substring(0, length)); }
private static void GenerateVariableJob(GeneratorJobType job, ScintillaNet.ScintillaControl Sci, MemberModel member, bool detach, ClassModel inClass) { int position = 0; MemberModel latest = null; bool isOtherClass = false; Visibility varVisi = job.Equals(GeneratorJobType.Variable) ? GetDefaultVisibility() : Visibility.Public; FlagType ft = job.Equals(GeneratorJobType.Constant) ? FlagType.Constant : FlagType.Variable; // evaluate, if the variable (or constant) should be generated in other class ASResult varResult = ASComplete.GetExpressionType(Sci, Sci.WordEndPosition(Sci.CurrentPos, true)); int contextOwnerPos = GetContextOwnerEndPos(Sci, Sci.WordStartPosition(Sci.CurrentPos, true)); MemberModel isStatic = new MemberModel(); if (contextOwnerPos != -1) { ASResult contextOwnerResult = ASComplete.GetExpressionType(Sci, contextOwnerPos); if (contextOwnerResult != null) { if (contextOwnerResult.Member == null && contextOwnerResult.Type != null) { isStatic.Flags |= FlagType.Static; } } } else if (member != null && (member.Flags & FlagType.Static) > 0) { isStatic.Flags |= FlagType.Static; } ASResult returnType = null; int lineNum = Sci.CurrentLine; string line = Sci.GetLine(lineNum); Match m = Regex.Match(line, "\\b" + Regex.Escape(contextToken) + "\\("); if (m.Success) { returnType = new ASResult(); returnType.Type = ASContext.Context.ResolveType("Function", null); } else { m = Regex.Match(line, @"=\s*[^;\n\r}}]+"); if (m.Success) { int posLineStart = Sci.PositionFromLine(lineNum); if (posLineStart + m.Index >= Sci.CurrentPos) { line = line.Substring(m.Index); StatementReturnType rType = GetStatementReturnType(Sci, inClass, line, posLineStart + m.Index); if (rType != null) { returnType = rType.resolve; } } } } if (varResult.RelClass != null && !varResult.RelClass.IsVoid() && !varResult.RelClass.Equals(inClass)) { AddLookupPosition(); lookupPosition = -1; ASContext.MainForm.OpenEditableDocument(varResult.RelClass.InFile.FileName, false); Sci = ASContext.CurSciControl; isOtherClass = true; FileModel fileModel = new FileModel(); fileModel.Context = ASContext.Context; ASFileParser parser = new ASFileParser(); parser.ParseSrc(fileModel, Sci.Text); foreach (ClassModel cm in fileModel.Classes) { if (cm.QualifiedName.Equals(varResult.RelClass.QualifiedName)) { varResult.RelClass = cm; break; } } inClass = varResult.RelClass; ASContext.Context.UpdateContext(inClass.LineFrom); } latest = GetLatestMemberForVariable(job, inClass, varVisi, isStatic); // if we generate variable in current class.. if (!isOtherClass && member == null) { detach = false; lookupPosition = -1; position = Sci.WordStartPosition(Sci.CurrentPos, true); Sci.SetSel(position, Sci.WordEndPosition(position, true)); } else // if we generate variable in another class { 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); } // if this is a constant, we assign a value to constant string returnTypeStr = null; string eventValue = null; if (job == GeneratorJobType.Constant && returnType == null) { isStatic.Flags |= FlagType.Static; eventValue = "String = \"" + Camelize(contextToken) + "\""; } else if (returnType != null) { ClassModel inClassForImport = null; if (returnType.InClass != null) { inClassForImport = returnType.InClass; } else if (returnType.RelClass != null) { inClassForImport = returnType.RelClass; } else { inClassForImport = inClass; } List<String> imports = new List<string>(); if (returnType.Member != null) { if (returnType.Member.Type != ASContext.Context.Features.voidKey) { returnTypeStr = FormatType(GetShortType(returnType.Member.Type)); imports.Add(getQualifiedType(returnType.Member.Type, inClassForImport)); } } else if (returnType != null && returnType.Type != null) { returnTypeStr = FormatType(GetShortType(returnType.Type.QualifiedName)); imports.Add(getQualifiedType(returnType.Type.QualifiedName, inClassForImport)); } if (imports.Count > 0) { position += AddImportsByName(imports, Sci.LineFromPosition(position)); Sci.SetSel(position, position); } } MemberModel newMember = NewMember(contextToken, isStatic, ft, varVisi); if (returnTypeStr != null) { newMember.Type = returnTypeStr; } else if (eventValue != null) { newMember.Type = eventValue; } GenerateVariable(newMember, position, detach); }
public static string ValidateSource(string fileName, string src, ScintillaNet.ScintillaControl sci) { Stream str = new MemoryStream(Encoding.Default.GetBytes(src)); // model generator AS3Lexer lexer = new AS3Lexer(str); lexer.setFilename(fileName); AS3Parser parser = new AS3Parser(lexer); parser.setFilename(fileName); // start parsing try { parser.compilationUnit(); } catch (RecognitionException rex) { string result = fileName + ":" + rex.line + ": "; string line = (rex.line > 0) ? sci.GetLine(rex.line - 1) : ""; int col = rex.column; if (sci != null && rex.line > 0) { Match token = Regex.Match(rex.Message, "found '([^']+)"); if (!token.Success) token = Regex.Match(rex.Message, "\"([^\"]+)"); // find token position if (token.Success) { string tok = token.Groups[1].Value; int p = line.IndexOf(tok); if (p > 0) { p = sci.MBSafeTextLength(line.Substring(0, p)); int len = sci.MBSafeTextLength(tok); return result + "characters " + p + "-" + (p + len) + " : " + rex.Message; } } // fix column index else { for (int i = 0; i < line.Length; i++) if (line[i] == '\t') col -= 7; else if (line[i] != ' ') break; } } return result + "character "+Math.Max(0, col)+" : "+rex.Message; } catch (TokenStreamRecognitionException trex) { int col = trex.recog.column; if (trex.recog.line > 0) { // fix column index string line = sci.GetLine(trex.recog.line - 1); for (int i = 0; i < line.Length; i++) if (line[i] == '\t') col -= 7; else if (line[i] != ' ') break; } return fileName + ":" + trex.recog.line + ": character " + col + " : " + trex.Message; } catch (TokenStreamException tex) { return fileName + ": IO Error: " + tex.Message; } catch (Exception ex) { return fileName + ": Validator Exception: " + ex.Message; } return null; }
private static bool RemoveOneLocalDeclaration(ScintillaNet.ScintillaControl Sci, MemberModel contextMember) { string type = ""; if (contextMember.Type != null && (contextMember.Flags & FlagType.Inferred) == 0) { type = FormatType(contextMember.Type); if (type.IndexOf('*') > 0) type = type.Replace("/*", @"/\*\s*").Replace("*/", @"\s*\*/"); type = @":\s*" + type; } Regex reDecl = new Regex(String.Format(@"[\s\(]((var|const)\s+{0}\s*{1})\s*", contextMember.Name, type)); for (int i = contextMember.LineFrom; i <= contextMember.LineTo + 10; i++) { string text = Sci.GetLine(i); Match m = reDecl.Match(text); if (m.Success) { int index = Sci.MBSafeTextLength(text.Substring(0, m.Groups[1].Index)); int position = Sci.PositionFromLine(i) + index; int len = Sci.MBSafeTextLength(m.Groups[1].Value); Sci.SetSel(position, position + len); if (contextMember.Type == null || (contextMember.Flags & FlagType.Inferred) != 0) Sci.ReplaceSel(contextMember.Name + " "); else Sci.ReplaceSel(contextMember.Name); UpdateLookupPosition(position, contextMember.Name.Length - len); return true; } } return false; }
public static MemberModel GetTemplateBlockMember(ScintillaNet.ScintillaControl Sci, string blockTmpl) { blockTmpl = blockTmpl.Replace("\n", LineEndDetector.GetNewLineMarker(Sci.EOLMode)); int lineNum = 0; while (lineNum < Sci.LineCount) { string line = Sci.GetLine(lineNum); int funcBlockIndex = line.IndexOf(blockTmpl); if (funcBlockIndex != -1) { MemberModel latest = new MemberModel(); latest.LineFrom = lineNum; latest.LineTo = lineNum; return latest; } lineNum++; } return null; }
public static bool RenameMember(ScintillaNet.ScintillaControl Sci, MemberModel member, string newName) { ContextFeatures features = ASContext.Context.Features; string kind = features.varKey; if ((member.Flags & FlagType.Getter) > 0) kind = features.getKey; else if ((member.Flags & FlagType.Setter) > 0) kind = features.setKey; else if (member.Flags == FlagType.Function) kind = features.functionKey; Regex reMember = new Regex(String.Format(@"{0}\s+({1})[\s:]", kind, member.Name)); string line; Match m; int index, position; for (int i = member.LineFrom; i <= member.LineTo; i++) { line = Sci.GetLine(i); m = reMember.Match(line); if (m.Success) { index = Sci.MBSafeTextLength(line.Substring(0, m.Groups[1].Index)); position = Sci.PositionFromLine(i) + index; Sci.SetSel(position, position + member.Name.Length); Sci.ReplaceSel(newName); UpdateLookupPosition(position, 1); return true; } } return false; }
public static MemberModel GetTemplateBlockMember(ScintillaNet.ScintillaControl Sci, string blockTmpl) { if (string.IsNullOrEmpty(blockTmpl)) return null; string firstLine = blockTmpl; int lineCount = 0; int index = blockTmpl.IndexOf("\n"); if (index != -1) { firstLine = blockTmpl.Substring(0, index); lineCount = Regex.Matches(blockTmpl, "\n").Count; } int lineNum = 0; while (lineNum < Sci.LineCount) { string line = Sci.GetLine(lineNum); int funcBlockIndex = line.IndexOf(firstLine); if (funcBlockIndex != -1) { MemberModel latest = new MemberModel(); latest.LineFrom = lineNum; latest.LineTo = lineNum; latest.LineTo = lineNum + lineCount; return latest; } lineNum++; } return null; }
static public void ContextualGenerator(ScintillaNet.ScintillaControl Sci) { if (ASContext.Context is ASContext) (ASContext.Context as ASContext).UpdateCurrentFile(false); // update model if ((ASContext.Context.CurrentClass.Flags & (FlagType.Enum | FlagType.TypeDef)) > 0) return; lookupPosition = -1; int position = Sci.CurrentPos; if (Sci.BaseStyleAt(position) == 19) // on keyword return; bool isNotInterface = (ASContext.Context.CurrentClass.Flags & FlagType.Interface) == 0; 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 (isNotInterface && !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 (isNotInterface && resolve.Member != null && (((resolve.Member.Flags & FlagType.AutomaticVar) > 0) || (resolve.InClass != null && resolve.InClass.QualifiedName == "Object"))) { resolve.Member = null; resolve.Type = null; } if (isNotInterface && 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 && resolve.Member == null) // import declaration { if ((resolve.Type == null || resolve.Type.IsVoid() || !ASContext.Context.IsImported(resolve.Type, line)) && CheckAutoImport(found)) return; if (resolve.Type == null) { int stylemask = (1 << Sci.StyleBits) - 1; suggestItemDeclaration = ASComplete.IsTextStyle(Sci.StyleAt(position - 1) & stylemask); } } if (isNotInterface && 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; } 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; 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.CurrentLine); 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 != ClassModel.VoidClass && found.inClass.Implements != null && found.inClass.Implements.Count > 0) { string funcName = found.member.Name; FlagType flags = found.member.Flags & ~FlagType.Access; 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); foreach (MemberModel m in cm.Members) { if (m.Name.Equals(funcName) && m.Flags.Equals(flags)) { skip = true; break; } } if (!skip) { interfaces.Add(interf); } } if (interfaces.Count > 0) { ShowAddInterfaceDefList(found, interfaces); return; } } // "assign var to statement" suggestion int curLine = Sci.CurrentLine; string ln = Sci.GetLine(curLine).TrimEnd(); if (ln.Length > 0 && ln.IndexOf("=") == -1 && ln.Length <= Sci.CurrentPos - Sci.PositionFromLine(curLine)) // cursor at end of line { ShowAssignStatementToVarList(found); return; } } // suggest generate constructor / toString if (isNotInterface && found.member == null && found.inClass != ClassModel.VoidClass && contextToken == null) { bool hasConstructor = false; bool hasToString = false; foreach (MemberModel m in ASContext.Context.CurrentClass.Members) { if (!hasConstructor && (m.Flags & FlagType.Constructor) > 0) hasConstructor = true; if (!hasToString && (m.Flags & FlagType.Function) > 0 && m.Name.Equals("toString")) hasToString = true; } if (!hasConstructor || !hasToString) { ShowConstructorAndToStringList(found, hasConstructor, hasToString); return; } } if (isNotInterface && resolve.Member != null && resolve.Type != null && resolve.Type.QualifiedName == "String" && found.inClass != ClassModel.VoidClass) { int lineStartPos = Sci.PositionFromLine(Sci.CurrentLine); 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? }
/// <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; }