Index: tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs =================================================================== --- tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs +++ tools/clang-format-vs/ClangFormat/ClangFormatPackage.cs @@ -19,10 +19,10 @@ using Microsoft.VisualStudio.Text.Editor; using Microsoft.VisualStudio.TextManager.Interop; using System; +using System.Collections; using System.ComponentModel; using System.ComponentModel.Design; using System.IO; -using System.Reflection; using System.Runtime.InteropServices; using System.Xml.Linq; @@ -32,13 +32,53 @@ [CLSCompliant(false), ComVisible(true)] public class OptionPageGrid : DialogPage { - private string style = "File"; + private string assumeFilename = ""; + private string fallbackStyle = "LLVM"; + private bool sortIncludes = false; + private string style = "file"; + + 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("LLVM/Clang")] [DisplayName("Style")] [Description("Coding style, currently supports:\n" + - " - Predefined styles ('LLVM', 'Google', 'Chromium', 'Mozilla').\n" + - " - 'File' to search for a YAML .clang-format or _clang-format\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" + @@ -48,11 +88,81 @@ " 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("LLVM/Clang")] + [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("LLVM/Clang")] + [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("LLVM/Clang")] + [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; } + } } [PackageRegistration(UseManagedResourcesOnly = true)] @@ -138,10 +248,17 @@ // Poor man's escaping - this will not work when quotes are already escaped // in the input (but we don't need more). string style = GetStyle().Replace("\"", "\\\""); + string fallbackStyle = GetFallbackStyle().Replace("\"", "\\\""); process.StartInfo.Arguments = " -offset " + offset + " -length " + length + " -output-replacements-xml " + - " -style \"" + style + "\""; + " -style \"" + style + "\"" + + " -fallback-style \"" + fallbackStyle + "\""; + if (GetSortIncludes()) + process.StartInfo.Arguments += " -sort-includes "; + string assumeFilename = GetAssumeFilename(); + if (!string.IsNullOrEmpty(assumeFilename)) + process.StartInfo.Arguments += " -assume-filename \"" + assumeFilename + "\""; process.StartInfo.CreateNoWindow = true; process.StartInfo.RedirectStandardInput = true; process.StartInfo.RedirectStandardOutput = true; @@ -211,6 +328,24 @@ return page.Style; } + private string GetAssumeFilename() + { + var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); + return page.AssumeFilename; + } + + private string GetFallbackStyle() + { + var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); + return page.FallbackStyle; + } + + private bool GetSortIncludes() + { + var page = (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); + return page.SortIncludes; + } + private string GetDocumentParent(IWpfTextView view) { ITextDocument document; Index: tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs =================================================================== --- tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs +++ tools/clang-format-vs/ClangFormat/Properties/AssemblyInfo.cs @@ -29,5 +29,5 @@ // You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("1.1.0.0")] +[assembly: AssemblyFileVersion("1.1.0.0")] Index: tools/clang-format/ClangFormat.cpp =================================================================== --- tools/clang-format/ClangFormat.cpp +++ tools/clang-format/ClangFormat.cpp @@ -199,9 +199,11 @@ } static void outputReplacementXML(StringRef Text) { + // FIXME: When we sort includes, we need to make sure the stream is correct + // utf-8. size_t From = 0; size_t Index; - while ((Index = Text.find_first_of("\n\r", From)) != StringRef::npos) { + while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) { llvm::outs() << Text.substr(From, Index - From); switch (Text[Index]) { case '\n': @@ -210,6 +212,12 @@ case '\r': llvm::outs() << " "; break; + case '<': + llvm::outs() << "<"; + break; + case '&': + llvm::outs() << "&"; + break; default: llvm_unreachable("Unexpected character encountered!"); }