private void gotoDeclaration(int pos) {
    Reference<Integer> abcIndex = new Reference<>(0);
    Reference<Integer> classIndex = new Reference<>(0);
    Reference<Integer> traitIndex = new Reference<>(0);
    Reference<Boolean> classTrait = new Reference<>(false);
    Reference<Integer> multinameIndexRef = new Reference<>(0);

    if (decompiledTextArea.getPropertyTypeAtPos(
        pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef)) {
      UsageFrame.gotoUsage(
          ABCPanel.this,
          new TraitMultinameUsage(
              getAbcList().get(abcIndex.getVal()).getABC(),
              multinameIndexRef.getVal(),
              classIndex.getVal(),
              traitIndex.getVal(),
              classTrait.getVal(),
              null,
              -1) {});
      return;
    }
    int multinameIndex = decompiledTextArea.getMultinameAtPos(pos);
    if (multinameIndex > -1) {
      List<MultinameUsage> usages = abc.findMultinameDefinition(multinameIndex);

      Multiname m = abc.constants.constant_multiname.get(multinameIndex);
      // search other ABC tags if this is not private multiname
      if (m.namespace_index > 0
          && abc.constants.constant_namespace.get(m.namespace_index).kind
              != Namespace.KIND_PRIVATE) {
        for (ABCContainerTag at : getAbcList()) {
          ABC a = at.getABC();
          if (a == abc) {
            continue;
          }
          int mid = a.constants.getMultinameId(m, false);
          if (mid > 0) {
            usages.addAll(a.findMultinameDefinition(mid));
          }
        }
      }

      // more than one? display list
      if (usages.size() > 1) {
        UsageFrame usageFrame = new UsageFrame(abc, multinameIndex, ABCPanel.this, true);
        usageFrame.setVisible(true);
        return;
      } else if (!usages.isEmpty()) { // one
        UsageFrame.gotoUsage(ABCPanel.this, usages.get(0));
        return;
      }
    }

    int dpos = decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>(""));
    if (dpos > -1) {
      decompiledTextArea.setCaretPosition(dpos);
    }
  }
  private boolean hasDeclaration(int pos) {

    SyntaxDocument sd = (SyntaxDocument) decompiledTextArea.getDocument();
    Token t = sd.getTokenAt(pos);
    if (t == null
        || (t.type != TokenType.IDENTIFIER
            && t.type != TokenType.KEYWORD
            && t.type != TokenType.REGEX)) {
      return false;
    }
    Reference<Integer> abcIndex = new Reference<>(0);
    Reference<Integer> classIndex = new Reference<>(0);
    Reference<Integer> traitIndex = new Reference<>(0);
    Reference<Integer> multinameIndexRef = new Reference<>(0);
    Reference<Boolean> classTrait = new Reference<>(false);

    if (decompiledTextArea.getPropertyTypeAtPos(
        pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef)) {
      return true;
    }
    int multinameIndex = decompiledTextArea.getMultinameAtPos(pos);
    if (multinameIndex > -1) {
      if (multinameIndex == 0) {
        return false;
      }
      List<MultinameUsage> usages = abc.findMultinameDefinition(multinameIndex);

      Multiname m = abc.constants.constant_multiname.get(multinameIndex);
      // search other ABC tags if this is not private multiname
      if (m.namespace_index > 0
          && abc.constants.constant_namespace.get(m.namespace_index).kind
              != Namespace.KIND_PRIVATE) {
        for (ABCContainerTag at : getAbcList()) {
          ABC a = at.getABC();
          if (a == abc) {
            continue;
          }
          int mid = a.constants.getMultinameId(m, false);
          if (mid > 0) {
            usages.addAll(a.findMultinameDefinition(mid));
          }
        }
      }

      // more than one? display list
      if (!usages.isEmpty()) {
        return true;
      }
    }

    return decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>("")) != -1;
  }