* @param filename the path containing the reference, or null if there was an error
     */
    @Nullable
    private String toURL(@NotNull Binding binding, String filename) {
        Def def = binding.getFirstNode();
        if (def == null) {
            return null;
        }
        if (binding.isBuiltin()) {
            return def.getURL();
        }

        String destPath = null;

        if (binding.getKind() == Binding.Kind.MODULE) {
            ModuleType mtype = binding.getType().asModuleType();
            if (mtype != null) {
                destPath = mtype.getFile();
            }
        } else {
            destPath = def.getFile();
        }

        if (destPath == null) {
            return null;
        }

        String anchor = "#" + binding.getQname();
        if (binding.getFirstFile().equals(filename)) {
            return anchor;
        }

        if (destPath.startsWith(rootPath)) {
            String relpath;
            if (filename != null) {
                relpath = Util.relativize(filename, destPath);
            } else {
                relpath = destPath;
            }

            if (relpath != null) {
                return relpath + ".html" + anchor;
            } else {
                return anchor;
            }
        } else {
            return "file://" + destPath + anchor;
        }
    }