The quick fix class
The definition of the quick fix for the hint presented in part 1 is the following:
class IfToStatementModifierFix(
info : CompilationInfo,
condition : Node,
statement : Node,
ifNode : Node,
kind : StatementModifierFix) extends Fix {
def isSafe = true
def isInteractive = false
...
}
As shown in this fragment the class that represents the fix requires a reference to each tree element involved in the problem. In this case the important parts are the complete if statement, the condition and the then statement.
Also a kind argument(specific for this quick fix) is used to determine if a
if
or a unless
statement modifier needs to be created. The definition for StatementModifierFix
, looks like this:
abstract class StatementModifierFix
case class IfStatementModifierFix extends StatementModifierFix
case class UnlessStatementModifierFix extends StatementModifierFix
The quick fix implementation
The
IfToStatementModifierFix
class needs to implement the implement
method in order to do its work, here's the code:
def implement() = {
val doc = info.getDocument.asInstanceOf[BaseDocument]
val conditionRange = AstUtilities.getRange(condition)
val conditionText = getConditionText(doc,conditionRange)
val statementRange = AstUtilities.getRange(statement)
val statementText = doc.getText(statementRange.getStart,statementRange.getLength)
val ifRange = AstUtilities.getRange(ifNode)
val resultingStatement = statementText + getModifierText + conditionText
doc.atomicLock
doc.replace(ifRange.getStart,ifRange.getLength,resultingStatement,null)
doc.atomicUnlock
}
In order to generate the
unless
statement we need to change the operator from !=
to ==
.The
getConditionText
method does this job:
def getConditionText(doc : BaseDocument,range: OffsetRange) = {
val text = doc.getText(range.getStart,range.getLength)
kind match {
case IfStatementModifierFix() => text
case UnlessStatementModifierFix() => text.replace("!=","==")
}
}
The last thing we need to do is to connect the hint with this quick fix. In order to do this we need to modify the
run
method of the IfToStatementModifierHint
class presented in part 1. We need to add a fix for each identified case.The case when a method is used as a condition:
...
case ifStat@IfStatement(methodCall : CallNode,
NewlineNode(thenStat),
null) => {
val range = AstUtilities.getRange(node)
val fixes = new java.util.ArrayList
fixes.add(
new IfToStatementModifierFix(info,methodCall,thenStat,ifStat,IfStatementModifierFix))
val desc =
new Description(this,
recomendationText,
info.getFileObject,range,
fixes,
600)
result.add(desc)
}
...
The case when the condition is a not-equal comparison with
nil
:
case ifStat@IfStatement(condition@NotNode(eqExp@EqualComparison(x,_ : NilNode)),
NewlineNode(thenStat),
null) => {
val range = AstUtilities.getRange(node)
val fixes = new java.util.ArrayList
fixes.add(
new IfToStatementModifierFix(info,condition,thenStat,ifStat,IfStatementModifierFix))
fixes.add(
new IfToStatementModifierFix(info,eqExp,thenStat,ifStat,UnlessStatementModifierFix))
val desc =
new Description(this,
recomendationText,
info.getFileObject,range,
fixes,
600)
result.add(desc)
}
Note that for this case we also offer the quick fix for
unless
.Example 1
Activating the hint on this code:
Now displays the following quick fix:
And changes the code as:
Example 2
Also for code like this:
The following options are presented:
By selecting option 2 the code is changed as:
Code for this experiment can be found here.