Update some code used in our visual studio plugins to use linux file
authorChandler Carruth <chandlerc@gmail.com>
Sat, 19 Jan 2019 06:29:07 +0000 (06:29 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sat, 19 Jan 2019 06:29:07 +0000 (06:29 +0000)
endings. We already used them in some cases, and this makes things
consistent. This will also simplify updating the licenses in these
files.

llvm-svn: 351632

clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPackage.cs
clang-tools-extra/clang-tidy-vs/ClangTidy/ClangTidyPropertyGrid.cs
clang-tools-extra/clang-tidy-vs/ClangTidy/PkgCmdID.cs
clang/tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs
clang/tools/clang-format-vs/ClangFormat/Guids.cs
clang/tools/clang-format-vs/ClangFormat/PkgCmdID.cs

index 9a0c9b6..c5164e7 100644 (file)
@@ -1,56 +1,56 @@
-//===-- ClangTidyPackages.cs - VSPackage for clang-tidy ----------*- C# -*-===//\r
-//\r
-//                     The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This class contains a VS extension package that runs clang-tidy over a\r
-// file in a VS text editor.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-using Microsoft.VisualStudio.Editor;\r
-using Microsoft.VisualStudio.Shell;\r
-using Microsoft.VisualStudio.Shell.Interop;\r
-using Microsoft.VisualStudio.TextManager.Interop;\r
-using System;\r
-using System.Collections;\r
-using System.ComponentModel;\r
-using System.ComponentModel.Design;\r
-using System.IO;\r
-using System.Runtime.InteropServices;\r
-using System.Windows.Forms;\r
-using System.Xml.Linq;\r
-\r
-namespace LLVM.ClangTidy\r
-{\r
-    [PackageRegistration(UseManagedResourcesOnly = true)]\r
-    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]\r
-    [ProvideMenuResource("Menus.ctmenu", 1)]\r
-    [Guid(GuidList.guidClangTidyPkgString)]\r
-    [ProvideOptionPage(typeof(ClangTidyConfigurationPage), "LLVM/Clang", "ClangTidy", 0, 0, true)]\r
-    public sealed class ClangTidyPackage : Package\r
-    {\r
-        #region Package Members\r
-        protected override void Initialize()\r
-        {\r
-            base.Initialize();\r
-\r
-            var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;\r
-            if (commandService != null)\r
-            {\r
-                var menuCommandID = new CommandID(GuidList.guidClangTidyCmdSet, (int)PkgCmdIDList.cmdidClangTidy);\r
-                var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);\r
-                commandService.AddCommand(menuItem);\r
-            }\r
-        }\r
-        #endregion\r
-\r
-        private void MenuItemCallback(object sender, EventArgs args)\r
-        {\r
-        }\r
-    }\r
-}\r
+//===-- ClangTidyPackages.cs - VSPackage for clang-tidy ----------*- C# -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class contains a VS extension package that runs clang-tidy over a
+// file in a VS text editor.
+//
+//===----------------------------------------------------------------------===//
+
+using Microsoft.VisualStudio.Editor;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.TextManager.Interop;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+using System.Xml.Linq;
+
+namespace LLVM.ClangTidy
+{
+    [PackageRegistration(UseManagedResourcesOnly = true)]
+    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
+    [ProvideMenuResource("Menus.ctmenu", 1)]
+    [Guid(GuidList.guidClangTidyPkgString)]
+    [ProvideOptionPage(typeof(ClangTidyConfigurationPage), "LLVM/Clang", "ClangTidy", 0, 0, true)]
+    public sealed class ClangTidyPackage : Package
+    {
+        #region Package Members
+        protected override void Initialize()
+        {
+            base.Initialize();
+
+            var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+            if (commandService != null)
+            {
+                var menuCommandID = new CommandID(GuidList.guidClangTidyCmdSet, (int)PkgCmdIDList.cmdidClangTidy);
+                var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+                commandService.AddCommand(menuItem);
+            }
+        }
+        #endregion
+
+        private void MenuItemCallback(object sender, EventArgs args)
+        {
+        }
+    }
+}
index 20c8a8f..9b49e66 100644 (file)
-//===-- ClangTidyPropertyGrid.cs - UI for configuring clang-tidy -*- C# -*-===//\r
-//\r
-//                     The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This class contains a UserControl consisting of a .NET PropertyGrid control\r
-// allowing configuration of checks and check options for ClangTidy.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-using System;\r
-using System.Collections.Generic;\r
-using System.ComponentModel;\r
-using System.Drawing;\r
-using System.Data;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Threading.Tasks;\r
-using System.Windows.Forms;\r
-using System.IO;\r
-using Microsoft.VisualStudio.Shell;\r
-\r
-namespace LLVM.ClangTidy\r
-{\r
-    /// <summary>\r
-    ///  A UserControl displaying a PropertyGrid allowing configuration of clang-tidy\r
-    ///  checks and check options, as well as serialization and deserialization of\r
-    ///  clang-tidy configuration files.  When a configuration file is loaded, the\r
-    ///  entire chain of configuration files is analyzed based on the file path,\r
-    ///  and quick access is provided to edit or view any of the files in the\r
-    ///  configuration chain, allowing easy visualization of where values come from\r
-    ///  (similar in spirit to the -explain-config option of clang-tidy).\r
-    /// </summary>\r
-    public partial class ClangTidyPropertyGrid : UserControl\r
-    {\r
-        /// <summary>\r
-        /// The sequence of .clang-tidy configuration files, starting from the root\r
-        /// of the filesystem, down to the selected file.\r
-        /// </summary>\r
-        List<KeyValuePair<string, ClangTidyProperties>> PropertyChain_ = null;\r
-\r
-        public ClangTidyPropertyGrid()\r
-        {\r
-            InitializeComponent();\r
-            InitializeSettings();\r
-        }\r
-\r
-        private enum ShouldCancel\r
-        {\r
-            Yes,\r
-            No,\r
-        }\r
-\r
-        public void SaveSettingsToStorage()\r
-        {\r
-            PersistUnsavedChanges(false);\r
-        }\r
-\r
-        private ShouldCancel PersistUnsavedChanges(bool PromptFirst)\r
-        {\r
-            var UnsavedResults = PropertyChain_.Where(x => x.Key != null && x.Value.GetHasUnsavedChanges());\r
-            if (UnsavedResults.Count() == 0)\r
-                return ShouldCancel.No;\r
-\r
-            bool ShouldSave = false;\r
-            if (PromptFirst)\r
-            {\r
-                var Response = MessageBox.Show(\r
-                    "You have unsaved changes!  Do you want to save before loading a new file?",\r
-                    "clang-tidy",\r
-                    MessageBoxButtons.YesNoCancel);\r
-\r
-                ShouldSave = (Response == DialogResult.Yes);\r
-                if (Response == DialogResult.Cancel)\r
-                    return ShouldCancel.Yes;\r
-            }\r
-            else\r
-                ShouldSave = true;\r
-\r
-            if (ShouldSave)\r
-            {\r
-                foreach (var Result in UnsavedResults)\r
-                {\r
-                    ClangTidyConfigParser.SerializeClangTidyFile(Result.Value, Result.Key);\r
-                    Result.Value.SetHasUnsavedChanges(false);\r
-                }\r
-            }\r
-            return ShouldCancel.No;\r
-        }\r
-\r
-        public void InitializeSettings()\r
-        {\r
-            PropertyChain_ = new List<KeyValuePair<string, ClangTidyProperties>>();\r
-            PropertyChain_.Add(new KeyValuePair<string, ClangTidyProperties>(null, ClangTidyProperties.RootProperties));\r
-            reloadPropertyChain();\r
-        }\r
-\r
-        private void button1_Click(object sender, EventArgs e)\r
-        {\r
-            ShouldCancel Cancel = PersistUnsavedChanges(true);\r
-            if (Cancel == ShouldCancel.Yes)\r
-                return;\r
-\r
-            using (OpenFileDialog D = new OpenFileDialog())\r
-            {\r
-                D.Filter = "Clang Tidy files|.clang-tidy";\r
-                D.CheckPathExists = true;\r
-                D.CheckFileExists = true;\r
-\r
-                if (D.ShowDialog() == DialogResult.OK)\r
-                {\r
-                    PropertyChain_.Clear();\r
-                    PropertyChain_ = ClangTidyConfigParser.ParseConfigurationChain(D.FileName);\r
-                    textBox1.Text = D.FileName;\r
-                    reloadPropertyChain();\r
-                }\r
-            }\r
-        }\r
-\r
-        private static readonly string DefaultText = "(Default)";\r
-        private static readonly string BrowseText = "Browse for a file to edit its properties";\r
-\r
-        /// <summary>\r
-        /// After a new configuration file is chosen, analyzes the directory hierarchy\r
-        /// and finds all .clang-tidy files in the path, parses them and updates the\r
-        /// PropertyGrid and quick-access LinkLabel control to reflect the new property\r
-        /// chain.\r
-        /// </summary>\r
-        private void reloadPropertyChain()\r
-        {\r
-            StringBuilder LinkBuilder = new StringBuilder();\r
-            LinkBuilder.Append(DefaultText);\r
-            LinkBuilder.Append(" > ");\r
-            int PrefixLength = LinkBuilder.Length;\r
-\r
-            if (PropertyChain_.Count == 1)\r
-                LinkBuilder.Append(BrowseText);\r
-            else\r
-                LinkBuilder.Append(PropertyChain_[PropertyChain_.Count - 1].Key);\r
-\r
-            linkLabelPath.Text = LinkBuilder.ToString();\r
-\r
-            // Given a path like D:\Foo\Bar\Baz, construct a LinkLabel where individual\r
-            // components of the path are clickable iff they contain a .clang-tidy file.\r
-            // Clicking one of the links then updates the PropertyGrid to display the\r
-            // selected .clang-tidy file.\r
-            ClangTidyProperties LastProps = ClangTidyProperties.RootProperties;\r
-            linkLabelPath.Links.Clear();\r
-            linkLabelPath.Links.Add(0, DefaultText.Length, LastProps);\r
-            foreach (var Prop in PropertyChain_.Skip(1))\r
-            {\r
-                LastProps = Prop.Value;\r
-                string ClangTidyFolder = Path.GetFileName(Prop.Key);\r
-                int ClangTidyFolderOffset = Prop.Key.Length - ClangTidyFolder.Length;\r
-                linkLabelPath.Links.Add(PrefixLength + ClangTidyFolderOffset, ClangTidyFolder.Length, LastProps);\r
-            }\r
-            propertyGrid1.SelectedObject = LastProps;\r
-        }\r
-\r
-        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)\r
-        {\r
-            ClangTidyProperties Props = (ClangTidyProperties)propertyGrid1.SelectedObject;\r
-            Props.SetHasUnsavedChanges(true);\r
-\r
-            // When a CategoryVerb is selected, perform the corresponding action.\r
-            PropertyDescriptor Property = e.ChangedItem.PropertyDescriptor;\r
-            if (!(e.ChangedItem.Value is CategoryVerb))\r
-                return;\r
-\r
-            CategoryVerb Action = (CategoryVerb)e.ChangedItem.Value;\r
-            if (Action == CategoryVerb.None)\r
-                return;\r
-\r
-            var Category = Property.Attributes.OfType<CategoryAttribute>().FirstOrDefault();\r
-            if (Category == null)\r
-                return;\r
-            var SameCategoryProps = Props.GetProperties(new Attribute[] { Category });\r
-            foreach (PropertyDescriptor P in SameCategoryProps)\r
-            {\r
-                if (P == Property)\r
-                    continue;\r
-                switch (Action)\r
-                {\r
-                    case CategoryVerb.Disable:\r
-                        P.SetValue(propertyGrid1.SelectedObject, false);\r
-                        break;\r
-                    case CategoryVerb.Enable:\r
-                        P.SetValue(propertyGrid1.SelectedObject, true);\r
-                        break;\r
-                    case CategoryVerb.Inherit:\r
-                        P.ResetValue(propertyGrid1.SelectedObject);\r
-                        break;\r
-                }\r
-            }\r
-            Property.ResetValue(propertyGrid1.SelectedObject);\r
-            propertyGrid1.Invalidate();\r
-        }\r
-\r
-        private void linkLabelPath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)\r
-        {\r
-            ClangTidyProperties Props = (ClangTidyProperties)e.Link.LinkData;\r
-            propertyGrid1.SelectedObject = Props;\r
-        }\r
-    }\r
-}\r
+//===-- ClangTidyPropertyGrid.cs - UI for configuring clang-tidy -*- C# -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class contains a UserControl consisting of a .NET PropertyGrid control
+// allowing configuration of checks and check options for ClangTidy.
+//
+//===----------------------------------------------------------------------===//
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.IO;
+using Microsoft.VisualStudio.Shell;
+
+namespace LLVM.ClangTidy
+{
+    /// <summary>
+    ///  A UserControl displaying a PropertyGrid allowing configuration of clang-tidy
+    ///  checks and check options, as well as serialization and deserialization of
+    ///  clang-tidy configuration files.  When a configuration file is loaded, the
+    ///  entire chain of configuration files is analyzed based on the file path,
+    ///  and quick access is provided to edit or view any of the files in the
+    ///  configuration chain, allowing easy visualization of where values come from
+    ///  (similar in spirit to the -explain-config option of clang-tidy).
+    /// </summary>
+    public partial class ClangTidyPropertyGrid : UserControl
+    {
+        /// <summary>
+        /// The sequence of .clang-tidy configuration files, starting from the root
+        /// of the filesystem, down to the selected file.
+        /// </summary>
+        List<KeyValuePair<string, ClangTidyProperties>> PropertyChain_ = null;
+
+        public ClangTidyPropertyGrid()
+        {
+            InitializeComponent();
+            InitializeSettings();
+        }
+
+        private enum ShouldCancel
+        {
+            Yes,
+            No,
+        }
+
+        public void SaveSettingsToStorage()
+        {
+            PersistUnsavedChanges(false);
+        }
+
+        private ShouldCancel PersistUnsavedChanges(bool PromptFirst)
+        {
+            var UnsavedResults = PropertyChain_.Where(x => x.Key != null && x.Value.GetHasUnsavedChanges());
+            if (UnsavedResults.Count() == 0)
+                return ShouldCancel.No;
+
+            bool ShouldSave = false;
+            if (PromptFirst)
+            {
+                var Response = MessageBox.Show(
+                    "You have unsaved changes!  Do you want to save before loading a new file?",
+                    "clang-tidy",
+                    MessageBoxButtons.YesNoCancel);
+
+                ShouldSave = (Response == DialogResult.Yes);
+                if (Response == DialogResult.Cancel)
+                    return ShouldCancel.Yes;
+            }
+            else
+                ShouldSave = true;
+
+            if (ShouldSave)
+            {
+                foreach (var Result in UnsavedResults)
+                {
+                    ClangTidyConfigParser.SerializeClangTidyFile(Result.Value, Result.Key);
+                    Result.Value.SetHasUnsavedChanges(false);
+                }
+            }
+            return ShouldCancel.No;
+        }
+
+        public void InitializeSettings()
+        {
+            PropertyChain_ = new List<KeyValuePair<string, ClangTidyProperties>>();
+            PropertyChain_.Add(new KeyValuePair<string, ClangTidyProperties>(null, ClangTidyProperties.RootProperties));
+            reloadPropertyChain();
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            ShouldCancel Cancel = PersistUnsavedChanges(true);
+            if (Cancel == ShouldCancel.Yes)
+                return;
+
+            using (OpenFileDialog D = new OpenFileDialog())
+            {
+                D.Filter = "Clang Tidy files|.clang-tidy";
+                D.CheckPathExists = true;
+                D.CheckFileExists = true;
+
+                if (D.ShowDialog() == DialogResult.OK)
+                {
+                    PropertyChain_.Clear();
+                    PropertyChain_ = ClangTidyConfigParser.ParseConfigurationChain(D.FileName);
+                    textBox1.Text = D.FileName;
+                    reloadPropertyChain();
+                }
+            }
+        }
+
+        private static readonly string DefaultText = "(Default)";
+        private static readonly string BrowseText = "Browse for a file to edit its properties";
+
+        /// <summary>
+        /// After a new configuration file is chosen, analyzes the directory hierarchy
+        /// and finds all .clang-tidy files in the path, parses them and updates the
+        /// PropertyGrid and quick-access LinkLabel control to reflect the new property
+        /// chain.
+        /// </summary>
+        private void reloadPropertyChain()
+        {
+            StringBuilder LinkBuilder = new StringBuilder();
+            LinkBuilder.Append(DefaultText);
+            LinkBuilder.Append(" > ");
+            int PrefixLength = LinkBuilder.Length;
+
+            if (PropertyChain_.Count == 1)
+                LinkBuilder.Append(BrowseText);
+            else
+                LinkBuilder.Append(PropertyChain_[PropertyChain_.Count - 1].Key);
+
+            linkLabelPath.Text = LinkBuilder.ToString();
+
+            // Given a path like D:\Foo\Bar\Baz, construct a LinkLabel where individual
+            // components of the path are clickable iff they contain a .clang-tidy file.
+            // Clicking one of the links then updates the PropertyGrid to display the
+            // selected .clang-tidy file.
+            ClangTidyProperties LastProps = ClangTidyProperties.RootProperties;
+            linkLabelPath.Links.Clear();
+            linkLabelPath.Links.Add(0, DefaultText.Length, LastProps);
+            foreach (var Prop in PropertyChain_.Skip(1))
+            {
+                LastProps = Prop.Value;
+                string ClangTidyFolder = Path.GetFileName(Prop.Key);
+                int ClangTidyFolderOffset = Prop.Key.Length - ClangTidyFolder.Length;
+                linkLabelPath.Links.Add(PrefixLength + ClangTidyFolderOffset, ClangTidyFolder.Length, LastProps);
+            }
+            propertyGrid1.SelectedObject = LastProps;
+        }
+
+        private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
+        {
+            ClangTidyProperties Props = (ClangTidyProperties)propertyGrid1.SelectedObject;
+            Props.SetHasUnsavedChanges(true);
+
+            // When a CategoryVerb is selected, perform the corresponding action.
+            PropertyDescriptor Property = e.ChangedItem.PropertyDescriptor;
+            if (!(e.ChangedItem.Value is CategoryVerb))
+                return;
+
+            CategoryVerb Action = (CategoryVerb)e.ChangedItem.Value;
+            if (Action == CategoryVerb.None)
+                return;
+
+            var Category = Property.Attributes.OfType<CategoryAttribute>().FirstOrDefault();
+            if (Category == null)
+                return;
+            var SameCategoryProps = Props.GetProperties(new Attribute[] { Category });
+            foreach (PropertyDescriptor P in SameCategoryProps)
+            {
+                if (P == Property)
+                    continue;
+                switch (Action)
+                {
+                    case CategoryVerb.Disable:
+                        P.SetValue(propertyGrid1.SelectedObject, false);
+                        break;
+                    case CategoryVerb.Enable:
+                        P.SetValue(propertyGrid1.SelectedObject, true);
+                        break;
+                    case CategoryVerb.Inherit:
+                        P.ResetValue(propertyGrid1.SelectedObject);
+                        break;
+                }
+            }
+            Property.ResetValue(propertyGrid1.SelectedObject);
+            propertyGrid1.Invalidate();
+        }
+
+        private void linkLabelPath_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
+        {
+            ClangTidyProperties Props = (ClangTidyProperties)e.Link.LinkData;
+            propertyGrid1.SelectedObject = Props;
+        }
+    }
+}
index 3faf403..beabbce 100644 (file)
@@ -4,4 +4,4 @@
     {\r
         public const uint cmdidClangTidy = 0x100;\r
     };\r
-}
\ No newline at end of file
+}\r
index 1071b68..d801dd1 100644 (file)
-//===-- ClangFormatPackages.cs - VSPackage for clang-format ------*- C# -*-===//\r
-//\r
-//                     The LLVM Compiler Infrastructure\r
-//\r
-// This file is distributed under the University of Illinois Open Source\r
-// License. See LICENSE.TXT for details.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-//\r
-// This class contains a VS extension package that runs clang-format over a\r
-// selection in a VS text editor.\r
-//\r
-//===----------------------------------------------------------------------===//\r
-\r
-using EnvDTE;\r
-using Microsoft.VisualStudio.Shell;\r
-using Microsoft.VisualStudio.Shell.Interop;\r
-using Microsoft.VisualStudio.Text;\r
-using Microsoft.VisualStudio.Text.Editor;\r
-using System;\r
-using System.Collections;\r
-using System.ComponentModel;\r
-using System.ComponentModel.Design;\r
-using System.IO;\r
-using System.Runtime.InteropServices;\r
-using System.Xml.Linq;\r
-using System.Linq;\r
-\r
-namespace LLVM.ClangFormat\r
-{\r
-    [ClassInterface(ClassInterfaceType.AutoDual)]\r
-    [CLSCompliant(false), ComVisible(true)]\r
-    public class OptionPageGrid : DialogPage\r
-    {\r
-        private string assumeFilename = "";\r
-        private string fallbackStyle = "LLVM";\r
-        private bool sortIncludes = false;\r
-        private string style = "file";\r
-        private bool formatOnSave = false;\r
-        private string formatOnSaveFileExtensions =\r
-            ".c;.cpp;.cxx;.cc;.tli;.tlh;.h;.hh;.hpp;.hxx;.hh;.inl;" +\r
-            ".java;.js;.ts;.m;.mm;.proto;.protodevel;.td";\r
-\r
-        public OptionPageGrid Clone()\r
-        {\r
-            // Use MemberwiseClone to copy value types.\r
-            var clone = (OptionPageGrid)MemberwiseClone();\r
-            return clone;\r
-        }\r
-\r
-        public class StyleConverter : TypeConverter\r
-        {\r
-            protected ArrayList values;\r
-            public StyleConverter()\r
-            {\r
-                // Initializes the standard values list with defaults.\r
-                values = new ArrayList(new string[] { "file", "Chromium", "Google", "LLVM", "Mozilla", "WebKit" });\r
-            }\r
-\r
-            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)\r
-            {\r
-                return true;\r
-            }\r
-\r
-            public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)\r
-            {\r
-                return new StandardValuesCollection(values);\r
-            }\r
-\r
-            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\r
-            {\r
-                if (sourceType == typeof(string))\r
-                    return true;\r
-\r
-                return base.CanConvertFrom(context, sourceType);\r
-            }\r
-\r
-            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)\r
-            {\r
-                string s = value as string;\r
-                if (s == null)\r
-                    return base.ConvertFrom(context, culture, value);\r
-\r
-                return value;\r
-            }\r
-        }\r
-\r
-        [Category("Format Options")]\r
-        [DisplayName("Style")]\r
-        [Description("Coding style, currently supports:\n" +\r
-                     "  - Predefined styles ('LLVM', 'Google', 'Chromium', 'Mozilla', 'WebKit').\n" +\r
-                     "  - 'file' to search for a YAML .clang-format or _clang-format\n" +\r
-                     "    configuration file.\n" +\r
-                     "  - A YAML configuration snippet.\n\n" +\r
-                     "'File':\n" +\r
-                     "  Searches for a .clang-format or _clang-format configuration file\n" +\r
-                     "  in the source file's directory and its parents.\n\n" +\r
-                     "YAML configuration snippet:\n" +\r
-                     "  The content of a .clang-format configuration file, as string.\n" +\r
-                     "  Example: '{BasedOnStyle: \"LLVM\", IndentWidth: 8}'\n\n" +\r
-                     "See also: http://clang.llvm.org/docs/ClangFormatStyleOptions.html.")]\r
-        [TypeConverter(typeof(StyleConverter))]\r
-        public string Style\r
-        {\r
-            get { return style; }\r
-            set { style = value; }\r
-        }\r
-\r
-        public sealed class FilenameConverter : TypeConverter\r
-        {\r
-            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)\r
-            {\r
-                if (sourceType == typeof(string))\r
-                    return true;\r
-\r
-                return base.CanConvertFrom(context, sourceType);\r
-            }\r
-\r
-            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)\r
-            {\r
-                string s = value as string;\r
-                if (s == null)\r
-                    return base.ConvertFrom(context, culture, value);\r
-\r
-                // Check if string contains quotes. On Windows, file names cannot contain quotes.\r
-                // We do not accept them however to avoid hard-to-debug problems.\r
-                // A quote in user input would end the parameter quote and so break the command invocation.\r
-                if (s.IndexOf('\"') != -1)\r
-                    throw new NotSupportedException("Filename cannot contain quotes");\r
-\r
-                return value;\r
-            }\r
-        }\r
-\r
-        [Category("Format Options")]\r
-        [DisplayName("Assume Filename")]\r
-        [Description("When reading from stdin, clang-format assumes this " +\r
-                     "filename to look for a style config file (with 'file' style) " +\r
-                     "and to determine the language.")]\r
-        [TypeConverter(typeof(FilenameConverter))]\r
-        public string AssumeFilename\r
-        {\r
-            get { return assumeFilename; }\r
-            set { assumeFilename = value; }\r
-        }\r
-\r
-        public sealed class FallbackStyleConverter : StyleConverter\r
-        {\r
-            public FallbackStyleConverter()\r
-            {\r
-                // Add "none" to the list of styles.\r
-                values.Insert(0, "none");\r
-            }\r
-        }\r
-\r
-        [Category("Format Options")]\r
-        [DisplayName("Fallback Style")]\r
-        [Description("The name of the predefined style used as a fallback in case clang-format " +\r
-                     "is invoked with 'file' style, but can not find the configuration file.\n" +\r
-                     "Use 'none' fallback style to skip formatting.")]\r
-        [TypeConverter(typeof(FallbackStyleConverter))]\r
-        public string FallbackStyle\r
-        {\r
-            get { return fallbackStyle; }\r
-            set { fallbackStyle = value; }\r
-        }\r
-\r
-        [Category("Format Options")]\r
-        [DisplayName("Sort includes")]\r
-        [Description("Sort touched include lines.\n\n" +\r
-                     "See also: http://clang.llvm.org/docs/ClangFormat.html.")]\r
-        public bool SortIncludes\r
-        {\r
-            get { return sortIncludes; }\r
-            set { sortIncludes = value; }\r
-        }\r
-\r
-        [Category("Format On Save")]\r
-        [DisplayName("Enable")]\r
-        [Description("Enable running clang-format when modified files are saved. " +\r
-                     "Will only format if Style is found (ignores Fallback Style)."\r
-            )]\r
-        public bool FormatOnSave\r
-        {\r
-            get { return formatOnSave; }\r
-            set { formatOnSave = value; }\r
-        }\r
-\r
-        [Category("Format On Save")]\r
-        [DisplayName("File extensions")]\r
-        [Description("When formatting on save, clang-format will be applied only to " +\r
-                     "files with these extensions.")]\r
-        public string FormatOnSaveFileExtensions\r
-        {\r
-            get { return formatOnSaveFileExtensions; }\r
-            set { formatOnSaveFileExtensions = value; }\r
-        }\r
-    }\r
-\r
-    [PackageRegistration(UseManagedResourcesOnly = true)]\r
-    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]\r
-    [ProvideMenuResource("Menus.ctmenu", 1)]\r
-    [ProvideAutoLoad(UIContextGuids80.SolutionExists)] // Load package on solution load\r
-    [Guid(GuidList.guidClangFormatPkgString)]\r
-    [ProvideOptionPage(typeof(OptionPageGrid), "LLVM/Clang", "ClangFormat", 0, 0, true)]\r
-    public sealed class ClangFormatPackage : Package\r
-    {\r
-        #region Package Members\r
-\r
-        RunningDocTableEventsDispatcher _runningDocTableEventsDispatcher;\r
-\r
-        protected override void Initialize()\r
-        {\r
-            base.Initialize();\r
-\r
-            _runningDocTableEventsDispatcher = new RunningDocTableEventsDispatcher(this);\r
-            _runningDocTableEventsDispatcher.BeforeSave += OnBeforeSave;\r
-\r
-            var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;\r
-            if (commandService != null)\r
-            {\r
-                {\r
-                    var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatSelection);\r
-                    var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);\r
-                    commandService.AddCommand(menuItem);\r
-                }\r
-\r
-                {\r
-                    var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatDocument);\r
-                    var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);\r
-                    commandService.AddCommand(menuItem);\r
-                }\r
-            }\r
-        }\r
-        #endregion\r
-\r
-        OptionPageGrid GetUserOptions()\r
-        {\r
-            return (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));\r
-        }\r
-\r
-        private void MenuItemCallback(object sender, EventArgs args)\r
-        {\r
-            var mc = sender as System.ComponentModel.Design.MenuCommand;\r
-            if (mc == null)\r
-                return;\r
-\r
-            switch (mc.CommandID.ID)\r
-            {\r
-                case (int)PkgCmdIDList.cmdidClangFormatSelection:\r
-                    FormatSelection(GetUserOptions());\r
-                    break;\r
-\r
-                case (int)PkgCmdIDList.cmdidClangFormatDocument:\r
-                    FormatDocument(GetUserOptions());\r
-                    break;\r
-            }\r
-        }\r
-\r
-        private static bool FileHasExtension(string filePath, string fileExtensions)\r
-        {\r
-            var extensions = fileExtensions.ToLower().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);\r
-            return extensions.Contains(Path.GetExtension(filePath).ToLower());\r
-        }\r
-\r
-        private void OnBeforeSave(object sender, Document document)\r
-        {\r
-            var options = GetUserOptions();\r
-\r
-            if (!options.FormatOnSave)\r
-                return;\r
-\r
-            if (!FileHasExtension(document.FullName, options.FormatOnSaveFileExtensions))\r
-                return;\r
-\r
-            if (!Vsix.IsDocumentDirty(document))\r
-                return;\r
-\r
-            var optionsWithNoFallbackStyle = GetUserOptions().Clone();\r
-            optionsWithNoFallbackStyle.FallbackStyle = "none";\r
-            FormatDocument(document, optionsWithNoFallbackStyle);\r
-        }\r
-\r
-        /// <summary>\r
-        /// Runs clang-format on the current selection\r
-        /// </summary>\r
-        private void FormatSelection(OptionPageGrid options)\r
-        {\r
-            IWpfTextView view = Vsix.GetCurrentView();\r
-            if (view == null)\r
-                // We're not in a text view.\r
-                return;\r
-            string text = view.TextBuffer.CurrentSnapshot.GetText();\r
-            int start = view.Selection.Start.Position.GetContainingLine().Start.Position;\r
-            int end = view.Selection.End.Position.GetContainingLine().End.Position;\r
-            int length = end - start;\r
-            \r
-            // clang-format doesn't support formatting a range that starts at the end\r
-            // of the file.\r
-            if (start >= text.Length && text.Length > 0)\r
-                start = text.Length - 1;\r
-            string path = Vsix.GetDocumentParent(view);\r
-            string filePath = Vsix.GetDocumentPath(view);\r
-\r
-            RunClangFormatAndApplyReplacements(text, start, length, path, filePath, options, view);\r
-        }\r
-\r
-        /// <summary>\r
-        /// Runs clang-format on the current document\r
-        /// </summary>\r
-        private void FormatDocument(OptionPageGrid options)\r
-        {\r
-            FormatView(Vsix.GetCurrentView(), options);\r
-        }\r
-\r
-        private void FormatDocument(Document document, OptionPageGrid options)\r
-        {\r
-            FormatView(Vsix.GetDocumentView(document), options);\r
-        }\r
-\r
-        private void FormatView(IWpfTextView view, OptionPageGrid options)\r
-        {\r
-            if (view == null)\r
-                // We're not in a text view.\r
-                return;\r
-\r
-            string filePath = Vsix.GetDocumentPath(view);\r
-            var path = Path.GetDirectoryName(filePath);\r
-\r
-            string text = view.TextBuffer.CurrentSnapshot.GetText();\r
-            if (!text.EndsWith(Environment.NewLine))\r
-            {\r
-                view.TextBuffer.Insert(view.TextBuffer.CurrentSnapshot.Length, Environment.NewLine);\r
-                text += Environment.NewLine;\r
-            }\r
-\r
-            RunClangFormatAndApplyReplacements(text, 0, text.Length, path, filePath, options, view);\r
-        }\r
-\r
-        private void RunClangFormatAndApplyReplacements(string text, int offset, int length, string path, string filePath, OptionPageGrid options, IWpfTextView view)\r
-        {\r
-            try\r
-            {\r
-                string replacements = RunClangFormat(text, offset, length, path, filePath, options);\r
-                ApplyClangFormatReplacements(replacements, view);\r
-            }\r
-            catch (Exception e)\r
-            {\r
-                var uiShell = (IVsUIShell)GetService(typeof(SVsUIShell));\r
-                var id = Guid.Empty;\r
-                int result;\r
-                uiShell.ShowMessageBox(\r
-                        0, ref id,\r
-                        "Error while running clang-format:",\r
-                        e.Message,\r
-                        string.Empty, 0,\r
-                        OLEMSGBUTTON.OLEMSGBUTTON_OK,\r
-                        OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,\r
-                        OLEMSGICON.OLEMSGICON_INFO,\r
-                        0, out result);\r
-            }\r
-        }\r
-\r
-        /// <summary>\r
-        /// Runs the given text through clang-format and returns the replacements as XML.\r
-        /// \r
-        /// Formats the text range starting at offset of the given length.\r
-        /// </summary>\r
-        private static string RunClangFormat(string text, int offset, int length, string path, string filePath, OptionPageGrid options)\r
-        {\r
-            string vsixPath = Path.GetDirectoryName(\r
-                typeof(ClangFormatPackage).Assembly.Location);\r
-\r
-            System.Diagnostics.Process process = new System.Diagnostics.Process();\r
-            process.StartInfo.UseShellExecute = false;\r
-            process.StartInfo.FileName = vsixPath + "\\clang-format.exe";\r
-            // Poor man's escaping - this will not work when quotes are already escaped\r
-            // in the input (but we don't need more).\r
-            string style = options.Style.Replace("\"", "\\\"");\r
-            string fallbackStyle = options.FallbackStyle.Replace("\"", "\\\"");\r
-            process.StartInfo.Arguments = " -offset " + offset +\r
-                                          " -length " + length +\r
-                                          " -output-replacements-xml " +\r
-                                          " -style \"" + style + "\"" +\r
-                                          " -fallback-style \"" + fallbackStyle + "\"";\r
-            if (options.SortIncludes)\r
-              process.StartInfo.Arguments += " -sort-includes ";\r
-            string assumeFilename = options.AssumeFilename;\r
-            if (string.IsNullOrEmpty(assumeFilename))\r
-                assumeFilename = filePath;\r
-            if (!string.IsNullOrEmpty(assumeFilename))\r
-              process.StartInfo.Arguments += " -assume-filename \"" + assumeFilename + "\"";\r
-            process.StartInfo.CreateNoWindow = true;\r
-            process.StartInfo.RedirectStandardInput = true;\r
-            process.StartInfo.RedirectStandardOutput = true;\r
-            process.StartInfo.RedirectStandardError = true;\r
-            if (path != null)\r
-                process.StartInfo.WorkingDirectory = path;\r
-            // We have to be careful when communicating via standard input / output,\r
-            // as writes to the buffers will block until they are read from the other side.\r
-            // Thus, we:\r
-            // 1. Start the process - clang-format.exe will start to read the input from the\r
-            //    standard input.\r
-            try\r
-            {\r
-                process.Start();\r
-            }\r
-            catch (Exception e)\r
-            {\r
-                throw new Exception(\r
-                    "Cannot execute " + process.StartInfo.FileName + ".\n\"" + \r
-                    e.Message + "\".\nPlease make sure it is on the PATH.");\r
-            }\r
-            // 2. We write everything to the standard output - this cannot block, as clang-format\r
-            //    reads the full standard input before analyzing it without writing anything to the\r
-            //    standard output.\r
-            process.StandardInput.Write(text);\r
-            // 3. We notify clang-format that the input is done - after this point clang-format\r
-            //    will start analyzing the input and eventually write the output.\r
-            process.StandardInput.Close();\r
-            // 4. We must read clang-format's output before waiting for it to exit; clang-format\r
-            //    will close the channel by exiting.\r
-            string output = process.StandardOutput.ReadToEnd();\r
-            // 5. clang-format is done, wait until it is fully shut down.\r
-            process.WaitForExit();\r
-            if (process.ExitCode != 0)\r
-            {\r
-                // FIXME: If clang-format writes enough to the standard error stream to block,\r
-                // we will never reach this point; instead, read the standard error asynchronously.\r
-                throw new Exception(process.StandardError.ReadToEnd());\r
-            }\r
-            return output;\r
-        }\r
-\r
-        /// <summary>\r
-        /// Applies the clang-format replacements (xml) to the current view\r
-        /// </summary>\r
-        private static void ApplyClangFormatReplacements(string replacements, IWpfTextView view)\r
-        {\r
-            // clang-format returns no replacements if input text is empty\r
-            if (replacements.Length == 0)\r
-                return;\r
-\r
-            var root = XElement.Parse(replacements);\r
-            var edit = view.TextBuffer.CreateEdit();\r
-            foreach (XElement replacement in root.Descendants("replacement"))\r
-            {\r
-                var span = new Span(\r
-                    int.Parse(replacement.Attribute("offset").Value),\r
-                    int.Parse(replacement.Attribute("length").Value));\r
-                edit.Replace(span, replacement.Value);\r
-            }\r
-            edit.Apply();\r
-        }\r
-    }\r
-}\r
+//===-- ClangFormatPackages.cs - VSPackage for clang-format ------*- C# -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class contains a VS extension package that runs clang-format over a
+// selection in a VS text editor.
+//
+//===----------------------------------------------------------------------===//
+
+using EnvDTE;
+using Microsoft.VisualStudio.Shell;
+using Microsoft.VisualStudio.Shell.Interop;
+using Microsoft.VisualStudio.Text;
+using Microsoft.VisualStudio.Text.Editor;
+using System;
+using System.Collections;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Xml.Linq;
+using System.Linq;
+
+namespace LLVM.ClangFormat
+{
+    [ClassInterface(ClassInterfaceType.AutoDual)]
+    [CLSCompliant(false), ComVisible(true)]
+    public class OptionPageGrid : DialogPage
+    {
+        private string assumeFilename = "";
+        private string fallbackStyle = "LLVM";
+        private bool sortIncludes = false;
+        private string style = "file";
+        private bool formatOnSave = false;
+        private string formatOnSaveFileExtensions =
+            ".c;.cpp;.cxx;.cc;.tli;.tlh;.h;.hh;.hpp;.hxx;.hh;.inl;" +
+            ".java;.js;.ts;.m;.mm;.proto;.protodevel;.td";
+
+        public OptionPageGrid Clone()
+        {
+            // Use MemberwiseClone to copy value types.
+            var clone = (OptionPageGrid)MemberwiseClone();
+            return clone;
+        }
+
+        public class StyleConverter : TypeConverter
+        {
+            protected ArrayList values;
+            public StyleConverter()
+            {
+                // Initializes the standard values list with defaults.
+                values = new ArrayList(new string[] { "file", "Chromium", "Google", "LLVM", "Mozilla", "WebKit" });
+            }
+
+            public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
+            {
+                return true;
+            }
+
+            public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
+            {
+                return new StandardValuesCollection(values);
+            }
+
+            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+            {
+                if (sourceType == typeof(string))
+                    return true;
+
+                return base.CanConvertFrom(context, sourceType);
+            }
+
+            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
+            {
+                string s = value as string;
+                if (s == null)
+                    return base.ConvertFrom(context, culture, value);
+
+                return value;
+            }
+        }
+
+        [Category("Format Options")]
+        [DisplayName("Style")]
+        [Description("Coding style, currently supports:\n" +
+                     "  - Predefined styles ('LLVM', 'Google', 'Chromium', 'Mozilla', 'WebKit').\n" +
+                     "  - 'file' to search for a YAML .clang-format or _clang-format\n" +
+                     "    configuration file.\n" +
+                     "  - A YAML configuration snippet.\n\n" +
+                     "'File':\n" +
+                     "  Searches for a .clang-format or _clang-format configuration file\n" +
+                     "  in the source file's directory and its parents.\n\n" +
+                     "YAML configuration snippet:\n" +
+                     "  The content of a .clang-format configuration file, as string.\n" +
+                     "  Example: '{BasedOnStyle: \"LLVM\", IndentWidth: 8}'\n\n" +
+                     "See also: http://clang.llvm.org/docs/ClangFormatStyleOptions.html.")]
+        [TypeConverter(typeof(StyleConverter))]
+        public string Style
+        {
+            get { return style; }
+            set { style = value; }
+        }
+
+        public sealed class FilenameConverter : TypeConverter
+        {
+            public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
+            {
+                if (sourceType == typeof(string))
+                    return true;
+
+                return base.CanConvertFrom(context, sourceType);
+            }
+
+            public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
+            {
+                string s = value as string;
+                if (s == null)
+                    return base.ConvertFrom(context, culture, value);
+
+                // Check if string contains quotes. On Windows, file names cannot contain quotes.
+                // We do not accept them however to avoid hard-to-debug problems.
+                // A quote in user input would end the parameter quote and so break the command invocation.
+                if (s.IndexOf('\"') != -1)
+                    throw new NotSupportedException("Filename cannot contain quotes");
+
+                return value;
+            }
+        }
+
+        [Category("Format Options")]
+        [DisplayName("Assume Filename")]
+        [Description("When reading from stdin, clang-format assumes this " +
+                     "filename to look for a style config file (with 'file' style) " +
+                     "and to determine the language.")]
+        [TypeConverter(typeof(FilenameConverter))]
+        public string AssumeFilename
+        {
+            get { return assumeFilename; }
+            set { assumeFilename = value; }
+        }
+
+        public sealed class FallbackStyleConverter : StyleConverter
+        {
+            public FallbackStyleConverter()
+            {
+                // Add "none" to the list of styles.
+                values.Insert(0, "none");
+            }
+        }
+
+        [Category("Format Options")]
+        [DisplayName("Fallback Style")]
+        [Description("The name of the predefined style used as a fallback in case clang-format " +
+                     "is invoked with 'file' style, but can not find the configuration file.\n" +
+                     "Use 'none' fallback style to skip formatting.")]
+        [TypeConverter(typeof(FallbackStyleConverter))]
+        public string FallbackStyle
+        {
+            get { return fallbackStyle; }
+            set { fallbackStyle = value; }
+        }
+
+        [Category("Format Options")]
+        [DisplayName("Sort includes")]
+        [Description("Sort touched include lines.\n\n" +
+                     "See also: http://clang.llvm.org/docs/ClangFormat.html.")]
+        public bool SortIncludes
+        {
+            get { return sortIncludes; }
+            set { sortIncludes = value; }
+        }
+
+        [Category("Format On Save")]
+        [DisplayName("Enable")]
+        [Description("Enable running clang-format when modified files are saved. " +
+                     "Will only format if Style is found (ignores Fallback Style)."
+            )]
+        public bool FormatOnSave
+        {
+            get { return formatOnSave; }
+            set { formatOnSave = value; }
+        }
+
+        [Category("Format On Save")]
+        [DisplayName("File extensions")]
+        [Description("When formatting on save, clang-format will be applied only to " +
+                     "files with these extensions.")]
+        public string FormatOnSaveFileExtensions
+        {
+            get { return formatOnSaveFileExtensions; }
+            set { formatOnSaveFileExtensions = value; }
+        }
+    }
+
+    [PackageRegistration(UseManagedResourcesOnly = true)]
+    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
+    [ProvideMenuResource("Menus.ctmenu", 1)]
+    [ProvideAutoLoad(UIContextGuids80.SolutionExists)] // Load package on solution load
+    [Guid(GuidList.guidClangFormatPkgString)]
+    [ProvideOptionPage(typeof(OptionPageGrid), "LLVM/Clang", "ClangFormat", 0, 0, true)]
+    public sealed class ClangFormatPackage : Package
+    {
+        #region Package Members
+
+        RunningDocTableEventsDispatcher _runningDocTableEventsDispatcher;
+
+        protected override void Initialize()
+        {
+            base.Initialize();
+
+            _runningDocTableEventsDispatcher = new RunningDocTableEventsDispatcher(this);
+            _runningDocTableEventsDispatcher.BeforeSave += OnBeforeSave;
+
+            var commandService = GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
+            if (commandService != null)
+            {
+                {
+                    var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatSelection);
+                    var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+                    commandService.AddCommand(menuItem);
+                }
+
+                {
+                    var menuCommandID = new CommandID(GuidList.guidClangFormatCmdSet, (int)PkgCmdIDList.cmdidClangFormatDocument);
+                    var menuItem = new MenuCommand(MenuItemCallback, menuCommandID);
+                    commandService.AddCommand(menuItem);
+                }
+            }
+        }
+        #endregion
+
+        OptionPageGrid GetUserOptions()
+        {
+            return (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid));
+        }
+
+        private void MenuItemCallback(object sender, EventArgs args)
+        {
+            var mc = sender as System.ComponentModel.Design.MenuCommand;
+            if (mc == null)
+                return;
+
+            switch (mc.CommandID.ID)
+            {
+                case (int)PkgCmdIDList.cmdidClangFormatSelection:
+                    FormatSelection(GetUserOptions());
+                    break;
+
+                case (int)PkgCmdIDList.cmdidClangFormatDocument:
+                    FormatDocument(GetUserOptions());
+                    break;
+            }
+        }
+
+        private static bool FileHasExtension(string filePath, string fileExtensions)
+        {
+            var extensions = fileExtensions.ToLower().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
+            return extensions.Contains(Path.GetExtension(filePath).ToLower());
+        }
+
+        private void OnBeforeSave(object sender, Document document)
+        {
+            var options = GetUserOptions();
+
+            if (!options.FormatOnSave)
+                return;
+
+            if (!FileHasExtension(document.FullName, options.FormatOnSaveFileExtensions))
+                return;
+
+            if (!Vsix.IsDocumentDirty(document))
+                return;
+
+            var optionsWithNoFallbackStyle = GetUserOptions().Clone();
+            optionsWithNoFallbackStyle.FallbackStyle = "none";
+            FormatDocument(document, optionsWithNoFallbackStyle);
+        }
+
+        /// <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);
+        }
+
+        /// <summary>
+        /// Runs clang-format on the current document
+        /// </summary>
+        private void FormatDocument(OptionPageGrid options)
+        {
+            FormatView(Vsix.GetCurrentView(), options);
+        }
+
+        private void FormatDocument(Document document, OptionPageGrid options)
+        {
+            FormatView(Vsix.GetDocumentView(document), options);
+        }
+
+        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;
+            }
+
+            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)
+        {
+            try
+            {
+                string replacements = RunClangFormat(text, 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);
+            }
+        }
+
+        /// <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(string text, 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
+            {
+                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.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();
+            // 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());
+            }
+            return output;
+        }
+
+        /// <summary>
+        /// Applies the clang-format replacements (xml) to the current view
+        /// </summary>
+        private static void ApplyClangFormatReplacements(string replacements, IWpfTextView view)
+        {
+            // clang-format returns no replacements if input text is empty
+            if (replacements.Length == 0)
+                return;
+
+            var root = XElement.Parse(replacements);
+            var edit = view.TextBuffer.CreateEdit();
+            foreach (XElement replacement in root.Descendants("replacement"))
+            {
+                var span = new Span(
+                    int.Parse(replacement.Attribute("offset").Value),
+                    int.Parse(replacement.Attribute("length").Value));
+                edit.Replace(span, replacement.Value);
+            }
+            edit.Apply();
+        }
+    }
+}
index c045224..ed1c12d 100644 (file)
@@ -9,4 +9,4 @@ namespace LLVM.ClangFormat
 \r
         public static readonly Guid guidClangFormatCmdSet = new Guid(guidClangFormatCmdSetString);\r
     };\r
-}
\ No newline at end of file
+}\r
index fcc31ee..c274d1c 100644 (file)
@@ -5,4 +5,4 @@
         public const uint cmdidClangFormatSelection = 0x100;\r
         public const uint cmdidClangFormatDocument = 0x101;\r
     };\r
-}
\ No newline at end of file
+}\r