private Referenceable resolveNative(
      Referenceable referenceable, Declaration dec, Backends backends) {
    Unit unit = dec.getUnit();
    Scope containerToSearchHeaderIn = null;
    if (unit instanceof CeylonBinaryUnit) {
      CeylonBinaryUnit binaryUnit = (CeylonBinaryUnit) unit;
      ExternalPhasedUnit phasedUnit = binaryUnit.getPhasedUnit();
      if (phasedUnit != null) {
        ExternalSourceFile sourceFile = phasedUnit.getUnit();
        if (sourceFile != null) {
          String sourceRelativePath =
              toJavaString(
                  binaryUnit
                      .getCeylonModule()
                      .toSourceUnitRelativePath(toCeylonString(unit.getRelativePath())));
          if (sourceRelativePath != null && sourceRelativePath.endsWith(".ceylon")) {
            for (Declaration sourceDecl : sourceFile.getDeclarations()) {
              if (sourceDecl.equals(dec)) {
                containerToSearchHeaderIn = sourceDecl.getContainer();
                break;
              }
            }
          } else {
            for (Declaration sourceDecl : sourceFile.getDeclarations()) {
              if (sourceDecl.getQualifiedNameString().equals(dec.getQualifiedNameString())) {
                containerToSearchHeaderIn = sourceDecl.getContainer();
                break;
              }
            }
          }
        }
      }
    } else {
      containerToSearchHeaderIn = dec.getContainer();
    }

    if (containerToSearchHeaderIn != null) {
      Declaration headerDeclaration = getNativeHeader(containerToSearchHeaderIn, dec.getName());
      if (headerDeclaration == null || !headerDeclaration.isNative()) return null;
      if (backends.header()) {
        referenceable = headerDeclaration;
      } else {
        if (headerDeclaration != null) {
          referenceable = getNativeDeclaration(headerDeclaration, supportedBackends());
        }
      }
    }
    return referenceable;
  }
 @Override
 public int compare(DeclarationWithProximity x, DeclarationWithProximity y) {
   String xname = x.getName();
   String yname = y.getName();
   if (exactName != null) {
     boolean xhit = xname.equals(exactName);
     boolean yhit = yname.equals(exactName);
     if (xhit && !yhit) {
       return -1;
     }
     if (yhit && !xhit) {
       return 1;
     }
     xhit = isNameMatching(xname, exactName);
     yhit = isNameMatching(yname, exactName);
     if (xhit && !yhit) {
       return -1;
     }
     if (yhit && !xhit) {
       return 1;
     }
   }
   Declaration xd = x.getDeclaration();
   Declaration yd = y.getDeclaration();
   boolean xdepr = xd.isDeprecated();
   boolean ydepr = yd.isDeprecated();
   if (xdepr && !ydepr) {
     return 1;
   }
   if (!xdepr && ydepr) {
     return -1;
   }
   int xp = x.getProximity();
   int yp = y.getProximity();
   int p = xp - yp;
   if (p != 0) {
     return p;
   }
   int c = xname.compareTo(yname);
   if (c != 0) {
     return c;
   }
   return xd.getQualifiedNameString().compareTo(yd.getQualifiedNameString());
 }
  @NotNull
  @Override
  public String getDescriptiveName(@NotNull PsiElement element) {
    if (element instanceof CeylonPsi.AttributeDeclarationPsi) {
      return ((CeylonPsi.AttributeDeclarationPsi) element)
          .getCeylonNode()
          .getDeclarationModel()
          .getQualifiedNameString();
    } else if (element instanceof CeylonPsi.ClassOrInterfacePsi) {
      Tree.Declaration ceylonNode = ((CeylonPsi.ClassOrInterfacePsi) element).getCeylonNode();
      //            if (ceylonNode == null) {
      //                // perhaps a stub
      //                return ((CeylonPsi.ClassOrInterfacePsi) element).getQualifiedName();
      //            }
      Declaration model = ceylonNode.getDeclarationModel();
      return model == null ? ceylonNode.getIdentifier().getText() : model.getQualifiedNameString();
    } else if (element instanceof CeylonPsi.AnyMethodPsi) {
      Function model = ((CeylonPsi.AnyMethodPsi) element).getCeylonNode().getDeclarationModel();
      return model == null
          ? ((CeylonPsi.AnyMethodPsi) element).getCeylonNode().getIdentifier().getText()
          : model.getQualifiedNameString();
    } else if (element instanceof CeylonPsi.ParameterDeclarationPsi) {
      return ((CeylonPsi.ParameterDeclarationPsi) element)
          .getCeylonNode()
          .getTypedDeclaration()
          .getIdentifier()
          .getText();
    } else if (element instanceof CeylonPsi.TypeParameterDeclarationPsi) {
      return ((CeylonPsi.TypeParameterDeclarationPsi) element)
          .getCeylonNode()
          .getIdentifier()
          .getText();
    } else if (element instanceof CeylonFile) {
      return ((CeylonFile) element).getName();
    } else if (element instanceof CeylonPsi.ObjectDefinitionPsi) {
      return ((CeylonPsi.ObjectDefinitionPsi) element).getCeylonNode().getIdentifier().getText();
    }

    throw new UnsupportedOperationException(
        "Descriptive name not implemented for " + element.getClass());
  }