diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/folding/FoldingTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/folding/FoldingTest.java new file mode 100644 index 00000000000..486945ca7fc --- /dev/null +++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/folding/FoldingTest.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2023 Vector Informatik GmbH and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Vector Informatik GmbH - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.ui.tests.folding; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + +import org.eclipse.jdt.testplugin.JavaProjectHelper; + +import org.eclipse.core.runtime.CoreException; + +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.projection.ProjectionAnnotation; +import org.eclipse.jface.text.source.projection.ProjectionAnnotationModel; + +import org.eclipse.ui.PartInitException; + +import org.eclipse.jdt.core.ICompilationUnit; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaModelException; + +import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup; + +import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; +import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; + +public class FoldingTest { + @Rule + public ProjectTestSetup projectSetup= new ProjectTestSetup(); + + private IJavaProject jProject; + + private IPackageFragmentRoot sourceFolder; + + private IPackageFragment packageFragment; + + @Before + public void setUp() throws CoreException { + jProject= projectSetup.getProject(); + sourceFolder= jProject.findPackageFragmentRoot(jProject.getResource().getFullPath().append("src")); + if (sourceFolder == null) { + sourceFolder= JavaProjectHelper.addSourceContainer(jProject, "src"); + } + packageFragment= sourceFolder.createPackageFragment("org.example.test", false, null); + } + + @After + public void tearDown() throws CoreException { + JavaProjectHelper.delete(jProject); + } + + @Test + public void testMethodDeclarationFoldingWithSameLineStart() throws JavaModelException, PartInitException { + String str= """ + package org.example.test; + public class Q { + void a() { + int i = 0; + }void b() { + } + } + """; + List regions= getProjectionRangesOfFile(str); + assertTrue(regions.size() >= 2); + + regions.sort((r1, r2) -> Integer.compare(r1.getOffset(), r2.getOffset())); + IRegion methodARegion= regions.get(0); + IRegion methodBRegion= regions.get(1); + int methodAEnd= methodARegion.getOffset() + methodARegion.getLength(); + int methodBStart= methodBRegion.getOffset(); + + assertTrue(methodBStart >= methodAEnd); + } + + private List getProjectionRangesOfFile(String str) throws JavaModelException, PartInitException { + ICompilationUnit cu= packageFragment.createCompilationUnit("TestFolding.java", str, true, null); + JavaEditor editor= (JavaEditor) EditorUtility.openInEditor(cu); + ProjectionAnnotationModel model= editor.getAdapter(ProjectionAnnotationModel.class); + List regions= new ArrayList<>(); + Iterator it= model.getAnnotationIterator(); + while (it.hasNext()) { + Annotation a= it.next(); + if (a instanceof ProjectionAnnotation) { + Position p= model.getPosition(a); + regions.add(new Region(p.getOffset(), p.getLength())); + } + } + return regions; + } +} 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 e212f37c39a..0f41c8c525f 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 @@ -1279,23 +1279,15 @@ protected final IRegion alignRegion(IRegion region, FoldingStructureComputationC IDocument document= ctx.getDocument(); try { - int start= document.getLineOfOffset(region.getOffset()); - int end= document.getLineOfOffset(region.getOffset() + region.getLength()); + int end= document.getLineOfOffset(region.getOffset() + region.getLength() - 1); if (start >= end) return null; - - int offset= document.getLineOffset(start); - int endOffset; - if (document.getNumberOfLines() > end + 1) - endOffset= document.getLineOffset(end + 1); - else - endOffset= document.getLineOffset(end) + document.getLineLength(end); + int offset = document.getLineOffset(start); + int endOffset = document.getLineOffset(end); return new Region(offset, endOffset - offset); - } catch (BadLocationException x) { - // concurrent modification return null; } }