private boolean doDeleteRemote(
      @NotNull String branchName, @NotNull Collection<GitRepository> repositories) {
    Couple<String> pair = splitNameOfRemoteBranch(branchName);
    String remoteName = pair.getFirst();
    String branch = pair.getSecond();

    GitCompoundResult result = new GitCompoundResult(myProject);
    for (GitRepository repository : repositories) {
      GitCommandResult res;
      GitRemote remote = getRemoteByName(repository, remoteName);
      if (remote == null) {
        String error = "Couldn't find remote by name: " + remoteName;
        LOG.error(error);
        res = GitCommandResult.error(error);
      } else {
        res = pushDeletion(repository, remote, branch);
        if (!res.success() && isAlreadyDeletedError(res.getErrorOutputAsJoinedString())) {
          res = myGit.remotePrune(repository, remote);
        }
      }
      result.append(repository, res);
      repository.update();
    }
    if (!result.totalSuccess()) {
      VcsNotifier.getInstance(myProject)
          .notifyError(
              "Failed to delete remote branch " + branchName,
              result.getErrorOutputWithReposIndication());
    }
    return result.totalSuccess();
  }
  public Couple<String> setText(@Nullable final String text, @Nullable final String requestor) {
    if (StringUtil.isEmpty(text)
        && !Comparing.equal(requestor, myCurrentRequestor)
        && !EventLog.LOG_REQUESTOR.equals(requestor)) {
      return Couple.of(myInfoPanel.getText(), myCurrentRequestor);
    }

    boolean logMode = myInfoPanel.updateText(EventLog.LOG_REQUESTOR.equals(requestor) ? "" : text);
    myCurrentRequestor = logMode ? EventLog.LOG_REQUESTOR : requestor;
    return Couple.of(text, requestor);
  }
 /**
  * Makes the password database key for the URL: inserts the login after the scheme:
  * http://login@url.
  */
 @NotNull
 private static String makeKey(@NotNull String url, @Nullable String login) {
   if (login == null) {
     return url;
   }
   Couple<String> pair = UriUtil.splitScheme(url);
   String scheme = pair.getFirst();
   if (!StringUtil.isEmpty(scheme)) {
     return scheme + URLUtil.SCHEME_SEPARATOR + login + "@" + pair.getSecond();
   }
   return login + "@" + url;
 }
 private boolean isValidLibrary(
     @NotNull File file, @NotNull final String name, @Nullable Ref<Couple<String>> cache) {
   Couple<String> info = parseLibrary(file);
   if (info == null) {
     return false;
   }
   if (Comparing.equal(info.getFirst(), name)) {
     if (cache != null) {
       cache.set(info);
     }
     return true;
   }
   return false;
 }
  private static Couple<Integer> composeText(
      StringBuilder sb,
      List<Pair<String, HighlightInfo>> list,
      int index,
      String text,
      int endPos,
      int startPos) {
    int i = index;
    while (i < list.size()) {
      Pair<String, HighlightInfo> pair = list.get(i);
      HighlightInfo info = pair.second;
      if (info.endOffset <= startPos) {
        break;
      }

      String severity = pair.first;
      HighlightInfo prev = i < list.size() - 1 ? list.get(i + 1).second : null;

      sb.insert(0, text.substring(info.endOffset, endPos));
      sb.insert(0, "</" + severity + ">");
      endPos = info.endOffset;
      if (prev != null && prev.endOffset > info.startOffset) {
        Couple<Integer> result = composeText(sb, list, i + 1, text, endPos, info.startOffset);
        i = result.first - 1;
        endPos = result.second;
      }
      sb.insert(0, text.substring(info.startOffset, endPos));
      sb.insert(0, "<" + severity + " descr=\"" + info.getDescription() + "\">");

      endPos = info.startOffset;
      i++;
    }

    return Couple.newOne(i, endPos);
  }
    /**
     * For the given VirtualFile constructs a FilePathImpl object without referring to the initial
     * VirtualFile object and adds this FilePathImpl to the set of files for proper
     * VcsDirtyScopeManager - to mark these files dirty when the set will be populated.
     *
     * @param file file which path is to be added.
     * @param addToFiles If true, then add to dirty files even if it is a directory. Otherwise add
     *     to the proper set.
     */
    private void add(VirtualFile file, boolean addToFiles, final boolean forDelete) {
      if (file == null) {
        return;
      }
      final boolean isDirectory = file.isDirectory();
      // need to create FilePath explicitly without referring to VirtualFile because the path of
      // VirtualFile may change
      final FilePathImpl path =
          forDelete
              ? new FilePathImpl(new File(file.getPath()), isDirectory)
              : new FilePathImpl(file);

      final Collection<VcsDirtyScopeManager> managers = getManagers(file);
      for (VcsDirtyScopeManager manager : managers) {
        Couple<HashSet<FilePath>> filesAndDirs = map.get(manager);
        if (filesAndDirs == null) {
          filesAndDirs = Couple.of(new HashSet<FilePath>(), new HashSet<FilePath>());
          map.put(manager, filesAndDirs);
        }

        if (addToFiles || !isDirectory) {
          filesAndDirs.first.add(path);
        } else {
          filesAndDirs.second.add(path);
        }
      }
    }
  public void writeExternal(Element macro) {
    macro.setAttribute(ATTRIBUTE_NAME, myName);
    final ActionDescriptor[] actions = getActions();
    for (ActionDescriptor action : actions) {
      Element actionNode = null;
      if (action instanceof TypedDescriptor) {
        actionNode = new Element(ELEMENT_TYPING);
        TypedDescriptor typedDescriptor = (TypedDescriptor) action;
        actionNode.setText(typedDescriptor.getText().replaceAll(" ", "&#x20;"));
        actionNode.setAttribute(
            ATTRIBUTE_KEY_CODES,
            unparseKeyCodes(
                Couple.of(typedDescriptor.getKeyCodes(), typedDescriptor.getKeyModifiers())));
      } else if (action instanceof IdActionDescriptor) {
        actionNode = new Element(ELEMENT_ACTION);
        actionNode.setAttribute(ATTRIBUTE_ID, ((IdActionDescriptor) action).getActionId());
      } else if (action instanceof ShortcutActionDesciption) {
        actionNode = new Element(ELEMENT_SHORTCUT);
        actionNode.setAttribute(ATTRIBUTE_TEXT, ((ShortcutActionDesciption) action).getText());
      }

      assert actionNode != null : action;

      macro.addContent(actionNode);
    }
  }
 private Couple<String> keyForChange(final Change change) {
   final FilePath beforePath = ChangesUtil.getBeforePath(change);
   final String beforeKey = beforePath == null ? null : beforePath.getIOFile().getAbsolutePath();
   final FilePath afterPath = ChangesUtil.getAfterPath(change);
   final String afterKey = afterPath == null ? null : afterPath.getIOFile().getAbsolutePath();
   return Couple.of(beforeKey, afterKey);
 }
 @NotNull
 @Override
 public Map<String, String> getAvailableSystemLibraries() {
   Map<String, String> map = new TreeMap<String, String>();
   File[] directoriesForLibraries = getFilesForLibraries();
   for (File childFile : directoriesForLibraries) {
     if (!FileUtilRt.getExtension(childFile.getName()).equals("dll")) {
       continue;
     }
     Couple<String> info = parseLibrary(childFile);
     if (info == null) {
       continue;
     }
     map.put(info.getFirst(), info.getSecond());
   }
   return map;
 }
  @NotNull
  private static Couple<Collection<TextRange>> getUsages(
      @NotNull PsiElement target,
      PsiElement psiElement,
      boolean withDeclarations,
      boolean detectAccess) {
    List<TextRange> readRanges = new ArrayList<TextRange>();
    List<TextRange> writeRanges = new ArrayList<TextRange>();
    final ReadWriteAccessDetector detector =
        detectAccess ? ReadWriteAccessDetector.findDetector(target) : null;
    final FindUsagesManager findUsagesManager =
        ((FindManagerImpl) FindManager.getInstance(target.getProject())).getFindUsagesManager();
    final FindUsagesHandler findUsagesHandler =
        findUsagesManager.getFindUsagesHandler(target, true);
    final LocalSearchScope scope = new LocalSearchScope(psiElement);
    Collection<PsiReference> refs =
        findUsagesHandler != null
            ? findUsagesHandler.findReferencesToHighlight(target, scope)
            : ReferencesSearch.search(target, scope).findAll();
    for (PsiReference psiReference : refs) {
      if (psiReference == null) {
        LOG.error(
            "Null reference returned, findUsagesHandler="
                + findUsagesHandler
                + "; target="
                + target
                + " of "
                + target.getClass());
        continue;
      }
      List<TextRange> destination;
      if (detector == null
          || detector.getReferenceAccess(target, psiReference)
              == ReadWriteAccessDetector.Access.Read) {
        destination = readRanges;
      } else {
        destination = writeRanges;
      }
      HighlightUsagesHandler.collectRangesToHighlight(psiReference, destination);
    }

    if (withDeclarations) {
      final TextRange declRange =
          HighlightUsagesHandler.getNameIdentifierRange(psiElement.getContainingFile(), target);
      if (declRange != null) {
        if (detector != null && detector.isDeclarationWriteAccess(target)) {
          writeRanges.add(declRange);
        } else {
          readRanges.add(declRange);
        }
      }
    }

    return Couple.<Collection<TextRange>>of(readRanges, writeRanges);
  }
 /**
  * Compares the given revisions and returns a pair of them, where the first one is older, and
  * second is newer.
  */
 @NotNull
 public static Couple<VcsFileRevision> sortRevisions(
     @NotNull VcsFileRevision revision1, @NotNull VcsFileRevision revision2) {
   VcsFileRevision left = revision1;
   VcsFileRevision right = revision2;
   if (compare(revision1, revision2) > 0) {
     left = revision2;
     right = revision1;
   }
   return Couple.of(left, right);
 }
  private static void collectPropertyAccessors(Class<?> aClass, List<Accessor> accessors) {
    final Map<String, Couple<Method>> candidates =
        ContainerUtilRt.newTreeMap(); // (name,(getter,setter))
    for (Method method : aClass.getMethods()) {
      if (!Modifier.isPublic(method.getModifiers())) {
        continue;
      }

      Pair<String, Boolean> propertyData = getPropertyData(method.getName()); // (name,isSetter)
      if (propertyData == null
          || propertyData.first.equals("class")
          || method.getParameterTypes().length != (propertyData.second ? 1 : 0)) {
        continue;
      }

      Couple<Method> candidate = candidates.get(propertyData.first);
      if (candidate == null) {
        candidate = Couple.getEmpty();
      }
      if ((propertyData.second ? candidate.second : candidate.first) != null) {
        continue;
      }
      candidate =
          Couple.of(
              propertyData.second ? candidate.first : method,
              propertyData.second ? method : candidate.second);
      candidates.put(propertyData.first, candidate);
    }
    for (Map.Entry<String, Couple<Method>> candidate : candidates.entrySet()) {
      Couple<Method> methods = candidate.getValue(); // (getter,setter)
      if (methods.first != null
          && methods.second != null
          && methods.first.getReturnType().equals(methods.second.getParameterTypes()[0])
          && methods.first.getAnnotation(Transient.class) == null
          && methods.second.getAnnotation(Transient.class) == null) {
        accessors.add(
            new PropertyAccessor(
                candidate.getKey(), methods.first.getReturnType(), methods.first, methods.second));
      }
    }
  }
 public Collection<Couple<TemplateResource>> getTemplateCouples() {
   final LinkedHashMap<String, Couple<TemplateResource>> resources =
       new LinkedHashMap<String, Couple<TemplateResource>>();
   for (TemplateResource resource : getAllTemplates()) {
     final String baseName = getTemplateBaseName(resource);
     TemplateResource eq = toEqualsName(baseName).equals(resource.getFileName()) ? resource : null;
     TemplateResource hc =
         toHashCodeName(baseName).equals(resource.getFileName()) ? resource : null;
     final Couple<TemplateResource> couple = resources.get(baseName);
     if (couple != null) {
       resources.put(
           baseName,
           Couple.of(
               couple.first != null ? couple.first : eq,
               couple.second != null ? couple.second : hc));
     } else {
       resources.put(baseName, Couple.of(eq, hc));
     }
   }
   return resources.values();
 }
  protected Couple<String> doAction(
      Project project, PsiElement psiElement, I18nizeQuickFixModel model) {
    if (!model.hasValidData()) {
      return null;
    }
    final String key = model.getKey();
    final String value = model.getValue();

    final Collection<PropertiesFile> selectedPropertiesFiles = model.getAllPropertiesFiles();
    createProperty(project, psiElement, selectedPropertiesFiles, key, value);

    return Couple.newOne(key, value);
  }
  private static Couple<Integer> composeText(
      StringBuilder sb,
      List<Pair<String, HighlightInfo>> list,
      int index,
      String text,
      int endPos,
      int startPos,
      boolean showAttributesKeys) {
    int i = index;
    while (i < list.size()) {
      Pair<String, HighlightInfo> pair = list.get(i);
      HighlightInfo info = pair.second;
      if (info.endOffset <= startPos) {
        break;
      }

      String severity = pair.first;
      HighlightInfo prev = i < list.size() - 1 ? list.get(i + 1).second : null;

      sb.insert(0, text.substring(info.endOffset, endPos));
      sb.insert(0, "</" + severity + ">");
      endPos = info.endOffset;
      if (prev != null && prev.endOffset > info.startOffset) {
        Couple<Integer> result =
            composeText(sb, list, i + 1, text, endPos, info.startOffset, showAttributesKeys);
        i = result.first - 1;
        endPos = result.second;
      }
      sb.insert(0, text.substring(info.startOffset, endPos));

      String str =
          "<"
              + severity
              + " descr=\""
              + StringUtil.escapeQuotes(String.valueOf(info.getDescription()))
              + "\"";
      if (showAttributesKeys) {
        str += " textAttributesKey=\"" + info.forcedTextAttributesKey + "\"";
      }
      str += ">";
      sb.insert(0, str);

      endPos = info.startOffset;
      i++;
    }

    return Couple.of(i, endPos);
  }
 private Map<Integer, Couple<Integer>> createVirtualSelectionMap(
     int startVisualLine, int endVisualLine) {
   HashMap<Integer, Couple<Integer>> map = new HashMap<Integer, Couple<Integer>>();
   for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
     if (caret.hasSelection()) {
       VisualPosition selectionStart = caret.getSelectionStartPosition();
       VisualPosition selectionEnd = caret.getSelectionEndPosition();
       if (selectionStart.line == selectionEnd.line) {
         int line = selectionStart.line;
         if (line >= startVisualLine && line <= endVisualLine) {
           map.put(line, Couple.of(selectionStart.column, selectionEnd.column));
         }
       }
     }
   }
   return map;
 }
  private Couple<TextRange> findCommentBlock(
      TextRange range, String commentPrefix, String commentSuffix) {
    CharSequence chars = myDocument.getCharsSequence();
    int startOffset = range.getStartOffset();
    boolean endsProperly =
        CharArrayUtil.regionMatches(
            chars, range.getEndOffset() - commentSuffix.length(), commentSuffix);

    TextRange start = expandRange(startOffset, startOffset + commentPrefix.length());
    TextRange end;
    if (endsProperly) {
      end = expandRange(range.getEndOffset() - commentSuffix.length(), range.getEndOffset());
    } else {
      end = new TextRange(range.getEndOffset(), range.getEndOffset());
    }

    return Couple.of(start, end);
  }
    @Nullable
    private Couple<Integer> pointToCellCoords(Point p) {
      int x = p.x;
      int y = p.y;

      final Insets i = getInsets();
      final Dimension d = getSize();

      final int left = i.left + (d.width - i.left - i.right - WIDTH) / 2;
      final int top = i.top + (d.height - i.top - i.bottom - HEIGHT) / 2;

      int col = (x - left - 2) / 31;
      col = col > 9 ? 9 : col;
      int row = (y - top - 2) / 31;
      row = row > 1 ? 1 : row;

      return row >= 0 && col >= 0 ? Couple.of(row, col) : null;
    }
  @NotNull
  private DiffInfo doLoadDiffInfo(@NotNull final BranchInfo branch) throws VcsException {
    // TODO: make cancelable and abort old speculative requests (when git4idea will allow to do so)
    String currentBranch = myCurrentBranch;
    String targetBranch = branch.getForkInfo().getRemoteName() + "/" + branch.getRemoteName();

    List<GitCommit> commits1 =
        GitHistoryUtils.history(myProject, myGitRepository.getRoot(), ".." + targetBranch);
    List<GitCommit> commits2 =
        GitHistoryUtils.history(myProject, myGitRepository.getRoot(), targetBranch + "..");
    Collection<Change> diff =
        GitChangeUtils.getDiff(
            myProject, myGitRepository.getRoot(), targetBranch, myCurrentBranch, null);
    GitCommitCompareInfo info =
        new GitCommitCompareInfo(GitCommitCompareInfo.InfoType.BRANCH_TO_HEAD);
    info.put(myGitRepository, diff);
    info.put(myGitRepository, Couple.of(commits1, commits2));

    return new DiffInfo(info, currentBranch, targetBranch);
  }
 @Nullable
 private static Couple<String> parseLibrary(File f) {
   DotNetLibraryOpenCache.Record record = null;
   try {
     record = DotNetLibraryOpenCache.acquire(f.getPath());
     ModuleParser moduleParser = record.get();
     return Couple.of(
         moduleParser.getAssemblyInfo().getName(),
         moduleParser.getAssemblyInfo().getMajorVersion()
             + "."
             + moduleParser.getAssemblyInfo().getMinorVersion()
             + "."
             + moduleParser.getAssemblyInfo().getBuildNumber()
             + "."
             + moduleParser.getAssemblyInfo().getRevisionNumber());
   } catch (Exception e) {
     return null;
   } finally {
     if (record != null) {
       record.finish();
     }
   }
 }
 @NotNull
 private static Couple<String> createKey(
     @NotNull WCInfoWithBranches root, @NotNull WCInfoWithBranches.Branch branch) {
   return Couple.of(root.getPath(), branch.getUrl());
 }
  private static Couple<Integer> getRemotePortsFromProcess(RemoteSshProcess process)
      throws ExecutionException {
    Scanner s = new Scanner(process.getInputStream());

    return Couple.of(readInt(s, process), readInt(s, process));
  }
 /**
  * Returns the remote and the "local" name of a remote branch. Expects branch in format
  * "origin/master", i.e. remote/branch
  */
 private static Couple<String> splitNameOfRemoteBranch(String branchName) {
   int firstSlash = branchName.indexOf('/');
   String remoteName = firstSlash > -1 ? branchName.substring(0, firstSlash) : branchName;
   String remoteBranchName = branchName.substring(firstSlash + 1);
   return Couple.of(remoteName, remoteBranchName);
 }
 public Copy(@NonNls String file, @NonNls String toFile) {
   //noinspection HardCodedStringLiteral
   super("copy", Couple.of("file", file), Couple.of("tofile", toFile));
 }
 public Copy(@NonNls String toDir) {
   //noinspection HardCodedStringLiteral
   super("copy", Couple.of("todir", toDir));
 }
  public void uncommentRange(
      TextRange range, String commentPrefix, String commentSuffix, Commenter commenter) {
    if (commenter instanceof SelfManagingCommenter) {
      final SelfManagingCommenter selfManagingCommenter = (SelfManagingCommenter) commenter;
      selfManagingCommenter.uncommentBlockComment(
          range.getStartOffset(), range.getEndOffset(), myDocument, mySelfManagedCommenterData);
      return;
    }

    String text =
        myDocument
            .getCharsSequence()
            .subSequence(range.getStartOffset(), range.getEndOffset())
            .toString();
    int startOffset = range.getStartOffset();
    // boolean endsProperly = CharArrayUtil.regionMatches(chars, range.getEndOffset() -
    // commentSuffix.length(), commentSuffix);
    List<Couple<TextRange>> ranges = new ArrayList<>();

    if (commenter instanceof CustomUncommenter) {
      /*
       In case of custom uncommenter, we need to ask it for list of [commentOpen-start,commentOpen-end], [commentClose-start,commentClose-end]
       and shift if according to current offset
      */
      CustomUncommenter customUncommenter = (CustomUncommenter) commenter;
      for (Couple<TextRange> coupleFromCommenter :
          customUncommenter.getCommentRangesToDelete(text)) {
        TextRange openComment = coupleFromCommenter.first.shiftRight(startOffset);
        TextRange closeComment = coupleFromCommenter.second.shiftRight(startOffset);
        ranges.add(Couple.of(openComment, closeComment));
      }
    } else {
      // If commenter is not custom, we need to get this list by our selves
      int position = 0;
      while (true) {
        int start = getNearest(text, commentPrefix, position);
        if (start == text.length()) {
          break;
        }
        position = start;
        int end =
            getNearest(text, commentSuffix, position + commentPrefix.length())
                + commentSuffix.length();
        position = end;
        Couple<TextRange> pair =
            findCommentBlock(
                new TextRange(start + startOffset, end + startOffset),
                commentPrefix,
                commentSuffix);
        ranges.add(pair);
      }
    }

    RangeMarker marker = myDocument.createRangeMarker(range);
    try {
      for (int i = ranges.size() - 1; i >= 0; i--) {
        Couple<TextRange> toDelete = ranges.get(i);
        myDocument.deleteString(toDelete.first.getStartOffset(), toDelete.first.getEndOffset());
        int shift = toDelete.first.getEndOffset() - toDelete.first.getStartOffset();
        myDocument.deleteString(
            toDelete.second.getStartOffset() - shift, toDelete.second.getEndOffset() - shift);
        if (commenter.getCommentedBlockCommentPrefix() != null) {
          commentNestedComments(
              myDocument,
              new TextRange(
                  toDelete.first.getEndOffset() - shift, toDelete.second.getStartOffset() - shift),
              commenter);
        }
      }

      processDocument(myDocument, marker, commenter, false);
    } finally {
      marker.dispose();
    }
  }
 @NotNull
 public Couple<String> getSimpleDefaultDescriptionMessage(@NotNull final BranchInfo branch) {
   Couple<String> message = Couple.of(myCurrentBranch, "");
   branch.setDefaultMessage(message);
   return message;
 }
 public Couple<String> getKey() {
   return Couple.newOne(myPatch.getBeforeName(), myPatch.getAfterName());
 }
  /**
   * This method searches ast node that could be reparsed incrementally and returns pair of target
   * reparseable node and new replacement node. Returns null if there is no any chance to make
   * incremental parsing.
   */
  @Nullable
  public Couple<ASTNode> findReparseableRoots(
      @NotNull PsiFileImpl file,
      @NotNull TextRange changedPsiRange,
      @NotNull CharSequence newFileText) {
    Project project = file.getProject();
    final FileElement fileElement = file.getTreeElement();
    final CharTable charTable = fileElement.getCharTable();
    int lengthShift = newFileText.length() - fileElement.getTextLength();

    if (fileElement.getElementType() instanceof ITemplateDataElementType || isTooDeep(file)) {
      // unable to perform incremental reparse for template data in JSP, or in exceptionally deep
      // trees
      return null;
    }

    final ASTNode leafAtStart =
        fileElement.findLeafElementAt(Math.max(0, changedPsiRange.getStartOffset() - 1));
    final ASTNode leafAtEnd =
        fileElement.findLeafElementAt(
            Math.min(changedPsiRange.getEndOffset(), fileElement.getTextLength() - 1));
    ASTNode node =
        leafAtStart != null && leafAtEnd != null
            ? TreeUtil.findCommonParent(leafAtStart, leafAtEnd)
            : fileElement;
    Language baseLanguage = file.getViewProvider().getBaseLanguage();

    while (node != null && !(node instanceof FileElement)) {
      IElementType elementType = node.getElementType();
      if (elementType instanceof IReparseableElementType) {
        final TextRange textRange = node.getTextRange();
        final IReparseableElementType reparseable = (IReparseableElementType) elementType;

        if (baseLanguage.isKindOf(reparseable.getLanguage())
            && textRange.getLength() + lengthShift > 0) {
          final int start = textRange.getStartOffset();
          final int end = start + textRange.getLength() + lengthShift;
          if (end > newFileText.length()) {
            reportInconsistentLength(file, newFileText, node, start, end);
            break;
          }

          CharSequence newTextStr = newFileText.subSequence(start, end);

          if (reparseable.isParsable(node.getTreeParent(), newTextStr, baseLanguage, project)) {
            ASTNode chameleon = reparseable.createNode(newTextStr);
            if (chameleon != null) {
              DummyHolder holder =
                  DummyHolderFactory.createHolder(
                      file.getManager(), null, node.getPsi(), charTable);
              holder.getTreeElement().rawAddChildren((TreeElement) chameleon);

              if (holder.getTextLength() != newTextStr.length()) {
                String details =
                    ApplicationManager.getApplication().isInternal()
                        ? "text=" + newTextStr + "; treeText=" + holder.getText() + ";"
                        : "";
                LOG.error("Inconsistent reparse: " + details + " type=" + elementType);
              }

              return Couple.of(node, chameleon);
            }
          }
        }
      }
      node = node.getTreeParent();
    }
    return null;
  }
 public static Class<?> substituteGenericType(Type genericType, Type classType) {
   return ourVariableSubstitutions.get(Couple.of(genericType, classType));
 }