@Override
  public void renderElement(LookupElementPresentation presentation) {
    final Object object = getObject();
    if (object instanceof PsiClass) {
      JavaPsiClassReferenceElement.renderClassItem(
          presentation, this, (PsiClass) object, myDiamond, myLocationString, mySubstitutor);
    } else {
      assert object instanceof PsiType;

      if (!(object instanceof PsiPrimitiveType)) {
        presentation.setIcon(DefaultLookupItemRenderer.getRawIcon(this, presentation.isReal()));
      }

      presentation.setItemText(((PsiType) object).getCanonicalText());
      presentation.setItemTextBold(object instanceof PsiPrimitiveType);
      if (isAddArrayInitializer()) {
        presentation.setTailText("{...}");
      }
    }
    if (myBracketsCount > 0) {
      presentation.setTailText(
          StringUtil.repeat("[]", myBracketsCount)
              + StringUtil.notNullize(presentation.getTailText()),
          true);
    }
  }
Example #2
0
 public static String prepareValueText(String text, Project project) {
   text = StringUtil.unquoteString(text);
   text = StringUtil.unescapeStringCharacters(text);
   int tabSize = CodeStyleSettingsManager.getSettings(project).getTabSize(StdFileTypes.JAVA);
   if (tabSize < 0) {
     tabSize = 0;
   }
   return text.replace("\t", StringUtil.repeat(" ", tabSize));
 }
    @NotNull
    private String getBranchesText() {
      if (myBranches == null) {
        return "<i>In branches: loading...</i>";
      }
      if (myBranches.isEmpty()) return "<i>Not in any branch</i>";
      if (myExpanded) {
        int rowCount = (int) Math.ceil((double) myBranches.size() / BRANCHES_TABLE_COLUMN_COUNT);
        HtmlTableBuilder builder = new HtmlTableBuilder();

        for (int i = 0; i < rowCount; i++) {
          builder.startRow();
          if (i == 0) {
            builder.append(
                "<i>In "
                    + myBranches.size()
                    + " branches, </i><a href=\""
                    + SHOW_OR_HIDE_BRANCHES
                    + "\"><i>hide</i></a>: ");
          } else {
            builder.append("");
          }

          for (int j = 0; j < BRANCHES_TABLE_COLUMN_COUNT; j++) {
            int index = rowCount * j + i;
            if (index >= myBranches.size()) {
              builder.append("");
            } else if (index != myBranches.size() - 1) {
              builder.append(
                  myBranches.get(index) + "," + StringUtil.repeat("&nbsp;", 20), LEFT_ALIGN);
            } else {
              builder.append(myBranches.get(index), LEFT_ALIGN);
            }
          }

          builder.endRow();
        }

        return builder.build();
      } else {
        String branchText;
        if (myBranches.size() <= BRANCHES_LIMIT) {
          branchText = StringUtil.join(myBranches, ", ");
        } else {
          branchText =
              StringUtil.join(ContainerUtil.getFirstItems(myBranches, BRANCHES_LIMIT), ", ")
                  + ", ... <a href=\""
                  + SHOW_OR_HIDE_BRANCHES
                  + "\"><i>Show All</i></a>";
        }
        return "<i>In "
            + myBranches.size()
            + StringUtil.pluralize(" branch", myBranches.size())
            + ":</i> "
            + branchText;
      }
    }
  private String getDecompiledTextWithMarks(Map<ClsElementImpl, JetDeclaration> map) {
    String decompiledText = getDecompiledText();

    int[] openings = new int[decompiledText.length() + 1];
    int[] closings = new int[decompiledText.length() + 1];
    for (JetDeclaration jetDeclaration : map.values()) {
      TextRange textRange = jetDeclaration.getTextRange();
      openings[textRange.getStartOffset()]++;
      closings[textRange.getEndOffset()]++;
    }

    StringBuilder result = new StringBuilder();
    for (int i = 0; i <= decompiledText.length(); i++) {
      result.append(StringUtil.repeat("]", closings[i]));
      result.append(StringUtil.repeat("[", openings[i]));
      if (i < decompiledText.length()) {
        result.append(decompiledText.charAt(i));
      }
    }
    return result.toString();
  }
  @Override
  public TextRange surroundStatements(
      Project project, Editor editor, PsiElement container, PsiElement[] statements)
      throws IncorrectOperationException {
    PsiManager manager = PsiManager.getInstance(project);
    PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);

    statements = SurroundWithUtil.moveDeclarationsOut(container, statements, false);
    if (statements.length == 0) {
      return null;
    }

    @NonNls String text = "try{\n}finally{\n\n}";
    PsiTryStatement tryStatement = (PsiTryStatement) factory.createStatementFromText(text, null);
    tryStatement = (PsiTryStatement) codeStyleManager.reformat(tryStatement);

    tryStatement =
        (PsiTryStatement) container.addAfter(tryStatement, statements[statements.length - 1]);

    PsiCodeBlock tryBlock = tryStatement.getTryBlock();
    if (tryBlock == null) {
      return null;
    }
    SurroundWithUtil.indentCommentIfNecessary(tryBlock, statements);
    tryBlock.addRange(statements[0], statements[statements.length - 1]);
    container.deleteChildRange(statements[0], statements[statements.length - 1]);

    PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
    if (finallyBlock == null) {
      return null;
    }
    int offset = finallyBlock.getTextRange().getStartOffset() + 2;
    editor.getCaretModel().moveToOffset(offset);
    final Document document = editor.getDocument();
    PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
    editor.getSelectionModel().removeSelection();
    final PsiStatement firstTryStmt = tryBlock.getStatements()[0];
    final int indent =
        firstTryStmt.getTextOffset()
            - document.getLineStartOffset(document.getLineNumber(firstTryStmt.getTextOffset()));
    EditorModificationUtil.insertStringAtCaret(editor, StringUtil.repeat(" ", indent), false, true);
    return new TextRange(editor.getCaretModel().getOffset(), editor.getCaretModel().getOffset());
  }
  @Override
  public void handleInsert(InsertionContext context) {
    myImportFixer.handleInsert(context, this);

    PsiElement position = context.getFile().findElementAt(context.getStartOffset());
    if (position != null) {
      int genericsStart = context.getTailOffset();
      context
          .getDocument()
          .insertString(
              genericsStart,
              JavaCompletionUtil.escapeXmlIfNeeded(context, calcGenerics(position, context)));
      JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1);
    }

    int tail = context.getTailOffset();
    String braces = StringUtil.repeat("[]", getBracketsCount());
    Editor editor = context.getEditor();
    if (!braces.isEmpty()) {
      if (myAddArrayInitializer) {
        context.getDocument().insertString(tail, braces + "{}");
        editor.getCaretModel().moveToOffset(tail + braces.length() + 1);
      } else {
        context.getDocument().insertString(tail, braces);
        editor.getCaretModel().moveToOffset(tail + 1);
        if (context.getCompletionChar() == '[') {
          context.setAddCompletionChar(false);
        }
      }
    } else {
      editor.getCaretModel().moveToOffset(tail);
    }
    editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);

    InsertHandler handler = getInsertHandler();
    if (handler != null) {
      //noinspection unchecked
      handler.handleInsert(context, this);
    }
  }
 @NotNull
 public String getPresentableText(@NotNull String myName) {
   final StringBuilder sb = new StringBuilder(getQualifiedName(myName, myPath, myImportElement));
   PsiElement parent = null;
   if (myImportElement != null) {
     parent = myImportElement.getParent();
   }
   if (myImportable instanceof PyFunction) {
     sb.append(((PyFunction) myImportable).getParameterList().getPresentableText(false));
   } else if (myImportable instanceof PyClass) {
     final List<String> supers =
         ContainerUtil.mapNotNull(
             ((PyClass) myImportable).getSuperClasses(),
             new Function<PyClass, String>() {
               @Override
               public String fun(PyClass cls) {
                 return PyUtil.isObjectClass(cls) ? null : cls.getName();
               }
             });
     if (!supers.isEmpty()) {
       sb.append("(");
       StringUtil.join(supers, ", ", sb);
       sb.append(")");
     }
   }
   if (parent instanceof PyFromImportStatement) {
     sb.append(" from ");
     final PyFromImportStatement fromImportStatement = (PyFromImportStatement) parent;
     sb.append(StringUtil.repeat(".", fromImportStatement.getRelativeLevel()));
     final PyReferenceExpression source = fromImportStatement.getImportSource();
     if (source != null) {
       sb.append(source.getReferencedName());
     }
   }
   return sb.toString();
 }
/** Git revision number */
public class GitRevisionNumber implements ShortVcsRevisionNumber {
  /** the hash from 40 zeros representing not yet created commit */
  public static final String NOT_COMMITTED_HASH = StringUtil.repeat("0", 40);

  /**
   * the revision number (40 character hashcode, tag, or reference). In some cases incomplete
   * hashcode could be used.
   */
  @NotNull private final String myRevisionHash;
  /** the date when revision created */
  @NotNull private final Date myTimestamp;

  private static final Logger LOG = Logger.getInstance(GitRevisionNumber.class);

  /**
   * A constructor from version. The current date is used.
   *
   * @param version the version number.
   */
  public GitRevisionNumber(@NonNls @NotNull String version) {
    // TODO review usages
    myRevisionHash = version;
    myTimestamp = new Date();
  }

  /**
   * A constructor from version and time
   *
   * @param version the version number
   * @param timeStamp the time when the version has been created
   */
  public GitRevisionNumber(@NotNull String version, @NotNull Date timeStamp) {
    myTimestamp = timeStamp;
    myRevisionHash = version;
  }

  @NotNull
  public String asString() {
    return myRevisionHash;
  }

  @Override
  public String toShortString() {
    return asString().substring(0, 7);
  }

  /** @return revision time */
  @NotNull
  public Date getTimestamp() {
    return myTimestamp;
  }

  /** @return revision number */
  @NotNull
  public String getRev() {
    return myRevisionHash;
  }

  /**
   * @return the short revision number. The revision number likely unambiguously identify local
   *     revision, however in rare cases there could be conflicts.
   */
  @NotNull
  public String getShortRev() {
    return DvcsUtil.getShortHash(myRevisionHash);
  }

  /** {@inheritDoc} */
  public int compareTo(VcsRevisionNumber crev) {
    if (this == crev) return 0;

    if (crev instanceof GitRevisionNumber) {
      GitRevisionNumber other = (GitRevisionNumber) crev;
      if ((other.myRevisionHash != null) && myRevisionHash.equals(other.myRevisionHash)) {
        return 0;
      }

      if ((other.myRevisionHash.indexOf("[") > 0) && (other.myTimestamp != null)) {
        return myTimestamp.compareTo(other.myTimestamp);
      }

      // check for parent revs
      String otherName = null;
      String thisName = null;
      int otherParents = -1;
      int thisParent = -1;

      if (other.myRevisionHash.contains("~")) {
        int tildeIndex = other.myRevisionHash.indexOf('~');
        otherName = other.myRevisionHash.substring(0, tildeIndex);
        otherParents = Integer.parseInt(other.myRevisionHash.substring(tildeIndex));
      }

      if (myRevisionHash.contains("~")) {
        int tildeIndex = myRevisionHash.indexOf('~');
        thisName = myRevisionHash.substring(0, tildeIndex);
        thisParent = Integer.parseInt(myRevisionHash.substring(tildeIndex));
      }

      if (otherName == null && thisName == null) {
        final int result = myTimestamp.compareTo(other.myTimestamp);
        if (result == 0) {
          // it can NOT be 0 - it would mean that revisions are equal but they have different hash
          // codes
          // but this is NOT correct. but we don't know here how to sort
          return myRevisionHash.compareTo(other.myRevisionHash);
        }
        return result;
      } else if (otherName == null) {
        return 1; // I am an ancestor of the compared revision
      } else if (thisName == null) {
        return -1; // the compared revision is my ancestor
      } else {
        return thisParent - otherParents; // higher relative rev numbers are older ancestors
      }
    }

    return -1;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) return true;
    if ((obj == null) || (obj.getClass() != getClass())) return false;

    GitRevisionNumber test = (GitRevisionNumber) obj;
    // TODO normalize revision string?
    return myRevisionHash.equals(test.myRevisionHash);
  }

  @Override
  public int hashCode() {
    return myRevisionHash.hashCode();
  }

  /**
   * @return a revision string that refers to the parent revision relatively to the current one. The
   *     git operator "~" is used. Note that in case of merges, the first revision of several will
   *     referred.
   */
  public String getParentRevisionStr() {
    String rev = myRevisionHash;
    int bracketIdx = rev.indexOf("[");
    if (bracketIdx > 0) {
      rev = myRevisionHash.substring(bracketIdx + 1, myRevisionHash.indexOf("]"));
    }

    int tildeIndex = rev.indexOf("~");
    if (tildeIndex > 0) {
      int n = Integer.parseInt(rev.substring(tildeIndex)) + 1;
      return rev.substring(0, tildeIndex) + "~" + n;
    }
    return rev + "~1";
  }

  /**
   * Resolve revision number for the specified revision
   *
   * @param project a project
   * @param vcsRoot a vcs root
   * @param rev a revision expression
   * @return a resolved revision number with correct time
   * @throws VcsException if there is a problem with running git
   */
  public static GitRevisionNumber resolve(Project project, VirtualFile vcsRoot, @NonNls String rev)
      throws VcsException {
    GitSimpleHandler h = new GitSimpleHandler(project, vcsRoot, GitCommand.REV_LIST);
    h.setSilent(true);
    h.addParameters("--timestamp", "--max-count=1", rev);
    h.endOptions();
    final String output = h.run();
    return parseRevlistOutputAsRevisionNumber(h, output);
  }

  @NotNull
  public static GitRevisionNumber parseRevlistOutputAsRevisionNumber(
      @NotNull GitSimpleHandler h, @NotNull String output) throws VcsException {
    try {
      StringTokenizer tokenizer = new StringTokenizer(output, "\n\r \t", false);
      LOG.assertTrue(tokenizer.hasMoreTokens(), "No required tokens in the output: \n" + output);
      Date timestamp = GitUtil.parseTimestampWithNFEReport(tokenizer.nextToken(), h, output);
      return new GitRevisionNumber(tokenizer.nextToken(), timestamp);
    } catch (Exception e) {
      throw new VcsException("Couldn't parse the output: [" + output + "]", e);
    }
  }

  @Override
  public String toString() {
    return myRevisionHash;
  }
}
    @SuppressWarnings("AssignmentToForLoopParameter")
    @Override
    public void replace(
        @NotNull ArrangementEntryWrapper<E> newWrapper,
        @NotNull ArrangementEntryWrapper<E> oldWrapper,
        @Nullable ArrangementEntryWrapper<E> previous,
        @NotNull Context<E> context) {
      // Calculate blank lines before the arrangement.
      int blankLinesBefore = oldWrapper.getBlankLinesBefore();

      ArrangementEntryWrapper<E> parentWrapper = oldWrapper.getParent();
      int desiredBlankLinesNumber =
          context.rearranger.getBlankLines(
              context.settings,
              parentWrapper == null ? null : parentWrapper.getEntry(),
              previous == null ? null : previous.getEntry(),
              newWrapper.getEntry());
      if ((desiredBlankLinesNumber < 0 || desiredBlankLinesNumber == blankLinesBefore)
          && newWrapper.equals(oldWrapper)) {
        return;
      }

      int lineFeedsDiff = desiredBlankLinesNumber - blankLinesBefore;
      int insertionOffset = oldWrapper.getStartOffset();
      if (oldWrapper.getStartOffset() > newWrapper.getStartOffset()) {
        insertionOffset -= newWrapper.getEndOffset() - newWrapper.getStartOffset();
      }
      if (newWrapper.getStartOffset() != oldWrapper.getStartOffset()
          || !newWrapper.equals(oldWrapper)) {
        context.addMoveInfo(
            newWrapper.getStartOffset(), newWrapper.getEndOffset(), oldWrapper.getStartOffset());
        myDocument.moveText(
            newWrapper.getStartOffset(), newWrapper.getEndOffset(), oldWrapper.getStartOffset());
        for (int i = myWrappers.size() - 1; i >= 0; i--) {
          ArrangementEntryWrapper<E> w = myWrappers.get(i);
          if (w == newWrapper) {
            continue;
          }
          if (w.getStartOffset() >= oldWrapper.getStartOffset()
              && w.getStartOffset() < newWrapper.getStartOffset()) {
            w.applyShift(newWrapper.getEndOffset() - newWrapper.getStartOffset());
          } else if (w.getStartOffset() < oldWrapper.getStartOffset()
              && w.getStartOffset() > newWrapper.getStartOffset()) {
            w.applyShift(newWrapper.getStartOffset() - newWrapper.getEndOffset());
          }
        }
      }

      if (desiredBlankLinesNumber >= 0 && lineFeedsDiff > 0) {
        myDocument.insertString(insertionOffset, StringUtil.repeat("\n", lineFeedsDiff));
        shiftOffsets(lineFeedsDiff, insertionOffset);
      }

      if (desiredBlankLinesNumber >= 0 && lineFeedsDiff < 0) {
        // Cut exceeding blank lines.
        int replacementStartOffset = getBlankLineOffset(-lineFeedsDiff, insertionOffset);
        myDocument.deleteString(replacementStartOffset, insertionOffset);
        shiftOffsets(replacementStartOffset - insertionOffset, insertionOffset);
      }

      // Update wrapper ranges.
      if (desiredBlankLinesNumber < 0 || lineFeedsDiff == 0 || parentWrapper == null) {
        return;
      }

      Deque<ArrangementEntryWrapper<E>> parents = new ArrayDeque<ArrangementEntryWrapper<E>>();
      do {
        parents.add(parentWrapper);
        parentWrapper.setEndOffset(parentWrapper.getEndOffset() + lineFeedsDiff);
        parentWrapper = parentWrapper.getParent();
      } while (parentWrapper != null);

      while (!parents.isEmpty()) {
        for (ArrangementEntryWrapper<E> wrapper = parents.removeLast().getNext();
            wrapper != null;
            wrapper = wrapper.getNext()) {
          wrapper.applyShift(lineFeedsDiff);
        }
      }
    }
    @SuppressWarnings("AssignmentToForLoopParameter")
    @Override
    public void replace(
        @NotNull ArrangementEntryWrapper<E> newWrapper,
        @NotNull ArrangementEntryWrapper<E> oldWrapper,
        @Nullable ArrangementEntryWrapper<E> previous,
        @NotNull Context<E> context) {
      // Calculate blank lines before the arrangement.
      int blankLinesBefore = 0;
      TIntArrayList lineFeedOffsets = new TIntArrayList();
      int oldStartLine = context.document.getLineNumber(oldWrapper.getStartOffset());
      if (oldStartLine > 0) {
        int lastLineFeed = context.document.getLineStartOffset(oldStartLine) - 1;
        lineFeedOffsets.add(lastLineFeed);
        for (int i = lastLineFeed - 1 - myParentShift; i >= 0; i--) {
          i = CharArrayUtil.shiftBackward(myParentText, i, " \t");
          if (myParentText.charAt(i) == '\n') {
            blankLinesBefore++;
            lineFeedOffsets.add(i + myParentShift);
          } else {
            break;
          }
        }
      }

      ArrangementEntryWrapper<E> parentWrapper = oldWrapper.getParent();
      int desiredBlankLinesNumber =
          context.rearranger.getBlankLines(
              context.settings,
              parentWrapper == null ? null : parentWrapper.getEntry(),
              previous == null ? null : previous.getEntry(),
              newWrapper.getEntry());
      if (desiredBlankLinesNumber == blankLinesBefore && newWrapper.equals(oldWrapper)) {
        return;
      }

      String newEntryText =
          myParentText.substring(
              newWrapper.getStartOffset() - myParentShift,
              newWrapper.getEndOffset() - myParentShift);
      int lineFeedsDiff = desiredBlankLinesNumber - blankLinesBefore;
      if (lineFeedsDiff == 0 || desiredBlankLinesNumber < 0) {
        context.addMoveInfo(
            newWrapper.getStartOffset() - myParentShift,
            newWrapper.getEndOffset() - myParentShift,
            oldWrapper.getStartOffset());
        context.document.replaceString(
            oldWrapper.getStartOffset(), oldWrapper.getEndOffset(), newEntryText);
        return;
      }

      if (lineFeedsDiff > 0) {
        // Insert necessary number of blank lines.
        StringBuilder buffer = new StringBuilder(StringUtil.repeat("\n", lineFeedsDiff));
        buffer.append(newEntryText);
        context.document.replaceString(
            oldWrapper.getStartOffset(), oldWrapper.getEndOffset(), buffer);
      } else {
        // Cut exceeding blank lines.
        int replacementStartOffset = lineFeedOffsets.get(-lineFeedsDiff) + 1;
        context.document.replaceString(
            replacementStartOffset, oldWrapper.getEndOffset(), newEntryText);
      }

      // Update wrapper ranges.
      ArrangementEntryWrapper<E> parent = oldWrapper.getParent();
      if (parent == null) {
        return;
      }

      Deque<ArrangementEntryWrapper<E>> parents = new ArrayDeque<ArrangementEntryWrapper<E>>();
      do {
        parents.add(parent);
        parent.setEndOffset(parent.getEndOffset() + lineFeedsDiff);
        parent = parent.getParent();
      } while (parent != null);

      while (!parents.isEmpty()) {

        for (ArrangementEntryWrapper<E> wrapper = parents.removeLast().getNext();
            wrapper != null;
            wrapper = wrapper.getNext()) {
          wrapper.applyShift(lineFeedsDiff);
        }
      }
    }