[PATCH] D61015: [LibTooling] Change Transformer's TextGenerator to a partial function.

Ilya Biryukov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 30 03:28:25 PDT 2019


ilya-biryukov added inline comments.


================
Comment at: clang/include/clang/Tooling/Refactoring/Transformer.h:47
 
-using TextGenerator =
-    std::function<std::string(const ast_matchers::MatchFinder::MatchResult &)>;
+// \c TextGenerator may fail, because it processes dynamically-bound match
+// results.  For example, a typo in the name of a bound node or a mismatch in
----------------
NIT: maybe shorten a bit, still capturing the essence? Something like the following should be enough:

```
Note that \p TextGenerator is allowed to fail, e.g. when trying to access a matched node that was not bound.
Allowing this to fail simplifies error handling for interactive tools like clang-query.
```


================
Comment at: clang/include/clang/Tooling/Refactoring/Transformer.h:58
 
-/// Wraps a string as a TextGenerator.
+/// Wraps a string as a (trivially successful) TextGenerator.
 inline TextGenerator text(std::string M) {
----------------
Maybe drop `trivially successful`? Does not seem to be super-important.


================
Comment at: clang/include/clang/Tooling/Refactoring/Transformer.h:238
+  /// occurs in constructing a single \c AtomicChange then the change is still
+  /// passed to \c Consumer, but it's error will be set.  Note that clients are
+  /// responsible for handling the case that independent \c AtomicChanges
----------------
s/it's/its


================
Comment at: clang/lib/Tooling/Refactoring/Transformer.cpp:164
       return SmallVector<Transformation, 0>();
-    T.Replacement = Edit.Replacement(Result);
+    auto ReplacementOrErr = Edit.Replacement(Result);
+    if (auto Err = ReplacementOrErr.takeError())
----------------
Maybe follow a typical pattern for handling errors here (to avoid  `OrErr` suffixes and an extra `Err` variable)? I.e.
```
auto Replacement = Edit.Replacement(Result);
if (!Replacement)
  return Replacement.takeError();
T.Replacement = std::move(*Replacement);
```



================
Comment at: clang/lib/Tooling/Refactoring/Transformer.cpp:205
   if (auto Err = TransformationsOrErr.takeError()) {
-    llvm::errs() << "Transformation failed: " << llvm::toString(std::move(Err))
-                 << "\n";
+    AC.setError(llvm::toString(std::move(Err)));
+    Consumer(AC);
----------------
This looks super-complicated.
Having `Error` in `AtomicChange` seems like a bad idea in the first place, why would we choose to use it here?

The following alternatives would encourage clients to handle errors properly:
1. accept an `Expected<AtomicChange>` in our callback,
2. provide a separate callback to consume errors.

WDYT about picking one of those two?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D61015/new/

https://reviews.llvm.org/D61015





More information about the cfe-commits mailing list