Hackしたいけど実現できていないこと(1)

id:taichitaichiから伝授されて以来、守っている掟がある。

「否定演算子(!)は見にくいので使わない」ことである。if(!foo) ではなく if(foo == false) と書く*1

これを指摘するHackを作ろうと思った。

import org.ashikunep.irenka.dom.CtUnary;
import org.ashikunep.irenka.dom.UnaryOperator;
import org.ashikunep.irenka.toolkit.Messager;

/**
 * 否定演算子をチェックするIrenka Hack。
 * @author daisuke
 */
public class NotOperatorChecker {
  
  /**
   * インターフェイスに関する命名規則チェック。
   * @param messager
   * @param unary 単項演算子
   * @when {@link UnaryOperator#NOT} = unary.operator
   */
  public void foundNotOperator(CtUnary<Boolean> unary, Messager messager) {
    messager.warn(unary, "否定演算子は推奨されません。\"!foo\"\"foo == false\"に書き換えて下さい。");
  }
}

これを以下のコードに適用してみる。

public class TestClass {
  
  public static void main(String[] args) {
    boolean result = !Boolean.valueOf(args[0]);
    System.out.println(result);
  }
}

すると、ビルダーが例外を吐いているようで、指摘が行われない。


java.lang.ClassCastException: java.lang.String
at org.ashikunep.irenka.query.ir.property.NavigatedProperty.apply(NavigatedProperty.java:98)
at org.ashikunep.irenka.query.ir.engine.SegmentResolver.visitProperty(SegmentResolver.java:109)
at org.ashikunep.irenka.query.ir.engine.SegmentResolver.visitProperty(SegmentResolver.java:1)
at org.ashikunep.irenka.query.ir.IrProperty.accept(IrProperty.java:88)
at org.ashikunep.irenka.query.ir.engine.ConstraintSegment.performPropagate(ConstraintSegment.java:140)
at org.ashikunep.irenka.query.ir.engine.ConstraintSegment.resolve(ConstraintSegment.java:82)
at org.ashikunep.irenka.query.ir.engine.IrQueryCursor.resolveSegment(IrQueryCursor.java:221)
at org.ashikunep.irenka.query.ir.engine.IrQueryCursor.push(IrQueryCursor.java:248)
at org.ashikunep.irenka.query.ir.engine.IrQueryCursor.prepare(IrQueryCursor.java:129)
at org.ashikunep.irenka.query.ir.engine.IrQueryCursor.hasNext(IrQueryCursor.java:81)
at org.ashikunep.irenka.apply.impl.DefaultHackApplier.applyActionToTarget(DefaultHackApplier.java:280)
at org.ashikunep.irenka.apply.impl.DefaultHackApplier.applyMatchActionToTarget(DefaultHackApplier.java:217)
at org.ashikunep.irenka.apply.impl.DefaultHackApplier.applyHackToTarget(DefaultHackApplier.java:173)
at org.ashikunep.irenka.apply.impl.DefaultHackApplier.applyHackToAll(DefaultHackApplier.java:129)
at org.ashikunep.irenka.apply.impl.DefaultHackApplier.apply(DefaultHackApplier.java:79)
at org.ashikunep.irenka.hack.engine.AbstractHackEngine.applyHacks(AbstractHackEngine.java:123)
at org.ashikunep.irenka.hack.engine.AbstractHackEngine.process(AbstractHackEngine.java:81)
at org.ashikunep.irenka.studio.JdtIrenkaBuildEngine.actionHack(JdtIrenkaBuildEngine.java:55)
at org.ashikunep.irenka.build.engine.IrenkaBuildEngine.build(IrenkaBuildEngine.java:54)
at org.ashikunep.irenka.studio.IrenkaBuilder.build(IrenkaBuilder.java:95)
at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:624)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:166)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:197)
at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:246)
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:37)
at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:249)
at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:302)
at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:334)
at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:137)
at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:235)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:55)

俺が間違っているのか、バグなのか…。まぁ、こういう時は大抵俺が間違ってるんだよなw

*1:値の反転の時は使っても良いんじゃないかと思っているけど。ex. boolean y = !x;