@Nullable
  private static String transformPattern(@NotNull String urlPattern, QualifiedName moduleQName, @Nullable PsiNamedElement element,
                                         String pyVersion) {
    Map<String, String> macros = new HashMap<>();
    macros.put("element.name", element == null ? null : element.getName());
    PyClass pyClass = element == null ? null : PsiTreeUtil.getParentOfType(element, PyClass.class, false);
    macros.put("class.name", pyClass == null ? null : pyClass.getName());
    if (element != null) {
      StringBuilder qName = new StringBuilder(moduleQName.toString()).append(".");
      if (element instanceof PyFunction && ((PyFunction)element).getContainingClass() != null) {
        qName.append(((PyFunction)element).getContainingClass().getName()).append(".");
      }
      qName.append(element.getName());
      macros.put("element.qname", qName.toString());
    }
    else {
      macros.put("element.qname", "");
    }
    String functionName = element instanceof PyFunction && element.getName() != null ? element.getName() : "";
    macros.put("function.name", functionName);
    macros.put("functionToProperty.name", functionToProperty(functionName));
    macros.put("module.name", moduleQName.toString());
    macros.put("python.version", pyVersion);
    macros.put("module.basename", moduleQName.getLastComponent());

    macros.put("functionIsProperty?", Boolean.toString(!functionName.equals(functionToProperty(functionName))));

    final String pattern = transformPattern(urlPattern, macros);
    if (pattern == null) {
      return rootForPattern(urlPattern);
    }
    return pattern;
  }
@Nullable
  private static String transformPattern(@NotNull String urlPattern, QualifiedName moduleQName, @Nullable PsiNamedElement element,
                                         String pyVersion)