@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); } }
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(" ", 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); } } }