using FastReport.Controls; using FastReport.Editor.Syntax.Parsers; using FastReport.Engine; using FastReport.Utils; using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Windows.Forms; namespace FastReport.Design.PageDesigners.Code { partial class AvalonSyntaxEditor { private void DoCodeCompletion(CompletionEventArgs e) { List parts = e.Text.Split('.').ToList(); string filter = ""; if (e.Action == CompletionAction.CtrlSpacePressed) { // last item is incomplete - we will use it as a filter if (parts.Count > 0) { filter = parts[parts.Count - 1]; parts.RemoveAt(parts.Count - 1); } } if (parts.Count == 0) { // list all report objects var list = new List(); foreach (Base obj in report.AllObjects) { if (string.IsNullOrEmpty(obj.Name)) continue; list.Add(new NamedItem(obj.Name, obj.GetType())); } list.Add(new NamedItem("Report", typeof(Report))); list.Add(new NamedItem("Engine", typeof(ReportEngine))); list.Sort((x, y) => x.Name.CompareTo(y.Name)); foreach (var obj in list) { if (obj.Name.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) == -1) continue; string description = obj.Type.Name + " " + obj.Name; System.Drawing.Image image = null; var objInfo = RegisteredObjects.FindObject(obj.Type); if (objInfo != null) image = report.Designer.GetImage(objInfo.ImageIndex); e.CompletionData.Add(new CompletionData(obj.Name, description, image)); } } else { Type rootType = null; // report object object root = report.FindObject(parts[0]); if (root != null) rootType = root.GetType(); else { // some frequently used types like Color? if (parts[0] == "Color") rootType = typeof(System.Drawing.Color); else if (parts[0] == "Report") rootType = typeof(Report); else if (parts[0] == "Engine") rootType = typeof(ReportEngine); } if (rootType != null) { for (int i = 1; i < parts.Count; i++) { PropertyInfo member = null; try { member = rootType.GetProperty(parts[i]); } catch { // ambiguous properties found, take first one member = rootType.GetProperties().Where(x => x.Name == parts[i]).FirstOrDefault(); } if (member != null) rootType = member.PropertyType; else { rootType = null; break; } } } if (rootType != null) { if (e.Action == CompletionAction.EqualEntered) { if (rootType.IsEnum) { // list enum members foreach(var name in Enum.GetNames(rootType)) { var fieldInfo = rootType.GetField(name); e.CompletionData.Add(new CompletionData(rootType.Name + "." + name, ReflectionRepository.DescriptionHelper.GetDescription(fieldInfo), null)); } } } else { var members = rootType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static).ToList(); members.Sort((x, y) => (x.Name.CompareTo(y.Name))); foreach (var member in members) { if (!string.IsNullOrEmpty(filter) && member.Name.IndexOf(filter, StringComparison.InvariantCultureIgnoreCase) == -1) continue; string description = ""; System.Drawing.Image image = null; if (member.MemberType == MemberTypes.Property) { var propInfo = member as PropertyInfo; image = report.Designer.GetImage(78); description = report.CodeHelper.GetPropertySignature(propInfo, true); description += "
" + ReflectionRepository.DescriptionHelper.GetDescription(member); } else if (member.MemberType == MemberTypes.Method) { var methodInfo = member as MethodInfo; if (methodInfo.IsSpecialName) continue; image = report.Designer.GetImage(199); description = report.CodeHelper.GetMethodSignature(methodInfo, true); description += "
" + ReflectionRepository.DescriptionHelper.GetDescription(methodInfo); description += "
"; foreach (ParameterInfo parInfo in methodInfo.GetParameters()) { // special case - skip "thisReport" parameter if (parInfo.Name == "thisReport") continue; string s = ReflectionRepository.DescriptionHelper.GetDescription(parInfo); s = s.Replace("", "{i}").Replace(":", "{/i}").Replace("&", "&").Replace("<", "<").Replace(">", ">").Replace("{i}", "").Replace("{/i}", ""); description += "
" + s + "
"; } description = description.Replace("\t", "
"); } else { continue; } if (description.EndsWith("
")) description = description.Substring(0, description.Length - 5); e.CompletionData.Add(new CompletionData(member.Name, description, image)); } } } } } private class NamedItem { public string Name { get; } public Type Type { get; } public NamedItem(string name, Type type) { Name = name; Type = type; } } private class CompletionData : ICompletionData { private string htmlDescription; private HtmlDescriptionTextBlock descriptionTextBlock; public CompletionData(string text, string htmlDescription, System.Drawing.Image image) { this.Text = text; this.htmlDescription = htmlDescription; this.Image = Helper.GetImage(image); } public System.Windows.Media.ImageSource Image { get; } public string Text { get; private set; } public object Content => this.Text; public object Description { get { if (descriptionTextBlock == null) CreateTextBlock(); return descriptionTextBlock; } set { } } public double Priority => 0; public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) { textArea.Document.Replace(completionSegment, this.Text); } private void CreateTextBlock() { descriptionTextBlock = new HtmlDescriptionTextBlock(); descriptionTextBlock.Image = this.Image; descriptionTextBlock.Description = this.htmlDescription; descriptionTextBlock.ParseDescription(); } } } }