ICompletionDataList GenerateCompletionData(CodeCompletionContext completionContext, PythonModule module, TextEditorData editor, char completionChar) { var triggerWord = GetTriggerWord (editor, completionContext); // Its annoying when the data is poped up during an assignment such as: // abc = _ if (completionChar == '=' && String.IsNullOrEmpty (triggerWord)) return null; var triggerLine = editor.GetLineText (completionContext.TriggerLine); // if completionChar is ' ' and it is not a known completion type // that we can handle, return as early as possible if (completionChar == ' ') { if (!triggerWord.Contains ('.') && !triggerLine.StartsWith ("class") && !triggerLine.StartsWith ("def") && !triggerLine.StartsWith ("from") && !triggerLine.StartsWith ("import")) return null; } // "self." if (module != null && triggerWord == "self" && completionChar == '.') { var klass = GetClass (module, completionContext.TriggerLine); if (klass == null) return null; // nothing to complete, self not in a class return new CompletionDataList (SelfDotCompletionData (klass)); } var inFrom = triggerLine.StartsWith ("from "); var inClass = triggerLine.StartsWith ("class ") || (triggerLine.StartsWith ("class") && completionChar == ' '); var inDef = triggerLine.StartsWith ("def ") || (triggerLine.StartsWith ("def") && completionChar == ' '); var parts = triggerLine.Split (new char [] { ' ' }, StringSplitOptions.RemoveEmptyEntries); // "from blah " if (inFrom && parts.Length == 2 && completionChar == ' ') { return new CompletionDataList (new CompletionData[] { new CompletionData ("import") }); } // "from blah import " else if (inFrom && parts.Length > 2) { triggerWord = parts [1] + "."; return new CompletionDataList ( from ParserItem item in m_site.Database.Find (triggerWord) where !item.FullName.Substring (triggerWord.Length).Contains ('.') select CreateCompletionData (item, triggerWord)) ; } // if we are in a new class line and not to '(' yet // we cannot complete anything at this time, finish now if (inClass && parts.Length < 2) return null; // if we are in a new def line, the only time we can complete // is after an equal '='. so ignore space trigger if (inDef && completionChar == ' ') return null; else if (inDef && completionChar == '=') triggerWord = ""; if (inClass) { if (completionChar == '(') triggerWord = ""; else triggerWord = triggerLine.Substring (triggerLine.LastIndexOf ('(') + 1); } // limit the depth of search to number of "." in trigger // "xml." has depth of 1 so anything matching ^xml. and no more . with match int depth = 0; foreach (var c in triggerWord) if (c == '.') depth++; // anything in the sqlite store if (!String.IsNullOrEmpty (triggerWord)) { // todo: try to complete on class/module/func/attr data return new CompletionDataList ( from ParserItem item in m_site.Database.Find (triggerWord, ParserItemType.Any, depth) select CreateCompletionData (item, triggerWord)) ; } ParserItemType itemType = String.IsNullOrEmpty (triggerWord) ? ParserItemType.Module : ParserItemType.Any; return new CompletionDataList ( from ParserItem item in m_site.Database.Find ("", itemType, depth) select CreateCompletionData (item, triggerWord)) ; }
static PythonClass GetClass(PythonModule module, int line) { foreach (PythonClass pyClass in module.Classes) if (InRegion (pyClass.Region, line)) return pyClass; // todo: classes in functions? return null; }
public void Reset() { module = new PythonModule (); containers.Clear (); containers.Push (module); }
/// <summary> /// Walks the xml element tree to build a result. This expects /// rootElement to be a <module /> element. /// <param name="rootElement"> /// A <see cref="XmlElement"/> /// </param> /// </summary> /// <param name="rootElement"> /// A <see cref="XmlElement"/> /// </param> void BuildFromXmlElement(XmlElement rootElement, StringReader content) { Debug.Assert (rootElement.LocalName == "module"); string moduleName = String.Empty; if (!String.IsNullOrEmpty (FileName)) moduleName = PythonHelper.ModuleFromFilename (FileName); Module = new PythonModule () { FullName = moduleName, Region = GetDomRegion (rootElement), }; foreach (XmlElement child in rootElement) { switch (child.LocalName) { case "import": BuildImport (child); break; case "class": BuildClass (child); break; case "attribute": BuildAttribute (child); break; case "function": BuildFunction (child); break; case "warning": BuildWarning (child); break; default: Debug.Assert (false, "Assert not reached"); break; } } }
public CustomPythonWalker() { module = new PythonModule (); containers = new Stack<PythonContainerNode> (); containers.Push (module); }