[clang] e20a1e4 - clang-format-vs : Fix Unicode formatting

Hans Wennborg via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 27 00:59:12 PST 2019


Author: Hans Wennborg
Date: 2019-11-27T09:58:59+01:00
New Revision: e20a1e486e144c88188bc7b420885d5326b39088

URL: https://github.com/llvm/llvm-project/commit/e20a1e486e144c88188bc7b420885d5326b39088
DIFF: https://github.com/llvm/llvm-project/commit/e20a1e486e144c88188bc7b420885d5326b39088.diff

LOG: 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

Added: 
    

Modified: 
    clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs

Removed: 
    


################################################################################
diff  --git a/clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs b/clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
index 7443405efad2..26a0af3b55b5 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.Runtime.InteropServices;
 using System.Xml.Linq;
 using System.Linq;
+using System.Text;
 
 namespace LLVM.ClangFormat
 {
@@ -292,8 +293,7 @@ private void FormatSelection(OptionPageGrid options)
             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 @@ private void FormatSelection(OptionPageGrid options)
             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);
         }
 
         /// <summary>
@@ -336,11 +336,11 @@ private void FormatView(IWpfTextView view, OptionPageGrid options)
             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 @@ private void RunClangFormatAndApplyReplacements(string text, int offset, int len
         /// <summary>
         /// 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.
         /// </summary>
-        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 @@ private static string RunClangFormat(string text, int offset, int length, string
             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 @@ private static string RunClangFormat(string text, int offset, int length, string
             // 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 @@ private static void ApplyClangFormatReplacements(string replacements, IWpfTextVi
             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();


        


More information about the cfe-commits mailing list