The final step takes buggy source code and fix patterns from the pattern mining step and produces patched versions of the source code. There are typically many fix patterns to choose from (as seen in the dendrogram above). So a challenge we have to address in this step is selecting the correct pattern to fix a particular bug. If the pattern applies in several locations, Getafix must also select the right match. The following examples illustrate our general approach and how we address this challenge in Getafix.
Example 1. Consider the pattern we mined above: h0.h1(); → if (h0 == null) return; h0.h1();
We briefly explain the steps to produce the following patch on previously unseen code.
Getafix creates a patch using the following steps
Find sub-AST matching the before part: mListView.clearListeners();
Instantiate holes h0 and h1
Replace sub-AST with instantiated after part
Note that h0 in the after part is bound because of the inclusion of unmodified context h0.h1();, which helpfully restricts the number of places the pattern applies. Without the unmodified context, the pattern would have been <nothing> → if (h0 == null) return;. This pattern applies in unintended places, such as after mListView.clearListeners(); or even after mListView = null;.
The insertion-only pattern will in fact also appear higher up in the dendrogram, where the pattern with context h0.h1(); is anti-unified with a pattern inserting the return in front of a different statement. The next example illustrates how Getafix deals with patterns that seem to apply in too many places.
Example 2. Consider the following pattern: h0.h1() → h0!=null && h0.h1()
Typically, this patch would get mined from fixes within if conditions or return expressions, so we’d expect it to be applied there as well. But it also matches in other situations, such as the call statement shown in a previous example above: mListView.clearListeners();. Getafix’s ranking strategy tries to estimate the likelihood that a pattern is indeed a fix and that it is the most likely fix for a given context. This strategy allows the system to be less reliant on the validation step later, thus saving time.
The above pattern will compete with other patterns, such as the more specific if (h0.h1()) { ... } → if (h0!=null && h0.h1()) { ... } or the pattern from Example 1, which applies only to call statements rather than expressions. More specific patterns match in fewer places and are thus considered to be more specialized for the situation, so Getafix ranks them higher.The final step takes buggy source code and fix patterns from the pattern mining step and produces patched versions of the source code. There are typically many fix patterns to choose from (as seen in the dendrogram above). So a challenge we have to address in this step is selecting the correct pattern to fix a particular bug. If the pattern applies in several locations, Getafix must also select the right match. The following examples illustrate our general approach and how we address this challenge in Getafix.
Example 1. Consider the pattern we mined above: h0.h1(); → if (h0 == null) return; h0.h1();
We briefly explain the steps to produce the following patch on previously unseen code.
Getafix creates a patch using the following steps
Find sub-AST matching the before part: mListView.clearListeners();
Instantiate holes h0 and h1
Replace sub-AST with instantiated after part
Note that h0 in the after part is bound because of the inclusion of unmodified context h0.h1();, which helpfully restricts the number of places the pattern applies. Without the unmodified context, the pattern would have been <nothing> → if (h0 == null) return;. This pattern applies in unintended places, such as after mListView.clearListeners(); or even after mListView = null;.
The insertion-only pattern will in fact also appear higher up in the dendrogram, where the pattern with context h0.h1(); is anti-unified with a pattern inserting the return in front of a different statement. The next example illustrates how Getafix deals with patterns that seem to apply in too many places.
Example 2. Consider the following pattern: h0.h1() → h0!=null && h0.h1()
Typically, this patch would get mined from fixes within if conditions or return expressions, so we’d expect it to be applied there as well. But it also matches in other situations, such as the call statement shown in a previous example above: mListView.clearListeners();. Getafix’s ranking strategy tries to estimate the likelihood that a pattern is indeed a fix and that it is the most likely fix for a given context. This strategy allows the system to be less reliant on the validation step later, thus saving time.
The above pattern will compete with other patterns, such as the more specific if (h0.h1()) { ... } → if (h0!=null && h0.h1()) { ... } or the pattern from Example 1, which applies only to call statements rather than expressions. More specific patterns match in fewer places and are thus considered to be more specialized for the situation, so Getafix ranks them higher.