import org.checkerframework.checker.guieffect.qual.UIEffect;

public class TransitiveInheritance {

  public static class TopLevel {
    // Implicitly safe
    public void foo() {}
  }

  public static interface ITop {
    public void bar();
  }

  public static interface IIndirect {
    public void baz();
  }

  // Mid-level class and interface that do not redeclare or override the default safe methods
  public abstract static class MidLevel extends TopLevel implements IIndirect {}

  public static interface IMid extends ITop {}

  // Issue #3287 is that if foo or bar is overridden with a @UIEffect implementation here, the
  // "skip" in declarations causes the override error to not be issued
  // We check both classes and interfaces; the reported issue is related only to methods whose
  // nearest explicit definition lives in an interface
  public static class Base extends MidLevel implements IMid {

    // Should catch when the override is for a method originating in a class two levels up (here
    // TopLevel)
    @Override
    @UIEffect
    // :: error: (override.effect)
    public void foo() {}

    // Should catch when the override is for a method originating in an interface two levels up
    // (here ITop)
    @Override
    @UIEffect
    // :: error: (override.effect)
    public void bar() {}

    // Should catch when the override is for a method originating in an interface two levels up,
    // but which is implemented via class inheritance (here IIndirect, which is implemented by
    // MidLevel).
    @Override
    @UIEffect
    // :: error: (override.effect)
    public void baz() {}
  }

  public static interface IBase extends IMid {
    @Override
    @UIEffect
    // :: error: (override.effect)
    public void bar();
  }
}
