private static void collapseBlock(List<FoldingDescriptor> descriptors, PsiElement psi) { if (psi instanceof GrCodeBlock) { final int lineFeedCount = StringUtil.countChars(psi.getText(), '\n'); if (lineFeedCount <= 2) { final PsiElement lbrace = ((GrCodeBlock)psi).getLBrace(); final PsiElement rbrace = ((GrCodeBlock)psi).getRBrace(); if (lbrace != null && rbrace != null) { final PsiElement next = lbrace.getNextSibling(); final PsiElement prev = rbrace.getPrevSibling(); if (next != null && PsiImplUtil.isWhiteSpaceOrNls(next) && prev != null && PsiImplUtil.isWhiteSpaceOrNls(prev)) { final FoldingGroup group = FoldingGroup.newGroup("block_group"); descriptors.add(new NamedFoldingDescriptor(psi, lbrace.getTextRange().getStartOffset(), next.getTextRange().getEndOffset(), group, "{")); descriptors.add(new NamedFoldingDescriptor(psi, prev.getTextRange().getStartOffset(), rbrace.getTextRange().getEndOffset(), group, "}")); return; } } } } descriptors.add(new FoldingDescriptor(psi, psi.getTextRange())); }
private boolean addClosureFolding(@NotNull PsiClass aClass, @NotNull Document document, @NotNull List<FoldingDescriptor> foldElements, @NotNull Set<PsiElement> processedComments, boolean quick) { if(!JavaCodeFoldingSettings.getInstance().isCollapseLambdas()) { return false; } if(aClass instanceof PsiAnonymousClass) { final PsiAnonymousClass anonymousClass = (PsiAnonymousClass) aClass; ClosureFolding closureFolding = ClosureFolding.prepare(anonymousClass, quick, this); List<NamedFoldingDescriptor> descriptors = closureFolding == null ? null : closureFolding.process(document); if(descriptors != null) { foldElements.addAll(descriptors); addCodeBlockFolds(closureFolding.methodBody, foldElements, processedComments, document, quick); return true; } } return false; }
@Nullable private List<NamedFoldingDescriptor> createDescriptors(PsiElement classRBrace, int rangeStart, int rangeEnd, String header, String footer) { if(rangeStart >= rangeEnd) { return null; } FoldingGroup group = FoldingGroup.newGroup("lambda"); List<NamedFoldingDescriptor> foldElements = new ArrayList<>(); foldElements.add(new NamedFoldingDescriptor(myNewExpression, getClosureStartOffset(), rangeStart, group, header)); if(rangeEnd + 1 < getClosureEndOffset()) { foldElements.add(new NamedFoldingDescriptor(classRBrace, rangeEnd, getClosureEndOffset(), group, footer)); } return foldElements; }
@Nullable private static <T extends PsiElement> FoldingDescriptor createNamedFoldingDescriptor(final T namedElement, boolean includeFirstElement, boolean includeLastElement, final String stringName) { final int firstChildLength = includeFirstElement ? namedElement.getFirstChild().getText().length() : 0; final int lastChildLength = includeLastElement ? namedElement.getLastChild().getText().length() : 0; TextRange range = new TextRange(namedElement.getTextRange().getStartOffset() + firstChildLength, namedElement.getTextRange().getEndOffset() - lastChildLength); return range.getLength() > 0 ? new NamedFoldingDescriptor(namedElement.getNode(), range, null, stringName != null ? stringName : "...") : null; }
@Nullable List<NamedFoldingDescriptor> process(Document document) { PsiJavaToken lbrace = methodBody.getLBrace(); PsiJavaToken rbrace = methodBody.getRBrace(); PsiElement classRBrace = myAnonymousClass.getRBrace(); if(lbrace == null || rbrace == null || classRBrace == null) { return null; } CharSequence seq = document.getCharsSequence(); int rangeStart = lbrace.getTextRange().getEndOffset(); int rangeEnd = getContentRangeEnd(document, rbrace, classRBrace); String contents = getClosureContents(rangeStart, rangeEnd, seq); if(contents == null) { return null; } String header = getFoldingHeader(); if(showSingleLineFolding(document, contents, header)) { return createDescriptors(classRBrace, trimStartSpaces(seq, rangeStart), trimTailSpaces(seq, rangeEnd), header + " ", " }"); } return createDescriptors(classRBrace, rangeStart, rangeEnd, header, "}"); }
private boolean addOneLineMethodFolding(List<FoldingDescriptor> descriptorList, PsiMethod method) { if (!JavaCodeFoldingSettings.getInstance().isCollapseOneLineMethods()) { return false; } Document document = method.getContainingFile().getViewProvider().getDocument(); PsiCodeBlock body = method.getBody(); PsiIdentifier nameIdentifier = method.getNameIdentifier(); if (body == null || document == null || nameIdentifier == null) { return false; } if (document.getLineNumber(nameIdentifier.getTextRange().getStartOffset()) != document.getLineNumber(method.getParameterList().getTextRange().getEndOffset())) { return false; } PsiJavaToken lBrace = body.getLBrace(); PsiJavaToken rBrace = body.getRBrace(); PsiStatement[] statements = body.getStatements(); if (lBrace == null || rBrace == null || statements.length != 1) { return false; } PsiStatement statement = statements[0]; if (statement.textContains('\n')) { return false; } if (!areOnAdjacentLines(lBrace, statement, document) || !areOnAdjacentLines(statement, rBrace, document)) { //the user might intend to type at an empty line return false; } int leftStart = method.getParameterList().getTextRange().getEndOffset(); int bodyStart = body.getTextRange().getStartOffset(); if (bodyStart > leftStart && !StringUtil.isEmptyOrSpaces(document.getCharsSequence().subSequence(leftStart + 1, bodyStart))) { return false; } int leftEnd = statement.getTextRange().getStartOffset(); int rightStart = statement.getTextRange().getEndOffset(); int rightEnd = body.getTextRange().getEndOffset(); if (leftEnd <= leftStart + 1 || rightEnd <= rightStart + 1) { return false; } String leftText = " { "; String rightText = " }"; if (!fitsRightMargin(method, document, leftStart, rightEnd, rightStart - leftEnd + leftText.length() + rightText.length())) { return false; } FoldingGroup group = FoldingGroup.newGroup("one-liner"); descriptorList.add(new NamedFoldingDescriptor(lBrace, leftStart, leftEnd, group, leftText)); descriptorList.add(new NamedFoldingDescriptor(rBrace, rightStart, rightEnd, group, rightText)); return true; }
@NotNull private static NamedFoldingDescriptor createFoldingDescriptor(@NotNull PsiExpression callArgument, @NotNull PsiParameter methodParam) { TextRange range = callArgument.getTextRange(); String placeholderText = methodParam.getName() + ": " + callArgument.getText(); return new NamedFoldingDescriptor(callArgument, range.getStartOffset(), range.getEndOffset(), null, placeholderText); }
private static void addFoldingForStrings(List<FoldingDescriptor> descriptors, ASTNode node) { if (!isMultiLineStringLiteral(node)) return; if (!node.getElementType().equals(GroovyElementTypes.GSTRING) && !node.getElementType().equals(GroovyElementTypes.REGEX)) { descriptors.add(new FoldingDescriptor(node, node.getTextRange())); return; } final GrString grString = (GrString)node.getPsi(); if (grString == null) return; final GrStringInjection[] injections = grString.getInjections(); if (injections.length == 0) { descriptors.add(new FoldingDescriptor(node, node.getTextRange())); return; } final String start_quote = GrStringUtil.getStartQuote(node.getText()); final String end_quote = GrStringUtil.getEndQuote(node.getText()); final FoldingGroup group = FoldingGroup.newGroup("GString"); final TextRange nodeRange = node.getTextRange(); int startOffset = nodeRange.getStartOffset(); GrStringInjection injection = injections[0]; TextRange injectionRange = injection.getTextRange(); if (startOffset + 1 < injectionRange.getStartOffset()) { descriptors.add(new NamedFoldingDescriptor(node, startOffset, injectionRange.getStartOffset(), group, start_quote)); } final String placeholder = " "; startOffset = injectionRange.getEndOffset(); for (int i = 1; i < injections.length; i++) { injection = injections[i]; injectionRange = injection.getTextRange(); final int endOffset = injectionRange.getStartOffset(); if (endOffset - startOffset >= 2) { descriptors.add(new NamedFoldingDescriptor(injection.getNode().getTreePrev(), startOffset, endOffset, group, placeholder)); } startOffset = injectionRange.getEndOffset(); } if (startOffset + 1 < nodeRange.getEndOffset()) { descriptors.add(new NamedFoldingDescriptor(node.getLastChildNode(), startOffset, nodeRange.getEndOffset(), group, end_quote)); } }
private boolean addOneLineMethodFolding(@NotNull List<FoldingDescriptor> descriptorList, @NotNull PsiMethod method) { if(!JavaCodeFoldingSettings.getInstance().isCollapseOneLineMethods()) { return false; } Document document = method.getContainingFile().getViewProvider().getDocument(); PsiCodeBlock body = method.getBody(); PsiIdentifier nameIdentifier = method.getNameIdentifier(); if(body == null || document == null || nameIdentifier == null) { return false; } if(document.getLineNumber(nameIdentifier.getTextRange().getStartOffset()) != document.getLineNumber(method.getParameterList().getTextRange().getEndOffset())) { return false; } PsiJavaToken lBrace = body.getLBrace(); PsiJavaToken rBrace = body.getRBrace(); PsiStatement[] statements = body.getStatements(); if(lBrace == null || rBrace == null || statements.length != 1) { return false; } PsiStatement statement = statements[0]; if(statement.textContains('\n')) { return false; } if(!areOnAdjacentLines(lBrace, statement, document) || !areOnAdjacentLines(statement, rBrace, document)) { //the user might intend to type at an empty line return false; } int leftStart = method.getParameterList().getTextRange().getEndOffset(); int bodyStart = body.getTextRange().getStartOffset(); if(bodyStart > leftStart && !StringUtil.isEmptyOrSpaces(document.getCharsSequence().subSequence(leftStart + 1, bodyStart))) { return false; } int leftEnd = statement.getTextRange().getStartOffset(); int rightStart = statement.getTextRange().getEndOffset(); int rightEnd = body.getTextRange().getEndOffset(); if(leftEnd <= leftStart + 1 || rightEnd <= rightStart + 1) { return false; } String leftText = " { "; String rightText = " }"; if(!fitsRightMargin(method, document, leftStart, rightEnd, rightStart - leftEnd + leftText.length() + rightText.length())) { return false; } FoldingGroup group = FoldingGroup.newGroup("one-liner"); descriptorList.add(new NamedFoldingDescriptor(lBrace, leftStart, leftEnd, group, leftText)); descriptorList.add(new NamedFoldingDescriptor(rBrace, rightStart, rightEnd, group, rightText)); return true; }