public static <FnT extends DoFn<?, ?>> DoFnSignature getSignature(Class<FnT> fn) {
    return signatureCache.computeIfAbsent(fn, DoFnSignatures::parseSignature);
  }
@Test
  public void testUsageOfStateDeclaredInSuperclass() throws Exception {
    DoFnDeclaringState fn =
        new DoFnDeclaringState() {
          @ProcessElement
          public void process(
              ProcessContext context,
              @StateId(DoFnDeclaringState.STATE_ID) ValueState<Integer> state) {}
        };

    thrown.expect(IllegalArgumentException.class);
    thrown.expectMessage("process");
    thrown.expectMessage("declared in a different class");
    thrown.expectMessage(DoFnDeclaringState.STATE_ID);
    thrown.expectMessage(fn.getClass().getSimpleName());
    DoFnSignatures.getSignature(fn.getClass());
  }