fodinabor created this revision. fodinabor added reviewers: bkramer, djasper, klimek. Herald added subscribers: llvm-commits, cfe-commits, hiraditya. Herald added projects: clang, LLVM. fodinabor requested review of this revision.
Currently newer clang-format options cannot be included in .clang-format files, if not all users can be forced to use an updated version. This patch tries to solve this by adding an option to clang-format, enabling to ignore unknown (newer) options. As this is my first LLVM patch, I'm expecting to get some things wrong and are happy to receive any feedback! E.g.: I haven't found how to update the clang-format help page yet. Is it auto generated? Also if you have any suggestions on whom to ask wrt review, please add them. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D86137 Files: clang/include/clang/Format/Format.h clang/lib/Format/Format.cpp clang/tools/clang-format/ClangFormat.cpp llvm/include/llvm/Support/YAMLTraits.h llvm/lib/Support/YAMLTraits.cpp
Index: llvm/lib/Support/YAMLTraits.cpp =================================================================== --- llvm/lib/Support/YAMLTraits.cpp +++ llvm/lib/Support/YAMLTraits.cpp @@ -195,6 +195,8 @@ MapHNode *MN = dyn_cast_or_null<MapHNode>(CurrentNode); if (!MN) return; + if (IgnoreUnkown) + return; for (const auto &NN : MN->Mapping) { if (!is_contained(MN->ValidKeys, NN.first())) { setError(NN.second.get(), Twine("unknown key '") + NN.first() + "'"); @@ -428,6 +430,8 @@ setError(CurrentNode, Message); } +void Input::setIgnoreUnknown(bool Value) { IgnoreUnkown = Value; } + bool Input::canElideEmptySequence() { return false; } @@ -735,6 +739,8 @@ void Output::setError(const Twine &message) { } +void Output::setIgnoreUnknown(bool Value) {} + bool Output::canElideEmptySequence() { // Normally, with an optional key/value where the value is an empty sequence, // the whole key/value can be not written. But, that produces wrong yaml Index: llvm/include/llvm/Support/YAMLTraits.h =================================================================== --- llvm/include/llvm/Support/YAMLTraits.h +++ llvm/include/llvm/Support/YAMLTraits.h @@ -789,6 +789,7 @@ virtual NodeKind getNodeKind() = 0; virtual void setError(const Twine &) = 0; + virtual void setIgnoreUnknown(bool) = 0; template <typename T> void enumCase(T &Val, const char* Str, const T ConstVal) { @@ -1504,6 +1505,8 @@ /// Returns the current node that's being parsed by the YAML Parser. const Node *getCurrentNode() const; + void setIgnoreUnknown(bool) override; + private: SourceMgr SrcMgr; // must be before Strm std::unique_ptr<llvm::yaml::Stream> Strm; @@ -1514,6 +1517,7 @@ std::vector<bool> BitValuesUsed; HNode *CurrentNode = nullptr; bool ScalarMatchFound = false; + bool IgnoreUnkown = false; }; /// @@ -1561,6 +1565,7 @@ void scalarTag(std::string &) override; NodeKind getNodeKind() override; void setError(const Twine &message) override; + void setIgnoreUnknown(bool) override; bool canElideEmptySequence() override; // These are only used by operator<<. They could be private Index: clang/tools/clang-format/ClangFormat.cpp =================================================================== --- clang/tools/clang-format/ClangFormat.cpp +++ clang/tools/clang-format/ClangFormat.cpp @@ -104,6 +104,11 @@ "SortIncludes style flag"), cl::cat(ClangFormatCategory)); +static cl::opt<bool> + IgnoreUnkownOptions("ignore-unknown-options", + cl::desc("If set, unknown format options are ignored."), + cl::init(false), cl::cat(ClangFormatCategory)); + static cl::opt<bool> Verbose("verbose", cl::desc("If set, shows the list of processed files"), cl::cat(ClangFormatCategory)); @@ -378,7 +383,8 @@ } llvm::Expected<FormatStyle> FormatStyle = - getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer()); + getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer(), + nullptr, IgnoreUnkownOptions.getValue()); if (!FormatStyle) { llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n"; return true; Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -1288,7 +1288,8 @@ return true; } -std::error_code parseConfiguration(StringRef Text, FormatStyle *Style) { +std::error_code parseConfiguration(StringRef Text, FormatStyle *Style, + bool IgnoreUnknownOptions) { assert(Style); FormatStyle::LanguageKind Language = Style->Language; assert(Language != FormatStyle::LK_None); @@ -1302,6 +1303,7 @@ // Mapping also uses the context to get the language to find the correct // base style. Input.setContext(Style); + Input.setIgnoreUnknown(IgnoreUnknownOptions); Input >> Styles; if (Input.error()) return Input.error(); @@ -2800,8 +2802,8 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyleName, - StringRef Code, - llvm::vfs::FileSystem *FS) { + StringRef Code, llvm::vfs::FileSystem *FS, + bool IgnoreUnknownOptions) { if (!FS) { FS = llvm::vfs::getRealFileSystem().get(); } @@ -2813,7 +2815,8 @@ if (StyleName.startswith("{")) { // Parse YAML/JSON style from the command line. - if (std::error_code ec = parseConfiguration(StyleName, &Style)) + if (std::error_code ec = + parseConfiguration(StyleName, &Style, IgnoreUnknownOptions)) return make_string_error("Error parsing -style: " + ec.message()); return Style; } @@ -2857,8 +2860,8 @@ FS->getBufferForFile(ConfigFile.str()); if (std::error_code EC = Text.getError()) return make_string_error(EC.message()); - if (std::error_code ec = - parseConfiguration(Text.get()->getBuffer(), &Style)) { + if (std::error_code ec = parseConfiguration( + Text.get()->getBuffer(), &Style, IgnoreUnknownOptions)) { if (ec == ParseError::Unsuitable) { if (!UnsuitableConfigFiles.empty()) UnsuitableConfigFiles.append(", "); Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -2478,7 +2478,8 @@ private: FormatStyleSet StyleSet; - friend std::error_code parseConfiguration(StringRef Text, FormatStyle *Style); + friend std::error_code parseConfiguration(StringRef Text, FormatStyle *Style, + bool IgnoreUnknownOptions); }; /// Returns a format style complying with the LLVM coding standards: @@ -2533,7 +2534,11 @@ /// /// 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); +/// +/// If IgnoreUnknownOptions is true, no errors are emitted if unknown +/// format options are occured. +std::error_code parseConfiguration(StringRef Text, FormatStyle *Style, + bool IgnoreUnknownOptions = false); /// Gets configuration in a YAML string. std::string configurationAsText(const FormatStyle &Style); @@ -2670,6 +2675,8 @@ /// language if the filename isn't sufficient. /// \param[in] FS The underlying file system, in which the file resides. By /// default, the file system is the real file system. +/// \param[in] IgnoreUnknownOptions If true, unknown format options are ignored. +/// If false, errors are emitted on unknown format options. /// /// \returns FormatStyle as specified by ``StyleName``. If ``StyleName`` is /// "file" and no file is found, returns ``FallbackStyle``. If no style could be @@ -2677,7 +2684,8 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, StringRef FallbackStyle, StringRef Code = "", - llvm::vfs::FileSystem *FS = nullptr); + llvm::vfs::FileSystem *FS = nullptr, + bool IgnoreUnknownOptions = false); // Guesses the language from the ``FileName`` and ``Code`` to be formatted. // Defaults to FormatStyle::LK_Cpp.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits