head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.13
	netbsd-11-0-RC3:1.1.1.13
	netbsd-11-0-RC2:1.1.1.13
	netbsd-11-0-RC1:1.1.1.13
	perseant-exfatfs-base-20250801:1.1.1.13
	netbsd-11:1.1.1.13.0.10
	netbsd-11-base:1.1.1.13
	netbsd-10-1-RELEASE:1.1.1.13
	perseant-exfatfs-base-20240630:1.1.1.13
	perseant-exfatfs:1.1.1.13.0.8
	perseant-exfatfs-base:1.1.1.13
	netbsd-8-3-RELEASE:1.1.1.9
	netbsd-9-4-RELEASE:1.1.1.12
	netbsd-10-0-RELEASE:1.1.1.13
	netbsd-10-0-RC6:1.1.1.13
	netbsd-10-0-RC5:1.1.1.13
	netbsd-10-0-RC4:1.1.1.13
	netbsd-10-0-RC3:1.1.1.13
	netbsd-10-0-RC2:1.1.1.13
	netbsd-10-0-RC1:1.1.1.13
	netbsd-10:1.1.1.13.0.6
	netbsd-10-base:1.1.1.13
	netbsd-9-3-RELEASE:1.1.1.12
	cjep_sun2x:1.1.1.13.0.4
	cjep_sun2x-base:1.1.1.13
	cjep_staticlib_x-base1:1.1.1.13
	netbsd-9-2-RELEASE:1.1.1.12
	cjep_staticlib_x:1.1.1.13.0.2
	cjep_staticlib_x-base:1.1.1.13
	netbsd-9-1-RELEASE:1.1.1.12
	phil-wifi-20200421:1.1.1.13
	phil-wifi-20200411:1.1.1.13
	phil-wifi-20200406:1.1.1.13
	netbsd-8-2-RELEASE:1.1.1.9
	netbsd-9-0-RELEASE:1.1.1.12
	netbsd-9-0-RC2:1.1.1.12
	netbsd-9-0-RC1:1.1.1.12
	netbsd-9:1.1.1.12.0.2
	netbsd-9-base:1.1.1.12
	phil-wifi-20190609:1.1.1.12
	netbsd-8-1-RELEASE:1.1.1.9
	netbsd-8-1-RC1:1.1.1.9
	pgoyette-compat-merge-20190127:1.1.1.11.2.1
	pgoyette-compat-20190127:1.1.1.12
	pgoyette-compat-20190118:1.1.1.12
	pgoyette-compat-1226:1.1.1.12
	pgoyette-compat-1126:1.1.1.12
	pgoyette-compat-1020:1.1.1.12
	pgoyette-compat-0930:1.1.1.12
	pgoyette-compat-0906:1.1.1.12
	netbsd-7-2-RELEASE:1.1.1.6.2.1
	pgoyette-compat-0728:1.1.1.12
	clang-337282:1.1.1.12
	netbsd-8-0-RELEASE:1.1.1.9
	phil-wifi:1.1.1.11.0.4
	phil-wifi-base:1.1.1.11
	pgoyette-compat-0625:1.1.1.11
	netbsd-8-0-RC2:1.1.1.9
	pgoyette-compat-0521:1.1.1.11
	pgoyette-compat-0502:1.1.1.11
	pgoyette-compat-0422:1.1.1.11
	netbsd-8-0-RC1:1.1.1.9
	pgoyette-compat-0415:1.1.1.11
	pgoyette-compat-0407:1.1.1.11
	pgoyette-compat-0330:1.1.1.11
	pgoyette-compat-0322:1.1.1.11
	pgoyette-compat-0315:1.1.1.11
	netbsd-7-1-2-RELEASE:1.1.1.6.2.1
	pgoyette-compat:1.1.1.11.0.2
	pgoyette-compat-base:1.1.1.11
	netbsd-7-1-1-RELEASE:1.1.1.6.2.1
	clang-319952:1.1.1.11
	matt-nb8-mediatek:1.1.1.9.0.10
	matt-nb8-mediatek-base:1.1.1.9
	clang-309604:1.1.1.10
	perseant-stdc-iso10646:1.1.1.9.0.8
	perseant-stdc-iso10646-base:1.1.1.9
	netbsd-8:1.1.1.9.0.6
	netbsd-8-base:1.1.1.9
	prg-localcount2-base3:1.1.1.9
	prg-localcount2-base2:1.1.1.9
	prg-localcount2-base1:1.1.1.9
	prg-localcount2:1.1.1.9.0.4
	prg-localcount2-base:1.1.1.9
	pgoyette-localcount-20170426:1.1.1.9
	bouyer-socketcan-base1:1.1.1.9
	pgoyette-localcount-20170320:1.1.1.9
	netbsd-7-1:1.1.1.6.2.1.0.6
	netbsd-7-1-RELEASE:1.1.1.6.2.1
	netbsd-7-1-RC2:1.1.1.6.2.1
	clang-294123:1.1.1.9
	netbsd-7-nhusb-base-20170116:1.1.1.6.2.1
	bouyer-socketcan:1.1.1.9.0.2
	bouyer-socketcan-base:1.1.1.9
	clang-291444:1.1.1.9
	pgoyette-localcount-20170107:1.1.1.8
	netbsd-7-1-RC1:1.1.1.6.2.1
	pgoyette-localcount-20161104:1.1.1.8
	netbsd-7-0-2-RELEASE:1.1.1.6.2.1
	localcount-20160914:1.1.1.8
	netbsd-7-nhusb:1.1.1.6.2.1.0.4
	netbsd-7-nhusb-base:1.1.1.6.2.1
	clang-280599:1.1.1.8
	pgoyette-localcount-20160806:1.1.1.8
	pgoyette-localcount-20160726:1.1.1.8
	pgoyette-localcount:1.1.1.8.0.2
	pgoyette-localcount-base:1.1.1.8
	netbsd-7-0-1-RELEASE:1.1.1.6.2.1
	clang-261930:1.1.1.8
	netbsd-7-0:1.1.1.6.2.1.0.2
	netbsd-7-0-RELEASE:1.1.1.6.2.1
	netbsd-7-0-RC3:1.1.1.6.2.1
	netbsd-7-0-RC2:1.1.1.6.2.1
	netbsd-7-0-RC1:1.1.1.6.2.1
	clang-237755:1.1.1.7
	clang-232565:1.1.1.7
	clang-227398:1.1.1.7
	tls-maxphys-base:1.1.1.6
	tls-maxphys:1.1.1.6.0.4
	netbsd-7:1.1.1.6.0.2
	netbsd-7-base:1.1.1.6
	clang-215315:1.1.1.6
	clang-209886:1.1.1.5
	yamt-pagecache:1.1.1.4.0.4
	yamt-pagecache-base9:1.1.1.4
	tls-earlyentropy:1.1.1.4.0.2
	tls-earlyentropy-base:1.1.1.5
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.4
	riastradh-drm2-base3:1.1.1.4
	clang-202566:1.1.1.4
	clang-201163:1.1.1.4
	clang-199312:1.1.1.3
	clang-198450:1.1.1.2
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.52;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.52;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.05.15.39.27;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	wh3aCSIWykURqWjx;

1.1.1.3
date	2014.01.15.21.26.24;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	NQXlzzA0SPkc5glx;

1.1.1.4
date	2014.02.14.20.07.24;	author joerg;	state Exp;
branches
	1.1.1.4.2.1
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	annVkZ1sc17rF6px;

1.1.1.5
date	2014.05.30.18.14.41;	author joerg;	state Exp;
branches;
next	1.1.1.6;
commitid	8q0kdlBlCn09GACx;

1.1.1.6
date	2014.08.10.17.08.34;	author joerg;	state Exp;
branches
	1.1.1.6.2.1
	1.1.1.6.4.1;
next	1.1.1.7;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.7
date	2015.01.29.19.57.30;	author joerg;	state Exp;
branches;
next	1.1.1.8;
commitid	mlISSizlPKvepX7y;

1.1.1.8
date	2016.02.27.22.12.04;	author joerg;	state Exp;
branches
	1.1.1.8.2.1;
next	1.1.1.9;
commitid	tIimz3oDlh1NpBWy;

1.1.1.9
date	2017.01.11.10.33.38;	author joerg;	state Exp;
branches;
next	1.1.1.10;
commitid	CNnUNfII1jgNmxBz;

1.1.1.10
date	2017.08.01.19.34.53;	author joerg;	state Exp;
branches;
next	1.1.1.11;
commitid	pMuDy65V0VicSx1A;

1.1.1.11
date	2017.12.17.20.58.50;	author joerg;	state Exp;
branches
	1.1.1.11.2.1
	1.1.1.11.4.1;
next	1.1.1.12;
commitid	T7p9sjiUJyY1UhjA;

1.1.1.12
date	2018.07.17.18.30.57;	author joerg;	state Exp;
branches;
next	1.1.1.13;
commitid	wDzL46ALjrCZgwKA;

1.1.1.13
date	2019.11.13.22.19.23;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.4.2.1
date	2014.08.10.07.08.08;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.4.4.1
date	2014.02.14.20.07.24;	author yamt;	state dead;
branches;
next	1.1.1.4.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.4.4.2
date	2014.05.22.16.18.27;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.6.2.1
date	2015.06.04.20.04.28;	author snj;	state Exp;
branches;
next	;
commitid	yRnjq9fueSo6n9oy;

1.1.1.6.4.1
date	2014.08.10.17.08.34;	author tls;	state dead;
branches;
next	1.1.1.6.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.6.4.2
date	2014.08.19.23.47.28;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.8.2.1
date	2017.03.20.06.52.38;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.11.2.1
date	2018.07.28.04.33.19;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.11.4.1
date	2019.06.10.21.45.23;	author christos;	state Exp;
branches;
next	1.1.1.11.4.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.11.4.2
date	2020.04.13.07.46.33;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@//===--- Format.cpp - Format C++ code -------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements functions declared in Format.h. This will be
/// split into separate files as we go.
///
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "format-formatter"

#include "ContinuationIndenter.h"
#include "TokenAnnotator.h"
#include "UnwrappedLineParser.h"
#include "WhitespaceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/YAMLTraits.h"
#include "llvm/Support/Path.h"
#include <queue>
#include <string>

namespace llvm {
namespace yaml {
template <>
struct ScalarEnumerationTraits<clang::format::FormatStyle::LanguageStandard> {
  static void enumeration(IO &IO,
                          clang::format::FormatStyle::LanguageStandard &Value) {
    IO.enumCase(Value, "Cpp03", clang::format::FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "C++03", clang::format::FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "Cpp11", clang::format::FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "C++11", clang::format::FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "Auto", clang::format::FormatStyle::LS_Auto);
  }
};

template <>
struct ScalarEnumerationTraits<clang::format::FormatStyle::UseTabStyle> {
  static void enumeration(IO &IO,
                          clang::format::FormatStyle::UseTabStyle &Value) {
    IO.enumCase(Value, "Never", clang::format::FormatStyle::UT_Never);
    IO.enumCase(Value, "false", clang::format::FormatStyle::UT_Never);
    IO.enumCase(Value, "Always", clang::format::FormatStyle::UT_Always);
    IO.enumCase(Value, "true", clang::format::FormatStyle::UT_Always);
    IO.enumCase(Value, "ForIndentation",
                clang::format::FormatStyle::UT_ForIndentation);
  }
};

template <>
struct ScalarEnumerationTraits<clang::format::FormatStyle::BraceBreakingStyle> {
  static void
  enumeration(IO &IO, clang::format::FormatStyle::BraceBreakingStyle &Value) {
    IO.enumCase(Value, "Attach", clang::format::FormatStyle::BS_Attach);
    IO.enumCase(Value, "Linux", clang::format::FormatStyle::BS_Linux);
    IO.enumCase(Value, "Stroustrup", clang::format::FormatStyle::BS_Stroustrup);
    IO.enumCase(Value, "Allman", clang::format::FormatStyle::BS_Allman);
  }
};

template <>
struct ScalarEnumerationTraits<
    clang::format::FormatStyle::NamespaceIndentationKind> {
  static void
  enumeration(IO &IO,
              clang::format::FormatStyle::NamespaceIndentationKind &Value) {
    IO.enumCase(Value, "None", clang::format::FormatStyle::NI_None);
    IO.enumCase(Value, "Inner", clang::format::FormatStyle::NI_Inner);
    IO.enumCase(Value, "All", clang::format::FormatStyle::NI_All);
  }
};

template <> struct MappingTraits<clang::format::FormatStyle> {
  static void mapping(llvm::yaml::IO &IO, clang::format::FormatStyle &Style) {
    if (IO.outputting()) {
      StringRef StylesArray[] = { "LLVM",    "Google", "Chromium",
                                  "Mozilla", "WebKit" };
      ArrayRef<StringRef> Styles(StylesArray);
      for (size_t i = 0, e = Styles.size(); i < e; ++i) {
        StringRef StyleName(Styles[i]);
        clang::format::FormatStyle PredefinedStyle;
        if (clang::format::getPredefinedStyle(StyleName, &PredefinedStyle) &&
            Style == PredefinedStyle) {
          IO.mapOptional("# BasedOnStyle", StyleName);
          break;
        }
      }
    } else {
      StringRef BasedOnStyle;
      IO.mapOptional("BasedOnStyle", BasedOnStyle);
      if (!BasedOnStyle.empty())
        if (!clang::format::getPredefinedStyle(BasedOnStyle, &Style)) {
          IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
          return;
        }
    }

    IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
    IO.mapOptional("ConstructorInitializerIndentWidth",
                   Style.ConstructorInitializerIndentWidth);
    IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
    IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
    IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
                   Style.AllowAllParametersOfDeclarationOnNextLine);
    IO.mapOptional("AllowShortIfStatementsOnASingleLine",
                   Style.AllowShortIfStatementsOnASingleLine);
    IO.mapOptional("AllowShortLoopsOnASingleLine",
                   Style.AllowShortLoopsOnASingleLine);
    IO.mapOptional("AlwaysBreakTemplateDeclarations",
                   Style.AlwaysBreakTemplateDeclarations);
    IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
                   Style.AlwaysBreakBeforeMultilineStrings);
    IO.mapOptional("BreakBeforeBinaryOperators",
                   Style.BreakBeforeBinaryOperators);
    IO.mapOptional("BreakBeforeTernaryOperators",
                   Style.BreakBeforeTernaryOperators);
    IO.mapOptional("BreakConstructorInitializersBeforeComma",
                   Style.BreakConstructorInitializersBeforeComma);
    IO.mapOptional("BinPackParameters", Style.BinPackParameters);
    IO.mapOptional("ColumnLimit", Style.ColumnLimit);
    IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
                   Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
    IO.mapOptional("DerivePointerBinding", Style.DerivePointerBinding);
    IO.mapOptional("ExperimentalAutoDetectBinPacking",
                   Style.ExperimentalAutoDetectBinPacking);
    IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
    IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
    IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
    IO.mapOptional("ObjCSpaceBeforeProtocolList",
                   Style.ObjCSpaceBeforeProtocolList);
    IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
                   Style.PenaltyBreakBeforeFirstCallParameter);
    IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
    IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
    IO.mapOptional("PenaltyBreakFirstLessLess",
                   Style.PenaltyBreakFirstLessLess);
    IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
    IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
                   Style.PenaltyReturnTypeOnItsOwnLine);
    IO.mapOptional("PointerBindsToType", Style.PointerBindsToType);
    IO.mapOptional("SpacesBeforeTrailingComments",
                   Style.SpacesBeforeTrailingComments);
    IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
    IO.mapOptional("Standard", Style.Standard);
    IO.mapOptional("IndentWidth", Style.IndentWidth);
    IO.mapOptional("TabWidth", Style.TabWidth);
    IO.mapOptional("UseTab", Style.UseTab);
    IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
    IO.mapOptional("IndentFunctionDeclarationAfterType",
                   Style.IndentFunctionDeclarationAfterType);
    IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
    IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
    IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
    IO.mapOptional("SpacesInCStyleCastParentheses",
                   Style.SpacesInCStyleCastParentheses);
    IO.mapOptional("SpaceAfterControlStatementKeyword",
                   Style.SpaceAfterControlStatementKeyword);
    IO.mapOptional("SpaceBeforeAssignmentOperators",
                   Style.SpaceBeforeAssignmentOperators);
    IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
  }
};
}
}

namespace clang {
namespace format {

void setDefaultPenalties(FormatStyle &Style) {
  Style.PenaltyBreakComment = 60;
  Style.PenaltyBreakFirstLessLess = 120;
  Style.PenaltyBreakString = 1000;
  Style.PenaltyExcessCharacter = 1000000;
}

FormatStyle getLLVMStyle() {
  FormatStyle LLVMStyle;
  LLVMStyle.AccessModifierOffset = -2;
  LLVMStyle.AlignEscapedNewlinesLeft = false;
  LLVMStyle.AlignTrailingComments = true;
  LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
  LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
  LLVMStyle.AllowShortLoopsOnASingleLine = false;
  LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
  LLVMStyle.AlwaysBreakTemplateDeclarations = false;
  LLVMStyle.BinPackParameters = true;
  LLVMStyle.BreakBeforeBinaryOperators = false;
  LLVMStyle.BreakBeforeTernaryOperators = true;
  LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
  LLVMStyle.BreakConstructorInitializersBeforeComma = false;
  LLVMStyle.ColumnLimit = 80;
  LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
  LLVMStyle.ConstructorInitializerIndentWidth = 4;
  LLVMStyle.Cpp11BracedListStyle = false;
  LLVMStyle.DerivePointerBinding = false;
  LLVMStyle.ExperimentalAutoDetectBinPacking = false;
  LLVMStyle.IndentCaseLabels = false;
  LLVMStyle.IndentFunctionDeclarationAfterType = false;
  LLVMStyle.IndentWidth = 2;
  LLVMStyle.TabWidth = 8;
  LLVMStyle.MaxEmptyLinesToKeep = 1;
  LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
  LLVMStyle.ObjCSpaceBeforeProtocolList = true;
  LLVMStyle.PointerBindsToType = false;
  LLVMStyle.SpacesBeforeTrailingComments = 1;
  LLVMStyle.Standard = FormatStyle::LS_Cpp03;
  LLVMStyle.UseTab = FormatStyle::UT_Never;
  LLVMStyle.SpacesInParentheses = false;
  LLVMStyle.SpaceInEmptyParentheses = false;
  LLVMStyle.SpacesInCStyleCastParentheses = false;
  LLVMStyle.SpaceAfterControlStatementKeyword = true;
  LLVMStyle.SpaceBeforeAssignmentOperators = true;
  LLVMStyle.ContinuationIndentWidth = 4;
  LLVMStyle.SpacesInAngles = false;

  setDefaultPenalties(LLVMStyle);
  LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
  LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;

  return LLVMStyle;
}

FormatStyle getGoogleStyle() {
  FormatStyle GoogleStyle;
  GoogleStyle.AccessModifierOffset = -1;
  GoogleStyle.AlignEscapedNewlinesLeft = true;
  GoogleStyle.AlignTrailingComments = true;
  GoogleStyle.AllowAllParametersOfDeclarationOnNextLine = true;
  GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
  GoogleStyle.AllowShortLoopsOnASingleLine = true;
  GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
  GoogleStyle.AlwaysBreakTemplateDeclarations = true;
  GoogleStyle.BinPackParameters = true;
  GoogleStyle.BreakBeforeBinaryOperators = false;
  GoogleStyle.BreakBeforeTernaryOperators = true;
  GoogleStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
  GoogleStyle.BreakConstructorInitializersBeforeComma = false;
  GoogleStyle.ColumnLimit = 80;
  GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
  GoogleStyle.ConstructorInitializerIndentWidth = 4;
  GoogleStyle.Cpp11BracedListStyle = true;
  GoogleStyle.DerivePointerBinding = true;
  GoogleStyle.ExperimentalAutoDetectBinPacking = false;
  GoogleStyle.IndentCaseLabels = true;
  GoogleStyle.IndentFunctionDeclarationAfterType = true;
  GoogleStyle.IndentWidth = 2;
  GoogleStyle.TabWidth = 8;
  GoogleStyle.MaxEmptyLinesToKeep = 1;
  GoogleStyle.NamespaceIndentation = FormatStyle::NI_None;
  GoogleStyle.ObjCSpaceBeforeProtocolList = false;
  GoogleStyle.PointerBindsToType = true;
  GoogleStyle.SpacesBeforeTrailingComments = 2;
  GoogleStyle.Standard = FormatStyle::LS_Auto;
  GoogleStyle.UseTab = FormatStyle::UT_Never;
  GoogleStyle.SpacesInParentheses = false;
  GoogleStyle.SpaceInEmptyParentheses = false;
  GoogleStyle.SpacesInCStyleCastParentheses = false;
  GoogleStyle.SpaceAfterControlStatementKeyword = true;
  GoogleStyle.SpaceBeforeAssignmentOperators = true;
  GoogleStyle.ContinuationIndentWidth = 4;
  GoogleStyle.SpacesInAngles = false;

  setDefaultPenalties(GoogleStyle);
  GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
  GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;

  return GoogleStyle;
}

FormatStyle getChromiumStyle() {
  FormatStyle ChromiumStyle = getGoogleStyle();
  ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
  ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
  ChromiumStyle.AllowShortLoopsOnASingleLine = false;
  ChromiumStyle.BinPackParameters = false;
  ChromiumStyle.DerivePointerBinding = false;
  ChromiumStyle.Standard = FormatStyle::LS_Cpp03;
  return ChromiumStyle;
}

FormatStyle getMozillaStyle() {
  FormatStyle MozillaStyle = getLLVMStyle();
  MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
  MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
  MozillaStyle.DerivePointerBinding = true;
  MozillaStyle.IndentCaseLabels = true;
  MozillaStyle.ObjCSpaceBeforeProtocolList = false;
  MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
  MozillaStyle.PointerBindsToType = true;
  return MozillaStyle;
}

FormatStyle getWebKitStyle() {
  FormatStyle Style = getLLVMStyle();
  Style.AccessModifierOffset = -4;
  Style.AlignTrailingComments = false;
  Style.BreakBeforeBinaryOperators = true;
  Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
  Style.BreakConstructorInitializersBeforeComma = true;
  Style.ColumnLimit = 0;
  Style.IndentWidth = 4;
  Style.NamespaceIndentation = FormatStyle::NI_Inner;
  Style.PointerBindsToType = true;
  return Style;
}

bool getPredefinedStyle(StringRef Name, FormatStyle *Style) {
  if (Name.equals_lower("llvm"))
    *Style = getLLVMStyle();
  else if (Name.equals_lower("chromium"))
    *Style = getChromiumStyle();
  else if (Name.equals_lower("mozilla"))
    *Style = getMozillaStyle();
  else if (Name.equals_lower("google"))
    *Style = getGoogleStyle();
  else if (Name.equals_lower("webkit"))
    *Style = getWebKitStyle();
  else
    return false;

  return true;
}

llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
  if (Text.trim().empty())
    return llvm::make_error_code(llvm::errc::invalid_argument);
  llvm::yaml::Input Input(Text);
  Input >> *Style;
  return Input.error();
}

std::string configurationAsText(const FormatStyle &Style) {
  std::string Text;
  llvm::raw_string_ostream Stream(Text);
  llvm::yaml::Output Output(Stream);
  // We use the same mapping method for input and output, so we need a non-const
  // reference here.
  FormatStyle NonConstStyle = Style;
  Output << NonConstStyle;
  return Stream.str();
}

namespace {

class NoColumnLimitFormatter {
public:
  NoColumnLimitFormatter(ContinuationIndenter *Indenter) : Indenter(Indenter) {}

  /// \brief Formats the line starting at \p State, simply keeping all of the
  /// input's line breaking decisions.
  void format(unsigned FirstIndent, const AnnotatedLine *Line) {
    LineState State =
        Indenter->getInitialState(FirstIndent, Line, /*DryRun=*/false);
    while (State.NextToken != NULL) {
      bool Newline =
          Indenter->mustBreak(State) ||
          (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
      Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
    }
  }

private:
  ContinuationIndenter *Indenter;
};

class LineJoiner {
public:
  LineJoiner(const FormatStyle &Style) : Style(Style) {}

  /// \brief Calculates how many lines can be merged into 1 starting at \p I.
  unsigned
  tryFitMultipleLinesInOne(unsigned Indent,
                           SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
                           SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
    // We can never merge stuff if there are trailing line comments.
    AnnotatedLine *TheLine = *I;
    if (TheLine->Last->Type == TT_LineComment)
      return 0;

    if (Indent > Style.ColumnLimit)
      return 0;

    unsigned Limit =
        Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
    // If we already exceed the column limit, we set 'Limit' to 0. The different
    // tryMerge..() functions can then decide whether to still do merging.
    Limit = TheLine->Last->TotalLength > Limit
                ? 0
                : Limit - TheLine->Last->TotalLength;

    if (I + 1 == E || I[1]->Type == LT_Invalid)
      return 0;

    if (TheLine->Last->is(tok::l_brace)) {
      return tryMergeSimpleBlock(I, E, Limit);
    } else if (Style.AllowShortIfStatementsOnASingleLine &&
               TheLine->First->is(tok::kw_if)) {
      return tryMergeSimpleControlStatement(I, E, Limit);
    } else if (Style.AllowShortLoopsOnASingleLine &&
               TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
      return tryMergeSimpleControlStatement(I, E, Limit);
    } else if (TheLine->InPPDirective && (TheLine->First->HasUnescapedNewline ||
                                          TheLine->First->IsFirst)) {
      return tryMergeSimplePPDirective(I, E, Limit);
    }
    return 0;
  }

private:
  unsigned
  tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
                            SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                            unsigned Limit) {
    if (Limit == 0)
      return 0;
    if (!I[1]->InPPDirective || I[1]->First->HasUnescapedNewline)
      return 0;
    if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    return 1;
  }

  unsigned tryMergeSimpleControlStatement(
      SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
      SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
    if (Limit == 0)
      return 0;
    if (Style.BreakBeforeBraces == FormatStyle::BS_Allman &&
        I[1]->First->is(tok::l_brace))
      return 0;
    if (I[1]->InPPDirective != (*I)->InPPDirective ||
        (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline))
      return 0;
    AnnotatedLine &Line = **I;
    if (Line.Last->isNot(tok::r_paren))
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
                                   tok::kw_while) ||
        I[1]->First->Type == TT_LineComment)
      return 0;
    // Only inline simple if's (no nested if or else).
    if (I + 2 != E && Line.First->is(tok::kw_if) &&
        I[2]->First->is(tok::kw_else))
      return 0;
    return 1;
  }

  unsigned
  tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator &I,
                      SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                      unsigned Limit) {
    // No merging if the brace already is on the next line.
    if (Style.BreakBeforeBraces != FormatStyle::BS_Attach)
      return 0;

    // First, check that the current line allows merging. This is the case if
    // we're not in a control flow statement and the last token is an opening
    // brace.
    AnnotatedLine &Line = **I;
    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
                            tok::kw_else, tok::kw_try, tok::kw_catch,
                            tok::kw_for,
                            // This gets rid of all ObjC @@ keywords and methods.
                            tok::at, tok::minus, tok::plus))
      return 0;

    FormatToken *Tok = I[1]->First;
    if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
        (Tok->getNextNonComment() == NULL ||
         Tok->getNextNonComment()->is(tok::semi))) {
      // We merge empty blocks even if the line exceeds the column limit.
      Tok->SpacesRequiredBefore = 0;
      Tok->CanBreakBefore = true;
      return 1;
    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
      // Check that we still have three lines and they fit into the limit.
      if (I + 2 == E || I[2]->Type == LT_Invalid)
        return 0;

      if (!nextTwoLinesFitInto(I, Limit))
        return 0;

      // Second, check that the next line does not contain any braces - if it
      // does, readability declines when putting it into a single line.
      if (I[1]->Last->Type == TT_LineComment || Tok->MustBreakBefore)
        return 0;
      do {
        if (Tok->isOneOf(tok::l_brace, tok::r_brace))
          return 0;
        Tok = Tok->Next;
      } while (Tok != NULL);

      // Last, check that the third line contains a single closing brace.
      Tok = I[2]->First;
      if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||
          Tok->MustBreakBefore)
        return 0;

      return 2;
    }
    return 0;
  }

  bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                           unsigned Limit) {
    return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
  }

  const FormatStyle &Style;
};

class UnwrappedLineFormatter {
public:
  UnwrappedLineFormatter(SourceManager &SourceMgr,
                         SmallVectorImpl<CharSourceRange> &Ranges,
                         ContinuationIndenter *Indenter,
                         WhitespaceManager *Whitespaces,
                         const FormatStyle &Style)
      : SourceMgr(SourceMgr), Ranges(Ranges), Indenter(Indenter),
        Whitespaces(Whitespaces), Style(Style), Joiner(Style) {}

  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
                  int AdditionalIndent = 0) {
    assert(!Lines.empty());
    unsigned Penalty = 0;
    std::vector<int> IndentForLevel;
    for (unsigned i = 0, e = Lines[0]->Level; i != e; ++i)
      IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
    bool PreviousLineWasTouched = false;
    const AnnotatedLine *PreviousLine = NULL;
    bool FormatPPDirective = false;
    for (SmallVectorImpl<AnnotatedLine *>::const_iterator I = Lines.begin(),
                                                          E = Lines.end();
         I != E; ++I) {
      const AnnotatedLine &TheLine = **I;
      const FormatToken *FirstTok = TheLine.First;
      int Offset = getIndentOffset(*FirstTok);

      // Check whether this line is part of a formatted preprocessor directive.
      if (FirstTok->HasUnescapedNewline)
        FormatPPDirective = false;
      if (!FormatPPDirective && TheLine.InPPDirective &&
          (touchesLine(TheLine) || touchesPPDirective(I + 1, E)))
        FormatPPDirective = true;

      // Determine indent and try to merge multiple unwrapped lines.
      while (IndentForLevel.size() <= TheLine.Level)
        IndentForLevel.push_back(-1);
      IndentForLevel.resize(TheLine.Level + 1);
      unsigned Indent = getIndent(IndentForLevel, TheLine.Level);
      if (static_cast<int>(Indent) + Offset >= 0)
        Indent += Offset;
      unsigned MergedLines = Joiner.tryFitMultipleLinesInOne(Indent, I, E);
      if (!DryRun) {
        for (unsigned i = 0; i < MergedLines; ++i) {
          join(*I[i], *I[i + 1]);
        }
      }
      I += MergedLines;

      bool WasMoved = PreviousLineWasTouched && FirstTok->NewlinesBefore == 0;
      if (TheLine.First->is(tok::eof)) {
        if (PreviousLineWasTouched && !DryRun) {
          unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u);
          Whitespaces->replaceWhitespace(*TheLine.First, Newlines,
                                         /*IndentLevel=*/0, /*Spaces=*/0,
                                         /*TargetColumn=*/0);
        }
      } else if (TheLine.Type != LT_Invalid &&
                 (WasMoved || FormatPPDirective || touchesLine(TheLine))) {
        unsigned LevelIndent =
            getIndent(IndentForLevel, TheLine.Level);
        if (FirstTok->WhitespaceRange.isValid()) {
          if (!DryRun)
            formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level,
                             Indent, TheLine.InPPDirective);
        } else {
          Indent = LevelIndent = FirstTok->OriginalColumn;
        }

        // If everything fits on a single line, just put it there.
        unsigned ColumnLimit = Style.ColumnLimit;
        if (I + 1 != E) {
          AnnotatedLine *NextLine = I[1];
          if (NextLine->InPPDirective && !NextLine->First->HasUnescapedNewline)
            ColumnLimit = getColumnLimit(TheLine.InPPDirective);
        }

        if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {
          LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);
          while (State.NextToken != NULL)
            Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
        } else if (Style.ColumnLimit == 0) {
          NoColumnLimitFormatter Formatter(Indenter);
          if (!DryRun)
            Formatter.format(Indent, &TheLine);
        } else {
          Penalty += format(TheLine, Indent, DryRun);
        }

        IndentForLevel[TheLine.Level] = LevelIndent;
        PreviousLineWasTouched = true;
      } else {
        // Format the first token if necessary, and notify the WhitespaceManager
        // about the unchanged whitespace.
        for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
          if (Tok == TheLine.First &&
              (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
            unsigned LevelIndent = Tok->OriginalColumn;
            if (!DryRun) {
              // Remove trailing whitespace of the previous line if it was
              // touched.
              if (PreviousLineWasTouched || touchesEmptyLineBefore(TheLine)) {
                formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent,
                                 TheLine.InPPDirective);
              } else {
                Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
              }
            }

            if (static_cast<int>(LevelIndent) - Offset >= 0)
              LevelIndent -= Offset;
            if (Tok->isNot(tok::comment))
              IndentForLevel[TheLine.Level] = LevelIndent;
          } else if (!DryRun) {
            Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
          }
        }
        // If we did not reformat this unwrapped line, the column at the end of
        // the last token is unchanged - thus, we can calculate the end of the
        // last token.
        PreviousLineWasTouched = false;
      }
      if (!DryRun) {
        for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
          Tok->Finalized = true;
        }
      }
      PreviousLine = *I;
    }
    return Penalty;
  }

private:
  /// \brief Formats an \c AnnotatedLine and returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned format(const AnnotatedLine &Line, unsigned FirstIndent,
                  bool DryRun) {
    LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);

    // If the ObjC method declaration does not fit on a line, we should format
    // it with one arg per line.
    if (State.Line->Type == LT_ObjCMethodDecl)
      State.Stack.back().BreakBeforeParameter = true;

    // Find best solution in solution space.
    return analyzeSolutionSpace(State, DryRun);
  }

  /// \brief An edge in the solution space from \c Previous->State to \c State,
  /// inserting a newline dependent on the \c NewLine.
  struct StateNode {
    StateNode(const LineState &State, bool NewLine, StateNode *Previous)
        : State(State), NewLine(NewLine), Previous(Previous) {}
    LineState State;
    bool NewLine;
    StateNode *Previous;
  };

  /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.
  ///
  /// In case of equal penalties, we want to prefer states that were inserted
  /// first. During state generation we make sure that we insert states first
  /// that break the line as late as possible.
  typedef std::pair<unsigned, unsigned> OrderedPenalty;

  /// \brief An item in the prioritized BFS search queue. The \c StateNode's
  /// \c State has the given \c OrderedPenalty.
  typedef std::pair<OrderedPenalty, StateNode *> QueueItem;

  /// \brief The BFS queue type.
  typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
                              std::greater<QueueItem> > QueueType;

  /// \brief Get the offset of the line relatively to the level.
  ///
  /// For example, 'public:' labels in classes are offset by 1 or 2
  /// characters to the left from their level.
  int getIndentOffset(const FormatToken &RootToken) {
    if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())
      return Style.AccessModifierOffset;
    return 0;
  }

  /// \brief Add a new line and the required indent before the first Token
  /// of the \c UnwrappedLine if there was no structural parsing error.
  void formatFirstToken(FormatToken &RootToken,
                        const AnnotatedLine *PreviousLine, unsigned IndentLevel,
                        unsigned Indent, bool InPPDirective) {
    unsigned Newlines =
        std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
    // Remove empty lines before "}" where applicable.
    if (RootToken.is(tok::r_brace) &&
        (!RootToken.Next ||
         (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))
      Newlines = std::min(Newlines, 1u);
    if (Newlines == 0 && !RootToken.IsFirst)
      Newlines = 1;

    // Insert extra new line before access specifiers.
    if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
        RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)
      ++Newlines;

    // Remove empty lines after access specifiers.
    if (PreviousLine && PreviousLine->First->isAccessSpecifier())
      Newlines = std::min(1u, Newlines);

    Whitespaces->replaceWhitespace(
        RootToken, Newlines, IndentLevel, Indent, Indent,
        InPPDirective && !RootToken.HasUnescapedNewline);
  }

  /// \brief Get the indent of \p Level from \p IndentForLevel.
  ///
  /// \p IndentForLevel must contain the indent for the level \c l
  /// at \p IndentForLevel[l], or a value < 0 if the indent for
  /// that level is unknown.
  unsigned getIndent(const std::vector<int> IndentForLevel, unsigned Level) {
    if (IndentForLevel[Level] != -1)
      return IndentForLevel[Level];
    if (Level == 0)
      return 0;
    return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
  }

  void join(AnnotatedLine &A, const AnnotatedLine &B) {
    assert(!A.Last->Next);
    assert(!B.First->Previous);
    A.Last->Next = B.First;
    B.First->Previous = A.Last;
    B.First->CanBreakBefore = true;
    unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
    for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
      Tok->TotalLength += LengthA;
      A.Last = Tok;
    }
  }

  unsigned getColumnLimit(bool InPPDirective) const {
    // In preprocessor directives reserve two chars for trailing " \"
    return Style.ColumnLimit - (InPPDirective ? 2 : 0);
  }

  bool touchesRanges(const CharSourceRange &Range) {
    for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
                                                          E = Ranges.end();
         I != E; ++I) {
      if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
          !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
        return true;
    }
    return false;
  }

  bool touchesLine(const AnnotatedLine &TheLine) {
    const FormatToken *First = TheLine.First;
    const FormatToken *Last = TheLine.Last;
    CharSourceRange LineRange = CharSourceRange::getCharRange(
        First->WhitespaceRange.getBegin().getLocWithOffset(
            First->LastNewlineOffset),
        Last->getStartOfNonWhitespace().getLocWithOffset(
            Last->TokenText.size() - 1));
    return touchesRanges(LineRange);
  }

  bool touchesPPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                          SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
    for (; I != E; ++I) {
      if ((*I)->First->HasUnescapedNewline)
        return false;
      if (touchesLine(**I))
        return true;
    }
    return false;
  }

  bool touchesEmptyLineBefore(const AnnotatedLine &TheLine) {
    const FormatToken *First = TheLine.First;
    CharSourceRange LineRange = CharSourceRange::getCharRange(
        First->WhitespaceRange.getBegin(),
        First->WhitespaceRange.getBegin().getLocWithOffset(
            First->LastNewlineOffset));
    return touchesRanges(LineRange);
  }

  /// \brief Analyze the entire solution space starting from \p InitialState.
  ///
  /// This implements a variant of Dijkstra's algorithm on the graph that spans
  /// the solution space (\c LineStates are the nodes). The algorithm tries to
  /// find the shortest path (the one with lowest penalty) from \p InitialState
  /// to a state where all tokens are placed. Returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false) {
    std::set<LineState> Seen;

    // Increasing count of \c StateNode items we have created. This is used to
    // create a deterministic order independent of the container.
    unsigned Count = 0;
    QueueType Queue;

    // Insert start element into queue.
    StateNode *Node =
        new (Allocator.Allocate()) StateNode(InitialState, false, NULL);
    Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
    ++Count;

    unsigned Penalty = 0;

    // While not empty, take first element and follow edges.
    while (!Queue.empty()) {
      Penalty = Queue.top().first.first;
      StateNode *Node = Queue.top().second;
      if (Node->State.NextToken == NULL) {
        DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
        break;
      }
      Queue.pop();

      // Cut off the analysis of certain solutions if the analysis gets too
      // complex. See description of IgnoreStackForComparison.
      if (Count > 10000)
        Node->State.IgnoreStackForComparison = true;

      if (!Seen.insert(Node->State).second)
        // State already examined with lower penalty.
        continue;

      FormatDecision LastFormat = Node->State.NextToken->Decision;
      if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
      if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
    }

    if (Queue.empty()) {
      // We were unable to find a solution, do nothing.
      // FIXME: Add diagnostic?
      DEBUG(llvm::dbgs() << "Could not find a solution.\n");
      return 0;
    }

    // Reconstruct the solution.
    if (!DryRun)
      reconstructPath(InitialState, Queue.top().second);

    DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
    DEBUG(llvm::dbgs() << "---\n");

    return Penalty;
  }

  void reconstructPath(LineState &State, StateNode *Current) {
    std::deque<StateNode *> Path;
    // We do not need a break before the initial token.
    while (Current->Previous) {
      Path.push_front(Current);
      Current = Current->Previous;
    }
    for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
         I != E; ++I) {
      unsigned Penalty = 0;
      formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
      Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);

      DEBUG({
        if ((*I)->NewLine) {
          llvm::dbgs() << "Penalty for placing "
                       << (*I)->Previous->State.NextToken->Tok.getName() << ": "
                       << Penalty << "\n";
        }
      });
    }
  }

  /// \brief Add the following state to the analysis queue \c Queue.
  ///
  /// Assume the current state is \p PreviousNode and has been reached with a
  /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
                           bool NewLine, unsigned *Count, QueueType *Queue) {
    if (NewLine && !Indenter->canBreak(PreviousNode->State))
      return;
    if (!NewLine && Indenter->mustBreak(PreviousNode->State))
      return;

    StateNode *Node = new (Allocator.Allocate())
        StateNode(PreviousNode->State, NewLine, PreviousNode);
    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
      return;

    Penalty += Indenter->addTokenToState(Node->State, NewLine, true);

    Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
    ++(*Count);
  }

  /// \brief If the \p State's next token is an r_brace closing a nested block,
  /// format the nested block before it.
  ///
  /// Returns \c true if all children could be placed successfully and adapts
  /// \p Penalty as well as \p State. If \p DryRun is false, also directly
  /// creates changes using \c Whitespaces.
  ///
  /// The crucial idea here is that children always get formatted upon
  /// encountering the closing brace right after the nested block. Now, if we
  /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
  /// \c false), the entire block has to be kept on the same line (which is only
  /// possible if it fits on the line, only contains a single statement, etc.
  ///
  /// If \p NewLine is true, we format the nested block on separate lines, i.e.
  /// break after the "{", format all lines with correct indentation and the put
  /// the closing "}" on yet another new line.
  ///
  /// This enables us to keep the simple structure of the
  /// \c UnwrappedLineFormatter, where we only have two options for each token:
  /// break or don't break.
  bool formatChildren(LineState &State, bool NewLine, bool DryRun,
                      unsigned &Penalty) {
    FormatToken &Previous = *State.NextToken->Previous;
    const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
    if (!LBrace || LBrace->isNot(tok::l_brace) ||
        LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)
      // The previous token does not open a block. Nothing to do. We don't
      // assert so that we can simply call this function for all tokens.
      return true;

    if (NewLine) {
      int AdditionalIndent = State.Stack.back().Indent -
                             Previous.Children[0]->Level * Style.IndentWidth;
      Penalty += format(Previous.Children, DryRun, AdditionalIndent);
      return true;
    }

    // Cannot merge multiple statements into a single line.
    if (Previous.Children.size() > 1)
      return false; 

    // We can't put the closing "}" on a line with a trailing comment.
    if (Previous.Children[0]->Last->isTrailingComment())
      return false;

    if (!DryRun) {
      Whitespaces->replaceWhitespace(
          *Previous.Children[0]->First,
          /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,
          /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
    }
    Penalty += format(*Previous.Children[0], State.Column + 1, DryRun);

    State.Column += 1 + Previous.Children[0]->Last->TotalLength;
    return true;
  }

  SourceManager &SourceMgr;
  SmallVectorImpl<CharSourceRange> &Ranges;
  ContinuationIndenter *Indenter;
  WhitespaceManager *Whitespaces;
  FormatStyle Style;
  LineJoiner Joiner;

  llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
};

class FormatTokenLexer {
public:
  FormatTokenLexer(Lexer &Lex, SourceManager &SourceMgr, FormatStyle &Style,
                   encoding::Encoding Encoding)
      : FormatTok(NULL), IsFirstToken(true), GreaterStashed(false), Column(0),
        TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr), Style(Style),
        IdentTable(getFormattingLangOpts()), Encoding(Encoding) {
    Lex.SetKeepWhitespaceMode(true);
  }

  ArrayRef<FormatToken *> lex() {
    assert(Tokens.empty());
    do {
      Tokens.push_back(getNextToken());
      maybeJoinPreviousTokens();
    } while (Tokens.back()->Tok.isNot(tok::eof));
    return Tokens;
  }

  IdentifierTable &getIdentTable() { return IdentTable; }

private:
  void maybeJoinPreviousTokens() {
    if (Tokens.size() < 4)
      return;
    FormatToken *Last = Tokens.back();
    if (!Last->is(tok::r_paren))
      return;

    FormatToken *String = Tokens[Tokens.size() - 2];
    if (!String->is(tok::string_literal) || String->IsMultiline)
      return;

    if (!Tokens[Tokens.size() - 3]->is(tok::l_paren))
      return;

    FormatToken *Macro = Tokens[Tokens.size() - 4];
    if (Macro->TokenText != "_T")
      return;

    const char *Start = Macro->TokenText.data();
    const char *End = Last->TokenText.data() + Last->TokenText.size();
    String->TokenText = StringRef(Start, End - Start);
    String->IsFirst = Macro->IsFirst;
    String->LastNewlineOffset = Macro->LastNewlineOffset;
    String->WhitespaceRange = Macro->WhitespaceRange;
    String->OriginalColumn = Macro->OriginalColumn;
    String->ColumnWidth = encoding::columnWidthWithTabs(
        String->TokenText, String->OriginalColumn, Style.TabWidth, Encoding);

    Tokens.pop_back();
    Tokens.pop_back();
    Tokens.pop_back();
    Tokens.back() = String;
  }

  FormatToken *getNextToken() {
    if (GreaterStashed) {
      // Create a synthesized second '>' token.
      // FIXME: Increment Column and set OriginalColumn.
      Token Greater = FormatTok->Tok;
      FormatTok = new (Allocator.Allocate()) FormatToken;
      FormatTok->Tok = Greater;
      SourceLocation GreaterLocation =
          FormatTok->Tok.getLocation().getLocWithOffset(1);
      FormatTok->WhitespaceRange =
          SourceRange(GreaterLocation, GreaterLocation);
      FormatTok->TokenText = ">";
      FormatTok->ColumnWidth = 1;
      GreaterStashed = false;
      return FormatTok;
    }

    FormatTok = new (Allocator.Allocate()) FormatToken;
    readRawToken(*FormatTok);
    SourceLocation WhitespaceStart =
        FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace);
    FormatTok->IsFirst = IsFirstToken;
    IsFirstToken = false;

    // Consume and record whitespace until we find a significant token.
    unsigned WhitespaceLength = TrailingWhitespace;
    while (FormatTok->Tok.is(tok::unknown)) {
      for (int i = 0, e = FormatTok->TokenText.size(); i != e; ++i) {
        switch (FormatTok->TokenText[i]) {
        case '\n':
          ++FormatTok->NewlinesBefore;
          // FIXME: This is technically incorrect, as it could also
          // be a literal backslash at the end of the line.
          if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' &&
                         (FormatTok->TokenText[i - 1] != '\r' || i == 1 ||
                          FormatTok->TokenText[i - 2] != '\\')))
            FormatTok->HasUnescapedNewline = true;
          FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
          Column = 0;
          break;
        case '\r':
        case '\f':
        case '\v':
          Column = 0;
          break;
        case ' ':
          ++Column;
          break;
        case '\t':
          Column += Style.TabWidth - Column % Style.TabWidth;
          break;
        case '\\':
          ++Column;
          if (i + 1 == e || (FormatTok->TokenText[i + 1] != '\r' &&
                             FormatTok->TokenText[i + 1] != '\n'))
            FormatTok->Type = TT_ImplicitStringLiteral;
          break;
        default:
          FormatTok->Type = TT_ImplicitStringLiteral;
          ++Column;
          break;
        }
      }

      if (FormatTok->Type == TT_ImplicitStringLiteral)
        break;
      WhitespaceLength += FormatTok->Tok.getLength();

      readRawToken(*FormatTok);
    }

    // In case the token starts with escaped newlines, we want to
    // take them into account as whitespace - this pattern is quite frequent
    // in macro definitions.
    // FIXME: Add a more explicit test.
    while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' &&
           FormatTok->TokenText[1] == '\n') {
      // FIXME: ++FormatTok->NewlinesBefore is missing...
      WhitespaceLength += 2;
      Column = 0;
      FormatTok->TokenText = FormatTok->TokenText.substr(2);
    }

    FormatTok->WhitespaceRange = SourceRange(
        WhitespaceStart, WhitespaceStart.getLocWithOffset(WhitespaceLength));

    FormatTok->OriginalColumn = Column;

    TrailingWhitespace = 0;
    if (FormatTok->Tok.is(tok::comment)) {
      // FIXME: Add the trimmed whitespace to Column.
      StringRef UntrimmedText = FormatTok->TokenText;
      FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f");
      TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size();
    } else if (FormatTok->Tok.is(tok::raw_identifier)) {
      IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText);
      FormatTok->Tok.setIdentifierInfo(&Info);
      FormatTok->Tok.setKind(Info.getTokenID());
    } else if (FormatTok->Tok.is(tok::greatergreater)) {
      FormatTok->Tok.setKind(tok::greater);
      FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
      GreaterStashed = true;
    }

    // Now FormatTok is the next non-whitespace token.

    StringRef Text = FormatTok->TokenText;
    size_t FirstNewlinePos = Text.find('\n');
    if (FirstNewlinePos == StringRef::npos) {
      // FIXME: ColumnWidth actually depends on the start column, we need to
      // take this into account when the token is moved.
      FormatTok->ColumnWidth =
          encoding::columnWidthWithTabs(Text, Column, Style.TabWidth, Encoding);
      Column += FormatTok->ColumnWidth;
    } else {
      FormatTok->IsMultiline = true;
      // FIXME: ColumnWidth actually depends on the start column, we need to
      // take this into account when the token is moved.
      FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
          Text.substr(0, FirstNewlinePos), Column, Style.TabWidth, Encoding);

      // The last line of the token always starts in column 0.
      // Thus, the length can be precomputed even in the presence of tabs.
      FormatTok->LastLineColumnWidth = encoding::columnWidthWithTabs(
          Text.substr(Text.find_last_of('\n') + 1), 0, Style.TabWidth,
          Encoding);
      Column = FormatTok->LastLineColumnWidth;
    }

    return FormatTok;
  }

  FormatToken *FormatTok;
  bool IsFirstToken;
  bool GreaterStashed;
  unsigned Column;
  unsigned TrailingWhitespace;
  Lexer &Lex;
  SourceManager &SourceMgr;
  FormatStyle &Style;
  IdentifierTable IdentTable;
  encoding::Encoding Encoding;
  llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
  SmallVector<FormatToken *, 16> Tokens;

  void readRawToken(FormatToken &Tok) {
    Lex.LexFromRawLexer(Tok.Tok);
    Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
                              Tok.Tok.getLength());
    // For formatting, treat unterminated string literals like normal string
    // literals.
    if (Tok.is(tok::unknown) && !Tok.TokenText.empty() &&
        Tok.TokenText[0] == '"') {
      Tok.Tok.setKind(tok::string_literal);
      Tok.IsUnterminatedLiteral = true;
    }
  }
};

class Formatter : public UnwrappedLineConsumer {
public:
  Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
            const std::vector<CharSourceRange> &Ranges)
      : Style(Style), Lex(Lex), SourceMgr(SourceMgr),
        Whitespaces(SourceMgr, Style, inputUsesCRLF(Lex.getBuffer())),
        Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1),
        Encoding(encoding::detectEncoding(Lex.getBuffer())) {
    DEBUG(llvm::dbgs() << "File encoding: "
                       << (Encoding == encoding::Encoding_UTF8 ? "UTF8"
                                                               : "unknown")
                       << "\n");
  }

  tooling::Replacements format() {
    tooling::Replacements Result;
    FormatTokenLexer Tokens(Lex, SourceMgr, Style, Encoding);

    UnwrappedLineParser Parser(Style, Tokens.lex(), *this);
    bool StructuralError = Parser.parse();
    assert(UnwrappedLines.rbegin()->empty());
    for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE;
         ++Run) {
      DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
      SmallVector<AnnotatedLine *, 16> AnnotatedLines;
      for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) {
        AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i]));
      }
      tooling::Replacements RunResult =
          format(AnnotatedLines, StructuralError, Tokens);
      DEBUG({
        llvm::dbgs() << "Replacements for run " << Run << ":\n";
        for (tooling::Replacements::iterator I = RunResult.begin(),
                                             E = RunResult.end();
             I != E; ++I) {
          llvm::dbgs() << I->toString() << "\n";
        }
      });
      for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
        delete AnnotatedLines[i];
      }
      Result.insert(RunResult.begin(), RunResult.end());
      Whitespaces.reset();
    }
    return Result;
  }

  tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                               bool StructuralError, FormatTokenLexer &Tokens) {
    TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      Annotator.annotate(*AnnotatedLines[i]);
    }
    deriveLocalStyle(AnnotatedLines);
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
    }

    Annotator.setCommentLineLevels(AnnotatedLines);
    ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,
                                  BinPackInconclusiveFunctions);
    UnwrappedLineFormatter Formatter(SourceMgr, Ranges, &Indenter, &Whitespaces,
                                     Style);
    Formatter.format(AnnotatedLines, /*DryRun=*/false);
    return Whitespaces.generateReplacements();
  }

private:
  static bool inputUsesCRLF(StringRef Text) {
    return Text.count('\r') * 2 > Text.count('\n');
  }

  void
  deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
    unsigned CountBoundToVariable = 0;
    unsigned CountBoundToType = 0;
    bool HasCpp03IncompatibleFormat = false;
    bool HasBinPackedFunction = false;
    bool HasOnePerLineFunction = false;
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      if (!AnnotatedLines[i]->First->Next)
        continue;
      FormatToken *Tok = AnnotatedLines[i]->First->Next;
      while (Tok->Next) {
        if (Tok->Type == TT_PointerOrReference) {
          bool SpacesBefore =
              Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
          bool SpacesAfter = Tok->Next->WhitespaceRange.getBegin() !=
                             Tok->Next->WhitespaceRange.getEnd();
          if (SpacesBefore && !SpacesAfter)
            ++CountBoundToVariable;
          else if (!SpacesBefore && SpacesAfter)
            ++CountBoundToType;
        }

        if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
          if (Tok->is(tok::coloncolon) &&
              Tok->Previous->Type == TT_TemplateOpener)
            HasCpp03IncompatibleFormat = true;
          if (Tok->Type == TT_TemplateCloser &&
              Tok->Previous->Type == TT_TemplateCloser)
            HasCpp03IncompatibleFormat = true;
        }

        if (Tok->PackingKind == PPK_BinPacked)
          HasBinPackedFunction = true;
        if (Tok->PackingKind == PPK_OnePerLine)
          HasOnePerLineFunction = true;

        Tok = Tok->Next;
      }
    }
    if (Style.DerivePointerBinding) {
      if (CountBoundToType > CountBoundToVariable)
        Style.PointerBindsToType = true;
      else if (CountBoundToType < CountBoundToVariable)
        Style.PointerBindsToType = false;
    }
    if (Style.Standard == FormatStyle::LS_Auto) {
      Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11
                                                  : FormatStyle::LS_Cpp03;
    }
    BinPackInconclusiveFunctions =
        HasBinPackedFunction || !HasOnePerLineFunction;
  }

  virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {
    assert(!UnwrappedLines.empty());
    UnwrappedLines.back().push_back(TheLine);
  }

  virtual void finishRun() {
    UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>());
  }

  FormatStyle Style;
  Lexer &Lex;
  SourceManager &SourceMgr;
  WhitespaceManager Whitespaces;
  SmallVector<CharSourceRange, 8> Ranges;
  SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines;

  encoding::Encoding Encoding;
  bool BinPackInconclusiveFunctions;
};

} // end anonymous namespace

tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
                               SourceManager &SourceMgr,
                               std::vector<CharSourceRange> Ranges) {
  Formatter formatter(Style, Lex, SourceMgr, Ranges);
  return formatter.format();
}

tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               std::vector<tooling::Range> Ranges,
                               StringRef FileName) {
  FileManager Files((FileSystemOptions()));
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
      new DiagnosticOptions);
  SourceManager SourceMgr(Diagnostics, Files);
  llvm::MemoryBuffer *Buf = llvm::MemoryBuffer::getMemBuffer(Code, FileName);
  const clang::FileEntry *Entry =
      Files.getVirtualFile(FileName, Buf->getBufferSize(), 0);
  SourceMgr.overrideFileContents(Entry, Buf);
  FileID ID =
      SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
  Lexer Lex(ID, SourceMgr.getBuffer(ID), SourceMgr,
            getFormattingLangOpts(Style.Standard));
  SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);
  std::vector<CharSourceRange> CharRanges;
  for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
    SourceLocation Start = StartOfFile.getLocWithOffset(Ranges[i].getOffset());
    SourceLocation End = Start.getLocWithOffset(Ranges[i].getLength());
    CharRanges.push_back(CharSourceRange::getCharRange(Start, End));
  }
  return reformat(Style, Lex, SourceMgr, CharRanges);
}

LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard) {
  LangOptions LangOpts;
  LangOpts.CPlusPlus = 1;
  LangOpts.CPlusPlus11 = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.LineComment = 1;
  LangOpts.Bool = 1;
  LangOpts.ObjC1 = 1;
  LangOpts.ObjC2 = 1;
  return LangOpts;
}

const char *StyleOptionHelpDescription =
    "Coding style, currently supports:\n"
    "  LLVM, Google, Chromium, Mozilla, WebKit.\n"
    "Use -style=file to load style configuration from\n"
    ".clang-format file located in one of the parent\n"
    "directories of the source file (or current\n"
    "directory for stdin).\n"
    "Use -style=\"{key: value, ...}\" to set specific\n"
    "parameters, e.g.:\n"
    "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";

FormatStyle getStyle(StringRef StyleName, StringRef FileName) {
  // Fallback style in case the rest of this function can't determine a style.
  StringRef FallbackStyle = "LLVM";
  FormatStyle Style;
  getPredefinedStyle(FallbackStyle, &Style);

  if (StyleName.startswith("{")) {
    // Parse YAML/JSON style from the command line.
    if (llvm::error_code ec = parseConfiguration(StyleName, &Style)) {
      llvm::errs() << "Error parsing -style: " << ec.message() << ", using "
                   << FallbackStyle << " style\n";
    }
    return Style;
  }

  if (!StyleName.equals_lower("file")) {
    if (!getPredefinedStyle(StyleName, &Style))
      llvm::errs() << "Invalid value for -style, using " << FallbackStyle
                   << " style\n";
    return Style;
  }

  SmallString<128> Path(FileName);
  llvm::sys::fs::make_absolute(Path);
  for (StringRef Directory = Path; !Directory.empty();
       Directory = llvm::sys::path::parent_path(Directory)) {
    if (!llvm::sys::fs::is_directory(Directory))
      continue;
    SmallString<128> ConfigFile(Directory);

    llvm::sys::path::append(ConfigFile, ".clang-format");
    DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
    bool IsFile = false;
    // Ignore errors from is_regular_file: we only need to know if we can read
    // the file or not.
    llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);

    if (!IsFile) {
      // Try _clang-format too, since dotfiles are not commonly used on Windows.
      ConfigFile = Directory;
      llvm::sys::path::append(ConfigFile, "_clang-format");
      DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
      llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
    }

    if (IsFile) {
      OwningPtr<llvm::MemoryBuffer> Text;
      if (llvm::error_code ec =
              llvm::MemoryBuffer::getFile(ConfigFile.c_str(), Text)) {
        llvm::errs() << ec.message() << "\n";
        continue;
      }
      if (llvm::error_code ec = parseConfiguration(Text->getBuffer(), &Style)) {
        llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()
                     << "\n";
        continue;
      }
      DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
      return Style;
    }
  }
  llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle
               << " style\n";
  return Style;
}

} // namespace format
} // namespace clang
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import clang 3.5svn r198450.
@
text
@a33 2
using clang::format::FormatStyle;

d36 9
a44 4
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
  static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
    IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
    IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
d48 10
a57 27
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
  static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
    IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
  static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
    IO.enumCase(Value, "Never", FormatStyle::UT_Never);
    IO.enumCase(Value, "false", FormatStyle::UT_Never);
    IO.enumCase(Value, "Always", FormatStyle::UT_Always);
    IO.enumCase(Value, "true", FormatStyle::UT_Always);
    IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
  static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
    IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
    IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
    IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
    IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
    IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
d62 7
a68 6
struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
  static void enumeration(IO &IO,
                          FormatStyle::NamespaceIndentationKind &Value) {
    IO.enumCase(Value, "None", FormatStyle::NI_None);
    IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
    IO.enumCase(Value, "All", FormatStyle::NI_All);
d73 8
a80 11
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
  static void enumeration(IO &IO,
                          FormatStyle::SpaceBeforeParensOptions &Value) {
    IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
    IO.enumCase(Value, "ControlStatements",
                FormatStyle::SBPO_ControlStatements);
    IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
    IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
d84 2
a85 5
template <> struct MappingTraits<FormatStyle> {
  static void mapping(IO &IO, FormatStyle &Style) {
    // When reading, read the language first, we need it for getPredefinedStyle.
    IO.mapOptional("Language", Style.Language);

d88 1
a88 1
                                  "Mozilla", "WebKit", "GNU" };
d92 2
a93 2
        FormatStyle PredefinedStyle;
        if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
d102 2
a103 5
      if (!BasedOnStyle.empty()) {
        FormatStyle::LanguageKind OldLanguage = Style.Language;
        FormatStyle::LanguageKind Language =
            ((FormatStyle *)IO.getContext())->Language;
        if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
a106 2
        Style.Language = OldLanguage;
      }
a119 2
    IO.mapOptional("AllowShortFunctionsOnASingleLine",
                   Style.AllowShortFunctionsOnASingleLine);
d167 2
a171 34
    IO.mapOptional("CommentPragmas", Style.CommentPragmas);

    // For backward compatibility.
    if (!IO.outputting()) {
      IO.mapOptional("SpaceAfterControlStatementKeyword",
                     Style.SpaceBeforeParens);
    }
    IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
  }
};

// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
// If the first element has no Language specified, it will be treated as the
// default one for the following elements.
template <> struct DocumentListTraits<std::vector<FormatStyle> > {
  static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
    return Seq.size();
  }
  static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
                              size_t Index) {
    if (Index >= Seq.size()) {
      assert(Index == Seq.size());
      FormatStyle Template;
      if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) {
        Template = Seq[0];
      } else {
        Template = *((const FormatStyle*)IO.getContext());
        Template.Language = FormatStyle::LK_None;
      }
      Seq.resize(Index + 1, Template);
    }
    return Seq[Index];
d180 7
a188 1
  LLVMStyle.Language = FormatStyle::LK_Cpp;
a192 1
  LLVMStyle.AllowShortFunctionsOnASingleLine = true;
d222 1
a222 1
  LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
a225 1
  LLVMStyle.CommentPragmas = "^ IWYU pragma:";
d227 1
a227 4
  LLVMStyle.PenaltyBreakComment = 300;
  LLVMStyle.PenaltyBreakFirstLessLess = 120;
  LLVMStyle.PenaltyBreakString = 1000;
  LLVMStyle.PenaltyExcessCharacter = 1000000;
d235 1
a235 1
  FormatStyle GoogleStyle = getLLVMStyle();
d238 2
d244 6
d251 1
d254 1
d257 4
d265 8
d274 1
a280 10
FormatStyle getGoogleJSStyle() {
  FormatStyle GoogleJSStyle = getGoogleStyle();
  GoogleJSStyle.Language = FormatStyle::LK_JavaScript;
  GoogleJSStyle.BreakBeforeTernaryOperators = false;
  // FIXME: Currently unimplemented:
  // var arr = [1, 2, 3];  // No space after [ or before ].
  // var obj = {a: 1, b: 2, c: 3};  // No space after ':'.
  return GoogleJSStyle;
}

d318 2
a319 13
FormatStyle getGNUStyle() {
  FormatStyle Style = getLLVMStyle();
  Style.BreakBeforeBinaryOperators = true;
  Style.BreakBeforeBraces = FormatStyle::BS_GNU;
  Style.BreakBeforeTernaryOperators = true;
  Style.ColumnLimit = 79;
  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
  return Style;
}

bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
                        FormatStyle *Style) {
  if (Name.equals_lower("llvm")) {
d321 1
a321 1
  } else if (Name.equals_lower("chromium")) {
d323 1
a323 1
  } else if (Name.equals_lower("mozilla")) {
d325 3
a327 4
  } else if (Name.equals_lower("google")) {
    *Style = Language == FormatStyle::LK_JavaScript ? getGoogleJSStyle()
                                                    : getGoogleStyle();
  } else if (Name.equals_lower("webkit")) {
d329 1
a329 3
  } else if (Name.equals_lower("gnu")) {
    *Style = getGNUStyle();
  } else {
a330 1
  }
a331 1
  Style->Language = Language;
a335 3
  assert(Style);
  FormatStyle::LanguageKind Language = Style->Language;
  assert(Language != FormatStyle::LK_None);
a337 2

  std::vector<FormatStyle> Styles;
d339 2
a340 35
  // DocumentListTraits<vector<FormatStyle>> uses the context to get default
  // values for the fields, keys for which are missing from the configuration.
  // Mapping also uses the context to get the language to find the correct
  // base style.
  Input.setContext(Style);
  Input >> Styles;
  if (Input.error())
    return Input.error();

  for (unsigned i = 0; i < Styles.size(); ++i) {
    // Ensures that only the first configuration can skip the Language option.
    if (Styles[i].Language == FormatStyle::LK_None && i != 0)
      return llvm::make_error_code(llvm::errc::invalid_argument);
    // Ensure that each language is configured at most once.
    for (unsigned j = 0; j < i; ++j) {
      if (Styles[i].Language == Styles[j].Language) {
        DEBUG(llvm::dbgs()
              << "Duplicate languages in the config file on positions " << j
              << " and " << i << "\n");
        return llvm::make_error_code(llvm::errc::invalid_argument);
      }
    }
  }
  // Look for a suitable configuration starting from the end, so we can
  // find the configuration for the specific language first, and the default
  // configuration (which can only be at slot 0) after it.
  for (int i = Styles.size() - 1; i >= 0; --i) {
    if (Styles[i].Language == Language ||
        Styles[i].Language == FormatStyle::LK_None) {
      *Style = Styles[i];
      Style->Language = Language;
      return llvm::make_error_code(llvm::errc::success);
    }
  }
  return llvm::make_error_code(llvm::errc::not_supported);
d384 1
a384 1
                           SmallVectorImpl<AnnotatedLine *>::const_iterator I,
d387 1
a387 1
    const AnnotatedLine *TheLine = *I;
d391 1
a391 1
    if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
a404 6
    if (TheLine->Last->Type == TT_FunctionLBrace &&
        TheLine->First != TheLine->Last) {
      return Style.AllowShortFunctionsOnASingleLine
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
d406 9
a414 33
      return Style.BreakBeforeBraces == FormatStyle::BS_Attach
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
    if (I[1]->First->Type == TT_FunctionLBrace &&
        Style.BreakBeforeBraces != FormatStyle::BS_Attach) {
      // Check for Limit <= 2 to account for the " {".
      if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
        return 0;
      Limit -= 2;

      unsigned MergedLines = 0;
      if (Style.AllowShortFunctionsOnASingleLine) {
        MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
        // If we managed to merge the block, count the function header, which is
        // on a separate line.
        if (MergedLines > 0)
          ++MergedLines;
      }
      return MergedLines;
    }
    if (TheLine->First->is(tok::kw_if)) {
      return Style.AllowShortIfStatementsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
      return Style.AllowShortLoopsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->InPPDirective &&
        (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
d422 1
a422 1
  tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
d437 1
a437 1
      SmallVectorImpl<AnnotatedLine *>::const_iterator I,
d441 1
a441 2
    if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
         Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
d453 1
a453 1
                             tok::kw_while) ||
d464 1
a464 1
  tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
d467 4
a523 8
  bool containsMustBreak(const AnnotatedLine *Line) {
    for (const FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
      if (Tok->MustBreakBefore)
        return true;
    }
    return false;
  }

d529 3
a531 1
  UnwrappedLineFormatter(ContinuationIndenter *Indenter,
d534 2
a535 2
      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
        Joiner(Style) {}
d538 1
a538 1
                  int AdditionalIndent = 0, bool FixBadIndentation = false) {
d544 1
d546 1
d554 7
d562 4
a565 10
      unsigned Indent;
      if (TheLine.InPPDirective) {
        Indent = TheLine.Level * Style.IndentWidth;
      } else {
        while (IndentForLevel.size() <= TheLine.Level)
          IndentForLevel.push_back(-1);
        IndentForLevel.resize(TheLine.Level + 1);
        Indent = getIndent(IndentForLevel, TheLine.Level);
      }
      unsigned LevelIndent = Indent;
a567 2

      // Merge multiple lines if possible.
a568 8
      if (MergedLines > 0 && Style.ColumnLimit == 0) {
        // Disallow line merging if there is a break at the start of one of the
        // input lines.
        for (unsigned i = 0; i < MergedLines; ++i) {
          if (I[i + 1]->First->NewlinesBefore > 0)
            MergedLines = 0;
        }
      }
d576 1
a576 2
      bool FixIndentation =
          FixBadIndentation && (LevelIndent != FirstTok->OriginalColumn);
d578 1
a578 2
        if (PreviousLine && PreviousLine->Affected && !DryRun) {
          // Remove the file's trailing whitespace.
d585 3
a587 1
                 (TheLine.Affected || FixIndentation)) {
a608 1
          // FIXME: Implement nested blocks for ColumnLimit = 0.
d616 2
a617 4
        if (!TheLine.InPPDirective)
          IndentForLevel[TheLine.Level] = LevelIndent;
      } else if (TheLine.ChildrenAffected) {
        format(TheLine.Children, DryRun);
d626 3
a628 3
              // Remove trailing whitespace of the previous line.
              if ((PreviousLine && PreviousLine->Affected) ||
                  TheLine.LeadingEmptyLinesAffected) {
d638 1
a638 1
            if (Tok->isNot(tok::comment) && !TheLine.InPPDirective)
d644 4
d735 3
a737 3
    Whitespaces->replaceWhitespace(RootToken, Newlines, IndentLevel, Indent,
                                   Indent, InPPDirective &&
                                               !RootToken.HasUnescapedNewline);
a755 2
    if (B.Affected)
      A.Affected = true;
d771 42
d958 1
a958 2
      Penalty += format(Previous.Children, DryRun, AdditionalIndent,
                        /*FixBadIndentation=*/true);
d964 1
a964 1
      return false;
d982 2
d1006 1
a1006 1
      tryMergePreviousTokens();
d1014 2
a1015 2
  void tryMergePreviousTokens() {
    if (tryMerge_TMacro())
a1016 42

    if (Style.Language == FormatStyle::LK_JavaScript) {
      static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };
      static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };
      static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,
                                               tok::greaterequal };
      // FIXME: We probably need to change token type to mimic operator with the
      // correct priority.
      if (tryMergeTokens(JSIdentity))
        return;
      if (tryMergeTokens(JSNotIdentity))
        return;
      if (tryMergeTokens(JSShiftEqual))
        return;
    }
  }

  bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {
    if (Tokens.size() < Kinds.size())
      return false;

    SmallVectorImpl<FormatToken *>::const_iterator First =
        Tokens.end() - Kinds.size();
    if (!First[0]->is(Kinds[0]))
      return false;
    unsigned AddLength = 0;
    for (unsigned i = 1; i < Kinds.size(); ++i) {
      if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=
                                         First[i]->WhitespaceRange.getEnd())
        return false;
      AddLength += First[i]->TokenText.size();
    }
    Tokens.resize(Tokens.size() - Kinds.size() + 1);
    First[0]->TokenText = StringRef(First[0]->TokenText.data(),
                                    First[0]->TokenText.size() + AddLength);
    First[0]->ColumnWidth += AddLength;
    return true;
  }

  bool tryMerge_TMacro() {
    if (Tokens.size() < 4)
      return false;
d1019 1
a1019 1
      return false;
d1023 1
a1023 1
      return false;
d1026 1
a1026 1
      return false;
d1030 1
a1030 1
      return false;
a1045 1
    return true;
a1206 11
static StringRef getLanguageName(FormatStyle::LanguageKind Language) {
  switch (Language) {
  case FormatStyle::LK_Cpp:
    return "C++";
  case FormatStyle::LK_JavaScript:
    return "JavaScript";
  default:
    return "Unknown";
  }
}

a1218 2
    DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)
                       << "\n");
a1263 1
    computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end());
d1268 2
a1269 1
    UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style);
a1274 135
  // Determines which lines are affected by the SourceRanges given as input.
  // Returns \c true if at least one line between I and E or one of their
  // children is affected.
  bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I,
                            SmallVectorImpl<AnnotatedLine *>::iterator E) {
    bool SomeLineAffected = false;
    const AnnotatedLine *PreviousLine = NULL;
    while (I != E) {
      AnnotatedLine *Line = *I;
      Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);

      // If a line is part of a preprocessor directive, it needs to be formatted
      // if any token within the directive is affected.
      if (Line->InPPDirective) {
        FormatToken *Last = Line->Last;
        SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
        while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
          Last = (*PPEnd)->Last;
          ++PPEnd;
        }

        if (affectsTokenRange(*Line->First, *Last,
                              /*IncludeLeadingNewlines=*/false)) {
          SomeLineAffected = true;
          markAllAsAffected(I, PPEnd);
        }
        I = PPEnd;
        continue;
      }

      if (nonPPLineAffected(Line, PreviousLine))
        SomeLineAffected = true;

      PreviousLine = Line;
      ++I;
    }
    return SomeLineAffected;
  }

  // Determines whether 'Line' is affected by the SourceRanges given as input.
  // Returns \c true if line or one if its children is affected.
  bool nonPPLineAffected(AnnotatedLine *Line,
                         const AnnotatedLine *PreviousLine) {
    bool SomeLineAffected = false;
    Line->ChildrenAffected =
        computeAffectedLines(Line->Children.begin(), Line->Children.end());
    if (Line->ChildrenAffected)
      SomeLineAffected = true;

    // Stores whether one of the line's tokens is directly affected.
    bool SomeTokenAffected = false;
    // Stores whether we need to look at the leading newlines of the next token
    // in order to determine whether it was affected.
    bool IncludeLeadingNewlines = false;

    // Stores whether the first child line of any of this line's tokens is
    // affected.
    bool SomeFirstChildAffected = false;

    for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
      // Determine whether 'Tok' was affected.
      if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
        SomeTokenAffected = true;

      // Determine whether the first child of 'Tok' was affected.
      if (!Tok->Children.empty() && Tok->Children.front()->Affected)
        SomeFirstChildAffected = true;

      IncludeLeadingNewlines = Tok->Children.empty();
    }

    // Was this line moved, i.e. has it previously been on the same line as an
    // affected line?
    bool LineMoved = PreviousLine && PreviousLine->Affected &&
                     Line->First->NewlinesBefore == 0;

    bool IsContinuedComment = Line->First->is(tok::comment) &&
                              Line->First->Next == NULL &&
                              Line->First->NewlinesBefore < 2 && PreviousLine &&
                              PreviousLine->Affected &&
                              PreviousLine->Last->is(tok::comment);

    if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
        IsContinuedComment) {
      Line->Affected = true;
      SomeLineAffected = true;
    }
    return SomeLineAffected;
  }

  // Marks all lines between I and E as well as all their children as affected.
  void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I,
                         SmallVectorImpl<AnnotatedLine *>::iterator E) {
    while (I != E) {
      (*I)->Affected = true;
      markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
      ++I;
    }
  }

  // Returns true if the range from 'First' to 'Last' intersects with one of the
  // input ranges.
  bool affectsTokenRange(const FormatToken &First, const FormatToken &Last,
                         bool IncludeLeadingNewlines) {
    SourceLocation Start = First.WhitespaceRange.getBegin();
    if (!IncludeLeadingNewlines)
      Start = Start.getLocWithOffset(First.LastNewlineOffset);
    SourceLocation End = Last.getStartOfNonWhitespace();
    if (Last.TokenText.size() > 0)
      End = End.getLocWithOffset(Last.TokenText.size() - 1);
    CharSourceRange Range = CharSourceRange::getCharRange(Start, End);
    return affectsCharSourceRange(Range);
  }

  // Returns true if one of the input ranges intersect the leading empty lines
  // before 'Tok'.
  bool affectsLeadingEmptyLines(const FormatToken &Tok) {
    CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(
        Tok.WhitespaceRange.getBegin(),
        Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));
    return affectsCharSourceRange(EmptyLineRange);
  }

  // Returns true if 'Range' intersects with one of the input ranges.
  bool affectsCharSourceRange(const CharSourceRange &Range) {
    for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
                                                          E = Ranges.end();
         I != E; ++I) {
      if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
          !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
        return true;
    }
    return false;
  }

d1410 5
a1414 16
static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
  if (FileName.endswith_lower(".js")) {
    return FormatStyle::LK_JavaScript;
  }
  return FormatStyle::LK_Cpp;
}

FormatStyle getStyle(StringRef StyleName, StringRef FileName,
                     StringRef FallbackStyle) {
  FormatStyle Style = getLLVMStyle();
  Style.Language = getLanguageByFileName(FileName);
  if (!getPredefinedStyle(FallbackStyle, Style.Language, &Style)) {
    llvm::errs() << "Invalid fallback style \"" << FallbackStyle
                 << "\" using LLVM style\n";
    return Style;
  }
d1426 1
a1426 1
    if (!getPredefinedStyle(StyleName, Style.Language, &Style))
a1431 2
  // Look for .clang-format/_clang-format file in the file's parent directories.
  SmallString<128> UnsuitableConfigFiles;
d1460 1
a1460 1
        break;
a1462 6
        if (ec == llvm::errc::not_supported) {
          if (!UnsuitableConfigFiles.empty())
            UnsuitableConfigFiles.append(", ");
          UnsuitableConfigFiles.append(ConfigFile);
          continue;
        }
d1465 1
a1465 1
        break;
a1472 5
  if (!UnsuitableConfigFiles.empty()) {
    llvm::errs() << "Configuration file(s) do(es) not support "
                 << getLanguageName(Style.Language) << ": "
                 << UnsuitableConfigFiles << "\n";
  }
@


1.1.1.3
log
@Import Clang 3.5svn r199312
@
text
@d29 1
a30 1
#include "llvm/Support/YAMLTraits.h"
@


1.1.1.4
log
@Import Clang 3.5svn r201163.
@
text
@a41 1
    IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
a165 1
    IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
a192 2
    IO.mapOptional("SpacesInContainerLiterals",
                   Style.SpacesInContainerLiterals);
a266 1
  LLVMStyle.ObjCSpaceAfterProperty = false;
a273 1
  LLVMStyle.SpacesInContainerLiterals = true;
d291 1
a291 1
FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
a292 2
  GoogleStyle.Language = Language;

a303 1
  GoogleStyle.ObjCSpaceAfterProperty = false;
d312 2
a313 7
  if (Language == FormatStyle::LK_JavaScript) {
    GoogleStyle.BreakBeforeTernaryOperators = false;
    GoogleStyle.MaxEmptyLinesToKeep = 2;
    GoogleStyle.SpacesInContainerLiterals = false;
  } else if (Language == FormatStyle::LK_Proto) {
    GoogleStyle.AllowShortFunctionsOnASingleLine = false;
  }
d315 8
a322 1
  return GoogleStyle;
d325 2
a326 2
FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
  FormatStyle ChromiumStyle = getGoogleStyle(Language);
a341 1
  MozillaStyle.ObjCSpaceAfterProperty = true;
a357 1
  Style.ObjCSpaceAfterProperty = true;
d377 1
a377 1
    *Style = getChromiumStyle(Language);
d381 2
a382 1
    *Style = getGoogleStyle(Language);
a575 1
    Limit = limitConsideringMacros(I + 1, E, Limit);
a618 1
      Limit = limitConsideringMacros(I + 2, E, Limit);
a643 13
  /// Returns the modified column limit for \p I if it is inside a macro and
  /// needs a trailing '\'.
  unsigned
  limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                         SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                         unsigned Limit) {
    if (I[0]->InPPDirective && I + 1 != E &&
        !I[1]->First->HasUnescapedNewline && !I[1]->First->is(tok::eof)) {
      return Limit < 2 ? 0 : Limit - 2;
    }
    return Limit;
  }

d1338 4
a1341 8
    if (Tok.is(tok::unknown)) {
      if (!Tok.TokenText.empty() && Tok.TokenText[0] == '"') {
        Tok.Tok.setKind(tok::string_literal);
        Tok.IsUnterminatedLiteral = true;
      } else if (Style.Language == FormatStyle::LK_JavaScript &&
                 Tok.TokenText == "''") {
        Tok.Tok.setKind(tok::char_constant);
      }
a1351 2
  case FormatStyle::LK_Proto:
    return "Proto";
a1699 3
  } else if (FileName.endswith_lower(".proto") ||
             FileName.endswith_lower(".protodevel")) {
    return FormatStyle::LK_Proto;
@


1.1.1.4.2.1
log
@Rebase.
@
text
@d16 2
a22 1
#include "clang/Basic/DiagnosticOptions.h"
a33 2
#define DEBUG_TYPE "format-formatter"

a35 2
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)

a65 10
template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
  static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::SFS_None);
    IO.enumCase(Value, "false", FormatStyle::SFS_None);
    IO.enumCase(Value, "All", FormatStyle::SFS_All);
    IO.enumCase(Value, "true", FormatStyle::SFS_All);
    IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
  }
};

a140 2
    IO.mapOptional("AllowShortBlocksOnASingleLine",
                   Style.AllowShortBlocksOnASingleLine);
a165 2
    IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
                   Style.KeepEmptyLinesAtTheStartOfBlocks);
a200 1
    IO.mapOptional("ForEachMacros", Style.ForEachMacros);
a207 1
    IO.mapOptional("DisableFormat", Style.DisableFormat);
d228 1
a228 1
        Template = *((const FormatStyle *)IO.getContext());
d249 1
a249 2
  LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
  LLVMStyle.AllowShortBlocksOnASingleLine = false;
a259 1
  LLVMStyle.CommentPragmas = "^ IWYU pragma:";
d262 1
a262 2
  LLVMStyle.ContinuationIndentWidth = 4;
  LLVMStyle.Cpp11BracedListStyle = true;
a264 3
  LLVMStyle.ForEachMacros.push_back("foreach");
  LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
  LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
a269 1
  LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
d275 1
a275 1
  LLVMStyle.Standard = FormatStyle::LS_Cpp11;
d283 1
d285 1
a293 2
  LLVMStyle.DisableFormat = false;

d308 1
a311 1
  GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
d323 1
a323 1
    GoogleStyle.MaxEmptyLinesToKeep = 3;
d326 1
a326 2
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
    GoogleStyle.SpacesInContainerLiterals = false;
a334 1
  ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
a345 1
  MozillaStyle.Cpp11BracedListStyle = false;
a352 1
  MozillaStyle.Standard = FormatStyle::LS_Cpp03;
a362 1
  Style.Cpp11BracedListStyle = false;
a367 1
  Style.Standard = FormatStyle::LS_Cpp03;
a375 1
  Style.Cpp11BracedListStyle = false;
a377 1
  Style.Standard = FormatStyle::LS_Cpp03;
a380 6
FormatStyle getNoStyle() {
  FormatStyle NoStyle = getLLVMStyle();
  NoStyle.DisableFormat = true;
  return NoStyle;
}

a394 2
  } else if (Name.equals_lower("none")) {
    *Style = getNoStyle();
d443 1
a443 1
      return llvm::error_code::success();
d471 1
a471 1
    while (State.NextToken) {
d508 1
a508 1
    if (I + 1 == E || I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
a510 7
    // FIXME: TheLine->Level != 0 might or might not be the right check to do.
    // If necessary, change to something smarter.
    bool MergeShortFunctions =
        Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
        (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
         TheLine->Level != 0);

d513 3
a515 1
      return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
d530 1
a530 1
      if (MergeShortFunctions) {
d579 1
a579 1
        (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
d605 3
d609 5
a613 3

    // Don't merge ObjC @@ keywords and methods.
    if (Line.First->isOneOf(tok::at, tok::minus, tok::plus))
a615 20
    // Check that the current line allows merging. This depends on whether we
    // are in a control flow statements as well as several style flags.
    if (Line.First->isOneOf(tok::kw_else, tok::kw_case))
      return 0;
    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
                            tok::kw_catch, tok::kw_for, tok::r_brace)) {
      if (!Style.AllowShortBlocksOnASingleLine)
        return 0;
      if (!Style.AllowShortIfStatementsOnASingleLine &&
          Line.First->is(tok::kw_if))
        return 0;
      if (!Style.AllowShortLoopsOnASingleLine &&
          Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
        return 0;
      // FIXME: Consider an option to allow short exception handling clauses on
      // a single line.
      if (Line.First->isOneOf(tok::kw_try, tok::kw_catch))
        return 0;
    }

d618 1
a618 1
        (Tok->getNextNonComment() == nullptr ||
a624 4
      // We don't merge short records.
      if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct))
        return 0;

d635 1
a635 1
      if (I[1]->Last->Type == TT_LineComment)
d638 1
a638 1
        if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
d641 1
a641 1
      } while (Tok);
d643 1
a643 1
      // Last, check that the third line starts with a closing brace.
d645 2
a646 1
      if (Tok->isNot(tok::r_brace))
a668 2
    if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
      return false;
a692 7
    // Try to look up already computed penalty in DryRun-mode.
    std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
        &Lines, AdditionalIndent);
    auto CacheIt = PenaltyCache.find(CacheKey);
    if (DryRun && CacheIt != PenaltyCache.end())
      return CacheIt->second;

d698 1
a698 1
    const AnnotatedLine *PreviousLine = nullptr;
d767 1
a767 2
          while (State.NextToken) {
            formatChildren(State, /*Newline=*/false, /*DryRun=*/false, Penalty);
a768 1
          }
d785 1
a785 1
        for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
d810 1
a810 1
        for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
a815 1
    PenaltyCache[CacheKey] = Penalty;
a884 8
    if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
      Newlines = 0;

    // Remove empty lines after "{".
    if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
        PreviousLine->Last->is(tok::l_brace) &&
        PreviousLine->First->isNot(tok::kw_namespace))
      Newlines = 1;
a932 6
  struct CompareLineStatePointers {
    bool operator()(LineState *obj1, LineState *obj2) const {
      return *obj1 < *obj2;
    }
  };

d942 1
a942 1
    std::set<LineState *, CompareLineStatePointers> Seen;
d951 1
a951 1
        new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
d961 1
a961 1
      if (!Node->State.NextToken) {
d972 1
a972 1
      if (!Seen.insert(&Node->State).second)
d1076 2
a1077 7
      int AdditionalIndent = 0;
      if (State.Stack.size() < 2 ||
          !State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
        AdditionalIndent = State.Stack.back().Indent -
                           Previous.Children[0]->Level * Style.IndentWidth;
      }

a1086 4
    // Cannot merge into one line if this line ends on a comment.
    if (Previous.is(tok::comment))
      return false;

a1090 7
    // If the child line exceeds the column limit, we wouldn't want to merge it.
    // We add +2 for the trailing " }".
    if (Style.ColumnLimit > 0 &&
        Previous.Children[0]->Last->TotalLength + State.Column + 2 >
            Style.ColumnLimit)
      return false;

a1108 6

  // Cache to store the penalty of formatting a vector of AnnotatedLines
  // starting from a specific additional offset. Improves performance if there
  // are many nested blocks.
  std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
           unsigned> PenaltyCache;
d1115 3
a1117 4
      : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
        Column(0), TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr),
        Style(Style), IdentTable(getFormattingLangOpts()), Encoding(Encoding),
        FirstInLineIndex(0) {
a1118 4

    for (const std::string &ForEachMacro : Style.ForEachMacros)
      ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
    std::sort(ForEachMacros.begin(), ForEachMacros.end());
a1122 1
    assert(FirstInLineIndex == 0);
a1125 2
      if (Tokens.back()->NewlinesBefore > 0)
        FirstInLineIndex = Tokens.size() - 1;
a1135 2
    if (tryMergeConflictMarkers())
      return;
a1137 5
      if (tryMergeEscapeSequence())
        return;
      if (tryMergeJSRegexLiteral())
        return;

a1141 1
      static tok::TokenKind JSRightArrow[] = { tok::equal, tok::greater };
a1149 2
      if (tryMergeTokens(JSRightArrow))
        return;
a1174 50
  // Tries to merge an escape sequence, i.e. a "\\" and the following
  // character. Use e.g. inside JavaScript regex literals.
  bool tryMergeEscapeSequence() {
    if (Tokens.size() < 2)
      return false;
    FormatToken *Previous = Tokens[Tokens.size() - 2];
    if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\" ||
        Tokens.back()->NewlinesBefore != 0)
      return false;
    Previous->ColumnWidth += Tokens.back()->ColumnWidth;
    StringRef Text = Previous->TokenText;
    Previous->TokenText =
        StringRef(Text.data(), Text.size() + Tokens.back()->TokenText.size());
    Tokens.resize(Tokens.size() - 1);
    return true;
  }

  // Try to determine whether the current token ends a JavaScript regex literal.
  // We heuristically assume that this is a regex literal if we find two
  // unescaped slashes on a line and the token before the first slash is one of
  // "(;,{}![:?", a binary operator or 'return', as those cannot be followed by
  // a division.
  bool tryMergeJSRegexLiteral() {
    if (Tokens.size() < 2 || Tokens.back()->isNot(tok::slash) ||
        (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
         Tokens[Tokens.size() - 2]->TokenText == "\\"))
      return false;
    unsigned TokenCount = 0;
    unsigned LastColumn = Tokens.back()->OriginalColumn;
    for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
      ++TokenCount;
      if (I[0]->is(tok::slash) && I + 1 != E &&
          (I[1]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace,
                         tok::exclaim, tok::l_square, tok::colon, tok::comma,
                         tok::question, tok::kw_return) ||
           I[1]->isBinaryOperator())) {
        Tokens.resize(Tokens.size() - TokenCount);
        Tokens.back()->Tok.setKind(tok::unknown);
        Tokens.back()->Type = TT_RegexLiteral;
        Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
        return true;
      }

      // There can't be a newline inside a regex literal.
      if (I[0]->NewlinesBefore > 0)
        return false;
    }
    return false;
  }

a1209 62
  bool tryMergeConflictMarkers() {
    if (Tokens.back()->NewlinesBefore == 0 && Tokens.back()->isNot(tok::eof))
      return false;

    // Conflict lines look like:
    // <marker> <text from the vcs>
    // For example:
    // >>>>>>> /file/in/file/system at revision 1234
    //
    // We merge all tokens in a line that starts with a conflict marker
    // into a single token with a special token type that the unwrapped line
    // parser will use to correctly rebuild the underlying code.

    FileID ID;
    // Get the position of the first token in the line.
    unsigned FirstInLineOffset;
    std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
        Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
    StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
    // Calculate the offset of the start of the current line.
    auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
    if (LineOffset == StringRef::npos) {
      LineOffset = 0;
    } else {
      ++LineOffset;
    }

    auto FirstSpace = Buffer.find_first_of(" \n", LineOffset);
    StringRef LineStart;
    if (FirstSpace == StringRef::npos) {
      LineStart = Buffer.substr(LineOffset);
    } else {
      LineStart = Buffer.substr(LineOffset, FirstSpace - LineOffset);
    }

    TokenType Type = TT_Unknown;
    if (LineStart == "<<<<<<<" || LineStart == ">>>>") {
      Type = TT_ConflictStart;
    } else if (LineStart == "|||||||" || LineStart == "=======" ||
               LineStart == "====") {
      Type = TT_ConflictAlternative;
    } else if (LineStart == ">>>>>>>" || LineStart == "<<<<") {
      Type = TT_ConflictEnd;
    }

    if (Type != TT_Unknown) {
      FormatToken *Next = Tokens.back();

      Tokens.resize(FirstInLineIndex + 1);
      // We do not need to build a complete token here, as we will skip it
      // during parsing anyway (as we must not touch whitespace around conflict
      // markers).
      Tokens.back()->Type = Type;
      Tokens.back()->Tok.setKind(tok::kw___unknown_anytype);

      Tokens.push_back(Next);
      return true;
    }

    return false;
  }

d1287 1
a1287 1
      ++FormatTok->NewlinesBefore;
a1338 4
    FormatTok->IsForEachMacro =
        std::binary_search(ForEachMacros.begin(), ForEachMacros.end(),
                           FormatTok->Tok.getIdentifierInfo());

a1352 2
  // Index (in 'Tokens') of the last token that starts a new line.
  unsigned FirstInLineIndex;
a1353 1
  SmallVector<IdentifierInfo *, 8> ForEachMacros;
d1462 1
a1462 1
    const AnnotatedLine *PreviousLine = nullptr;
d1532 5
a1536 4
    bool IsContinuedComment =
        Line->First->is(tok::comment) && Line->First->Next == nullptr &&
        Line->First->NewlinesBefore < 2 && PreviousLine &&
        PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
d1649 1
a1649 1
  void consumeUnwrappedLine(const UnwrappedLine &TheLine) override {
d1654 1
a1654 1
  void finishRun() override {
a1673 5
  if (Style.DisableFormat) {
    tooling::Replacements EmptyResult;
    return EmptyResult;
  }

a1707 1
  LangOpts.CPlusPlus1y = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
a1708 1
  LangOpts.CXXOperatorNames = 1;
d1788 1
a1788 1
      std::unique_ptr<llvm::MemoryBuffer> Text;
@


1.1.1.5
log
@Import Clang 3.5svn r209886.
@
text
@d16 2
a22 1
#include "clang/Basic/DiagnosticOptions.h"
a33 2
#define DEBUG_TYPE "format-formatter"

a35 2
LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)

a65 10
template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
  static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::SFS_None);
    IO.enumCase(Value, "false", FormatStyle::SFS_None);
    IO.enumCase(Value, "All", FormatStyle::SFS_All);
    IO.enumCase(Value, "true", FormatStyle::SFS_All);
    IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
  }
};

a140 2
    IO.mapOptional("AllowShortBlocksOnASingleLine",
                   Style.AllowShortBlocksOnASingleLine);
a165 2
    IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
                   Style.KeepEmptyLinesAtTheStartOfBlocks);
a200 1
    IO.mapOptional("ForEachMacros", Style.ForEachMacros);
a207 1
    IO.mapOptional("DisableFormat", Style.DisableFormat);
d228 1
a228 1
        Template = *((const FormatStyle *)IO.getContext());
d249 1
a249 2
  LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
  LLVMStyle.AllowShortBlocksOnASingleLine = false;
a259 1
  LLVMStyle.CommentPragmas = "^ IWYU pragma:";
d262 1
a262 2
  LLVMStyle.ContinuationIndentWidth = 4;
  LLVMStyle.Cpp11BracedListStyle = true;
a264 3
  LLVMStyle.ForEachMacros.push_back("foreach");
  LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
  LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
a269 1
  LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
d275 1
a275 1
  LLVMStyle.Standard = FormatStyle::LS_Cpp11;
d283 1
d285 1
a293 2
  LLVMStyle.DisableFormat = false;

d308 1
a311 1
  GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
d323 1
a323 1
    GoogleStyle.MaxEmptyLinesToKeep = 3;
d326 1
a326 2
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
    GoogleStyle.SpacesInContainerLiterals = false;
a334 1
  ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
a345 1
  MozillaStyle.Cpp11BracedListStyle = false;
a352 1
  MozillaStyle.Standard = FormatStyle::LS_Cpp03;
a362 1
  Style.Cpp11BracedListStyle = false;
a367 1
  Style.Standard = FormatStyle::LS_Cpp03;
a375 1
  Style.Cpp11BracedListStyle = false;
a377 1
  Style.Standard = FormatStyle::LS_Cpp03;
a380 6
FormatStyle getNoStyle() {
  FormatStyle NoStyle = getLLVMStyle();
  NoStyle.DisableFormat = true;
  return NoStyle;
}

a394 2
  } else if (Name.equals_lower("none")) {
    *Style = getNoStyle();
d443 1
a443 1
      return llvm::error_code::success();
d471 1
a471 1
    while (State.NextToken) {
d508 1
a508 1
    if (I + 1 == E || I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
a510 7
    // FIXME: TheLine->Level != 0 might or might not be the right check to do.
    // If necessary, change to something smarter.
    bool MergeShortFunctions =
        Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
        (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
         TheLine->Level != 0);

d513 3
a515 1
      return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
d530 1
a530 1
      if (MergeShortFunctions) {
d579 1
a579 1
        (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
d605 3
d609 5
a613 3

    // Don't merge ObjC @@ keywords and methods.
    if (Line.First->isOneOf(tok::at, tok::minus, tok::plus))
a615 20
    // Check that the current line allows merging. This depends on whether we
    // are in a control flow statements as well as several style flags.
    if (Line.First->isOneOf(tok::kw_else, tok::kw_case))
      return 0;
    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
                            tok::kw_catch, tok::kw_for, tok::r_brace)) {
      if (!Style.AllowShortBlocksOnASingleLine)
        return 0;
      if (!Style.AllowShortIfStatementsOnASingleLine &&
          Line.First->is(tok::kw_if))
        return 0;
      if (!Style.AllowShortLoopsOnASingleLine &&
          Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
        return 0;
      // FIXME: Consider an option to allow short exception handling clauses on
      // a single line.
      if (Line.First->isOneOf(tok::kw_try, tok::kw_catch))
        return 0;
    }

d618 1
a618 1
        (Tok->getNextNonComment() == nullptr ||
a624 4
      // We don't merge short records.
      if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct))
        return 0;

d635 1
a635 1
      if (I[1]->Last->Type == TT_LineComment)
d638 1
a638 1
        if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
d641 1
a641 1
      } while (Tok);
d643 1
a643 1
      // Last, check that the third line starts with a closing brace.
d645 2
a646 1
      if (Tok->isNot(tok::r_brace))
a668 2
    if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
      return false;
a692 7
    // Try to look up already computed penalty in DryRun-mode.
    std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
        &Lines, AdditionalIndent);
    auto CacheIt = PenaltyCache.find(CacheKey);
    if (DryRun && CacheIt != PenaltyCache.end())
      return CacheIt->second;

d698 1
a698 1
    const AnnotatedLine *PreviousLine = nullptr;
d767 1
a767 2
          while (State.NextToken) {
            formatChildren(State, /*Newline=*/false, /*DryRun=*/false, Penalty);
a768 1
          }
d785 1
a785 1
        for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
d810 1
a810 1
        for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
a815 1
    PenaltyCache[CacheKey] = Penalty;
a884 8
    if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
      Newlines = 0;

    // Remove empty lines after "{".
    if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
        PreviousLine->Last->is(tok::l_brace) &&
        PreviousLine->First->isNot(tok::kw_namespace))
      Newlines = 1;
a932 6
  struct CompareLineStatePointers {
    bool operator()(LineState *obj1, LineState *obj2) const {
      return *obj1 < *obj2;
    }
  };

d942 1
a942 1
    std::set<LineState *, CompareLineStatePointers> Seen;
d951 1
a951 1
        new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
d961 1
a961 1
      if (!Node->State.NextToken) {
d972 1
a972 1
      if (!Seen.insert(&Node->State).second)
d1076 2
a1077 7
      int AdditionalIndent = 0;
      if (State.Stack.size() < 2 ||
          !State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
        AdditionalIndent = State.Stack.back().Indent -
                           Previous.Children[0]->Level * Style.IndentWidth;
      }

a1086 4
    // Cannot merge into one line if this line ends on a comment.
    if (Previous.is(tok::comment))
      return false;

a1090 7
    // If the child line exceeds the column limit, we wouldn't want to merge it.
    // We add +2 for the trailing " }".
    if (Style.ColumnLimit > 0 &&
        Previous.Children[0]->Last->TotalLength + State.Column + 2 >
            Style.ColumnLimit)
      return false;

a1108 6

  // Cache to store the penalty of formatting a vector of AnnotatedLines
  // starting from a specific additional offset. Improves performance if there
  // are many nested blocks.
  std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
           unsigned> PenaltyCache;
d1115 3
a1117 4
      : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
        Column(0), TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr),
        Style(Style), IdentTable(getFormattingLangOpts()), Encoding(Encoding),
        FirstInLineIndex(0) {
a1118 4

    for (const std::string &ForEachMacro : Style.ForEachMacros)
      ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
    std::sort(ForEachMacros.begin(), ForEachMacros.end());
a1122 1
    assert(FirstInLineIndex == 0);
a1125 2
      if (Tokens.back()->NewlinesBefore > 0)
        FirstInLineIndex = Tokens.size() - 1;
a1135 2
    if (tryMergeConflictMarkers())
      return;
a1137 5
      if (tryMergeEscapeSequence())
        return;
      if (tryMergeJSRegexLiteral())
        return;

a1141 1
      static tok::TokenKind JSRightArrow[] = { tok::equal, tok::greater };
a1149 2
      if (tryMergeTokens(JSRightArrow))
        return;
a1174 50
  // Tries to merge an escape sequence, i.e. a "\\" and the following
  // character. Use e.g. inside JavaScript regex literals.
  bool tryMergeEscapeSequence() {
    if (Tokens.size() < 2)
      return false;
    FormatToken *Previous = Tokens[Tokens.size() - 2];
    if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\" ||
        Tokens.back()->NewlinesBefore != 0)
      return false;
    Previous->ColumnWidth += Tokens.back()->ColumnWidth;
    StringRef Text = Previous->TokenText;
    Previous->TokenText =
        StringRef(Text.data(), Text.size() + Tokens.back()->TokenText.size());
    Tokens.resize(Tokens.size() - 1);
    return true;
  }

  // Try to determine whether the current token ends a JavaScript regex literal.
  // We heuristically assume that this is a regex literal if we find two
  // unescaped slashes on a line and the token before the first slash is one of
  // "(;,{}![:?", a binary operator or 'return', as those cannot be followed by
  // a division.
  bool tryMergeJSRegexLiteral() {
    if (Tokens.size() < 2 || Tokens.back()->isNot(tok::slash) ||
        (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
         Tokens[Tokens.size() - 2]->TokenText == "\\"))
      return false;
    unsigned TokenCount = 0;
    unsigned LastColumn = Tokens.back()->OriginalColumn;
    for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
      ++TokenCount;
      if (I[0]->is(tok::slash) && I + 1 != E &&
          (I[1]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace,
                         tok::exclaim, tok::l_square, tok::colon, tok::comma,
                         tok::question, tok::kw_return) ||
           I[1]->isBinaryOperator())) {
        Tokens.resize(Tokens.size() - TokenCount);
        Tokens.back()->Tok.setKind(tok::unknown);
        Tokens.back()->Type = TT_RegexLiteral;
        Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
        return true;
      }

      // There can't be a newline inside a regex literal.
      if (I[0]->NewlinesBefore > 0)
        return false;
    }
    return false;
  }

a1209 62
  bool tryMergeConflictMarkers() {
    if (Tokens.back()->NewlinesBefore == 0 && Tokens.back()->isNot(tok::eof))
      return false;

    // Conflict lines look like:
    // <marker> <text from the vcs>
    // For example:
    // >>>>>>> /file/in/file/system at revision 1234
    //
    // We merge all tokens in a line that starts with a conflict marker
    // into a single token with a special token type that the unwrapped line
    // parser will use to correctly rebuild the underlying code.

    FileID ID;
    // Get the position of the first token in the line.
    unsigned FirstInLineOffset;
    std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
        Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
    StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
    // Calculate the offset of the start of the current line.
    auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
    if (LineOffset == StringRef::npos) {
      LineOffset = 0;
    } else {
      ++LineOffset;
    }

    auto FirstSpace = Buffer.find_first_of(" \n", LineOffset);
    StringRef LineStart;
    if (FirstSpace == StringRef::npos) {
      LineStart = Buffer.substr(LineOffset);
    } else {
      LineStart = Buffer.substr(LineOffset, FirstSpace - LineOffset);
    }

    TokenType Type = TT_Unknown;
    if (LineStart == "<<<<<<<" || LineStart == ">>>>") {
      Type = TT_ConflictStart;
    } else if (LineStart == "|||||||" || LineStart == "=======" ||
               LineStart == "====") {
      Type = TT_ConflictAlternative;
    } else if (LineStart == ">>>>>>>" || LineStart == "<<<<") {
      Type = TT_ConflictEnd;
    }

    if (Type != TT_Unknown) {
      FormatToken *Next = Tokens.back();

      Tokens.resize(FirstInLineIndex + 1);
      // We do not need to build a complete token here, as we will skip it
      // during parsing anyway (as we must not touch whitespace around conflict
      // markers).
      Tokens.back()->Type = Type;
      Tokens.back()->Tok.setKind(tok::kw___unknown_anytype);

      Tokens.push_back(Next);
      return true;
    }

    return false;
  }

d1287 1
a1287 1
      ++FormatTok->NewlinesBefore;
a1338 4
    FormatTok->IsForEachMacro =
        std::binary_search(ForEachMacros.begin(), ForEachMacros.end(),
                           FormatTok->Tok.getIdentifierInfo());

a1352 2
  // Index (in 'Tokens') of the last token that starts a new line.
  unsigned FirstInLineIndex;
a1353 1
  SmallVector<IdentifierInfo *, 8> ForEachMacros;
d1462 1
a1462 1
    const AnnotatedLine *PreviousLine = nullptr;
d1532 5
a1536 4
    bool IsContinuedComment =
        Line->First->is(tok::comment) && Line->First->Next == nullptr &&
        Line->First->NewlinesBefore < 2 && PreviousLine &&
        PreviousLine->Affected && PreviousLine->Last->is(tok::comment);
d1649 1
a1649 1
  void consumeUnwrappedLine(const UnwrappedLine &TheLine) override {
d1654 1
a1654 1
  void finishRun() override {
a1673 5
  if (Style.DisableFormat) {
    tooling::Replacements EmptyResult;
    return EmptyResult;
  }

a1707 1
  LangOpts.CPlusPlus1y = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
a1708 1
  LangOpts.CXXOperatorNames = 1;
d1788 1
a1788 1
      std::unique_ptr<llvm::MemoryBuffer> Text;
@


1.1.1.6
log
@Import clang 3.6svn r215315.
@
text
@a99 14
struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
  static void enumeration(IO &IO,
                          FormatStyle::PointerAlignmentStyle &Value) {
    IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
    IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
    IO.enumCase(Value, "Right", FormatStyle::PAS_Right);

    // For backward compatibility.
    IO.enumCase(Value, "true", FormatStyle::PAS_Left);
    IO.enumCase(Value, "false", FormatStyle::PAS_Right);
  }
};

template <>
a161 2
    IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
                   Style.AlwaysBreakAfterDefinitionReturnType);
d176 1
a176 1
    IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
a179 4
    IO.mapOptional("IndentWrappedFunctionNames",
                   Style.IndentWrappedFunctionNames);
    IO.mapOptional("IndentFunctionDeclarationAfterType",
                   Style.IndentWrappedFunctionNames);
d196 1
a196 1
    IO.mapOptional("PointerAlignment", Style.PointerAlignment);
d205 2
a223 2
      IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
      IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
a260 24
const std::error_category &getParseCategory() {
  static ParseErrorCategory C;
  return C;
}
std::error_code make_error_code(ParseError e) {
  return std::error_code(static_cast<int>(e), getParseCategory());
}

const char *ParseErrorCategory::name() const LLVM_NOEXCEPT {
  return "clang-format.parse_error";
}

std::string ParseErrorCategory::message(int EV) const {
  switch (static_cast<ParseError>(EV)) {
  case ParseError::Success:
    return "Success";
  case ParseError::Error:
    return "Invalid argument";
  case ParseError::Unsuitable:
    return "Unsuitable";
  }
  llvm_unreachable("unexpected parse error");
}

a271 1
  LLVMStyle.AlwaysBreakAfterDefinitionReturnType = false;
d285 1
a285 1
  LLVMStyle.DerivePointerAlignment = false;
d291 1
a291 1
  LLVMStyle.IndentWrappedFunctionNames = false;
d299 1
a299 1
  LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
d334 1
a334 1
  GoogleStyle.DerivePointerAlignment = true;
d336 1
d340 1
a340 1
  GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
d366 1
a366 1
  ChromiumStyle.DerivePointerAlignment = false;
d376 1
a376 1
  MozillaStyle.DerivePointerAlignment = true;
d381 1
a381 1
  MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
d398 1
a398 1
  Style.PointerAlignment = FormatStyle::PAS_Left;
a404 1
  Style.AlwaysBreakAfterDefinitionReturnType = true;
d445 1
a445 1
std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
d450 1
a450 1
    return make_error_code(ParseError::Error);
d466 1
a466 1
      return make_error_code(ParseError::Error);
d473 1
a473 1
        return make_error_code(ParseError::Error);
d485 1
a485 1
      return make_error_code(ParseError::Success);
d488 1
a488 1
  return make_error_code(ParseError::Unsuitable);
d1167 1
a1167 2
      int AdditionalIndent =
          State.FirstIndent - State.Line->Level * Style.IndentWidth;
d1231 1
a1231 1
        FirstInLineIndex(0), FormattingDisabled(false) {
a1604 2
  bool FormattingDisabled;

a1619 5
    if (Tok.is(tok::comment) && Tok.TokenText == "// clang-format on")
      FormattingDisabled = false;
    Tok.Finalized = FormattingDisabled;
    if (Tok.is(tok::comment) && Tok.TokenText == "// clang-format off")
      FormattingDisabled = true;
d1884 1
a1884 1
    if (Style.DerivePointerAlignment) {
d1886 1
a1886 1
        Style.PointerAlignment = FormatStyle::PAS_Left;
d1888 1
a1888 1
        Style.PointerAlignment = FormatStyle::PAS_Right;
d2004 1
a2004 1
    if (std::error_code ec = parseConfiguration(StyleName, &Style)) {
d2044 4
a2047 4
      llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
          llvm::MemoryBuffer::getFile(ConfigFile.c_str());
      if (std::error_code EC = Text.getError()) {
        llvm::errs() << EC.message() << "\n";
d2050 2
a2051 3
      if (std::error_code ec =
              parseConfiguration(Text.get()->getBuffer(), &Style)) {
        if (ec == ParseError::Unsuitable) {
@


1.1.1.6.2.1
log
@Update LLVM to 3.6.1, requested by joerg in ticket 824.
@
text
@a17 1
#include "UnwrappedLineFormatter.h"
a43 1
    IO.enumCase(Value, "Java", FormatStyle::LK_Java);
a75 11
    IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
  static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
    IO.enumCase(Value, "All", FormatStyle::BOS_All);
    IO.enumCase(Value, "true", FormatStyle::BOS_All);
    IO.enumCase(Value, "None", FormatStyle::BOS_None);
    IO.enumCase(Value, "false", FormatStyle::BOS_None);
    IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
d162 2
a163 1
    IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
a164 1
    IO.mapOptional("AlignOperands", Style.AlignOperands);
a169 2
    IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
                   Style.AllowShortCaseLabelsOnASingleLine);
a188 1
    IO.mapOptional("BinPackArguments", Style.BinPackArguments);
a191 2
    IO.mapOptional("ConstructorInitializerIndentWidth",
                   Style.ConstructorInitializerIndentWidth);
a203 1
    IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
a225 1
    IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
a229 1
    IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
a309 2
  LLVMStyle.AlignAfterOpenBracket = true;
  LLVMStyle.AlignOperands = true;
a313 1
  LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
d320 1
a320 2
  LLVMStyle.BinPackArguments = true;
  LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
a341 1
  LLVMStyle.ObjCBlockIndentWidth = 2;
a348 1
  LLVMStyle.SpacesInSquareBrackets = false;
a351 1
  LLVMStyle.SpaceAfterCStyleCast = false;
d391 1
a391 12
  if (Language == FormatStyle::LK_Java) {
    GoogleStyle.AlignAfterOpenBracket = false;
    GoogleStyle.AlignOperands = false;
    GoogleStyle.AlignTrailingComments = false;
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
    GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
    GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
    GoogleStyle.ColumnLimit = 100;
    GoogleStyle.SpaceAfterCStyleCast = true;
    GoogleStyle.SpacesBeforeTrailingComments = 1;
  } else if (Language == FormatStyle::LK_JavaScript) {
a394 2
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
d405 7
a411 12
  if (Language == FormatStyle::LK_Java) {
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = true;
    ChromiumStyle.IndentWidth = 4;
    ChromiumStyle.ContinuationIndentWidth = 8;
  } else {
    ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
    ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
    ChromiumStyle.AllowShortLoopsOnASingleLine = false;
    ChromiumStyle.BinPackParameters = false;
    ChromiumStyle.DerivePointerAlignment = false;
  }
a432 2
  Style.AlignAfterOpenBracket = false;
  Style.AlignOperands = false;
d434 1
a434 1
  Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
a440 1
  Style.ObjCBlockIndentWidth = 4;
d450 1
a450 1
  Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
d549 721
d1272 1
a1272 1
  FormatTokenLexer(SourceManager &SourceMgr, FileID ID, FormatStyle &Style,
d1275 4
a1278 7
        Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
        Style(Style), IdentTable(getFormattingLangOpts(Style)),
        Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
        FormattingDisabled(false) {
    Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
                        getFormattingLangOpts(Style)));
    Lex->SetKeepWhitespaceMode(true);
d1297 1
a1297 1
  const AdditionalKeywords &getKeywords() { return Keywords; }
d1307 2
a1310 2
      if (tryMergeEscapeSequence())
        return;
d1358 2
a1359 1
    if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\")
d1361 1
a1361 1
    ++Previous->ColumnWidth;
d1363 2
a1364 2
    Previous->TokenText = StringRef(Text.data(), Text.size() + 1);
    resetLexer(SourceMgr.getFileOffset(Tokens.back()->Tok.getLocation()) + 1);
a1365 1
    Column = Previous->OriginalColumn + Previous->ColumnWidth;
d1375 3
a1377 12
    if (Tokens.size() < 2)
      return false;
    // If a regex literal ends in "\//", this gets represented by an unknown
    // token "\" and a comment.
    bool MightEndWithEscapedSlash =
        Tokens.back()->is(tok::comment) &&
        Tokens.back()->TokenText.startswith("//") &&
        Tokens[Tokens.size() - 2]->TokenText == "\\";
    if (!MightEndWithEscapedSlash &&
        (Tokens.back()->isNot(tok::slash) ||
         (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
          Tokens[Tokens.size() - 2]->TokenText == "\\")))
a1387 6
        if (MightEndWithEscapedSlash) {
          // This regex literal ends in '\//'. Skip past the '//' of the last
          // token and re-start lexing from there.
          SourceLocation Loc = Tokens.back()->Tok.getLocation();
          resetLexer(SourceMgr.getFileOffset(Loc) + 2);
        }
d1551 1
d1563 1
a1563 1
      if (FormatTok->is(TT_ImplicitStringLiteral))
a1596 5
      if (Style.Language == FormatStyle::LK_Java &&
          FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete)) {
        FormatTok->Tok.setKind(tok::identifier);
        FormatTok->Tok.setIdentifierInfo(nullptr);
      }
d1640 1
a1640 1
  std::unique_ptr<Lexer> Lex;
a1641 1
  FileID ID;
a1643 1
  AdditionalKeywords Keywords;
d1654 1
a1654 1
    Lex->LexFromRawLexer(Tok.Tok);
d1668 1
a1668 3

    if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format on" ||
                                 Tok.TokenText == "/* clang-format on */")) {
a1669 2
    }

d1671 1
a1671 3

    if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format off" ||
                                 Tok.TokenText == "/* clang-format off */")) {
a1672 9
    }
  }

  void resetLexer(unsigned Offset) {
    StringRef Buffer = SourceMgr.getBufferData(ID);
    Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID),
                        getFormattingLangOpts(Style), Buffer.begin(),
                        Buffer.begin() + Offset, Buffer.end()));
    Lex->SetKeepWhitespaceMode(true);
a1679 2
  case FormatStyle::LK_Java:
    return "Java";
d1691 4
a1694 5
  Formatter(const FormatStyle &Style, SourceManager &SourceMgr, FileID ID,
            ArrayRef<CharSourceRange> Ranges)
      : Style(Style), ID(ID), SourceMgr(SourceMgr),
        Whitespaces(SourceMgr, Style,
                    inputUsesCRLF(SourceMgr.getBufferData(ID))),
d1696 1
a1696 1
        Encoding(encoding::detectEncoding(SourceMgr.getBufferData(ID))) {
d1707 1
a1707 1
    FormatTokenLexer Tokens(SourceMgr, ID, Style, Encoding);
d1709 1
a1709 2
    UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(),
                               *this);
d1740 1
a1740 1
    TokenAnnotator Annotator(Style, Tokens.getKeywords());
d1751 1
a1751 2
    ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr,
                                  Whitespaces, Encoding,
d1866 2
a1867 1
    End = End.getLocWithOffset(Last.TokenText.size());
d1909 1
a1909 1
        if (Tok->is(TT_PointerOrReference)) {
d1921 2
a1922 1
          if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
d1924 2
a1925 2
          if (Tok->is(TT_TemplateCloser) &&
              Tok->Previous->is(TT_TemplateCloser))
d1961 1
a1961 1
  FileID ID;
d1975 5
a1979 6
                               ArrayRef<CharSourceRange> Ranges) {
  if (Style.DisableFormat)
    return tooling::Replacements();
  return reformat(Style, SourceMgr,
                  SourceMgr.getFileID(Lex.getSourceLocation()), Ranges);
}
d1981 1
a1981 6
tooling::Replacements reformat(const FormatStyle &Style,
                               SourceManager &SourceMgr, FileID ID,
                               ArrayRef<CharSourceRange> Ranges) {
  if (Style.DisableFormat)
    return tooling::Replacements();
  Formatter formatter(Style, SourceMgr, ID, Ranges);
d1986 1
a1986 1
                               ArrayRef<tooling::Range> Ranges,
a1987 3
  if (Style.DisableFormat)
    return tooling::Replacements();

d1993 1
a1993 2
  std::unique_ptr<llvm::MemoryBuffer> Buf =
      llvm::MemoryBuffer::getMemBuffer(Code, FileName);
d1996 1
a1996 1
  SourceMgr.overrideFileContents(Entry, std::move(Buf));
d1999 2
d2003 3
a2005 3
  for (const tooling::Range &Range : Ranges) {
    SourceLocation Start = StartOfFile.getLocWithOffset(Range.getOffset());
    SourceLocation End = Start.getLocWithOffset(Range.getLength());
d2008 1
a2008 1
  return reformat(Style, SourceMgr, ID, CharRanges);
d2011 1
a2011 1
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
d2014 2
a2015 2
  LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
d2017 1
a2017 3
  bool AlternativeOperators = Style.Language != FormatStyle::LK_JavaScript &&
                              Style.Language != FormatStyle::LK_Java;
  LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
d2036 1
a2036 3
  if (FileName.endswith(".java")) {
    return FormatStyle::LK_Java;
  } else if (FileName.endswith_lower(".js")) {
@


1.1.1.7
log
@Import Clang 3.6RC1 r227398.
@
text
@a17 1
#include "UnwrappedLineFormatter.h"
a43 1
    IO.enumCase(Value, "Java", FormatStyle::LK_Java);
a75 11
    IO.enumCase(Value, "Empty", FormatStyle::SFS_Empty);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::BinaryOperatorStyle> {
  static void enumeration(IO &IO, FormatStyle::BinaryOperatorStyle &Value) {
    IO.enumCase(Value, "All", FormatStyle::BOS_All);
    IO.enumCase(Value, "true", FormatStyle::BOS_All);
    IO.enumCase(Value, "None", FormatStyle::BOS_None);
    IO.enumCase(Value, "false", FormatStyle::BOS_None);
    IO.enumCase(Value, "NonAssignment", FormatStyle::BOS_NonAssignment);
d162 2
a163 1
    IO.mapOptional("AlignAfterOpenBracket", Style.AlignAfterOpenBracket);
a164 1
    IO.mapOptional("AlignOperands", Style.AlignOperands);
a169 2
    IO.mapOptional("AllowShortCaseLabelsOnASingleLine",
                   Style.AllowShortCaseLabelsOnASingleLine);
a188 1
    IO.mapOptional("BinPackArguments", Style.BinPackArguments);
a191 2
    IO.mapOptional("ConstructorInitializerIndentWidth",
                   Style.ConstructorInitializerIndentWidth);
a203 1
    IO.mapOptional("ObjCBlockIndentWidth", Style.ObjCBlockIndentWidth);
a225 1
    IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
a229 1
    IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
a309 2
  LLVMStyle.AlignAfterOpenBracket = true;
  LLVMStyle.AlignOperands = true;
a313 1
  LLVMStyle.AllowShortCaseLabelsOnASingleLine = false;
d320 1
a320 2
  LLVMStyle.BinPackArguments = true;
  LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
a341 1
  LLVMStyle.ObjCBlockIndentWidth = 2;
a348 1
  LLVMStyle.SpacesInSquareBrackets = false;
a351 1
  LLVMStyle.SpaceAfterCStyleCast = false;
d391 1
a391 12
  if (Language == FormatStyle::LK_Java) {
    GoogleStyle.AlignAfterOpenBracket = false;
    GoogleStyle.AlignOperands = false;
    GoogleStyle.AlignTrailingComments = false;
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
    GoogleStyle.AllowShortIfStatementsOnASingleLine = false;
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
    GoogleStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment;
    GoogleStyle.ColumnLimit = 100;
    GoogleStyle.SpaceAfterCStyleCast = true;
    GoogleStyle.SpacesBeforeTrailingComments = 1;
  } else if (Language == FormatStyle::LK_JavaScript) {
a394 2
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
d405 7
a411 12
  if (Language == FormatStyle::LK_Java) {
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = true;
    ChromiumStyle.IndentWidth = 4;
    ChromiumStyle.ContinuationIndentWidth = 8;
  } else {
    ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
    ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
    ChromiumStyle.AllowShortLoopsOnASingleLine = false;
    ChromiumStyle.BinPackParameters = false;
    ChromiumStyle.DerivePointerAlignment = false;
  }
a432 2
  Style.AlignAfterOpenBracket = false;
  Style.AlignOperands = false;
d434 1
a434 1
  Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
a440 1
  Style.ObjCBlockIndentWidth = 4;
d450 1
a450 1
  Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All;
d549 721
d1272 1
a1272 1
  FormatTokenLexer(SourceManager &SourceMgr, FileID ID, FormatStyle &Style,
d1275 4
a1278 7
        Column(0), TrailingWhitespace(0), SourceMgr(SourceMgr), ID(ID),
        Style(Style), IdentTable(getFormattingLangOpts(Style)),
        Keywords(IdentTable), Encoding(Encoding), FirstInLineIndex(0),
        FormattingDisabled(false) {
    Lex.reset(new Lexer(ID, SourceMgr.getBuffer(ID), SourceMgr,
                        getFormattingLangOpts(Style)));
    Lex->SetKeepWhitespaceMode(true);
d1297 1
a1297 1
  const AdditionalKeywords &getKeywords() { return Keywords; }
d1307 2
a1310 2
      if (tryMergeEscapeSequence())
        return;
d1358 2
a1359 1
    if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\")
d1361 1
a1361 1
    ++Previous->ColumnWidth;
d1363 2
a1364 2
    Previous->TokenText = StringRef(Text.data(), Text.size() + 1);
    resetLexer(SourceMgr.getFileOffset(Tokens.back()->Tok.getLocation()) + 1);
a1365 1
    Column = Previous->OriginalColumn + Previous->ColumnWidth;
d1375 3
a1377 12
    if (Tokens.size() < 2)
      return false;
    // If a regex literal ends in "\//", this gets represented by an unknown
    // token "\" and a comment.
    bool MightEndWithEscapedSlash =
        Tokens.back()->is(tok::comment) &&
        Tokens.back()->TokenText.startswith("//") &&
        Tokens[Tokens.size() - 2]->TokenText == "\\";
    if (!MightEndWithEscapedSlash &&
        (Tokens.back()->isNot(tok::slash) ||
         (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
          Tokens[Tokens.size() - 2]->TokenText == "\\")))
a1387 6
        if (MightEndWithEscapedSlash) {
          // This regex literal ends in '\//'. Skip past the '//' of the last
          // token and re-start lexing from there.
          SourceLocation Loc = Tokens.back()->Tok.getLocation();
          resetLexer(SourceMgr.getFileOffset(Loc) + 2);
        }
d1551 1
d1563 1
a1563 1
      if (FormatTok->is(TT_ImplicitStringLiteral))
a1596 5
      if (Style.Language == FormatStyle::LK_Java &&
          FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete)) {
        FormatTok->Tok.setKind(tok::identifier);
        FormatTok->Tok.setIdentifierInfo(nullptr);
      }
d1640 1
a1640 1
  std::unique_ptr<Lexer> Lex;
a1641 1
  FileID ID;
a1643 1
  AdditionalKeywords Keywords;
d1654 1
a1654 1
    Lex->LexFromRawLexer(Tok.Tok);
d1668 1
a1668 3

    if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format on" ||
                                 Tok.TokenText == "/* clang-format on */")) {
a1669 2
    }

d1671 1
a1671 3

    if (Tok.is(tok::comment) && (Tok.TokenText == "// clang-format off" ||
                                 Tok.TokenText == "/* clang-format off */")) {
a1672 9
    }
  }

  void resetLexer(unsigned Offset) {
    StringRef Buffer = SourceMgr.getBufferData(ID);
    Lex.reset(new Lexer(SourceMgr.getLocForStartOfFile(ID),
                        getFormattingLangOpts(Style), Buffer.begin(),
                        Buffer.begin() + Offset, Buffer.end()));
    Lex->SetKeepWhitespaceMode(true);
a1679 2
  case FormatStyle::LK_Java:
    return "Java";
d1691 4
a1694 5
  Formatter(const FormatStyle &Style, SourceManager &SourceMgr, FileID ID,
            ArrayRef<CharSourceRange> Ranges)
      : Style(Style), ID(ID), SourceMgr(SourceMgr),
        Whitespaces(SourceMgr, Style,
                    inputUsesCRLF(SourceMgr.getBufferData(ID))),
d1696 1
a1696 1
        Encoding(encoding::detectEncoding(SourceMgr.getBufferData(ID))) {
d1707 1
a1707 1
    FormatTokenLexer Tokens(SourceMgr, ID, Style, Encoding);
d1709 1
a1709 2
    UnwrappedLineParser Parser(Style, Tokens.getKeywords(), Tokens.lex(),
                               *this);
d1740 1
a1740 1
    TokenAnnotator Annotator(Style, Tokens.getKeywords());
d1751 1
a1751 2
    ContinuationIndenter Indenter(Style, Tokens.getKeywords(), SourceMgr,
                                  Whitespaces, Encoding,
d1866 2
a1867 1
    End = End.getLocWithOffset(Last.TokenText.size());
d1909 1
a1909 1
        if (Tok->is(TT_PointerOrReference)) {
d1921 2
a1922 1
          if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
d1924 2
a1925 2
          if (Tok->is(TT_TemplateCloser) &&
              Tok->Previous->is(TT_TemplateCloser))
d1961 1
a1961 1
  FileID ID;
d1975 5
a1979 6
                               ArrayRef<CharSourceRange> Ranges) {
  if (Style.DisableFormat)
    return tooling::Replacements();
  return reformat(Style, SourceMgr,
                  SourceMgr.getFileID(Lex.getSourceLocation()), Ranges);
}
d1981 1
a1981 6
tooling::Replacements reformat(const FormatStyle &Style,
                               SourceManager &SourceMgr, FileID ID,
                               ArrayRef<CharSourceRange> Ranges) {
  if (Style.DisableFormat)
    return tooling::Replacements();
  Formatter formatter(Style, SourceMgr, ID, Ranges);
d1986 1
a1986 1
                               ArrayRef<tooling::Range> Ranges,
a1987 3
  if (Style.DisableFormat)
    return tooling::Replacements();

d1993 1
a1993 2
  std::unique_ptr<llvm::MemoryBuffer> Buf =
      llvm::MemoryBuffer::getMemBuffer(Code, FileName);
d1996 1
a1996 1
  SourceMgr.overrideFileContents(Entry, std::move(Buf));
d1999 2
d2003 3
a2005 3
  for (const tooling::Range &Range : Ranges) {
    SourceLocation Start = StartOfFile.getLocWithOffset(Range.getOffset());
    SourceLocation End = Start.getLocWithOffset(Range.getLength());
d2008 1
a2008 1
  return reformat(Style, SourceMgr, ID, CharRanges);
d2011 1
a2011 1
LangOptions getFormattingLangOpts(const FormatStyle &Style) {
d2014 2
a2015 2
  LangOpts.CPlusPlus11 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.CPlusPlus14 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
d2017 1
a2017 3
  bool AlternativeOperators = Style.Language != FormatStyle::LK_JavaScript &&
                              Style.Language != FormatStyle::LK_Java;
  LangOpts.CXXOperatorNames = AlternativeOperators ? 1 : 0;
d2036 1
a2036 3
  if (FileName.endswith(".java")) {
    return FormatStyle::LK_Java;
  } else if (FileName.endswith_lower(".js")) {
@


1.1.1.8
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a15 1
#include "clang/Format/Format.h"
d24 1
a29 1
#include "llvm/Support/Regex.h"
a38 1
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::IncludeCategory)
a47 1
    IO.enumCase(Value, "TableGen", FormatStyle::LK_TableGen);
a95 1
    IO.enumCase(Value, "Mozilla", FormatStyle::BS_Mozilla);
a98 28
    IO.enumCase(Value, "WebKit", FormatStyle::BS_WebKit);
    IO.enumCase(Value, "Custom", FormatStyle::BS_Custom);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
  static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::RTBS_None);
    IO.enumCase(Value, "All", FormatStyle::RTBS_All);
    IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
    IO.enumCase(Value, "TopLevelDefinitions",
                FormatStyle::RTBS_TopLevelDefinitions);
    IO.enumCase(Value, "AllDefinitions", FormatStyle::RTBS_AllDefinitions);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
  static void
  enumeration(IO &IO, FormatStyle::DefinitionReturnTypeBreakingStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::DRTBS_None);
    IO.enumCase(Value, "All", FormatStyle::DRTBS_All);
    IO.enumCase(Value, "TopLevel", FormatStyle::DRTBS_TopLevel);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::DRTBS_None);
    IO.enumCase(Value, "true", FormatStyle::DRTBS_All);
d112 4
a115 14
template <> struct ScalarEnumerationTraits<FormatStyle::BracketAlignmentStyle> {
  static void enumeration(IO &IO, FormatStyle::BracketAlignmentStyle &Value) {
    IO.enumCase(Value, "Align", FormatStyle::BAS_Align);
    IO.enumCase(Value, "DontAlign", FormatStyle::BAS_DontAlign);
    IO.enumCase(Value, "AlwaysBreak", FormatStyle::BAS_AlwaysBreak);

    // For backward compatibility.
    IO.enumCase(Value, "true", FormatStyle::BAS_Align);
    IO.enumCase(Value, "false", FormatStyle::BAS_DontAlign);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
  static void enumeration(IO &IO, FormatStyle::PointerAlignmentStyle &Value) {
d147 2
a148 2
      StringRef StylesArray[] = {"LLVM",    "Google", "Chromium",
                                 "Mozilla", "WebKit", "GNU"};
a173 10
    // For backward compatibility.
    if (!IO.outputting()) {
      IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
      IO.mapOptional("IndentFunctionDeclarationAfterType",
                     Style.IndentWrappedFunctionNames);
      IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
      IO.mapOptional("SpaceAfterControlStatementKeyword",
                     Style.SpaceBeforeParens);
    }

a175 4
    IO.mapOptional("AlignConsecutiveAssignments",
                   Style.AlignConsecutiveAssignments);
    IO.mapOptional("AlignConsecutiveDeclarations",
                   Style.AlignConsecutiveDeclarations);
a184 2
    IO.mapOptional("AllowShortFunctionsOnASingleLine",
                   Style.AllowShortFunctionsOnASingleLine);
d189 2
d193 2
a194 15
    IO.mapOptional("AlwaysBreakAfterReturnType",
                   Style.AlwaysBreakAfterReturnType);
    // If AlwaysBreakAfterDefinitionReturnType was specified but
    // AlwaysBreakAfterReturnType was not, initialize the latter from the
    // former for backwards compatibility.
    if (Style.AlwaysBreakAfterDefinitionReturnType != FormatStyle::DRTBS_None &&
        Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None) {
      if (Style.AlwaysBreakAfterDefinitionReturnType == FormatStyle::DRTBS_All)
        Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
      else if (Style.AlwaysBreakAfterDefinitionReturnType ==
               FormatStyle::DRTBS_TopLevel)
        Style.AlwaysBreakAfterReturnType =
            FormatStyle::RTBS_TopLevelDefinitions;
    }

a196 5
    IO.mapOptional("AlwaysBreakTemplateDeclarations",
                   Style.AlwaysBreakTemplateDeclarations);
    IO.mapOptional("BinPackArguments", Style.BinPackArguments);
    IO.mapOptional("BinPackParameters", Style.BinPackParameters);
    IO.mapOptional("BraceWrapping", Style.BraceWrapping);
a198 1
    IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
d203 2
a205 1
    IO.mapOptional("CommentPragmas", Style.CommentPragmas);
a209 2
    IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
    IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
a210 1
    IO.mapOptional("DisableFormat", Style.DisableFormat);
a212 2
    IO.mapOptional("ForEachMacros", Style.ForEachMacros);
    IO.mapOptional("IncludeCategories", Style.IncludeCategories);
a213 1
    IO.mapOptional("IndentWidth", Style.IndentWidth);
d216 3
a220 3
    IO.mapOptional("MacroBlockBegin", Style.MacroBlockBegin);
    IO.mapOptional("MacroBlockEnd", Style.MacroBlockEnd);
    IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
d229 1
a231 1
    IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
a235 7
    IO.mapOptional("ReflowComments", Style.ReflowComments);
    IO.mapOptional("SortIncludes", Style.SortIncludes);
    IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast);
    IO.mapOptional("SpaceBeforeAssignmentOperators",
                   Style.SpaceBeforeAssignmentOperators);
    IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
    IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
d238 8
d247 4
d253 5
a257 9
    IO.mapOptional("SpacesInCStyleCastParentheses",
                   Style.SpacesInCStyleCastParentheses);
    IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
    IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
    IO.mapOptional("Standard", Style.Standard);
    IO.mapOptional("TabWidth", Style.TabWidth);
    IO.mapOptional("UseTab", Style.UseTab);
  }
};
d259 9
a267 20
template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
  static void mapping(IO &IO, FormatStyle::BraceWrappingFlags &Wrapping) {
    IO.mapOptional("AfterClass", Wrapping.AfterClass);
    IO.mapOptional("AfterControlStatement", Wrapping.AfterControlStatement);
    IO.mapOptional("AfterEnum", Wrapping.AfterEnum);
    IO.mapOptional("AfterFunction", Wrapping.AfterFunction);
    IO.mapOptional("AfterNamespace", Wrapping.AfterNamespace);
    IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
    IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
    IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
    IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
    IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
    IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
  }
};

template <> struct MappingTraits<FormatStyle::IncludeCategory> {
  static void mapping(IO &IO, FormatStyle::IncludeCategory &Category) {
    IO.mapOptional("Regex", Category.Regex);
    IO.mapOptional("Priority", Category.Priority);
d276 1
a276 1
template <> struct DocumentListTraits<std::vector<FormatStyle>> {
d296 2
a297 2
} // namespace yaml
} // namespace llvm
a325 48
static FormatStyle expandPresets(const FormatStyle &Style) {
  if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
    return Style;
  FormatStyle Expanded = Style;
  Expanded.BraceWrapping = {false, false, false, false, false, false,
                            false, false, false, false, false};
  switch (Style.BreakBeforeBraces) {
  case FormatStyle::BS_Linux:
    Expanded.BraceWrapping.AfterClass = true;
    Expanded.BraceWrapping.AfterFunction = true;
    Expanded.BraceWrapping.AfterNamespace = true;
    break;
  case FormatStyle::BS_Mozilla:
    Expanded.BraceWrapping.AfterClass = true;
    Expanded.BraceWrapping.AfterEnum = true;
    Expanded.BraceWrapping.AfterFunction = true;
    Expanded.BraceWrapping.AfterStruct = true;
    Expanded.BraceWrapping.AfterUnion = true;
    break;
  case FormatStyle::BS_Stroustrup:
    Expanded.BraceWrapping.AfterFunction = true;
    Expanded.BraceWrapping.BeforeCatch = true;
    Expanded.BraceWrapping.BeforeElse = true;
    break;
  case FormatStyle::BS_Allman:
    Expanded.BraceWrapping.AfterClass = true;
    Expanded.BraceWrapping.AfterControlStatement = true;
    Expanded.BraceWrapping.AfterEnum = true;
    Expanded.BraceWrapping.AfterFunction = true;
    Expanded.BraceWrapping.AfterNamespace = true;
    Expanded.BraceWrapping.AfterObjCDeclaration = true;
    Expanded.BraceWrapping.AfterStruct = true;
    Expanded.BraceWrapping.BeforeCatch = true;
    Expanded.BraceWrapping.BeforeElse = true;
    break;
  case FormatStyle::BS_GNU:
    Expanded.BraceWrapping = {true, true, true, true, true, true,
                              true, true, true, true, true};
    break;
  case FormatStyle::BS_WebKit:
    Expanded.BraceWrapping.AfterFunction = true;
    break;
  default:
    break;
  }
  return Expanded;
}

d331 1
a331 1
  LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
a333 2
  LLVMStyle.AlignConsecutiveAssignments = false;
  LLVMStyle.AlignConsecutiveDeclarations = false;
d340 1
a340 2
  LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
  LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
a347 2
  LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
                             false, false, false, false, false};
a348 1
  LLVMStyle.BreakAfterJavaFieldAnnotations = false;
a359 3
  LLVMStyle.IncludeCategories = {{"^\"(llvm|llvm-c|clang|clang-c)/", 2},
                                 {"^(<|\"(gtest|isl|json)/)", 3},
                                 {".*", 1}};
a373 1
  LLVMStyle.ReflowComments = true;
a391 1
  LLVMStyle.SortIncludes = true;
a407 1
  GoogleStyle.IncludeCategories = {{"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
d420 1
a420 1
    GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
a430 4
    GoogleStyle.AlignAfterOpenBracket = FormatStyle::BAS_AlwaysBreak;
    GoogleStyle.AlignOperands = false;
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
a431 1
    GoogleStyle.CommentPragmas = "@@(export|visibility) {";
d434 2
d448 1
a448 1
    ChromiumStyle.BreakAfterJavaFieldAnnotations = true;
a449 1
    ChromiumStyle.IndentWidth = 4;
a457 1
  ChromiumStyle.SortIncludes = false;
a463 10
  MozillaStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
  MozillaStyle.AlwaysBreakAfterReturnType =
      FormatStyle::RTBS_TopLevelDefinitions;
  MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
      FormatStyle::DRTBS_TopLevel;
  MozillaStyle.AlwaysBreakTemplateDeclarations = true;
  MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
  MozillaStyle.BreakConstructorInitializersBeforeComma = true;
  MozillaStyle.ConstructorInitializerIndentWidth = 2;
  MozillaStyle.ContinuationIndentWidth = 2;
d465 2
d472 1
d479 1
a479 1
  Style.AlignAfterOpenBracket = FormatStyle::BAS_DontAlign;
d483 1
a483 1
  Style.BreakBeforeBraces = FormatStyle::BS_WebKit;
d498 1
a498 2
  Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
  Style.AlwaysBreakAfterReturnType = FormatStyle::RTBS_AllDefinitions;
a511 1
  NoStyle.SortIncludes = false;
d591 1
a591 1
  FormatStyle NonConstStyle = expandPresets(Style);
d603 4
a606 6
        LessStashed(false), Column(0), TrailingWhitespace(0),
        SourceMgr(SourceMgr), ID(ID), Style(Style),
        IdentTable(getFormattingLangOpts(Style)), Keywords(IdentTable),
        Encoding(Encoding), FirstInLineIndex(0), FormattingDisabled(false),
        MacroBlockBeginRegex(Style.MacroBlockBegin),
        MacroBlockEndRegex(Style.MacroBlockEnd) {
a620 2
      if (Style.Language == FormatStyle::LK_JavaScript)
        tryParseJSRegexLiteral();
d622 1
a622 1
      if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
a635 2
    if (tryMergeLessLess())
      return;
d638 3
a640 1
      if (tryMergeTemplateString())
d643 8
a650 8
      static const tok::TokenKind JSIdentity[] = {tok::equalequal, tok::equal};
      static const tok::TokenKind JSNotIdentity[] = {tok::exclaimequal,
                                                     tok::equal};
      static const tok::TokenKind JSShiftEqual[] = {tok::greater, tok::greater,
                                                    tok::greaterequal};
      static const tok::TokenKind JSRightArrow[] = {tok::equal, tok::greater};
      // FIXME: Investigate what token type gives the correct operator priority.
      if (tryMergeTokens(JSIdentity, TT_BinaryOperator))
d652 1
a652 1
      if (tryMergeTokens(JSNotIdentity, TT_BinaryOperator))
d654 1
a654 1
      if (tryMergeTokens(JSShiftEqual, TT_BinaryOperator))
d656 1
a656 1
      if (tryMergeTokens(JSRightArrow, TT_JsFatArrow))
d661 1
a661 27
  bool tryMergeLessLess() {
    // Merge X,less,less,Y into X,lessless,Y unless X or Y is less.
    if (Tokens.size() < 3)
      return false;

    bool FourthTokenIsLess = false;
    if (Tokens.size() > 3)
      FourthTokenIsLess = (Tokens.end() - 4)[0]->is(tok::less);

    auto First = Tokens.end() - 3;
    if (First[2]->is(tok::less) || First[1]->isNot(tok::less) ||
        First[0]->isNot(tok::less) || FourthTokenIsLess)
      return false;

    // Only merge if there currently is no whitespace between the two "<".
    if (First[1]->WhitespaceRange.getBegin() !=
        First[1]->WhitespaceRange.getEnd())
      return false;

    First[0]->Tok.setKind(tok::lessless);
    First[0]->TokenText = "<<";
    First[0]->ColumnWidth += 1;
    Tokens.erase(Tokens.end() - 2);
    return true;
  }

  bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType) {
d671 2
a672 3
      if (!First[i]->is(Kinds[i]) ||
          First[i]->WhitespaceRange.getBegin() !=
              First[i]->WhitespaceRange.getEnd())
a679 1
    First[0]->Type = NewType;
d683 7
a689 29
  // Returns \c true if \p Tok can only be followed by an operand in JavaScript.
  bool precedesOperand(FormatToken *Tok) {
    // NB: This is not entirely correct, as an r_paren can introduce an operand
    // location in e.g. `if (foo) /bar/.exec(...);`. That is a rare enough
    // corner case to not matter in practice, though.
    return Tok->isOneOf(tok::period, tok::l_paren, tok::comma, tok::l_brace,
                        tok::r_brace, tok::l_square, tok::semi, tok::exclaim,
                        tok::colon, tok::question, tok::tilde) ||
           Tok->isOneOf(tok::kw_return, tok::kw_do, tok::kw_case, tok::kw_throw,
                        tok::kw_else, tok::kw_new, tok::kw_delete, tok::kw_void,
                        tok::kw_typeof, Keywords.kw_instanceof,
                        Keywords.kw_in) ||
           Tok->isBinaryOperator();
  }

  bool canPrecedeRegexLiteral(FormatToken *Prev) {
    if (!Prev)
      return true;

    // Regex literals can only follow after prefix unary operators, not after
    // postfix unary operators. If the '++' is followed by a non-operand
    // introducing token, the slash here is the operand and not the start of a
    // regex.
    if (Prev->isOneOf(tok::plusplus, tok::minusminus))
      return (Tokens.size() < 3 || precedesOperand(Tokens[Tokens.size() - 3]));

    // The previous token must introduce an operand location where regex
    // literals can occur.
    if (!precedesOperand(Prev))
d691 6
a696 1

d700 6
a705 60
  // Tries to parse a JavaScript Regex literal starting at the current token,
  // if that begins with a slash and is in a location where JavaScript allows
  // regex literals. Changes the current token to a regex literal and updates
  // its text if successful.
  void tryParseJSRegexLiteral() {
    FormatToken *RegexToken = Tokens.back();
    if (!RegexToken->isOneOf(tok::slash, tok::slashequal))
      return;

    FormatToken *Prev = nullptr;
    for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
      // NB: Because previous pointers are not initialized yet, this cannot use
      // Token.getPreviousNonComment.
      if ((*I)->isNot(tok::comment)) {
        Prev = *I;
        break;
      }
    }

    if (!canPrecedeRegexLiteral(Prev))
      return;

    // 'Manually' lex ahead in the current file buffer.
    const char *Offset = Lex->getBufferLocation();
    const char *RegexBegin = Offset - RegexToken->TokenText.size();
    StringRef Buffer = Lex->getBuffer();
    bool InCharacterClass = false;
    bool HaveClosingSlash = false;
    for (; !HaveClosingSlash && Offset != Buffer.end(); ++Offset) {
      // Regular expressions are terminated with a '/', which can only be
      // escaped using '\' or a character class between '[' and ']'.
      // See http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.5.
      switch (*Offset) {
      case '\\':
        // Skip the escaped character.
        ++Offset;
        break;
      case '[':
        InCharacterClass = true;
        break;
      case ']':
        InCharacterClass = false;
        break;
      case '/':
        if (!InCharacterClass)
          HaveClosingSlash = true;
        break;
      }
    }

    RegexToken->Type = TT_RegexLiteral;
    // Treat regex literals like other string_literals.
    RegexToken->Tok.setKind(tok::string_literal);
    RegexToken->TokenText = StringRef(RegexBegin, Offset - RegexBegin);
    RegexToken->ColumnWidth = RegexToken->TokenText.size();

    resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset)));
  }

  bool tryMergeTemplateString() {
d708 10
a717 12

    FormatToken *EndBacktick = Tokens.back();
    // Backticks get lexed as tok::unknown tokens. If a template string contains
    // a comment start, it gets lexed as a tok::comment, or tok::unknown if
    // unterminated.
    if (!EndBacktick->isOneOf(tok::comment, tok::string_literal,
                              tok::char_constant, tok::unknown))
      return false;
    size_t CommentBacktickPos = EndBacktick->TokenText.find('`');
    // Unknown token that's not actually a backtick, or a comment that doesn't
    // contain a backtick.
    if (CommentBacktickPos == StringRef::npos)
a718 1

d720 2
a721 4
    bool IsMultiline = false;
    unsigned EndColumnInFirstLine =
        EndBacktick->OriginalColumn + EndBacktick->ColumnWidth;
    for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; I++) {
d723 10
a732 19
      if (I[0]->IsMultiline)
        IsMultiline = true;

      // If there was a preceding template string, this must be the start of a
      // template string, not the end.
      if (I[0]->is(TT_TemplateString))
        return false;

      if (I[0]->isNot(tok::unknown) || I[0]->TokenText != "`") {
        // Keep track of the rhs offset of the last token to wrap across lines -
        // its the rhs offset of the first line of the template string, used to
        // determine its width.
        if (I[0]->IsMultiline)
          EndColumnInFirstLine = I[0]->OriginalColumn + I[0]->ColumnWidth;
        // If the token has newlines, the token before it (if it exists) is the
        // rhs end of the previous line.
        if (I[0]->NewlinesBefore > 0 && (I + 1 != E)) {
          EndColumnInFirstLine = I[1]->OriginalColumn + I[1]->ColumnWidth;
          IsMultiline = true;
d734 5
a738 1
        continue;
d741 3
a743 38
      Tokens.resize(Tokens.size() - TokenCount);
      Tokens.back()->Type = TT_TemplateString;
      const char *EndOffset =
          EndBacktick->TokenText.data() + 1 + CommentBacktickPos;
      if (CommentBacktickPos != 0) {
        // If the backtick was not the first character (e.g. in a comment),
        // re-lex after the backtick position.
        SourceLocation Loc = EndBacktick->Tok.getLocation();
        resetLexer(SourceMgr.getFileOffset(Loc) + CommentBacktickPos + 1);
      }
      Tokens.back()->TokenText =
          StringRef(Tokens.back()->TokenText.data(),
                    EndOffset - Tokens.back()->TokenText.data());

      unsigned EndOriginalColumn = EndBacktick->OriginalColumn;
      if (EndOriginalColumn == 0) {
        SourceLocation Loc = EndBacktick->Tok.getLocation();
        EndOriginalColumn = SourceMgr.getSpellingColumnNumber(Loc);
      }
      // If the ` is further down within the token (e.g. in a comment).
      EndOriginalColumn += CommentBacktickPos;

      if (IsMultiline) {
        // ColumnWidth is from backtick to last token in line.
        // LastLineColumnWidth is 0 to backtick.
        // x = `some content
        //     until here`;
        Tokens.back()->ColumnWidth =
            EndColumnInFirstLine - Tokens.back()->OriginalColumn;
        // +1 for the ` itself.
        Tokens.back()->LastLineColumnWidth = EndOriginalColumn + 1;
        Tokens.back()->IsMultiline = true;
      } else {
        // Token simply spans from start to end, +1 for the ` itself.
        Tokens.back()->ColumnWidth =
            EndOriginalColumn - Tokens.back()->OriginalColumn + 1;
      }
      return true;
a774 2
    String->NewlinesBefore = Macro->NewlinesBefore;
    String->HasUnescapedNewline = Macro->HasUnescapedNewline;
a844 19
  FormatToken *getStashedToken() {
    // Create a synthesized second '>' or '<' token.
    Token Tok = FormatTok->Tok;
    StringRef TokenText = FormatTok->TokenText;

    unsigned OriginalColumn = FormatTok->OriginalColumn;
    FormatTok = new (Allocator.Allocate()) FormatToken;
    FormatTok->Tok = Tok;
    SourceLocation TokLocation =
        FormatTok->Tok.getLocation().getLocWithOffset(Tok.getLength() - 1);
    FormatTok->Tok.setLocation(TokLocation);
    FormatTok->WhitespaceRange = SourceRange(TokLocation, TokLocation);
    FormatTok->TokenText = TokenText;
    FormatTok->ColumnWidth = 1;
    FormatTok->OriginalColumn = OriginalColumn + 1;

    return FormatTok;
  }

d847 11
d859 1
a859 5
      return getStashedToken();
    }
    if (LessStashed) {
      LessStashed = false;
      return getStashedToken();
d872 2
a873 16
      StringRef Text = FormatTok->TokenText;
      auto EscapesNewline = [&](int pos) {
        // A '\r' here is just part of '\r\n'. Skip it.
        if (pos >= 0 && Text[pos] == '\r')
          --pos;
        // See whether there is an odd number of '\' before this.
        unsigned count = 0;
        for (; pos >= 0; --pos, ++count)
          if (Text[pos] != '\\')
            break;
        return count & 1;
      };
      // FIXME: This miscounts tok:unknown tokens that are not just
      // whitespace, e.g. a '`' character.
      for (int i = 0, e = Text.size(); i != e; ++i) {
        switch (Text[i]) {
d876 6
a881 1
          FormatTok->HasUnescapedNewline = !EscapesNewline(i - 1);
a885 3
          FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
          Column = 0;
          break;
d897 2
a898 1
          if (i + 1 == e || (Text[i + 1] != '\r' && Text[i + 1] != '\n'))
d903 1
a905 2
        if (FormatTok->Type == TT_ImplicitStringLiteral)
          break;
a922 1
      FormatTok->LastNewlineOffset = 2;
d943 1
a943 7
          FormatTok->isOneOf(tok::kw_struct, tok::kw_union, tok::kw_delete,
                             tok::kw_operator)) {
        FormatTok->Tok.setKind(tok::identifier);
        FormatTok->Tok.setIdentifierInfo(nullptr);
      } else if (Style.Language == FormatStyle::LK_JavaScript &&
                 FormatTok->isOneOf(tok::kw_struct, tok::kw_union,
                                    tok::kw_operator)) {
a950 4
    } else if (FormatTok->Tok.is(tok::lessless)) {
      FormatTok->Tok.setKind(tok::less);
      FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
      LessStashed = true;
d978 3
a980 15
    if (Style.Language == FormatStyle::LK_Cpp) {
      if (!(Tokens.size() > 0 && Tokens.back()->Tok.getIdentifierInfo() &&
            Tokens.back()->Tok.getIdentifierInfo()->getPPKeywordID() ==
                tok::pp_define) &&
          std::find(ForEachMacros.begin(), ForEachMacros.end(),
                    FormatTok->Tok.getIdentifierInfo()) != ForEachMacros.end()) {
        FormatTok->Type = TT_ForEachMacro;
      } else if (FormatTok->is(tok::identifier)) {
        if (MacroBlockBeginRegex.match(Text)) {
          FormatTok->Type = TT_MacroBlockBegin;
        } else if (MacroBlockEndRegex.match(Text)) {
          FormatTok->Type = TT_MacroBlockEnd;
        }
      }
    }
d987 1
a987 1
  bool GreaterStashed, LessStashed;
a1004 3
  llvm::Regex MacroBlockBeginRegex;
  llvm::Regex MacroBlockEndRegex;

a1039 1
    TrailingWhitespace = 0;
d1075 1
a1075 1
  tooling::Replacements format(bool *IncompleteFormat) {
d1081 1
a1081 1
    Parser.parse();
d1091 1
a1091 1
          format(AnnotatedLines, Tokens, IncompleteFormat);
d1110 1
a1110 2
                               FormatTokenLexer &Tokens,
                               bool *IncompleteFormat) {
d1125 2
a1126 3
    UnwrappedLineFormatter(&Indenter, &Whitespaces, Style, Tokens.getKeywords(),
                           IncompleteFormat)
        .format(AnnotatedLines);
a1267 38
  bool
  hasCpp03IncompatibleFormat(const SmallVectorImpl<AnnotatedLine *> &Lines) {
    for (const AnnotatedLine* Line : Lines) {
      if (hasCpp03IncompatibleFormat(Line->Children))
        return true;
      for (FormatToken *Tok = Line->First->Next; Tok; Tok = Tok->Next) {
        if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
          if (Tok->is(tok::coloncolon) && Tok->Previous->is(TT_TemplateOpener))
            return true;
          if (Tok->is(TT_TemplateCloser) &&
              Tok->Previous->is(TT_TemplateCloser))
            return true;
        }
      }
    }
    return false;
  }

  int countVariableAlignments(const SmallVectorImpl<AnnotatedLine *> &Lines) {
    int AlignmentDiff = 0;
    for (const AnnotatedLine* Line : Lines) {
      AlignmentDiff += countVariableAlignments(Line->Children);
      for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
        if (!Tok->is(TT_PointerOrReference))
          continue;
        bool SpaceBefore =
            Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
        bool SpaceAfter = Tok->Next->WhitespaceRange.getBegin() !=
                          Tok->Next->WhitespaceRange.getEnd();
        if (SpaceBefore && !SpaceAfter)
          ++AlignmentDiff;
        if (!SpaceBefore && SpaceAfter)
          --AlignmentDiff;
      }
    }
    return AlignmentDiff;
  }

d1270 3
d1280 19
d1307 10
a1316 8
    if (Style.DerivePointerAlignment)
      Style.PointerAlignment = countVariableAlignments(AnnotatedLines) <= 0
                                   ? FormatStyle::PAS_Left
                                   : FormatStyle::PAS_Right;
    if (Style.Standard == FormatStyle::LS_Auto)
      Style.Standard = hasCpp03IncompatibleFormat(AnnotatedLines)
                           ? FormatStyle::LS_Cpp11
                           : FormatStyle::LS_Cpp03;
a1340 7
struct IncludeDirective {
  StringRef Filename;
  StringRef Text;
  unsigned Offset;
  int Category;
};

d1343 7
a1349 150
// Determines whether 'Ranges' intersects with ('Start', 'End').
static bool affectsRange(ArrayRef<tooling::Range> Ranges, unsigned Start,
                         unsigned End) {
  for (auto Range : Ranges) {
    if (Range.getOffset() < End &&
        Range.getOffset() + Range.getLength() > Start)
      return true;
  }
  return false;
}

// Sorts a block of includes given by 'Includes' alphabetically adding the
// necessary replacement to 'Replaces'. 'Includes' must be in strict source
// order.
static void sortIncludes(const FormatStyle &Style,
                         const SmallVectorImpl<IncludeDirective> &Includes,
                         ArrayRef<tooling::Range> Ranges, StringRef FileName,
                         tooling::Replacements &Replaces, unsigned *Cursor) {
  if (!affectsRange(Ranges, Includes.front().Offset,
                    Includes.back().Offset + Includes.back().Text.size()))
    return;
  SmallVector<unsigned, 16> Indices;
  for (unsigned i = 0, e = Includes.size(); i != e; ++i)
    Indices.push_back(i);
  std::sort(Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) {
    return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
           std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
  });

  // If the #includes are out of order, we generate a single replacement fixing
  // the entire block. Otherwise, no replacement is generated.
  bool OutOfOrder = false;
  for (unsigned i = 1, e = Indices.size(); i != e; ++i) {
    if (Indices[i] != i) {
      OutOfOrder = true;
      break;
    }
  }
  if (!OutOfOrder)
    return;

  std::string result;
  bool CursorMoved = false;
  for (unsigned Index : Indices) {
    if (!result.empty())
      result += "\n";
    result += Includes[Index].Text;

    if (Cursor && !CursorMoved) {
      unsigned Start = Includes[Index].Offset;
      unsigned End = Start + Includes[Index].Text.size();
      if (*Cursor >= Start && *Cursor < End) {
        *Cursor = Includes.front().Offset + result.size() + *Cursor - End;
        CursorMoved = true;
      }
    }
  }

  // Sorting #includes shouldn't change their total number of characters.
  // This would otherwise mess up 'Ranges'.
  assert(result.size() ==
         Includes.back().Offset + Includes.back().Text.size() -
             Includes.front().Offset);

  Replaces.insert(tooling::Replacement(FileName, Includes.front().Offset,
                                       result.size(), result));
}

tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
                                   ArrayRef<tooling::Range> Ranges,
                                   StringRef FileName, unsigned *Cursor) {
  tooling::Replacements Replaces;
  if (!Style.SortIncludes)
    return Replaces;

  unsigned Prev = 0;
  unsigned SearchFrom = 0;
  llvm::Regex IncludeRegex(
      R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))");
  SmallVector<StringRef, 4> Matches;
  SmallVector<IncludeDirective, 16> IncludesInBlock;

  // In compiled files, consider the first #include to be the main #include of
  // the file if it is not a system #include. This ensures that the header
  // doesn't have hidden dependencies
  // (http://llvm.org/docs/CodingStandards.html#include-style).
  //
  // FIXME: Do some sanity checking, e.g. edit distance of the base name, to fix
  // cases where the first #include is unlikely to be the main header.
  bool IsSource = FileName.endswith(".c") || FileName.endswith(".cc") ||
                  FileName.endswith(".cpp") || FileName.endswith(".c++") ||
                  FileName.endswith(".cxx") || FileName.endswith(".m") ||
                  FileName.endswith(".mm");
  StringRef FileStem = llvm::sys::path::stem(FileName);
  bool FirstIncludeBlock = true;
  bool MainIncludeFound = false;

  // Create pre-compiled regular expressions for the #include categories.
  SmallVector<llvm::Regex, 4> CategoryRegexs;
  for (const auto &Category : Style.IncludeCategories)
    CategoryRegexs.emplace_back(Category.Regex);

  bool FormattingOff = false;

  for (;;) {
    auto Pos = Code.find('\n', SearchFrom);
    StringRef Line =
        Code.substr(Prev, (Pos != StringRef::npos ? Pos : Code.size()) - Prev);

    StringRef Trimmed = Line.trim();
    if (Trimmed == "// clang-format off")
      FormattingOff = true;
    else if (Trimmed == "// clang-format on")
      FormattingOff = false;

    if (!FormattingOff && !Line.endswith("\\")) {
      if (IncludeRegex.match(Line, &Matches)) {
        StringRef IncludeName = Matches[2];
        int Category = INT_MAX;
        for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i) {
          if (CategoryRegexs[i].match(IncludeName)) {
            Category = Style.IncludeCategories[i].Priority;
            break;
          }
        }
        if (IsSource && !MainIncludeFound && Category > 0 &&
            FirstIncludeBlock && IncludeName.startswith("\"")) {
          StringRef HeaderStem =
              llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
          if (FileStem.startswith(HeaderStem)) {
            Category = 0;
            MainIncludeFound = true;
          }
        }
        IncludesInBlock.push_back({IncludeName, Line, Prev, Category});
      } else if (!IncludesInBlock.empty()) {
        sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
                     Cursor);
        IncludesInBlock.clear();
        FirstIncludeBlock = false;
      }
      Prev = Pos + 1;
    }
    if (Pos == StringRef::npos || Pos + 1 == Code.size())
      break;
    SearchFrom = Pos + 1;
  }
  if (!IncludesInBlock.empty())
    sortIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
  return Replaces;
d1354 2
a1355 4
                               ArrayRef<CharSourceRange> Ranges,
                               bool *IncompleteFormat) {
  FormatStyle Expanded = expandPresets(Style);
  if (Expanded.DisableFormat)
d1357 2
a1358 2
  Formatter formatter(Expanded, SourceMgr, ID, Ranges);
  return formatter.format(IncompleteFormat);
d1363 1
a1363 1
                               StringRef FileName, bool *IncompleteFormat) {
d1367 1
a1367 3
  IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
      new vfs::InMemoryFileSystem);
  FileManager Files(FileSystemOptions(), InMemoryFileSystem);
d1372 7
a1378 5
  InMemoryFileSystem->addFile(
      FileName, 0, llvm::MemoryBuffer::getMemBuffer(
                       Code, FileName, /*RequiresNullTerminator=*/false));
  FileID ID = SourceMgr.createFileID(Files.getFile(FileName), SourceLocation(),
                                     clang::SrcMgr::C_User);
d1386 1
a1386 1
  return reformat(Style, SourceMgr, ID, CharRanges, IncompleteFormat);
d1395 2
a1396 1
  bool AlternativeOperators = Style.Language == FormatStyle::LK_Cpp;
a1400 2
  LangOpts.MicrosoftExt = 1; // To get kw___try, kw___finally.
  LangOpts.DeclSpecKeyword = 1; // To get __declspec.
d1416 1
a1416 1
  if (FileName.endswith(".java"))
d1418 4
a1421 4
  if (FileName.endswith_lower(".js") || FileName.endswith_lower(".ts"))
    return FormatStyle::LK_JavaScript; // JavaScript or TypeScript.
  if (FileName.endswith_lower(".proto") ||
      FileName.endswith_lower(".protodevel"))
d1423 1
a1423 2
  if (FileName.endswith_lower(".td"))
    return FormatStyle::LK_TableGen;
d1501 2
@


1.1.1.8.2.1
log
@Sync with HEAD
@
text
@a16 1
#include "AffectedRangeManager.h"
a17 3
#include "FormatTokenLexer.h"
#include "SortJavaScriptImports.h"
#include "TokenAnalyzer.h"
a24 1
#include "clang/Basic/VirtualFileSystem.h"
d32 1
a32 2
#include <algorithm>
#include <memory>
a48 1
    IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
a70 10
    IO.enumCase(Value, "ForContinuationAndIndentation",
                FormatStyle::UT_ForContinuationAndIndentation);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
  static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
    IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
    IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
    IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
a277 3
    IO.mapOptional("BreakAfterJavaFieldAnnotations",
                   Style.BreakAfterJavaFieldAnnotations);
    IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
a291 1
    IO.mapOptional("IncludeIsMainRegex", Style.IncludeIsMainRegex);
a295 2
    IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
    IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
a318 1
    IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword);
d400 1
a400 1
const char *ParseErrorCategory::name() const noexcept {
d491 1
a492 2
  LLVMStyle.BreakConstructorInitializersBeforeComma = false;
  LLVMStyle.BreakStringLiterals = true;
a506 1
  LLVMStyle.IncludeIsMainRegex = "$";
a509 2
  LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
  LLVMStyle.JavaScriptWrapImports = true;
a520 1
  LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
a527 1
  LLVMStyle.SpaceAfterTemplateKeyword = true;
a557 1
  GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
d583 1
a583 1
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
d586 1
a586 2
    GoogleStyle.CommentPragmas =
        "(taze:|@@(export|requirecss|return|returns|see|visibility)) ";
a587 1
    GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
a588 2
    GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
    GoogleStyle.JavaScriptWrapImports = false;
a591 2
  } else if (Language == FormatStyle::LK_ObjC) {
    GoogleStyle.ColumnLimit = 100;
a603 3
  } else if (Language == FormatStyle::LK_JavaScript) {
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
    ChromiumStyle.AllowShortLoopsOnASingleLine = false;
d621 1
a621 1
      FormatStyle::RTBS_TopLevel;
a624 2
  MozillaStyle.BinPackParameters = false;
  MozillaStyle.BinPackArguments = false;
a634 1
  MozillaStyle.SpaceAfterTemplateKeyword = false;
d654 1
d762 1
a762 1
class JavaScriptRequoter : public TokenAnalyzer {
d764 33
a796 2
  JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style) {}
d798 172
a969 9
  tooling::Replacements
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
                                          AnnotatedLines.end());
    tooling::Replacements Result;
    requoteJSStringLiteral(AnnotatedLines, Result);
    return Result;
d972 43
a1014 8
private:
  // Replaces double/single-quoted string literal as appropriate, re-escaping
  // the contents in the process.
  void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
                              tooling::Replacements &Result) {
    for (AnnotatedLine *Line : Lines) {
      requoteJSStringLiteral(Line->Children, Result);
      if (!Line->Affected)
d1016 142
a1157 11
      for (FormatToken *FormatTok = Line->First; FormatTok;
           FormatTok = FormatTok->Next) {
        StringRef Input = FormatTok->TokenText;
        if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
            // NB: testing for not starting with a double quote to avoid
            // breaking `template strings`.
            (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
             !Input.startswith("\"")) ||
            (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
             !Input.startswith("\'")))
          continue;
d1159 48
a1206 32
        // Change start and end quote.
        bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
        SourceLocation Start = FormatTok->Tok.getLocation();
        auto Replace = [&](SourceLocation Start, unsigned Length,
                           StringRef ReplacementText) {
          auto Err = Result.add(tooling::Replacement(
              Env.getSourceManager(), Start, Length, ReplacementText));
          // FIXME: handle error. For now, print error message and skip the
          // replacement for release version.
          if (Err) {
            llvm::errs() << llvm::toString(std::move(Err)) << "\n";
            assert(false);
          }
        };
        Replace(Start, 1, IsSingle ? "'" : "\"");
        Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
                IsSingle ? "'" : "\"");

        // Escape internal quotes.
        bool Escaped = false;
        for (size_t i = 1; i < Input.size() - 1; i++) {
          switch (Input[i]) {
          case '\\':
            if (!Escaped && i + 1 < Input.size() &&
                ((IsSingle && Input[i + 1] == '"') ||
                 (!IsSingle && Input[i + 1] == '\''))) {
              // Remove this \, it's escaping a " or ' that no longer needs
              // escaping
              Replace(Start.getLocWithOffset(i), 1, "");
              continue;
            }
            Escaped = !Escaped;
d1208 131
a1338 12
          case '\"':
          case '\'':
            if (!Escaped && IsSingle == (Input[i] == '\'')) {
              // Escape the quote.
              Replace(Start.getLocWithOffset(i), 0, "\\");
            }
            Escaped = false;
            break;
          default:
            Escaped = false;
            break;
          }
d1342 78
d1421 1
a1421 1
};
d1423 1
a1423 1
class Formatter : public TokenAnalyzer {
d1425 16
a1440 8
  Formatter(const Environment &Env, const FormatStyle &Style,
            bool *IncompleteFormat)
      : TokenAnalyzer(Env, Style), IncompleteFormat(IncompleteFormat) {}

  tooling::Replacements
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
d1442 39
a1481 2
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
                                          AnnotatedLines.end());
d1485 2
d1488 2
a1489 6

    WhitespaceManager Whitespaces(
        Env.getSourceManager(), Style,
        inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID())));
    ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
                                  Env.getSourceManager(), Whitespaces, Encoding,
d1494 1
a1494 4
    for (const auto &R : Whitespaces.generateReplacements())
      if (Result.add(R))
        return Result;
    return Result;
d1498 132
d1637 1
a1637 1
    for (const AnnotatedLine *Line : Lines) {
d1655 1
a1655 1
    for (const AnnotatedLine *Line : Lines) {
d1702 3
a1704 51
  bool BinPackInconclusiveFunctions;
  bool *IncompleteFormat;
};

// This class clean up the erroneous/redundant code around the given ranges in
// file.
class Cleaner : public TokenAnalyzer {
public:
  Cleaner(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style),
        DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}

  // FIXME: eliminate unused parameters.
  tooling::Replacements
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    // FIXME: in the current implementation the granularity of affected range
    // is an annotated line. However, this is not sufficient. Furthermore,
    // redundant code introduced by replacements does not necessarily
    // intercept with ranges of replacements that result in the redundancy.
    // To determine if some redundant code is actually introduced by
    // replacements(e.g. deletions), we need to come up with a more
    // sophisticated way of computing affected ranges.
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
                                          AnnotatedLines.end());

    checkEmptyNamespace(AnnotatedLines);

    for (auto &Line : AnnotatedLines) {
      if (Line->Affected) {
        cleanupRight(Line->First, tok::comma, tok::comma);
        cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
        cleanupRight(Line->First, tok::l_paren, tok::comma);
        cleanupLeft(Line->First, tok::comma, tok::r_paren);
        cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
        cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
        cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
      }
    }

    return generateFixes();
  }

private:
  bool containsOnlyComments(const AnnotatedLine &Line) {
    for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) {
      if (Tok->isNot(tok::comment))
        return false;
    }
    return true;
d1707 2
a1708 18
  // Iterate through all lines and remove any empty (nested) namespaces.
  void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
    std::set<unsigned> DeletedLines;
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      auto &Line = *AnnotatedLines[i];
      if (Line.startsWith(tok::kw_namespace) ||
          Line.startsWith(tok::kw_inline, tok::kw_namespace)) {
        checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
      }
    }

    for (auto Line : DeletedLines) {
      FormatToken *Tok = AnnotatedLines[Line]->First;
      while (Tok) {
        deleteToken(Tok);
        Tok = Tok->Next;
      }
    }
d1711 6
a1716 22
  // The function checks if the namespace, which starts from \p CurrentLine, and
  // its nested namespaces are empty and delete them if they are empty. It also
  // sets \p NewLine to the last line checked.
  // Returns true if the current namespace is empty.
  bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                           unsigned CurrentLine, unsigned &NewLine,
                           std::set<unsigned> &DeletedLines) {
    unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
    if (Style.BraceWrapping.AfterNamespace) {
      // If the left brace is in a new line, we should consume it first so that
      // it does not make the namespace non-empty.
      // FIXME: error handling if there is no left brace.
      if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
        NewLine = CurrentLine;
        return false;
      }
    } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
      return false;
    }
    while (++CurrentLine < End) {
      if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
        break;
d1718 2
a1719 130
      if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
          AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
                                                  tok::kw_namespace)) {
        if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
                                 DeletedLines))
          return false;
        CurrentLine = NewLine;
        continue;
      }

      if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
        continue;

      // If there is anything other than comments or nested namespaces in the
      // current namespace, the namespace cannot be empty.
      NewLine = CurrentLine;
      return false;
    }

    NewLine = CurrentLine;
    if (CurrentLine >= End)
      return false;

    // Check if the empty namespace is actually affected by changed ranges.
    if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
            AnnotatedLines[InitLine]->First->Tok.getLocation(),
            AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
      return false;

    for (unsigned i = InitLine; i <= CurrentLine; ++i) {
      DeletedLines.insert(i);
    }

    return true;
  }

  // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
  // of the token in the pair if the left token has \p LK token kind and the
  // right token has \p RK token kind. If \p DeleteLeft is true, the left token
  // is deleted on match; otherwise, the right token is deleted.
  template <typename LeftKind, typename RightKind>
  void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
                   bool DeleteLeft) {
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
      for (auto *Res = Tok.Next; Res; Res = Res->Next)
        if (!Res->is(tok::comment) &&
            DeletedTokens.find(Res) == DeletedTokens.end())
          return Res;
      return nullptr;
    };
    for (auto *Left = Start; Left;) {
      auto *Right = NextNotDeleted(*Left);
      if (!Right)
        break;
      if (Left->is(LK) && Right->is(RK)) {
        deleteToken(DeleteLeft ? Left : Right);
        for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
          deleteToken(Tok);
        // If the right token is deleted, we should keep the left token
        // unchanged and pair it with the new right token.
        if (!DeleteLeft)
          continue;
      }
      Left = Right;
    }
  }

  template <typename LeftKind, typename RightKind>
  void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
  }

  template <typename LeftKind, typename RightKind>
  void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
  }

  // Delete the given token.
  inline void deleteToken(FormatToken *Tok) {
    if (Tok)
      DeletedTokens.insert(Tok);
  }

  tooling::Replacements generateFixes() {
    tooling::Replacements Fixes;
    std::vector<FormatToken *> Tokens;
    std::copy(DeletedTokens.begin(), DeletedTokens.end(),
              std::back_inserter(Tokens));

    // Merge multiple continuous token deletions into one big deletion so that
    // the number of replacements can be reduced. This makes computing affected
    // ranges more efficient when we run reformat on the changed code.
    unsigned Idx = 0;
    while (Idx < Tokens.size()) {
      unsigned St = Idx, End = Idx;
      while ((End + 1) < Tokens.size() &&
             Tokens[End]->Next == Tokens[End + 1]) {
        End++;
      }
      auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
                                              Tokens[End]->Tok.getEndLoc());
      auto Err =
          Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
      // FIXME: better error handling. for now just print error message and skip
      // for the release version.
      if (Err) {
        llvm::errs() << llvm::toString(std::move(Err)) << "\n";
        assert(false && "Fixes must not conflict!");
      }
      Idx = End + 1;
    }

    return Fixes;
  }

  // Class for less-than inequality comparason for the set `RedundantTokens`.
  // We store tokens in the order they appear in the translation unit so that
  // we do not need to sort them in `generateFixes()`.
  struct FormatTokenLess {
    FormatTokenLess(const SourceManager &SM) : SM(SM) {}

    bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
      return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
                                          RHS->Tok.getLocation());
    }
    const SourceManager &SM;
  };

  // Tokens to be deleted.
  std::set<FormatToken *, FormatTokenLess> DeletedTokens;
d1742 9
a1750 44
// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
// before sorting/deduplicating. Index is the index of the include under the
// cursor in the original set of includes. If this include has duplicates, it is
// the index of the first of the duplicates as the others are going to be
// removed. OffsetToEOL describes the cursor's position relative to the end of
// its current line.
// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
static std::pair<unsigned, unsigned>
FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
                const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
  unsigned CursorIndex = UINT_MAX;
  unsigned OffsetToEOL = 0;
  for (int i = 0, e = Includes.size(); i != e; ++i) {
    unsigned Start = Includes[Indices[i]].Offset;
    unsigned End = Start + Includes[Indices[i]].Text.size();
    if (!(Cursor >= Start && Cursor < End))
      continue;
    CursorIndex = Indices[i];
    OffsetToEOL = End - Cursor;
    // Put the cursor on the only remaining #include among the duplicate
    // #includes.
    while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
      CursorIndex = i;
    break;
  }
  return std::make_pair(CursorIndex, OffsetToEOL);
}

// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
// source order.
// #include directives with the same text will be deduplicated, and only the
// first #include in the duplicate #includes remains. If the `Cursor` is
// provided and put on a deleted #include, it will be moved to the remaining
// #include in the duplicate #includes.
static void sortCppIncludes(const FormatStyle &Style,
                            const SmallVectorImpl<IncludeDirective> &Includes,
                            ArrayRef<tooling::Range> Ranges, StringRef FileName,
                            tooling::Replacements &Replaces, unsigned *Cursor) {
  unsigned IncludesBeginOffset = Includes.front().Offset;
  unsigned IncludesEndOffset =
      Includes.back().Offset + Includes.back().Text.size();
  unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
  if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
d1755 4
a1758 20
  std::stable_sort(
      Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) {
        return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
               std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
      });
  // The index of the include on which the cursor will be put after
  // sorting/deduplicating.
  unsigned CursorIndex;
  // The offset from cursor to the end of line.
  unsigned CursorToEOLOffset;
  if (Cursor)
    std::tie(CursorIndex, CursorToEOLOffset) =
        FindCursorIndex(Includes, Indices, *Cursor);

  // Deduplicate #includes.
  Indices.erase(std::unique(Indices.begin(), Indices.end(),
                            [&](unsigned LHSI, unsigned RHSI) {
                              return Includes[LHSI].Text == Includes[RHSI].Text;
                            }),
                Indices.end());
d1762 8
a1769 2
  if (Indices.size() == Includes.size() &&
      std::is_sorted(Indices.begin(), Indices.end()))
d1773 1
a1777 15
    if (Cursor && CursorIndex == Index)
      *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
  }

  auto Err = Replaces.add(tooling::Replacement(
      FileName, Includes.front().Offset, IncludesBlockSize, result));
  // FIXME: better error handling. For now, just skip the replacement for the
  // release version.
  if (Err) {
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
    assert(false);
  }
}

namespace {
d1779 6
a1784 24
// This class manages priorities of #include categories and calculates
// priorities for headers.
class IncludeCategoryManager {
public:
  IncludeCategoryManager(const FormatStyle &Style, StringRef FileName)
      : Style(Style), FileName(FileName) {
    FileStem = llvm::sys::path::stem(FileName);
    for (const auto &Category : Style.IncludeCategories)
      CategoryRegexs.emplace_back(Category.Regex);
    IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
                 FileName.endswith(".cpp") || FileName.endswith(".c++") ||
                 FileName.endswith(".cxx") || FileName.endswith(".m") ||
                 FileName.endswith(".mm");
  }

  // Returns the priority of the category which \p IncludeName belongs to.
  // If \p CheckMainHeader is true and \p IncludeName is a main header, returns
  // 0. Otherwise, returns the priority of the matching category or INT_MAX.
  int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) {
    int Ret = INT_MAX;
    for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
      if (CategoryRegexs[i].match(IncludeName)) {
        Ret = Style.IncludeCategories[i].Priority;
        break;
a1785 16
    if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
      Ret = 0;
    return Ret;
  }

private:
  bool isMainHeader(StringRef IncludeName) const {
    if (!IncludeName.startswith("\""))
      return false;
    StringRef HeaderStem =
        llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
    if (FileStem.startswith(HeaderStem)) {
      llvm::Regex MainIncludeRegex(
          (HeaderStem + Style.IncludeIsMainRegex).str());
      if (MainIncludeRegex.match(FileStem))
        return true;
a1786 1
    return false;
d1789 5
a1793 6
  const FormatStyle &Style;
  bool IsMainFile;
  StringRef FileName;
  StringRef FileStem;
  SmallVector<llvm::Regex, 4> CategoryRegexs;
};
d1795 3
a1797 2
const char IncludeRegexPattern[] =
    R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
d1799 6
a1804 1
} // anonymous namespace
a1805 5
tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
                                      ArrayRef<tooling::Range> Ranges,
                                      StringRef FileName,
                                      tooling::Replacements &Replaces,
                                      unsigned *Cursor) {
d1808 2
a1809 1
  llvm::Regex IncludeRegex(IncludeRegexPattern);
d1820 5
a1824 1
  IncludeCategoryManager Categories(Style, FileName);
d1827 6
d1849 16
a1864 5
        int Category = Categories.getIncludePriority(
            IncludeName,
            /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
        if (Category == 0)
          MainIncludeFound = true;
d1867 2
a1868 2
        sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
                        Cursor);
d1879 1
a1879 1
    sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
d1883 6
a1888 18
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
                                   ArrayRef<tooling::Range> Ranges,
                                   StringRef FileName, unsigned *Cursor) {
  tooling::Replacements Replaces;
  if (!Style.SortIncludes)
    return Replaces;
  if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
    return sortJavaScriptImports(Style, Code, Ranges, FileName);
  sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
  return Replaces;
}

template <typename T>
static llvm::Expected<tooling::Replacements>
processReplacements(T ProcessFunc, StringRef Code,
                    const tooling::Replacements &Replaces,
                    const FormatStyle &Style) {
  if (Replaces.empty())
d1890 2
a1891 324

  auto NewCode = applyAllReplacements(Code, Replaces);
  if (!NewCode)
    return NewCode.takeError();
  std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
  StringRef FileName = Replaces.begin()->getFilePath();

  tooling::Replacements FormatReplaces =
      ProcessFunc(Style, *NewCode, ChangedRanges, FileName);

  return Replaces.merge(FormatReplaces);
}

llvm::Expected<tooling::Replacements>
formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
                   const FormatStyle &Style) {
  // We need to use lambda function here since there are two versions of
  // `sortIncludes`.
  auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
                         std::vector<tooling::Range> Ranges,
                         StringRef FileName) -> tooling::Replacements {
    return sortIncludes(Style, Code, Ranges, FileName);
  };
  auto SortedReplaces =
      processReplacements(SortIncludes, Code, Replaces, Style);
  if (!SortedReplaces)
    return SortedReplaces.takeError();

  // We need to use lambda function here since there are two versions of
  // `reformat`.
  auto Reformat = [](const FormatStyle &Style, StringRef Code,
                     std::vector<tooling::Range> Ranges,
                     StringRef FileName) -> tooling::Replacements {
    return reformat(Style, Code, Ranges, FileName);
  };
  return processReplacements(Reformat, Code, *SortedReplaces, Style);
}

namespace {

inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
  return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
         llvm::Regex(IncludeRegexPattern).match(Replace.getReplacementText());
}

inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
  return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
}

// Returns the offset after skipping a sequence of tokens, matched by \p
// GetOffsetAfterSequence, from the start of the code.
// \p GetOffsetAfterSequence should be a function that matches a sequence of
// tokens and returns an offset after the sequence.
unsigned getOffsetAfterTokenSequence(
    StringRef FileName, StringRef Code, const FormatStyle &Style,
    std::function<unsigned(const SourceManager &, Lexer &, Token &)>
        GetOffsetAfterSequense) {
  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{});
  const SourceManager &SourceMgr = Env->getSourceManager();
  Lexer Lex(Env->getFileID(), SourceMgr.getBuffer(Env->getFileID()), SourceMgr,
            getFormattingLangOpts(Style));
  Token Tok;
  // Get the first token.
  Lex.LexFromRawLexer(Tok);
  return GetOffsetAfterSequense(SourceMgr, Lex, Tok);
}

// Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is,
// \p Tok will be the token after this directive; otherwise, it can be any token
// after the given \p Tok (including \p Tok).
bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &Tok) {
  bool Matched = Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
                 Tok.is(tok::raw_identifier) &&
                 Tok.getRawIdentifier() == Name && !Lex.LexFromRawLexer(Tok) &&
                 Tok.is(tok::raw_identifier);
  if (Matched)
    Lex.LexFromRawLexer(Tok);
  return Matched;
}

void skipComments(Lexer &Lex, Token &Tok) {
  while (Tok.is(tok::comment))
    if (Lex.LexFromRawLexer(Tok))
      return;
}

// Returns the offset after header guard directives and any comments
// before/after header guards. If no header guard presents in the code, this
// will returns the offset after skipping all comments from the start of the
// code.
unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName,
                                               StringRef Code,
                                               const FormatStyle &Style) {
  return getOffsetAfterTokenSequence(
      FileName, Code, Style,
      [](const SourceManager &SM, Lexer &Lex, Token Tok) {
        skipComments(Lex, Tok);
        unsigned InitialOffset = SM.getFileOffset(Tok.getLocation());
        if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) {
          skipComments(Lex, Tok);
          if (checkAndConsumeDirectiveWithName(Lex, "define", Tok))
            return SM.getFileOffset(Tok.getLocation());
        }
        return InitialOffset;
      });
}

// Check if a sequence of tokens is like
//    "#include ("header.h" | <header.h>)".
// If it is, \p Tok will be the token after this directive; otherwise, it can be
// any token after the given \p Tok (including \p Tok).
bool checkAndConsumeInclusiveDirective(Lexer &Lex, Token &Tok) {
  auto Matched = [&]() {
    Lex.LexFromRawLexer(Tok);
    return true;
  };
  if (Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
      Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "include") {
    if (Lex.LexFromRawLexer(Tok))
      return false;
    if (Tok.is(tok::string_literal))
      return Matched();
    if (Tok.is(tok::less)) {
      while (!Lex.LexFromRawLexer(Tok) && Tok.isNot(tok::greater)) {
      }
      if (Tok.is(tok::greater))
        return Matched();
    }
  }
  return false;
}

// Returns the offset of the last #include directive after which a new
// #include can be inserted. This ignores #include's after the #include block(s)
// in the beginning of a file to avoid inserting headers into code sections
// where new #include's should not be added by default.
// These code sections include:
//      - raw string literals (containing #include).
//      - #if blocks.
//      - Special #include's among declarations (e.g. functions).
//
// If no #include after which a new #include can be inserted, this returns the
// offset after skipping all comments from the start of the code.
// Inserting after an #include is not allowed if it comes after code that is not
// #include (e.g. pre-processing directive that is not #include, declarations).
unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code,
                                     const FormatStyle &Style) {
  return getOffsetAfterTokenSequence(
      FileName, Code, Style,
      [](const SourceManager &SM, Lexer &Lex, Token Tok) {
        skipComments(Lex, Tok);
        unsigned MaxOffset = SM.getFileOffset(Tok.getLocation());
        while (checkAndConsumeInclusiveDirective(Lex, Tok))
          MaxOffset = SM.getFileOffset(Tok.getLocation());
        return MaxOffset;
      });
}

bool isDeletedHeader(llvm::StringRef HeaderName,
                     const std::set<llvm::StringRef> &HeadersToDelete) {
  return HeadersToDelete.count(HeaderName) ||
         HeadersToDelete.count(HeaderName.trim("\"<>"));
}

// FIXME: insert empty lines between newly created blocks.
tooling::Replacements
fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
                        const FormatStyle &Style) {
  if (Style.Language != FormatStyle::LanguageKind::LK_Cpp)
    return Replaces;

  tooling::Replacements HeaderInsertions;
  std::set<llvm::StringRef> HeadersToDelete;
  tooling::Replacements Result;
  for (const auto &R : Replaces) {
    if (isHeaderInsertion(R)) {
      // Replacements from \p Replaces must be conflict-free already, so we can
      // simply consume the error.
      llvm::consumeError(HeaderInsertions.add(R));
    } else if (isHeaderDeletion(R)) {
      HeadersToDelete.insert(R.getReplacementText());
    } else if (R.getOffset() == UINT_MAX) {
      llvm::errs() << "Insertions other than header #include insertion are "
                      "not supported! "
                   << R.getReplacementText() << "\n";
    } else {
      llvm::consumeError(Result.add(R));
    }
  }
  if (HeaderInsertions.empty() && HeadersToDelete.empty())
    return Replaces;

  llvm::Regex IncludeRegex(IncludeRegexPattern);
  llvm::Regex DefineRegex(R"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)");
  SmallVector<StringRef, 4> Matches;

  StringRef FileName = Replaces.begin()->getFilePath();
  IncludeCategoryManager Categories(Style, FileName);

  // Record the offset of the end of the last include in each category.
  std::map<int, int> CategoryEndOffsets;
  // All possible priorities.
  // Add 0 for main header and INT_MAX for headers that are not in any category.
  std::set<int> Priorities = {0, INT_MAX};
  for (const auto &Category : Style.IncludeCategories)
    Priorities.insert(Category.Priority);
  int FirstIncludeOffset = -1;
  // All new headers should be inserted after this offset.
  unsigned MinInsertOffset =
      getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style);
  StringRef TrimmedCode = Code.drop_front(MinInsertOffset);
  // Max insertion offset in the original code.
  unsigned MaxInsertOffset =
      MinInsertOffset +
      getMaxHeaderInsertionOffset(FileName, TrimmedCode, Style);
  SmallVector<StringRef, 32> Lines;
  TrimmedCode.split(Lines, '\n');
  unsigned Offset = MinInsertOffset;
  unsigned NextLineOffset;
  std::set<StringRef> ExistingIncludes;
  for (auto Line : Lines) {
    NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1);
    if (IncludeRegex.match(Line, &Matches)) {
      // The header name with quotes or angle brackets.
      StringRef IncludeName = Matches[2];
      ExistingIncludes.insert(IncludeName);
      // Only record the offset of current #include if we can insert after it.
      if (Offset <= MaxInsertOffset) {
        int Category = Categories.getIncludePriority(
            IncludeName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
        CategoryEndOffsets[Category] = NextLineOffset;
        if (FirstIncludeOffset < 0)
          FirstIncludeOffset = Offset;
      }
      if (isDeletedHeader(IncludeName, HeadersToDelete)) {
        // If this is the last line without trailing newline, we need to make
        // sure we don't delete across the file boundary.
        unsigned Length = std::min(Line.size() + 1, Code.size() - Offset);
        llvm::Error Err =
            Result.add(tooling::Replacement(FileName, Offset, Length, ""));
        if (Err) {
          // Ignore the deletion on conflict.
          llvm::errs() << "Failed to add header deletion replacement for "
                       << IncludeName << ": " << llvm::toString(std::move(Err))
                       << "\n";
        }
      }
    }
    Offset = NextLineOffset;
  }

  // Populate CategoryEndOfssets:
  // - Ensure that CategoryEndOffset[Highest] is always populated.
  // - If CategoryEndOffset[Priority] isn't set, use the next higher value that
  //   is set, up to CategoryEndOffset[Highest].
  auto Highest = Priorities.begin();
  if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) {
    if (FirstIncludeOffset >= 0)
      CategoryEndOffsets[*Highest] = FirstIncludeOffset;
    else
      CategoryEndOffsets[*Highest] = MinInsertOffset;
  }
  // By this point, CategoryEndOffset[Highest] is always set appropriately:
  //  - to an appropriate location before/after existing #includes, or
  //  - to right after the header guard, or
  //  - to the beginning of the file.
  for (auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I)
    if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
      CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];

  bool NeedNewLineAtEnd = !Code.empty() && Code.back() != '\n';
  for (const auto &R : HeaderInsertions) {
    auto IncludeDirective = R.getReplacementText();
    bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
    assert(Matched && "Header insertion replacement must have replacement text "
                      "'#include ...'");
    (void)Matched;
    auto IncludeName = Matches[2];
    if (ExistingIncludes.find(IncludeName) != ExistingIncludes.end()) {
      DEBUG(llvm::dbgs() << "Skip adding existing include : " << IncludeName
                         << "\n");
      continue;
    }
    int Category =
        Categories.getIncludePriority(IncludeName, /*CheckMainHeader=*/true);
    Offset = CategoryEndOffsets[Category];
    std::string NewInclude = !IncludeDirective.endswith("\n")
                                 ? (IncludeDirective + "\n").str()
                                 : IncludeDirective.str();
    // When inserting headers at end of the code, also append '\n' to the code
    // if it does not end with '\n'.
    if (NeedNewLineAtEnd && Offset == Code.size()) {
      NewInclude = "\n" + NewInclude;
      NeedNewLineAtEnd = false;
    }
    auto NewReplace = tooling::Replacement(FileName, Offset, 0, NewInclude);
    auto Err = Result.add(NewReplace);
    if (Err) {
      llvm::consumeError(std::move(Err));
      unsigned NewOffset = Result.getShiftedCodePosition(Offset);
      NewReplace = tooling::Replacement(FileName, NewOffset, 0, NewInclude);
      Result = Result.merge(tooling::Replacements(NewReplace));
    }
  }
  return Result;
}

} // anonymous namespace

llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
                          const FormatStyle &Style) {
  // We need to use lambda function here since there are two versions of
  // `cleanup`.
  auto Cleanup = [](const FormatStyle &Style, StringRef Code,
                    std::vector<tooling::Range> Ranges,
                    StringRef FileName) -> tooling::Replacements {
    return cleanup(Style, Code, Ranges, FileName);
  };
  // Make header insertion replacements insert new headers into correct blocks.
  tooling::Replacements NewReplaces =
      fixCppIncludeInsertions(Code, Replaces, Style);
  return processReplacements(Cleanup, Code, NewReplaces, Style);
d1897 1
a1897 2
  FormatStyle Expanded = expandPresets(Style);
  if (Expanded.DisableFormat)
d1900 18
a1917 16
  auto Env = Environment::CreateVirtualEnvironment(Code, FileName, Ranges);

  if (Style.Language == FormatStyle::LK_JavaScript &&
      Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
    JavaScriptRequoter Requoter(*Env, Expanded);
    tooling::Replacements Requotes = Requoter.process();
    if (!Requotes.empty()) {
      auto NewCode = applyAllReplacements(Code, Requotes);
      if (NewCode) {
        auto NewEnv = Environment::CreateVirtualEnvironment(
            *NewCode, FileName,
            tooling::calculateRangesAfterReplacements(Requotes, Ranges));
        Formatter Format(*NewEnv, Expanded, IncompleteFormat);
        return Requotes.merge(Format.process());
      }
    }
d1919 1
a1919 12

  Formatter Format(*Env, Expanded, IncompleteFormat);
  return Format.process();
}

tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
                              ArrayRef<tooling::Range> Ranges,
                              StringRef FileName) {
  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
  Cleaner Clean(*Env, Style);
  return Clean.process();
d1933 1
a1933 1
  LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
a1953 2
  if (FileName.endswith(".m") || FileName.endswith(".mm"))
    return FormatStyle::LK_ObjC;
d1963 1
a1963 5
                     StringRef FallbackStyle, StringRef Code,
                     vfs::FileSystem *FS) {
  if (!FS) {
    FS = vfs::getRealFileSystem().get();
  }
a1965 8

  // This is a very crude detection of whether a header contains ObjC code that
  // should be improved over time and probably be done on tokens, not one the
  // bare content of the file.
  if (Style.Language == FormatStyle::LK_Cpp && FileName.endswith(".h") &&
      (Code.contains("\n- (") || Code.contains("\n+ (")))
    Style.Language = FormatStyle::LK_ObjC;

d1991 1
a1991 5
  if (std::error_code EC = FS->makeAbsolute(Path)) {
    llvm::errs() << EC.message() << "\n";
    return Style;
  }

d1994 1
a1994 4

    auto Status = FS->status(Directory);
    if (!Status ||
        Status->getType() != llvm::sys::fs::file_type::directory_file) {
a1995 2
    }

d2000 4
a2004 3
    Status = FS->status(ConfigFile.str());
    bool IsFile =
        Status && (Status->getType() == llvm::sys::fs::file_type::regular_file);
d2010 1
a2010 3
      Status = FS->status(ConfigFile.str());
      IsFile = Status &&
               (Status->getType() == llvm::sys::fs::file_type::regular_file);
d2015 1
a2015 1
          FS->getBufferForFile(ConfigFile.str());
@


1.1.1.9
log
@Import Clang pre-4.0.0 r291444.
@
text
@a16 1
#include "AffectedRangeManager.h"
a17 3
#include "FormatTokenLexer.h"
#include "SortJavaScriptImports.h"
#include "TokenAnalyzer.h"
a24 1
#include "clang/Basic/VirtualFileSystem.h"
d32 1
a32 2
#include <algorithm>
#include <memory>
a48 1
    IO.enumCase(Value, "ObjC", FormatStyle::LK_ObjC);
a70 10
    IO.enumCase(Value, "ForContinuationAndIndentation",
                FormatStyle::UT_ForContinuationAndIndentation);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::JavaScriptQuoteStyle> {
  static void enumeration(IO &IO, FormatStyle::JavaScriptQuoteStyle &Value) {
    IO.enumCase(Value, "Leave", FormatStyle::JSQS_Leave);
    IO.enumCase(Value, "Single", FormatStyle::JSQS_Single);
    IO.enumCase(Value, "Double", FormatStyle::JSQS_Double);
a277 3
    IO.mapOptional("BreakAfterJavaFieldAnnotations",
                   Style.BreakAfterJavaFieldAnnotations);
    IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
a291 1
    IO.mapOptional("IncludeIsMainRegex", Style.IncludeIsMainRegex);
a295 2
    IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes);
    IO.mapOptional("JavaScriptWrapImports", Style.JavaScriptWrapImports);
a318 1
    IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword);
d400 1
a400 1
const char *ParseErrorCategory::name() const noexcept {
d491 1
a492 2
  LLVMStyle.BreakConstructorInitializersBeforeComma = false;
  LLVMStyle.BreakStringLiterals = true;
a506 1
  LLVMStyle.IncludeIsMainRegex = "$";
a509 2
  LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
  LLVMStyle.JavaScriptWrapImports = true;
a520 1
  LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave;
a527 1
  LLVMStyle.SpaceAfterTemplateKeyword = true;
a557 1
  GoogleStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
d583 1
a583 1
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Empty;
d586 1
a586 2
    GoogleStyle.CommentPragmas =
        "(taze:|@@(export|requirecss|return|returns|see|visibility)) ";
a587 1
    GoogleStyle.NamespaceIndentation = FormatStyle::NI_All;
a588 2
    GoogleStyle.JavaScriptQuotes = FormatStyle::JSQS_Single;
    GoogleStyle.JavaScriptWrapImports = false;
a591 2
  } else if (Language == FormatStyle::LK_ObjC) {
    GoogleStyle.ColumnLimit = 100;
a603 3
  } else if (Language == FormatStyle::LK_JavaScript) {
    ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
    ChromiumStyle.AllowShortLoopsOnASingleLine = false;
d621 1
a621 1
      FormatStyle::RTBS_TopLevel;
a624 2
  MozillaStyle.BinPackParameters = false;
  MozillaStyle.BinPackArguments = false;
a634 1
  MozillaStyle.SpaceAfterTemplateKeyword = false;
d654 1
d762 1
a762 1
class JavaScriptRequoter : public TokenAnalyzer {
d764 33
a796 2
  JavaScriptRequoter(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style) {}
d798 172
a969 9
  tooling::Replacements
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
                                          AnnotatedLines.end());
    tooling::Replacements Result;
    requoteJSStringLiteral(AnnotatedLines, Result);
    return Result;
d972 43
a1014 8
private:
  // Replaces double/single-quoted string literal as appropriate, re-escaping
  // the contents in the process.
  void requoteJSStringLiteral(SmallVectorImpl<AnnotatedLine *> &Lines,
                              tooling::Replacements &Result) {
    for (AnnotatedLine *Line : Lines) {
      requoteJSStringLiteral(Line->Children, Result);
      if (!Line->Affected)
d1016 142
a1157 11
      for (FormatToken *FormatTok = Line->First; FormatTok;
           FormatTok = FormatTok->Next) {
        StringRef Input = FormatTok->TokenText;
        if (FormatTok->Finalized || !FormatTok->isStringLiteral() ||
            // NB: testing for not starting with a double quote to avoid
            // breaking `template strings`.
            (Style.JavaScriptQuotes == FormatStyle::JSQS_Single &&
             !Input.startswith("\"")) ||
            (Style.JavaScriptQuotes == FormatStyle::JSQS_Double &&
             !Input.startswith("\'")))
          continue;
d1159 48
a1206 32
        // Change start and end quote.
        bool IsSingle = Style.JavaScriptQuotes == FormatStyle::JSQS_Single;
        SourceLocation Start = FormatTok->Tok.getLocation();
        auto Replace = [&](SourceLocation Start, unsigned Length,
                           StringRef ReplacementText) {
          auto Err = Result.add(tooling::Replacement(
              Env.getSourceManager(), Start, Length, ReplacementText));
          // FIXME: handle error. For now, print error message and skip the
          // replacement for release version.
          if (Err) {
            llvm::errs() << llvm::toString(std::move(Err)) << "\n";
            assert(false);
          }
        };
        Replace(Start, 1, IsSingle ? "'" : "\"");
        Replace(FormatTok->Tok.getEndLoc().getLocWithOffset(-1), 1,
                IsSingle ? "'" : "\"");

        // Escape internal quotes.
        bool Escaped = false;
        for (size_t i = 1; i < Input.size() - 1; i++) {
          switch (Input[i]) {
          case '\\':
            if (!Escaped && i + 1 < Input.size() &&
                ((IsSingle && Input[i + 1] == '"') ||
                 (!IsSingle && Input[i + 1] == '\''))) {
              // Remove this \, it's escaping a " or ' that no longer needs
              // escaping
              Replace(Start.getLocWithOffset(i), 1, "");
              continue;
            }
            Escaped = !Escaped;
d1208 131
a1338 12
          case '\"':
          case '\'':
            if (!Escaped && IsSingle == (Input[i] == '\'')) {
              // Escape the quote.
              Replace(Start.getLocWithOffset(i), 0, "\\");
            }
            Escaped = false;
            break;
          default:
            Escaped = false;
            break;
          }
d1342 78
d1421 1
a1421 1
};
d1423 1
a1423 1
class Formatter : public TokenAnalyzer {
d1425 16
a1440 8
  Formatter(const Environment &Env, const FormatStyle &Style,
            bool *IncompleteFormat)
      : TokenAnalyzer(Env, Style), IncompleteFormat(IncompleteFormat) {}

  tooling::Replacements
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
d1442 39
a1481 2
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
                                          AnnotatedLines.end());
d1485 2
d1488 2
a1489 6

    WhitespaceManager Whitespaces(
        Env.getSourceManager(), Style,
        inputUsesCRLF(Env.getSourceManager().getBufferData(Env.getFileID())));
    ContinuationIndenter Indenter(Style, Tokens.getKeywords(),
                                  Env.getSourceManager(), Whitespaces, Encoding,
d1494 1
a1494 4
    for (const auto &R : Whitespaces.generateReplacements())
      if (Result.add(R))
        return Result;
    return Result;
d1498 132
d1637 1
a1637 1
    for (const AnnotatedLine *Line : Lines) {
d1655 1
a1655 1
    for (const AnnotatedLine *Line : Lines) {
d1702 3
a1704 51
  bool BinPackInconclusiveFunctions;
  bool *IncompleteFormat;
};

// This class clean up the erroneous/redundant code around the given ranges in
// file.
class Cleaner : public TokenAnalyzer {
public:
  Cleaner(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style),
        DeletedTokens(FormatTokenLess(Env.getSourceManager())) {}

  // FIXME: eliminate unused parameters.
  tooling::Replacements
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    // FIXME: in the current implementation the granularity of affected range
    // is an annotated line. However, this is not sufficient. Furthermore,
    // redundant code introduced by replacements does not necessarily
    // intercept with ranges of replacements that result in the redundancy.
    // To determine if some redundant code is actually introduced by
    // replacements(e.g. deletions), we need to come up with a more
    // sophisticated way of computing affected ranges.
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines.begin(),
                                          AnnotatedLines.end());

    checkEmptyNamespace(AnnotatedLines);

    for (auto &Line : AnnotatedLines) {
      if (Line->Affected) {
        cleanupRight(Line->First, tok::comma, tok::comma);
        cleanupRight(Line->First, TT_CtorInitializerColon, tok::comma);
        cleanupRight(Line->First, tok::l_paren, tok::comma);
        cleanupLeft(Line->First, tok::comma, tok::r_paren);
        cleanupLeft(Line->First, TT_CtorInitializerComma, tok::l_brace);
        cleanupLeft(Line->First, TT_CtorInitializerColon, tok::l_brace);
        cleanupLeft(Line->First, TT_CtorInitializerColon, tok::equal);
      }
    }

    return generateFixes();
  }

private:
  bool containsOnlyComments(const AnnotatedLine &Line) {
    for (FormatToken *Tok = Line.First; Tok != nullptr; Tok = Tok->Next) {
      if (Tok->isNot(tok::comment))
        return false;
    }
    return true;
d1707 2
a1708 18
  // Iterate through all lines and remove any empty (nested) namespaces.
  void checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
    std::set<unsigned> DeletedLines;
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      auto &Line = *AnnotatedLines[i];
      if (Line.startsWith(tok::kw_namespace) ||
          Line.startsWith(tok::kw_inline, tok::kw_namespace)) {
        checkEmptyNamespace(AnnotatedLines, i, i, DeletedLines);
      }
    }

    for (auto Line : DeletedLines) {
      FormatToken *Tok = AnnotatedLines[Line]->First;
      while (Tok) {
        deleteToken(Tok);
        Tok = Tok->Next;
      }
    }
d1711 6
a1716 22
  // The function checks if the namespace, which starts from \p CurrentLine, and
  // its nested namespaces are empty and delete them if they are empty. It also
  // sets \p NewLine to the last line checked.
  // Returns true if the current namespace is empty.
  bool checkEmptyNamespace(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                           unsigned CurrentLine, unsigned &NewLine,
                           std::set<unsigned> &DeletedLines) {
    unsigned InitLine = CurrentLine, End = AnnotatedLines.size();
    if (Style.BraceWrapping.AfterNamespace) {
      // If the left brace is in a new line, we should consume it first so that
      // it does not make the namespace non-empty.
      // FIXME: error handling if there is no left brace.
      if (!AnnotatedLines[++CurrentLine]->startsWith(tok::l_brace)) {
        NewLine = CurrentLine;
        return false;
      }
    } else if (!AnnotatedLines[CurrentLine]->endsWith(tok::l_brace)) {
      return false;
    }
    while (++CurrentLine < End) {
      if (AnnotatedLines[CurrentLine]->startsWith(tok::r_brace))
        break;
d1718 2
a1719 130
      if (AnnotatedLines[CurrentLine]->startsWith(tok::kw_namespace) ||
          AnnotatedLines[CurrentLine]->startsWith(tok::kw_inline,
                                                  tok::kw_namespace)) {
        if (!checkEmptyNamespace(AnnotatedLines, CurrentLine, NewLine,
                                 DeletedLines))
          return false;
        CurrentLine = NewLine;
        continue;
      }

      if (containsOnlyComments(*AnnotatedLines[CurrentLine]))
        continue;

      // If there is anything other than comments or nested namespaces in the
      // current namespace, the namespace cannot be empty.
      NewLine = CurrentLine;
      return false;
    }

    NewLine = CurrentLine;
    if (CurrentLine >= End)
      return false;

    // Check if the empty namespace is actually affected by changed ranges.
    if (!AffectedRangeMgr.affectsCharSourceRange(CharSourceRange::getCharRange(
            AnnotatedLines[InitLine]->First->Tok.getLocation(),
            AnnotatedLines[CurrentLine]->Last->Tok.getEndLoc())))
      return false;

    for (unsigned i = InitLine; i <= CurrentLine; ++i) {
      DeletedLines.insert(i);
    }

    return true;
  }

  // Checks pairs {start, start->next},..., {end->previous, end} and deletes one
  // of the token in the pair if the left token has \p LK token kind and the
  // right token has \p RK token kind. If \p DeleteLeft is true, the left token
  // is deleted on match; otherwise, the right token is deleted.
  template <typename LeftKind, typename RightKind>
  void cleanupPair(FormatToken *Start, LeftKind LK, RightKind RK,
                   bool DeleteLeft) {
    auto NextNotDeleted = [this](const FormatToken &Tok) -> FormatToken * {
      for (auto *Res = Tok.Next; Res; Res = Res->Next)
        if (!Res->is(tok::comment) &&
            DeletedTokens.find(Res) == DeletedTokens.end())
          return Res;
      return nullptr;
    };
    for (auto *Left = Start; Left;) {
      auto *Right = NextNotDeleted(*Left);
      if (!Right)
        break;
      if (Left->is(LK) && Right->is(RK)) {
        deleteToken(DeleteLeft ? Left : Right);
        for (auto *Tok = Left->Next; Tok && Tok != Right; Tok = Tok->Next)
          deleteToken(Tok);
        // If the right token is deleted, we should keep the left token
        // unchanged and pair it with the new right token.
        if (!DeleteLeft)
          continue;
      }
      Left = Right;
    }
  }

  template <typename LeftKind, typename RightKind>
  void cleanupLeft(FormatToken *Start, LeftKind LK, RightKind RK) {
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/true);
  }

  template <typename LeftKind, typename RightKind>
  void cleanupRight(FormatToken *Start, LeftKind LK, RightKind RK) {
    cleanupPair(Start, LK, RK, /*DeleteLeft=*/false);
  }

  // Delete the given token.
  inline void deleteToken(FormatToken *Tok) {
    if (Tok)
      DeletedTokens.insert(Tok);
  }

  tooling::Replacements generateFixes() {
    tooling::Replacements Fixes;
    std::vector<FormatToken *> Tokens;
    std::copy(DeletedTokens.begin(), DeletedTokens.end(),
              std::back_inserter(Tokens));

    // Merge multiple continuous token deletions into one big deletion so that
    // the number of replacements can be reduced. This makes computing affected
    // ranges more efficient when we run reformat on the changed code.
    unsigned Idx = 0;
    while (Idx < Tokens.size()) {
      unsigned St = Idx, End = Idx;
      while ((End + 1) < Tokens.size() &&
             Tokens[End]->Next == Tokens[End + 1]) {
        End++;
      }
      auto SR = CharSourceRange::getCharRange(Tokens[St]->Tok.getLocation(),
                                              Tokens[End]->Tok.getEndLoc());
      auto Err =
          Fixes.add(tooling::Replacement(Env.getSourceManager(), SR, ""));
      // FIXME: better error handling. for now just print error message and skip
      // for the release version.
      if (Err) {
        llvm::errs() << llvm::toString(std::move(Err)) << "\n";
        assert(false && "Fixes must not conflict!");
      }
      Idx = End + 1;
    }

    return Fixes;
  }

  // Class for less-than inequality comparason for the set `RedundantTokens`.
  // We store tokens in the order they appear in the translation unit so that
  // we do not need to sort them in `generateFixes()`.
  struct FormatTokenLess {
    FormatTokenLess(const SourceManager &SM) : SM(SM) {}

    bool operator()(const FormatToken *LHS, const FormatToken *RHS) const {
      return SM.isBeforeInTranslationUnit(LHS->Tok.getLocation(),
                                          RHS->Tok.getLocation());
    }
    const SourceManager &SM;
  };

  // Tokens to be deleted.
  std::set<FormatToken *, FormatTokenLess> DeletedTokens;
d1742 9
a1750 44
// Returns a pair (Index, OffsetToEOL) describing the position of the cursor
// before sorting/deduplicating. Index is the index of the include under the
// cursor in the original set of includes. If this include has duplicates, it is
// the index of the first of the duplicates as the others are going to be
// removed. OffsetToEOL describes the cursor's position relative to the end of
// its current line.
// If `Cursor` is not on any #include, `Index` will be UINT_MAX.
static std::pair<unsigned, unsigned>
FindCursorIndex(const SmallVectorImpl<IncludeDirective> &Includes,
                const SmallVectorImpl<unsigned> &Indices, unsigned Cursor) {
  unsigned CursorIndex = UINT_MAX;
  unsigned OffsetToEOL = 0;
  for (int i = 0, e = Includes.size(); i != e; ++i) {
    unsigned Start = Includes[Indices[i]].Offset;
    unsigned End = Start + Includes[Indices[i]].Text.size();
    if (!(Cursor >= Start && Cursor < End))
      continue;
    CursorIndex = Indices[i];
    OffsetToEOL = End - Cursor;
    // Put the cursor on the only remaining #include among the duplicate
    // #includes.
    while (--i >= 0 && Includes[CursorIndex].Text == Includes[Indices[i]].Text)
      CursorIndex = i;
    break;
  }
  return std::make_pair(CursorIndex, OffsetToEOL);
}

// Sorts and deduplicate a block of includes given by 'Includes' alphabetically
// adding the necessary replacement to 'Replaces'. 'Includes' must be in strict
// source order.
// #include directives with the same text will be deduplicated, and only the
// first #include in the duplicate #includes remains. If the `Cursor` is
// provided and put on a deleted #include, it will be moved to the remaining
// #include in the duplicate #includes.
static void sortCppIncludes(const FormatStyle &Style,
                            const SmallVectorImpl<IncludeDirective> &Includes,
                            ArrayRef<tooling::Range> Ranges, StringRef FileName,
                            tooling::Replacements &Replaces, unsigned *Cursor) {
  unsigned IncludesBeginOffset = Includes.front().Offset;
  unsigned IncludesEndOffset =
      Includes.back().Offset + Includes.back().Text.size();
  unsigned IncludesBlockSize = IncludesEndOffset - IncludesBeginOffset;
  if (!affectsRange(Ranges, IncludesBeginOffset, IncludesEndOffset))
d1755 4
a1758 20
  std::stable_sort(
      Indices.begin(), Indices.end(), [&](unsigned LHSI, unsigned RHSI) {
        return std::tie(Includes[LHSI].Category, Includes[LHSI].Filename) <
               std::tie(Includes[RHSI].Category, Includes[RHSI].Filename);
      });
  // The index of the include on which the cursor will be put after
  // sorting/deduplicating.
  unsigned CursorIndex;
  // The offset from cursor to the end of line.
  unsigned CursorToEOLOffset;
  if (Cursor)
    std::tie(CursorIndex, CursorToEOLOffset) =
        FindCursorIndex(Includes, Indices, *Cursor);

  // Deduplicate #includes.
  Indices.erase(std::unique(Indices.begin(), Indices.end(),
                            [&](unsigned LHSI, unsigned RHSI) {
                              return Includes[LHSI].Text == Includes[RHSI].Text;
                            }),
                Indices.end());
d1762 8
a1769 2
  if (Indices.size() == Includes.size() &&
      std::is_sorted(Indices.begin(), Indices.end()))
d1773 1
a1777 15
    if (Cursor && CursorIndex == Index)
      *Cursor = IncludesBeginOffset + result.size() - CursorToEOLOffset;
  }

  auto Err = Replaces.add(tooling::Replacement(
      FileName, Includes.front().Offset, IncludesBlockSize, result));
  // FIXME: better error handling. For now, just skip the replacement for the
  // release version.
  if (Err) {
    llvm::errs() << llvm::toString(std::move(Err)) << "\n";
    assert(false);
  }
}

namespace {
d1779 6
a1784 24
// This class manages priorities of #include categories and calculates
// priorities for headers.
class IncludeCategoryManager {
public:
  IncludeCategoryManager(const FormatStyle &Style, StringRef FileName)
      : Style(Style), FileName(FileName) {
    FileStem = llvm::sys::path::stem(FileName);
    for (const auto &Category : Style.IncludeCategories)
      CategoryRegexs.emplace_back(Category.Regex);
    IsMainFile = FileName.endswith(".c") || FileName.endswith(".cc") ||
                 FileName.endswith(".cpp") || FileName.endswith(".c++") ||
                 FileName.endswith(".cxx") || FileName.endswith(".m") ||
                 FileName.endswith(".mm");
  }

  // Returns the priority of the category which \p IncludeName belongs to.
  // If \p CheckMainHeader is true and \p IncludeName is a main header, returns
  // 0. Otherwise, returns the priority of the matching category or INT_MAX.
  int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) {
    int Ret = INT_MAX;
    for (unsigned i = 0, e = CategoryRegexs.size(); i != e; ++i)
      if (CategoryRegexs[i].match(IncludeName)) {
        Ret = Style.IncludeCategories[i].Priority;
        break;
a1785 16
    if (CheckMainHeader && IsMainFile && Ret > 0 && isMainHeader(IncludeName))
      Ret = 0;
    return Ret;
  }

private:
  bool isMainHeader(StringRef IncludeName) const {
    if (!IncludeName.startswith("\""))
      return false;
    StringRef HeaderStem =
        llvm::sys::path::stem(IncludeName.drop_front(1).drop_back(1));
    if (FileStem.startswith(HeaderStem)) {
      llvm::Regex MainIncludeRegex(
          (HeaderStem + Style.IncludeIsMainRegex).str());
      if (MainIncludeRegex.match(FileStem))
        return true;
a1786 1
    return false;
d1789 5
a1793 6
  const FormatStyle &Style;
  bool IsMainFile;
  StringRef FileName;
  StringRef FileStem;
  SmallVector<llvm::Regex, 4> CategoryRegexs;
};
d1795 3
a1797 2
const char IncludeRegexPattern[] =
    R"(^[\t\ ]*#[\t\ ]*(import|include)[^"<]*(["<][^">]*[">]))";
d1799 6
a1804 1
} // anonymous namespace
a1805 5
tooling::Replacements sortCppIncludes(const FormatStyle &Style, StringRef Code,
                                      ArrayRef<tooling::Range> Ranges,
                                      StringRef FileName,
                                      tooling::Replacements &Replaces,
                                      unsigned *Cursor) {
d1808 2
a1809 1
  llvm::Regex IncludeRegex(IncludeRegexPattern);
d1820 5
a1824 1
  IncludeCategoryManager Categories(Style, FileName);
d1827 6
d1849 16
a1864 5
        int Category = Categories.getIncludePriority(
            IncludeName,
            /*CheckMainHeader=*/!MainIncludeFound && FirstIncludeBlock);
        if (Category == 0)
          MainIncludeFound = true;
d1867 2
a1868 2
        sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces,
                        Cursor);
d1879 1
a1879 1
    sortCppIncludes(Style, IncludesInBlock, Ranges, FileName, Replaces, Cursor);
d1883 6
a1888 18
tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code,
                                   ArrayRef<tooling::Range> Ranges,
                                   StringRef FileName, unsigned *Cursor) {
  tooling::Replacements Replaces;
  if (!Style.SortIncludes)
    return Replaces;
  if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript)
    return sortJavaScriptImports(Style, Code, Ranges, FileName);
  sortCppIncludes(Style, Code, Ranges, FileName, Replaces, Cursor);
  return Replaces;
}

template <typename T>
static llvm::Expected<tooling::Replacements>
processReplacements(T ProcessFunc, StringRef Code,
                    const tooling::Replacements &Replaces,
                    const FormatStyle &Style) {
  if (Replaces.empty())
d1890 2
a1891 324

  auto NewCode = applyAllReplacements(Code, Replaces);
  if (!NewCode)
    return NewCode.takeError();
  std::vector<tooling::Range> ChangedRanges = Replaces.getAffectedRanges();
  StringRef FileName = Replaces.begin()->getFilePath();

  tooling::Replacements FormatReplaces =
      ProcessFunc(Style, *NewCode, ChangedRanges, FileName);

  return Replaces.merge(FormatReplaces);
}

llvm::Expected<tooling::Replacements>
formatReplacements(StringRef Code, const tooling::Replacements &Replaces,
                   const FormatStyle &Style) {
  // We need to use lambda function here since there are two versions of
  // `sortIncludes`.
  auto SortIncludes = [](const FormatStyle &Style, StringRef Code,
                         std::vector<tooling::Range> Ranges,
                         StringRef FileName) -> tooling::Replacements {
    return sortIncludes(Style, Code, Ranges, FileName);
  };
  auto SortedReplaces =
      processReplacements(SortIncludes, Code, Replaces, Style);
  if (!SortedReplaces)
    return SortedReplaces.takeError();

  // We need to use lambda function here since there are two versions of
  // `reformat`.
  auto Reformat = [](const FormatStyle &Style, StringRef Code,
                     std::vector<tooling::Range> Ranges,
                     StringRef FileName) -> tooling::Replacements {
    return reformat(Style, Code, Ranges, FileName);
  };
  return processReplacements(Reformat, Code, *SortedReplaces, Style);
}

namespace {

inline bool isHeaderInsertion(const tooling::Replacement &Replace) {
  return Replace.getOffset() == UINT_MAX && Replace.getLength() == 0 &&
         llvm::Regex(IncludeRegexPattern).match(Replace.getReplacementText());
}

inline bool isHeaderDeletion(const tooling::Replacement &Replace) {
  return Replace.getOffset() == UINT_MAX && Replace.getLength() == 1;
}

// Returns the offset after skipping a sequence of tokens, matched by \p
// GetOffsetAfterSequence, from the start of the code.
// \p GetOffsetAfterSequence should be a function that matches a sequence of
// tokens and returns an offset after the sequence.
unsigned getOffsetAfterTokenSequence(
    StringRef FileName, StringRef Code, const FormatStyle &Style,
    std::function<unsigned(const SourceManager &, Lexer &, Token &)>
        GetOffsetAfterSequense) {
  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, /*Ranges=*/{});
  const SourceManager &SourceMgr = Env->getSourceManager();
  Lexer Lex(Env->getFileID(), SourceMgr.getBuffer(Env->getFileID()), SourceMgr,
            getFormattingLangOpts(Style));
  Token Tok;
  // Get the first token.
  Lex.LexFromRawLexer(Tok);
  return GetOffsetAfterSequense(SourceMgr, Lex, Tok);
}

// Check if a sequence of tokens is like "#<Name> <raw_identifier>". If it is,
// \p Tok will be the token after this directive; otherwise, it can be any token
// after the given \p Tok (including \p Tok).
bool checkAndConsumeDirectiveWithName(Lexer &Lex, StringRef Name, Token &Tok) {
  bool Matched = Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
                 Tok.is(tok::raw_identifier) &&
                 Tok.getRawIdentifier() == Name && !Lex.LexFromRawLexer(Tok) &&
                 Tok.is(tok::raw_identifier);
  if (Matched)
    Lex.LexFromRawLexer(Tok);
  return Matched;
}

void skipComments(Lexer &Lex, Token &Tok) {
  while (Tok.is(tok::comment))
    if (Lex.LexFromRawLexer(Tok))
      return;
}

// Returns the offset after header guard directives and any comments
// before/after header guards. If no header guard presents in the code, this
// will returns the offset after skipping all comments from the start of the
// code.
unsigned getOffsetAfterHeaderGuardsAndComments(StringRef FileName,
                                               StringRef Code,
                                               const FormatStyle &Style) {
  return getOffsetAfterTokenSequence(
      FileName, Code, Style,
      [](const SourceManager &SM, Lexer &Lex, Token Tok) {
        skipComments(Lex, Tok);
        unsigned InitialOffset = SM.getFileOffset(Tok.getLocation());
        if (checkAndConsumeDirectiveWithName(Lex, "ifndef", Tok)) {
          skipComments(Lex, Tok);
          if (checkAndConsumeDirectiveWithName(Lex, "define", Tok))
            return SM.getFileOffset(Tok.getLocation());
        }
        return InitialOffset;
      });
}

// Check if a sequence of tokens is like
//    "#include ("header.h" | <header.h>)".
// If it is, \p Tok will be the token after this directive; otherwise, it can be
// any token after the given \p Tok (including \p Tok).
bool checkAndConsumeInclusiveDirective(Lexer &Lex, Token &Tok) {
  auto Matched = [&]() {
    Lex.LexFromRawLexer(Tok);
    return true;
  };
  if (Tok.is(tok::hash) && !Lex.LexFromRawLexer(Tok) &&
      Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == "include") {
    if (Lex.LexFromRawLexer(Tok))
      return false;
    if (Tok.is(tok::string_literal))
      return Matched();
    if (Tok.is(tok::less)) {
      while (!Lex.LexFromRawLexer(Tok) && Tok.isNot(tok::greater)) {
      }
      if (Tok.is(tok::greater))
        return Matched();
    }
  }
  return false;
}

// Returns the offset of the last #include directive after which a new
// #include can be inserted. This ignores #include's after the #include block(s)
// in the beginning of a file to avoid inserting headers into code sections
// where new #include's should not be added by default.
// These code sections include:
//      - raw string literals (containing #include).
//      - #if blocks.
//      - Special #include's among declarations (e.g. functions).
//
// If no #include after which a new #include can be inserted, this returns the
// offset after skipping all comments from the start of the code.
// Inserting after an #include is not allowed if it comes after code that is not
// #include (e.g. pre-processing directive that is not #include, declarations).
unsigned getMaxHeaderInsertionOffset(StringRef FileName, StringRef Code,
                                     const FormatStyle &Style) {
  return getOffsetAfterTokenSequence(
      FileName, Code, Style,
      [](const SourceManager &SM, Lexer &Lex, Token Tok) {
        skipComments(Lex, Tok);
        unsigned MaxOffset = SM.getFileOffset(Tok.getLocation());
        while (checkAndConsumeInclusiveDirective(Lex, Tok))
          MaxOffset = SM.getFileOffset(Tok.getLocation());
        return MaxOffset;
      });
}

bool isDeletedHeader(llvm::StringRef HeaderName,
                     const std::set<llvm::StringRef> &HeadersToDelete) {
  return HeadersToDelete.count(HeaderName) ||
         HeadersToDelete.count(HeaderName.trim("\"<>"));
}

// FIXME: insert empty lines between newly created blocks.
tooling::Replacements
fixCppIncludeInsertions(StringRef Code, const tooling::Replacements &Replaces,
                        const FormatStyle &Style) {
  if (Style.Language != FormatStyle::LanguageKind::LK_Cpp)
    return Replaces;

  tooling::Replacements HeaderInsertions;
  std::set<llvm::StringRef> HeadersToDelete;
  tooling::Replacements Result;
  for (const auto &R : Replaces) {
    if (isHeaderInsertion(R)) {
      // Replacements from \p Replaces must be conflict-free already, so we can
      // simply consume the error.
      llvm::consumeError(HeaderInsertions.add(R));
    } else if (isHeaderDeletion(R)) {
      HeadersToDelete.insert(R.getReplacementText());
    } else if (R.getOffset() == UINT_MAX) {
      llvm::errs() << "Insertions other than header #include insertion are "
                      "not supported! "
                   << R.getReplacementText() << "\n";
    } else {
      llvm::consumeError(Result.add(R));
    }
  }
  if (HeaderInsertions.empty() && HeadersToDelete.empty())
    return Replaces;

  llvm::Regex IncludeRegex(IncludeRegexPattern);
  llvm::Regex DefineRegex(R"(^[\t\ ]*#[\t\ ]*define[\t\ ]*[^\\]*$)");
  SmallVector<StringRef, 4> Matches;

  StringRef FileName = Replaces.begin()->getFilePath();
  IncludeCategoryManager Categories(Style, FileName);

  // Record the offset of the end of the last include in each category.
  std::map<int, int> CategoryEndOffsets;
  // All possible priorities.
  // Add 0 for main header and INT_MAX for headers that are not in any category.
  std::set<int> Priorities = {0, INT_MAX};
  for (const auto &Category : Style.IncludeCategories)
    Priorities.insert(Category.Priority);
  int FirstIncludeOffset = -1;
  // All new headers should be inserted after this offset.
  unsigned MinInsertOffset =
      getOffsetAfterHeaderGuardsAndComments(FileName, Code, Style);
  StringRef TrimmedCode = Code.drop_front(MinInsertOffset);
  // Max insertion offset in the original code.
  unsigned MaxInsertOffset =
      MinInsertOffset +
      getMaxHeaderInsertionOffset(FileName, TrimmedCode, Style);
  SmallVector<StringRef, 32> Lines;
  TrimmedCode.split(Lines, '\n');
  unsigned Offset = MinInsertOffset;
  unsigned NextLineOffset;
  std::set<StringRef> ExistingIncludes;
  for (auto Line : Lines) {
    NextLineOffset = std::min(Code.size(), Offset + Line.size() + 1);
    if (IncludeRegex.match(Line, &Matches)) {
      // The header name with quotes or angle brackets.
      StringRef IncludeName = Matches[2];
      ExistingIncludes.insert(IncludeName);
      // Only record the offset of current #include if we can insert after it.
      if (Offset <= MaxInsertOffset) {
        int Category = Categories.getIncludePriority(
            IncludeName, /*CheckMainHeader=*/FirstIncludeOffset < 0);
        CategoryEndOffsets[Category] = NextLineOffset;
        if (FirstIncludeOffset < 0)
          FirstIncludeOffset = Offset;
      }
      if (isDeletedHeader(IncludeName, HeadersToDelete)) {
        // If this is the last line without trailing newline, we need to make
        // sure we don't delete across the file boundary.
        unsigned Length = std::min(Line.size() + 1, Code.size() - Offset);
        llvm::Error Err =
            Result.add(tooling::Replacement(FileName, Offset, Length, ""));
        if (Err) {
          // Ignore the deletion on conflict.
          llvm::errs() << "Failed to add header deletion replacement for "
                       << IncludeName << ": " << llvm::toString(std::move(Err))
                       << "\n";
        }
      }
    }
    Offset = NextLineOffset;
  }

  // Populate CategoryEndOfssets:
  // - Ensure that CategoryEndOffset[Highest] is always populated.
  // - If CategoryEndOffset[Priority] isn't set, use the next higher value that
  //   is set, up to CategoryEndOffset[Highest].
  auto Highest = Priorities.begin();
  if (CategoryEndOffsets.find(*Highest) == CategoryEndOffsets.end()) {
    if (FirstIncludeOffset >= 0)
      CategoryEndOffsets[*Highest] = FirstIncludeOffset;
    else
      CategoryEndOffsets[*Highest] = MinInsertOffset;
  }
  // By this point, CategoryEndOffset[Highest] is always set appropriately:
  //  - to an appropriate location before/after existing #includes, or
  //  - to right after the header guard, or
  //  - to the beginning of the file.
  for (auto I = ++Priorities.begin(), E = Priorities.end(); I != E; ++I)
    if (CategoryEndOffsets.find(*I) == CategoryEndOffsets.end())
      CategoryEndOffsets[*I] = CategoryEndOffsets[*std::prev(I)];

  bool NeedNewLineAtEnd = !Code.empty() && Code.back() != '\n';
  for (const auto &R : HeaderInsertions) {
    auto IncludeDirective = R.getReplacementText();
    bool Matched = IncludeRegex.match(IncludeDirective, &Matches);
    assert(Matched && "Header insertion replacement must have replacement text "
                      "'#include ...'");
    (void)Matched;
    auto IncludeName = Matches[2];
    if (ExistingIncludes.find(IncludeName) != ExistingIncludes.end()) {
      DEBUG(llvm::dbgs() << "Skip adding existing include : " << IncludeName
                         << "\n");
      continue;
    }
    int Category =
        Categories.getIncludePriority(IncludeName, /*CheckMainHeader=*/true);
    Offset = CategoryEndOffsets[Category];
    std::string NewInclude = !IncludeDirective.endswith("\n")
                                 ? (IncludeDirective + "\n").str()
                                 : IncludeDirective.str();
    // When inserting headers at end of the code, also append '\n' to the code
    // if it does not end with '\n'.
    if (NeedNewLineAtEnd && Offset == Code.size()) {
      NewInclude = "\n" + NewInclude;
      NeedNewLineAtEnd = false;
    }
    auto NewReplace = tooling::Replacement(FileName, Offset, 0, NewInclude);
    auto Err = Result.add(NewReplace);
    if (Err) {
      llvm::consumeError(std::move(Err));
      unsigned NewOffset = Result.getShiftedCodePosition(Offset);
      NewReplace = tooling::Replacement(FileName, NewOffset, 0, NewInclude);
      Result = Result.merge(tooling::Replacements(NewReplace));
    }
  }
  return Result;
}

} // anonymous namespace

llvm::Expected<tooling::Replacements>
cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces,
                          const FormatStyle &Style) {
  // We need to use lambda function here since there are two versions of
  // `cleanup`.
  auto Cleanup = [](const FormatStyle &Style, StringRef Code,
                    std::vector<tooling::Range> Ranges,
                    StringRef FileName) -> tooling::Replacements {
    return cleanup(Style, Code, Ranges, FileName);
  };
  // Make header insertion replacements insert new headers into correct blocks.
  tooling::Replacements NewReplaces =
      fixCppIncludeInsertions(Code, Replaces, Style);
  return processReplacements(Cleanup, Code, NewReplaces, Style);
d1897 1
a1897 2
  FormatStyle Expanded = expandPresets(Style);
  if (Expanded.DisableFormat)
d1900 18
a1917 16
  auto Env = Environment::CreateVirtualEnvironment(Code, FileName, Ranges);

  if (Style.Language == FormatStyle::LK_JavaScript &&
      Style.JavaScriptQuotes != FormatStyle::JSQS_Leave) {
    JavaScriptRequoter Requoter(*Env, Expanded);
    tooling::Replacements Requotes = Requoter.process();
    if (!Requotes.empty()) {
      auto NewCode = applyAllReplacements(Code, Requotes);
      if (NewCode) {
        auto NewEnv = Environment::CreateVirtualEnvironment(
            *NewCode, FileName,
            tooling::calculateRangesAfterReplacements(Requotes, Ranges));
        Formatter Format(*NewEnv, Expanded, IncompleteFormat);
        return Requotes.merge(Format.process());
      }
    }
d1919 1
a1919 12

  Formatter Format(*Env, Expanded, IncompleteFormat);
  return Format.process();
}

tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code,
                              ArrayRef<tooling::Range> Ranges,
                              StringRef FileName) {
  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
  Cleaner Clean(*Env, Style);
  return Clean.process();
d1933 1
a1933 1
  LangOpts.MicrosoftExt = 1;    // To get kw___try, kw___finally.
a1953 2
  if (FileName.endswith(".m") || FileName.endswith(".mm"))
    return FormatStyle::LK_ObjC;
d1963 1
a1963 5
                     StringRef FallbackStyle, StringRef Code,
                     vfs::FileSystem *FS) {
  if (!FS) {
    FS = vfs::getRealFileSystem().get();
  }
a1965 8

  // This is a very crude detection of whether a header contains ObjC code that
  // should be improved over time and probably be done on tokens, not one the
  // bare content of the file.
  if (Style.Language == FormatStyle::LK_Cpp && FileName.endswith(".h") &&
      (Code.contains("\n- (") || Code.contains("\n+ (")))
    Style.Language = FormatStyle::LK_ObjC;

d1991 1
a1991 5
  if (std::error_code EC = FS->makeAbsolute(Path)) {
    llvm::errs() << EC.message() << "\n";
    return Style;
  }

d1994 1
a1994 4

    auto Status = FS->status(Directory);
    if (!Status ||
        Status->getType() != llvm::sys::fs::file_type::directory_file) {
a1995 2
    }

d2000 4
a2004 3
    Status = FS->status(ConfigFile.str());
    bool IsFile =
        Status && (Status->getType() == llvm::sys::fs::file_type::regular_file);
d2010 1
a2010 3
      Status = FS->status(ConfigFile.str());
      IsFile = Status &&
               (Status->getType() == llvm::sys::fs::file_type::regular_file);
d2015 1
a2015 1
          FS->getBufferForFile(ConfigFile.str());
@


1.1.1.10
log
@Import clang r309604 from branches/release_50
@
text
@a19 1
#include "NamespaceEndCommentsFixer.h"
a24 1
#include "UsingDeclarationsSorter.h"
d45 1
a57 1
    IO.enumCase(Value, "TextProto", FormatStyle::LK_TextProto);
a97 1
    IO.enumCase(Value, "InlineOnly", FormatStyle::SFS_InlineOnly);
a124 8
template <> struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
  static void enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
    IO.enumCase(Value, "BeforeColon", FormatStyle::BCIS_BeforeColon);
    IO.enumCase(Value, "BeforeComma", FormatStyle::BCIS_BeforeComma);
    IO.enumCase(Value, "AfterColon", FormatStyle::BCIS_AfterColon);
  }
};

a172 12
template <> struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
  static void enumeration(IO &IO, FormatStyle::EscapedNewlineAlignmentStyle &Value) {
    IO.enumCase(Value, "DontAlign", FormatStyle::ENAS_DontAlign);
    IO.enumCase(Value, "Left", FormatStyle::ENAS_Left);
    IO.enumCase(Value, "Right", FormatStyle::ENAS_Right);

    // For backward compatibility.
    IO.enumCase(Value, "true", FormatStyle::ENAS_Left);
    IO.enumCase(Value, "false", FormatStyle::ENAS_Right);
  }
};

a234 1
      IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlines);
d249 1
a249 1
    IO.mapOptional("AlignEscapedNewlines", Style.AlignEscapedNewlines);
a290 2
    IO.mapOptional("BreakBeforeInheritanceComma",
                   Style.BreakBeforeInheritanceComma);
a292 2

    bool BreakConstructorInitializersBeforeComma = false;
d294 1
a294 10
                   BreakConstructorInitializersBeforeComma);
    IO.mapOptional("BreakConstructorInitializers",
                   Style.BreakConstructorInitializers);
    // If BreakConstructorInitializersBeforeComma was specified but
    // BreakConstructorInitializers was not, initialize the latter from the
    // former for backwards compatibility.
    if (BreakConstructorInitializersBeforeComma &&
        Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeColon)
      Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;

a299 1
    IO.mapOptional("CompactNamespaces", Style.CompactNamespaces);
a309 1
    IO.mapOptional("FixNamespaceComments", Style.FixNamespaceComments);
a328 2
    IO.mapOptional("PenaltyBreakAssignment",
                   Style.PenaltyBreakAssignment);
a340 1
    IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations);
a374 3
    IO.mapOptional("SplitEmptyFunction", Wrapping.SplitEmptyFunction);
    IO.mapOptional("SplitEmptyRecord", Wrapping.SplitEmptyRecord);
    IO.mapOptional("SplitEmptyNamespace", Wrapping.SplitEmptyNamespace);
a423 5
inline llvm::Error make_string_error(const llvm::Twine &Message) {
  return llvm::make_error<llvm::StringError>(Message,
                                             llvm::inconvertibleErrorCode());
}

d445 1
a445 2
                            false, false, false, false, false, true,
                            true,  true};
a457 2
    Expanded.BraceWrapping.SplitEmptyFunction = false;
    Expanded.BraceWrapping.SplitEmptyRecord = false;
d477 1
a477 2
                              true, true, true, true, true, true,
                              true, true};
d492 1
a492 1
  LLVMStyle.AlignEscapedNewlines = FormatStyle::ENAS_Right;
d508 1
a509 1
  LLVMStyle.BinPackParameters = true;
d514 1
a514 2
                             false, false, false, false, false, true,
                             true,  true};
d516 1
a516 2
  LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
  LLVMStyle.BreakBeforeInheritanceComma = false;
a519 1
  LLVMStyle.CompactNamespaces = false;
a525 1
  LLVMStyle.FixNamespaceComments = true;
d530 1
a530 1
                                 {"^(<|\"(gtest|gmock|isl|json)/)", 3},
d532 1
a532 1
  LLVMStyle.IncludeIsMainRegex = "(Test)?$";
d549 1
a561 1
  LLVMStyle.PenaltyBreakAssignment = prec::Assignment;
a570 1
  LLVMStyle.SortUsingDeclarations = true;
a575 6
  if (Language == FormatStyle::LK_TextProto) {
    FormatStyle GoogleStyle = getGoogleStyle(FormatStyle::LK_Proto);
    GoogleStyle.Language = FormatStyle::LK_TextProto;
    return GoogleStyle;
  }

d580 1
a580 1
  GoogleStyle.AlignEscapedNewlines = FormatStyle::ENAS_Left;
a616 2
    // taze:, triple slash directives (`/// <...`), @@tag followed by { for a lot
    // of JSDoc tags, and @@see, which is commonly followed by overlong URLs.
d618 1
a618 1
        "(taze:|^/[ \t]*<|(@@[A-Za-z_0-9-]+[ \\t]*{)|@@see)";
a650 2
    if (Language == FormatStyle::LK_ObjC)
      ChromiumStyle.ColumnLimit = 80;
d652 1
d668 1
a668 2
  MozillaStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
  MozillaStyle.BreakBeforeInheritanceComma = true;
a671 1
  MozillaStyle.FixNamespaceComments = false;
d689 1
a689 1
  Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeComma;
a691 1
  Style.FixNamespaceComments = false;
a708 1
  Style.FixNamespaceComments = false;
a717 1
  NoStyle.SortUsingDeclarations = false;
d895 2
a896 2
            FormattingAttemptStatus *Status)
      : TokenAnalyzer(Env, Style), Status(Status) {}
d918 1
a918 1
                           Env.getSourceManager(), Status)
d1000 1
a1000 1
  FormattingAttemptStatus *Status;
d1351 1
a1351 1
      CategoryRegexs.emplace_back(Category.Regex, llvm::Regex::IgnoreCase);
d1379 1
a1379 2
    if (FileStem.startswith(HeaderStem) ||
        FileStem.startswith_lower(HeaderStem)) {
d1381 1
a1381 2
          (HeaderStem + Style.IncludeIsMainRegex).str(),
          llvm::Regex::IgnoreCase);
a1459 7
bool isMpegTS(StringRef Code) {
  // MPEG transport streams use the ".ts" file extension. clang-format should
  // not attempt to format those. MPEG TS' frame format starts with 0x47 every
  // 189 bytes - detect that and return.
  return Code.size() > 188 && Code[0] == 0x47 && Code[188] == 0x47;
}

a1465 3
  if (Style.Language == FormatStyle::LanguageKind::LK_JavaScript &&
      isMpegTS(Code))
    return Replaces;
d1534 2
a1535 2
    llvm::function_ref<unsigned(const SourceManager &, Lexer &, Token &)>
        GetOffsetAfterSequence) {
d1544 1
a1544 1
  return GetOffsetAfterSequence(SourceMgr, Lex, Tok);
d1648 1
a1648 1
  if (!Style.isCpp())
d1807 1
a1807 2
                               StringRef FileName,
                               FormattingAttemptStatus *Status) {
a1810 2
  if (Expanded.Language == FormatStyle::LK_JavaScript && isMpegTS(Code))
    return tooling::Replacements();
d1812 1
a1812 15
  typedef std::function<tooling::Replacements(const Environment &)>
      AnalyzerPass;
  SmallVector<AnalyzerPass, 4> Passes;

  if (Style.Language == FormatStyle::LK_Cpp) {
    if (Style.FixNamespaceComments)
      Passes.emplace_back([&](const Environment &Env) {
        return NamespaceEndCommentsFixer(Env, Expanded).process();
      });

    if (Style.SortUsingDeclarations)
      Passes.emplace_back([&](const Environment &Env) {
        return UsingDeclarationsSorter(Env, Expanded).process();
      });
  }
d1815 11
a1825 24
      Style.JavaScriptQuotes != FormatStyle::JSQS_Leave)
    Passes.emplace_back([&](const Environment &Env) {
      return JavaScriptRequoter(Env, Expanded).process();
    });

  Passes.emplace_back([&](const Environment &Env) {
    return Formatter(Env, Expanded, Status).process();
  });

  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
  llvm::Optional<std::string> CurrentCode = None;
  tooling::Replacements Fixes;
  for (size_t I = 0, E = Passes.size(); I < E; ++I) {
    tooling::Replacements PassFixes = Passes[I](*Env);
    auto NewCode = applyAllReplacements(
        CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes);
    if (NewCode) {
      Fixes = Fixes.merge(PassFixes);
      if (I + 1 < E) {
        CurrentCode = std::move(*NewCode);
        Env = Environment::CreateVirtualEnvironment(
            *CurrentCode, FileName,
            tooling::calculateRangesAfterReplacements(Fixes, Ranges));
d1830 2
a1831 1
  return Fixes;
a1836 3
  // cleanups only apply to C++ (they mostly concern ctor commas etc.)
  if (Style.Language != FormatStyle::LK_Cpp)
    return tooling::Replacements();
a1842 30
tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               ArrayRef<tooling::Range> Ranges,
                               StringRef FileName, bool *IncompleteFormat) {
  FormattingAttemptStatus Status;
  auto Result = reformat(Style, Code, Ranges, FileName, &Status);
  if (!Status.FormatComplete)
    *IncompleteFormat = true;
  return Result;
}

tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style,
                                              StringRef Code,
                                              ArrayRef<tooling::Range> Ranges,
                                              StringRef FileName) {
  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
  NamespaceEndCommentsFixer Fix(*Env, Style);
  return Fix.process();
}

tooling::Replacements sortUsingDeclarations(const FormatStyle &Style,
                                            StringRef Code,
                                            ArrayRef<tooling::Range> Ranges,
                                            StringRef FileName) {
  std::unique_ptr<Environment> Env =
      Environment::CreateVirtualEnvironment(Code, FileName, Ranges);
  UsingDeclarationsSorter Sorter(*Env, Style);
  return Sorter.process();
}

a1847 1
  LangOpts.CPlusPlus1z = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
d1849 1
a1849 1
  bool AlternativeOperators = Style.isCpp();
d1885 3
a1887 3
llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName,
                                     StringRef FallbackStyleName,
                                     StringRef Code, vfs::FileSystem *FS) {
d1901 5
a1905 3
  FormatStyle FallbackStyle = getNoStyle();
  if (!getPredefinedStyle(FallbackStyleName, Style.Language, &FallbackStyle))
    return make_string_error("Invalid fallback style \"" + FallbackStyleName);
d1909 4
a1912 2
    if (std::error_code ec = parseConfiguration(StyleName, &Style))
      return make_string_error("Error parsing -style: " + ec.message());
d1918 2
a1919 1
      return make_string_error("Invalid value for -style");
d1926 4
a1929 2
  if (std::error_code EC = FS->makeAbsolute(Path))
    return make_string_error(EC.message());
d1946 1
a1946 1
    bool FoundConfigFile =
d1948 1
a1948 1
    if (!FoundConfigFile) {
d1954 2
a1955 2
      FoundConfigFile = Status && (Status->getType() ==
                                   llvm::sys::fs::file_type::regular_file);
d1958 1
a1958 1
    if (FoundConfigFile) {
d1961 4
a1964 2
      if (std::error_code EC = Text.getError())
        return make_string_error(EC.message());
d1973 3
a1975 2
        return make_string_error("Error reading " + ConfigFile + ": " +
                                 ec.message());
d1981 6
a1986 5
  if (!UnsuitableConfigFiles.empty())
    return make_string_error("Configuration file(s) do(es) not support " +
                             getLanguageName(Style.Language) + ": " +
                             UnsuitableConfigFiles);
  return FallbackStyle;
@


1.1.1.11
log
@Import clang r319952 from branches/release_50
@
text
@d509 1
a509 1
    Expanded.BraceWrapping.SplitEmptyFunction = true;
@


1.1.1.11.4.1
log
@Sync with HEAD
@
text
@d11 1
a11 1
/// This file implements functions declared in Format.h. This will be
a18 1
#include "FormatInternal.h"
a32 1
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
a33 1
#include "llvm/ADT/StringRef.h"
a40 1
#include <mutex>
a41 1
#include <unordered_map>
d47 1
a47 1
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
a104 8
template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
  static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
    IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
    IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
    IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
  }
};

d128 2
a129 4
template <>
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
  static void
  enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
a136 18
struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
  static void
  enumeration(IO &IO, FormatStyle::BreakInheritanceListStyle &Value) {
    IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
    IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
    IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
  static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
    IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
  }
};

template <>
a148 13
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
  static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value) {
    IO.enumCase(Value, "No", FormatStyle::BTDS_No);
    IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
    IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
    IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
  }
};

template <>
d184 2
a185 4
template <>
struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
  static void enumeration(IO &IO,
                          FormatStyle::EscapedNewlineAlignmentStyle &Value) {
a314 2

    bool BreakBeforeInheritanceComma = false;
d316 1
a316 10
                   BreakBeforeInheritanceComma);
    IO.mapOptional("BreakInheritanceList",
                   Style.BreakInheritanceList);
    // If BreakBeforeInheritanceComma was specified but
    // BreakInheritance was not, initialize the latter from the
    // former for backwards compatibility.
    if (BreakBeforeInheritanceComma &&
        Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
      Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;

d350 2
a351 3
    IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
    IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
    IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
a352 1
    IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
a363 1
    IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
d368 2
a369 1
    IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
a375 2
    IO.mapOptional("PenaltyBreakTemplateDeclaration",
                   Style.PenaltyBreakTemplateDeclaration);
a379 1
    IO.mapOptional("RawStringFormats", Style.RawStringFormats);
d384 1
a384 2
    IO.mapOptional("SpaceAfterTemplateKeyword",
                   Style.SpaceAfterTemplateKeyword);
a386 6
    IO.mapOptional("SpaceBeforeCpp11BracedList",
                   Style.SpaceBeforeCpp11BracedList);
    IO.mapOptional("SpaceBeforeCtorInitializerColon",
                   Style.SpaceBeforeCtorInitializerColon);
    IO.mapOptional("SpaceBeforeInheritanceColon",
                   Style.SpaceBeforeInheritanceColon);
a387 2
    IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
                   Style.SpaceBeforeRangeBasedForLoopColon);
a413 1
    IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
d423 4
a426 7
template <> struct MappingTraits<FormatStyle::RawStringFormat> {
  static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
    IO.mapOptional("Language", Format.Language);
    IO.mapOptional("Delimiters", Format.Delimiters);
    IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
    IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
    IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
d444 1
a444 1
      if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
d462 1
a462 1
  static const ParseErrorCategory C{};
d494 3
a496 3
  Expanded.BraceWrapping = {false, false, false, false, false,
                            false, false, false, false, false,
                            false, false, true,  true,  true};
a508 1
    Expanded.BraceWrapping.AfterExternBlock = true;
a524 1
    Expanded.BraceWrapping.AfterExternBlock = true;
d529 3
a531 2
    Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
                              true, true, true, true, true, true, true};
d561 1
a561 1
  LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
d567 3
a569 3
  LLVMStyle.BraceWrapping = {false, false, false, false, false,
                             false, false, false, false, false,
                             false, false, true,  true,  true};
d572 1
a572 1
  LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
d587 4
a590 6
  LLVMStyle.IncludeStyle.IncludeCategories = {
      {"^\"(llvm|llvm-c|clang|clang-c)/", 2},
      {"^(<|\"(gtest|gmock|isl|json)/)", 3},
      {".*", 1}};
  LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
  LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
a591 1
  LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
a599 1
  LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
a614 2
  LLVMStyle.SpaceBeforeCtorInitializerColon = true;
  LLVMStyle.SpaceBeforeInheritanceColon = true;
a615 1
  LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
a616 1
  LLVMStyle.SpaceBeforeCpp11BracedList = false;
a625 1
  LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
a637 1

d649 1
a649 1
  GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
d652 2
a653 3
  GoogleStyle.IncludeStyle.IncludeCategories = {
      {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
  GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
a655 1
  GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
d657 1
a657 1
  GoogleStyle.ObjCSpaceBeforeProtocolList = true;
a658 39
  GoogleStyle.RawStringFormats = {
      {
          FormatStyle::LK_Cpp,
          /*Delimiters=*/
          {
              "cc",
              "CC",
              "cpp",
              "Cpp",
              "CPP",
              "c++",
              "C++",
          },
          /*EnclosingFunctionNames=*/
          {},
          /*CanonicalDelimiter=*/"",
          /*BasedOnStyle=*/"google",
      },
      {
          FormatStyle::LK_TextProto,
          /*Delimiters=*/
          {
              "pb",
              "PB",
              "proto",
              "PROTO",
          },
          /*EnclosingFunctionNames=*/
          {
              "EqualsProto",
              "EquivToProto",
              "PARSE_TEST_PROTO",
              "PARSE_TEXT_PROTO",
              "ParseTextOrDie",
          },
          /*CanonicalDelimiter=*/"",
          /*BasedOnStyle=*/"google",
      },
  };
a692 1
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
a693 7
    GoogleStyle.Cpp11BracedListStyle = false;
    // This affects protocol buffer options specifications and text protos.
    // Text protos are currently mostly formatted inside C++ raw string literals
    // and often the current breaking behavior of string literals is not
    // beneficial there. Investigate turning this on once proper string reflow
    // has been implemented.
    GoogleStyle.BreakStringLiterals = false;
a694 1
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
d728 2
a729 1
  MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
d732 1
a732 1
  MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
d737 1
a737 1
  MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
a767 1
  Style.SpaceBeforeCpp11BracedList = true;
d824 1
a824 1
  Style->StyleSet.Clear();
d843 3
a845 3
        LLVM_DEBUG(llvm::dbgs()
                   << "Duplicate languages in the config file on positions "
                   << j << " and " << i << "\n");
a852 2
  FormatStyle::FormatStyleSet StyleSet;
  bool LanguageFound = false;
d854 6
a859 11
    if (Styles[i].Language != FormatStyle::LK_None)
      StyleSet.Add(Styles[i]);
    if (Styles[i].Language == Language)
      LanguageFound = true;
  }
  if (!LanguageFound) {
    if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
      return make_error_code(ParseError::Unsuitable);
    FormatStyle DefaultStyle = Styles[0];
    DefaultStyle.Language = Language;
    StyleSet.Add(std::move(DefaultStyle));
d861 1
a861 2
  *Style = *StyleSet.Get(Language);
  return make_error_code(ParseError::Success);
a874 32
llvm::Optional<FormatStyle>
FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
  if (!Styles)
    return None;
  auto It = Styles->find(Language);
  if (It == Styles->end())
    return None;
  FormatStyle Style = It->second;
  Style.StyleSet = *this;
  return Style;
}

void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
  assert(Style.Language != LK_None &&
         "Cannot add a style for LK_None to a StyleSet");
  assert(
      !Style.StyleSet.Styles &&
      "Cannot add a style associated with an existing StyleSet to a StyleSet");
  if (!Styles)
    Styles = std::make_shared<MapType>();
  (*Styles)[Style.Language] = std::move(Style);
}

void FormatStyle::FormatStyleSet::Clear() {
  Styles.reset();
}

llvm::Optional<FormatStyle>
FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
  return StyleSet.Get(Language);
}

d882 1
a882 1
  std::pair<tooling::Replacements, unsigned>
d886 2
a887 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d890 1
a890 1
    return {Result, 0};
d971 1
a971 1
  std::pair<tooling::Replacements, unsigned>
d977 2
a978 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d990 3
a992 10
    unsigned Penalty =
        UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
                               Tokens.getKeywords(), Env.getSourceManager(),
                               Status)
            .format(AnnotatedLines, /*DryRun=*/false,
                    /*AdditionalIndent=*/0,
                    /*FixBadIndentation=*/false,
                    /*FirstStartColumn=*/Env.getFirstStartColumn(),
                    /*NextStartColumn=*/Env.getNextStartColumn(),
                    /*LastStartColumn=*/Env.getLastStartColumn());
d995 2
a996 2
        return std::make_pair(Result, 0);
    return std::make_pair(Result, Penalty);
d1000 1
d1085 1
a1085 1
  std::pair<tooling::Replacements, unsigned>
d1096 2
a1097 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d1113 1
a1113 1
    return {generateFixes(), 0};
a1299 122
class ObjCHeaderStyleGuesser : public TokenAnalyzer {
public:
  ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style), IsObjC(false) {}

  std::pair<tooling::Replacements, unsigned>
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    assert(Style.Language == FormatStyle::LK_Cpp);
    IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
    tooling::Replacements Result;
    return {Result, 0};
  }

  bool isObjC() { return IsObjC; }

private:
  static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                          const AdditionalKeywords &Keywords) {
    // Keep this array sorted, since we are binary searching over it.
    static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
        "CGFloat",
        "CGPoint",
        "CGPointMake",
        "CGPointZero",
        "CGRect",
        "CGRectEdge",
        "CGRectInfinite",
        "CGRectMake",
        "CGRectNull",
        "CGRectZero",
        "CGSize",
        "CGSizeMake",
        "CGVector",
        "CGVectorMake",
        "NSAffineTransform",
        "NSArray",
        "NSAttributedString",
        "NSBlockOperation",
        "NSBundle",
        "NSCache",
        "NSCalendar",
        "NSCharacterSet",
        "NSCountedSet",
        "NSData",
        "NSDataDetector",
        "NSDecimal",
        "NSDecimalNumber",
        "NSDictionary",
        "NSEdgeInsets",
        "NSHashTable",
        "NSIndexPath",
        "NSIndexSet",
        "NSInteger",
        "NSInvocationOperation",
        "NSLocale",
        "NSMapTable",
        "NSMutableArray",
        "NSMutableAttributedString",
        "NSMutableCharacterSet",
        "NSMutableData",
        "NSMutableDictionary",
        "NSMutableIndexSet",
        "NSMutableOrderedSet",
        "NSMutableSet",
        "NSMutableString",
        "NSNumber",
        "NSNumberFormatter",
        "NSObject",
        "NSOperation",
        "NSOperationQueue",
        "NSOperationQueuePriority",
        "NSOrderedSet",
        "NSPoint",
        "NSPointerArray",
        "NSQualityOfService",
        "NSRange",
        "NSRect",
        "NSRegularExpression",
        "NSSet",
        "NSSize",
        "NSString",
        "NSTimeZone",
        "NSUInteger",
        "NSURL",
        "NSURLComponents",
        "NSURLQueryItem",
        "NSUUID",
        "NSValue",
        "UIImage",
        "UIView",
    };

    for (auto Line : AnnotatedLines) {
      for (const FormatToken *FormatTok = Line->First; FormatTok;
           FormatTok = FormatTok->Next) {
        if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
             (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
              FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
                                 tok::l_brace))) ||
            (FormatTok->Tok.isAnyIdentifier() &&
             std::binary_search(std::begin(FoundationIdentifiers),
                                std::end(FoundationIdentifiers),
                                FormatTok->TokenText)) ||
            FormatTok->is(TT_ObjCStringLiteral) ||
            FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
                               TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
                               TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
                               TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
          return true;
        }
        if (guessIsObjC(Line->Children, Keywords))
          return true;
      }
    }
    return false;
  }

  bool IsObjC;
};

a1388 2
  int CurrentCategory = Includes.front().Category;

d1392 1
a1392 2
      std::is_sorted(Indices.begin(), Indices.end()) &&
      Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
d1397 1
a1397 1
    if (!result.empty()) {
a1398 5
      if (Style.IncludeStyle.IncludeBlocks ==
              tooling::IncludeStyle::IBS_Regroup &&
          CurrentCategory != Includes[Index].Category)
        result += "\n";
    }
a1401 1
    CurrentCategory = Includes[Index].Category;
d1416 54
d1493 1
a1493 1
  tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
a1508 6
    const bool EmptyLineSkipped =
        Trimmed.empty() &&
        (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
         Style.IncludeStyle.IncludeBlocks ==
             tooling::IncludeStyle::IBS_Regroup);

d1518 1
a1518 1
      } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
a1541 2
bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }

a1547 2
  if (isLikelyXml(Code))
    return Replaces;
d1613 116
d1757 3
d1762 1
a1762 1
  tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
d1764 47
a1810 10
  for (const auto &Header : HeadersToDelete) {
    tooling::Replacements Replaces =
        Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
    for (const auto &R : Replaces) {
      auto Err = Result.add(R);
      if (Err) {
        // Ignore the deletion on conflict.
        llvm::errs() << "Failed to add header deletion replacement for "
                     << Header << ": " << llvm::toString(std::move(Err))
                     << "\n";
d1813 1
d1816 20
a1835 2
  llvm::Regex IncludeRegex = llvm::Regex(IncludeRegexPattern);
  llvm::SmallVector<StringRef, 4> Matches;
d1843 24
a1866 11
    auto Replace =
        Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
    if (Replace) {
      auto Err = Result.add(*Replace);
      if (Err) {
        llvm::consumeError(std::move(Err));
        unsigned NewOffset = Result.getShiftedCodePosition(Replace->getOffset());
        auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
                                            Replace->getReplacementText());
        Result = Result.merge(tooling::Replacements(Shifted));
      }
d1890 4
a1893 6
namespace internal {
std::pair<tooling::Replacements, unsigned>
reformat(const FormatStyle &Style, StringRef Code,
         ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
         unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
         FormattingAttemptStatus *Status) {
d1896 1
a1896 3
    return {tooling::Replacements(), 0};
  if (isLikelyXml(Code))
    return {tooling::Replacements(), 0};
d1898 1
a1898 1
    return {tooling::Replacements(), 0};
d1900 1
a1900 2
  typedef std::function<std::pair<tooling::Replacements, unsigned>(
      const Environment &)>
d1926 2
a1927 3
  auto Env =
      llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
                                     NextStartColumn, LastStartColumn);
a1929 1
  unsigned Penalty = 0;
d1931 1
a1931 1
    std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
d1933 1
a1933 1
        CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
d1935 1
a1935 2
      Fixes = Fixes.merge(PassFixes.first);
      Penalty += PassFixes.second;
d1938 1
a1938 1
        Env = llvm::make_unique<Environment>(
d1940 1
a1940 2
            tooling::calculateRangesAfterReplacements(Fixes, Ranges),
            FirstStartColumn, NextStartColumn, LastStartColumn);
d1945 1
a1945 13
  return {Fixes, Penalty};
}
} // namespace internal

tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               ArrayRef<tooling::Range> Ranges,
                               StringRef FileName,
                               FormattingAttemptStatus *Status) {
  return internal::reformat(Style, Code, Ranges,
                            /*FirstStartColumn=*/0,
                            /*NextStartColumn=*/0,
                            /*LastStartColumn=*/0, FileName, Status)
      .first;
d1954 4
a1957 1
  return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
d1974 4
a1977 3
  return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
      .process()
      .first;
d1984 4
a1987 3
  return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
      .process()
      .first;
d1995 1
a1995 2
  LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
a2027 5
  if (FileName.endswith_lower(".textpb") ||
      FileName.endswith_lower(".pb.txt") ||
      FileName.endswith_lower(".textproto") ||
      FileName.endswith_lower(".asciipb"))
    return FormatStyle::LK_TextProto;
a2032 22
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
  const auto GuessedLanguage = getLanguageByFileName(FileName);
  if (GuessedLanguage == FormatStyle::LK_Cpp) {
    auto Extension = llvm::sys::path::extension(FileName);
    // If there's no file extension (or it's .h), we need to check the contents
    // of the code to see if it contains Objective-C.
    if (Extension.empty() || Extension == ".h") {
      auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
      Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
      ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
      Guesser.process();
      if (Guesser.isObjC())
        return FormatStyle::LK_ObjC;
    }
  }
  return GuessedLanguage;
}

const char *DefaultFormatStyle = "file";

const char *DefaultFallbackStyle = "LLVM";

d2040 8
a2047 1
  Style.Language = guessLanguage(FileName, Code);
d2084 1
a2084 1
    LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
d2093 1
a2093 1
      LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
d2115 1
a2115 2
      LLVM_DEBUG(llvm::dbgs()
                 << "Using configuration file " << ConfigFile << "\n");
@


1.1.1.11.4.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.11.2.1
log
@Sync with HEAD
@
text
@d11 1
a11 1
/// This file implements functions declared in Format.h. This will be
a18 1
#include "FormatInternal.h"
a32 1
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
a33 1
#include "llvm/ADT/StringRef.h"
a40 1
#include <mutex>
a41 1
#include <unordered_map>
d47 1
a47 1
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
a104 8
template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
  static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
    IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
    IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
    IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
  }
};

d128 2
a129 4
template <>
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
  static void
  enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
a136 18
struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
  static void
  enumeration(IO &IO, FormatStyle::BreakInheritanceListStyle &Value) {
    IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
    IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
    IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
  static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
    IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
  }
};

template <>
a148 13
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
  static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value) {
    IO.enumCase(Value, "No", FormatStyle::BTDS_No);
    IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
    IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
    IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
  }
};

template <>
d184 2
a185 4
template <>
struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
  static void enumeration(IO &IO,
                          FormatStyle::EscapedNewlineAlignmentStyle &Value) {
a314 2

    bool BreakBeforeInheritanceComma = false;
d316 1
a316 10
                   BreakBeforeInheritanceComma);
    IO.mapOptional("BreakInheritanceList",
                   Style.BreakInheritanceList);
    // If BreakBeforeInheritanceComma was specified but
    // BreakInheritance was not, initialize the latter from the
    // former for backwards compatibility.
    if (BreakBeforeInheritanceComma &&
        Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
      Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;

d350 2
a351 3
    IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
    IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
    IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
a352 1
    IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
a363 1
    IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
d368 2
a369 1
    IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
a375 2
    IO.mapOptional("PenaltyBreakTemplateDeclaration",
                   Style.PenaltyBreakTemplateDeclaration);
a379 1
    IO.mapOptional("RawStringFormats", Style.RawStringFormats);
d384 1
a384 2
    IO.mapOptional("SpaceAfterTemplateKeyword",
                   Style.SpaceAfterTemplateKeyword);
a386 6
    IO.mapOptional("SpaceBeforeCpp11BracedList",
                   Style.SpaceBeforeCpp11BracedList);
    IO.mapOptional("SpaceBeforeCtorInitializerColon",
                   Style.SpaceBeforeCtorInitializerColon);
    IO.mapOptional("SpaceBeforeInheritanceColon",
                   Style.SpaceBeforeInheritanceColon);
a387 2
    IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
                   Style.SpaceBeforeRangeBasedForLoopColon);
a413 1
    IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
d423 4
a426 7
template <> struct MappingTraits<FormatStyle::RawStringFormat> {
  static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
    IO.mapOptional("Language", Format.Language);
    IO.mapOptional("Delimiters", Format.Delimiters);
    IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
    IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
    IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
d444 1
a444 1
      if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
d462 1
a462 1
  static const ParseErrorCategory C{};
d494 3
a496 3
  Expanded.BraceWrapping = {false, false, false, false, false,
                            false, false, false, false, false,
                            false, false, true,  true,  true};
a508 1
    Expanded.BraceWrapping.AfterExternBlock = true;
a524 1
    Expanded.BraceWrapping.AfterExternBlock = true;
d529 3
a531 2
    Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
                              true, true, true, true, true, true, true};
d561 1
a561 1
  LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
d567 3
a569 3
  LLVMStyle.BraceWrapping = {false, false, false, false, false,
                             false, false, false, false, false,
                             false, false, true,  true,  true};
d572 1
a572 1
  LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
d587 4
a590 6
  LLVMStyle.IncludeStyle.IncludeCategories = {
      {"^\"(llvm|llvm-c|clang|clang-c)/", 2},
      {"^(<|\"(gtest|gmock|isl|json)/)", 3},
      {".*", 1}};
  LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
  LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
a591 1
  LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
a599 1
  LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
a614 2
  LLVMStyle.SpaceBeforeCtorInitializerColon = true;
  LLVMStyle.SpaceBeforeInheritanceColon = true;
a615 1
  LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
a616 1
  LLVMStyle.SpaceBeforeCpp11BracedList = false;
a625 1
  LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
a637 1

d649 1
a649 1
  GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
d652 2
a653 3
  GoogleStyle.IncludeStyle.IncludeCategories = {
      {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
  GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
a655 1
  GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
d657 1
a657 1
  GoogleStyle.ObjCSpaceBeforeProtocolList = true;
a658 39
  GoogleStyle.RawStringFormats = {
      {
          FormatStyle::LK_Cpp,
          /*Delimiters=*/
          {
              "cc",
              "CC",
              "cpp",
              "Cpp",
              "CPP",
              "c++",
              "C++",
          },
          /*EnclosingFunctionNames=*/
          {},
          /*CanonicalDelimiter=*/"",
          /*BasedOnStyle=*/"google",
      },
      {
          FormatStyle::LK_TextProto,
          /*Delimiters=*/
          {
              "pb",
              "PB",
              "proto",
              "PROTO",
          },
          /*EnclosingFunctionNames=*/
          {
              "EqualsProto",
              "EquivToProto",
              "PARSE_TEST_PROTO",
              "PARSE_TEXT_PROTO",
              "ParseTextOrDie",
          },
          /*CanonicalDelimiter=*/"",
          /*BasedOnStyle=*/"google",
      },
  };
a692 1
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
a693 7
    GoogleStyle.Cpp11BracedListStyle = false;
    // This affects protocol buffer options specifications and text protos.
    // Text protos are currently mostly formatted inside C++ raw string literals
    // and often the current breaking behavior of string literals is not
    // beneficial there. Investigate turning this on once proper string reflow
    // has been implemented.
    GoogleStyle.BreakStringLiterals = false;
a694 1
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
d728 2
a729 1
  MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
d732 1
a732 1
  MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
d737 1
a737 1
  MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
a767 1
  Style.SpaceBeforeCpp11BracedList = true;
d824 1
a824 1
  Style->StyleSet.Clear();
d843 3
a845 3
        LLVM_DEBUG(llvm::dbgs()
                   << "Duplicate languages in the config file on positions "
                   << j << " and " << i << "\n");
a852 2
  FormatStyle::FormatStyleSet StyleSet;
  bool LanguageFound = false;
d854 6
a859 11
    if (Styles[i].Language != FormatStyle::LK_None)
      StyleSet.Add(Styles[i]);
    if (Styles[i].Language == Language)
      LanguageFound = true;
  }
  if (!LanguageFound) {
    if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
      return make_error_code(ParseError::Unsuitable);
    FormatStyle DefaultStyle = Styles[0];
    DefaultStyle.Language = Language;
    StyleSet.Add(std::move(DefaultStyle));
d861 1
a861 2
  *Style = *StyleSet.Get(Language);
  return make_error_code(ParseError::Success);
a874 32
llvm::Optional<FormatStyle>
FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
  if (!Styles)
    return None;
  auto It = Styles->find(Language);
  if (It == Styles->end())
    return None;
  FormatStyle Style = It->second;
  Style.StyleSet = *this;
  return Style;
}

void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
  assert(Style.Language != LK_None &&
         "Cannot add a style for LK_None to a StyleSet");
  assert(
      !Style.StyleSet.Styles &&
      "Cannot add a style associated with an existing StyleSet to a StyleSet");
  if (!Styles)
    Styles = std::make_shared<MapType>();
  (*Styles)[Style.Language] = std::move(Style);
}

void FormatStyle::FormatStyleSet::Clear() {
  Styles.reset();
}

llvm::Optional<FormatStyle>
FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
  return StyleSet.Get(Language);
}

d882 1
a882 1
  std::pair<tooling::Replacements, unsigned>
d886 2
a887 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d890 1
a890 1
    return {Result, 0};
d971 1
a971 1
  std::pair<tooling::Replacements, unsigned>
d977 2
a978 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d990 3
a992 10
    unsigned Penalty =
        UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
                               Tokens.getKeywords(), Env.getSourceManager(),
                               Status)
            .format(AnnotatedLines, /*DryRun=*/false,
                    /*AdditionalIndent=*/0,
                    /*FixBadIndentation=*/false,
                    /*FirstStartColumn=*/Env.getFirstStartColumn(),
                    /*NextStartColumn=*/Env.getNextStartColumn(),
                    /*LastStartColumn=*/Env.getLastStartColumn());
d995 2
a996 2
        return std::make_pair(Result, 0);
    return std::make_pair(Result, Penalty);
d1000 1
d1085 1
a1085 1
  std::pair<tooling::Replacements, unsigned>
d1096 2
a1097 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d1113 1
a1113 1
    return {generateFixes(), 0};
a1299 122
class ObjCHeaderStyleGuesser : public TokenAnalyzer {
public:
  ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style), IsObjC(false) {}

  std::pair<tooling::Replacements, unsigned>
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    assert(Style.Language == FormatStyle::LK_Cpp);
    IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
    tooling::Replacements Result;
    return {Result, 0};
  }

  bool isObjC() { return IsObjC; }

private:
  static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                          const AdditionalKeywords &Keywords) {
    // Keep this array sorted, since we are binary searching over it.
    static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
        "CGFloat",
        "CGPoint",
        "CGPointMake",
        "CGPointZero",
        "CGRect",
        "CGRectEdge",
        "CGRectInfinite",
        "CGRectMake",
        "CGRectNull",
        "CGRectZero",
        "CGSize",
        "CGSizeMake",
        "CGVector",
        "CGVectorMake",
        "NSAffineTransform",
        "NSArray",
        "NSAttributedString",
        "NSBlockOperation",
        "NSBundle",
        "NSCache",
        "NSCalendar",
        "NSCharacterSet",
        "NSCountedSet",
        "NSData",
        "NSDataDetector",
        "NSDecimal",
        "NSDecimalNumber",
        "NSDictionary",
        "NSEdgeInsets",
        "NSHashTable",
        "NSIndexPath",
        "NSIndexSet",
        "NSInteger",
        "NSInvocationOperation",
        "NSLocale",
        "NSMapTable",
        "NSMutableArray",
        "NSMutableAttributedString",
        "NSMutableCharacterSet",
        "NSMutableData",
        "NSMutableDictionary",
        "NSMutableIndexSet",
        "NSMutableOrderedSet",
        "NSMutableSet",
        "NSMutableString",
        "NSNumber",
        "NSNumberFormatter",
        "NSObject",
        "NSOperation",
        "NSOperationQueue",
        "NSOperationQueuePriority",
        "NSOrderedSet",
        "NSPoint",
        "NSPointerArray",
        "NSQualityOfService",
        "NSRange",
        "NSRect",
        "NSRegularExpression",
        "NSSet",
        "NSSize",
        "NSString",
        "NSTimeZone",
        "NSUInteger",
        "NSURL",
        "NSURLComponents",
        "NSURLQueryItem",
        "NSUUID",
        "NSValue",
        "UIImage",
        "UIView",
    };

    for (auto Line : AnnotatedLines) {
      for (const FormatToken *FormatTok = Line->First; FormatTok;
           FormatTok = FormatTok->Next) {
        if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
             (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
              FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
                                 tok::l_brace))) ||
            (FormatTok->Tok.isAnyIdentifier() &&
             std::binary_search(std::begin(FoundationIdentifiers),
                                std::end(FoundationIdentifiers),
                                FormatTok->TokenText)) ||
            FormatTok->is(TT_ObjCStringLiteral) ||
            FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
                               TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
                               TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
                               TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
          return true;
        }
        if (guessIsObjC(Line->Children, Keywords))
          return true;
      }
    }
    return false;
  }

  bool IsObjC;
};

a1388 2
  int CurrentCategory = Includes.front().Category;

d1392 1
a1392 2
      std::is_sorted(Indices.begin(), Indices.end()) &&
      Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
d1397 1
a1397 1
    if (!result.empty()) {
a1398 5
      if (Style.IncludeStyle.IncludeBlocks ==
              tooling::IncludeStyle::IBS_Regroup &&
          CurrentCategory != Includes[Index].Category)
        result += "\n";
    }
a1401 1
    CurrentCategory = Includes[Index].Category;
d1416 54
d1493 1
a1493 1
  tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
a1508 6
    const bool EmptyLineSkipped =
        Trimmed.empty() &&
        (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
         Style.IncludeStyle.IncludeBlocks ==
             tooling::IncludeStyle::IBS_Regroup);

d1518 1
a1518 1
      } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
a1541 2
bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }

a1547 2
  if (isLikelyXml(Code))
    return Replaces;
d1613 116
d1757 3
d1762 1
a1762 1
  tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
d1764 47
a1810 10
  for (const auto &Header : HeadersToDelete) {
    tooling::Replacements Replaces =
        Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
    for (const auto &R : Replaces) {
      auto Err = Result.add(R);
      if (Err) {
        // Ignore the deletion on conflict.
        llvm::errs() << "Failed to add header deletion replacement for "
                     << Header << ": " << llvm::toString(std::move(Err))
                     << "\n";
d1813 1
d1816 20
a1835 2
  llvm::Regex IncludeRegex = llvm::Regex(IncludeRegexPattern);
  llvm::SmallVector<StringRef, 4> Matches;
d1843 24
a1866 11
    auto Replace =
        Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
    if (Replace) {
      auto Err = Result.add(*Replace);
      if (Err) {
        llvm::consumeError(std::move(Err));
        unsigned NewOffset = Result.getShiftedCodePosition(Replace->getOffset());
        auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
                                            Replace->getReplacementText());
        Result = Result.merge(tooling::Replacements(Shifted));
      }
d1890 4
a1893 6
namespace internal {
std::pair<tooling::Replacements, unsigned>
reformat(const FormatStyle &Style, StringRef Code,
         ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
         unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
         FormattingAttemptStatus *Status) {
d1896 1
a1896 3
    return {tooling::Replacements(), 0};
  if (isLikelyXml(Code))
    return {tooling::Replacements(), 0};
d1898 1
a1898 1
    return {tooling::Replacements(), 0};
d1900 1
a1900 2
  typedef std::function<std::pair<tooling::Replacements, unsigned>(
      const Environment &)>
d1926 2
a1927 3
  auto Env =
      llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
                                     NextStartColumn, LastStartColumn);
a1929 1
  unsigned Penalty = 0;
d1931 1
a1931 1
    std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
d1933 1
a1933 1
        CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
d1935 1
a1935 2
      Fixes = Fixes.merge(PassFixes.first);
      Penalty += PassFixes.second;
d1938 1
a1938 1
        Env = llvm::make_unique<Environment>(
d1940 1
a1940 2
            tooling::calculateRangesAfterReplacements(Fixes, Ranges),
            FirstStartColumn, NextStartColumn, LastStartColumn);
d1945 1
a1945 13
  return {Fixes, Penalty};
}
} // namespace internal

tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               ArrayRef<tooling::Range> Ranges,
                               StringRef FileName,
                               FormattingAttemptStatus *Status) {
  return internal::reformat(Style, Code, Ranges,
                            /*FirstStartColumn=*/0,
                            /*NextStartColumn=*/0,
                            /*LastStartColumn=*/0, FileName, Status)
      .first;
d1954 4
a1957 1
  return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
d1974 4
a1977 3
  return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
      .process()
      .first;
d1984 4
a1987 3
  return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
      .process()
      .first;
d1995 1
a1995 2
  LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
a2027 5
  if (FileName.endswith_lower(".textpb") ||
      FileName.endswith_lower(".pb.txt") ||
      FileName.endswith_lower(".textproto") ||
      FileName.endswith_lower(".asciipb"))
    return FormatStyle::LK_TextProto;
a2032 22
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
  const auto GuessedLanguage = getLanguageByFileName(FileName);
  if (GuessedLanguage == FormatStyle::LK_Cpp) {
    auto Extension = llvm::sys::path::extension(FileName);
    // If there's no file extension (or it's .h), we need to check the contents
    // of the code to see if it contains Objective-C.
    if (Extension.empty() || Extension == ".h") {
      auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
      Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
      ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
      Guesser.process();
      if (Guesser.isObjC())
        return FormatStyle::LK_ObjC;
    }
  }
  return GuessedLanguage;
}

const char *DefaultFormatStyle = "file";

const char *DefaultFallbackStyle = "LLVM";

d2040 8
a2047 1
  Style.Language = guessLanguage(FileName, Code);
d2084 1
a2084 1
    LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
d2093 1
a2093 1
      LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
d2115 1
a2115 2
      LLVM_DEBUG(llvm::dbgs()
                 << "Using configuration file " << ConfigFile << "\n");
@


1.1.1.12
log
@Import clang r337282 from trunk
@
text
@d11 1
a11 1
/// This file implements functions declared in Format.h. This will be
a18 1
#include "FormatInternal.h"
a32 1
#include "clang/Tooling/Inclusions/HeaderIncludes.h"
a33 1
#include "llvm/ADT/StringRef.h"
a40 1
#include <mutex>
a41 1
#include <unordered_map>
d47 1
a47 1
LLVM_YAML_IS_SEQUENCE_VECTOR(clang::format::FormatStyle::RawStringFormat)
a104 8
template <> struct ScalarEnumerationTraits<FormatStyle::BinPackStyle> {
  static void enumeration(IO &IO, FormatStyle::BinPackStyle &Value) {
    IO.enumCase(Value, "Auto", FormatStyle::BPS_Auto);
    IO.enumCase(Value, "Always", FormatStyle::BPS_Always);
    IO.enumCase(Value, "Never", FormatStyle::BPS_Never);
  }
};

d128 2
a129 4
template <>
struct ScalarEnumerationTraits<FormatStyle::BreakConstructorInitializersStyle> {
  static void
  enumeration(IO &IO, FormatStyle::BreakConstructorInitializersStyle &Value) {
a136 18
struct ScalarEnumerationTraits<FormatStyle::BreakInheritanceListStyle> {
  static void
  enumeration(IO &IO, FormatStyle::BreakInheritanceListStyle &Value) {
    IO.enumCase(Value, "BeforeColon", FormatStyle::BILS_BeforeColon);
    IO.enumCase(Value, "BeforeComma", FormatStyle::BILS_BeforeComma);
    IO.enumCase(Value, "AfterColon", FormatStyle::BILS_AfterColon);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::PPDirectiveIndentStyle> {
  static void enumeration(IO &IO, FormatStyle::PPDirectiveIndentStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::PPDIS_None);
    IO.enumCase(Value, "AfterHash", FormatStyle::PPDIS_AfterHash);
  }
};

template <>
a148 13
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
  static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value) {
    IO.enumCase(Value, "No", FormatStyle::BTDS_No);
    IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
    IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
    IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
  }
};

template <>
d184 2
a185 4
template <>
struct ScalarEnumerationTraits<FormatStyle::EscapedNewlineAlignmentStyle> {
  static void enumeration(IO &IO,
                          FormatStyle::EscapedNewlineAlignmentStyle &Value) {
a314 2

    bool BreakBeforeInheritanceComma = false;
d316 1
a316 10
                   BreakBeforeInheritanceComma);
    IO.mapOptional("BreakInheritanceList",
                   Style.BreakInheritanceList);
    // If BreakBeforeInheritanceComma was specified but
    // BreakInheritance was not, initialize the latter from the
    // former for backwards compatibility.
    if (BreakBeforeInheritanceComma &&
        Style.BreakInheritanceList == FormatStyle::BILS_BeforeColon)
      Style.BreakInheritanceList = FormatStyle::BILS_BeforeComma;

d350 2
a351 3
    IO.mapOptional("IncludeBlocks", Style.IncludeStyle.IncludeBlocks);
    IO.mapOptional("IncludeCategories", Style.IncludeStyle.IncludeCategories);
    IO.mapOptional("IncludeIsMainRegex", Style.IncludeStyle.IncludeIsMainRegex);
a352 1
    IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives);
a363 1
    IO.mapOptional("ObjCBinPackProtocolList", Style.ObjCBinPackProtocolList);
d368 2
a369 1
    IO.mapOptional("PenaltyBreakAssignment", Style.PenaltyBreakAssignment);
a375 2
    IO.mapOptional("PenaltyBreakTemplateDeclaration",
                   Style.PenaltyBreakTemplateDeclaration);
a379 1
    IO.mapOptional("RawStringFormats", Style.RawStringFormats);
d384 1
a384 2
    IO.mapOptional("SpaceAfterTemplateKeyword",
                   Style.SpaceAfterTemplateKeyword);
a386 6
    IO.mapOptional("SpaceBeforeCpp11BracedList",
                   Style.SpaceBeforeCpp11BracedList);
    IO.mapOptional("SpaceBeforeCtorInitializerColon",
                   Style.SpaceBeforeCtorInitializerColon);
    IO.mapOptional("SpaceBeforeInheritanceColon",
                   Style.SpaceBeforeInheritanceColon);
a387 2
    IO.mapOptional("SpaceBeforeRangeBasedForLoopColon",
                   Style.SpaceBeforeRangeBasedForLoopColon);
a413 1
    IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
d423 4
a426 7
template <> struct MappingTraits<FormatStyle::RawStringFormat> {
  static void mapping(IO &IO, FormatStyle::RawStringFormat &Format) {
    IO.mapOptional("Language", Format.Language);
    IO.mapOptional("Delimiters", Format.Delimiters);
    IO.mapOptional("EnclosingFunctions", Format.EnclosingFunctions);
    IO.mapOptional("CanonicalDelimiter", Format.CanonicalDelimiter);
    IO.mapOptional("BasedOnStyle", Format.BasedOnStyle);
d444 1
a444 1
      if (!Seq.empty() && Seq[0].Language == FormatStyle::LK_None) {
d462 1
a462 1
  static const ParseErrorCategory C{};
d494 3
a496 3
  Expanded.BraceWrapping = {false, false, false, false, false,
                            false, false, false, false, false,
                            false, false, true,  true,  true};
a508 1
    Expanded.BraceWrapping.AfterExternBlock = true;
a524 1
    Expanded.BraceWrapping.AfterExternBlock = true;
d529 3
a531 2
    Expanded.BraceWrapping = {true, true, true, true, true, true, true, true,
                              true, true, true, true, true, true, true};
d561 1
a561 1
  LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
d567 3
a569 3
  LLVMStyle.BraceWrapping = {false, false, false, false, false,
                             false, false, false, false, false,
                             false, false, true,  true,  true};
d572 1
a572 1
  LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon;
d587 4
a590 6
  LLVMStyle.IncludeStyle.IncludeCategories = {
      {"^\"(llvm|llvm-c|clang|clang-c)/", 2},
      {"^(<|\"(gtest|gmock|isl|json)/)", 3},
      {".*", 1}};
  LLVMStyle.IncludeStyle.IncludeIsMainRegex = "(Test)?$";
  LLVMStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Preserve;
a591 1
  LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
a599 1
  LLVMStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Auto;
a614 2
  LLVMStyle.SpaceBeforeCtorInitializerColon = true;
  LLVMStyle.SpaceBeforeInheritanceColon = true;
a615 1
  LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
a616 1
  LLVMStyle.SpaceBeforeCpp11BracedList = false;
a625 1
  LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
a637 1

d649 1
a649 1
  GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
d652 2
a653 3
  GoogleStyle.IncludeStyle.IncludeCategories = {
      {"^<ext/.*\\.h>", 2}, {"^<.*\\.h>", 1}, {"^<.*", 2}, {".*", 3}};
  GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$";
a655 1
  GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never;
d657 1
a657 1
  GoogleStyle.ObjCSpaceBeforeProtocolList = true;
a658 39
  GoogleStyle.RawStringFormats = {
      {
          FormatStyle::LK_Cpp,
          /*Delimiters=*/
          {
              "cc",
              "CC",
              "cpp",
              "Cpp",
              "CPP",
              "c++",
              "C++",
          },
          /*EnclosingFunctionNames=*/
          {},
          /*CanonicalDelimiter=*/"",
          /*BasedOnStyle=*/"google",
      },
      {
          FormatStyle::LK_TextProto,
          /*Delimiters=*/
          {
              "pb",
              "PB",
              "proto",
              "PROTO",
          },
          /*EnclosingFunctionNames=*/
          {
              "EqualsProto",
              "EquivToProto",
              "PARSE_TEST_PROTO",
              "PARSE_TEXT_PROTO",
              "ParseTextOrDie",
          },
          /*CanonicalDelimiter=*/"",
          /*BasedOnStyle=*/"google",
      },
  };
a692 1
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
a693 7
    GoogleStyle.Cpp11BracedListStyle = false;
    // This affects protocol buffer options specifications and text protos.
    // Text protos are currently mostly formatted inside C++ raw string literals
    // and often the current breaking behavior of string literals is not
    // beneficial there. Investigate turning this on once proper string reflow
    // has been implemented.
    GoogleStyle.BreakStringLiterals = false;
a694 1
    GoogleStyle.AlwaysBreakBeforeMultilineStrings = false;
d728 2
a729 1
  MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
d732 1
a732 1
  MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
d737 1
a737 1
  MozillaStyle.BreakInheritanceList = FormatStyle::BILS_BeforeComma;
a767 1
  Style.SpaceBeforeCpp11BracedList = true;
d824 1
a824 1
  Style->StyleSet.Clear();
d843 3
a845 3
        LLVM_DEBUG(llvm::dbgs()
                   << "Duplicate languages in the config file on positions "
                   << j << " and " << i << "\n");
a852 2
  FormatStyle::FormatStyleSet StyleSet;
  bool LanguageFound = false;
d854 6
a859 11
    if (Styles[i].Language != FormatStyle::LK_None)
      StyleSet.Add(Styles[i]);
    if (Styles[i].Language == Language)
      LanguageFound = true;
  }
  if (!LanguageFound) {
    if (Styles.empty() || Styles[0].Language != FormatStyle::LK_None)
      return make_error_code(ParseError::Unsuitable);
    FormatStyle DefaultStyle = Styles[0];
    DefaultStyle.Language = Language;
    StyleSet.Add(std::move(DefaultStyle));
d861 1
a861 2
  *Style = *StyleSet.Get(Language);
  return make_error_code(ParseError::Success);
a874 32
llvm::Optional<FormatStyle>
FormatStyle::FormatStyleSet::Get(FormatStyle::LanguageKind Language) const {
  if (!Styles)
    return None;
  auto It = Styles->find(Language);
  if (It == Styles->end())
    return None;
  FormatStyle Style = It->second;
  Style.StyleSet = *this;
  return Style;
}

void FormatStyle::FormatStyleSet::Add(FormatStyle Style) {
  assert(Style.Language != LK_None &&
         "Cannot add a style for LK_None to a StyleSet");
  assert(
      !Style.StyleSet.Styles &&
      "Cannot add a style associated with an existing StyleSet to a StyleSet");
  if (!Styles)
    Styles = std::make_shared<MapType>();
  (*Styles)[Style.Language] = std::move(Style);
}

void FormatStyle::FormatStyleSet::Clear() {
  Styles.reset();
}

llvm::Optional<FormatStyle>
FormatStyle::GetLanguageStyle(FormatStyle::LanguageKind Language) const {
  return StyleSet.Get(Language);
}

d882 1
a882 1
  std::pair<tooling::Replacements, unsigned>
d886 2
a887 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d890 1
a890 1
    return {Result, 0};
d971 1
a971 1
  std::pair<tooling::Replacements, unsigned>
d977 2
a978 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d990 3
a992 10
    unsigned Penalty =
        UnwrappedLineFormatter(&Indenter, &Whitespaces, Style,
                               Tokens.getKeywords(), Env.getSourceManager(),
                               Status)
            .format(AnnotatedLines, /*DryRun=*/false,
                    /*AdditionalIndent=*/0,
                    /*FixBadIndentation=*/false,
                    /*FirstStartColumn=*/Env.getFirstStartColumn(),
                    /*NextStartColumn=*/Env.getNextStartColumn(),
                    /*LastStartColumn=*/Env.getLastStartColumn());
d995 2
a996 2
        return std::make_pair(Result, 0);
    return std::make_pair(Result, Penalty);
d1000 1
d1085 1
a1085 1
  std::pair<tooling::Replacements, unsigned>
d1096 2
a1097 1
    AffectedRangeMgr.computeAffectedLines(AnnotatedLines);
d1113 1
a1113 1
    return {generateFixes(), 0};
a1299 122
class ObjCHeaderStyleGuesser : public TokenAnalyzer {
public:
  ObjCHeaderStyleGuesser(const Environment &Env, const FormatStyle &Style)
      : TokenAnalyzer(Env, Style), IsObjC(false) {}

  std::pair<tooling::Replacements, unsigned>
  analyze(TokenAnnotator &Annotator,
          SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
          FormatTokenLexer &Tokens) override {
    assert(Style.Language == FormatStyle::LK_Cpp);
    IsObjC = guessIsObjC(AnnotatedLines, Tokens.getKeywords());
    tooling::Replacements Result;
    return {Result, 0};
  }

  bool isObjC() { return IsObjC; }

private:
  static bool guessIsObjC(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                          const AdditionalKeywords &Keywords) {
    // Keep this array sorted, since we are binary searching over it.
    static constexpr llvm::StringLiteral FoundationIdentifiers[] = {
        "CGFloat",
        "CGPoint",
        "CGPointMake",
        "CGPointZero",
        "CGRect",
        "CGRectEdge",
        "CGRectInfinite",
        "CGRectMake",
        "CGRectNull",
        "CGRectZero",
        "CGSize",
        "CGSizeMake",
        "CGVector",
        "CGVectorMake",
        "NSAffineTransform",
        "NSArray",
        "NSAttributedString",
        "NSBlockOperation",
        "NSBundle",
        "NSCache",
        "NSCalendar",
        "NSCharacterSet",
        "NSCountedSet",
        "NSData",
        "NSDataDetector",
        "NSDecimal",
        "NSDecimalNumber",
        "NSDictionary",
        "NSEdgeInsets",
        "NSHashTable",
        "NSIndexPath",
        "NSIndexSet",
        "NSInteger",
        "NSInvocationOperation",
        "NSLocale",
        "NSMapTable",
        "NSMutableArray",
        "NSMutableAttributedString",
        "NSMutableCharacterSet",
        "NSMutableData",
        "NSMutableDictionary",
        "NSMutableIndexSet",
        "NSMutableOrderedSet",
        "NSMutableSet",
        "NSMutableString",
        "NSNumber",
        "NSNumberFormatter",
        "NSObject",
        "NSOperation",
        "NSOperationQueue",
        "NSOperationQueuePriority",
        "NSOrderedSet",
        "NSPoint",
        "NSPointerArray",
        "NSQualityOfService",
        "NSRange",
        "NSRect",
        "NSRegularExpression",
        "NSSet",
        "NSSize",
        "NSString",
        "NSTimeZone",
        "NSUInteger",
        "NSURL",
        "NSURLComponents",
        "NSURLQueryItem",
        "NSUUID",
        "NSValue",
        "UIImage",
        "UIView",
    };

    for (auto Line : AnnotatedLines) {
      for (const FormatToken *FormatTok = Line->First; FormatTok;
           FormatTok = FormatTok->Next) {
        if ((FormatTok->Previous && FormatTok->Previous->is(tok::at) &&
             (FormatTok->Tok.getObjCKeywordID() != tok::objc_not_keyword ||
              FormatTok->isOneOf(tok::numeric_constant, tok::l_square,
                                 tok::l_brace))) ||
            (FormatTok->Tok.isAnyIdentifier() &&
             std::binary_search(std::begin(FoundationIdentifiers),
                                std::end(FoundationIdentifiers),
                                FormatTok->TokenText)) ||
            FormatTok->is(TT_ObjCStringLiteral) ||
            FormatTok->isOneOf(Keywords.kw_NS_ENUM, Keywords.kw_NS_OPTIONS,
                               TT_ObjCBlockLBrace, TT_ObjCBlockLParen,
                               TT_ObjCDecl, TT_ObjCForIn, TT_ObjCMethodExpr,
                               TT_ObjCMethodSpecifier, TT_ObjCProperty)) {
          return true;
        }
        if (guessIsObjC(Line->Children, Keywords))
          return true;
      }
    }
    return false;
  }

  bool IsObjC;
};

a1388 2
  int CurrentCategory = Includes.front().Category;

d1392 1
a1392 2
      std::is_sorted(Indices.begin(), Indices.end()) &&
      Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Preserve)
d1397 1
a1397 1
    if (!result.empty()) {
a1398 5
      if (Style.IncludeStyle.IncludeBlocks ==
              tooling::IncludeStyle::IBS_Regroup &&
          CurrentCategory != Includes[Index].Category)
        result += "\n";
    }
a1401 1
    CurrentCategory = Includes[Index].Category;
d1416 54
d1493 1
a1493 1
  tooling::IncludeCategoryManager Categories(Style.IncludeStyle, FileName);
a1508 6
    const bool EmptyLineSkipped =
        Trimmed.empty() &&
        (Style.IncludeStyle.IncludeBlocks == tooling::IncludeStyle::IBS_Merge ||
         Style.IncludeStyle.IncludeBlocks ==
             tooling::IncludeStyle::IBS_Regroup);

d1518 1
a1518 1
      } else if (!IncludesInBlock.empty() && !EmptyLineSkipped) {
a1541 2
bool isLikelyXml(StringRef Code) { return Code.ltrim().startswith("<"); }

a1547 2
  if (isLikelyXml(Code))
    return Replaces;
d1613 116
d1757 3
d1762 1
a1762 1
  tooling::HeaderIncludes Includes(FileName, Code, Style.IncludeStyle);
d1764 47
a1810 10
  for (const auto &Header : HeadersToDelete) {
    tooling::Replacements Replaces =
        Includes.remove(Header.trim("\"<>"), Header.startswith("<"));
    for (const auto &R : Replaces) {
      auto Err = Result.add(R);
      if (Err) {
        // Ignore the deletion on conflict.
        llvm::errs() << "Failed to add header deletion replacement for "
                     << Header << ": " << llvm::toString(std::move(Err))
                     << "\n";
d1813 1
d1816 20
a1835 2
  llvm::Regex IncludeRegex = llvm::Regex(IncludeRegexPattern);
  llvm::SmallVector<StringRef, 4> Matches;
d1843 24
a1866 11
    auto Replace =
        Includes.insert(IncludeName.trim("\"<>"), IncludeName.startswith("<"));
    if (Replace) {
      auto Err = Result.add(*Replace);
      if (Err) {
        llvm::consumeError(std::move(Err));
        unsigned NewOffset = Result.getShiftedCodePosition(Replace->getOffset());
        auto Shifted = tooling::Replacement(FileName, NewOffset, 0,
                                            Replace->getReplacementText());
        Result = Result.merge(tooling::Replacements(Shifted));
      }
d1890 4
a1893 6
namespace internal {
std::pair<tooling::Replacements, unsigned>
reformat(const FormatStyle &Style, StringRef Code,
         ArrayRef<tooling::Range> Ranges, unsigned FirstStartColumn,
         unsigned NextStartColumn, unsigned LastStartColumn, StringRef FileName,
         FormattingAttemptStatus *Status) {
d1896 1
a1896 3
    return {tooling::Replacements(), 0};
  if (isLikelyXml(Code))
    return {tooling::Replacements(), 0};
d1898 1
a1898 1
    return {tooling::Replacements(), 0};
d1900 1
a1900 2
  typedef std::function<std::pair<tooling::Replacements, unsigned>(
      const Environment &)>
d1926 2
a1927 3
  auto Env =
      llvm::make_unique<Environment>(Code, FileName, Ranges, FirstStartColumn,
                                     NextStartColumn, LastStartColumn);
a1929 1
  unsigned Penalty = 0;
d1931 1
a1931 1
    std::pair<tooling::Replacements, unsigned> PassFixes = Passes[I](*Env);
d1933 1
a1933 1
        CurrentCode ? StringRef(*CurrentCode) : Code, PassFixes.first);
d1935 1
a1935 2
      Fixes = Fixes.merge(PassFixes.first);
      Penalty += PassFixes.second;
d1938 1
a1938 1
        Env = llvm::make_unique<Environment>(
d1940 1
a1940 2
            tooling::calculateRangesAfterReplacements(Fixes, Ranges),
            FirstStartColumn, NextStartColumn, LastStartColumn);
d1945 1
a1945 13
  return {Fixes, Penalty};
}
} // namespace internal

tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               ArrayRef<tooling::Range> Ranges,
                               StringRef FileName,
                               FormattingAttemptStatus *Status) {
  return internal::reformat(Style, Code, Ranges,
                            /*FirstStartColumn=*/0,
                            /*NextStartColumn=*/0,
                            /*LastStartColumn=*/0, FileName, Status)
      .first;
d1954 4
a1957 1
  return Cleaner(Environment(Code, FileName, Ranges), Style).process().first;
d1974 4
a1977 3
  return NamespaceEndCommentsFixer(Environment(Code, FileName, Ranges), Style)
      .process()
      .first;
d1984 4
a1987 3
  return UsingDeclarationsSorter(Environment(Code, FileName, Ranges), Style)
      .process()
      .first;
d1995 1
a1995 2
  LangOpts.CPlusPlus17 = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.CPlusPlus2a = Style.Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
a2027 5
  if (FileName.endswith_lower(".textpb") ||
      FileName.endswith_lower(".pb.txt") ||
      FileName.endswith_lower(".textproto") ||
      FileName.endswith_lower(".asciipb"))
    return FormatStyle::LK_TextProto;
a2032 22
FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code) {
  const auto GuessedLanguage = getLanguageByFileName(FileName);
  if (GuessedLanguage == FormatStyle::LK_Cpp) {
    auto Extension = llvm::sys::path::extension(FileName);
    // If there's no file extension (or it's .h), we need to check the contents
    // of the code to see if it contains Objective-C.
    if (Extension.empty() || Extension == ".h") {
      auto NonEmptyFileName = FileName.empty() ? "guess.h" : FileName;
      Environment Env(Code, NonEmptyFileName, /*Ranges=*/{});
      ObjCHeaderStyleGuesser Guesser(Env, getLLVMStyle());
      Guesser.process();
      if (Guesser.isObjC())
        return FormatStyle::LK_ObjC;
    }
  }
  return GuessedLanguage;
}

const char *DefaultFormatStyle = "file";

const char *DefaultFallbackStyle = "LLVM";

d2040 8
a2047 1
  Style.Language = guessLanguage(FileName, Code);
d2084 1
a2084 1
    LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
d2093 1
a2093 1
      LLVM_DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
d2115 1
a2115 2
      LLVM_DEBUG(llvm::dbgs()
                 << "Using configuration file " << ConfigFile << "\n");
@


1.1.1.13
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.6.4.1
log
@file Format.cpp was added on branch tls-maxphys on 2014-08-19 23:47:28 +0000
@
text
@d1 2130
@


1.1.1.6.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 2130
//===--- Format.cpp - Format C++ code -------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements functions declared in Format.h. This will be
/// split into separate files as we go.
///
//===----------------------------------------------------------------------===//

#include "ContinuationIndenter.h"
#include "TokenAnnotator.h"
#include "UnwrappedLineParser.h"
#include "WhitespaceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLTraits.h"
#include <queue>
#include <string>

#define DEBUG_TYPE "format-formatter"

using clang::format::FormatStyle;

LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(std::string)

namespace llvm {
namespace yaml {
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
  static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
    IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
    IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
    IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
  static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
    IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
  static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
    IO.enumCase(Value, "Never", FormatStyle::UT_Never);
    IO.enumCase(Value, "false", FormatStyle::UT_Never);
    IO.enumCase(Value, "Always", FormatStyle::UT_Always);
    IO.enumCase(Value, "true", FormatStyle::UT_Always);
    IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::ShortFunctionStyle> {
  static void enumeration(IO &IO, FormatStyle::ShortFunctionStyle &Value) {
    IO.enumCase(Value, "None", FormatStyle::SFS_None);
    IO.enumCase(Value, "false", FormatStyle::SFS_None);
    IO.enumCase(Value, "All", FormatStyle::SFS_All);
    IO.enumCase(Value, "true", FormatStyle::SFS_All);
    IO.enumCase(Value, "Inline", FormatStyle::SFS_Inline);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
  static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
    IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
    IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
    IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
    IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
    IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
  static void enumeration(IO &IO,
                          FormatStyle::NamespaceIndentationKind &Value) {
    IO.enumCase(Value, "None", FormatStyle::NI_None);
    IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
    IO.enumCase(Value, "All", FormatStyle::NI_All);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::PointerAlignmentStyle> {
  static void enumeration(IO &IO,
                          FormatStyle::PointerAlignmentStyle &Value) {
    IO.enumCase(Value, "Middle", FormatStyle::PAS_Middle);
    IO.enumCase(Value, "Left", FormatStyle::PAS_Left);
    IO.enumCase(Value, "Right", FormatStyle::PAS_Right);

    // For backward compatibility.
    IO.enumCase(Value, "true", FormatStyle::PAS_Left);
    IO.enumCase(Value, "false", FormatStyle::PAS_Right);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
  static void enumeration(IO &IO,
                          FormatStyle::SpaceBeforeParensOptions &Value) {
    IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
    IO.enumCase(Value, "ControlStatements",
                FormatStyle::SBPO_ControlStatements);
    IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
    IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
  }
};

template <> struct MappingTraits<FormatStyle> {
  static void mapping(IO &IO, FormatStyle &Style) {
    // When reading, read the language first, we need it for getPredefinedStyle.
    IO.mapOptional("Language", Style.Language);

    if (IO.outputting()) {
      StringRef StylesArray[] = { "LLVM",    "Google", "Chromium",
                                  "Mozilla", "WebKit", "GNU" };
      ArrayRef<StringRef> Styles(StylesArray);
      for (size_t i = 0, e = Styles.size(); i < e; ++i) {
        StringRef StyleName(Styles[i]);
        FormatStyle PredefinedStyle;
        if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
            Style == PredefinedStyle) {
          IO.mapOptional("# BasedOnStyle", StyleName);
          break;
        }
      }
    } else {
      StringRef BasedOnStyle;
      IO.mapOptional("BasedOnStyle", BasedOnStyle);
      if (!BasedOnStyle.empty()) {
        FormatStyle::LanguageKind OldLanguage = Style.Language;
        FormatStyle::LanguageKind Language =
            ((FormatStyle *)IO.getContext())->Language;
        if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
          IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
          return;
        }
        Style.Language = OldLanguage;
      }
    }

    IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
    IO.mapOptional("ConstructorInitializerIndentWidth",
                   Style.ConstructorInitializerIndentWidth);
    IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
    IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
    IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
                   Style.AllowAllParametersOfDeclarationOnNextLine);
    IO.mapOptional("AllowShortBlocksOnASingleLine",
                   Style.AllowShortBlocksOnASingleLine);
    IO.mapOptional("AllowShortIfStatementsOnASingleLine",
                   Style.AllowShortIfStatementsOnASingleLine);
    IO.mapOptional("AllowShortLoopsOnASingleLine",
                   Style.AllowShortLoopsOnASingleLine);
    IO.mapOptional("AllowShortFunctionsOnASingleLine",
                   Style.AllowShortFunctionsOnASingleLine);
    IO.mapOptional("AlwaysBreakAfterDefinitionReturnType",
                   Style.AlwaysBreakAfterDefinitionReturnType);
    IO.mapOptional("AlwaysBreakTemplateDeclarations",
                   Style.AlwaysBreakTemplateDeclarations);
    IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
                   Style.AlwaysBreakBeforeMultilineStrings);
    IO.mapOptional("BreakBeforeBinaryOperators",
                   Style.BreakBeforeBinaryOperators);
    IO.mapOptional("BreakBeforeTernaryOperators",
                   Style.BreakBeforeTernaryOperators);
    IO.mapOptional("BreakConstructorInitializersBeforeComma",
                   Style.BreakConstructorInitializersBeforeComma);
    IO.mapOptional("BinPackParameters", Style.BinPackParameters);
    IO.mapOptional("ColumnLimit", Style.ColumnLimit);
    IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
                   Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
    IO.mapOptional("DerivePointerAlignment", Style.DerivePointerAlignment);
    IO.mapOptional("ExperimentalAutoDetectBinPacking",
                   Style.ExperimentalAutoDetectBinPacking);
    IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
    IO.mapOptional("IndentWrappedFunctionNames",
                   Style.IndentWrappedFunctionNames);
    IO.mapOptional("IndentFunctionDeclarationAfterType",
                   Style.IndentWrappedFunctionNames);
    IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
    IO.mapOptional("KeepEmptyLinesAtTheStartOfBlocks",
                   Style.KeepEmptyLinesAtTheStartOfBlocks);
    IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
    IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
    IO.mapOptional("ObjCSpaceBeforeProtocolList",
                   Style.ObjCSpaceBeforeProtocolList);
    IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
                   Style.PenaltyBreakBeforeFirstCallParameter);
    IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
    IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
    IO.mapOptional("PenaltyBreakFirstLessLess",
                   Style.PenaltyBreakFirstLessLess);
    IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
    IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
                   Style.PenaltyReturnTypeOnItsOwnLine);
    IO.mapOptional("PointerAlignment", Style.PointerAlignment);
    IO.mapOptional("SpacesBeforeTrailingComments",
                   Style.SpacesBeforeTrailingComments);
    IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
    IO.mapOptional("Standard", Style.Standard);
    IO.mapOptional("IndentWidth", Style.IndentWidth);
    IO.mapOptional("TabWidth", Style.TabWidth);
    IO.mapOptional("UseTab", Style.UseTab);
    IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
    IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
    IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
    IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
    IO.mapOptional("SpacesInCStyleCastParentheses",
                   Style.SpacesInCStyleCastParentheses);
    IO.mapOptional("SpacesInContainerLiterals",
                   Style.SpacesInContainerLiterals);
    IO.mapOptional("SpaceBeforeAssignmentOperators",
                   Style.SpaceBeforeAssignmentOperators);
    IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
    IO.mapOptional("CommentPragmas", Style.CommentPragmas);
    IO.mapOptional("ForEachMacros", Style.ForEachMacros);

    // For backward compatibility.
    if (!IO.outputting()) {
      IO.mapOptional("SpaceAfterControlStatementKeyword",
                     Style.SpaceBeforeParens);
      IO.mapOptional("PointerBindsToType", Style.PointerAlignment);
      IO.mapOptional("DerivePointerBinding", Style.DerivePointerAlignment);
    }
    IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
    IO.mapOptional("DisableFormat", Style.DisableFormat);
  }
};

// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
// If the first element has no Language specified, it will be treated as the
// default one for the following elements.
template <> struct DocumentListTraits<std::vector<FormatStyle> > {
  static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
    return Seq.size();
  }
  static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
                              size_t Index) {
    if (Index >= Seq.size()) {
      assert(Index == Seq.size());
      FormatStyle Template;
      if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) {
        Template = Seq[0];
      } else {
        Template = *((const FormatStyle *)IO.getContext());
        Template.Language = FormatStyle::LK_None;
      }
      Seq.resize(Index + 1, Template);
    }
    return Seq[Index];
  }
};
}
}

namespace clang {
namespace format {

const std::error_category &getParseCategory() {
  static ParseErrorCategory C;
  return C;
}
std::error_code make_error_code(ParseError e) {
  return std::error_code(static_cast<int>(e), getParseCategory());
}

const char *ParseErrorCategory::name() const LLVM_NOEXCEPT {
  return "clang-format.parse_error";
}

std::string ParseErrorCategory::message(int EV) const {
  switch (static_cast<ParseError>(EV)) {
  case ParseError::Success:
    return "Success";
  case ParseError::Error:
    return "Invalid argument";
  case ParseError::Unsuitable:
    return "Unsuitable";
  }
  llvm_unreachable("unexpected parse error");
}

FormatStyle getLLVMStyle() {
  FormatStyle LLVMStyle;
  LLVMStyle.Language = FormatStyle::LK_Cpp;
  LLVMStyle.AccessModifierOffset = -2;
  LLVMStyle.AlignEscapedNewlinesLeft = false;
  LLVMStyle.AlignTrailingComments = true;
  LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
  LLVMStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_All;
  LLVMStyle.AllowShortBlocksOnASingleLine = false;
  LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
  LLVMStyle.AllowShortLoopsOnASingleLine = false;
  LLVMStyle.AlwaysBreakAfterDefinitionReturnType = false;
  LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
  LLVMStyle.AlwaysBreakTemplateDeclarations = false;
  LLVMStyle.BinPackParameters = true;
  LLVMStyle.BreakBeforeBinaryOperators = false;
  LLVMStyle.BreakBeforeTernaryOperators = true;
  LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
  LLVMStyle.BreakConstructorInitializersBeforeComma = false;
  LLVMStyle.ColumnLimit = 80;
  LLVMStyle.CommentPragmas = "^ IWYU pragma:";
  LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
  LLVMStyle.ConstructorInitializerIndentWidth = 4;
  LLVMStyle.ContinuationIndentWidth = 4;
  LLVMStyle.Cpp11BracedListStyle = true;
  LLVMStyle.DerivePointerAlignment = false;
  LLVMStyle.ExperimentalAutoDetectBinPacking = false;
  LLVMStyle.ForEachMacros.push_back("foreach");
  LLVMStyle.ForEachMacros.push_back("Q_FOREACH");
  LLVMStyle.ForEachMacros.push_back("BOOST_FOREACH");
  LLVMStyle.IndentCaseLabels = false;
  LLVMStyle.IndentWrappedFunctionNames = false;
  LLVMStyle.IndentWidth = 2;
  LLVMStyle.TabWidth = 8;
  LLVMStyle.MaxEmptyLinesToKeep = 1;
  LLVMStyle.KeepEmptyLinesAtTheStartOfBlocks = true;
  LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
  LLVMStyle.ObjCSpaceAfterProperty = false;
  LLVMStyle.ObjCSpaceBeforeProtocolList = true;
  LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
  LLVMStyle.SpacesBeforeTrailingComments = 1;
  LLVMStyle.Standard = FormatStyle::LS_Cpp11;
  LLVMStyle.UseTab = FormatStyle::UT_Never;
  LLVMStyle.SpacesInParentheses = false;
  LLVMStyle.SpaceInEmptyParentheses = false;
  LLVMStyle.SpacesInContainerLiterals = true;
  LLVMStyle.SpacesInCStyleCastParentheses = false;
  LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
  LLVMStyle.SpaceBeforeAssignmentOperators = true;
  LLVMStyle.SpacesInAngles = false;

  LLVMStyle.PenaltyBreakComment = 300;
  LLVMStyle.PenaltyBreakFirstLessLess = 120;
  LLVMStyle.PenaltyBreakString = 1000;
  LLVMStyle.PenaltyExcessCharacter = 1000000;
  LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
  LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;

  LLVMStyle.DisableFormat = false;

  return LLVMStyle;
}

FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
  FormatStyle GoogleStyle = getLLVMStyle();
  GoogleStyle.Language = Language;

  GoogleStyle.AccessModifierOffset = -1;
  GoogleStyle.AlignEscapedNewlinesLeft = true;
  GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
  GoogleStyle.AllowShortLoopsOnASingleLine = true;
  GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
  GoogleStyle.AlwaysBreakTemplateDeclarations = true;
  GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
  GoogleStyle.DerivePointerAlignment = true;
  GoogleStyle.IndentCaseLabels = true;
  GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false;
  GoogleStyle.ObjCSpaceAfterProperty = false;
  GoogleStyle.ObjCSpaceBeforeProtocolList = false;
  GoogleStyle.PointerAlignment = FormatStyle::PAS_Left;
  GoogleStyle.SpacesBeforeTrailingComments = 2;
  GoogleStyle.Standard = FormatStyle::LS_Auto;

  GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
  GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;

  if (Language == FormatStyle::LK_JavaScript) {
    GoogleStyle.BreakBeforeTernaryOperators = false;
    GoogleStyle.MaxEmptyLinesToKeep = 3;
    GoogleStyle.SpacesInContainerLiterals = false;
  } else if (Language == FormatStyle::LK_Proto) {
    GoogleStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
    GoogleStyle.SpacesInContainerLiterals = false;
  }

  return GoogleStyle;
}

FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
  FormatStyle ChromiumStyle = getGoogleStyle(Language);
  ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
  ChromiumStyle.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_Inline;
  ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
  ChromiumStyle.AllowShortLoopsOnASingleLine = false;
  ChromiumStyle.BinPackParameters = false;
  ChromiumStyle.DerivePointerAlignment = false;
  ChromiumStyle.Standard = FormatStyle::LS_Cpp03;
  return ChromiumStyle;
}

FormatStyle getMozillaStyle() {
  FormatStyle MozillaStyle = getLLVMStyle();
  MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
  MozillaStyle.Cpp11BracedListStyle = false;
  MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
  MozillaStyle.DerivePointerAlignment = true;
  MozillaStyle.IndentCaseLabels = true;
  MozillaStyle.ObjCSpaceAfterProperty = true;
  MozillaStyle.ObjCSpaceBeforeProtocolList = false;
  MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
  MozillaStyle.PointerAlignment = FormatStyle::PAS_Left;
  MozillaStyle.Standard = FormatStyle::LS_Cpp03;
  return MozillaStyle;
}

FormatStyle getWebKitStyle() {
  FormatStyle Style = getLLVMStyle();
  Style.AccessModifierOffset = -4;
  Style.AlignTrailingComments = false;
  Style.BreakBeforeBinaryOperators = true;
  Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
  Style.BreakConstructorInitializersBeforeComma = true;
  Style.Cpp11BracedListStyle = false;
  Style.ColumnLimit = 0;
  Style.IndentWidth = 4;
  Style.NamespaceIndentation = FormatStyle::NI_Inner;
  Style.ObjCSpaceAfterProperty = true;
  Style.PointerAlignment = FormatStyle::PAS_Left;
  Style.Standard = FormatStyle::LS_Cpp03;
  return Style;
}

FormatStyle getGNUStyle() {
  FormatStyle Style = getLLVMStyle();
  Style.AlwaysBreakAfterDefinitionReturnType = true;
  Style.BreakBeforeBinaryOperators = true;
  Style.BreakBeforeBraces = FormatStyle::BS_GNU;
  Style.BreakBeforeTernaryOperators = true;
  Style.Cpp11BracedListStyle = false;
  Style.ColumnLimit = 79;
  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
  Style.Standard = FormatStyle::LS_Cpp03;
  return Style;
}

FormatStyle getNoStyle() {
  FormatStyle NoStyle = getLLVMStyle();
  NoStyle.DisableFormat = true;
  return NoStyle;
}

bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
                        FormatStyle *Style) {
  if (Name.equals_lower("llvm")) {
    *Style = getLLVMStyle();
  } else if (Name.equals_lower("chromium")) {
    *Style = getChromiumStyle(Language);
  } else if (Name.equals_lower("mozilla")) {
    *Style = getMozillaStyle();
  } else if (Name.equals_lower("google")) {
    *Style = getGoogleStyle(Language);
  } else if (Name.equals_lower("webkit")) {
    *Style = getWebKitStyle();
  } else if (Name.equals_lower("gnu")) {
    *Style = getGNUStyle();
  } else if (Name.equals_lower("none")) {
    *Style = getNoStyle();
  } else {
    return false;
  }

  Style->Language = Language;
  return true;
}

std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
  assert(Style);
  FormatStyle::LanguageKind Language = Style->Language;
  assert(Language != FormatStyle::LK_None);
  if (Text.trim().empty())
    return make_error_code(ParseError::Error);

  std::vector<FormatStyle> Styles;
  llvm::yaml::Input Input(Text);
  // DocumentListTraits<vector<FormatStyle>> uses the context to get default
  // values for the fields, keys for which are missing from the configuration.
  // Mapping also uses the context to get the language to find the correct
  // base style.
  Input.setContext(Style);
  Input >> Styles;
  if (Input.error())
    return Input.error();

  for (unsigned i = 0; i < Styles.size(); ++i) {
    // Ensures that only the first configuration can skip the Language option.
    if (Styles[i].Language == FormatStyle::LK_None && i != 0)
      return make_error_code(ParseError::Error);
    // Ensure that each language is configured at most once.
    for (unsigned j = 0; j < i; ++j) {
      if (Styles[i].Language == Styles[j].Language) {
        DEBUG(llvm::dbgs()
              << "Duplicate languages in the config file on positions " << j
              << " and " << i << "\n");
        return make_error_code(ParseError::Error);
      }
    }
  }
  // Look for a suitable configuration starting from the end, so we can
  // find the configuration for the specific language first, and the default
  // configuration (which can only be at slot 0) after it.
  for (int i = Styles.size() - 1; i >= 0; --i) {
    if (Styles[i].Language == Language ||
        Styles[i].Language == FormatStyle::LK_None) {
      *Style = Styles[i];
      Style->Language = Language;
      return make_error_code(ParseError::Success);
    }
  }
  return make_error_code(ParseError::Unsuitable);
}

std::string configurationAsText(const FormatStyle &Style) {
  std::string Text;
  llvm::raw_string_ostream Stream(Text);
  llvm::yaml::Output Output(Stream);
  // We use the same mapping method for input and output, so we need a non-const
  // reference here.
  FormatStyle NonConstStyle = Style;
  Output << NonConstStyle;
  return Stream.str();
}

namespace {

class NoColumnLimitFormatter {
public:
  NoColumnLimitFormatter(ContinuationIndenter *Indenter) : Indenter(Indenter) {}

  /// \brief Formats the line starting at \p State, simply keeping all of the
  /// input's line breaking decisions.
  void format(unsigned FirstIndent, const AnnotatedLine *Line) {
    LineState State =
        Indenter->getInitialState(FirstIndent, Line, /*DryRun=*/false);
    while (State.NextToken) {
      bool Newline =
          Indenter->mustBreak(State) ||
          (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
      Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
    }
  }

private:
  ContinuationIndenter *Indenter;
};

class LineJoiner {
public:
  LineJoiner(const FormatStyle &Style) : Style(Style) {}

  /// \brief Calculates how many lines can be merged into 1 starting at \p I.
  unsigned
  tryFitMultipleLinesInOne(unsigned Indent,
                           SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                           SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
    // We can never merge stuff if there are trailing line comments.
    const AnnotatedLine *TheLine = *I;
    if (TheLine->Last->Type == TT_LineComment)
      return 0;

    if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
      return 0;

    unsigned Limit =
        Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
    // If we already exceed the column limit, we set 'Limit' to 0. The different
    // tryMerge..() functions can then decide whether to still do merging.
    Limit = TheLine->Last->TotalLength > Limit
                ? 0
                : Limit - TheLine->Last->TotalLength;

    if (I + 1 == E || I[1]->Type == LT_Invalid || I[1]->First->MustBreakBefore)
      return 0;

    // FIXME: TheLine->Level != 0 might or might not be the right check to do.
    // If necessary, change to something smarter.
    bool MergeShortFunctions =
        Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_All ||
        (Style.AllowShortFunctionsOnASingleLine == FormatStyle::SFS_Inline &&
         TheLine->Level != 0);

    if (TheLine->Last->Type == TT_FunctionLBrace &&
        TheLine->First != TheLine->Last) {
      return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
    }
    if (TheLine->Last->is(tok::l_brace)) {
      return Style.BreakBeforeBraces == FormatStyle::BS_Attach
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
    if (I[1]->First->Type == TT_FunctionLBrace &&
        Style.BreakBeforeBraces != FormatStyle::BS_Attach) {
      // Check for Limit <= 2 to account for the " {".
      if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
        return 0;
      Limit -= 2;

      unsigned MergedLines = 0;
      if (MergeShortFunctions) {
        MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
        // If we managed to merge the block, count the function header, which is
        // on a separate line.
        if (MergedLines > 0)
          ++MergedLines;
      }
      return MergedLines;
    }
    if (TheLine->First->is(tok::kw_if)) {
      return Style.AllowShortIfStatementsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
      return Style.AllowShortLoopsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->InPPDirective &&
        (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
      return tryMergeSimplePPDirective(I, E, Limit);
    }
    return 0;
  }

private:
  unsigned
  tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                            SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                            unsigned Limit) {
    if (Limit == 0)
      return 0;
    if (!I[1]->InPPDirective || I[1]->First->HasUnescapedNewline)
      return 0;
    if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    return 1;
  }

  unsigned tryMergeSimpleControlStatement(
      SmallVectorImpl<AnnotatedLine *>::const_iterator I,
      SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
    if (Limit == 0)
      return 0;
    if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
         Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
        (I[1]->First->is(tok::l_brace) && !Style.AllowShortBlocksOnASingleLine))
      return 0;
    if (I[1]->InPPDirective != (*I)->InPPDirective ||
        (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline))
      return 0;
    Limit = limitConsideringMacros(I + 1, E, Limit);
    AnnotatedLine &Line = **I;
    if (Line.Last->isNot(tok::r_paren))
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
                             tok::kw_while) ||
        I[1]->First->Type == TT_LineComment)
      return 0;
    // Only inline simple if's (no nested if or else).
    if (I + 2 != E && Line.First->is(tok::kw_if) &&
        I[2]->First->is(tok::kw_else))
      return 0;
    return 1;
  }

  unsigned
  tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                      SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                      unsigned Limit) {
    AnnotatedLine &Line = **I;

    // Don't merge ObjC @@ keywords and methods.
    if (Line.First->isOneOf(tok::at, tok::minus, tok::plus))
      return 0;

    // Check that the current line allows merging. This depends on whether we
    // are in a control flow statements as well as several style flags.
    if (Line.First->isOneOf(tok::kw_else, tok::kw_case))
      return 0;
    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::kw_try,
                            tok::kw_catch, tok::kw_for, tok::r_brace)) {
      if (!Style.AllowShortBlocksOnASingleLine)
        return 0;
      if (!Style.AllowShortIfStatementsOnASingleLine &&
          Line.First->is(tok::kw_if))
        return 0;
      if (!Style.AllowShortLoopsOnASingleLine &&
          Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for))
        return 0;
      // FIXME: Consider an option to allow short exception handling clauses on
      // a single line.
      if (Line.First->isOneOf(tok::kw_try, tok::kw_catch))
        return 0;
    }

    FormatToken *Tok = I[1]->First;
    if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
        (Tok->getNextNonComment() == nullptr ||
         Tok->getNextNonComment()->is(tok::semi))) {
      // We merge empty blocks even if the line exceeds the column limit.
      Tok->SpacesRequiredBefore = 0;
      Tok->CanBreakBefore = true;
      return 1;
    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
      // We don't merge short records.
      if (Line.First->isOneOf(tok::kw_class, tok::kw_union, tok::kw_struct))
        return 0;

      // Check that we still have three lines and they fit into the limit.
      if (I + 2 == E || I[2]->Type == LT_Invalid)
        return 0;
      Limit = limitConsideringMacros(I + 2, E, Limit);

      if (!nextTwoLinesFitInto(I, Limit))
        return 0;

      // Second, check that the next line does not contain any braces - if it
      // does, readability declines when putting it into a single line.
      if (I[1]->Last->Type == TT_LineComment)
        return 0;
      do {
        if (Tok->is(tok::l_brace) && Tok->BlockKind != BK_BracedInit)
          return 0;
        Tok = Tok->Next;
      } while (Tok);

      // Last, check that the third line starts with a closing brace.
      Tok = I[2]->First;
      if (Tok->isNot(tok::r_brace))
        return 0;

      return 2;
    }
    return 0;
  }

  /// Returns the modified column limit for \p I if it is inside a macro and
  /// needs a trailing '\'.
  unsigned
  limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                         SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                         unsigned Limit) {
    if (I[0]->InPPDirective && I + 1 != E &&
        !I[1]->First->HasUnescapedNewline && !I[1]->First->is(tok::eof)) {
      return Limit < 2 ? 0 : Limit - 2;
    }
    return Limit;
  }

  bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                           unsigned Limit) {
    if (I[1]->First->MustBreakBefore || I[2]->First->MustBreakBefore)
      return false;
    return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
  }

  bool containsMustBreak(const AnnotatedLine *Line) {
    for (const FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
      if (Tok->MustBreakBefore)
        return true;
    }
    return false;
  }

  const FormatStyle &Style;
};

class UnwrappedLineFormatter {
public:
  UnwrappedLineFormatter(ContinuationIndenter *Indenter,
                         WhitespaceManager *Whitespaces,
                         const FormatStyle &Style)
      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
        Joiner(Style) {}

  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
                  int AdditionalIndent = 0, bool FixBadIndentation = false) {
    // Try to look up already computed penalty in DryRun-mode.
    std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned> CacheKey(
        &Lines, AdditionalIndent);
    auto CacheIt = PenaltyCache.find(CacheKey);
    if (DryRun && CacheIt != PenaltyCache.end())
      return CacheIt->second;

    assert(!Lines.empty());
    unsigned Penalty = 0;
    std::vector<int> IndentForLevel;
    for (unsigned i = 0, e = Lines[0]->Level; i != e; ++i)
      IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
    const AnnotatedLine *PreviousLine = nullptr;
    for (SmallVectorImpl<AnnotatedLine *>::const_iterator I = Lines.begin(),
                                                          E = Lines.end();
         I != E; ++I) {
      const AnnotatedLine &TheLine = **I;
      const FormatToken *FirstTok = TheLine.First;
      int Offset = getIndentOffset(*FirstTok);

      // Determine indent and try to merge multiple unwrapped lines.
      unsigned Indent;
      if (TheLine.InPPDirective) {
        Indent = TheLine.Level * Style.IndentWidth;
      } else {
        while (IndentForLevel.size() <= TheLine.Level)
          IndentForLevel.push_back(-1);
        IndentForLevel.resize(TheLine.Level + 1);
        Indent = getIndent(IndentForLevel, TheLine.Level);
      }
      unsigned LevelIndent = Indent;
      if (static_cast<int>(Indent) + Offset >= 0)
        Indent += Offset;

      // Merge multiple lines if possible.
      unsigned MergedLines = Joiner.tryFitMultipleLinesInOne(Indent, I, E);
      if (MergedLines > 0 && Style.ColumnLimit == 0) {
        // Disallow line merging if there is a break at the start of one of the
        // input lines.
        for (unsigned i = 0; i < MergedLines; ++i) {
          if (I[i + 1]->First->NewlinesBefore > 0)
            MergedLines = 0;
        }
      }
      if (!DryRun) {
        for (unsigned i = 0; i < MergedLines; ++i) {
          join(*I[i], *I[i + 1]);
        }
      }
      I += MergedLines;

      bool FixIndentation =
          FixBadIndentation && (LevelIndent != FirstTok->OriginalColumn);
      if (TheLine.First->is(tok::eof)) {
        if (PreviousLine && PreviousLine->Affected && !DryRun) {
          // Remove the file's trailing whitespace.
          unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u);
          Whitespaces->replaceWhitespace(*TheLine.First, Newlines,
                                         /*IndentLevel=*/0, /*Spaces=*/0,
                                         /*TargetColumn=*/0);
        }
      } else if (TheLine.Type != LT_Invalid &&
                 (TheLine.Affected || FixIndentation)) {
        if (FirstTok->WhitespaceRange.isValid()) {
          if (!DryRun)
            formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level,
                             Indent, TheLine.InPPDirective);
        } else {
          Indent = LevelIndent = FirstTok->OriginalColumn;
        }

        // If everything fits on a single line, just put it there.
        unsigned ColumnLimit = Style.ColumnLimit;
        if (I + 1 != E) {
          AnnotatedLine *NextLine = I[1];
          if (NextLine->InPPDirective && !NextLine->First->HasUnescapedNewline)
            ColumnLimit = getColumnLimit(TheLine.InPPDirective);
        }

        if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {
          LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);
          while (State.NextToken) {
            formatChildren(State, /*Newline=*/false, /*DryRun=*/false, Penalty);
            Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
          }
        } else if (Style.ColumnLimit == 0) {
          // FIXME: Implement nested blocks for ColumnLimit = 0.
          NoColumnLimitFormatter Formatter(Indenter);
          if (!DryRun)
            Formatter.format(Indent, &TheLine);
        } else {
          Penalty += format(TheLine, Indent, DryRun);
        }

        if (!TheLine.InPPDirective)
          IndentForLevel[TheLine.Level] = LevelIndent;
      } else if (TheLine.ChildrenAffected) {
        format(TheLine.Children, DryRun);
      } else {
        // Format the first token if necessary, and notify the WhitespaceManager
        // about the unchanged whitespace.
        for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
          if (Tok == TheLine.First &&
              (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
            unsigned LevelIndent = Tok->OriginalColumn;
            if (!DryRun) {
              // Remove trailing whitespace of the previous line.
              if ((PreviousLine && PreviousLine->Affected) ||
                  TheLine.LeadingEmptyLinesAffected) {
                formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent,
                                 TheLine.InPPDirective);
              } else {
                Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
              }
            }

            if (static_cast<int>(LevelIndent) - Offset >= 0)
              LevelIndent -= Offset;
            if (Tok->isNot(tok::comment) && !TheLine.InPPDirective)
              IndentForLevel[TheLine.Level] = LevelIndent;
          } else if (!DryRun) {
            Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
          }
        }
      }
      if (!DryRun) {
        for (FormatToken *Tok = TheLine.First; Tok; Tok = Tok->Next) {
          Tok->Finalized = true;
        }
      }
      PreviousLine = *I;
    }
    PenaltyCache[CacheKey] = Penalty;
    return Penalty;
  }

private:
  /// \brief Formats an \c AnnotatedLine and returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned format(const AnnotatedLine &Line, unsigned FirstIndent,
                  bool DryRun) {
    LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);

    // If the ObjC method declaration does not fit on a line, we should format
    // it with one arg per line.
    if (State.Line->Type == LT_ObjCMethodDecl)
      State.Stack.back().BreakBeforeParameter = true;

    // Find best solution in solution space.
    return analyzeSolutionSpace(State, DryRun);
  }

  /// \brief An edge in the solution space from \c Previous->State to \c State,
  /// inserting a newline dependent on the \c NewLine.
  struct StateNode {
    StateNode(const LineState &State, bool NewLine, StateNode *Previous)
        : State(State), NewLine(NewLine), Previous(Previous) {}
    LineState State;
    bool NewLine;
    StateNode *Previous;
  };

  /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.
  ///
  /// In case of equal penalties, we want to prefer states that were inserted
  /// first. During state generation we make sure that we insert states first
  /// that break the line as late as possible.
  typedef std::pair<unsigned, unsigned> OrderedPenalty;

  /// \brief An item in the prioritized BFS search queue. The \c StateNode's
  /// \c State has the given \c OrderedPenalty.
  typedef std::pair<OrderedPenalty, StateNode *> QueueItem;

  /// \brief The BFS queue type.
  typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
                              std::greater<QueueItem> > QueueType;

  /// \brief Get the offset of the line relatively to the level.
  ///
  /// For example, 'public:' labels in classes are offset by 1 or 2
  /// characters to the left from their level.
  int getIndentOffset(const FormatToken &RootToken) {
    if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())
      return Style.AccessModifierOffset;
    return 0;
  }

  /// \brief Add a new line and the required indent before the first Token
  /// of the \c UnwrappedLine if there was no structural parsing error.
  void formatFirstToken(FormatToken &RootToken,
                        const AnnotatedLine *PreviousLine, unsigned IndentLevel,
                        unsigned Indent, bool InPPDirective) {
    unsigned Newlines =
        std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
    // Remove empty lines before "}" where applicable.
    if (RootToken.is(tok::r_brace) &&
        (!RootToken.Next ||
         (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))
      Newlines = std::min(Newlines, 1u);
    if (Newlines == 0 && !RootToken.IsFirst)
      Newlines = 1;
    if (RootToken.IsFirst && !RootToken.HasUnescapedNewline)
      Newlines = 0;

    // Remove empty lines after "{".
    if (!Style.KeepEmptyLinesAtTheStartOfBlocks && PreviousLine &&
        PreviousLine->Last->is(tok::l_brace) &&
        PreviousLine->First->isNot(tok::kw_namespace))
      Newlines = 1;

    // Insert extra new line before access specifiers.
    if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
        RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)
      ++Newlines;

    // Remove empty lines after access specifiers.
    if (PreviousLine && PreviousLine->First->isAccessSpecifier())
      Newlines = std::min(1u, Newlines);

    Whitespaces->replaceWhitespace(RootToken, Newlines, IndentLevel, Indent,
                                   Indent, InPPDirective &&
                                               !RootToken.HasUnescapedNewline);
  }

  /// \brief Get the indent of \p Level from \p IndentForLevel.
  ///
  /// \p IndentForLevel must contain the indent for the level \c l
  /// at \p IndentForLevel[l], or a value < 0 if the indent for
  /// that level is unknown.
  unsigned getIndent(const std::vector<int> IndentForLevel, unsigned Level) {
    if (IndentForLevel[Level] != -1)
      return IndentForLevel[Level];
    if (Level == 0)
      return 0;
    return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
  }

  void join(AnnotatedLine &A, const AnnotatedLine &B) {
    assert(!A.Last->Next);
    assert(!B.First->Previous);
    if (B.Affected)
      A.Affected = true;
    A.Last->Next = B.First;
    B.First->Previous = A.Last;
    B.First->CanBreakBefore = true;
    unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
    for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
      Tok->TotalLength += LengthA;
      A.Last = Tok;
    }
  }

  unsigned getColumnLimit(bool InPPDirective) const {
    // In preprocessor directives reserve two chars for trailing " \"
    return Style.ColumnLimit - (InPPDirective ? 2 : 0);
  }

  struct CompareLineStatePointers {
    bool operator()(LineState *obj1, LineState *obj2) const {
      return *obj1 < *obj2;
    }
  };

  /// \brief Analyze the entire solution space starting from \p InitialState.
  ///
  /// This implements a variant of Dijkstra's algorithm on the graph that spans
  /// the solution space (\c LineStates are the nodes). The algorithm tries to
  /// find the shortest path (the one with lowest penalty) from \p InitialState
  /// to a state where all tokens are placed. Returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false) {
    std::set<LineState *, CompareLineStatePointers> Seen;

    // Increasing count of \c StateNode items we have created. This is used to
    // create a deterministic order independent of the container.
    unsigned Count = 0;
    QueueType Queue;

    // Insert start element into queue.
    StateNode *Node =
        new (Allocator.Allocate()) StateNode(InitialState, false, nullptr);
    Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
    ++Count;

    unsigned Penalty = 0;

    // While not empty, take first element and follow edges.
    while (!Queue.empty()) {
      Penalty = Queue.top().first.first;
      StateNode *Node = Queue.top().second;
      if (!Node->State.NextToken) {
        DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
        break;
      }
      Queue.pop();

      // Cut off the analysis of certain solutions if the analysis gets too
      // complex. See description of IgnoreStackForComparison.
      if (Count > 10000)
        Node->State.IgnoreStackForComparison = true;

      if (!Seen.insert(&Node->State).second)
        // State already examined with lower penalty.
        continue;

      FormatDecision LastFormat = Node->State.NextToken->Decision;
      if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
      if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
    }

    if (Queue.empty()) {
      // We were unable to find a solution, do nothing.
      // FIXME: Add diagnostic?
      DEBUG(llvm::dbgs() << "Could not find a solution.\n");
      return 0;
    }

    // Reconstruct the solution.
    if (!DryRun)
      reconstructPath(InitialState, Queue.top().second);

    DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
    DEBUG(llvm::dbgs() << "---\n");

    return Penalty;
  }

  void reconstructPath(LineState &State, StateNode *Current) {
    std::deque<StateNode *> Path;
    // We do not need a break before the initial token.
    while (Current->Previous) {
      Path.push_front(Current);
      Current = Current->Previous;
    }
    for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
         I != E; ++I) {
      unsigned Penalty = 0;
      formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
      Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);

      DEBUG({
        if ((*I)->NewLine) {
          llvm::dbgs() << "Penalty for placing "
                       << (*I)->Previous->State.NextToken->Tok.getName() << ": "
                       << Penalty << "\n";
        }
      });
    }
  }

  /// \brief Add the following state to the analysis queue \c Queue.
  ///
  /// Assume the current state is \p PreviousNode and has been reached with a
  /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
                           bool NewLine, unsigned *Count, QueueType *Queue) {
    if (NewLine && !Indenter->canBreak(PreviousNode->State))
      return;
    if (!NewLine && Indenter->mustBreak(PreviousNode->State))
      return;

    StateNode *Node = new (Allocator.Allocate())
        StateNode(PreviousNode->State, NewLine, PreviousNode);
    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
      return;

    Penalty += Indenter->addTokenToState(Node->State, NewLine, true);

    Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
    ++(*Count);
  }

  /// \brief If the \p State's next token is an r_brace closing a nested block,
  /// format the nested block before it.
  ///
  /// Returns \c true if all children could be placed successfully and adapts
  /// \p Penalty as well as \p State. If \p DryRun is false, also directly
  /// creates changes using \c Whitespaces.
  ///
  /// The crucial idea here is that children always get formatted upon
  /// encountering the closing brace right after the nested block. Now, if we
  /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
  /// \c false), the entire block has to be kept on the same line (which is only
  /// possible if it fits on the line, only contains a single statement, etc.
  ///
  /// If \p NewLine is true, we format the nested block on separate lines, i.e.
  /// break after the "{", format all lines with correct indentation and the put
  /// the closing "}" on yet another new line.
  ///
  /// This enables us to keep the simple structure of the
  /// \c UnwrappedLineFormatter, where we only have two options for each token:
  /// break or don't break.
  bool formatChildren(LineState &State, bool NewLine, bool DryRun,
                      unsigned &Penalty) {
    FormatToken &Previous = *State.NextToken->Previous;
    const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
    if (!LBrace || LBrace->isNot(tok::l_brace) ||
        LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)
      // The previous token does not open a block. Nothing to do. We don't
      // assert so that we can simply call this function for all tokens.
      return true;

    if (NewLine) {
      int AdditionalIndent =
          State.FirstIndent - State.Line->Level * Style.IndentWidth;
      if (State.Stack.size() < 2 ||
          !State.Stack[State.Stack.size() - 2].JSFunctionInlined) {
        AdditionalIndent = State.Stack.back().Indent -
                           Previous.Children[0]->Level * Style.IndentWidth;
      }

      Penalty += format(Previous.Children, DryRun, AdditionalIndent,
                        /*FixBadIndentation=*/true);
      return true;
    }

    // Cannot merge multiple statements into a single line.
    if (Previous.Children.size() > 1)
      return false;

    // Cannot merge into one line if this line ends on a comment.
    if (Previous.is(tok::comment))
      return false;

    // We can't put the closing "}" on a line with a trailing comment.
    if (Previous.Children[0]->Last->isTrailingComment())
      return false;

    // If the child line exceeds the column limit, we wouldn't want to merge it.
    // We add +2 for the trailing " }".
    if (Style.ColumnLimit > 0 &&
        Previous.Children[0]->Last->TotalLength + State.Column + 2 >
            Style.ColumnLimit)
      return false;

    if (!DryRun) {
      Whitespaces->replaceWhitespace(
          *Previous.Children[0]->First,
          /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,
          /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
    }
    Penalty += format(*Previous.Children[0], State.Column + 1, DryRun);

    State.Column += 1 + Previous.Children[0]->Last->TotalLength;
    return true;
  }

  ContinuationIndenter *Indenter;
  WhitespaceManager *Whitespaces;
  FormatStyle Style;
  LineJoiner Joiner;

  llvm::SpecificBumpPtrAllocator<StateNode> Allocator;

  // Cache to store the penalty of formatting a vector of AnnotatedLines
  // starting from a specific additional offset. Improves performance if there
  // are many nested blocks.
  std::map<std::pair<const SmallVectorImpl<AnnotatedLine *> *, unsigned>,
           unsigned> PenaltyCache;
};

class FormatTokenLexer {
public:
  FormatTokenLexer(Lexer &Lex, SourceManager &SourceMgr, FormatStyle &Style,
                   encoding::Encoding Encoding)
      : FormatTok(nullptr), IsFirstToken(true), GreaterStashed(false),
        Column(0), TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr),
        Style(Style), IdentTable(getFormattingLangOpts()), Encoding(Encoding),
        FirstInLineIndex(0), FormattingDisabled(false) {
    Lex.SetKeepWhitespaceMode(true);

    for (const std::string &ForEachMacro : Style.ForEachMacros)
      ForEachMacros.push_back(&IdentTable.get(ForEachMacro));
    std::sort(ForEachMacros.begin(), ForEachMacros.end());
  }

  ArrayRef<FormatToken *> lex() {
    assert(Tokens.empty());
    assert(FirstInLineIndex == 0);
    do {
      Tokens.push_back(getNextToken());
      tryMergePreviousTokens();
      if (Tokens.back()->NewlinesBefore > 0)
        FirstInLineIndex = Tokens.size() - 1;
    } while (Tokens.back()->Tok.isNot(tok::eof));
    return Tokens;
  }

  IdentifierTable &getIdentTable() { return IdentTable; }

private:
  void tryMergePreviousTokens() {
    if (tryMerge_TMacro())
      return;
    if (tryMergeConflictMarkers())
      return;

    if (Style.Language == FormatStyle::LK_JavaScript) {
      if (tryMergeEscapeSequence())
        return;
      if (tryMergeJSRegexLiteral())
        return;

      static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };
      static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };
      static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,
                                               tok::greaterequal };
      static tok::TokenKind JSRightArrow[] = { tok::equal, tok::greater };
      // FIXME: We probably need to change token type to mimic operator with the
      // correct priority.
      if (tryMergeTokens(JSIdentity))
        return;
      if (tryMergeTokens(JSNotIdentity))
        return;
      if (tryMergeTokens(JSShiftEqual))
        return;
      if (tryMergeTokens(JSRightArrow))
        return;
    }
  }

  bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {
    if (Tokens.size() < Kinds.size())
      return false;

    SmallVectorImpl<FormatToken *>::const_iterator First =
        Tokens.end() - Kinds.size();
    if (!First[0]->is(Kinds[0]))
      return false;
    unsigned AddLength = 0;
    for (unsigned i = 1; i < Kinds.size(); ++i) {
      if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=
                                         First[i]->WhitespaceRange.getEnd())
        return false;
      AddLength += First[i]->TokenText.size();
    }
    Tokens.resize(Tokens.size() - Kinds.size() + 1);
    First[0]->TokenText = StringRef(First[0]->TokenText.data(),
                                    First[0]->TokenText.size() + AddLength);
    First[0]->ColumnWidth += AddLength;
    return true;
  }

  // Tries to merge an escape sequence, i.e. a "\\" and the following
  // character. Use e.g. inside JavaScript regex literals.
  bool tryMergeEscapeSequence() {
    if (Tokens.size() < 2)
      return false;
    FormatToken *Previous = Tokens[Tokens.size() - 2];
    if (Previous->isNot(tok::unknown) || Previous->TokenText != "\\" ||
        Tokens.back()->NewlinesBefore != 0)
      return false;
    Previous->ColumnWidth += Tokens.back()->ColumnWidth;
    StringRef Text = Previous->TokenText;
    Previous->TokenText =
        StringRef(Text.data(), Text.size() + Tokens.back()->TokenText.size());
    Tokens.resize(Tokens.size() - 1);
    return true;
  }

  // Try to determine whether the current token ends a JavaScript regex literal.
  // We heuristically assume that this is a regex literal if we find two
  // unescaped slashes on a line and the token before the first slash is one of
  // "(;,{}![:?", a binary operator or 'return', as those cannot be followed by
  // a division.
  bool tryMergeJSRegexLiteral() {
    if (Tokens.size() < 2 || Tokens.back()->isNot(tok::slash) ||
        (Tokens[Tokens.size() - 2]->is(tok::unknown) &&
         Tokens[Tokens.size() - 2]->TokenText == "\\"))
      return false;
    unsigned TokenCount = 0;
    unsigned LastColumn = Tokens.back()->OriginalColumn;
    for (auto I = Tokens.rbegin() + 1, E = Tokens.rend(); I != E; ++I) {
      ++TokenCount;
      if (I[0]->is(tok::slash) && I + 1 != E &&
          (I[1]->isOneOf(tok::l_paren, tok::semi, tok::l_brace, tok::r_brace,
                         tok::exclaim, tok::l_square, tok::colon, tok::comma,
                         tok::question, tok::kw_return) ||
           I[1]->isBinaryOperator())) {
        Tokens.resize(Tokens.size() - TokenCount);
        Tokens.back()->Tok.setKind(tok::unknown);
        Tokens.back()->Type = TT_RegexLiteral;
        Tokens.back()->ColumnWidth += LastColumn - I[0]->OriginalColumn;
        return true;
      }

      // There can't be a newline inside a regex literal.
      if (I[0]->NewlinesBefore > 0)
        return false;
    }
    return false;
  }

  bool tryMerge_TMacro() {
    if (Tokens.size() < 4)
      return false;
    FormatToken *Last = Tokens.back();
    if (!Last->is(tok::r_paren))
      return false;

    FormatToken *String = Tokens[Tokens.size() - 2];
    if (!String->is(tok::string_literal) || String->IsMultiline)
      return false;

    if (!Tokens[Tokens.size() - 3]->is(tok::l_paren))
      return false;

    FormatToken *Macro = Tokens[Tokens.size() - 4];
    if (Macro->TokenText != "_T")
      return false;

    const char *Start = Macro->TokenText.data();
    const char *End = Last->TokenText.data() + Last->TokenText.size();
    String->TokenText = StringRef(Start, End - Start);
    String->IsFirst = Macro->IsFirst;
    String->LastNewlineOffset = Macro->LastNewlineOffset;
    String->WhitespaceRange = Macro->WhitespaceRange;
    String->OriginalColumn = Macro->OriginalColumn;
    String->ColumnWidth = encoding::columnWidthWithTabs(
        String->TokenText, String->OriginalColumn, Style.TabWidth, Encoding);

    Tokens.pop_back();
    Tokens.pop_back();
    Tokens.pop_back();
    Tokens.back() = String;
    return true;
  }

  bool tryMergeConflictMarkers() {
    if (Tokens.back()->NewlinesBefore == 0 && Tokens.back()->isNot(tok::eof))
      return false;

    // Conflict lines look like:
    // <marker> <text from the vcs>
    // For example:
    // >>>>>>> /file/in/file/system at revision 1234
    //
    // We merge all tokens in a line that starts with a conflict marker
    // into a single token with a special token type that the unwrapped line
    // parser will use to correctly rebuild the underlying code.

    FileID ID;
    // Get the position of the first token in the line.
    unsigned FirstInLineOffset;
    std::tie(ID, FirstInLineOffset) = SourceMgr.getDecomposedLoc(
        Tokens[FirstInLineIndex]->getStartOfNonWhitespace());
    StringRef Buffer = SourceMgr.getBuffer(ID)->getBuffer();
    // Calculate the offset of the start of the current line.
    auto LineOffset = Buffer.rfind('\n', FirstInLineOffset);
    if (LineOffset == StringRef::npos) {
      LineOffset = 0;
    } else {
      ++LineOffset;
    }

    auto FirstSpace = Buffer.find_first_of(" \n", LineOffset);
    StringRef LineStart;
    if (FirstSpace == StringRef::npos) {
      LineStart = Buffer.substr(LineOffset);
    } else {
      LineStart = Buffer.substr(LineOffset, FirstSpace - LineOffset);
    }

    TokenType Type = TT_Unknown;
    if (LineStart == "<<<<<<<" || LineStart == ">>>>") {
      Type = TT_ConflictStart;
    } else if (LineStart == "|||||||" || LineStart == "=======" ||
               LineStart == "====") {
      Type = TT_ConflictAlternative;
    } else if (LineStart == ">>>>>>>" || LineStart == "<<<<") {
      Type = TT_ConflictEnd;
    }

    if (Type != TT_Unknown) {
      FormatToken *Next = Tokens.back();

      Tokens.resize(FirstInLineIndex + 1);
      // We do not need to build a complete token here, as we will skip it
      // during parsing anyway (as we must not touch whitespace around conflict
      // markers).
      Tokens.back()->Type = Type;
      Tokens.back()->Tok.setKind(tok::kw___unknown_anytype);

      Tokens.push_back(Next);
      return true;
    }

    return false;
  }

  FormatToken *getNextToken() {
    if (GreaterStashed) {
      // Create a synthesized second '>' token.
      // FIXME: Increment Column and set OriginalColumn.
      Token Greater = FormatTok->Tok;
      FormatTok = new (Allocator.Allocate()) FormatToken;
      FormatTok->Tok = Greater;
      SourceLocation GreaterLocation =
          FormatTok->Tok.getLocation().getLocWithOffset(1);
      FormatTok->WhitespaceRange =
          SourceRange(GreaterLocation, GreaterLocation);
      FormatTok->TokenText = ">";
      FormatTok->ColumnWidth = 1;
      GreaterStashed = false;
      return FormatTok;
    }

    FormatTok = new (Allocator.Allocate()) FormatToken;
    readRawToken(*FormatTok);
    SourceLocation WhitespaceStart =
        FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace);
    FormatTok->IsFirst = IsFirstToken;
    IsFirstToken = false;

    // Consume and record whitespace until we find a significant token.
    unsigned WhitespaceLength = TrailingWhitespace;
    while (FormatTok->Tok.is(tok::unknown)) {
      for (int i = 0, e = FormatTok->TokenText.size(); i != e; ++i) {
        switch (FormatTok->TokenText[i]) {
        case '\n':
          ++FormatTok->NewlinesBefore;
          // FIXME: This is technically incorrect, as it could also
          // be a literal backslash at the end of the line.
          if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' &&
                         (FormatTok->TokenText[i - 1] != '\r' || i == 1 ||
                          FormatTok->TokenText[i - 2] != '\\')))
            FormatTok->HasUnescapedNewline = true;
          FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
          Column = 0;
          break;
        case '\r':
        case '\f':
        case '\v':
          Column = 0;
          break;
        case ' ':
          ++Column;
          break;
        case '\t':
          Column += Style.TabWidth - Column % Style.TabWidth;
          break;
        case '\\':
          ++Column;
          if (i + 1 == e || (FormatTok->TokenText[i + 1] != '\r' &&
                             FormatTok->TokenText[i + 1] != '\n'))
            FormatTok->Type = TT_ImplicitStringLiteral;
          break;
        default:
          FormatTok->Type = TT_ImplicitStringLiteral;
          ++Column;
          break;
        }
      }

      if (FormatTok->Type == TT_ImplicitStringLiteral)
        break;
      WhitespaceLength += FormatTok->Tok.getLength();

      readRawToken(*FormatTok);
    }

    // In case the token starts with escaped newlines, we want to
    // take them into account as whitespace - this pattern is quite frequent
    // in macro definitions.
    // FIXME: Add a more explicit test.
    while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' &&
           FormatTok->TokenText[1] == '\n') {
      ++FormatTok->NewlinesBefore;
      WhitespaceLength += 2;
      Column = 0;
      FormatTok->TokenText = FormatTok->TokenText.substr(2);
    }

    FormatTok->WhitespaceRange = SourceRange(
        WhitespaceStart, WhitespaceStart.getLocWithOffset(WhitespaceLength));

    FormatTok->OriginalColumn = Column;

    TrailingWhitespace = 0;
    if (FormatTok->Tok.is(tok::comment)) {
      // FIXME: Add the trimmed whitespace to Column.
      StringRef UntrimmedText = FormatTok->TokenText;
      FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f");
      TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size();
    } else if (FormatTok->Tok.is(tok::raw_identifier)) {
      IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText);
      FormatTok->Tok.setIdentifierInfo(&Info);
      FormatTok->Tok.setKind(Info.getTokenID());
    } else if (FormatTok->Tok.is(tok::greatergreater)) {
      FormatTok->Tok.setKind(tok::greater);
      FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
      GreaterStashed = true;
    }

    // Now FormatTok is the next non-whitespace token.

    StringRef Text = FormatTok->TokenText;
    size_t FirstNewlinePos = Text.find('\n');
    if (FirstNewlinePos == StringRef::npos) {
      // FIXME: ColumnWidth actually depends on the start column, we need to
      // take this into account when the token is moved.
      FormatTok->ColumnWidth =
          encoding::columnWidthWithTabs(Text, Column, Style.TabWidth, Encoding);
      Column += FormatTok->ColumnWidth;
    } else {
      FormatTok->IsMultiline = true;
      // FIXME: ColumnWidth actually depends on the start column, we need to
      // take this into account when the token is moved.
      FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
          Text.substr(0, FirstNewlinePos), Column, Style.TabWidth, Encoding);

      // The last line of the token always starts in column 0.
      // Thus, the length can be precomputed even in the presence of tabs.
      FormatTok->LastLineColumnWidth = encoding::columnWidthWithTabs(
          Text.substr(Text.find_last_of('\n') + 1), 0, Style.TabWidth,
          Encoding);
      Column = FormatTok->LastLineColumnWidth;
    }

    FormatTok->IsForEachMacro =
        std::binary_search(ForEachMacros.begin(), ForEachMacros.end(),
                           FormatTok->Tok.getIdentifierInfo());

    return FormatTok;
  }

  FormatToken *FormatTok;
  bool IsFirstToken;
  bool GreaterStashed;
  unsigned Column;
  unsigned TrailingWhitespace;
  Lexer &Lex;
  SourceManager &SourceMgr;
  FormatStyle &Style;
  IdentifierTable IdentTable;
  encoding::Encoding Encoding;
  llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
  // Index (in 'Tokens') of the last token that starts a new line.
  unsigned FirstInLineIndex;
  SmallVector<FormatToken *, 16> Tokens;
  SmallVector<IdentifierInfo *, 8> ForEachMacros;

  bool FormattingDisabled;

  void readRawToken(FormatToken &Tok) {
    Lex.LexFromRawLexer(Tok.Tok);
    Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
                              Tok.Tok.getLength());
    // For formatting, treat unterminated string literals like normal string
    // literals.
    if (Tok.is(tok::unknown)) {
      if (!Tok.TokenText.empty() && Tok.TokenText[0] == '"') {
        Tok.Tok.setKind(tok::string_literal);
        Tok.IsUnterminatedLiteral = true;
      } else if (Style.Language == FormatStyle::LK_JavaScript &&
                 Tok.TokenText == "''") {
        Tok.Tok.setKind(tok::char_constant);
      }
    }
    if (Tok.is(tok::comment) && Tok.TokenText == "// clang-format on")
      FormattingDisabled = false;
    Tok.Finalized = FormattingDisabled;
    if (Tok.is(tok::comment) && Tok.TokenText == "// clang-format off")
      FormattingDisabled = true;
  }
};

static StringRef getLanguageName(FormatStyle::LanguageKind Language) {
  switch (Language) {
  case FormatStyle::LK_Cpp:
    return "C++";
  case FormatStyle::LK_JavaScript:
    return "JavaScript";
  case FormatStyle::LK_Proto:
    return "Proto";
  default:
    return "Unknown";
  }
}

class Formatter : public UnwrappedLineConsumer {
public:
  Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
            const std::vector<CharSourceRange> &Ranges)
      : Style(Style), Lex(Lex), SourceMgr(SourceMgr),
        Whitespaces(SourceMgr, Style, inputUsesCRLF(Lex.getBuffer())),
        Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1),
        Encoding(encoding::detectEncoding(Lex.getBuffer())) {
    DEBUG(llvm::dbgs() << "File encoding: "
                       << (Encoding == encoding::Encoding_UTF8 ? "UTF8"
                                                               : "unknown")
                       << "\n");
    DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)
                       << "\n");
  }

  tooling::Replacements format() {
    tooling::Replacements Result;
    FormatTokenLexer Tokens(Lex, SourceMgr, Style, Encoding);

    UnwrappedLineParser Parser(Style, Tokens.lex(), *this);
    bool StructuralError = Parser.parse();
    assert(UnwrappedLines.rbegin()->empty());
    for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE;
         ++Run) {
      DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
      SmallVector<AnnotatedLine *, 16> AnnotatedLines;
      for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) {
        AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i]));
      }
      tooling::Replacements RunResult =
          format(AnnotatedLines, StructuralError, Tokens);
      DEBUG({
        llvm::dbgs() << "Replacements for run " << Run << ":\n";
        for (tooling::Replacements::iterator I = RunResult.begin(),
                                             E = RunResult.end();
             I != E; ++I) {
          llvm::dbgs() << I->toString() << "\n";
        }
      });
      for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
        delete AnnotatedLines[i];
      }
      Result.insert(RunResult.begin(), RunResult.end());
      Whitespaces.reset();
    }
    return Result;
  }

  tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                               bool StructuralError, FormatTokenLexer &Tokens) {
    TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      Annotator.annotate(*AnnotatedLines[i]);
    }
    deriveLocalStyle(AnnotatedLines);
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
    }
    computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end());

    Annotator.setCommentLineLevels(AnnotatedLines);
    ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,
                                  BinPackInconclusiveFunctions);
    UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style);
    Formatter.format(AnnotatedLines, /*DryRun=*/false);
    return Whitespaces.generateReplacements();
  }

private:
  // Determines which lines are affected by the SourceRanges given as input.
  // Returns \c true if at least one line between I and E or one of their
  // children is affected.
  bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I,
                            SmallVectorImpl<AnnotatedLine *>::iterator E) {
    bool SomeLineAffected = false;
    const AnnotatedLine *PreviousLine = nullptr;
    while (I != E) {
      AnnotatedLine *Line = *I;
      Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);

      // If a line is part of a preprocessor directive, it needs to be formatted
      // if any token within the directive is affected.
      if (Line->InPPDirective) {
        FormatToken *Last = Line->Last;
        SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
        while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
          Last = (*PPEnd)->Last;
          ++PPEnd;
        }

        if (affectsTokenRange(*Line->First, *Last,
                              /*IncludeLeadingNewlines=*/false)) {
          SomeLineAffected = true;
          markAllAsAffected(I, PPEnd);
        }
        I = PPEnd;
        continue;
      }

      if (nonPPLineAffected(Line, PreviousLine))
        SomeLineAffected = true;

      PreviousLine = Line;
      ++I;
    }
    return SomeLineAffected;
  }

  // Determines whether 'Line' is affected by the SourceRanges given as input.
  // Returns \c true if line or one if its children is affected.
  bool nonPPLineAffected(AnnotatedLine *Line,
                         const AnnotatedLine *PreviousLine) {
    bool SomeLineAffected = false;
    Line->ChildrenAffected =
        computeAffectedLines(Line->Children.begin(), Line->Children.end());
    if (Line->ChildrenAffected)
      SomeLineAffected = true;

    // Stores whether one of the line's tokens is directly affected.
    bool SomeTokenAffected = false;
    // Stores whether we need to look at the leading newlines of the next token
    // in order to determine whether it was affected.
    bool IncludeLeadingNewlines = false;

    // Stores whether the first child line of any of this line's tokens is
    // affected.
    bool SomeFirstChildAffected = false;

    for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
      // Determine whether 'Tok' was affected.
      if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
        SomeTokenAffected = true;

      // Determine whether the first child of 'Tok' was affected.
      if (!Tok->Children.empty() && Tok->Children.front()->Affected)
        SomeFirstChildAffected = true;

      IncludeLeadingNewlines = Tok->Children.empty();
    }

    // Was this line moved, i.e. has it previously been on the same line as an
    // affected line?
    bool LineMoved = PreviousLine && PreviousLine->Affected &&
                     Line->First->NewlinesBefore == 0;

    bool IsContinuedComment =
        Line->First->is(tok::comment) && Line->First->Next == nullptr &&
        Line->First->NewlinesBefore < 2 && PreviousLine &&
        PreviousLine->Affected && PreviousLine->Last->is(tok::comment);

    if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
        IsContinuedComment) {
      Line->Affected = true;
      SomeLineAffected = true;
    }
    return SomeLineAffected;
  }

  // Marks all lines between I and E as well as all their children as affected.
  void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I,
                         SmallVectorImpl<AnnotatedLine *>::iterator E) {
    while (I != E) {
      (*I)->Affected = true;
      markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
      ++I;
    }
  }

  // Returns true if the range from 'First' to 'Last' intersects with one of the
  // input ranges.
  bool affectsTokenRange(const FormatToken &First, const FormatToken &Last,
                         bool IncludeLeadingNewlines) {
    SourceLocation Start = First.WhitespaceRange.getBegin();
    if (!IncludeLeadingNewlines)
      Start = Start.getLocWithOffset(First.LastNewlineOffset);
    SourceLocation End = Last.getStartOfNonWhitespace();
    if (Last.TokenText.size() > 0)
      End = End.getLocWithOffset(Last.TokenText.size() - 1);
    CharSourceRange Range = CharSourceRange::getCharRange(Start, End);
    return affectsCharSourceRange(Range);
  }

  // Returns true if one of the input ranges intersect the leading empty lines
  // before 'Tok'.
  bool affectsLeadingEmptyLines(const FormatToken &Tok) {
    CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(
        Tok.WhitespaceRange.getBegin(),
        Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));
    return affectsCharSourceRange(EmptyLineRange);
  }

  // Returns true if 'Range' intersects with one of the input ranges.
  bool affectsCharSourceRange(const CharSourceRange &Range) {
    for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
                                                          E = Ranges.end();
         I != E; ++I) {
      if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
          !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
        return true;
    }
    return false;
  }

  static bool inputUsesCRLF(StringRef Text) {
    return Text.count('\r') * 2 > Text.count('\n');
  }

  void
  deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
    unsigned CountBoundToVariable = 0;
    unsigned CountBoundToType = 0;
    bool HasCpp03IncompatibleFormat = false;
    bool HasBinPackedFunction = false;
    bool HasOnePerLineFunction = false;
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      if (!AnnotatedLines[i]->First->Next)
        continue;
      FormatToken *Tok = AnnotatedLines[i]->First->Next;
      while (Tok->Next) {
        if (Tok->Type == TT_PointerOrReference) {
          bool SpacesBefore =
              Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
          bool SpacesAfter = Tok->Next->WhitespaceRange.getBegin() !=
                             Tok->Next->WhitespaceRange.getEnd();
          if (SpacesBefore && !SpacesAfter)
            ++CountBoundToVariable;
          else if (!SpacesBefore && SpacesAfter)
            ++CountBoundToType;
        }

        if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
          if (Tok->is(tok::coloncolon) &&
              Tok->Previous->Type == TT_TemplateOpener)
            HasCpp03IncompatibleFormat = true;
          if (Tok->Type == TT_TemplateCloser &&
              Tok->Previous->Type == TT_TemplateCloser)
            HasCpp03IncompatibleFormat = true;
        }

        if (Tok->PackingKind == PPK_BinPacked)
          HasBinPackedFunction = true;
        if (Tok->PackingKind == PPK_OnePerLine)
          HasOnePerLineFunction = true;

        Tok = Tok->Next;
      }
    }
    if (Style.DerivePointerAlignment) {
      if (CountBoundToType > CountBoundToVariable)
        Style.PointerAlignment = FormatStyle::PAS_Left;
      else if (CountBoundToType < CountBoundToVariable)
        Style.PointerAlignment = FormatStyle::PAS_Right;
    }
    if (Style.Standard == FormatStyle::LS_Auto) {
      Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11
                                                  : FormatStyle::LS_Cpp03;
    }
    BinPackInconclusiveFunctions =
        HasBinPackedFunction || !HasOnePerLineFunction;
  }

  void consumeUnwrappedLine(const UnwrappedLine &TheLine) override {
    assert(!UnwrappedLines.empty());
    UnwrappedLines.back().push_back(TheLine);
  }

  void finishRun() override {
    UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>());
  }

  FormatStyle Style;
  Lexer &Lex;
  SourceManager &SourceMgr;
  WhitespaceManager Whitespaces;
  SmallVector<CharSourceRange, 8> Ranges;
  SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines;

  encoding::Encoding Encoding;
  bool BinPackInconclusiveFunctions;
};

} // end anonymous namespace

tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
                               SourceManager &SourceMgr,
                               std::vector<CharSourceRange> Ranges) {
  if (Style.DisableFormat) {
    tooling::Replacements EmptyResult;
    return EmptyResult;
  }

  Formatter formatter(Style, Lex, SourceMgr, Ranges);
  return formatter.format();
}

tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               std::vector<tooling::Range> Ranges,
                               StringRef FileName) {
  FileManager Files((FileSystemOptions()));
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
      new DiagnosticOptions);
  SourceManager SourceMgr(Diagnostics, Files);
  llvm::MemoryBuffer *Buf = llvm::MemoryBuffer::getMemBuffer(Code, FileName);
  const clang::FileEntry *Entry =
      Files.getVirtualFile(FileName, Buf->getBufferSize(), 0);
  SourceMgr.overrideFileContents(Entry, Buf);
  FileID ID =
      SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
  Lexer Lex(ID, SourceMgr.getBuffer(ID), SourceMgr,
            getFormattingLangOpts(Style.Standard));
  SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);
  std::vector<CharSourceRange> CharRanges;
  for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
    SourceLocation Start = StartOfFile.getLocWithOffset(Ranges[i].getOffset());
    SourceLocation End = Start.getLocWithOffset(Ranges[i].getLength());
    CharRanges.push_back(CharSourceRange::getCharRange(Start, End));
  }
  return reformat(Style, Lex, SourceMgr, CharRanges);
}

LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard) {
  LangOptions LangOpts;
  LangOpts.CPlusPlus = 1;
  LangOpts.CPlusPlus11 = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.CPlusPlus1y = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.LineComment = 1;
  LangOpts.CXXOperatorNames = 1;
  LangOpts.Bool = 1;
  LangOpts.ObjC1 = 1;
  LangOpts.ObjC2 = 1;
  return LangOpts;
}

const char *StyleOptionHelpDescription =
    "Coding style, currently supports:\n"
    "  LLVM, Google, Chromium, Mozilla, WebKit.\n"
    "Use -style=file to load style configuration from\n"
    ".clang-format file located in one of the parent\n"
    "directories of the source file (or current\n"
    "directory for stdin).\n"
    "Use -style=\"{key: value, ...}\" to set specific\n"
    "parameters, e.g.:\n"
    "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";

static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
  if (FileName.endswith_lower(".js")) {
    return FormatStyle::LK_JavaScript;
  } else if (FileName.endswith_lower(".proto") ||
             FileName.endswith_lower(".protodevel")) {
    return FormatStyle::LK_Proto;
  }
  return FormatStyle::LK_Cpp;
}

FormatStyle getStyle(StringRef StyleName, StringRef FileName,
                     StringRef FallbackStyle) {
  FormatStyle Style = getLLVMStyle();
  Style.Language = getLanguageByFileName(FileName);
  if (!getPredefinedStyle(FallbackStyle, Style.Language, &Style)) {
    llvm::errs() << "Invalid fallback style \"" << FallbackStyle
                 << "\" using LLVM style\n";
    return Style;
  }

  if (StyleName.startswith("{")) {
    // Parse YAML/JSON style from the command line.
    if (std::error_code ec = parseConfiguration(StyleName, &Style)) {
      llvm::errs() << "Error parsing -style: " << ec.message() << ", using "
                   << FallbackStyle << " style\n";
    }
    return Style;
  }

  if (!StyleName.equals_lower("file")) {
    if (!getPredefinedStyle(StyleName, Style.Language, &Style))
      llvm::errs() << "Invalid value for -style, using " << FallbackStyle
                   << " style\n";
    return Style;
  }

  // Look for .clang-format/_clang-format file in the file's parent directories.
  SmallString<128> UnsuitableConfigFiles;
  SmallString<128> Path(FileName);
  llvm::sys::fs::make_absolute(Path);
  for (StringRef Directory = Path; !Directory.empty();
       Directory = llvm::sys::path::parent_path(Directory)) {
    if (!llvm::sys::fs::is_directory(Directory))
      continue;
    SmallString<128> ConfigFile(Directory);

    llvm::sys::path::append(ConfigFile, ".clang-format");
    DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
    bool IsFile = false;
    // Ignore errors from is_regular_file: we only need to know if we can read
    // the file or not.
    llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);

    if (!IsFile) {
      // Try _clang-format too, since dotfiles are not commonly used on Windows.
      ConfigFile = Directory;
      llvm::sys::path::append(ConfigFile, "_clang-format");
      DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
      llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
    }

    if (IsFile) {
      llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
          llvm::MemoryBuffer::getFile(ConfigFile.c_str());
      if (std::error_code EC = Text.getError()) {
        llvm::errs() << EC.message() << "\n";
        break;
      }
      if (std::error_code ec =
              parseConfiguration(Text.get()->getBuffer(), &Style)) {
        if (ec == ParseError::Unsuitable) {
          if (!UnsuitableConfigFiles.empty())
            UnsuitableConfigFiles.append(", ");
          UnsuitableConfigFiles.append(ConfigFile);
          continue;
        }
        llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()
                     << "\n";
        break;
      }
      DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
      return Style;
    }
  }
  llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle
               << " style\n";
  if (!UnsuitableConfigFiles.empty()) {
    llvm::errs() << "Configuration file(s) do(es) not support "
                 << getLanguageName(Style.Language) << ": "
                 << UnsuitableConfigFiles << "\n";
  }
  return Style;
}

} // namespace format
} // namespace clang
@


1.1.1.4.4.1
log
@file Format.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:27 +0000
@
text
@d1 1820
@


1.1.1.4.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 1820
//===--- Format.cpp - Format C++ code -------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief This file implements functions declared in Format.h. This will be
/// split into separate files as we go.
///
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "format-formatter"

#include "ContinuationIndenter.h"
#include "TokenAnnotator.h"
#include "UnwrappedLineParser.h"
#include "WhitespaceManager.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Format/Format.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/YAMLTraits.h"
#include <queue>
#include <string>

using clang::format::FormatStyle;

namespace llvm {
namespace yaml {
template <> struct ScalarEnumerationTraits<FormatStyle::LanguageKind> {
  static void enumeration(IO &IO, FormatStyle::LanguageKind &Value) {
    IO.enumCase(Value, "Cpp", FormatStyle::LK_Cpp);
    IO.enumCase(Value, "JavaScript", FormatStyle::LK_JavaScript);
    IO.enumCase(Value, "Proto", FormatStyle::LK_Proto);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::LanguageStandard> {
  static void enumeration(IO &IO, FormatStyle::LanguageStandard &Value) {
    IO.enumCase(Value, "Cpp03", FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "C++03", FormatStyle::LS_Cpp03);
    IO.enumCase(Value, "Cpp11", FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "C++11", FormatStyle::LS_Cpp11);
    IO.enumCase(Value, "Auto", FormatStyle::LS_Auto);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::UseTabStyle> {
  static void enumeration(IO &IO, FormatStyle::UseTabStyle &Value) {
    IO.enumCase(Value, "Never", FormatStyle::UT_Never);
    IO.enumCase(Value, "false", FormatStyle::UT_Never);
    IO.enumCase(Value, "Always", FormatStyle::UT_Always);
    IO.enumCase(Value, "true", FormatStyle::UT_Always);
    IO.enumCase(Value, "ForIndentation", FormatStyle::UT_ForIndentation);
  }
};

template <> struct ScalarEnumerationTraits<FormatStyle::BraceBreakingStyle> {
  static void enumeration(IO &IO, FormatStyle::BraceBreakingStyle &Value) {
    IO.enumCase(Value, "Attach", FormatStyle::BS_Attach);
    IO.enumCase(Value, "Linux", FormatStyle::BS_Linux);
    IO.enumCase(Value, "Stroustrup", FormatStyle::BS_Stroustrup);
    IO.enumCase(Value, "Allman", FormatStyle::BS_Allman);
    IO.enumCase(Value, "GNU", FormatStyle::BS_GNU);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::NamespaceIndentationKind> {
  static void enumeration(IO &IO,
                          FormatStyle::NamespaceIndentationKind &Value) {
    IO.enumCase(Value, "None", FormatStyle::NI_None);
    IO.enumCase(Value, "Inner", FormatStyle::NI_Inner);
    IO.enumCase(Value, "All", FormatStyle::NI_All);
  }
};

template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensOptions> {
  static void enumeration(IO &IO,
                          FormatStyle::SpaceBeforeParensOptions &Value) {
    IO.enumCase(Value, "Never", FormatStyle::SBPO_Never);
    IO.enumCase(Value, "ControlStatements",
                FormatStyle::SBPO_ControlStatements);
    IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);

    // For backward compatibility.
    IO.enumCase(Value, "false", FormatStyle::SBPO_Never);
    IO.enumCase(Value, "true", FormatStyle::SBPO_ControlStatements);
  }
};

template <> struct MappingTraits<FormatStyle> {
  static void mapping(IO &IO, FormatStyle &Style) {
    // When reading, read the language first, we need it for getPredefinedStyle.
    IO.mapOptional("Language", Style.Language);

    if (IO.outputting()) {
      StringRef StylesArray[] = { "LLVM",    "Google", "Chromium",
                                  "Mozilla", "WebKit", "GNU" };
      ArrayRef<StringRef> Styles(StylesArray);
      for (size_t i = 0, e = Styles.size(); i < e; ++i) {
        StringRef StyleName(Styles[i]);
        FormatStyle PredefinedStyle;
        if (getPredefinedStyle(StyleName, Style.Language, &PredefinedStyle) &&
            Style == PredefinedStyle) {
          IO.mapOptional("# BasedOnStyle", StyleName);
          break;
        }
      }
    } else {
      StringRef BasedOnStyle;
      IO.mapOptional("BasedOnStyle", BasedOnStyle);
      if (!BasedOnStyle.empty()) {
        FormatStyle::LanguageKind OldLanguage = Style.Language;
        FormatStyle::LanguageKind Language =
            ((FormatStyle *)IO.getContext())->Language;
        if (!getPredefinedStyle(BasedOnStyle, Language, &Style)) {
          IO.setError(Twine("Unknown value for BasedOnStyle: ", BasedOnStyle));
          return;
        }
        Style.Language = OldLanguage;
      }
    }

    IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
    IO.mapOptional("ConstructorInitializerIndentWidth",
                   Style.ConstructorInitializerIndentWidth);
    IO.mapOptional("AlignEscapedNewlinesLeft", Style.AlignEscapedNewlinesLeft);
    IO.mapOptional("AlignTrailingComments", Style.AlignTrailingComments);
    IO.mapOptional("AllowAllParametersOfDeclarationOnNextLine",
                   Style.AllowAllParametersOfDeclarationOnNextLine);
    IO.mapOptional("AllowShortIfStatementsOnASingleLine",
                   Style.AllowShortIfStatementsOnASingleLine);
    IO.mapOptional("AllowShortLoopsOnASingleLine",
                   Style.AllowShortLoopsOnASingleLine);
    IO.mapOptional("AllowShortFunctionsOnASingleLine",
                   Style.AllowShortFunctionsOnASingleLine);
    IO.mapOptional("AlwaysBreakTemplateDeclarations",
                   Style.AlwaysBreakTemplateDeclarations);
    IO.mapOptional("AlwaysBreakBeforeMultilineStrings",
                   Style.AlwaysBreakBeforeMultilineStrings);
    IO.mapOptional("BreakBeforeBinaryOperators",
                   Style.BreakBeforeBinaryOperators);
    IO.mapOptional("BreakBeforeTernaryOperators",
                   Style.BreakBeforeTernaryOperators);
    IO.mapOptional("BreakConstructorInitializersBeforeComma",
                   Style.BreakConstructorInitializersBeforeComma);
    IO.mapOptional("BinPackParameters", Style.BinPackParameters);
    IO.mapOptional("ColumnLimit", Style.ColumnLimit);
    IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
                   Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
    IO.mapOptional("DerivePointerBinding", Style.DerivePointerBinding);
    IO.mapOptional("ExperimentalAutoDetectBinPacking",
                   Style.ExperimentalAutoDetectBinPacking);
    IO.mapOptional("IndentCaseLabels", Style.IndentCaseLabels);
    IO.mapOptional("MaxEmptyLinesToKeep", Style.MaxEmptyLinesToKeep);
    IO.mapOptional("NamespaceIndentation", Style.NamespaceIndentation);
    IO.mapOptional("ObjCSpaceAfterProperty", Style.ObjCSpaceAfterProperty);
    IO.mapOptional("ObjCSpaceBeforeProtocolList",
                   Style.ObjCSpaceBeforeProtocolList);
    IO.mapOptional("PenaltyBreakBeforeFirstCallParameter",
                   Style.PenaltyBreakBeforeFirstCallParameter);
    IO.mapOptional("PenaltyBreakComment", Style.PenaltyBreakComment);
    IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
    IO.mapOptional("PenaltyBreakFirstLessLess",
                   Style.PenaltyBreakFirstLessLess);
    IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
    IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
                   Style.PenaltyReturnTypeOnItsOwnLine);
    IO.mapOptional("PointerBindsToType", Style.PointerBindsToType);
    IO.mapOptional("SpacesBeforeTrailingComments",
                   Style.SpacesBeforeTrailingComments);
    IO.mapOptional("Cpp11BracedListStyle", Style.Cpp11BracedListStyle);
    IO.mapOptional("Standard", Style.Standard);
    IO.mapOptional("IndentWidth", Style.IndentWidth);
    IO.mapOptional("TabWidth", Style.TabWidth);
    IO.mapOptional("UseTab", Style.UseTab);
    IO.mapOptional("BreakBeforeBraces", Style.BreakBeforeBraces);
    IO.mapOptional("IndentFunctionDeclarationAfterType",
                   Style.IndentFunctionDeclarationAfterType);
    IO.mapOptional("SpacesInParentheses", Style.SpacesInParentheses);
    IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
    IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses);
    IO.mapOptional("SpacesInCStyleCastParentheses",
                   Style.SpacesInCStyleCastParentheses);
    IO.mapOptional("SpacesInContainerLiterals",
                   Style.SpacesInContainerLiterals);
    IO.mapOptional("SpaceBeforeAssignmentOperators",
                   Style.SpaceBeforeAssignmentOperators);
    IO.mapOptional("ContinuationIndentWidth", Style.ContinuationIndentWidth);
    IO.mapOptional("CommentPragmas", Style.CommentPragmas);

    // For backward compatibility.
    if (!IO.outputting()) {
      IO.mapOptional("SpaceAfterControlStatementKeyword",
                     Style.SpaceBeforeParens);
    }
    IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
  }
};

// Allows to read vector<FormatStyle> while keeping default values.
// IO.getContext() should contain a pointer to the FormatStyle structure, that
// will be used to get default values for missing keys.
// If the first element has no Language specified, it will be treated as the
// default one for the following elements.
template <> struct DocumentListTraits<std::vector<FormatStyle> > {
  static size_t size(IO &IO, std::vector<FormatStyle> &Seq) {
    return Seq.size();
  }
  static FormatStyle &element(IO &IO, std::vector<FormatStyle> &Seq,
                              size_t Index) {
    if (Index >= Seq.size()) {
      assert(Index == Seq.size());
      FormatStyle Template;
      if (Seq.size() > 0 && Seq[0].Language == FormatStyle::LK_None) {
        Template = Seq[0];
      } else {
        Template = *((const FormatStyle*)IO.getContext());
        Template.Language = FormatStyle::LK_None;
      }
      Seq.resize(Index + 1, Template);
    }
    return Seq[Index];
  }
};
}
}

namespace clang {
namespace format {

FormatStyle getLLVMStyle() {
  FormatStyle LLVMStyle;
  LLVMStyle.Language = FormatStyle::LK_Cpp;
  LLVMStyle.AccessModifierOffset = -2;
  LLVMStyle.AlignEscapedNewlinesLeft = false;
  LLVMStyle.AlignTrailingComments = true;
  LLVMStyle.AllowAllParametersOfDeclarationOnNextLine = true;
  LLVMStyle.AllowShortFunctionsOnASingleLine = true;
  LLVMStyle.AllowShortIfStatementsOnASingleLine = false;
  LLVMStyle.AllowShortLoopsOnASingleLine = false;
  LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
  LLVMStyle.AlwaysBreakTemplateDeclarations = false;
  LLVMStyle.BinPackParameters = true;
  LLVMStyle.BreakBeforeBinaryOperators = false;
  LLVMStyle.BreakBeforeTernaryOperators = true;
  LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
  LLVMStyle.BreakConstructorInitializersBeforeComma = false;
  LLVMStyle.ColumnLimit = 80;
  LLVMStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = false;
  LLVMStyle.ConstructorInitializerIndentWidth = 4;
  LLVMStyle.Cpp11BracedListStyle = false;
  LLVMStyle.DerivePointerBinding = false;
  LLVMStyle.ExperimentalAutoDetectBinPacking = false;
  LLVMStyle.IndentCaseLabels = false;
  LLVMStyle.IndentFunctionDeclarationAfterType = false;
  LLVMStyle.IndentWidth = 2;
  LLVMStyle.TabWidth = 8;
  LLVMStyle.MaxEmptyLinesToKeep = 1;
  LLVMStyle.NamespaceIndentation = FormatStyle::NI_None;
  LLVMStyle.ObjCSpaceAfterProperty = false;
  LLVMStyle.ObjCSpaceBeforeProtocolList = true;
  LLVMStyle.PointerBindsToType = false;
  LLVMStyle.SpacesBeforeTrailingComments = 1;
  LLVMStyle.Standard = FormatStyle::LS_Cpp03;
  LLVMStyle.UseTab = FormatStyle::UT_Never;
  LLVMStyle.SpacesInParentheses = false;
  LLVMStyle.SpaceInEmptyParentheses = false;
  LLVMStyle.SpacesInContainerLiterals = true;
  LLVMStyle.SpacesInCStyleCastParentheses = false;
  LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
  LLVMStyle.SpaceBeforeAssignmentOperators = true;
  LLVMStyle.ContinuationIndentWidth = 4;
  LLVMStyle.SpacesInAngles = false;
  LLVMStyle.CommentPragmas = "^ IWYU pragma:";

  LLVMStyle.PenaltyBreakComment = 300;
  LLVMStyle.PenaltyBreakFirstLessLess = 120;
  LLVMStyle.PenaltyBreakString = 1000;
  LLVMStyle.PenaltyExcessCharacter = 1000000;
  LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
  LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;

  return LLVMStyle;
}

FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
  FormatStyle GoogleStyle = getLLVMStyle();
  GoogleStyle.Language = Language;

  GoogleStyle.AccessModifierOffset = -1;
  GoogleStyle.AlignEscapedNewlinesLeft = true;
  GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
  GoogleStyle.AllowShortLoopsOnASingleLine = true;
  GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
  GoogleStyle.AlwaysBreakTemplateDeclarations = true;
  GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
  GoogleStyle.Cpp11BracedListStyle = true;
  GoogleStyle.DerivePointerBinding = true;
  GoogleStyle.IndentCaseLabels = true;
  GoogleStyle.IndentFunctionDeclarationAfterType = true;
  GoogleStyle.ObjCSpaceAfterProperty = false;
  GoogleStyle.ObjCSpaceBeforeProtocolList = false;
  GoogleStyle.PointerBindsToType = true;
  GoogleStyle.SpacesBeforeTrailingComments = 2;
  GoogleStyle.Standard = FormatStyle::LS_Auto;

  GoogleStyle.PenaltyReturnTypeOnItsOwnLine = 200;
  GoogleStyle.PenaltyBreakBeforeFirstCallParameter = 1;

  if (Language == FormatStyle::LK_JavaScript) {
    GoogleStyle.BreakBeforeTernaryOperators = false;
    GoogleStyle.MaxEmptyLinesToKeep = 2;
    GoogleStyle.SpacesInContainerLiterals = false;
  } else if (Language == FormatStyle::LK_Proto) {
    GoogleStyle.AllowShortFunctionsOnASingleLine = false;
  }

  return GoogleStyle;
}

FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language) {
  FormatStyle ChromiumStyle = getGoogleStyle(Language);
  ChromiumStyle.AllowAllParametersOfDeclarationOnNextLine = false;
  ChromiumStyle.AllowShortIfStatementsOnASingleLine = false;
  ChromiumStyle.AllowShortLoopsOnASingleLine = false;
  ChromiumStyle.BinPackParameters = false;
  ChromiumStyle.DerivePointerBinding = false;
  ChromiumStyle.Standard = FormatStyle::LS_Cpp03;
  return ChromiumStyle;
}

FormatStyle getMozillaStyle() {
  FormatStyle MozillaStyle = getLLVMStyle();
  MozillaStyle.AllowAllParametersOfDeclarationOnNextLine = false;
  MozillaStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
  MozillaStyle.DerivePointerBinding = true;
  MozillaStyle.IndentCaseLabels = true;
  MozillaStyle.ObjCSpaceAfterProperty = true;
  MozillaStyle.ObjCSpaceBeforeProtocolList = false;
  MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200;
  MozillaStyle.PointerBindsToType = true;
  return MozillaStyle;
}

FormatStyle getWebKitStyle() {
  FormatStyle Style = getLLVMStyle();
  Style.AccessModifierOffset = -4;
  Style.AlignTrailingComments = false;
  Style.BreakBeforeBinaryOperators = true;
  Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup;
  Style.BreakConstructorInitializersBeforeComma = true;
  Style.ColumnLimit = 0;
  Style.IndentWidth = 4;
  Style.NamespaceIndentation = FormatStyle::NI_Inner;
  Style.ObjCSpaceAfterProperty = true;
  Style.PointerBindsToType = true;
  return Style;
}

FormatStyle getGNUStyle() {
  FormatStyle Style = getLLVMStyle();
  Style.BreakBeforeBinaryOperators = true;
  Style.BreakBeforeBraces = FormatStyle::BS_GNU;
  Style.BreakBeforeTernaryOperators = true;
  Style.ColumnLimit = 79;
  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
  return Style;
}

bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language,
                        FormatStyle *Style) {
  if (Name.equals_lower("llvm")) {
    *Style = getLLVMStyle();
  } else if (Name.equals_lower("chromium")) {
    *Style = getChromiumStyle(Language);
  } else if (Name.equals_lower("mozilla")) {
    *Style = getMozillaStyle();
  } else if (Name.equals_lower("google")) {
    *Style = getGoogleStyle(Language);
  } else if (Name.equals_lower("webkit")) {
    *Style = getWebKitStyle();
  } else if (Name.equals_lower("gnu")) {
    *Style = getGNUStyle();
  } else {
    return false;
  }

  Style->Language = Language;
  return true;
}

llvm::error_code parseConfiguration(StringRef Text, FormatStyle *Style) {
  assert(Style);
  FormatStyle::LanguageKind Language = Style->Language;
  assert(Language != FormatStyle::LK_None);
  if (Text.trim().empty())
    return llvm::make_error_code(llvm::errc::invalid_argument);

  std::vector<FormatStyle> Styles;
  llvm::yaml::Input Input(Text);
  // DocumentListTraits<vector<FormatStyle>> uses the context to get default
  // values for the fields, keys for which are missing from the configuration.
  // Mapping also uses the context to get the language to find the correct
  // base style.
  Input.setContext(Style);
  Input >> Styles;
  if (Input.error())
    return Input.error();

  for (unsigned i = 0; i < Styles.size(); ++i) {
    // Ensures that only the first configuration can skip the Language option.
    if (Styles[i].Language == FormatStyle::LK_None && i != 0)
      return llvm::make_error_code(llvm::errc::invalid_argument);
    // Ensure that each language is configured at most once.
    for (unsigned j = 0; j < i; ++j) {
      if (Styles[i].Language == Styles[j].Language) {
        DEBUG(llvm::dbgs()
              << "Duplicate languages in the config file on positions " << j
              << " and " << i << "\n");
        return llvm::make_error_code(llvm::errc::invalid_argument);
      }
    }
  }
  // Look for a suitable configuration starting from the end, so we can
  // find the configuration for the specific language first, and the default
  // configuration (which can only be at slot 0) after it.
  for (int i = Styles.size() - 1; i >= 0; --i) {
    if (Styles[i].Language == Language ||
        Styles[i].Language == FormatStyle::LK_None) {
      *Style = Styles[i];
      Style->Language = Language;
      return llvm::make_error_code(llvm::errc::success);
    }
  }
  return llvm::make_error_code(llvm::errc::not_supported);
}

std::string configurationAsText(const FormatStyle &Style) {
  std::string Text;
  llvm::raw_string_ostream Stream(Text);
  llvm::yaml::Output Output(Stream);
  // We use the same mapping method for input and output, so we need a non-const
  // reference here.
  FormatStyle NonConstStyle = Style;
  Output << NonConstStyle;
  return Stream.str();
}

namespace {

class NoColumnLimitFormatter {
public:
  NoColumnLimitFormatter(ContinuationIndenter *Indenter) : Indenter(Indenter) {}

  /// \brief Formats the line starting at \p State, simply keeping all of the
  /// input's line breaking decisions.
  void format(unsigned FirstIndent, const AnnotatedLine *Line) {
    LineState State =
        Indenter->getInitialState(FirstIndent, Line, /*DryRun=*/false);
    while (State.NextToken != NULL) {
      bool Newline =
          Indenter->mustBreak(State) ||
          (Indenter->canBreak(State) && State.NextToken->NewlinesBefore > 0);
      Indenter->addTokenToState(State, Newline, /*DryRun=*/false);
    }
  }

private:
  ContinuationIndenter *Indenter;
};

class LineJoiner {
public:
  LineJoiner(const FormatStyle &Style) : Style(Style) {}

  /// \brief Calculates how many lines can be merged into 1 starting at \p I.
  unsigned
  tryFitMultipleLinesInOne(unsigned Indent,
                           SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                           SmallVectorImpl<AnnotatedLine *>::const_iterator E) {
    // We can never merge stuff if there are trailing line comments.
    const AnnotatedLine *TheLine = *I;
    if (TheLine->Last->Type == TT_LineComment)
      return 0;

    if (Style.ColumnLimit > 0 && Indent > Style.ColumnLimit)
      return 0;

    unsigned Limit =
        Style.ColumnLimit == 0 ? UINT_MAX : Style.ColumnLimit - Indent;
    // If we already exceed the column limit, we set 'Limit' to 0. The different
    // tryMerge..() functions can then decide whether to still do merging.
    Limit = TheLine->Last->TotalLength > Limit
                ? 0
                : Limit - TheLine->Last->TotalLength;

    if (I + 1 == E || I[1]->Type == LT_Invalid)
      return 0;

    if (TheLine->Last->Type == TT_FunctionLBrace &&
        TheLine->First != TheLine->Last) {
      return Style.AllowShortFunctionsOnASingleLine
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
    if (TheLine->Last->is(tok::l_brace)) {
      return Style.BreakBeforeBraces == FormatStyle::BS_Attach
                 ? tryMergeSimpleBlock(I, E, Limit)
                 : 0;
    }
    if (I[1]->First->Type == TT_FunctionLBrace &&
        Style.BreakBeforeBraces != FormatStyle::BS_Attach) {
      // Check for Limit <= 2 to account for the " {".
      if (Limit <= 2 || (Style.ColumnLimit == 0 && containsMustBreak(TheLine)))
        return 0;
      Limit -= 2;

      unsigned MergedLines = 0;
      if (Style.AllowShortFunctionsOnASingleLine) {
        MergedLines = tryMergeSimpleBlock(I + 1, E, Limit);
        // If we managed to merge the block, count the function header, which is
        // on a separate line.
        if (MergedLines > 0)
          ++MergedLines;
      }
      return MergedLines;
    }
    if (TheLine->First->is(tok::kw_if)) {
      return Style.AllowShortIfStatementsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while)) {
      return Style.AllowShortLoopsOnASingleLine
                 ? tryMergeSimpleControlStatement(I, E, Limit)
                 : 0;
    }
    if (TheLine->InPPDirective &&
        (TheLine->First->HasUnescapedNewline || TheLine->First->IsFirst)) {
      return tryMergeSimplePPDirective(I, E, Limit);
    }
    return 0;
  }

private:
  unsigned
  tryMergeSimplePPDirective(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                            SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                            unsigned Limit) {
    if (Limit == 0)
      return 0;
    if (!I[1]->InPPDirective || I[1]->First->HasUnescapedNewline)
      return 0;
    if (I + 2 != E && I[2]->InPPDirective && !I[2]->First->HasUnescapedNewline)
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    return 1;
  }

  unsigned tryMergeSimpleControlStatement(
      SmallVectorImpl<AnnotatedLine *>::const_iterator I,
      SmallVectorImpl<AnnotatedLine *>::const_iterator E, unsigned Limit) {
    if (Limit == 0)
      return 0;
    if ((Style.BreakBeforeBraces == FormatStyle::BS_Allman ||
         Style.BreakBeforeBraces == FormatStyle::BS_GNU) &&
        I[1]->First->is(tok::l_brace))
      return 0;
    if (I[1]->InPPDirective != (*I)->InPPDirective ||
        (I[1]->InPPDirective && I[1]->First->HasUnescapedNewline))
      return 0;
    Limit = limitConsideringMacros(I + 1, E, Limit);
    AnnotatedLine &Line = **I;
    if (Line.Last->isNot(tok::r_paren))
      return 0;
    if (1 + I[1]->Last->TotalLength > Limit)
      return 0;
    if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for,
                             tok::kw_while) ||
        I[1]->First->Type == TT_LineComment)
      return 0;
    // Only inline simple if's (no nested if or else).
    if (I + 2 != E && Line.First->is(tok::kw_if) &&
        I[2]->First->is(tok::kw_else))
      return 0;
    return 1;
  }

  unsigned
  tryMergeSimpleBlock(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                      SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                      unsigned Limit) {
    // First, check that the current line allows merging. This is the case if
    // we're not in a control flow statement and the last token is an opening
    // brace.
    AnnotatedLine &Line = **I;
    if (Line.First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_do, tok::r_brace,
                            tok::kw_else, tok::kw_try, tok::kw_catch,
                            tok::kw_for,
                            // This gets rid of all ObjC @@ keywords and methods.
                            tok::at, tok::minus, tok::plus))
      return 0;

    FormatToken *Tok = I[1]->First;
    if (Tok->is(tok::r_brace) && !Tok->MustBreakBefore &&
        (Tok->getNextNonComment() == NULL ||
         Tok->getNextNonComment()->is(tok::semi))) {
      // We merge empty blocks even if the line exceeds the column limit.
      Tok->SpacesRequiredBefore = 0;
      Tok->CanBreakBefore = true;
      return 1;
    } else if (Limit != 0 && Line.First->isNot(tok::kw_namespace)) {
      // Check that we still have three lines and they fit into the limit.
      if (I + 2 == E || I[2]->Type == LT_Invalid)
        return 0;
      Limit = limitConsideringMacros(I + 2, E, Limit);

      if (!nextTwoLinesFitInto(I, Limit))
        return 0;

      // Second, check that the next line does not contain any braces - if it
      // does, readability declines when putting it into a single line.
      if (I[1]->Last->Type == TT_LineComment || Tok->MustBreakBefore)
        return 0;
      do {
        if (Tok->isOneOf(tok::l_brace, tok::r_brace))
          return 0;
        Tok = Tok->Next;
      } while (Tok != NULL);

      // Last, check that the third line contains a single closing brace.
      Tok = I[2]->First;
      if (Tok->getNextNonComment() != NULL || Tok->isNot(tok::r_brace) ||
          Tok->MustBreakBefore)
        return 0;

      return 2;
    }
    return 0;
  }

  /// Returns the modified column limit for \p I if it is inside a macro and
  /// needs a trailing '\'.
  unsigned
  limitConsideringMacros(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                         SmallVectorImpl<AnnotatedLine *>::const_iterator E,
                         unsigned Limit) {
    if (I[0]->InPPDirective && I + 1 != E &&
        !I[1]->First->HasUnescapedNewline && !I[1]->First->is(tok::eof)) {
      return Limit < 2 ? 0 : Limit - 2;
    }
    return Limit;
  }

  bool nextTwoLinesFitInto(SmallVectorImpl<AnnotatedLine *>::const_iterator I,
                           unsigned Limit) {
    return 1 + I[1]->Last->TotalLength + 1 + I[2]->Last->TotalLength <= Limit;
  }

  bool containsMustBreak(const AnnotatedLine *Line) {
    for (const FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
      if (Tok->MustBreakBefore)
        return true;
    }
    return false;
  }

  const FormatStyle &Style;
};

class UnwrappedLineFormatter {
public:
  UnwrappedLineFormatter(ContinuationIndenter *Indenter,
                         WhitespaceManager *Whitespaces,
                         const FormatStyle &Style)
      : Indenter(Indenter), Whitespaces(Whitespaces), Style(Style),
        Joiner(Style) {}

  unsigned format(const SmallVectorImpl<AnnotatedLine *> &Lines, bool DryRun,
                  int AdditionalIndent = 0, bool FixBadIndentation = false) {
    assert(!Lines.empty());
    unsigned Penalty = 0;
    std::vector<int> IndentForLevel;
    for (unsigned i = 0, e = Lines[0]->Level; i != e; ++i)
      IndentForLevel.push_back(Style.IndentWidth * i + AdditionalIndent);
    const AnnotatedLine *PreviousLine = NULL;
    for (SmallVectorImpl<AnnotatedLine *>::const_iterator I = Lines.begin(),
                                                          E = Lines.end();
         I != E; ++I) {
      const AnnotatedLine &TheLine = **I;
      const FormatToken *FirstTok = TheLine.First;
      int Offset = getIndentOffset(*FirstTok);

      // Determine indent and try to merge multiple unwrapped lines.
      unsigned Indent;
      if (TheLine.InPPDirective) {
        Indent = TheLine.Level * Style.IndentWidth;
      } else {
        while (IndentForLevel.size() <= TheLine.Level)
          IndentForLevel.push_back(-1);
        IndentForLevel.resize(TheLine.Level + 1);
        Indent = getIndent(IndentForLevel, TheLine.Level);
      }
      unsigned LevelIndent = Indent;
      if (static_cast<int>(Indent) + Offset >= 0)
        Indent += Offset;

      // Merge multiple lines if possible.
      unsigned MergedLines = Joiner.tryFitMultipleLinesInOne(Indent, I, E);
      if (MergedLines > 0 && Style.ColumnLimit == 0) {
        // Disallow line merging if there is a break at the start of one of the
        // input lines.
        for (unsigned i = 0; i < MergedLines; ++i) {
          if (I[i + 1]->First->NewlinesBefore > 0)
            MergedLines = 0;
        }
      }
      if (!DryRun) {
        for (unsigned i = 0; i < MergedLines; ++i) {
          join(*I[i], *I[i + 1]);
        }
      }
      I += MergedLines;

      bool FixIndentation =
          FixBadIndentation && (LevelIndent != FirstTok->OriginalColumn);
      if (TheLine.First->is(tok::eof)) {
        if (PreviousLine && PreviousLine->Affected && !DryRun) {
          // Remove the file's trailing whitespace.
          unsigned Newlines = std::min(FirstTok->NewlinesBefore, 1u);
          Whitespaces->replaceWhitespace(*TheLine.First, Newlines,
                                         /*IndentLevel=*/0, /*Spaces=*/0,
                                         /*TargetColumn=*/0);
        }
      } else if (TheLine.Type != LT_Invalid &&
                 (TheLine.Affected || FixIndentation)) {
        if (FirstTok->WhitespaceRange.isValid()) {
          if (!DryRun)
            formatFirstToken(*TheLine.First, PreviousLine, TheLine.Level,
                             Indent, TheLine.InPPDirective);
        } else {
          Indent = LevelIndent = FirstTok->OriginalColumn;
        }

        // If everything fits on a single line, just put it there.
        unsigned ColumnLimit = Style.ColumnLimit;
        if (I + 1 != E) {
          AnnotatedLine *NextLine = I[1];
          if (NextLine->InPPDirective && !NextLine->First->HasUnescapedNewline)
            ColumnLimit = getColumnLimit(TheLine.InPPDirective);
        }

        if (TheLine.Last->TotalLength + Indent <= ColumnLimit) {
          LineState State = Indenter->getInitialState(Indent, &TheLine, DryRun);
          while (State.NextToken != NULL)
            Indenter->addTokenToState(State, /*Newline=*/false, DryRun);
        } else if (Style.ColumnLimit == 0) {
          // FIXME: Implement nested blocks for ColumnLimit = 0.
          NoColumnLimitFormatter Formatter(Indenter);
          if (!DryRun)
            Formatter.format(Indent, &TheLine);
        } else {
          Penalty += format(TheLine, Indent, DryRun);
        }

        if (!TheLine.InPPDirective)
          IndentForLevel[TheLine.Level] = LevelIndent;
      } else if (TheLine.ChildrenAffected) {
        format(TheLine.Children, DryRun);
      } else {
        // Format the first token if necessary, and notify the WhitespaceManager
        // about the unchanged whitespace.
        for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
          if (Tok == TheLine.First &&
              (Tok->NewlinesBefore > 0 || Tok->IsFirst)) {
            unsigned LevelIndent = Tok->OriginalColumn;
            if (!DryRun) {
              // Remove trailing whitespace of the previous line.
              if ((PreviousLine && PreviousLine->Affected) ||
                  TheLine.LeadingEmptyLinesAffected) {
                formatFirstToken(*Tok, PreviousLine, TheLine.Level, LevelIndent,
                                 TheLine.InPPDirective);
              } else {
                Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
              }
            }

            if (static_cast<int>(LevelIndent) - Offset >= 0)
              LevelIndent -= Offset;
            if (Tok->isNot(tok::comment) && !TheLine.InPPDirective)
              IndentForLevel[TheLine.Level] = LevelIndent;
          } else if (!DryRun) {
            Whitespaces->addUntouchableToken(*Tok, TheLine.InPPDirective);
          }
        }
      }
      if (!DryRun) {
        for (FormatToken *Tok = TheLine.First; Tok != NULL; Tok = Tok->Next) {
          Tok->Finalized = true;
        }
      }
      PreviousLine = *I;
    }
    return Penalty;
  }

private:
  /// \brief Formats an \c AnnotatedLine and returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned format(const AnnotatedLine &Line, unsigned FirstIndent,
                  bool DryRun) {
    LineState State = Indenter->getInitialState(FirstIndent, &Line, DryRun);

    // If the ObjC method declaration does not fit on a line, we should format
    // it with one arg per line.
    if (State.Line->Type == LT_ObjCMethodDecl)
      State.Stack.back().BreakBeforeParameter = true;

    // Find best solution in solution space.
    return analyzeSolutionSpace(State, DryRun);
  }

  /// \brief An edge in the solution space from \c Previous->State to \c State,
  /// inserting a newline dependent on the \c NewLine.
  struct StateNode {
    StateNode(const LineState &State, bool NewLine, StateNode *Previous)
        : State(State), NewLine(NewLine), Previous(Previous) {}
    LineState State;
    bool NewLine;
    StateNode *Previous;
  };

  /// \brief A pair of <penalty, count> that is used to prioritize the BFS on.
  ///
  /// In case of equal penalties, we want to prefer states that were inserted
  /// first. During state generation we make sure that we insert states first
  /// that break the line as late as possible.
  typedef std::pair<unsigned, unsigned> OrderedPenalty;

  /// \brief An item in the prioritized BFS search queue. The \c StateNode's
  /// \c State has the given \c OrderedPenalty.
  typedef std::pair<OrderedPenalty, StateNode *> QueueItem;

  /// \brief The BFS queue type.
  typedef std::priority_queue<QueueItem, std::vector<QueueItem>,
                              std::greater<QueueItem> > QueueType;

  /// \brief Get the offset of the line relatively to the level.
  ///
  /// For example, 'public:' labels in classes are offset by 1 or 2
  /// characters to the left from their level.
  int getIndentOffset(const FormatToken &RootToken) {
    if (RootToken.isAccessSpecifier(false) || RootToken.isObjCAccessSpecifier())
      return Style.AccessModifierOffset;
    return 0;
  }

  /// \brief Add a new line and the required indent before the first Token
  /// of the \c UnwrappedLine if there was no structural parsing error.
  void formatFirstToken(FormatToken &RootToken,
                        const AnnotatedLine *PreviousLine, unsigned IndentLevel,
                        unsigned Indent, bool InPPDirective) {
    unsigned Newlines =
        std::min(RootToken.NewlinesBefore, Style.MaxEmptyLinesToKeep + 1);
    // Remove empty lines before "}" where applicable.
    if (RootToken.is(tok::r_brace) &&
        (!RootToken.Next ||
         (RootToken.Next->is(tok::semi) && !RootToken.Next->Next)))
      Newlines = std::min(Newlines, 1u);
    if (Newlines == 0 && !RootToken.IsFirst)
      Newlines = 1;

    // Insert extra new line before access specifiers.
    if (PreviousLine && PreviousLine->Last->isOneOf(tok::semi, tok::r_brace) &&
        RootToken.isAccessSpecifier() && RootToken.NewlinesBefore == 1)
      ++Newlines;

    // Remove empty lines after access specifiers.
    if (PreviousLine && PreviousLine->First->isAccessSpecifier())
      Newlines = std::min(1u, Newlines);

    Whitespaces->replaceWhitespace(RootToken, Newlines, IndentLevel, Indent,
                                   Indent, InPPDirective &&
                                               !RootToken.HasUnescapedNewline);
  }

  /// \brief Get the indent of \p Level from \p IndentForLevel.
  ///
  /// \p IndentForLevel must contain the indent for the level \c l
  /// at \p IndentForLevel[l], or a value < 0 if the indent for
  /// that level is unknown.
  unsigned getIndent(const std::vector<int> IndentForLevel, unsigned Level) {
    if (IndentForLevel[Level] != -1)
      return IndentForLevel[Level];
    if (Level == 0)
      return 0;
    return getIndent(IndentForLevel, Level - 1) + Style.IndentWidth;
  }

  void join(AnnotatedLine &A, const AnnotatedLine &B) {
    assert(!A.Last->Next);
    assert(!B.First->Previous);
    if (B.Affected)
      A.Affected = true;
    A.Last->Next = B.First;
    B.First->Previous = A.Last;
    B.First->CanBreakBefore = true;
    unsigned LengthA = A.Last->TotalLength + B.First->SpacesRequiredBefore;
    for (FormatToken *Tok = B.First; Tok; Tok = Tok->Next) {
      Tok->TotalLength += LengthA;
      A.Last = Tok;
    }
  }

  unsigned getColumnLimit(bool InPPDirective) const {
    // In preprocessor directives reserve two chars for trailing " \"
    return Style.ColumnLimit - (InPPDirective ? 2 : 0);
  }

  /// \brief Analyze the entire solution space starting from \p InitialState.
  ///
  /// This implements a variant of Dijkstra's algorithm on the graph that spans
  /// the solution space (\c LineStates are the nodes). The algorithm tries to
  /// find the shortest path (the one with lowest penalty) from \p InitialState
  /// to a state where all tokens are placed. Returns the penalty.
  ///
  /// If \p DryRun is \c false, directly applies the changes.
  unsigned analyzeSolutionSpace(LineState &InitialState, bool DryRun = false) {
    std::set<LineState> Seen;

    // Increasing count of \c StateNode items we have created. This is used to
    // create a deterministic order independent of the container.
    unsigned Count = 0;
    QueueType Queue;

    // Insert start element into queue.
    StateNode *Node =
        new (Allocator.Allocate()) StateNode(InitialState, false, NULL);
    Queue.push(QueueItem(OrderedPenalty(0, Count), Node));
    ++Count;

    unsigned Penalty = 0;

    // While not empty, take first element and follow edges.
    while (!Queue.empty()) {
      Penalty = Queue.top().first.first;
      StateNode *Node = Queue.top().second;
      if (Node->State.NextToken == NULL) {
        DEBUG(llvm::dbgs() << "\n---\nPenalty for line: " << Penalty << "\n");
        break;
      }
      Queue.pop();

      // Cut off the analysis of certain solutions if the analysis gets too
      // complex. See description of IgnoreStackForComparison.
      if (Count > 10000)
        Node->State.IgnoreStackForComparison = true;

      if (!Seen.insert(Node->State).second)
        // State already examined with lower penalty.
        continue;

      FormatDecision LastFormat = Node->State.NextToken->Decision;
      if (LastFormat == FD_Unformatted || LastFormat == FD_Continue)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/false, &Count, &Queue);
      if (LastFormat == FD_Unformatted || LastFormat == FD_Break)
        addNextStateToQueue(Penalty, Node, /*NewLine=*/true, &Count, &Queue);
    }

    if (Queue.empty()) {
      // We were unable to find a solution, do nothing.
      // FIXME: Add diagnostic?
      DEBUG(llvm::dbgs() << "Could not find a solution.\n");
      return 0;
    }

    // Reconstruct the solution.
    if (!DryRun)
      reconstructPath(InitialState, Queue.top().second);

    DEBUG(llvm::dbgs() << "Total number of analyzed states: " << Count << "\n");
    DEBUG(llvm::dbgs() << "---\n");

    return Penalty;
  }

  void reconstructPath(LineState &State, StateNode *Current) {
    std::deque<StateNode *> Path;
    // We do not need a break before the initial token.
    while (Current->Previous) {
      Path.push_front(Current);
      Current = Current->Previous;
    }
    for (std::deque<StateNode *>::iterator I = Path.begin(), E = Path.end();
         I != E; ++I) {
      unsigned Penalty = 0;
      formatChildren(State, (*I)->NewLine, /*DryRun=*/false, Penalty);
      Penalty += Indenter->addTokenToState(State, (*I)->NewLine, false);

      DEBUG({
        if ((*I)->NewLine) {
          llvm::dbgs() << "Penalty for placing "
                       << (*I)->Previous->State.NextToken->Tok.getName() << ": "
                       << Penalty << "\n";
        }
      });
    }
  }

  /// \brief Add the following state to the analysis queue \c Queue.
  ///
  /// Assume the current state is \p PreviousNode and has been reached with a
  /// penalty of \p Penalty. Insert a line break if \p NewLine is \c true.
  void addNextStateToQueue(unsigned Penalty, StateNode *PreviousNode,
                           bool NewLine, unsigned *Count, QueueType *Queue) {
    if (NewLine && !Indenter->canBreak(PreviousNode->State))
      return;
    if (!NewLine && Indenter->mustBreak(PreviousNode->State))
      return;

    StateNode *Node = new (Allocator.Allocate())
        StateNode(PreviousNode->State, NewLine, PreviousNode);
    if (!formatChildren(Node->State, NewLine, /*DryRun=*/true, Penalty))
      return;

    Penalty += Indenter->addTokenToState(Node->State, NewLine, true);

    Queue->push(QueueItem(OrderedPenalty(Penalty, *Count), Node));
    ++(*Count);
  }

  /// \brief If the \p State's next token is an r_brace closing a nested block,
  /// format the nested block before it.
  ///
  /// Returns \c true if all children could be placed successfully and adapts
  /// \p Penalty as well as \p State. If \p DryRun is false, also directly
  /// creates changes using \c Whitespaces.
  ///
  /// The crucial idea here is that children always get formatted upon
  /// encountering the closing brace right after the nested block. Now, if we
  /// are currently trying to keep the "}" on the same line (i.e. \p NewLine is
  /// \c false), the entire block has to be kept on the same line (which is only
  /// possible if it fits on the line, only contains a single statement, etc.
  ///
  /// If \p NewLine is true, we format the nested block on separate lines, i.e.
  /// break after the "{", format all lines with correct indentation and the put
  /// the closing "}" on yet another new line.
  ///
  /// This enables us to keep the simple structure of the
  /// \c UnwrappedLineFormatter, where we only have two options for each token:
  /// break or don't break.
  bool formatChildren(LineState &State, bool NewLine, bool DryRun,
                      unsigned &Penalty) {
    FormatToken &Previous = *State.NextToken->Previous;
    const FormatToken *LBrace = State.NextToken->getPreviousNonComment();
    if (!LBrace || LBrace->isNot(tok::l_brace) ||
        LBrace->BlockKind != BK_Block || Previous.Children.size() == 0)
      // The previous token does not open a block. Nothing to do. We don't
      // assert so that we can simply call this function for all tokens.
      return true;

    if (NewLine) {
      int AdditionalIndent = State.Stack.back().Indent -
                             Previous.Children[0]->Level * Style.IndentWidth;
      Penalty += format(Previous.Children, DryRun, AdditionalIndent,
                        /*FixBadIndentation=*/true);
      return true;
    }

    // Cannot merge multiple statements into a single line.
    if (Previous.Children.size() > 1)
      return false;

    // We can't put the closing "}" on a line with a trailing comment.
    if (Previous.Children[0]->Last->isTrailingComment())
      return false;

    if (!DryRun) {
      Whitespaces->replaceWhitespace(
          *Previous.Children[0]->First,
          /*Newlines=*/0, /*IndentLevel=*/0, /*Spaces=*/1,
          /*StartOfTokenColumn=*/State.Column, State.Line->InPPDirective);
    }
    Penalty += format(*Previous.Children[0], State.Column + 1, DryRun);

    State.Column += 1 + Previous.Children[0]->Last->TotalLength;
    return true;
  }

  ContinuationIndenter *Indenter;
  WhitespaceManager *Whitespaces;
  FormatStyle Style;
  LineJoiner Joiner;

  llvm::SpecificBumpPtrAllocator<StateNode> Allocator;
};

class FormatTokenLexer {
public:
  FormatTokenLexer(Lexer &Lex, SourceManager &SourceMgr, FormatStyle &Style,
                   encoding::Encoding Encoding)
      : FormatTok(NULL), IsFirstToken(true), GreaterStashed(false), Column(0),
        TrailingWhitespace(0), Lex(Lex), SourceMgr(SourceMgr), Style(Style),
        IdentTable(getFormattingLangOpts()), Encoding(Encoding) {
    Lex.SetKeepWhitespaceMode(true);
  }

  ArrayRef<FormatToken *> lex() {
    assert(Tokens.empty());
    do {
      Tokens.push_back(getNextToken());
      tryMergePreviousTokens();
    } while (Tokens.back()->Tok.isNot(tok::eof));
    return Tokens;
  }

  IdentifierTable &getIdentTable() { return IdentTable; }

private:
  void tryMergePreviousTokens() {
    if (tryMerge_TMacro())
      return;

    if (Style.Language == FormatStyle::LK_JavaScript) {
      static tok::TokenKind JSIdentity[] = { tok::equalequal, tok::equal };
      static tok::TokenKind JSNotIdentity[] = { tok::exclaimequal, tok::equal };
      static tok::TokenKind JSShiftEqual[] = { tok::greater, tok::greater,
                                               tok::greaterequal };
      // FIXME: We probably need to change token type to mimic operator with the
      // correct priority.
      if (tryMergeTokens(JSIdentity))
        return;
      if (tryMergeTokens(JSNotIdentity))
        return;
      if (tryMergeTokens(JSShiftEqual))
        return;
    }
  }

  bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds) {
    if (Tokens.size() < Kinds.size())
      return false;

    SmallVectorImpl<FormatToken *>::const_iterator First =
        Tokens.end() - Kinds.size();
    if (!First[0]->is(Kinds[0]))
      return false;
    unsigned AddLength = 0;
    for (unsigned i = 1; i < Kinds.size(); ++i) {
      if (!First[i]->is(Kinds[i]) || First[i]->WhitespaceRange.getBegin() !=
                                         First[i]->WhitespaceRange.getEnd())
        return false;
      AddLength += First[i]->TokenText.size();
    }
    Tokens.resize(Tokens.size() - Kinds.size() + 1);
    First[0]->TokenText = StringRef(First[0]->TokenText.data(),
                                    First[0]->TokenText.size() + AddLength);
    First[0]->ColumnWidth += AddLength;
    return true;
  }

  bool tryMerge_TMacro() {
    if (Tokens.size() < 4)
      return false;
    FormatToken *Last = Tokens.back();
    if (!Last->is(tok::r_paren))
      return false;

    FormatToken *String = Tokens[Tokens.size() - 2];
    if (!String->is(tok::string_literal) || String->IsMultiline)
      return false;

    if (!Tokens[Tokens.size() - 3]->is(tok::l_paren))
      return false;

    FormatToken *Macro = Tokens[Tokens.size() - 4];
    if (Macro->TokenText != "_T")
      return false;

    const char *Start = Macro->TokenText.data();
    const char *End = Last->TokenText.data() + Last->TokenText.size();
    String->TokenText = StringRef(Start, End - Start);
    String->IsFirst = Macro->IsFirst;
    String->LastNewlineOffset = Macro->LastNewlineOffset;
    String->WhitespaceRange = Macro->WhitespaceRange;
    String->OriginalColumn = Macro->OriginalColumn;
    String->ColumnWidth = encoding::columnWidthWithTabs(
        String->TokenText, String->OriginalColumn, Style.TabWidth, Encoding);

    Tokens.pop_back();
    Tokens.pop_back();
    Tokens.pop_back();
    Tokens.back() = String;
    return true;
  }

  FormatToken *getNextToken() {
    if (GreaterStashed) {
      // Create a synthesized second '>' token.
      // FIXME: Increment Column and set OriginalColumn.
      Token Greater = FormatTok->Tok;
      FormatTok = new (Allocator.Allocate()) FormatToken;
      FormatTok->Tok = Greater;
      SourceLocation GreaterLocation =
          FormatTok->Tok.getLocation().getLocWithOffset(1);
      FormatTok->WhitespaceRange =
          SourceRange(GreaterLocation, GreaterLocation);
      FormatTok->TokenText = ">";
      FormatTok->ColumnWidth = 1;
      GreaterStashed = false;
      return FormatTok;
    }

    FormatTok = new (Allocator.Allocate()) FormatToken;
    readRawToken(*FormatTok);
    SourceLocation WhitespaceStart =
        FormatTok->Tok.getLocation().getLocWithOffset(-TrailingWhitespace);
    FormatTok->IsFirst = IsFirstToken;
    IsFirstToken = false;

    // Consume and record whitespace until we find a significant token.
    unsigned WhitespaceLength = TrailingWhitespace;
    while (FormatTok->Tok.is(tok::unknown)) {
      for (int i = 0, e = FormatTok->TokenText.size(); i != e; ++i) {
        switch (FormatTok->TokenText[i]) {
        case '\n':
          ++FormatTok->NewlinesBefore;
          // FIXME: This is technically incorrect, as it could also
          // be a literal backslash at the end of the line.
          if (i == 0 || (FormatTok->TokenText[i - 1] != '\\' &&
                         (FormatTok->TokenText[i - 1] != '\r' || i == 1 ||
                          FormatTok->TokenText[i - 2] != '\\')))
            FormatTok->HasUnescapedNewline = true;
          FormatTok->LastNewlineOffset = WhitespaceLength + i + 1;
          Column = 0;
          break;
        case '\r':
        case '\f':
        case '\v':
          Column = 0;
          break;
        case ' ':
          ++Column;
          break;
        case '\t':
          Column += Style.TabWidth - Column % Style.TabWidth;
          break;
        case '\\':
          ++Column;
          if (i + 1 == e || (FormatTok->TokenText[i + 1] != '\r' &&
                             FormatTok->TokenText[i + 1] != '\n'))
            FormatTok->Type = TT_ImplicitStringLiteral;
          break;
        default:
          FormatTok->Type = TT_ImplicitStringLiteral;
          ++Column;
          break;
        }
      }

      if (FormatTok->Type == TT_ImplicitStringLiteral)
        break;
      WhitespaceLength += FormatTok->Tok.getLength();

      readRawToken(*FormatTok);
    }

    // In case the token starts with escaped newlines, we want to
    // take them into account as whitespace - this pattern is quite frequent
    // in macro definitions.
    // FIXME: Add a more explicit test.
    while (FormatTok->TokenText.size() > 1 && FormatTok->TokenText[0] == '\\' &&
           FormatTok->TokenText[1] == '\n') {
      // FIXME: ++FormatTok->NewlinesBefore is missing...
      WhitespaceLength += 2;
      Column = 0;
      FormatTok->TokenText = FormatTok->TokenText.substr(2);
    }

    FormatTok->WhitespaceRange = SourceRange(
        WhitespaceStart, WhitespaceStart.getLocWithOffset(WhitespaceLength));

    FormatTok->OriginalColumn = Column;

    TrailingWhitespace = 0;
    if (FormatTok->Tok.is(tok::comment)) {
      // FIXME: Add the trimmed whitespace to Column.
      StringRef UntrimmedText = FormatTok->TokenText;
      FormatTok->TokenText = FormatTok->TokenText.rtrim(" \t\v\f");
      TrailingWhitespace = UntrimmedText.size() - FormatTok->TokenText.size();
    } else if (FormatTok->Tok.is(tok::raw_identifier)) {
      IdentifierInfo &Info = IdentTable.get(FormatTok->TokenText);
      FormatTok->Tok.setIdentifierInfo(&Info);
      FormatTok->Tok.setKind(Info.getTokenID());
    } else if (FormatTok->Tok.is(tok::greatergreater)) {
      FormatTok->Tok.setKind(tok::greater);
      FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
      GreaterStashed = true;
    }

    // Now FormatTok is the next non-whitespace token.

    StringRef Text = FormatTok->TokenText;
    size_t FirstNewlinePos = Text.find('\n');
    if (FirstNewlinePos == StringRef::npos) {
      // FIXME: ColumnWidth actually depends on the start column, we need to
      // take this into account when the token is moved.
      FormatTok->ColumnWidth =
          encoding::columnWidthWithTabs(Text, Column, Style.TabWidth, Encoding);
      Column += FormatTok->ColumnWidth;
    } else {
      FormatTok->IsMultiline = true;
      // FIXME: ColumnWidth actually depends on the start column, we need to
      // take this into account when the token is moved.
      FormatTok->ColumnWidth = encoding::columnWidthWithTabs(
          Text.substr(0, FirstNewlinePos), Column, Style.TabWidth, Encoding);

      // The last line of the token always starts in column 0.
      // Thus, the length can be precomputed even in the presence of tabs.
      FormatTok->LastLineColumnWidth = encoding::columnWidthWithTabs(
          Text.substr(Text.find_last_of('\n') + 1), 0, Style.TabWidth,
          Encoding);
      Column = FormatTok->LastLineColumnWidth;
    }

    return FormatTok;
  }

  FormatToken *FormatTok;
  bool IsFirstToken;
  bool GreaterStashed;
  unsigned Column;
  unsigned TrailingWhitespace;
  Lexer &Lex;
  SourceManager &SourceMgr;
  FormatStyle &Style;
  IdentifierTable IdentTable;
  encoding::Encoding Encoding;
  llvm::SpecificBumpPtrAllocator<FormatToken> Allocator;
  SmallVector<FormatToken *, 16> Tokens;

  void readRawToken(FormatToken &Tok) {
    Lex.LexFromRawLexer(Tok.Tok);
    Tok.TokenText = StringRef(SourceMgr.getCharacterData(Tok.Tok.getLocation()),
                              Tok.Tok.getLength());
    // For formatting, treat unterminated string literals like normal string
    // literals.
    if (Tok.is(tok::unknown)) {
      if (!Tok.TokenText.empty() && Tok.TokenText[0] == '"') {
        Tok.Tok.setKind(tok::string_literal);
        Tok.IsUnterminatedLiteral = true;
      } else if (Style.Language == FormatStyle::LK_JavaScript &&
                 Tok.TokenText == "''") {
        Tok.Tok.setKind(tok::char_constant);
      }
    }
  }
};

static StringRef getLanguageName(FormatStyle::LanguageKind Language) {
  switch (Language) {
  case FormatStyle::LK_Cpp:
    return "C++";
  case FormatStyle::LK_JavaScript:
    return "JavaScript";
  case FormatStyle::LK_Proto:
    return "Proto";
  default:
    return "Unknown";
  }
}

class Formatter : public UnwrappedLineConsumer {
public:
  Formatter(const FormatStyle &Style, Lexer &Lex, SourceManager &SourceMgr,
            const std::vector<CharSourceRange> &Ranges)
      : Style(Style), Lex(Lex), SourceMgr(SourceMgr),
        Whitespaces(SourceMgr, Style, inputUsesCRLF(Lex.getBuffer())),
        Ranges(Ranges.begin(), Ranges.end()), UnwrappedLines(1),
        Encoding(encoding::detectEncoding(Lex.getBuffer())) {
    DEBUG(llvm::dbgs() << "File encoding: "
                       << (Encoding == encoding::Encoding_UTF8 ? "UTF8"
                                                               : "unknown")
                       << "\n");
    DEBUG(llvm::dbgs() << "Language: " << getLanguageName(Style.Language)
                       << "\n");
  }

  tooling::Replacements format() {
    tooling::Replacements Result;
    FormatTokenLexer Tokens(Lex, SourceMgr, Style, Encoding);

    UnwrappedLineParser Parser(Style, Tokens.lex(), *this);
    bool StructuralError = Parser.parse();
    assert(UnwrappedLines.rbegin()->empty());
    for (unsigned Run = 0, RunE = UnwrappedLines.size(); Run + 1 != RunE;
         ++Run) {
      DEBUG(llvm::dbgs() << "Run " << Run << "...\n");
      SmallVector<AnnotatedLine *, 16> AnnotatedLines;
      for (unsigned i = 0, e = UnwrappedLines[Run].size(); i != e; ++i) {
        AnnotatedLines.push_back(new AnnotatedLine(UnwrappedLines[Run][i]));
      }
      tooling::Replacements RunResult =
          format(AnnotatedLines, StructuralError, Tokens);
      DEBUG({
        llvm::dbgs() << "Replacements for run " << Run << ":\n";
        for (tooling::Replacements::iterator I = RunResult.begin(),
                                             E = RunResult.end();
             I != E; ++I) {
          llvm::dbgs() << I->toString() << "\n";
        }
      });
      for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
        delete AnnotatedLines[i];
      }
      Result.insert(RunResult.begin(), RunResult.end());
      Whitespaces.reset();
    }
    return Result;
  }

  tooling::Replacements format(SmallVectorImpl<AnnotatedLine *> &AnnotatedLines,
                               bool StructuralError, FormatTokenLexer &Tokens) {
    TokenAnnotator Annotator(Style, Tokens.getIdentTable().get("in"));
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      Annotator.annotate(*AnnotatedLines[i]);
    }
    deriveLocalStyle(AnnotatedLines);
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      Annotator.calculateFormattingInformation(*AnnotatedLines[i]);
    }
    computeAffectedLines(AnnotatedLines.begin(), AnnotatedLines.end());

    Annotator.setCommentLineLevels(AnnotatedLines);
    ContinuationIndenter Indenter(Style, SourceMgr, Whitespaces, Encoding,
                                  BinPackInconclusiveFunctions);
    UnwrappedLineFormatter Formatter(&Indenter, &Whitespaces, Style);
    Formatter.format(AnnotatedLines, /*DryRun=*/false);
    return Whitespaces.generateReplacements();
  }

private:
  // Determines which lines are affected by the SourceRanges given as input.
  // Returns \c true if at least one line between I and E or one of their
  // children is affected.
  bool computeAffectedLines(SmallVectorImpl<AnnotatedLine *>::iterator I,
                            SmallVectorImpl<AnnotatedLine *>::iterator E) {
    bool SomeLineAffected = false;
    const AnnotatedLine *PreviousLine = NULL;
    while (I != E) {
      AnnotatedLine *Line = *I;
      Line->LeadingEmptyLinesAffected = affectsLeadingEmptyLines(*Line->First);

      // If a line is part of a preprocessor directive, it needs to be formatted
      // if any token within the directive is affected.
      if (Line->InPPDirective) {
        FormatToken *Last = Line->Last;
        SmallVectorImpl<AnnotatedLine *>::iterator PPEnd = I + 1;
        while (PPEnd != E && !(*PPEnd)->First->HasUnescapedNewline) {
          Last = (*PPEnd)->Last;
          ++PPEnd;
        }

        if (affectsTokenRange(*Line->First, *Last,
                              /*IncludeLeadingNewlines=*/false)) {
          SomeLineAffected = true;
          markAllAsAffected(I, PPEnd);
        }
        I = PPEnd;
        continue;
      }

      if (nonPPLineAffected(Line, PreviousLine))
        SomeLineAffected = true;

      PreviousLine = Line;
      ++I;
    }
    return SomeLineAffected;
  }

  // Determines whether 'Line' is affected by the SourceRanges given as input.
  // Returns \c true if line or one if its children is affected.
  bool nonPPLineAffected(AnnotatedLine *Line,
                         const AnnotatedLine *PreviousLine) {
    bool SomeLineAffected = false;
    Line->ChildrenAffected =
        computeAffectedLines(Line->Children.begin(), Line->Children.end());
    if (Line->ChildrenAffected)
      SomeLineAffected = true;

    // Stores whether one of the line's tokens is directly affected.
    bool SomeTokenAffected = false;
    // Stores whether we need to look at the leading newlines of the next token
    // in order to determine whether it was affected.
    bool IncludeLeadingNewlines = false;

    // Stores whether the first child line of any of this line's tokens is
    // affected.
    bool SomeFirstChildAffected = false;

    for (FormatToken *Tok = Line->First; Tok; Tok = Tok->Next) {
      // Determine whether 'Tok' was affected.
      if (affectsTokenRange(*Tok, *Tok, IncludeLeadingNewlines))
        SomeTokenAffected = true;

      // Determine whether the first child of 'Tok' was affected.
      if (!Tok->Children.empty() && Tok->Children.front()->Affected)
        SomeFirstChildAffected = true;

      IncludeLeadingNewlines = Tok->Children.empty();
    }

    // Was this line moved, i.e. has it previously been on the same line as an
    // affected line?
    bool LineMoved = PreviousLine && PreviousLine->Affected &&
                     Line->First->NewlinesBefore == 0;

    bool IsContinuedComment = Line->First->is(tok::comment) &&
                              Line->First->Next == NULL &&
                              Line->First->NewlinesBefore < 2 && PreviousLine &&
                              PreviousLine->Affected &&
                              PreviousLine->Last->is(tok::comment);

    if (SomeTokenAffected || SomeFirstChildAffected || LineMoved ||
        IsContinuedComment) {
      Line->Affected = true;
      SomeLineAffected = true;
    }
    return SomeLineAffected;
  }

  // Marks all lines between I and E as well as all their children as affected.
  void markAllAsAffected(SmallVectorImpl<AnnotatedLine *>::iterator I,
                         SmallVectorImpl<AnnotatedLine *>::iterator E) {
    while (I != E) {
      (*I)->Affected = true;
      markAllAsAffected((*I)->Children.begin(), (*I)->Children.end());
      ++I;
    }
  }

  // Returns true if the range from 'First' to 'Last' intersects with one of the
  // input ranges.
  bool affectsTokenRange(const FormatToken &First, const FormatToken &Last,
                         bool IncludeLeadingNewlines) {
    SourceLocation Start = First.WhitespaceRange.getBegin();
    if (!IncludeLeadingNewlines)
      Start = Start.getLocWithOffset(First.LastNewlineOffset);
    SourceLocation End = Last.getStartOfNonWhitespace();
    if (Last.TokenText.size() > 0)
      End = End.getLocWithOffset(Last.TokenText.size() - 1);
    CharSourceRange Range = CharSourceRange::getCharRange(Start, End);
    return affectsCharSourceRange(Range);
  }

  // Returns true if one of the input ranges intersect the leading empty lines
  // before 'Tok'.
  bool affectsLeadingEmptyLines(const FormatToken &Tok) {
    CharSourceRange EmptyLineRange = CharSourceRange::getCharRange(
        Tok.WhitespaceRange.getBegin(),
        Tok.WhitespaceRange.getBegin().getLocWithOffset(Tok.LastNewlineOffset));
    return affectsCharSourceRange(EmptyLineRange);
  }

  // Returns true if 'Range' intersects with one of the input ranges.
  bool affectsCharSourceRange(const CharSourceRange &Range) {
    for (SmallVectorImpl<CharSourceRange>::const_iterator I = Ranges.begin(),
                                                          E = Ranges.end();
         I != E; ++I) {
      if (!SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), I->getBegin()) &&
          !SourceMgr.isBeforeInTranslationUnit(I->getEnd(), Range.getBegin()))
        return true;
    }
    return false;
  }

  static bool inputUsesCRLF(StringRef Text) {
    return Text.count('\r') * 2 > Text.count('\n');
  }

  void
  deriveLocalStyle(const SmallVectorImpl<AnnotatedLine *> &AnnotatedLines) {
    unsigned CountBoundToVariable = 0;
    unsigned CountBoundToType = 0;
    bool HasCpp03IncompatibleFormat = false;
    bool HasBinPackedFunction = false;
    bool HasOnePerLineFunction = false;
    for (unsigned i = 0, e = AnnotatedLines.size(); i != e; ++i) {
      if (!AnnotatedLines[i]->First->Next)
        continue;
      FormatToken *Tok = AnnotatedLines[i]->First->Next;
      while (Tok->Next) {
        if (Tok->Type == TT_PointerOrReference) {
          bool SpacesBefore =
              Tok->WhitespaceRange.getBegin() != Tok->WhitespaceRange.getEnd();
          bool SpacesAfter = Tok->Next->WhitespaceRange.getBegin() !=
                             Tok->Next->WhitespaceRange.getEnd();
          if (SpacesBefore && !SpacesAfter)
            ++CountBoundToVariable;
          else if (!SpacesBefore && SpacesAfter)
            ++CountBoundToType;
        }

        if (Tok->WhitespaceRange.getBegin() == Tok->WhitespaceRange.getEnd()) {
          if (Tok->is(tok::coloncolon) &&
              Tok->Previous->Type == TT_TemplateOpener)
            HasCpp03IncompatibleFormat = true;
          if (Tok->Type == TT_TemplateCloser &&
              Tok->Previous->Type == TT_TemplateCloser)
            HasCpp03IncompatibleFormat = true;
        }

        if (Tok->PackingKind == PPK_BinPacked)
          HasBinPackedFunction = true;
        if (Tok->PackingKind == PPK_OnePerLine)
          HasOnePerLineFunction = true;

        Tok = Tok->Next;
      }
    }
    if (Style.DerivePointerBinding) {
      if (CountBoundToType > CountBoundToVariable)
        Style.PointerBindsToType = true;
      else if (CountBoundToType < CountBoundToVariable)
        Style.PointerBindsToType = false;
    }
    if (Style.Standard == FormatStyle::LS_Auto) {
      Style.Standard = HasCpp03IncompatibleFormat ? FormatStyle::LS_Cpp11
                                                  : FormatStyle::LS_Cpp03;
    }
    BinPackInconclusiveFunctions =
        HasBinPackedFunction || !HasOnePerLineFunction;
  }

  virtual void consumeUnwrappedLine(const UnwrappedLine &TheLine) {
    assert(!UnwrappedLines.empty());
    UnwrappedLines.back().push_back(TheLine);
  }

  virtual void finishRun() {
    UnwrappedLines.push_back(SmallVector<UnwrappedLine, 16>());
  }

  FormatStyle Style;
  Lexer &Lex;
  SourceManager &SourceMgr;
  WhitespaceManager Whitespaces;
  SmallVector<CharSourceRange, 8> Ranges;
  SmallVector<SmallVector<UnwrappedLine, 16>, 2> UnwrappedLines;

  encoding::Encoding Encoding;
  bool BinPackInconclusiveFunctions;
};

} // end anonymous namespace

tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex,
                               SourceManager &SourceMgr,
                               std::vector<CharSourceRange> Ranges) {
  Formatter formatter(Style, Lex, SourceMgr, Ranges);
  return formatter.format();
}

tooling::Replacements reformat(const FormatStyle &Style, StringRef Code,
                               std::vector<tooling::Range> Ranges,
                               StringRef FileName) {
  FileManager Files((FileSystemOptions()));
  DiagnosticsEngine Diagnostics(
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
      new DiagnosticOptions);
  SourceManager SourceMgr(Diagnostics, Files);
  llvm::MemoryBuffer *Buf = llvm::MemoryBuffer::getMemBuffer(Code, FileName);
  const clang::FileEntry *Entry =
      Files.getVirtualFile(FileName, Buf->getBufferSize(), 0);
  SourceMgr.overrideFileContents(Entry, Buf);
  FileID ID =
      SourceMgr.createFileID(Entry, SourceLocation(), clang::SrcMgr::C_User);
  Lexer Lex(ID, SourceMgr.getBuffer(ID), SourceMgr,
            getFormattingLangOpts(Style.Standard));
  SourceLocation StartOfFile = SourceMgr.getLocForStartOfFile(ID);
  std::vector<CharSourceRange> CharRanges;
  for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
    SourceLocation Start = StartOfFile.getLocWithOffset(Ranges[i].getOffset());
    SourceLocation End = Start.getLocWithOffset(Ranges[i].getLength());
    CharRanges.push_back(CharSourceRange::getCharRange(Start, End));
  }
  return reformat(Style, Lex, SourceMgr, CharRanges);
}

LangOptions getFormattingLangOpts(FormatStyle::LanguageStandard Standard) {
  LangOptions LangOpts;
  LangOpts.CPlusPlus = 1;
  LangOpts.CPlusPlus11 = Standard == FormatStyle::LS_Cpp03 ? 0 : 1;
  LangOpts.LineComment = 1;
  LangOpts.Bool = 1;
  LangOpts.ObjC1 = 1;
  LangOpts.ObjC2 = 1;
  return LangOpts;
}

const char *StyleOptionHelpDescription =
    "Coding style, currently supports:\n"
    "  LLVM, Google, Chromium, Mozilla, WebKit.\n"
    "Use -style=file to load style configuration from\n"
    ".clang-format file located in one of the parent\n"
    "directories of the source file (or current\n"
    "directory for stdin).\n"
    "Use -style=\"{key: value, ...}\" to set specific\n"
    "parameters, e.g.:\n"
    "  -style=\"{BasedOnStyle: llvm, IndentWidth: 8}\"";

static FormatStyle::LanguageKind getLanguageByFileName(StringRef FileName) {
  if (FileName.endswith_lower(".js")) {
    return FormatStyle::LK_JavaScript;
  } else if (FileName.endswith_lower(".proto") ||
             FileName.endswith_lower(".protodevel")) {
    return FormatStyle::LK_Proto;
  }
  return FormatStyle::LK_Cpp;
}

FormatStyle getStyle(StringRef StyleName, StringRef FileName,
                     StringRef FallbackStyle) {
  FormatStyle Style = getLLVMStyle();
  Style.Language = getLanguageByFileName(FileName);
  if (!getPredefinedStyle(FallbackStyle, Style.Language, &Style)) {
    llvm::errs() << "Invalid fallback style \"" << FallbackStyle
                 << "\" using LLVM style\n";
    return Style;
  }

  if (StyleName.startswith("{")) {
    // Parse YAML/JSON style from the command line.
    if (llvm::error_code ec = parseConfiguration(StyleName, &Style)) {
      llvm::errs() << "Error parsing -style: " << ec.message() << ", using "
                   << FallbackStyle << " style\n";
    }
    return Style;
  }

  if (!StyleName.equals_lower("file")) {
    if (!getPredefinedStyle(StyleName, Style.Language, &Style))
      llvm::errs() << "Invalid value for -style, using " << FallbackStyle
                   << " style\n";
    return Style;
  }

  // Look for .clang-format/_clang-format file in the file's parent directories.
  SmallString<128> UnsuitableConfigFiles;
  SmallString<128> Path(FileName);
  llvm::sys::fs::make_absolute(Path);
  for (StringRef Directory = Path; !Directory.empty();
       Directory = llvm::sys::path::parent_path(Directory)) {
    if (!llvm::sys::fs::is_directory(Directory))
      continue;
    SmallString<128> ConfigFile(Directory);

    llvm::sys::path::append(ConfigFile, ".clang-format");
    DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
    bool IsFile = false;
    // Ignore errors from is_regular_file: we only need to know if we can read
    // the file or not.
    llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);

    if (!IsFile) {
      // Try _clang-format too, since dotfiles are not commonly used on Windows.
      ConfigFile = Directory;
      llvm::sys::path::append(ConfigFile, "_clang-format");
      DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
      llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
    }

    if (IsFile) {
      OwningPtr<llvm::MemoryBuffer> Text;
      if (llvm::error_code ec =
              llvm::MemoryBuffer::getFile(ConfigFile.c_str(), Text)) {
        llvm::errs() << ec.message() << "\n";
        break;
      }
      if (llvm::error_code ec = parseConfiguration(Text->getBuffer(), &Style)) {
        if (ec == llvm::errc::not_supported) {
          if (!UnsuitableConfigFiles.empty())
            UnsuitableConfigFiles.append(", ");
          UnsuitableConfigFiles.append(ConfigFile);
          continue;
        }
        llvm::errs() << "Error reading " << ConfigFile << ": " << ec.message()
                     << "\n";
        break;
      }
      DEBUG(llvm::dbgs() << "Using configuration file " << ConfigFile << "\n");
      return Style;
    }
  }
  llvm::errs() << "Can't find usable .clang-format, using " << FallbackStyle
               << " style\n";
  if (!UnsuitableConfigFiles.empty()) {
    llvm::errs() << "Configuration file(s) do(es) not support "
                 << getLanguageName(Style.Language) << ": "
                 << UnsuitableConfigFiles << "\n";
  }
  return Style;
}

} // namespace format
} // namespace clang
@


