Author: krasimir Date: Mon Jan 15 04:06:16 2018 New Revision: 322479 URL: http://llvm.org/viewvc/llvm-project?rev=322479&view=rev Log: [clang-format] Adds a FormatStyleSet
Summary: This patch adds a FormatStyleSet for storing per-language FormatStyles for the purposes of formatting code blocks inside the main code. Reviewers: bkramer Reviewed By: bkramer Subscribers: klimek, djasper, bkramer, cfe-commits Differential Revision: https://reviews.llvm.org/D41487 Modified: cfe/trunk/include/clang/Format/Format.h cfe/trunk/lib/Format/Format.cpp Modified: cfe/trunk/include/clang/Format/Format.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Format/Format.h?rev=322479&r1=322478&r2=322479&view=diff ============================================================================== --- cfe/trunk/include/clang/Format/Format.h (original) +++ cfe/trunk/include/clang/Format/Format.h Mon Jan 15 04:06:16 2018 @@ -1685,6 +1685,43 @@ struct FormatStyle { Standard == R.Standard && TabWidth == R.TabWidth && UseTab == R.UseTab; } + + llvm::Optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const; + + // Stores per-language styles. A FormatStyle instance inside has an empty + // StyleSet. A FormatStyle instance returned by the Get method has its + // StyleSet set to a copy of the originating StyleSet, effectively keeping the + // internal representation of that StyleSet alive. + // + // The memory management and ownership reminds of a birds nest: chicks + // leaving the nest take photos of the nest with them. + struct FormatStyleSet { + typedef std::map<FormatStyle::LanguageKind, FormatStyle> MapType; + + llvm::Optional<FormatStyle> Get(FormatStyle::LanguageKind Language) const; + + // Adds \p Style to this FormatStyleSet. Style must not have an associated + // FormatStyleSet. + // Style.Language should be different than LK_None. If this FormatStyleSet + // already contains an entry for Style.Language, that gets replaced with the + // passed Style. + void Add(FormatStyle Style); + + // Clears this FormatStyleSet. + void Clear(); + + private: + std::shared_ptr<MapType> Styles; + }; + + static FormatStyleSet BuildStyleSetFromConfiguration( + const FormatStyle &MainStyle, + const std::vector<FormatStyle> &ConfigurationStyles); + +private: + FormatStyleSet StyleSet; + + friend std::error_code parseConfiguration(StringRef Text, FormatStyle *Style); }; /// \brief Returns a format style complying with the LLVM coding standards: @@ -1730,6 +1767,8 @@ bool getPredefinedStyle(StringRef Name, /// Style->Language is used to get the base style, if the ``BasedOnStyle`` /// option is present. /// +/// The FormatStyleSet of Style is reset. +/// /// When ``BasedOnStyle`` is not present, options not present in the YAML /// document, are retained in \p Style. std::error_code parseConfiguration(StringRef Text, FormatStyle *Style); Modified: cfe/trunk/lib/Format/Format.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/Format.cpp?rev=322479&r1=322478&r2=322479&view=diff ============================================================================== --- cfe/trunk/lib/Format/Format.cpp (original) +++ cfe/trunk/lib/Format/Format.cpp Mon Jan 15 04:06:16 2018 @@ -859,7 +859,7 @@ std::error_code parseConfiguration(Strin assert(Language != FormatStyle::LK_None); if (Text.trim().empty()) return make_error_code(ParseError::Error); - + Style->StyleSet.Clear(); std::vector<FormatStyle> Styles; llvm::yaml::Input Input(Text); // DocumentListTraits<vector<FormatStyle>> uses the context to get default @@ -888,15 +888,23 @@ std::error_code parseConfiguration(Strin // 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. + FormatStyle::FormatStyleSet StyleSet; + bool LanguageFound = false; 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); - } + 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)); } - return make_error_code(ParseError::Unsuitable); + *Style = *StyleSet.Get(Language); + return make_error_code(ParseError::Success); } std::string configurationAsText(const FormatStyle &Style) { @@ -910,6 +918,38 @@ std::string configurationAsText(const Fo return Stream.str(); } +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); +} + namespace { class JavaScriptRequoter : public TokenAnalyzer { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits