From 9b190bfacdf60c7d4432984dfb1933b388fcd1a4 Mon Sep 17 00:00:00 2001 From: Jakub Suliga Date: Fri, 31 Jan 2025 15:15:41 +0100 Subject: [PATCH] Fix folding of 2 consecutive methods If the second method starts in the same line the first one ends then there will still be 2 foldings. Fixes https://github.com/eclipse-jdt/eclipse.jdt.ui/issues/1992 --- .../jdt/text/tests/JdtTextTestSuite.java | 2 + .../jdt/text/tests/folding/FoldingTest.java | 225 +------- .../text/tests/folding/FoldingTestNew.java | 522 ++++++++++++++++++ .../DefaultJavaFoldingStructureProvider.java | 4 +- 4 files changed, 535 insertions(+), 218 deletions(-) create mode 100644 org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestNew.java diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java index ae6b859828e..aa71addcd33 100644 --- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/JdtTextTestSuite.java @@ -21,6 +21,7 @@ import org.eclipse.jdt.text.tests.codemining.ParameterNamesCodeMiningTest; import org.eclipse.jdt.text.tests.contentassist.ContentAssistTestSuite; import org.eclipse.jdt.text.tests.folding.FoldingTest; +import org.eclipse.jdt.text.tests.folding.FoldingTestNew; import org.eclipse.jdt.text.tests.semantictokens.SemanticTokensProviderTest; import org.eclipse.jdt.text.tests.spelling.SpellCheckEngineTestCase; import org.eclipse.jdt.text.tests.templates.TemplatesTestSuite; @@ -71,6 +72,7 @@ JavaElementPrefixPatternMatcherTest.class, CodeMiningTriggerTest.class, ParameterNamesCodeMiningTest.class, + FoldingTestNew.class, FoldingTest.class, }) public class JdtTextTestSuite { diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTest.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTest.java index 47469488f72..0faf06e25b6 100644 --- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTest.java +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTest.java @@ -24,19 +24,14 @@ import org.eclipse.core.runtime.CoreException; -import org.eclipse.jface.preference.IPreferenceStore; - import org.eclipse.jface.text.IRegion; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; -import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup; -import org.eclipse.jdt.internal.ui.JavaPlugin; - public class FoldingTest { @Rule public ProjectTestSetup projectSetup= new ProjectTestSetup(); @@ -55,9 +50,7 @@ public void setUp() throws CoreException { sourceFolder= JavaProjectHelper.addSourceContainer(jProject, "src"); } packageFragment= sourceFolder.createPackageFragment("org.example.test", false, null); - IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); - store.setValue(PreferenceConstants.EDITOR_NEW_FOLDING_ENABLED, true); - } + } @After public void tearDown() throws CoreException { @@ -242,7 +235,7 @@ void b() { //here should be an annotation } } """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 6); + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 5); List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 1, 3); // 1. Javadoc @@ -250,7 +243,6 @@ void b() { //here should be an annotation FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 7, 9); // 3. Javadoc FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 12, 14); // 4. Javadoc FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 15, 19); // Methode b() - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 16, 18); // 5. Javadoc } @Test @@ -285,217 +277,20 @@ void a() { } @Test - public void testIfStatementFolding() throws Exception { - String str= """ - package org.example.test; - public class D { - void x() { //here should be an annotation - if (true) { //here should be an annotation - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // if - } - - @Test - public void testTryStatementFolding() throws Exception { + public void testinnerClassinMethod() throws Exception { String str= """ package org.example.test; - public class E { - void x() { //here should be an annotation - try { //here should be an annotation + class Outer { + void a() { //here should be an annotation + class Inner2{ //here should be an annotation - } catch (Exception e) { //here should be an annotation - - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 3); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 7); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // try - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 6); // catch - } - - @Test - public void testWhileStatementFolding() throws Exception { - String str= """ - package org.example.test; - public class F { - void x() { //here should be an annotation - while (true) { //here should be an annotation - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // while - } - - @Test - public void testForStatementFolding() throws Exception { - String str= """ - package org.example.test; - public class G { - void x() { //here should be an annotation - for(int i=0;i<1;i++){ //here should be an annotation - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // for - } - - @Test - public void testEnhancedForStatementFolding() throws Exception { - String str= """ - package org.example.test; - public class H { - void x() { //here should be an annotation - for(String s: new String[0]){ //here should be an annotation - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // for - } - - @Test - public void testDoStatementFolding() throws Exception { - String str= """ - package org.example.test; - public class I { - void x() { //here should be an annotation - do { //here should be an annotation - - } while(false); - } + } + } } """; FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // do - } - - @Test - public void testSynchronizedStatementFolding() throws Exception { - String str= """ - package org.example.test; - public class K { - void x() { //here should be an annotation - synchronized(this) { //here should be an annotation - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // synchronized - } - - @Test - public void testLambdaExpressionFolding() throws Exception { - String str= """ - package org.example.test; - import java.util.function.Supplier; - public class L { - void x() { //here should be an annotation - Supplier s = () -> { //here should be an annotation - return ""; - }; - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 6); // 1. Method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 5); // Supplier - } - - @Test - public void testAnonymousClassDeclarationFolding() throws Exception { - String str= """ - package org.example.test; - public class M { - Object o = new Object(){ //here should be an annotation - void y() { //here should be an annotation - - } - }; - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // Object - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // Method - } - - @Test - public void testEnumDeclarationFolding() throws Exception { - String str= """ - package org.example.test; - public enum N { //here should be an annotation - A, - B - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 1, 3); // enum - } - - @Test - public void testInitializerFolding() throws Exception { - String str= """ - package org.example.test; - public class O { - static { //here should be an annotation - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 2); // static - } - - @Test - public void testNestedFolding() throws Exception { - String str= """ - package org.example.test; - public class P { - void x() { //here should be an annotation - if (true) { //here should be an annotation - for(int i=0;i<1;i++){ //here should be an annotation - while(true) { //here should be an annotation - do { //here should be an annotation - } while(false); - } - } - } - } - } - """; - FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 5); - List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 10); // method - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 9); // if - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 8); // for - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 7); // while - FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 6, 6); // do + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // inner class } } diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestNew.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestNew.java new file mode 100644 index 00000000000..b98c55013c7 --- /dev/null +++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/folding/FoldingTestNew.java @@ -0,0 +1,522 @@ +/******************************************************************************* + * Copyright (c) 2025 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.text.tests.folding; + +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.preference.IPreferenceStore; + +import org.eclipse.jface.text.IRegion; + +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.IPackageFragment; +import org.eclipse.jdt.core.IPackageFragmentRoot; + +import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.tests.core.rules.ProjectTestSetup; + +import org.eclipse.jdt.internal.ui.JavaPlugin; + +public class FoldingTestNew { + @Rule + public ProjectTestSetup projectSetup= new ProjectTestSetup(); + + private IJavaProject jProject; + + private IPackageFragmentRoot sourceFolder; + + private IPackageFragment packageFragment; + + private IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore(); + + @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); + + store.setValue(PreferenceConstants.EDITOR_NEW_FOLDING_ENABLED, true); + } + + @After + public void tearDown() throws CoreException { + JavaProjectHelper.delete(jProject); + store.setToDefault(PreferenceConstants.EDITOR_NEW_FOLDING_ENABLED); + } + + @Test + public void testCompilationUnitFolding() throws Exception { + String str= """ + package org.example.test; + public class A { //here should not be an annotation + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 0); + } + + @Test + public void testClassWithJavadocAsHeaderComment() throws Exception { + String str= """ + package org.example.test; + /** //here should be an annotation + * Javadoc + */ + public class HeaderCommentTest { + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 1, 3); // Javadoc + } + + @Test + public void testImportsFolding() throws Exception { + String str= """ + package org.example.test; + + import java.util.List; //here should be an annotation + import java.util.ArrayList; + + public class ImportsTest { + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 3); // Imports + } + + @Test + public void testSingleMethodWithJavadoc() throws Exception { + String str= """ + package org.example.test; + public class SingleMethodTest { + /** //here should be an annotation + * Javadoc + */ + public void foo() { //here should be an annotation + System.out.println("Hello"); + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 6); // foo Methode + } + + @Test + public void testMultipleMethodsWithoutComments() throws Exception { + String str= """ + package org.example.test; + public class MultipleMethodTest { + public void foo() { //here should be an annotation + + } + public void bar() { //here should be an annotation + + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 3); // foo Methode + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 6); // bar Methode + } + + @Test + public void testInnerClassFolding() throws Exception { + String str= """ + package org.example.test; + public class OuterClass { + class InnerClass { //here should be an annotation + void bar() { //here should be an annotation + + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // InnerClass + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // bar Methode + } + + @Test + public void testInnerClassWithJavadoc() throws Exception { + String str= """ + package org.example.test; + public class OuterWithDocs { + /** //here should be an annotation + * Javadoc + */ + class InnerWithDocs { //here should be an annotation + /** //here should be an annotation + * Javadoc + */ + void bar() { //here should be an annotation + + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 4); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // OuterWithDocs Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 11); // InnerWithDocs Klasse + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 6, 8); // InnerWithDocs Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 9, 10); // bar Methode + } + + @Test + public void testJavadocs() throws Exception { + String str= """ + package org.example.test; + /** //here should be an annotation + * Javadoc + */ + /** //here should be an annotation + * Another Javadoc + */ + /** //here should be an annotation + * Yet another Javadoc + */ + public class Example {} + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 3); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 1, 3); // 1. Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 6); // 2. Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 7, 9); // 3. Javadoc + } + + @Test + public void testCommentBlocks() throws Exception { + String str= """ + package org.example.test; + /* //here should be an annotation + * + */ + /* //here should be an annotation + * + */ + /* //here should be an annotation + * + */ + class h { + + /* //here should be an annotation + * + */ + void b() { //here should be an annotation + /* //here should be an annotation + * + */ + int a; + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 6); + + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 1, 3); // 1. Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 6); // 2. Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 7, 9); // 3. Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 12, 14); // 4. Javadoc + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 15, 19); // Methode b() + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 16, 18); // 5. Javadoc + } + + @Test + public void testCopyrightHeader() throws Exception { + String str= """ + /** //here should be an annotation + * This is some copyright header + */ + package org.example.test; + + class SomeClass {} + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); + } + + @Test + public void testMethodDeclarationFoldingWithSameLineStart() throws Exception { + String str= """ + package org.example.test; + public class Q { + void a() { + int i = 0; + }void b() { + + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 3); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 5); // 2. Method + } + + @Test + public void testIfStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class D { + void x() { //here should be an annotation + if (true) { //here should be an annotation + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // if + } + + @Test + public void testTryStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class E { + void x() { //here should be an annotation + try { //here should be an annotation + + } catch (Exception e) { //here should be an annotation + + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 3); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 7); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // try + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 6); // catch + } + + @Test + public void testWhileStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class F { + void x() { //here should be an annotation + while (true) { //here should be an annotation + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // while + } + + @Test + public void testForStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class G { + void x() { //here should be an annotation + for(int i=0;i<1;i++){ //here should be an annotation + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // for + } + + @Test + public void testEnhancedForStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class H { + void x() { //here should be an annotation + for(String s: new String[0]){ //here should be an annotation + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // for + } + + @Test + public void testDoStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class I { + void x() { //here should be an annotation + do { //here should be an annotation + + } while(false); + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // do + } + + @Test + public void testSynchronizedStatementFolding() throws Exception { + String str= """ + package org.example.test; + public class K { + void x() { //here should be an annotation + synchronized(this) { //here should be an annotation + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 4); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 3); // synchronized + } + + @Test + public void testLambdaExpressionFolding() throws Exception { + String str= """ + package org.example.test; + import java.util.function.Supplier; + public class L { + void x() { //here should be an annotation + Supplier s = () -> { //here should be an annotation + return ""; + }; + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 6); // 1. Method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 5); // Supplier + } + + @Test + public void testAnonymousClassDeclarationFolding() throws Exception { + String str= """ + package org.example.test; + public class M { + Object o = new Object(){ //here should be an annotation + void y() { //here should be an annotation + + } + }; + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // Object + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // Method + } + + @Test + public void testEnumDeclarationFolding() throws Exception { + String str= """ + package org.example.test; + public enum N { //here should be an annotation + A, + B + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 1, 3); // enum + } + + @Test + public void testInitializerFolding() throws Exception { + String str= """ + package org.example.test; + public class O { + static { //here should be an annotation + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 1); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 2); // static + } + + @Test + public void testNestedFolding() throws Exception { + String str= """ + package org.example.test; + public class P { + void x() { //here should be an annotation + if (true) { //here should be an annotation + for(int i=0;i<1;i++){ //here should be an annotation + while(true) { //here should be an annotation + do { //here should be an annotation + } while(false); + } + } + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 5); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 10); // method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 9); // if + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 4, 8); // for + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 5, 7); // while + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 6, 6); // do + } + + @Test + public void testinnerClassinMethod() throws Exception { + String str= """ + package org.example.test; + class Outer { + void a() { //here should be an annotation + class Inner2{ //here should be an annotation + + } + } + } + """; + FoldingTestUtils.assertCodeHasRegions(packageFragment, "TestFolding.java", str, 2); + List regions= FoldingTestUtils.getProjectionRangesOfFile(packageFragment, "TestFolding.java", str); + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 2, 5); // method + FoldingTestUtils.assertContainsRegionUsingStartAndEndLine(regions, str, 3, 4); // inner class + } +} 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 380a005f898..f3aac380c17 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 @@ -353,8 +353,7 @@ public boolean visit(CompilationUnit node) { @Override public boolean visit(TypeDeclaration node) { - boolean isInnerClass= node.isMemberTypeDeclaration(); - if (isInnerClass) { + if (node.isMemberTypeDeclaration() || node.isLocalTypeDeclaration()) { int start= node.getName().getStartPosition(); int end= node.getStartPosition() + node.getLength(); createFoldingRegion(start, end - start, ctx.collapseMembers()); @@ -1496,7 +1495,6 @@ protected void computeFoldingStructure(IJavaElement element, FoldingStructureCom includelastLine= true; IRegion normalized= alignRegion(regions[i], ctx); if (normalized != null) { - includelastLine= true; Position position= createCommentPosition(normalized); if (position != null) { boolean commentCollapse;