From ee3706a67a4793c6e9197eb24c88f18f7199f93e Mon Sep 17 00:00:00 2001 From: Kuba3105 Date: Wed, 6 Nov 2024 10:24:58 +0100 Subject: [PATCH] Move processComments call to be within ICompilationUnit check --- .../DefaultJavaFoldingStructureProvider.java | 823 +++++++++++------- 1 file changed, 488 insertions(+), 335 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..0937913e4fa 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,15 +79,14 @@ 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.ImportDeclaration; import org.eclipse.jdt.core.dom.Initializer; -import org.eclipse.jdt.core.dom.Javadoc; 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.SwitchStatement; +import org.eclipse.jdt.core.dom.SwitchExpression; import org.eclipse.jdt.core.dom.SynchronizedStatement; import org.eclipse.jdt.core.dom.TryStatement; import org.eclipse.jdt.core.dom.TypeDeclaration; @@ -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,389 @@ private static final class Tuple { } } + private class FoldingVisitor extends ASTVisitor { + + private FoldingStructureComputationContext ctx; + + public FoldingVisitor(FoldingStructureComputationContext ctx) { + this.ctx = ctx; + } + + @Override + public boolean visit(CompilationUnit node) { + List imports = node.imports(); + if (!imports.isEmpty()) { + int start = imports.get(0).getStartPosition(); + ImportDeclaration lastImport = imports.get(imports.size() - 1); + int end = lastImport.getStartPosition() + lastImport.getLength(); + try { + IDocument document = ctx.getDocument(); + int lastImportLine = document.getLineOfOffset(end); + if (lastImportLine + 1 < document.getNumberOfLines()) { + end = document.getLineOffset(lastImportLine + 1); + } else { + end = document.getLength(); + } + } catch (BadLocationException e) { + } + + IRegion region = new Region(start, end - start); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseImportContainer(), null, false); + ctx.addProjectionRange(annotation, position); + } + } + return super.visit(node); + } + + @Override + public boolean visit(TypeDeclaration node) { + boolean isInnerClass = node.isMemberTypeDeclaration(); + + if (isInnerClass) { + int start = node.getName().getStartPosition(); + int length = (node.getStartPosition() + node.getLength()) - start; + + if (length > 0) { + IRegion region = new Region(start, length); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && isMultiline(aligned)) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseInnerTypes(), null, false); + ctx.addProjectionRange(annotation, position); + } + } + } + return true; + } + + + + @Override + public boolean visit(MethodDeclaration node) { + int start = node.getName().getStartPosition(); + int length = (node.getStartPosition() + node.getLength()) - start; + + if (length > 0) { + IRegion region = new Region(start, length); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && isMultiline(aligned)) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseMembers(), null, false); + ctx.addProjectionRange(annotation, position); + } + } + return true; + } + + private void createFoldingRegionForStatement(ASTNode node) { + int start = node.getStartPosition(); + int length = node.getLength(); + if (!(node instanceof Block)) { + try { + IDocument document = ctx.getDocument(); + int endLine = document.getLineOfOffset(start + length - 1); + if (endLine + 1 < document.getNumberOfLines()) { + String currentIndent = getIndentOfLine(document, endLine); + String nextIndent = getIndentOfLine(document, endLine + 1); + if (nextIndent.length() > currentIndent.length()) { + int nextLineEndOffset = document.getLineOffset(endLine + 2) - 1; + length = nextLineEndOffset - start; + } else { + length = document.getLineOffset(endLine + 1) - start; + } + } else { + length = document.getLength() - start; + } + } catch (BadLocationException e) { + } + } + + IRegion region = new Region(start, length); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && isMultiline(aligned)) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseMembers(), null, false); + ctx.addProjectionRange(annotation, position); + } + } + + private String getIndentOfLine(IDocument document, int line) throws BadLocationException { + IRegion region = document.getLineInformation(line); + int lineStart = region.getOffset(); + int lineLength = region.getLength(); + + int whiteSpaceEnd = lineStart; + while (whiteSpaceEnd < lineStart + lineLength) { + char c = document.getChar(whiteSpaceEnd); + if (!Character.isWhitespace(c)) { + break; + } + whiteSpaceEnd++; + } + return document.get(lineStart, whiteSpaceEnd - lineStart); + } + + @Override + public boolean visit(IfStatement node) { + createFoldingRegionForIfPart(node); + node.getThenStatement().accept(this); + if (node.getElseStatement() != null) { + if (node.getElseStatement() instanceof IfStatement) { + createFoldingRegionForElseIfPart(node.getElseStatement()); + node.getElseStatement().accept(this); + } else { + createFoldingRegionForElsePart(node); + node.getElseStatement().accept(this); + } + } + return false; + } + + private void createFoldingRegionForIfPart(IfStatement node) { + int start = node.getStartPosition(); + int end = getEndPosition(node.getThenStatement()); + createFoldingRegion(start, end, ctx.collapseMembers()); + } + + private void createFoldingRegionForElseIfPart(Statement elseIfStatement) { + int start = findElseKeywordStart(elseIfStatement); + int end = getEndPosition(((IfStatement) elseIfStatement).getThenStatement()); + createFoldingRegion(start, end, ctx.collapseMembers()); + } + + private void createFoldingRegionForElsePart(IfStatement node) { + int start = findElseKeywordStart(node.getElseStatement()); + int end = getEndPosition(node.getElseStatement()); + createFoldingRegion(start, end, ctx.collapseMembers()); + } + + private int findElseKeywordStart(ASTNode node) { + try { + IDocument document = ctx.getDocument(); + int startSearch = node.getParent().getStartPosition(); + int endSearch = node.getStartPosition(); + + String text = document.get(startSearch, endSearch - startSearch); + int index = text.lastIndexOf("else"); //$NON-NLS-1$ + if (index >= 0) { + return startSearch + index; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + return node.getStartPosition(); + } + + private int getEndPosition(Statement statement) { + if (statement instanceof Block) { + return statement.getStartPosition() + statement.getLength(); + } else { + try { + IDocument document = ctx.getDocument(); + int start = statement.getStartPosition(); + int line = document.getLineOfOffset(start); + return document.getLineOffset(line + 1); + } catch (BadLocationException e) { + e.printStackTrace(); + return statement.getStartPosition() + statement.getLength(); + } + } + } + + @Override + public boolean visit(TryStatement node) { + createFoldingRegionForTryBlock(node); + node.getBody().accept(this); + for (Object obj : node.catchClauses()) { + CatchClause catchClause = (CatchClause) obj; + createFoldingRegionForCatchClause(catchClause); + catchClause.accept(this); + } + if (node.getFinally() != null) { + createFoldingRegionForFinallyBlock(node); + node.getFinally().accept(this); + } + return false; + } + + private void createFoldingRegionForTryBlock(TryStatement node) { + int start = node.getStartPosition(); + int end = getEndPosition(node.getBody()); + + createFoldingRegion(start, end, ctx.collapseMembers()); + } + + private void createFoldingRegionForCatchClause(CatchClause catchClause) { + int start = catchClause.getStartPosition(); + int end = getEndPosition(catchClause.getBody()); + + createFoldingRegion(start, end, ctx.collapseMembers()); + } + + private void createFoldingRegionForFinallyBlock(TryStatement node) { + Block finallyBlock = node.getFinally(); + int start = findFinallyKeywordStart(node); + int end = getEndPosition(finallyBlock); + + createFoldingRegion(start, end, ctx.collapseMembers()); + } + + private int findFinallyKeywordStart(TryStatement node) { + try { + IDocument document = ctx.getDocument(); + int startSearch = node.getStartPosition(); + int endSearch = node.getFinally().getStartPosition(); + + String text = document.get(startSearch, endSearch - startSearch); + int index = text.lastIndexOf("finally"); //$NON-NLS-1$ + if (index >= 0) { + return startSearch + index; + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + return node.getFinally().getStartPosition(); + } + + private void createFoldingRegion(int start, int end, boolean collapse) { + if (end > start) { + IRegion region = new Region(start, end - start); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && isMultiline(aligned)) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(collapse, null, false); + ctx.addProjectionRange(annotation, position); + } + } + } + + @Override + public boolean visit(WhileStatement node) { + createFoldingRegionForStatement(node); + node.getBody().accept(this); + return false; + } + + @Override + public boolean visit(ForStatement node) { + createFoldingRegionForStatement(node); + node.getBody().accept(this); + return false; + } + + @Override + public boolean visit(EnhancedForStatement node) { + createFoldingRegionForStatement(node); + node.getBody().accept(this); + return false; + } + + @Override + public boolean visit(DoStatement node) { + createFoldingRegionForStatement(node); + node.getBody().accept(this); + return false; + } + + @Override + public boolean visit(SwitchExpression node) { + createFoldingRegion(node, ctx.collapseMembers(), false); + List statements = node.statements(); + for (Object stmtObj : statements) { + Statement stmt = (Statement) stmtObj; + stmt.accept(this); + } + return false; + } + + @Override + public boolean visit(SynchronizedStatement node) { + createFoldingRegion(node, ctx.collapseMembers(), false); + node.getBody().accept(this); + return false; + } + + @Override + public boolean visit(LambdaExpression node) { + if (node.getBody() instanceof Block) { + createFoldingRegion(node.getBody(), ctx.collapseMembers(), false); + node.getBody().accept(this); + } + return false; + } + + @Override + public boolean visit(AnonymousClassDeclaration node) { + createFoldingRegion(node, ctx.collapseMembers(), true); + return true; + } + + @Override + public boolean visit(EnumDeclaration node) { + createFoldingRegion(node, ctx.collapseMembers(), true); + return true; + } + + @Override + public boolean visit(Initializer node) { + createFoldingRegion(node, ctx.collapseMembers(), false); + return true; + } + + private void createFoldingRegion(ASTNode node, boolean collapse, boolean excludeLastLine) { + int start = node.getStartPosition(); + int end = node.getStartPosition() + node.getLength(); + + if (excludeLastLine) { + end = adjustEndForControlStatements(end); + } + + if (end <= start) { + return; + } + int length = end - start; + IRegion region = new Region(start, length); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && isMultiline(aligned)) { + Position position = new Position(aligned.getOffset(), aligned.getLength()); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(collapse, null, false); + ctx.addProjectionRange(annotation, position); + } + } + + + private int adjustEndForControlStatements(int originalEnd) { + try { + IDocument document = ctx.getDocument(); + int endLine = document.getLineOfOffset(originalEnd); + int endLineOffset = document.getLineOffset(endLine); + return endLineOffset; + } catch (BadLocationException e) { + return originalEnd; + } + } + + private boolean isMultiline(IRegion region) { + try { + IDocument document = ctx.getDocument(); + int startLine = document.getLineOfOffset(region.getOffset()); + int endLine = document.getLineOfOffset(region.getOffset() + region.getLength()); + return endLine > startLine; + } catch (BadLocationException e) { + return false; + } + } +} + /** * Filter for annotations. */ @@ -445,7 +826,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 +872,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 +944,8 @@ public IRegion[] computeProjectionRegions(IDocument document) throws BadLocation return new IRegion[] { preRegion, postRegion }; } } - if (preRegion != null) return new IRegion[] { preRegion }; - return null; } @@ -666,7 +963,6 @@ public int computeCaptionOffset(IDocument document) throws BadLocationException } catch (JavaModelException e) { // ignore and use default } - return nameStart - offset; } @@ -867,7 +1163,6 @@ private FoldingStructureComputationContext createInitialContext() { fInput= getInputElement(); if (fInput == null) return null; - return createContext(true); } @@ -884,7 +1179,6 @@ private FoldingStructureComputationContext createContext(boolean allowCollapse) IScanner scanner= null; if (fUpdatingCount == 1) scanner= fSharedScanner; // reuse scanner - return new FoldingStructureComputationContext(doc, model, allowCollapse, scanner); } @@ -987,6 +1281,8 @@ private void update(FoldingStructureComputationContext ctx) { private void computeFoldingStructure(FoldingStructureComputationContext ctx) { if (fInput instanceof ICompilationUnit) { processCompilationUnit((ICompilationUnit) fInput, ctx); + processComments(ctx); + } else if (fInput instanceof ISourceReference) { processSourceReference((ISourceReference) fInput, ctx); } @@ -995,259 +1291,123 @@ 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.setBindingsRecovery(true); + parser.setStatementsRecovery(true); + parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setResolveBindings(true); - CompilationUnit ast = (CompilationUnit) parser.createAST(null); + parser.setUnitName(unit.getElementName()); + parser.setProject(unit.getJavaProject()); + parser.setSource(unit); + Map options = unit.getJavaProject().getOptions(true); + options.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_23); + options.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_23); + options.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_23); + options.put(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, JavaCore.ENABLED); + parser.setCompilerOptions(options); - 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 - } - - }); - } catch (JavaModelException e) { - e.printStackTrace(); + CompilationUnit ast = (CompilationUnit) parser.createAST(null); + ast.accept(new FoldingVisitor(ctx)); + } catch (JavaModelException | IllegalStateException e) { + e.printStackTrace(); } } - private void processSourceReference(ISourceReference sourceRef, FoldingStructureComputationContext ctx) { + private void processComments(FoldingStructureComputationContext ctx) { try { - String source = sourceRef.getSource(); - if (source == null) { - return; - } - - ctx.getScanner().setSource(source.toCharArray()); - - if (fInput instanceof IParent) { - IParent parent = (IParent) fInput; - computeFoldingStructure(parent.getChildren(), ctx); - } else { - computeFoldingStructure(fInput, ctx); + IDocument document = ctx.getDocument(); + String source = document.get(); + IScanner scanner = ctx.getScanner(); + scanner.setSource(source.toCharArray()); + scanner.resetTo(0, source.length() - 1); + + int token; + while ((token = scanner.getNextToken()) != ITerminalSymbols.TokenNameEOF) { + if (token == ITerminalSymbols.TokenNameCOMMENT_BLOCK || token == ITerminalSymbols.TokenNameCOMMENT_JAVADOC) { + int start = scanner.getCurrentTokenStartPosition(); + int end = scanner.getCurrentTokenEndPosition() + 1; + try { + int endLine = document.getLineOfOffset(end); + int lineOffset = document.getLineOffset(endLine); + int lineLength = document.getLineLength(endLine); + String lineText = document.get(lineOffset, lineLength); + int commentEndInLine = end - lineOffset; + String afterComment = lineText.substring(commentEndInLine); + + if (afterComment.trim().length() > 0) { + end = lineOffset; + } else { + if (endLine + 1 < document.getNumberOfLines()) { + end = document.getLineOffset(endLine + 1); + } else { + end = document.getLength(); + } + } + } catch (BadLocationException e) { + e.printStackTrace(); + } + + IRegion region = new Region(start, end - start); + IRegion aligned = alignRegion(region, ctx); + + if (aligned != null && isMultiline(aligned, ctx)) { + Position position = createCommentPosition(aligned); + JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(ctx.collapseJavadoc(), null, true); + ctx.addProjectionRange(annotation, position); + } + } } - } catch (JavaModelException e) { + } catch (InvalidInputException 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()); - processStatement(node.getThenStatement(), ctx); - Statement elseStmt = node.getElseStatement(); - if (elseStmt != null) { - processElseStatement(elseStmt, ctx); - } - } - - private void processElseStatement(Statement elseStmt, FoldingStructureComputationContext ctx) { - if (elseStmt instanceof IfStatement) { - processIfStatement((IfStatement) elseStmt, ctx); - } else { - createFoldingRegion(elseStmt, ctx, ctx.collapseMembers()); - processStatement(elseStmt, ctx); - } - } - - - 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()); - } - - private void createFoldingRegion(ASTNode node, FoldingStructureComputationContext ctx, boolean collapse) { - int start = node.getStartPosition(); - int end = calculateEndPosition(node, ctx); - - if (end <= start) { - return; - } - - int length = end - start; - IRegion region = new Region(start, length); - IRegion aligned = alignRegion(region, ctx); - - if (aligned != null) { - Position position = new Position(aligned.getOffset(), aligned.getLength()); - JavaProjectionAnnotation annotation = new JavaProjectionAnnotation(collapse, null, false); - ctx.addProjectionRange(annotation, position); + private boolean isMultiline(IRegion region, FoldingStructureComputationContext ctx) { + try { + IDocument document = ctx.getDocument(); + int startLine = document.getLineOfOffset(region.getOffset()); + int endLine = document.getLineOfOffset(region.getOffset() + region.getLength() - 1); + return endLine > startLine; + } catch (BadLocationException e) { + e.printStackTrace(); + return false; } } - private int calculateEndPosition(ASTNode node, FoldingStructureComputationContext ctx) { - int end = node.getStartPosition() + node.getLength(); + private void processSourceReference(ISourceReference sourceRef, FoldingStructureComputationContext ctx) { try { - IDocument document = ctx.getDocument(); - int endLine = document.getLineOfOffset(end - 1); - int lineEndOffset = document.getLineOffset(endLine) + document.getLineLength(endLine); + String source = sourceRef.getSource(); + if (source == null) return; - if (end < lineEndOffset) { - String remainingText = document.get(end, lineEndOffset - end).trim(); - if (!remainingText.isEmpty()) { - // Additional logic if needed - } + ctx.getScanner().setSource(source.toCharArray()); + if (fInput instanceof IParent) { + IParent parent = (IParent) fInput; + computeFoldingStructure(parent.getChildren(), ctx); + } else { + computeFoldingStructure(fInput, ctx); } - } catch (BadLocationException e) { - e.printStackTrace(); + } catch (JavaModelException e) { } - - return end; } + /** + * 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 +1435,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 +1622,6 @@ protected final IRegion[] computeProjectionRanges(ISourceReference reference, Fo return result; } catch (JavaModelException | InvalidInputException e) { } - return new IRegion[0]; } @@ -1750,4 +1903,4 @@ private void modifyFiltered(Filter filter, boolean expand) { model.modifyAnnotations(null, null, modified.toArray(new Annotation[modified.size()])); } -} +} \ No newline at end of file