<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Hi all,</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">This is a follow-up to my initial refactoring proposal <span style="color: #957e35" class="">[</span>1<span style="color: #957e35" class="">]</span>, in which I mentioned that I will send out a separate RFC that deals with the initiation of refactoring actions. This email outlines the proposed design ("action and rules") and describes how actions can control their own initiation. If you are interested in looking at code, I have a code sample <span style="color: #957e35" class="">[</span>2<span style="color: #957e35" class="">]</span> that takes Xcode's "Add missing switch cases" refactoring action, implements it in the new engine, and extends it to provide a global source transformation (add missing cases to all enums that operate on a particular switch) that is accessible via clang-refactor. The sample is not 100% complete, but it's pretty much almost there.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 19px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">## </span>Actions and Rules</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">A refactoring action is a class that defines a list of related refactoring rules (operations). These rules get grouped under a common umbrella - a single clang-refactor subcommand. An individual rule specifies how a function that performs a source transformation (i.e. refactoring) should run and when the call to that function can be initiated. Here's an outline of an action and a rule in code:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">class TransformCode: public RefactoringAction { // A refactoring action</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> RefactoringActionRules createActionRules() const override {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> return {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> refactoring_action_rules::apply(transformCode, ...) // A refactoring action rule</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> };</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> }</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> static RefactoringResult transformCode(...) { ... }</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">}</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Why are the rules grouped in actions? I'll try to answer this with an example. Let's consider the action that adds missing cases to a switch. In Xcode 9, you can add missing case statements to one switch at a time. However, it could be useful to have an operation that works on all switches that operate on a particular enum, as one could automatically update them after adding a new enum constant. This is when the distinction between rules and actions becomes useful, as it gives you the ability to create a single action that adds missing cases to a switch using two <span style="color: #957e35" class="">__</span><b class="">very</b><span style="color: #957e35" class="">__</span> different rules - the first rule describes a local operation that's initiated when you select a single switch, while the other describes a global operation that works with different TUs and is initiated once you pass in the name of the enum to clang-refactor (it's also possible to have a similar rule that can be initiated when the user selects the enum declaration in the editor).</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Each individual refactoring action maps to one subcommand in the clang-refactor tool. Clang-refactor will determine which rule should be invoked based on the command line arguments that are passed to it after the subcommand. These arguments are automatically processed by the tool, and the refactoring actions should never interact with any command line arguments directly. Individual rules that include a source selection requirement can be connected to IDEs by binding them to the editor command objects, e.g.:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""><span style="font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(149, 126, 53);" class="">`</span>auto Rule = MyEditorCommand.bind(apply(performRefactoring, requiredSelection(...)));<span style="font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(149, 126, 53);" class="">`</span><span style="font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(0, 0, 0);" class="">.</span></div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 14px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">### </span>Rules</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">What exactly is a refactoring action rule? Simply put, a rule is a function and a list of requirements that map to the corresponding arguments for that function. Here's a rule with a single <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredOption</span><span style="color: #957e35" class="">`</span> requirement that will print "Sample rule: abc" when a "-string-text=abc" argument is passed to clang-refactor:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">apply([](std::string string) { llvm::outs() << "Sample rule: " << string << "\n"; },</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> requiredOption(RefactoringOption<std::string>("string-text")));</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Different combinations of requirements can create very different operations, like local operations that work with the raw token stream, or global operations that work with many parsed TUs. Each requirement produces a value that's passed to the rule's function. The following requirements will be supported by the refactoring engine:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredSelection</span><span style="color: #957e35" class="">`</span>. Rules with this requirement can be initiated using source selection only (clang-refactor will support selection). This requirement and the type that's passed to the rule's function is described in the next section.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredOption</span><span style="color: #957e35" class="">`</span>. Rules with this requirement can be initiated only when the specified option is given to clang-refactor (editors can support these rules if they provide the required options). This requirement can be constructed using a previously created <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">RefactoringOption<Type></span><span style="color: #957e35" class="">`</span> value. A <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">Type</span><span style="color: #957e35" class="">`</span> value is passed to the rule's function, unless the option is mapped (more on that later).</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredIndexerCapabilites<...></span><span style="color: #957e35" class="">`</span>. Rules with this requirement can be initiated only when a particular client (clangd/libclang/clang-refactor) supports the set of specified indexer capabilities. An indexer object is passed to the rule's function. The indexer object has a type that's determined by the specified capabilities, and provides an API that exposes only these capabilities. This design guarantees that a refactoring action can <span style="color: #957e35" class="">__</span><b class="">never</b><span style="color: #957e35" class="">__</span> produce an indexer operation that's not supported by a client that initiated the action.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">option</span><span style="color: #957e35" class="">`</span>. Similar to <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredOption</span><span style="color: #957e35" class="">`</span>. However, a rule that includes an <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">option</span><span style="color: #957e35" class="">`</span> requirement can be initiated even when that option is not specified. An <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">Optional<Type></span><span style="color: #957e35" class="">`</span> value is passed to the rule's function.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">join</span><span style="color: #957e35" class="">`</span>. Can be used to group multiple <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">option</span><span style="color: #957e35" class="">`</span>s into a tuple for convenience. An appropriate tuple value is passed to the rule's function. It might make sense to join other requirements in the future.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredContinuation</span><span style="color: #957e35" class="">`</span>. Doesn't affect initiation. Refactoring continuations have to be specified in the rule because the indexer API in the new engine will work with tagged continuations that provide a name for a particular continuation function and act as alternative "entry points" to the action. This convention will ensure that continuations that have serializable state can be invoked in a separate process. This in turn will enable the creation of a refactoring tool that can distribute work across processes and machines (on a per-TU/file basis) without any changes to the code of a particular refactoring action.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Some requirements can contain user-specified functions that might change their behaviour. They can also modify the type of value that's passed to the rule's function. The <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredOption</span><span style="color: #957e35" class="">`</span> and <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">option</span><span style="color: #957e35" class="">`</span> requirements support the <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">map</span><span style="color: #957e35" class="">`</span> operation, which transforms the option's value to a value of a different type. One could use <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">map</span><span style="color: #957e35" class="">`</span> to convert options to action-specific types. The snippet below shows how <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">map</span><span style="color: #957e35" class="">`</span> can be used to ensure that a string USR represents a valid enum declaration in the project (the validation and error handling is performed automatically by the engine):</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">requiredOption(RefactoringOption<std::string>("enum-usr")),</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> .map([] (std::string USR) { return indexer::symbolForUSR<EnumDecl>(USR); })</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 14px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">### </span>Selection Requirements</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">The <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">requiredSelection</span><span style="color: #957e35" class="">`</span> requirement is quite different to the other ones. It's actually just a function that accepts a valid selection constraint and returns a value of any type that's passed to the rule's function or a diagnostic that ensures that the rule won't be initiated. For example, this requirement will pass <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">MySelection</span><span style="color: #957e35" class="">`</span> value to the rule's function when the rule is initiated successfully:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">struct MySelection {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> CallExpr &CE;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> DeclContext *EnclosingContext;</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">};</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">...</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">auto SelectionRule = requiredSelection([] (const ASTRefactoringOperation &Op,</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> selection::Code<CallExpr> Selection) -> DiagOr<MySelection> {</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> CallExpr &Call = Selection.get();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> if (!Call.getNumArgs())</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> return Op.Diag(diag::err_refactoring_missing_arguments);</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class=""> return MySelection { Call, Selection.getEnclosingContext() };</div><div style="margin: 0px; font-stretch: normal; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135); background-color: rgb(255, 255, 255);" class="">});</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">```</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">If the user selects <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">function()</span><span style="color: #957e35" class="">`</span> in the editor, it won't list this particular refactoring action as available. However, if the user selects <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">function(1)</span><span style="color: #957e35" class="">`</span>, then the rule will be initiated and the refactoring action will be performed successfully. The clang-refactor tool will report the <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">err_refactoring_missing_arguments</span><span style="color: #957e35" class="">`</span> diagnostic when the user gives it a source range that corresponds to the selection of <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">function()</span><span style="color: #957e35" class="">`</span>.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">A selection constraint is a special type that can be interpreted by the engine. The valid selection constraints are listed below:</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> The <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">selection::Code<></span><span style="color: #957e35" class="">`</span> constraint is satisfied only when some portion of code that is contained in one declaration is selected.</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> The <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">selection::Code<Expr></span><span style="color: #957e35" class="">`</span> constraint is satisfied only when one expression/statement of a given type is selected.</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> The <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">selection::ASTDecl<Decl></span><span style="color: #957e35" class="">`</span> constraint is satisfied only when a single declaration of a given type is selected.</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">-</span> The <span style="color: #957e35" class="">`</span><span style="font-stretch: normal; font-size: 12px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);" class="">selection::RawSelectionRange</span><span style="color: #957e35" class="">`</span> constraint is always satisfied (provided there's a selection range!). It allows actions with custom selection rules.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">What "selection" actually means depends on the particular type of the constraint. In general, selection is the prerogative of the refactoring engine (and not of the action), and it will try to optimize the selection rules for the best possible user experience. These choices will be documented appropriately.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 19px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">## </span>Conclusion</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">I believe the proposed design satisfies the goals that I've defined in my initial email. I've tested this design using code that implements all the actions that are supported by Xcode 9 and an additional refactoring action that’s currently implemented in a separate tool (clang-reorder-fields). I was quite satisfied with the results and have decided to settle on this particular design.</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">I'm looking forward to any feedback that you might have,</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Cheers,</div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; background-color: rgb(255, 255, 255);" class="">Alex</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(19, 55, 255); background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">[</span><span style="color: #000000" class="">1</span><span style="color: #957e35" class="">]:</span><span style="color: #000000" class=""> </span><a href="http://lists.llvm.org/pipermail/cfe-dev/2017-June/054286.html" class="">http://lists.llvm.org/pipermail/cfe-dev/2017-June/054286.html</a></div><div style="margin: 0px; font-stretch: normal; font-size: 13px; line-height: normal; font-family: 'Helvetica Neue'; color: rgb(19, 55, 255); background-color: rgb(255, 255, 255);" class=""><span style="color: #957e35" class="">[</span><span style="color: #000000" class="">2</span><span style="color: #957e35" class="">]:</span><span style="color: #000000" class=""> </span><a href="https://gist.github.com/hyp/6e3abc6464eca7fb570674041b1df1ed" class="">https://gist.github.com/hyp/6e3abc6464eca7fb570674041b1df1ed</a></div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255); min-height: 14px;" class=""><br class=""></div></body></html>