RoslynPadSyntaxEditor.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. using FastReport.Design.PageDesigners.Code;
  2. using FastReport.Engine;
  3. using FastReport.Utils;
  4. using Microsoft.CodeAnalysis;
  5. using RoslynPad.Editor;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. using System.Windows.Forms;
  12. namespace FastReport.WPF.RoslynPad
  13. {
  14. internal class RoslynPadSyntaxEditor : SyntaxEditorBase
  15. {
  16. private RoslynCodeEditor editor;
  17. private Report report;
  18. private MyRoslynHost _host;
  19. private string oldPartialClass;
  20. public override string Text
  21. {
  22. get => RemovePartialKeyword(editor.Text);
  23. set => editor.Text = AddPartialKeyword(value);
  24. }
  25. public override string SelectedText
  26. {
  27. get => editor.SelectedText;
  28. set => editor.SelectedText = value;
  29. }
  30. public override bool Modified
  31. {
  32. get => editor.IsModified;
  33. set => editor.IsModified = value;
  34. }
  35. public override bool ShowLineNumbers
  36. {
  37. get => editor.ShowLineNumbers;
  38. set => editor.ShowLineNumbers = value;
  39. }
  40. public override bool EnableVirtualSpace
  41. {
  42. get => editor.Options.EnableVirtualSpace;
  43. set => editor.Options.EnableVirtualSpace = value;
  44. }
  45. public override bool ConvertTabsToSpaces
  46. {
  47. get => editor.Options.ConvertTabsToSpaces;
  48. set => editor.Options.ConvertTabsToSpaces = value;
  49. }
  50. public override int IndentationSize
  51. {
  52. get => editor.Options.IndentationSize;
  53. set => editor.Options.IndentationSize = value;
  54. }
  55. private SyntaxType syntaxType;
  56. public override SyntaxType SyntaxType
  57. {
  58. get => syntaxType;
  59. set
  60. {
  61. if (syntaxType != value)
  62. {
  63. syntaxType = value;
  64. InitDocument();
  65. }
  66. }
  67. }
  68. public override bool AllowCodeCompletion { get; set; }
  69. public override void Cut() => editor.Cut();
  70. public override void Copy() => editor.Copy();
  71. public override void Paste() => editor.Paste();
  72. public override bool CanUndo => editor.CanUndo;
  73. public override void Undo() => editor.Undo();
  74. public override bool CanRedo => editor.CanRedo;
  75. public override void Redo() => editor.Redo();
  76. public override void Select(int start, int length) => editor.Select(start, length);
  77. public override void SelectAll() => editor.SelectAll();
  78. public override void Focus()
  79. {
  80. Application.DoEvents();
  81. editor.Dispatcher.InvokeAsync(() => editor.Focus());
  82. }
  83. public override void Locate(int line, int column)
  84. {
  85. editor.CaretOffset = editor.Document.GetOffset(line, column);
  86. }
  87. public override void SetCaretFromMousePosition(System.Drawing.Point pos)
  88. {
  89. var textPos = editor.GetPositionFromPoint(new System.Windows.Point(pos.X / DpiScale, pos.Y / DpiScale));
  90. if (textPos != null)
  91. {
  92. Locate(textPos.Value.Line, textPos.Value.Column);
  93. }
  94. }
  95. public override void UpdateInternals(Report report)
  96. {
  97. this.report = report;
  98. string partialClass = MakePartialClass();
  99. if (partialClass != oldPartialClass)
  100. {
  101. oldPartialClass = partialClass;
  102. _host.SetAdditionalInfo(partialClass, report.ReferencedAssemblies);
  103. }
  104. }
  105. private void InitDocument()
  106. {
  107. _host = new MyRoslynHost(SyntaxType);
  108. editor.InitializeAsync(_host, new ClassificationHighlightColors(), Directory.GetCurrentDirectory(), string.Empty, SourceCodeKind.Regular);
  109. }
  110. private string MakePartialClass()
  111. {
  112. ObjectCollection allObjects = report.AllObjects;
  113. SortedList<string, Base> objects = new SortedList<string, Base>();
  114. StringBuilder partialClass = new StringBuilder(1000);
  115. AddClassHeader(partialClass);
  116. // add all report objects
  117. AddObject(partialClass, typeof(Report), "Report");
  118. AddObject(partialClass, typeof(ReportEngine), "Engine");
  119. foreach (Base c in allObjects)
  120. {
  121. if (!String.IsNullOrEmpty(c.Name) && !objects.ContainsKey(c.Name))
  122. objects.Add(c.Name, c);
  123. }
  124. foreach (Base c in objects.Values)
  125. {
  126. AddObject(partialClass, c.GetType(), c.Name);
  127. }
  128. AddClassFooter(partialClass);
  129. return partialClass.ToString();
  130. }
  131. private void AddClassHeader(StringBuilder text)
  132. {
  133. if (SyntaxType == SyntaxType.Cs)
  134. {
  135. text.AppendLine("namespace FastReport {");
  136. text.AppendLine("partial class ReportScript {");
  137. }
  138. else
  139. {
  140. text.AppendLine("Namespace FastReport");
  141. text.AppendLine("Partial Class ReportScript");
  142. }
  143. }
  144. private void AddClassFooter(StringBuilder text)
  145. {
  146. if (SyntaxType == SyntaxType.Cs)
  147. {
  148. text.AppendLine("}}");
  149. }
  150. else
  151. {
  152. text.AppendLine("End Class");
  153. text.AppendLine("End Namespace");
  154. }
  155. }
  156. private void AddObject(StringBuilder text, Type type, string name)
  157. {
  158. if (SyntaxType == SyntaxType.Cs)
  159. {
  160. text.Append("public ").Append(type.FullName).Append(" ").Append(name).Append(";\r\n");
  161. }
  162. else
  163. {
  164. text.Append("public ").Append(name).Append(" as Global.").Append(type.FullName).Append("\r\n");
  165. }
  166. }
  167. private string AddPartialKeyword(string value)
  168. {
  169. if (SyntaxType == SyntaxType.Cs)
  170. {
  171. return value.Replace("public class ReportScript", "public partial class ReportScript");
  172. }
  173. return value.Replace("Public Class ReportScript", "Public Partial Class ReportScript");
  174. }
  175. private string RemovePartialKeyword(string value)
  176. {
  177. if (SyntaxType == SyntaxType.Cs)
  178. {
  179. return value.Replace("public partial class ReportScript", "public class ReportScript");
  180. }
  181. return value.Replace("Public Partial Class ReportScript", "Public Class ReportScript");
  182. }
  183. public RoslynPadSyntaxEditor()
  184. {
  185. editor = new RoslynCodeEditor();
  186. SetControl(editor);
  187. editor.HorizontalScrollBarVisibility = editor.VerticalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto;
  188. editor.Padding = new System.Windows.Thickness(4, 2, 0, 0);
  189. editor.TextChanged += (s, e) => OnTextChanged();
  190. }
  191. }
  192. public static class SyntaxEditor
  193. {
  194. public static void Register()
  195. {
  196. SyntaxEditorClass.Register(typeof(RoslynPadSyntaxEditor), SyntaxEditorKind.Code);
  197. Warmup();
  198. }
  199. private static async void Warmup()
  200. {
  201. await Task.Run(() => new MyRoslynHost(SyntaxType.Cs));
  202. }
  203. }
  204. }