/// <summary> /// Adds a node to the children collection /// </summary> /// <param name="node"></param> public void AddNode(IntellisenseEntry node) { lock (Children) { this.Children.Add(node); } }
/// <summary> /// Called when the text in the TextBox changes. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void EditorTextChanged(object sender, EventArgs e) { Text = _editor.Text; if (_popup != null) { string inputText = Text; if (inputText.ToLowerInvariant().StartsWith("new")) { inputText = inputText.Substring(3).Trim(); } IntellisenseEntry targetNode = await IntellisenseData.SearchNodesAsync(AddScopedNamespaces(inputText)) ?? IntellisenseData; if (targetNode.Children.Count == 0) { DestroyPopup(); } else { _popup.DataContext = targetNode.Children; } } var textChanged = TextChanged; if (textChanged != null) { textChanged.Invoke(this, EventArgs.Empty); } }
/// <summary> /// Internal search mechanism /// </summary> /// <param name="targetNodes"></param> /// <param name="namePath"></param> /// <returns></returns> private IntellisenseEntry SearchNodesInternal(IntellisenseEntry targetNodes, string namePath) { var targetPath = namePath.Split('.')[0]; if (string.IsNullOrWhiteSpace(targetPath)) { return(targetNodes); } var validNodes = (targetNodes.Children.Where(str => String.Equals(str.Name, targetPath, StringComparison.InvariantCultureIgnoreCase))); IntellisenseEntry locatedNode = validNodes.FirstOrDefault(); if (locatedNode == null) { return(targetNodes); } string nextPath = namePath.Substring(targetPath.Length, namePath.Length - targetPath.Length); if (nextPath.StartsWith(".")) { nextPath = nextPath.Substring(1, nextPath.Length - 1); } return(string.IsNullOrWhiteSpace(nextPath) ? locatedNode : SearchNodesInternal(locatedNode, nextPath)); }
/// <summary> /// Sorts the nodes /// </summary> /// <param name="targetNodes"></param> private static void SortNodes(IntellisenseEntry targetNodes) { targetNodes.Children.Sort(new ComparerName()); foreach (IntellisenseEntry node in targetNodes.Children) { SortNodes(node); } }
/// <summary> /// Locate the best node from a set of paths. /// </summary> /// <param name="namePaths"></param> /// <returns></returns> public async Task <IntellisenseEntry> SearchNodesAsync(IEnumerable <string> namePaths) { var results = await Task.WhenAll( namePaths.Select(n => Task.Run(() => SearchNodesInternal(this, n))).ToArray()); var node = new IntellisenseEntry(); node.Children.AddRange(results.SelectMany(r => r.RestrictViewToPartialType(namePaths.First()))); return(node); }
/// <summary> /// This commits the text to the text box from the intellisense prompt. /// </summary> /// <param name="selectedNodes"></param> private void CommitIntellisenseNode(IntellisenseEntry selectedNodes) { string str = _startText + selectedNodes.Name; DestroyPopup(); _editor.Text = str; _editor.SelectionStart = _editor.Text.Length; _editor.UpdateLayout(); }
/// <summary> /// Called when a double-click occurs on the intellisense window item. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ListItemDoubleClick(object sender, MouseButtonEventArgs e) { IntellisenseEntry dataContext = _popup.SelectedItem; if (dataContext != null) { _editor.Focus(); CommitIntellisenseNode(dataContext); } }
/// <summary> /// This updates the known intellisense to include defined variables. /// </summary> /// <param name="vars"></param> /// <returns></returns> private IntellisenseEntry CreateUpdatedIntellisense(IEnumerable <ModelItem> vars) { IntellisenseEntry tn = new IntellisenseEntry(); tn.Children.AddRange(_intellisenseData.Result.Children); lock (_guard) { int count = 0; foreach (var vs in vars) { var vsProp = vs.Properties["Name"]; if (vsProp == null) { continue; } var varName = vsProp.ComputedValue as String; var res = tn.Children.Where(x => x.Name == varName).ToList(); if (res.Count == 0) { Type sysType = null; var sysTypeProp = vs.Properties["Type"]; if (sysTypeProp != null) { sysType = (Type)sysTypeProp.ComputedValue; } var node = new IntellisenseEntry { Name = varName, Type = IntellisenseEntryType.Primitive, SystemType = sysType, Description = string.Empty }; if (sysType != null) { var tempNode = new IntellisenseEntry(); IntellisenseBuilder.AddTypeNode(tempNode, sysType, true); node.Children.AddRange(tempNode.Children[0].Children); } tn.Children.Insert(count++, node); } } } return(tn); }
private static void AddNestedTypeNode(IntellisenseEntry targetNodes, Type target) { foreach ( Type val in target.GetNestedTypes(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { var memberNodes = new IntellisenseEntry { Name = val.Name, SimpleName = val.Name, Type = IntellisenseEntryType.Method, Parent = targetNodes, }; targetNodes.AddNode(memberNodes); } }
/// <summary> /// Add an event node into the intellisense graph /// </summary> /// <param name="targetNodes"></param> /// <param name="target"></param> private static void AddEventNode(IntellisenseEntry targetNodes, Type target) { foreach ( EventInfo val in target.GetEvents(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { var memberNodes = new IntellisenseEntry { Name = val.Name, SimpleName = val.Name, Type = IntellisenseEntryType.Event, Parent = targetNodes, Description = CreateEventDescription(val), }; targetNodes.AddNode(memberNodes); } }
/// <summary> /// Called when a keypress occurs in the intellisense window. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ListKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) { DestroyPopup(); _editor.Focus(); } else if (e.Key == Key.Return || e.Key == Key.Space || e.Key == Key.Tab) { _editor.Focus(); IntellisenseEntry selectedItem = _popup.SelectedItem; if (selectedItem != null) { string fullPath = selectedItem.FullPath; _editor.Text = _startText + fullPath; _editor.SelectionStart = _editor.Text.Length; DestroyPopup(); } } }
/// <summary> /// Adds a node into the intellisense graph /// </summary> /// <param name="targetNodes"></param> /// <param name="namePath"></param> /// <param name="isNamespace"></param> private static void AddNode(IntellisenseEntry targetNodes, string namePath, bool isNamespace) { IntellisenseEntry existsNode; string[] targetPath = namePath.Split('.'); List <IntellisenseEntry> validNode = targetNodes.Children.Where( x => String.Equals(x.Name, targetPath[0], StringComparison.InvariantCultureIgnoreCase)).ToList(); if (validNode.Count > 0) { existsNode = validNode[0]; } else { existsNode = new IntellisenseEntry { Name = targetPath[0], SimpleName = targetPath[0], Type = (isNamespace) ? IntellisenseEntryType.Namespace : IntellisenseEntryType.Primitive, Parent = targetNodes, Description = (isNamespace) ? string.Format("Namespace {0}", targetPath[0]) : "", }; targetNodes.AddNode(existsNode); } if (isNamespace) { string nextPath = namePath.Substring(targetPath[0].Length, namePath.Length - targetPath[0].Length); if (nextPath.StartsWith(".")) { nextPath = nextPath.Substring(1, nextPath.Length - 1); } if (!string.IsNullOrWhiteSpace(nextPath)) { AddNode(existsNode, nextPath); } } }
/// <summary> /// Searches for a specific set of nodes. /// </summary> /// <param name="targetNodes"></param> /// <param name="namePath"></param> /// <returns></returns> private static IntellisenseEntry SearchNodes(IntellisenseEntry targetNodes, string namePath) { string targetPath = namePath.Split('.')[0]; IntellisenseEntry foundNode = targetNodes.Children.FirstOrDefault( str => String.Equals(str.Name, targetPath, StringComparison.CurrentCultureIgnoreCase)); if (foundNode == null) { return(targetNodes); } string nextPath = namePath.Substring(targetPath.Length, namePath.Length - targetPath.Length); if (nextPath.StartsWith(".")) { nextPath = nextPath.Substring(1, nextPath.Length - 1); } return(string.IsNullOrWhiteSpace(nextPath) ? foundNode : SearchNodes(foundNode, nextPath)); }
/// <summary> /// Add a method node into the intellisense graph /// </summary> /// <param name="targetNodes"></param> /// <param name="target"></param> private static void AddMethodNode(IntellisenseEntry targetNodes, Type target) { foreach ( MethodInfo val in target.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)) { // Ignore property implementation methods if (val.IsSpecialName) { continue; } var memberNodes = new IntellisenseEntry { Name = val.Name, SimpleName = val.Name, Type = IntellisenseEntryType.Method, Parent = targetNodes, Description = CreateMethodDescription(val), }; targetNodes.AddNode(memberNodes); } }
/// <summary> /// Loads intellisense for the given assemblies and namespaces. /// </summary> /// <param name="asmList"></param> /// <param name="ignoreNamespaces"></param> /// <returns></returns> private static IntellisenseEntry LoadInternal(IEnumerable <Assembly> asmList, IEnumerable <string> ignoreNamespaces) { if (ignoreNamespaces == null) { ignoreNamespaces = Enumerable.Empty <string>(); } List <Type> typeList = asmList.SelectMany(a => a.GetTypes().Where( x => x.IsPublic && x.IsVisible && x.Namespace != null && !ignoreNamespaces.Any(s => x.Namespace.ToLowerInvariant().Contains(s.ToLowerInvariant())))) .ToList(); var data = new IntellisenseEntry(); foreach (Type type in typeList) { AddNode(data, type.Namespace, true); AddTypeNode(data, type); } SortNodes(data); return(data); }
/// <summary> /// This is called just before a new key is added to the text box. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void EditorPreviewKeyDown(object sender, KeyEventArgs e) { bool isControlKeyDown = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control; // Move up/down the list if (e.Key == Key.Up || e.Key == Key.Down) { if (_popup == null || !_popup.IsOpen) { return; } _popup.SelectedIndex = (e.Key == Key.Up) ? _popup.SelectedIndex - 1 : _popup.SelectedIndex + 1; e.Handled = true; } else if (e.Key == Key.PageUp) { if (_popup == null || !_popup.IsOpen) { return; } _popup.SelectedIndex = _popup.SelectedIndex - 5; e.Handled = true; } else if (e.Key == Key.PageDown) { if (_popup == null || !_popup.IsOpen) { return; } _popup.SelectedIndex = _popup.SelectedIndex + 5; e.Handled = true; } else if (e.Key == Key.Home || e.Key == Key.End) { if (_popup == null || !_popup.IsOpen) { return; } _popup.SelectedIndex = (e.Key == Key.Home) ? 0 : _popup.ItemCount - 1; e.Handled = true; } // Close the popup else if (e.Key == Key.Escape) { DestroyPopup(); _startText = string.Empty; e.Handled = true; } // CTRL+Space or "." else if ((e.Key == Key.Decimal || e.Key == Key.OemPeriod) || (e.Key == Key.Space && isControlKeyDown)) { if (_popup == null || !_popup.IsOpen) { string rawText = _editor.Text; int pos = Math.Max(Math.Max( rawText.LastIndexOf(".", StringComparison.Ordinal), rawText.LastIndexOf("(", StringComparison.Ordinal)), rawText.LastIndexOf(" ", StringComparison.Ordinal)); _startText = (pos == -1) ? rawText : rawText.Substring(0, pos + 1); string inputText = rawText; if (inputText.ToLowerInvariant().StartsWith("new ")) { inputText = inputText.Substring(4); } if (e.Key == Key.Decimal || e.Key == Key.OemPeriod) { inputText = inputText + "."; } IntellisenseEntry intellisenseList = await IntellisenseData.SearchNodesAsync(AddScopedNamespaces(inputText)) ?? IntellisenseData; CreatePopup(intellisenseList.Children); e.Handled = (e.Key == Key.Space && isControlKeyDown); } } else if (e.Key == Key.Return || e.Key == Key.Enter || e.Key == Key.Space || e.Key == Key.Tab) { if (_popup == null || !_popup.IsOpen) { return; } IntellisenseEntry selectedItem = _popup.SelectedItem; if (selectedItem != null) { CommitIntellisenseNode(selectedItem); e.Handled = true; } } }
/// <summary> /// Adds a type node into the intellisense graph /// </summary> /// <param name="targetNodes"></param> /// <param name="target"></param> /// <param name="allowAbstract"></param> internal static void AddTypeNode(IntellisenseEntry targetNodes, Type target, bool allowAbstract = false) { if ((!target.IsAbstract || allowAbstract) && target.IsVisible) { string namePath = target.Namespace; string name = target.Name; IntellisenseEntry nodes = SearchNodes(targetNodes, namePath); string str = name; var node = new IntellisenseEntry { Name = name, SimpleName = name, Parent = nodes, SystemType = target }; if (target.IsGenericType) { node.Type = IntellisenseEntryType.Class; if (name.Contains("`")) { str = name.Substring(0, name.LastIndexOf("`", StringComparison.Ordinal)); node.SimpleName = str; } var builder = new StringBuilder(); int num = 0; foreach (Type type in target.GetGenericArguments()) { if (num > 0) { builder.Append(", "); } builder.Append(type.Name); num++; } str = str + "(" + builder + ")"; node.Name = str; node.Description = string.Format("Class {0}", node.SimpleName); } else if (target.IsClass) { node.Type = IntellisenseEntryType.Class; node.Description = string.Format("Class {0}", node.SimpleName); } else if (target.IsEnum) { node.Type = IntellisenseEntryType.Enum; node.Description = string.Format("Enum {0}", node.SimpleName); } else if (target.IsInterface) { node.Type = IntellisenseEntryType.Interface; node.Description = string.Format("Interface {0}", node.SimpleName); } else if (target.IsPrimitive) { node.Type = IntellisenseEntryType.Primitive; node.Description = string.Format("{0}", node.SimpleName); } else if (target.IsValueType) { node.Type = IntellisenseEntryType.ValueType; node.Description = string.Format("{0}", node.SimpleName); } else { return; } if (nodes == null) { targetNodes.AddNode(node); } else { nodes.AddNode(node); } AddMethodNode(node, target); AddPropertyNode(node, target); AddFieldNode(node, target); AddEventNode(node, target); AddNestedTypeNode(node, target); } }