/// <summary> /// Create a new <see cref="Editor"/> instance. /// </summary> /// <param name="initialText">The initial text of the editor.</param> /// <param name="preSource">The source code that should be prepended to the text of the document when compiling it.</param> /// <param name="postSource">The source code that should be appended to the text of the document when compiling it.</param> /// <param name="references">A list of <see cref="MetadataReference"/>s for which the compiled assembly will have bindings. Make sure to include an appropriate <see cref="DocumentationProvider"/>, if you would like documentation comments to appear in code completion windows. If this is <see langword="null"/>, references to all of the assemblies loaded in the current <see cref="AppDomain"/> will be added.</param> /// <param name="compilationOptions">The compilation options used to compile the code. If this is <see langword="null"/>, a <c>new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)</c> will be used.</param> /// <param name="guid">A unique identifier for the document being edited. If this is <see langword="null"/>, a new <see cref="System.Guid"/> is generated. If the same identifier is used multiple times, the save history of the document will be available, even if the application has been closed between different sessions.</param> /// <param name="additionalShortcuts">Additional application-specific shortcuts (for display purposes only - you need to implement your own logic).</param> /// <returns>A fully initialised <see cref="Editor"/> instance.</returns> public static async Task <Editor> Create(string initialText = "", string preSource = "", string postSource = "", IEnumerable <CachedMetadataReference> references = null, CSharpCompilationOptions compilationOptions = null, string guid = null, Shortcut[] additionalShortcuts = null) { if (references == null) { List <CachedMetadataReference> referencesList = new List <CachedMetadataReference>(); foreach (Assembly ass in AppDomain.CurrentDomain.GetAssemblies()) { string location = null; try { location = ass.Location; } catch (NotSupportedException) { }; if (!string.IsNullOrEmpty(location)) { referencesList.Add(CachedMetadataReference.CreateFromFile(location, Path.Combine(Path.GetDirectoryName(location), Path.GetFileNameWithoutExtension(location) + ".xml"))); } } references = referencesList; } if (compilationOptions == null) { compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); } if (string.IsNullOrEmpty(guid)) { guid = System.Guid.NewGuid().ToString("N"); } else { foreach (char c in Path.GetInvalidPathChars().Concat(Path.GetInvalidFileNameChars())) { if (guid.Contains(c)) { throw new ArgumentException("The provided Guid \"" + guid + "\" is not valid!\nThe Guid must be a valid identifier for a path or a file.", nameof(guid)); } } } Editor tbr = new Editor(false); await tbr.Initialize(initialText, preSource, postSource, references, compilationOptions, guid, additionalShortcuts ?? new Shortcut[0]); return(tbr); }
private async void AddReferenceClicked(object sender, RoutedEventArgs e) { OpenFileDialog dialog; if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { dialog = new OpenFileDialog() { Title = "Add reference...", AllowMultiple = false, Filters = new List <FileDialogFilter>() { new FileDialogFilter() { Name = "Component files", Extensions = new List <string>() { "exe", "dll", "tlb", "olb", "ocx", "winmd" } }, new FileDialogFilter() { Name = "All files", Extensions = new List <string>() { "*" } } } }; } else { dialog = new OpenFileDialog() { Title = "Add reference...", AllowMultiple = false }; } string[] result = await dialog.ShowAsync(this.FindAncestorOfType <Window>()); if (result != null && result.Length == 1) { string relativeToWorkingDir = System.IO.Path.GetRelativePath(Environment.CurrentDirectory, result[0]); string relativeToExecutable = System.IO.Path.GetRelativePath(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), result[0]); string path = result[0]; if (relativeToWorkingDir.Length < path.Length) { path = relativeToWorkingDir; } if (relativeToExecutable.Length < path.Length) { path = relativeToExecutable; } try { List <string> paths = Directory.GetFiles(Environment.CurrentDirectory, "*.dll").Concat(Directory.GetFiles(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "*.dll")).Concat(Directory.GetFiles(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "*.dll")).ToList(); HashSet <string> dllNames = new HashSet <string>(); List <string> uniquePaths = new List <string>(); for (int i = 0; i < paths.Count; i++) { if (dllNames.Add(System.IO.Path.GetFileName(paths[i]))) { uniquePaths.Add(paths[i]); } } using (MetadataLoadContext context = new MetadataLoadContext(new PathAssemblyResolver(uniquePaths), typeof(object).Assembly.FullName)) { Assembly ass = context.LoadFromAssemblyPath(result[0]); } CachedMetadataReference reference = CachedMetadataReference.CreateFromFile(path); AddReferenceLine(reference, this.FindControl <ToggleButton>("CoreReferencesButton"), this.FindControl <ToggleButton>("AdditionalReferencesButton")); References = References.Add(reference); Editor editor = this.FindAncestorOfType <Editor>(); await editor.SetReferences(References, false); } catch (Exception ex) { await ShowDialog("Error loading assembly", "An error occurred while loading the assembly!\n" + ex.Message, DialogIcon.Warning); } } }
private async Task DocumentationButtonClicked(MetadataReference reference, Canvas documentationIcon, Grid referenceGrid) { OpenFileDialog dialog; if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { dialog = new OpenFileDialog() { Title = "Add documentation...", AllowMultiple = false, Filters = new List <FileDialogFilter>() { new FileDialogFilter() { Name = "XML documentation", Extensions = new List <string>() { "xml" } }, new FileDialogFilter() { Name = "All files", Extensions = new List <string>() { "*" } } } }; } else { dialog = new OpenFileDialog() { Title = "Add documentation...", AllowMultiple = false }; } string[] result = await dialog.ShowAsync(this.FindAncestorOfType <Window>()); if (result != null && result.Length == 1) { try { List <string> describedMembers = new List <string>(); XDocument doc = XDocument.Load(result[0]); foreach (XElement element in doc.Descendants("member")) { string name = element.Attribute("name").Value; describedMembers.Add(name); } string fullAssemblyPath = GetFullAssemblyPath(reference.Display); int foundTypes = 0; int totalTypes = 0; List <string> paths = Directory.GetFiles(Environment.CurrentDirectory, "*.dll").Concat(Directory.GetFiles(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "*.dll")).Concat(Directory.GetFiles(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "*.dll")).ToList(); HashSet <string> dllNames = new HashSet <string>(); List <string> uniquePaths = new List <string>(); for (int i = 0; i < paths.Count; i++) { if (dllNames.Add(System.IO.Path.GetFileName(paths[i]))) { uniquePaths.Add(paths[i]); } } using (MetadataLoadContext context = new MetadataLoadContext(new PathAssemblyResolver(uniquePaths), typeof(object).Assembly.FullName)) { Assembly ass = context.LoadFromAssemblyPath(fullAssemblyPath); Type[] types = ass.GetTypes(); foreach (Type type in types) { if (type.IsPublic || type.IsPublic) { totalTypes++; string documentationId = "T:" + type.FullName.Replace("+", "."); if (describedMembers.Contains(documentationId)) { foundTypes++; } } } } await ShowDialog("Documentation analysis", "The documentation file describes " + foundTypes.ToString() + " types out of " + totalTypes + " contained in the assembly.", DialogIcon.Info); CachedMetadataReference newReference = CachedMetadataReference.CreateFromFile(reference.Display, result[0]); References = References.Replace(reference, newReference); referenceGrid.Tag = newReference; Editor editor = this.FindAncestorOfType <Editor>(); await editor.SetReferences(References, false); documentationIcon.Children.Clear(); documentationIcon.Children.Add(new DiagnosticIcons.TickIcon()); ToolTip.SetTip((Control)documentationIcon.Parent, "XML documentation available"); } catch { await ShowDialog("Error loading documentation", "An error occurred while loading the documentation!", DialogIcon.Warning); } } }
/// <summary> /// Start the loop that waits for breakpoint signals from the server. /// </summary> /// <param name="e">The event args.</param> protected override async void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) { base.OnAttachedToLogicalTree(e); if (Editor == null) { Editor = await Editor.Create(); Editor.AccessType = Editor.AccessTypes.ReadOnly; this.Content = Editor; } while (!ParentProcess.HasExited) { string message = await PipeClientInReader.ReadLineAsync(); if (message == "Abort") { if (!ParentProcessExitedRaised) { ParentProcessExitedRaised = true; ParentProcessExited?.Invoke(this, new EventArgs()); } break; } if (!ParentProcess.HasExited && message == "Init") { message = await PipeClientInReader.ReadLineAsync(); if (message == "Abort") { if (!ParentProcessExitedRaised) { ParentProcessExitedRaised = true; ParentProcessExited?.Invoke(this, new EventArgs()); } break; } if (!ParentProcess.HasExited && !string.IsNullOrEmpty(message)) { string[] messageParts = JsonSerializer.Deserialize <string[]>(message); string[][] localVariablesDisplayPartsJson = JsonSerializer.Deserialize <string[][]>(messageParts[0]); string[][] localVariablesJson = JsonSerializer.Deserialize <string[][]>(messageParts[1]); string sourceCode = messageParts[2]; int breakpointStart = int.Parse(messageParts[3]); string preSource = messageParts[4]; string postSource = messageParts[5]; IEnumerable <CachedMetadataReference> references = from el in JsonSerializer.Deserialize <string[]>(messageParts[6]) select CachedMetadataReference.CreateFromFile(el); Dictionary <string, TaggedText[]> localVariablesDisplayParts = new Dictionary <string, TaggedText[]>(); foreach (string[] item in localVariablesDisplayPartsJson) { localVariablesDisplayParts.Add(item[0], (from el in JsonSerializer.Deserialize <ReadWriteTaggedText[]>(item[1]) select(TaggedText) el).ToArray()); } Dictionary <string, (string, VariableTypes, object)> localVariables = new Dictionary <string, (string, VariableTypes, object)>(); foreach (string[] item in localVariablesJson) { VariableTypes variableType = JsonSerializer.Deserialize <VariableTypes>(item[2]); object variableValue = ParseVariableValue(variableType, item[3]); localVariables.Add(item[0], (item[1], variableType, variableValue)); } (string propertyId, VariableTypes propertyType, object propertyValue) propertyOrFieldGetter(string variableId, string propertyName, bool isProperty) { PipeClientOutWriter.WriteLine(JsonSerializer.Serialize(new string[] { "GetProperty", variableId, propertyName, isProperty.ToString() })); PipeClientOutWriter.Flush(); string message = PipeClientInReader.ReadLine(); if (message == "Abort") { if (!ParentProcessExitedRaised) { ParentProcessExitedRaised = true; ParentProcessExited?.Invoke(this, new EventArgs()); } return("", VariableTypes.Null, ""); } string[] output = JsonSerializer.Deserialize <string[]>(message); VariableTypes variableType = JsonSerializer.Deserialize <VariableTypes>(output[1]); return(output[0], variableType, ParseVariableValue(variableType, output[2])); } (string itemId, VariableTypes itemType, object itemValue)[] itemsGetter(string variableId)