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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits