From 36a0edbdbc2ae34c355fcda0126f610d0691cdab Mon Sep 17 00:00:00 2001 From: Kuba3105 Date: Wed, 6 Nov 2024 10:24:58 +0100 Subject: [PATCH] Revert of fix for classes and inner class --- .../DefaultJavaFoldingStructureProvider.java | 504 ++++++++---------- 1 file changed, 217 insertions(+), 287 deletions(-) diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/folding/DefaultJavaFoldingStructureProvider.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/folding/DefaultJavaFoldingStructureProvider.java index c907bf2ab6f..e82c17f38c5 100755 --- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/folding/DefaultJavaFoldingStructureProvider.java +++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/ui/text/folding/DefaultJavaFoldingStructureProvider.java @@ -79,7 +79,6 @@ import org.eclipse.jdt.core.dom.DoStatement; import org.eclipse.jdt.core.dom.EnhancedForStatement; import org.eclipse.jdt.core.dom.EnumDeclaration; -import org.eclipse.jdt.core.dom.FieldDeclaration; import org.eclipse.jdt.core.dom.ForStatement; import org.eclipse.jdt.core.dom.IfStatement; import org.eclipse.jdt.core.dom.Initializer; @@ -87,10 +86,10 @@ import org.eclipse.jdt.core.dom.LambdaExpression; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.Statement; +import org.eclipse.jdt.core.dom.SwitchCase; import org.eclipse.jdt.core.dom.SwitchStatement; import org.eclipse.jdt.core.dom.SynchronizedStatement; import org.eclipse.jdt.core.dom.TryStatement; -import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.WhileStatement; import org.eclipse.jdt.ui.PreferenceConstants; @@ -99,7 +98,6 @@ import org.eclipse.jdt.internal.ui.actions.SelectionConverter; import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; -import org.eclipse.jdt.internal.ui.text.DocumentCharacterIterator; /** * Updates the projection model of a class file or compilation unit. @@ -331,6 +329,164 @@ private static final class Tuple { } } + private class FoldingVisitor extends ASTVisitor { + + private FoldingStructureComputationContext ctx; + + public FoldingVisitor(FoldingStructureComputationContext ctx) { + this.ctx = ctx; + } + + @Override + public boolean visit(MethodDeclaration node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + if (node.getJavadoc() != null) { + int start = node.getStartPosition(); + int length = node.getLength(); + + IRegion region = new Region(start, length); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null) { + Position position = createCommentPosition(aligned); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseJavadoc(), null, true); + ctx.addProjectionRange(annotation, position); + } + } + return true; + } + + @Override + public boolean visit(IfStatement node) { + processIfStatement(node, ctx); + return false; + } + + @Override + public boolean visit(WhileStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(ForStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(EnhancedForStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(DoStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(TryStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + processStatement(node.getBody(), ctx); + for (Object catchClauseObj : node.catchClauses()) { + CatchClause catchClause = (CatchClause) catchClauseObj; + createFoldingRegion(catchClause, ctx, ctx.collapseMembers()); + processStatement(catchClause.getBody(), ctx); + } + if (node.getFinally() != null) { + createFoldingRegion(node.getFinally(), ctx, ctx.collapseMembers()); + processStatement(node.getFinally(), ctx); + } + return true; + } + + @Override + public boolean visit(SwitchStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + + List statements = node.statements(); + int statementsSize = statements.size(); + + for (int i = 0; i < statementsSize; i++) { + Statement stmt = (Statement) statements.get(i); + + if (stmt instanceof SwitchCase) { + int start = stmt.getStartPosition(); + int end = start; + int j = i + 1; + while (j < statementsSize && !(statements.get(j) instanceof SwitchCase)) { + Statement nextStmt = (Statement) statements.get(j); + end = nextStmt.getStartPosition() + nextStmt.getLength(); + j++; + } + + if (end > start) { + IRegion region = new Region(start, end - start); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && aligned.getLength() > 0) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseMembers(), null, false); + ctx.addProjectionRange(annotation, position); + } + } + } + } + return true; + } + + + @Override + public boolean visit(SynchronizedStatement node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(LambdaExpression node) { + if (node.getBody() instanceof Block) { + createFoldingRegion(node.getBody(), ctx, ctx.collapseMembers()); + } + return true; + } + + @Override + public boolean visit(AnonymousClassDeclaration node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(EnumDeclaration node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(Initializer node) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + return true; + } + + @Override + public boolean visit(Javadoc node) { + int start = node.getStartPosition(); + int length = node.getLength(); + + IRegion region = new Region(start, length); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null) { + Position position = createCommentPosition(aligned); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseJavadoc(), null, true); + ctx.addProjectionRange(annotation, position); + } + return false; + } + } + /** * Filter for annotations. */ @@ -445,7 +601,6 @@ private boolean shouldIgnoreDelta(CompilationUnit ast, IJavaElementDelta delta) IJavaElement elem= SelectionConverter.getElementAtOffset(ast.getTypeRoot(), new TextSelection(editor.getCachedSelectedRange().x, editor.getCachedSelectedRange().y)); if (!(elem instanceof IImportDeclaration)) return false; - } } catch (JavaModelException e) { return false; // can't compute @@ -492,87 +647,6 @@ private IJavaElementDelta findElement(IJavaElement target, IJavaElementDelta del } } - /** - * Projection position that will return two foldable regions: one folding away - * the region from after the '/**' to the beginning of the content, the other - * from after the first content line until after the comment. - */ - private static final class CommentPosition extends Position implements IProjectionPosition { - CommentPosition(int offset, int length) { - super(offset, length); - } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeFoldingRegions(org.eclipse.jface.text.IDocument) - */ - @Override - public IRegion[] computeProjectionRegions(IDocument document) throws BadLocationException { - DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length); - int prefixEnd= 0; - int contentStart= findFirstContent(sequence, prefixEnd); - - int firstLine= document.getLineOfOffset(offset + prefixEnd); - int captionLine= document.getLineOfOffset(offset + contentStart); - int lastLine= document.getLineOfOffset(offset + length); - - Assert.isTrue(firstLine <= captionLine, "first folded line is greater than the caption line"); //$NON-NLS-1$ - Assert.isTrue(captionLine <= lastLine, "caption line is greater than the last folded line"); //$NON-NLS-1$ - - IRegion preRegion; - if (firstLine < captionLine) { - int preOffset= document.getLineOffset(firstLine); - IRegion preEndLineInfo= document.getLineInformation(captionLine); - int preEnd= preEndLineInfo.getOffset(); - preRegion= new Region(preOffset, preEnd - preOffset); - } else { - preRegion= null; - } - - if (captionLine < lastLine) { - int postOffset= document.getLineOffset(captionLine + 1); - int postLength= offset + length - postOffset; - if (postLength > 0) { - IRegion postRegion= new Region(postOffset, postLength); - if (preRegion == null) - return new IRegion[] { postRegion }; - return new IRegion[] { preRegion, postRegion }; - } - } - - if (preRegion != null) - return new IRegion[] { preRegion }; - - return null; - } - - /** - * Finds the offset of the first identifier part within content. - * Returns 0 if none is found. - * - * @param content the content to search - * @param prefixEnd the end of the prefix - * @return the first index of a unicode identifier part, or zero if none can - * be found - */ - private int findFirstContent(final CharSequence content, int prefixEnd) { - int lenght= content.length(); - for (int i= prefixEnd; i < lenght; i++) { - if (Character.isUnicodeIdentifierPart(content.charAt(i))) - return i; - } - return 0; - } - - /* - * @see org.eclipse.jface.text.source.projection.IProjectionPosition#computeCaptionOffset(org.eclipse.jface.text.IDocument) - */ - @Override - public int computeCaptionOffset(IDocument document) throws BadLocationException { - DocumentCharacterIterator sequence= new DocumentCharacterIterator(document, offset, offset + length); - return findFirstContent(sequence, 0); - } - } - /** * Projection position that will return two foldable regions: one folding away * the lines before the one containing the simple name of the java element, one @@ -645,10 +719,8 @@ public IRegion[] computeProjectionRegions(IDocument document) throws BadLocation return new IRegion[] { preRegion, postRegion }; } } - if (preRegion != null) return new IRegion[] { preRegion }; - return null; } @@ -666,7 +738,6 @@ public int computeCaptionOffset(IDocument document) throws BadLocationException } catch (JavaModelException e) { // ignore and use default } - return nameStart - offset; } @@ -867,7 +938,6 @@ private FoldingStructureComputationContext createInitialContext() { fInput= getInputElement(); if (fInput == null) return null; - return createContext(true); } @@ -884,7 +954,6 @@ private FoldingStructureComputationContext createContext(boolean allowCollapse) IScanner scanner= null; if (fUpdatingCount == 1) scanner= fSharedScanner; // reuse scanner - return new FoldingStructureComputationContext(doc, model, allowCollapse, scanner); } @@ -995,129 +1064,24 @@ private void computeFoldingStructure(FoldingStructureComputationContext ctx) { private void processCompilationUnit(ICompilationUnit unit, FoldingStructureComputationContext ctx) { try { String source = unit.getSource(); - if (source == null) { - return; - } + if (source == null) return; ctx.getScanner().setSource(source.toCharArray()); - ASTParser parser = ASTParser.newParser(AST.getJLSLatest()); parser.setSource(unit); parser.setResolveBindings(true); CompilationUnit ast = (CompilationUnit) parser.createAST(null); - - ast.accept(new ASTVisitor() { - @Override - public boolean visit(MethodDeclaration node) { - processMethodDeclaration(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(FieldDeclaration node) { - processFieldDeclaration(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(IfStatement node) { - processIfStatement(node, ctx); - return false; // Prevents visiting children since we handle them explicitly - } - - @Override - public boolean visit(WhileStatement node) { - processStatement(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(ForStatement node) { - processStatement(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(EnhancedForStatement node) { - processStatement(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(DoStatement node) { - processStatement(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(SwitchStatement node) { - processStatement(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(TryStatement node) { - processTryStatement(node, ctx); - return false; // We handle the catch and finally blocks explicitly - } - - @Override - public boolean visit(SynchronizedStatement node) { - processStatement(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(LambdaExpression node) { - processLambdaExpression(node, ctx); - return false; // Prevents visiting children since we handle them explicitly - } - - @Override - public boolean visit(TypeDeclaration node) { - processTypeDeclaration(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(AnonymousClassDeclaration node) { - processAnonymousClassDeclaration(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(EnumDeclaration node) { - processEnumDeclaration(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(Initializer node) { - processInitializer(node, ctx); - return super.visit(node); - } - - @Override - public boolean visit(Javadoc node) { - processComment(node, ctx); - return false; // No need to visit children of Javadoc - } - - }); + ast.accept(new FoldingVisitor(ctx)); } catch (JavaModelException e) { - e.printStackTrace(); } } private void processSourceReference(ISourceReference sourceRef, FoldingStructureComputationContext ctx) { try { String source = sourceRef.getSource(); - if (source == null) { - return; - } + if (source == null) return; ctx.getScanner().setSource(source.toCharArray()); - if (fInput instanceof IParent) { IParent parent = (IParent) fInput; computeFoldingStructure(parent.getChildren(), ctx); @@ -1125,48 +1089,13 @@ private void processSourceReference(ISourceReference sourceRef, FoldingStructure computeFoldingStructure(fInput, ctx); } } catch (JavaModelException e) { - e.printStackTrace(); } } - private void processMethodDeclaration(MethodDeclaration node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); - if (node.getJavadoc() != null) { - processComment(node.getJavadoc(), ctx); - } - } - - private void processFieldDeclaration(FieldDeclaration node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); - if (node.getJavadoc() != null) { - processComment(node.getJavadoc(), ctx); - } - } - - private void processTypeDeclaration(TypeDeclaration node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); - if (node.getJavadoc() != null) { - processComment(node.getJavadoc(), ctx); - } - } - - private void processAnonymousClassDeclaration(AnonymousClassDeclaration node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); - } - - private void processEnumDeclaration(EnumDeclaration node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); - if (node.getJavadoc() != null) { - processComment(node.getJavadoc(), ctx); - } - } - - private void processInitializer(Initializer node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); - } - private void processIfStatement(IfStatement node, FoldingStructureComputationContext ctx) { - createFoldingRegion(node, ctx, ctx.collapseMembers()); + if (node.getThenStatement() instanceof Block || node.getElseStatement() != null) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + } processStatement(node.getThenStatement(), ctx); Statement elseStmt = node.getElseStatement(); if (elseStmt != null) { @@ -1174,6 +1103,7 @@ private void processIfStatement(IfStatement node, FoldingStructureComputationCon } } + private void processElseStatement(Statement elseStmt, FoldingStructureComputationContext ctx) { if (elseStmt instanceof IfStatement) { processIfStatement((IfStatement) elseStmt, ctx); @@ -1183,38 +1113,33 @@ private void processElseStatement(Statement elseStmt, FoldingStructureComputatio } } - - private void processTryStatement(TryStatement node, FoldingStructureComputationContext ctx) { - processStatement(node.getBody(), ctx); - for (Object catchClauseObj : node.catchClauses()) { - CatchClause catchClause = (CatchClause) catchClauseObj; - processStatement(catchClause.getBody(), ctx); - } - if (node.getFinally() != null) { - processStatement(node.getFinally(), ctx); - } - } - - private void processLambdaExpression(LambdaExpression node, FoldingStructureComputationContext ctx) { - if (node.getBody() instanceof Block) { - createFoldingRegion(node.getBody(), ctx, ctx.collapseMembers()); - } - } - private void processStatement(Statement node, FoldingStructureComputationContext ctx) { if (node == null) { return; } - createFoldingRegion(node, ctx, ctx.collapseMembers()); + if (node instanceof Block || node instanceof IfStatement || node instanceof WhileStatement || + node instanceof ForStatement || node instanceof EnhancedForStatement || + node instanceof DoStatement || node instanceof SwitchStatement || + node instanceof TryStatement || node instanceof SynchronizedStatement) { + createFoldingRegion(node, ctx, ctx.collapseMembers()); + } + node.accept(new FoldingVisitor(ctx)); } + private void createFoldingRegion(ASTNode node, FoldingStructureComputationContext ctx, boolean collapse) { int start = node.getStartPosition(); - int end = calculateEndPosition(node, ctx); + int end = calculateEndPosition(node); if (end <= start) { return; } + if (node instanceof MethodDeclaration) { + Block body = ((MethodDeclaration) node).getBody(); + if (body != null) { + start = body.getStartPosition(); + } + } int length = end - start; IRegion region = new Region(start, length); @@ -1227,27 +1152,39 @@ private void createFoldingRegion(ASTNode node, FoldingStructureComputationContex } } - private int calculateEndPosition(ASTNode node, FoldingStructureComputationContext ctx) { - int end = node.getStartPosition() + node.getLength(); - try { - IDocument document = ctx.getDocument(); - int endLine = document.getLineOfOffset(end - 1); - int lineEndOffset = document.getLineOffset(endLine) + document.getLineLength(endLine); - - if (end < lineEndOffset) { - String remainingText = document.get(end, lineEndOffset - end).trim(); - if (!remainingText.isEmpty()) { - // Additional logic if needed - } - } - } catch (BadLocationException e) { - e.printStackTrace(); + private int calculateEndPosition(ASTNode node) { + int end = node.getStartPosition() + node.getLength(); + if (node instanceof IfStatement) { + IfStatement ifStmt = (IfStatement) node; + int thenEnd = getEndPosition(ifStmt.getThenStatement()); + int elseEnd = ifStmt.getElseStatement() != null ? getEndPosition(ifStmt.getElseStatement()) : -1; + end = Math.max(end, Math.max(thenEnd, elseEnd)); } - return end; } + private int getEndPosition(ASTNode node) { + if (node == null) { + return -1; + } + return node.getStartPosition() + node.getLength(); + } + + + /** + * Aligns region to start and end at a line offset. The region's start is + * decreased to the next line offset, and the end offset increased to the next line start or the + * end of the document. null is returned if region is + * null itself or does not comprise at least one line delimiter, as a single line + * cannot be folded. + * + * @param region the region to align, may be null + * @param ctx the folding context + * @return a region equal or greater than region that is aligned with line + * offsets, null if the region is too small to be foldable (e.g. covers + * only one line) + */ protected IRegion alignRegion(IRegion region, FoldingStructureComputationContext ctx) { if (region == null) { return null; @@ -1275,20 +1212,14 @@ protected IRegion alignRegion(IRegion region, FoldingStructureComputationContext } } - private void processComment(Javadoc node, FoldingStructureComputationContext ctx) { - int start = node.getStartPosition(); - int length = node.getLength(); - - IRegion region = new Region(start, length); - IRegion aligned = alignRegion(region, ctx); - - if (aligned != null) { - Position position = createCommentPosition(aligned); - JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseJavadoc(), null, true); - ctx.addProjectionRange(annotation, position); - } - } - + /** + * Creates a comment folding position from an + * {@link #alignRegion(IRegion, DefaultJavaFoldingStructureProvider.FoldingStructureComputationContext) aligned} + * region. + * + * @param aligned an aligned region + * @return a folding position corresponding to aligned + */ protected Position createCommentPosition(IRegion aligned) { return new Position(aligned.getOffset(), aligned.getLength()); } @@ -1468,7 +1399,6 @@ protected final IRegion[] computeProjectionRanges(ISourceReference reference, Fo return result; } catch (JavaModelException | InvalidInputException e) { } - return new IRegion[0]; }