From cbdd79778764ce38017790e1e1f9316e52ec8104 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sun, 10 Mar 2019 09:05:11 +0200 Subject: Working on new scripting editor. --- .../CodeCompletion/CompletionListBoxItem.cs | 14 +- .../CodeCompletion/CompletionWindow.cs | 2 + .../CodeCompletion/CompletionWindowBase.cs | 5 +- .../Converters/BooleanToVisibilityConverter.cs | 24 + .../BooleanToVisibilityInversedConverter.cs | 24 + .../Tango.Scripting.Editors/Editing/Caret.cs | 2 +- .../Highlighting/Resources/CSharp-Mode.xshd | 1 + .../Tango.Scripting.Editors/Images/class.png | Bin 0 -> 212 bytes .../Tango.Scripting.Editors/Images/enum.png | Bin 0 -> 190 bytes .../Tango.Scripting.Editors/Images/interface.png | Bin 0 -> 222 bytes .../Tango.Scripting.Editors/Images/method.png | Bin 0 -> 276 bytes .../Tango.Scripting.Editors/Images/namespace.png | Bin 0 -> 250 bytes .../Tango.Scripting.Editors/Images/property.png | Bin 0 -> 316 bytes .../Tango.Scripting.Editors/Images/pubclass.gif | Bin 290 -> 0 bytes .../Tango.Scripting.Editors/Images/pubevent.gif | Bin 365 -> 0 bytes .../Tango.Scripting.Editors/Images/pubmethod.gif | Bin 599 -> 0 bytes .../Tango.Scripting.Editors/Images/pubproperty.gif | Bin 435 -> 0 bytes .../Tango.Scripting.Editors/Images/struct.png | Bin 0 -> 136 bytes .../Intellisense/KnownType.cs | 323 ++++++++++ .../Intellisense/KnownTypeConstructor.cs | 27 + .../Intellisense/KnownTypeMember.cs | 29 + .../Intellisense/KnownTypeMethod.cs | 25 + .../Intellisense/KnownTypeMethodParameter.cs | 16 + .../Intellisense/KnownTypeProperty.cs | 21 + .../Popups/MethodDescription.cs | 20 + .../Tango.Scripting.Editors/Popups/MethodPopup.cs | 82 +++ .../Popups/ParameterDescription.cs | 26 + .../Tango.Scripting.Editors/Rendering/TextView.cs | 22 +- .../Tango.Scripting.Editors/ScriptEditor.cs | 717 ++++++++++++++++++--- .../Tango.Scripting.Editors.csproj | 40 +- .../Tango.Scripting.Editors/Themes/Generic.xaml | 248 ++++++- .../Tango.Scripting/Parsing/DetectedType.cs | 13 - .../Tango.Scripting/Parsing/ScriptParser.cs | 71 +- .../Tango.Scripting/Tango.Scripting.csproj | 1 - 34 files changed, 1575 insertions(+), 178 deletions(-) create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityConverter.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityInversedConverter.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/class.png create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/enum.png create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/interface.png create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/method.png create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/namespace.png create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/property.png delete mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubclass.gif delete mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubevent.gif delete mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubmethod.gif delete mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubproperty.gif create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/struct.png create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeConstructor.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMember.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethod.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethodParameter.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeProperty.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodDescription.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodPopup.cs create mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/ParameterDescription.cs delete mode 100644 Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting/Parsing/DetectedType.cs (limited to 'Software/Visual_Studio/TEMP/Tango.Scripting') diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionListBoxItem.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionListBoxItem.cs index bb6acf69e..55d752bfd 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionListBoxItem.cs +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionListBoxItem.cs @@ -42,11 +42,15 @@ namespace Tango.Scripting.Editors.CodeCompletion protected override void OnSelected(RoutedEventArgs e) { - base.OnSelected(e); - toolTip.Content = DataContext; - toolTip.ContentTemplate = ToolTipContentTemplate; - toolTip.StaysOpen = true; - toolTip.IsOpen = true; + try + { + base.OnSelected(e); + toolTip.Content = DataContext; + toolTip.ContentTemplate = ToolTipContentTemplate; + toolTip.StaysOpen = true; + toolTip.IsOpen = true; + } + catch { } } protected override void OnUnselected(RoutedEventArgs e) diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindow.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindow.cs index 0e8cd781d..33759e351 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindow.cs +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindow.cs @@ -84,6 +84,8 @@ namespace Tango.Scripting.Editors.CodeCompletion { InsertionRequest?.Invoke(item); } + + completionList.SelectedItem = null; } void AttachEvents() diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindowBase.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindowBase.cs index b5bab3f97..e33ede203 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindowBase.cs +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/CodeCompletion/CompletionWindowBase.cs @@ -79,6 +79,7 @@ namespace Tango.Scripting.Editors.CodeCompletion public virtual void HideCompletion() { + Debug.WriteLine("Hide Completion..."); DetachEvents(); Hide(); } @@ -148,7 +149,7 @@ namespace Tango.Scripting.Editors.CodeCompletion public override void Detach() { base.Detach(); - window.HideCompletion(); + //window.HideCompletion(); } const Key KeyDeadCharProcessed = (Key)0xac; // Key.DeadCharProcessed; // new in .NET 4 @@ -367,6 +368,8 @@ namespace Tango.Scripting.Editors.CodeCompletion bounds = bounds.TransformFromDevice(textView); this.Left = bounds.X; this.Top = bounds.Y; + + Debug.WriteLine($"Position: {Left}x{Top}"); } /// diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityConverter.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityConverter.cs new file mode 100644 index 000000000..7412e4a67 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace Tango.Scripting.Editors.Converters +{ + public class BooleanToVisibilityConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value ? Visibility.Visible : Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityInversedConverter.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityInversedConverter.cs new file mode 100644 index 000000000..c91aa45fd --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Converters/BooleanToVisibilityInversedConverter.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; + +namespace Tango.Scripting.Editors.Converters +{ + public class BooleanToVisibilityInversedConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + return (bool)value ? Visibility.Collapsed : Visibility.Visible; + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Editing/Caret.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Editing/Caret.cs index 23542cd21..fb21448e5 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Editing/Caret.cs +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Editing/Caret.cs @@ -267,7 +267,7 @@ namespace Tango.Scripting.Editors.Editing if (!visualColumnValid) { TextDocument document = textArea.Document; if (document != null) { - Debug.WriteLine("Explicit validation of caret column"); + //Debug.WriteLine("Explicit validation of caret column"); var documentLine = document.GetLineByNumber(position.Line); RevalidateVisualColumn(textView.GetOrConstructVisualLine(documentLine)); } diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd index a8ca62be2..1ba2cbc6f 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Highlighting/Resources/CSharp-Mode.xshd @@ -220,6 +220,7 @@ uint ushort ulong + null diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/class.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/class.png new file mode 100644 index 000000000..91b35a829 Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/class.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/enum.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/enum.png new file mode 100644 index 000000000..b79aa844f Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/enum.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/interface.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/interface.png new file mode 100644 index 000000000..3b07597dd Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/interface.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/method.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/method.png new file mode 100644 index 000000000..249689941 Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/method.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/namespace.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/namespace.png new file mode 100644 index 000000000..7f2b6b5ef Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/namespace.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/property.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/property.png new file mode 100644 index 000000000..001a8c66a Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/property.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubclass.gif b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubclass.gif deleted file mode 100644 index 28abc36a7..000000000 Binary files a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubclass.gif and /dev/null differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubevent.gif b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubevent.gif deleted file mode 100644 index 7c2466f0e..000000000 Binary files a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubevent.gif and /dev/null differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubmethod.gif b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubmethod.gif deleted file mode 100644 index 040280d15..000000000 Binary files a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubmethod.gif and /dev/null differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubproperty.gif b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubproperty.gif deleted file mode 100644 index 49d5042b9..000000000 Binary files a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/pubproperty.gif and /dev/null differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/struct.png b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/struct.png new file mode 100644 index 000000000..02fbdbde7 Binary files /dev/null and b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Images/struct.png differ diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs new file mode 100644 index 000000000..3cb61b991 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownType.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using System.Xml; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class KnownType + { + private static String dotNetXmlFolder = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.X"; + private static Dictionary _assemblies_docs_cache; + + private bool _initialized; + + public Type Type { get; private set; } + public String Name { get; private set; } + public String TypeDefinition { get; private set; } + public String FriendlyName { get; private set; } + + private String _summary; + public String Summary + { + get + { + InitTypeDocumentation(); + return _summary; + } + private set { _summary = value; } + } + + + private List _constructors; + public List Constructors + { + get + { + InitTypeDocumentation(); + return _constructors; + } + private set { _constructors = value; } + } + + private List _methods; + public List Methods + { + get + { + InitTypeDocumentation(); + return _methods; + } + private set { _methods = value; } + } + + private List _properties; + public List Properties + { + get + { + InitTypeDocumentation(); + return _properties; + } + private set { _properties = value; } + } + + public List Members + { + get + { + List members = new List(); + + members.AddRange(Properties); + members.AddRange(Methods); + + return members.OrderBy(x => x.Name).ToList(); + } + } + + static KnownType() + { + _assemblies_docs_cache = new Dictionary(); + } + + public KnownType(Type type) + { + _constructors = new List(); + _methods = new List(); + _properties = new List(); + Type = type; + Name = type.Name; + Init(); + } + + private void Init() + { + InitTypeDefinition(); + InitFriendlyName(); + } + + private void InitFriendlyName() + { + if (Type.IsGenericType) + { + List args = new List(); + + foreach (var lGenericArgument in Type.GetGenericTypeDefinition().GetGenericArguments()) + { + args.Add(lGenericArgument.Name); + } + + String gArgs = String.Join(",", args); + + FriendlyName = $"{new String(Type.Name.TakeWhile(x => x != '`').ToArray())}<{gArgs}>"; + } + else + { + FriendlyName = Type.Name; + } + } + + private void InitTypeDefinition() + { + if (Type.IsClass) TypeDefinition = "class"; + else if (Type.IsEnum) TypeDefinition = "enum"; + else if (Type.IsInterface) TypeDefinition = "interface"; + else if (Type.IsValueType) TypeDefinition = "struct"; + } + + private void InitTypeDocumentation() + { + if (!_initialized) + { + XmlDocument xmlDoc = null; + + if (_assemblies_docs_cache.ContainsKey(Type.Assembly)) + { + xmlDoc = _assemblies_docs_cache[Type.Assembly]; + } + + if (xmlDoc == null) + { + String dllPath = Type.Assembly.Location; + + string docuPath = dllPath.Substring(0, dllPath.LastIndexOf(".")) + ".XML"; + + if (File.Exists(docuPath)) + { + xmlDoc = new XmlDocument(); + xmlDoc.Load(docuPath); + } + else if (File.Exists(System.IO.Path.Combine(dotNetXmlFolder, System.IO.Path.GetFileName(docuPath)))) + { + xmlDoc = new XmlDocument(); + xmlDoc.Load(System.IO.Path.Combine(dotNetXmlFolder, System.IO.Path.GetFileName(docuPath))); + } + + if (xmlDoc != null) + { + _assemblies_docs_cache.Add(Type.Assembly, xmlDoc); + } + } + + if (xmlDoc != null) + { + //Load Type Summary + { + string path = "T:" + Type.FullName; + XmlNode xmlDocuOfType = xmlDoc.SelectSingleNode("//member[starts-with(@name, '" + path + "')]"); + + if (xmlDocuOfType != null) + { + XmlNode summaryNode = xmlDocuOfType.SelectSingleNode("summary"); + Summary = summaryNode.InnerText; + } + } + + //Load Constructors... + { + string path = "M:" + Type.FullName + ".#ctor"; + + var docNodes = xmlDoc.SelectNodes("//member[starts-with(@name, '" + path + "')]").OfType().ToList(); + var constructors = Type.GetConstructors().Where(x => x.IsPublic).ToList(); + + for (int i = 0; i < constructors.Count; i++) + { + var constructor = constructors[i]; + XmlNode cDoc = null; + + if (i < docNodes.Count) + { + cDoc = docNodes[i]; + } + + KnownTypeConstructor c = new KnownTypeConstructor(this); + c.Summary = cDoc != null ? cDoc.SelectSingleNode("summary").InnerText : $"Initializes a new instance of {FriendlyName}."; + + var parameters = constructor.GetParameters().ToList(); + var parametersNodes = cDoc != null ? cDoc.SelectNodes("param").OfType().ToList() : new List(); + + for (int j = 0; j < parameters.Count; j++) + { + var parameter = parameters[j]; + XmlNode pNode = null; + + if (j < parametersNodes.Count) + { + pNode = parametersNodes[j]; + } + + KnownTypeMethodParameter p = new KnownTypeMethodParameter(); + p.Type = parameter.ParameterType; + p.Name = parameter.Name; + p.Description = pNode != null ? pNode.InnerText : null; + + if (j == parameters.Count - 1) + { + p.IsLast = true; + } + + c.Parameters.Add(p); + } + + _constructors.Add(c); + } + } + + //Load Methods... + { + string path = "M:" + Type.FullName; + + var docNodes = xmlDoc.SelectNodes("//member[starts-with(@name, '" + path + "')]").OfType().ToList(); + var methods = Type.GetRuntimeMethods().Where(x => x.IsPublic && !x.IsSpecialName).ToList(); + + //TODO: Separate extension methods! + methods.AddRange(Type.GetExtensionMethods(Type.Assembly).ToList()); + + for (int i = 0; i < methods.Count; i++) + { + var method = methods[i]; + XmlNode mDoc = null; + + mDoc = docNodes.FirstOrDefault(x => x.Attributes["name"].InnerText.Contains(method.DeclaringType.Name + "." + method.Name)); + + KnownTypeMethod m = new KnownTypeMethod(this); + m.Summary = mDoc != null ? mDoc.SelectSingleNode("summary").InnerText : "No documentation"; + m.Name = method.Name; + m.ReturnType = method.ReturnType; + m.ReturnTypeFriendlyName = method.ReturnType.Name; + + if (method.ReturnType.IsGenericType) + { + List args = new List(); + + foreach (var lGenericArgument in m.ReturnType.GetGenericTypeDefinition().GetGenericArguments()) + { + args.Add(lGenericArgument.Name); + } + + String gArgs = String.Join(",", args); + + m.ReturnTypeFriendlyName = $"{new String(Type.Name.TakeWhile(x => x != '`').ToArray())}<{gArgs}>"; + } + + var parameters = method.GetParameters().ToList(); + var parametersNodes = mDoc != null ? mDoc.SelectNodes("param").OfType().ToList() : new List(); + + for (int j = 0; j < parameters.Count; j++) + { + var parameter = parameters[j]; + XmlNode pNode = null; + + if (j < parametersNodes.Count) + { + pNode = parametersNodes[j]; + } + + KnownTypeMethodParameter p = new KnownTypeMethodParameter(); + p.Type = parameter.ParameterType; + p.Name = parameter.Name; + p.Description = pNode != null ? pNode.InnerText : null; + + if (j == parameters.Count - 1) + { + p.IsLast = true; + } + + m.Parameters.Add(p); + } + + _methods.Add(m); + } + } + + //Load Properties + { + string path = "P:" + Type.FullName; + + var docNodes = xmlDoc.SelectNodes("//member[starts-with(@name, '" + path + "')]").OfType().ToList(); + var properties = Type.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.PropertyType.IsPublic).ToList(); + + for (int i = 0; i < properties.Count; i++) + { + var property = properties[i]; + var pDoc = docNodes.FirstOrDefault(x => x.Attributes["name"].InnerText.Contains(property.DeclaringType.Name + "." + property.Name)); + + KnownTypeProperty p = new KnownTypeProperty(this); + p.Summary = pDoc != null ? pDoc.SelectSingleNode("summary").InnerText : "No documentation"; + p.Name = property.Name; + p.ReturnType = property.PropertyType; + + _properties.Add(p); + } + } + } + + _initialized = true; + } + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeConstructor.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeConstructor.cs new file mode 100644 index 000000000..273d61084 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeConstructor.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class KnownTypeConstructor + { + public KnownType Type { get; set; } + + public String Summary { get; set; } + + public List Parameters { get; set; } + + public KnownTypeConstructor() + { + Parameters = new List(); + } + + public KnownTypeConstructor(KnownType knownType) : this() + { + Type = knownType; + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMember.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMember.cs new file mode 100644 index 000000000..d3d8cb428 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMember.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Intellisense +{ + public abstract class KnownTypeMember + { + public Type ReturnType { get; set; } + + public KnownType Type { get; set; } + + public String Summary { get; set; } + + public String Name { get; set; } + + public KnownTypeMember() + { + + } + + public KnownTypeMember(KnownType knownType) : this() + { + Type = knownType; + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethod.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethod.cs new file mode 100644 index 000000000..27b052978 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethod.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class KnownTypeMethod : KnownTypeMember + { + public String ReturnTypeFriendlyName { get; set; } + + public List Parameters { get; set; } + + public KnownTypeMethod() + { + Parameters = new List(); + } + + public KnownTypeMethod(KnownType knownType) : this() + { + Type = knownType; + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethodParameter.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethodParameter.cs new file mode 100644 index 000000000..c4f2a62c5 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeMethodParameter.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class KnownTypeMethodParameter + { + public Type Type { get; set; } + public String Name { get; set; } + public String Description { get; set; } + public bool IsLast { get; set; } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeProperty.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeProperty.cs new file mode 100644 index 000000000..a77dd7dc2 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Intellisense/KnownTypeProperty.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Intellisense +{ + public class KnownTypeProperty : KnownTypeMember + { + public KnownTypeProperty() + { + + } + + public KnownTypeProperty(KnownType knownType) : this() + { + Type = knownType; + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodDescription.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodDescription.cs new file mode 100644 index 000000000..864072952 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodDescription.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Popups +{ + public class MethodDescription + { + public String Description { get; set; } + public String ReturnType { get; set; } + public List Parameters { get; set; } + + public MethodDescription() + { + Parameters = new List(); + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodPopup.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodPopup.cs new file mode 100644 index 000000000..7c431f9b4 --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/MethodPopup.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace Tango.Scripting.Editors.Popups +{ + public class MethodPopup : Control + { + public List Methods { get; set; } + + public int CurrentMethodIndex + { + get { return (int)GetValue(CurrentMethodIndexProperty); } + set { SetValue(CurrentMethodIndexProperty, value); } + } + public static readonly DependencyProperty CurrentMethodIndexProperty = + DependencyProperty.Register("CurrentMethodIndex", typeof(int), typeof(MethodPopup), new PropertyMetadata(1)); + + public MethodDescription CurrentMethod + { + get { return (MethodDescription)GetValue(CurrentMethodProperty); } + set { SetValue(CurrentMethodProperty, value); } + } + public static readonly DependencyProperty CurrentMethodProperty = + DependencyProperty.Register("CurrentMethod", typeof(MethodDescription), typeof(MethodPopup), new PropertyMetadata(null)); + + public void IncrementMethod() + { + if (Methods.Count > 0) + { + if (CurrentMethodIndex < Methods.Count) + { + CurrentMethodIndex++; + CurrentMethod = Methods[CurrentMethodIndex - 1]; + } + else + { + CurrentMethodIndex = 1; + CurrentMethod = Methods[0]; + } + } + } + + public void DecrementMethod() + { + if (Methods.Count > 0) + { + if (CurrentMethodIndex > 1) + { + CurrentMethodIndex--; + CurrentMethod = Methods[CurrentMethodIndex - 1]; + } + else + { + CurrentMethodIndex = Methods.Count; + CurrentMethod = Methods[Methods.Count - 1]; + } + } + } + + public MethodPopup() + { + Methods = new List(); + } + + static MethodPopup() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(MethodPopup), new FrameworkPropertyMetadata(typeof(MethodPopup))); + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/ParameterDescription.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/ParameterDescription.cs new file mode 100644 index 000000000..6650f76ec --- /dev/null +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Popups/ParameterDescription.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting.Editors.Popups +{ + public class ParameterDescription + { + public ParameterDescription(MethodDescription method) + { + Method = method; + } + + public MethodDescription Method { get; set; } + public String Type { get; set; } + public String Name { get; set; } + public String Description { get; set; } + + public bool IsLast + { + get { return Method.Parameters.Last() == this; } + } + } +} diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Rendering/TextView.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Rendering/TextView.cs index 6bbf13618..3dabb6b7a 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Rendering/TextView.cs +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Rendering/TextView.cs @@ -800,9 +800,14 @@ namespace Tango.Scripting.Editors.Rendering [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] public ReadOnlyCollection VisualLines { get { - if (visibleVisualLines == null) - throw new VisualLinesInvalidException(); - return visibleVisualLines; + if (visibleVisualLines == null) + { + return new ReadOnlyCollection(new List()); + } + else + { + return visibleVisualLines; + } } } @@ -848,11 +853,12 @@ namespace Tango.Scripting.Editors.Rendering // Sometimes we still have invalid lines after UpdateLayout - work around the problem // by calling MeasureOverride directly. if (!VisualLinesValid) { - Debug.WriteLine("UpdateLayout() failed in EnsureVisualLines"); - MeasureOverride(lastAvailableSize); - } - if (!VisualLinesValid) - throw new VisualLinesInvalidException("Internal error: visual lines invalid after EnsureVisualLines call"); + //Debug.WriteLine("UpdateLayout() failed in EnsureVisualLines"); + //MeasureOverride(lastAvailableSize); + // UpdateLayout(); + } + //if (!VisualLinesValid) + //throw new VisualLinesInvalidException("Internal error: visual lines invalid after EnsureVisualLines call"); } #endregion diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/ScriptEditor.cs b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/ScriptEditor.cs index 316b95ed7..3370ca0ee 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/ScriptEditor.cs +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/ScriptEditor.cs @@ -1,4 +1,5 @@ using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -11,6 +12,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; @@ -27,6 +29,9 @@ using Tango.Scripting.Editors.Editing; using Tango.Scripting.Editors.Folding; using Tango.Scripting.Editors.Highlighting; using Tango.Scripting.Editors.Highlighting.Xshd; +using Tango.Scripting.Editors.Intellisense; +using Tango.Scripting.Editors.Popups; +using Tango.Scripting.Editors.Rendering; using Tango.Scripting.Parsing; namespace Tango.Scripting.Editors @@ -35,18 +40,16 @@ namespace Tango.Scripting.Editors { private char[] word_separators = { ' ', '\t', '\n', '.', '(', ',', '-', '*', '/', '+', '$', '=' }; private string[] _blocking_type_words = { "class", "void" }; - private String dotNetXmlFolder = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.X"; private DispatcherTimer _update_timer; + private Popup _popup; private FoldingManager foldingManager; private BraceFoldingStrategy foldingStrategy; private CompletionWindow completionWindow; private ScriptParser _parser; private List _current_usings; - private List _knownTypes; + private List _knownTypes; private List _declaredTypes; - private Dictionary _known_types_docs_cache; - private Dictionary _assemblies_docs_cache; #region Mini Classes @@ -56,6 +59,20 @@ namespace Tango.Scripting.Editors public int Index { get; set; } } + private class ConstructionSession + { + public KnownType Type { get; set; } + public int ParameterIndex { get; set; } + public List TypeArguments { get; set; } + } + + private class MethodSession + { + public KnownType Type { get; set; } + public int ParameterIndex { get; set; } + public List TypeArguments { get; set; } + } + #endregion #region Completion @@ -64,7 +81,7 @@ namespace Tango.Scripting.Editors /// Represents an auto complete item. /// /// - internal class CompletionData : DependencyObject, ICompletionData + internal class TypeCompletionData : DependencyObject, ICompletionData { private String _description; @@ -74,12 +91,13 @@ namespace Tango.Scripting.Editors public BitmapSource Source { get; set; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The text. /// The description. - public CompletionData(String type, string name, String ns, String description) + public TypeCompletionData(String type, string name, String ns, String description) { + Type = type; this.Text = name; Namespace = ns; @@ -143,7 +161,7 @@ namespace Tango.Scripting.Editors set { SetValue(IsSelectedProperty, value); } } public static readonly DependencyProperty IsSelectedProperty = - DependencyProperty.Register("IsSelected", typeof(bool), typeof(CompletionData), new PropertyMetadata(false, IsSelectedChanged)); + DependencyProperty.Register("IsSelected", typeof(bool), typeof(TypeCompletionData), new PropertyMetadata(false, IsSelectedChanged)); private static void IsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { @@ -164,6 +182,209 @@ namespace Tango.Scripting.Editors } } + internal class MethodCompletionData : DependencyObject, ICompletionData + { + private String _description; + + /// + /// Gets or sets the icon source. + /// + public BitmapSource Source { get; set; } + + public String ReturnType { get; set; } + + public String Type { get; set; } + + public String Class { get; set; } + + public int Overloads { get; set; } + + public List Parameters { get; set; } + + public bool HasOverloads + { + get { return Overloads > 0; } + } + + public MethodCompletionData(String cls, string name, String returnType, String description, List parameters, int overloads) + { + Type = "method"; + Parameters = parameters; + Class = cls; + this.Text = name; + Overloads = overloads; + ReturnType = returnType; + _description = description; + } + + /// + /// Gets the image. + /// + public System.Windows.Media.ImageSource Image + { + get { return Source; } + } + + /// + /// Gets the text. This property is used to filter the list of visible elements. + /// + public string Text { get; private set; } + + // Use this property if you want to show a fancy UIElement in the drop down list. + public object Content + { + get { return this.Text; } + } + + /// + /// Gets the description. + /// + public object Description + { + get { return _description; } + } + + /// + /// Gets the priority. This property is used in the selection logic. You can use it to prefer selecting those items + /// which the user is accessing most frequently. + /// + public double Priority { get { return 0; } } + + /// + /// Perform the completion. + /// + /// The text area on which completion is performed. + /// The text segment that was used by the completion window if + /// the user types (segment between CompletionWindow.StartOffset and CompletionWindow.EndOffset). + /// The EventArgs used for the insertion request. + /// These can be TextCompositionEventArgs, KeyEventArgs, MouseEventArgs, depending on how + /// the insertion was triggered. + public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) + { + textArea.Document.Replace(completionSegment, this.Text); + } + + public bool IsSelected + { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + public static readonly DependencyProperty IsSelectedProperty = + DependencyProperty.Register("IsSelected", typeof(bool), typeof(MethodCompletionData), new PropertyMetadata(false, IsSelectedChanged)); + + private static void IsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + Debug.WriteLine("Selected"); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return Text; + } + } + + internal class PropertyCompletionData : DependencyObject, ICompletionData + { + private String _description; + + /// + /// Gets or sets the icon source. + /// + public BitmapSource Source { get; set; } + + public String ReturnType { get; set; } + + public String Type { get; set; } + + public String Class { get; set; } + + public PropertyCompletionData(String cls, string name, String returnType, String description) + { + Type = "property"; + Class = cls; + this.Text = name; + ReturnType = returnType; + _description = description; + } + + /// + /// Gets the image. + /// + public System.Windows.Media.ImageSource Image + { + get { return Source; } + } + + /// + /// Gets the text. This property is used to filter the list of visible elements. + /// + public string Text { get; private set; } + + // Use this property if you want to show a fancy UIElement in the drop down list. + public object Content + { + get { return this.Text; } + } + + /// + /// Gets the description. + /// + public object Description + { + get { return _description; } + } + + /// + /// Gets the priority. This property is used in the selection logic. You can use it to prefer selecting those items + /// which the user is accessing most frequently. + /// + public double Priority { get { return 0; } } + + /// + /// Perform the completion. + /// + /// The text area on which completion is performed. + /// The text segment that was used by the completion window if + /// the user types (segment between CompletionWindow.StartOffset and CompletionWindow.EndOffset). + /// The EventArgs used for the insertion request. + /// These can be TextCompositionEventArgs, KeyEventArgs, MouseEventArgs, depending on how + /// the insertion was triggered. + public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) + { + textArea.Document.Replace(completionSegment, this.Text); + } + + public bool IsSelected + { + get { return (bool)GetValue(IsSelectedProperty); } + set { SetValue(IsSelectedProperty, value); } + } + public static readonly DependencyProperty IsSelectedProperty = + DependencyProperty.Register("IsSelected", typeof(bool), typeof(PropertyCompletionData), new PropertyMetadata(false, IsSelectedChanged)); + + private static void IsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + Debug.WriteLine("Selected"); + } + + /// + /// Returns a that represents this instance. + /// + /// + /// A that represents this instance. + /// + public override string ToString() + { + return Text; + } + } + #endregion #region Properties @@ -201,6 +422,15 @@ namespace Tango.Scripting.Editors public static readonly DependencyProperty ReferenceAssembliesProperty = DependencyProperty.Register("ReferenceAssemblies", typeof(ObservableCollection), typeof(ScriptEditor), new PropertyMetadata(null)); + public Object CurrentPopupContent + { + get { return (Object)GetValue(CurrentPopupContentProperty); } + set { SetValue(CurrentPopupContentProperty, value); } + } + public static readonly DependencyProperty CurrentPopupContentProperty = + DependencyProperty.Register("CurrentPopupContent", typeof(Object), typeof(ScriptEditor), new PropertyMetadata(null)); + + #endregion #region Constructors @@ -218,8 +448,6 @@ namespace Tango.Scripting.Editors /// public ScriptEditor() { - _known_types_docs_cache = new Dictionary(); - _assemblies_docs_cache = new Dictionary(); _declaredTypes = new List(); _current_usings = new List(); @@ -230,7 +458,7 @@ namespace Tango.Scripting.Editors ReferenceAssemblies.Add(new ReferenceAssembly(typeof(String))); //mscorelib ReferenceAssemblies.Add(new ReferenceAssembly(typeof(Enumerable))); //System.Core - _knownTypes = new List(); + _knownTypes = new List(); _parser = new ScriptParser(); TextArea.IndentationStrategy = new Indentation.CSharp.CSharpIndentationStrategy(Options); @@ -410,6 +638,146 @@ namespace Tango.Scripting.Editors return GetWordByEndIndex(index); } + private ConstructionSession GetConstructionSession() + { + var expression = _parser.GetCurrentConstructionExpression(GetCurrentLineText()); + + if (expression != null) + { + ConstructionSession session = new ConstructionSession(); + + var line = GetCurrentLine(); + int parameterIndex = 0; + for (int i = CaretOffset; i > line.Offset; i--) + { + String c = Document.GetText(i, 1); + + if (c == "(") + { + var typeDeclaration = expression.Type as GenericNameSyntax; + + KnownType type = null; + + if (typeDeclaration != null) + { + var typeName = typeDeclaration.Identifier.ToString(); + var argumentsCount = typeDeclaration.TypeArgumentList.Arguments.Count; + session.TypeArguments = typeDeclaration.TypeArgumentList.Arguments.Select(x => x.ToString()).ToList(); + + if (argumentsCount == 0) + { + type = _knownTypes.FirstOrDefault(x => x.Type.Name == expression.Type.ToString()); + } + else + { + type = _knownTypes.FirstOrDefault(x => x.Type.Name == typeName + "`" + argumentsCount); + } + } + else + { + type = _knownTypes.FirstOrDefault(x => x.Name == expression.Type.ToString()); + } + + if (type != null) + { + session.Type = type; + session.ParameterIndex = parameterIndex; + return session; + } + else + { + return null; + } + } + else if (c == ",") + { + parameterIndex++; + } + + } + } + + return null; + } + + //private MethodSession GetMethodSession() + //{ + // var lineText = GetCurrentLineText(); + // var expression = lineText.Split(' ').ToList().LastOrDefault(); + + // if (expression != null) + // { + + // } + + + // var expression = _parser.GetExpression(GetCurrentLineText()); + + // if (expression != null) + // { + // MethodSession session = new MethodSession(); + + // var line = GetCurrentLine(); + // int parameterIndex = 0; + // for (int i = CaretOffset; i > line.Offset; i--) + // { + // String c = Document.GetText(i, 1); + + // if (c == "(") + // { + // //var typeDeclaration = expression.Type as GenericNameSyntax; + + // //KnownType type = null; + + // //if (typeDeclaration != null) + // //{ + // // var typeName = typeDeclaration.Identifier.ToString(); + // // var argumentsCount = typeDeclaration.TypeArgumentList.Arguments.Count; + // // session.TypeArguments = typeDeclaration.TypeArgumentList.Arguments.Select(x => x.ToString()).ToList(); + + // // if (argumentsCount == 0) + // // { + // // type = _knownTypes.FirstOrDefault(x => x.Type.Name == expression.Type.ToString()); + // // } + // // else + // // { + // // type = _knownTypes.FirstOrDefault(x => x.Type.Name == typeName + "`" + argumentsCount); + // // } + // //} + // //else + // //{ + // // type = _knownTypes.FirstOrDefault(x => x.Name == expression.Type.ToString()); + // //} + + // //if (type != null) + // //{ + // // session.Type = type; + // // session.ParameterIndex = parameterIndex; + // // return session; + // //} + // //else + // //{ + // // return null; + // //} + // } + // else if (c == ",") + // { + // parameterIndex++; + // } + + // } + // } + + // return null; + //} + + public List GetPreviousWords() + { + var currentLine = GetCurrentLine(); + var currentText = Document.GetText(currentLine.Offset, CaretOffset - currentLine.Offset); + return currentText.Split(' ').ToList(); + } + #endregion #region Highlighting @@ -431,7 +799,7 @@ namespace Tango.Scripting.Editors { lock (_knownTypes) { - _knownTypes.Add(type); + _knownTypes.Add(new KnownType(type)); } } }); @@ -453,22 +821,25 @@ namespace Tango.Scripting.Editors List referenceTypes = new List(); List interfaceTypes = new List(); - foreach (var type in _knownTypes) + lock (_knownTypes) { - String name = type.Name; - - if (type.ContainsGenericParameters) + foreach (var type in _knownTypes.ToList().Where(x => x != null)) { - name = new String(name.TakeWhile(x => x != '`').ToArray()); - } + String name = type.Name; - if (type.IsClass || (type.IsValueType && !type.IsPrimitive)) - { - referenceTypes.Add(String.Format("{0}", name)); - } - else if (type.IsInterface || type.IsEnum) - { - interfaceTypes.Add(String.Format("{0}", name)); + if (type.Type.ContainsGenericParameters) + { + name = new String(name.TakeWhile(x => x != '`').ToArray()); + } + + if (type.Type.IsInterface || type.Type.IsEnum) + { + interfaceTypes.Add(String.Format("{0}", name)); + } + else if (type.Type.IsClass) + { + referenceTypes.Add(String.Format("{0}", name)); + } } } @@ -545,12 +916,40 @@ namespace Tango.Scripting.Editors /// The that contains the event data. protected override void OnPreviewKeyDown(KeyEventArgs e) { + if (CurrentPopupContent is MethodPopup && (e.Key == Key.Down || e.Key == Key.Up)) + { + e.Handled = true; + + if (e.Key == Key.Down) + { + (CurrentPopupContent as MethodPopup).IncrementMethod(); + } + else if (e.Key == Key.Up) + { + (CurrentPopupContent as MethodPopup).DecrementMethod(); + } + + return; + } + base.OnPreviewKeyDown(e); + HidePopup(); HandleKeyCombinations(e); } #endregion + #region Apply Template + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _popup = GetTemplateChild("PART_popup") as Popup; + } + + #endregion + #region Key Combination Handling /// @@ -605,11 +1004,118 @@ namespace Tango.Scripting.Editors { List items = new List(); - if (e.Text == ".") + HidePopup(); + + var lineText = GetCurrentLineText(); + var previousWordsLast = GetPreviousWords().LastOrDefault(); + String currentWord = previousWordsLast != null ? previousWordsLast.Replace("\t", "") : String.Empty; + + + if (e.Text == ";" || e.Text == " ") { - var word = GetCurrentWord(); + HideCompletionWindow(); } - else + else if (e.Text == ".") + { + var expression = GetPreviousWords().LastOrDefault(); + + if (expression != null) + { + var tree = expression.Split('.').Select(x => x.Replace("\n", "").Replace("\r", "").Replace(" ", "").Replace("\t", "").Replace("(", "").Replace(")", "")).ToList(); + var variableName = tree.FirstOrDefault(); + + if (variableName != null) + { + tree.RemoveAt(0); + var variables = _parser.GetScriptVariables(Document.Text); + var variable = variables.FirstOrDefault(x => x.Name == variableName); + + if (variable != null) + { + var knownType = _knownTypes.FirstOrDefault(x => x.FriendlyName == variable.Type); + + if (knownType != null) + { + while (tree.Count > 1) + { + var memberName = tree.First(); + tree.RemoveAt(0); + var member = knownType.Members.FirstOrDefault(x => x.Name == memberName); + + if (member == null) + { + return; + } + + knownType = _knownTypes.FirstOrDefault(x => x.Type == member.ReturnType); + } + + if (knownType != null) + { + completionWindow.HideCompletion(); + IList data = new List(); + + var typeMembers = knownType.Members.ToList(); + + foreach (var methodGroup in typeMembers.GroupBy(x => x.Name)) + { + var member = methodGroup.First(); + + if (member.GetType() == typeof(KnownTypeMethod)) + { + var method = member as KnownTypeMethod; + data.Add(new MethodCompletionData(knownType.FriendlyName, method.Name, method.ReturnTypeFriendlyName, method.Summary, method.Parameters, methodGroup.Count() - 1)); + } + else + { + data.Add(new PropertyCompletionData(knownType.FriendlyName, member.Name, member.ReturnType.Name, member.Summary)); + } + } + + ShowCompletionWindow(data, GetCurrentWord()); + } + } + } + } + } + } + else if (e.Text == "(" || e.Text == ",") + { + completionWindow.HideCompletion(); + + var session = GetConstructionSession(); + + if (session != null) + { + var content = CreateConstructionSessionPopupContent(session); + if (content.Methods.Count > 0) + { + ShowPopup(content); + } + } + + //var methodSession = GetMethodSession(); + + //if (methodSession != null) + //{ + + //} + } + else if (lineText.StartsWith("using")) + { + IList data = new List(); + + foreach (var asm in ReferenceAssemblies) + { + foreach (var ns in asm.Assembly.GetTypes().Select(x => x.Namespace).Distinct().Where(x => x != null)) + { + data.Add(new TypeCompletionData("namespace", ns, "", asm.Assembly.GetName().Name)); + } + } + + ShowCompletionWindow(data, GetCurrentWord()); + } + else if (!currentWord.Contains(".")) { var previous_word = GetPreviousWord(); var word = GetCurrentWord(); @@ -631,33 +1137,19 @@ namespace Tango.Scripting.Editors { if (char.IsUpper(word.First())) { - IList data = completionWindow.CompletionList.CompletionData; - data.Clear(); + IList data = new List(); foreach (var type in _declaredTypes.Where(x => x.Name.StartsWith(word))) { - data.Add(new CompletionData(type.TypeKind.ToString().ToLower(), type.Name, type.ContainingNamespace?.Name, "Declared inside the current script...")); + data.Add(new TypeCompletionData(type.TypeKind.ToString().ToLower(), type.Name, type.ContainingNamespace?.Name, "Declared inside the current script...")); } foreach (var type in _knownTypes.Where(x => x.Name.StartsWith(word))) { - String doc = GetKnownTypeDocumentation(type); - data.Add(new CompletionData(GetTypeOfType(type), type.Name, type.Namespace, doc)); + data.Add(new TypeCompletionData(type.TypeDefinition, type.FriendlyName, type.Type.Namespace, type.Summary)); } - if (data.Count > 0) - { - completionWindow.ShowCompletion(); - - if (completionWindow.CompletionList.ListBox != null) - { - completionWindow.CompletionList.SelectItemFiltering(word); - } - } - else - { - completionWindow.HideCompletion(); - } + ShowCompletionWindow(data, word); } } } @@ -671,61 +1163,34 @@ namespace Tango.Scripting.Editors Document.Replace(index, Math.Min(max - index, item.Text.Length), item.Text); } - private String GetKnownTypeDocumentation(Type type) + private void ShowCompletionWindow(IList suggestions, String filter) { - if (_known_types_docs_cache.ContainsKey(type)) - { - return _known_types_docs_cache[type]; - } + IList data = completionWindow.CompletionList.CompletionData; + data.Clear(); - XmlDocument _docuDoc = null; - - if (_assemblies_docs_cache.ContainsKey(type.Assembly)) + foreach (var item in suggestions) { - _docuDoc = _assemblies_docs_cache[type.Assembly]; + data.Add(item); } - if (_docuDoc == null) + if (data.Count > 0) { - String dllPath = type.Assembly.Location; - - string docuPath = dllPath.Substring(0, dllPath.LastIndexOf(".")) + ".XML"; + completionWindow.ShowCompletion(); - if (File.Exists(docuPath)) + if (completionWindow.CompletionList.ListBox != null) { - _docuDoc = new XmlDocument(); - _docuDoc.Load(docuPath); + completionWindow.CompletionList.SelectItemFiltering(filter); } - else if (File.Exists(System.IO.Path.Combine(dotNetXmlFolder, System.IO.Path.GetFileName(docuPath)))) - { - _docuDoc = new XmlDocument(); - _docuDoc.Load(System.IO.Path.Combine(dotNetXmlFolder, System.IO.Path.GetFileName(docuPath))); - } - - _assemblies_docs_cache.Add(type.Assembly, _docuDoc); } - - if (_docuDoc != null) + else { - string path = "T:" + type.FullName; - XmlNode xmlDocuOfType = _docuDoc.SelectSingleNode("//member[starts-with(@name, '" + path + "')]"); - - _known_types_docs_cache.Add(type, xmlDocuOfType.InnerText); - - return xmlDocuOfType.InnerText; + completionWindow.HideCompletion(); } - - return String.Empty; } - private String GetTypeOfType(Type type) + private void HideCompletionWindow() { - if (type.IsClass) return "class"; - if (type.IsEnum) return "enum"; - if (type.IsInterface) return "interface"; - if (type.IsValueType) return "struct"; - - return ""; + completionWindow.HideCompletion(); } private List GetScriptClassNames() @@ -776,5 +1241,85 @@ namespace Tango.Scripting.Editors } #endregion + + #region Popup + + private void ShowPopup(Object content) + { + var position = TextArea.Caret.Position; + var textView = TextArea.TextView; + + var visualLocation = textView.GetVisualPosition(position, VisualYPosition.LineBottom); + var visualLocationTop = textView.GetVisualPosition(position, VisualYPosition.LineTop); + + Point location = textView.PointToScreen(visualLocation - textView.ScrollOffset); + Point locationTop = textView.PointToScreen(visualLocationTop - textView.ScrollOffset); + + _popup.Placement = PlacementMode.Absolute; + _popup.PlacementRectangle = new Rect(location, new Size(200, 100)); + + CurrentPopupContent = content; + + _popup.IsOpen = true; + } + + private void HidePopup() + { + _popup.IsOpen = false; + CurrentPopupContent = null; + } + + private MethodPopup CreateConstructionSessionPopupContent(ConstructionSession session) + { + MethodPopup popup = new MethodPopup(); + + foreach (var c in session.Type.Constructors) + { + MethodDescription method = new MethodDescription(); + method.ReturnType = session.Type.Name; + method.Description = c.Summary; + + if (session.Type.Type.IsGenericType && session.TypeArguments != null) + { + method.ReturnType = new String(session.Type.Name.TakeWhile(x => x != '`').ToArray()) + $"<{String.Join(",", session.TypeArguments)}>"; + } + + var parameters = c.Parameters; + + foreach (var p in parameters) + { + ParameterDescription pDescription = new ParameterDescription(method); + pDescription.Name = p.Name; + pDescription.Type = p.Type.Name; + pDescription.Description = p.Description; + method.Parameters.Add(pDescription); + } + + popup.Methods.Add(method); + } + + if (session.ParameterIndex > 0) + { + popup.CurrentMethod = popup.Methods.FirstOrDefault(x => x.Parameters.Count == session.ParameterIndex + 1); + + if (popup.CurrentMethod == null) + { + popup.CurrentMethod = popup.Methods.FirstOrDefault(); + } + } + else + { + popup.CurrentMethod = popup.Methods.FirstOrDefault(); + } + + if (popup.CurrentMethod != null) + { + popup.CurrentMethodIndex = popup.Methods.IndexOf(popup.CurrentMethod) + 1; + } + + return popup; + } + + #endregion } } diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj index 18ed1ff70..d7c455704 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Tango.Scripting.Editors.csproj @@ -189,6 +189,9 @@ + + + UndoStack.cs @@ -320,6 +323,14 @@ + + + + + + + + IBackgroundRenderer.cs @@ -560,19 +571,34 @@ - - - - - - + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Themes/Generic.xaml b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Themes/Generic.xaml index d113ca2a2..8b60d42a7 100644 --- a/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Themes/Generic.xaml +++ b/Software/Visual_Studio/TEMP/Tango.Scripting/Tango.Scripting.Editors/Themes/Generic.xaml @@ -1,9 +1,11 @@ @@ -21,6 +23,8 @@ #E6E6E6 #A0A0A0 #2B91AF + #4EC9B0 + #3F8FD6 @@ -29,6 +33,21 @@ + + + + + + + + + + + + + + + + + @@ -90,7 +205,35 @@ - + + + + + @@ -160,17 +303,86 @@ BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> - + + + + + + + + + + + + + + + +