From: Hans Wennborg Date: Wed, 27 Nov 2019 08:57:32 +0000 (+0100) Subject: clang-format-vs : Fix Unicode formatting X-Git-Tag: llvmorg-11-init~3360 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e20a1e486e144c88188bc7b420885d5326b39088;p=platform%2Fupstream%2Fllvm.git clang-format-vs : Fix Unicode formatting Use UTF-8 for communication with clang-format and convert the replacements offset/length to characters position/count. Internally VisualStudio.Text.Editor.IWpfTextView use sequence of Unicode characters encoded using UTF-16 and use characters position/count for manipulating text. Resolved "Error while running clang-format: Specified argument was out of the range of valid values. Parameter name: replaceSpan". Patch by empty2fill! Differential revision: https://reviews.llvm.org/D70633 --- diff --git a/clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs b/clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs index 7443405..26a0af3 100644 --- a/clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs +++ b/clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs @@ -24,6 +24,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Xml.Linq; using System.Linq; +using System.Text; namespace LLVM.ClangFormat { @@ -292,8 +293,7 @@ namespace LLVM.ClangFormat string text = view.TextBuffer.CurrentSnapshot.GetText(); int start = view.Selection.Start.Position.GetContainingLine().Start.Position; int end = view.Selection.End.Position.GetContainingLine().End.Position; - int length = end - start; - + // clang-format doesn't support formatting a range that starts at the end // of the file. if (start >= text.Length && text.Length > 0) @@ -301,7 +301,7 @@ namespace LLVM.ClangFormat string path = Vsix.GetDocumentParent(view); string filePath = Vsix.GetDocumentPath(view); - RunClangFormatAndApplyReplacements(text, start, length, path, filePath, options, view); + RunClangFormatAndApplyReplacements(text, start, end, path, filePath, options, view); } /// @@ -336,11 +336,11 @@ namespace LLVM.ClangFormat RunClangFormatAndApplyReplacements(text, 0, text.Length, path, filePath, options, view); } - private void RunClangFormatAndApplyReplacements(string text, int offset, int length, string path, string filePath, OptionPageGrid options, IWpfTextView view) + private void RunClangFormatAndApplyReplacements(string text, int start, int end, string path, string filePath, OptionPageGrid options, IWpfTextView view) { try { - string replacements = RunClangFormat(text, offset, length, path, filePath, options); + string replacements = RunClangFormat(text, start, end, path, filePath, options); ApplyClangFormatReplacements(replacements, view); } catch (Exception e) @@ -363,9 +363,9 @@ namespace LLVM.ClangFormat /// /// Runs the given text through clang-format and returns the replacements as XML. /// - /// Formats the text range starting at offset of the given length. + /// Formats the text in range start and end. /// - private static string RunClangFormat(string text, int offset, int length, string path, string filePath, OptionPageGrid options) + private static string RunClangFormat(string text, int start, int end, string path, string filePath, OptionPageGrid options) { string vsixPath = Path.GetDirectoryName( typeof(ClangFormatPackage).Assembly.Location); @@ -373,6 +373,9 @@ namespace LLVM.ClangFormat System.Diagnostics.Process process = new System.Diagnostics.Process(); process.StartInfo.UseShellExecute = false; process.StartInfo.FileName = vsixPath + "\\clang-format.exe"; + char[] chars = text.ToCharArray(); + int offset = Encoding.UTF8.GetByteCount(chars, 0, start); + int length = Encoding.UTF8.GetByteCount(chars, 0, end) - offset; // Poor man's escaping - this will not work when quotes are already escaped // in the input (but we don't need more). string style = options.Style.Replace("\"", "\\\""); @@ -413,10 +416,11 @@ namespace LLVM.ClangFormat // 2. We write everything to the standard output - this cannot block, as clang-format // reads the full standard input before analyzing it without writing anything to the // standard output. - process.StandardInput.Write(text); + StreamWriter utf8Writer = new StreamWriter(process.StandardInput.BaseStream, new UTF8Encoding(false)); + utf8Writer.Write(text); // 3. We notify clang-format that the input is done - after this point clang-format // will start analyzing the input and eventually write the output. - process.StandardInput.Close(); + utf8Writer.Close(); // 4. We must read clang-format's output before waiting for it to exit; clang-format // will close the channel by exiting. string output = process.StandardOutput.ReadToEnd(); @@ -440,13 +444,18 @@ namespace LLVM.ClangFormat if (replacements.Length == 0) return; + string text = view.TextBuffer.CurrentSnapshot.GetText(); + byte[] bytes = Encoding.UTF8.GetBytes(text); + var root = XElement.Parse(replacements); var edit = view.TextBuffer.CreateEdit(); foreach (XElement replacement in root.Descendants("replacement")) { + int offset = int.Parse(replacement.Attribute("offset").Value); + int length = int.Parse(replacement.Attribute("length").Value); var span = new Span( - int.Parse(replacement.Attribute("offset").Value), - int.Parse(replacement.Attribute("length").Value)); + Encoding.UTF8.GetCharCount(bytes, 0, offset), + Encoding.UTF8.GetCharCount(bytes, offset, length)); edit.Replace(span, replacement.Value); } edit.Apply();