コード例 #1
0
        /// <summary>
        /// Runs clang-format on the current selection
        /// </summary>
        private void FormatSelection(OptionPageGrid options)
        {
            IWpfTextView view = Vsix.GetCurrentView();

            if (view == null)
            {
                // We're not in a text view.
                return;
            }
            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)
            {
                start = text.Length - 1;
            }
            string path     = Vsix.GetDocumentParent(view);
            string filePath = Vsix.GetDocumentPath(view);

            RunClangFormatAndApplyReplacements(text, start, length, path, filePath, options, view);
        }
コード例 #2
0
        private void FormatView(IWpfTextView view, OptionPageGrid options)
        {
            if (view == null)
            {
                // We're not in a text view.
                return;
            }

            string filePath = Vsix.GetDocumentPath(view);
            var    path     = Path.GetDirectoryName(filePath);
            string text     = view.TextBuffer.CurrentSnapshot.GetText();

            RunClangFormatAndApplyReplacements(text, 0, text.Length, path, filePath, options, view);
        }
コード例 #3
0
        private void FormatView(IWpfTextView view, OptionPageGrid options)
        {
            if (view == null)
            {
                // We're not in a text view.
                return;
            }

            string filePath = Vsix.GetDocumentPath(view);
            var    path     = Path.GetDirectoryName(filePath);

            string text = view.TextBuffer.CurrentSnapshot.GetText();

            if (!text.EndsWith(Environment.NewLine))
            {
                view.TextBuffer.Insert(view.TextBuffer.CurrentSnapshot.Length, Environment.NewLine);
                text += Environment.NewLine;
            }
            byte[] buffer = enc.GetBytes(text);
            RunClangFormatAndApplyReplacements(buffer, 0, buffer.Length, path, filePath, options, view);
        }
コード例 #4
0
        /// <summary>
        /// Runs clang-format on the current selection
        /// </summary>
        private void FormatSelection(OptionPageGrid options)
        {
            IWpfTextView view = Vsix.GetCurrentView();

            if (view == null)
            {
                // We're not in a text view.
                return;
            }
            string text  = view.TextBuffer.CurrentSnapshot.GetText();
            int    start = view.Selection.Start.Position.GetContainingLine().Start.Position;
            int    end   = view.Selection.End.Position.GetContainingLine().End.Position;

            if (start >= end)
            {
                return;
            }

            // convert the utf16 index to multi bytes index
            start = enc.GetByteCount(text.ToCharArray(), 0, start);
            end   = enc.GetByteCount(text.ToCharArray(), 0, end);
            int length = end - start;

            if (length <= 0)
            {
                return;
            }

            // clang-format doesn't support formatting a range that starts at the end
            // of the file.
            if (start >= text.Length && text.Length > 0)
            {
                start = text.Length - 1;
            }
            string path     = Vsix.GetDocumentParent(view);
            string filePath = Vsix.GetDocumentPath(view);

            byte[] buffer = enc.GetBytes(text);
            RunClangFormatAndApplyReplacements(buffer, start, length, path, filePath, options, view);
        }
コード例 #5
0
        /// <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.
        /// </summary>
        private static string RunClangFormat(byte[] buffer, int offset, int length, string path, string filePath, OptionPageGrid options)
        {
            string vsixPath = Path.GetDirectoryName(
                typeof(ClangFormatPackage).Assembly.Location);

            System.Diagnostics.Process process = new System.Diagnostics.Process();
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.FileName        = vsixPath + "\\clang-format.exe";
            // 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("\"", "\\\"");
            string fallbackStyle = options.FallbackStyle.Replace("\"", "\\\"");

            process.StartInfo.Arguments = " -offset " + offset +
                                          " -length " + length +
                                          " -output-replacements-xml " +
                                          " -style \"" + style + "\"" +
                                          " -fallback-style \"" + fallbackStyle + "\"";
            if (options.SortIncludes)
            {
                process.StartInfo.Arguments += " -sort-includes ";
            }
            string assumeFilename = options.AssumeFilename;

            if (string.IsNullOrEmpty(assumeFilename))
            {
                assumeFilename = filePath;
            }
            if (!string.IsNullOrEmpty(assumeFilename))
            {
                process.StartInfo.Arguments += " -assume-filename \"" + assumeFilename + "\"";
            }
            process.StartInfo.CreateNoWindow         = true;
            process.StartInfo.RedirectStandardInput  = true;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardError  = true;
            if (path != null)
            {
                process.StartInfo.WorkingDirectory = path;
            }
            // We have to be careful when communicating via standard input / output,
            // as writes to the buffers will block until they are read from the other side.
            // Thus, we:
            // 1. Start the process - clang-format.exe will start to read the input from the
            //    standard input.
            try
            {
                if (options.OutputDetailInfo)
                {
                    Output("clang-format.exe ");
                    Output(process.StartInfo.Arguments);
                }
                process.Start();
            }
            catch (Exception e)
            {
                throw new Exception(
                          "Cannot execute " + process.StartInfo.FileName + ".\n\"" +
                          e.Message + "\".\nPlease make sure it is on the PATH.");
            }
            // 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.BaseStream.Write(buffer, 0, buffer.Length);

            // 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();
            // 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();

            // 5. clang-format is done, wait until it is fully shut down.
            process.WaitForExit();
            if (process.ExitCode != 0)
            {
                // FIXME: If clang-format writes enough to the standard error stream to block,
                // we will never reach this point; instead, read the standard error asynchronously.
                throw new Exception(process.StandardError.ReadToEnd());
            }
            if (options.OutputDetailInfo)
            {
                Output("\n");
                Output(output);
            }
            return(output);
        }
コード例 #6
0
 private void RunClangFormatAndApplyReplacements(byte[] buffer, int offset, int length, string path, string filePath, OptionPageGrid options, IWpfTextView view)
 {
     try
     {
         string replacements = RunClangFormat(buffer, offset, length, path, filePath, options);
         ApplyClangFormatReplacements(replacements, view);
     }
     catch (Exception e)
     {
         var uiShell = (IVsUIShell)GetService(typeof(SVsUIShell));
         var id      = Guid.Empty;
         int result;
         uiShell.ShowMessageBox(
             0, ref id,
             "Error while running clang-format:",
             e.Message,
             string.Empty, 0,
             OLEMSGBUTTON.OLEMSGBUTTON_OK,
             OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
             OLEMSGICON.OLEMSGICON_INFO,
             0, out result);
     }
 }
コード例 #7
0
 private void FormatDocument(Document document, OptionPageGrid options)
 {
     FormatView(Vsix.GetDocumentView(document), options);
 }
コード例 #8
0
 /// <summary>
 /// Runs clang-format on the current document
 /// </summary>
 private void FormatDocument(OptionPageGrid options)
 {
     FormatView(Vsix.GetCurrentView(), options);
 }