Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Folding mechanism for while/for/if/... #1562

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

jakub-suliga
Copy link

@jakub-suliga jakub-suliga commented Jul 31, 2024

Problem:
Currently, there is no folding mechanism for while/for/if/switch-case statements in Eclipse. VSCode and IntelliJ support a folding mechanism for these statements. Therefore, I have created a method that implements this folding mechanism. This is also an open issue: #1426. In addition, I deleted some commented-out code from 2007.

Before:
image

After:
image

How to test:

  1. Start an Eclipse workspace and create a new class.
  2. Add while/for/if/switch-case statements to this class.
  3. Verify that the folding mechanism works as expected.

Here is a small program you can use to test:

private int zaehler;
private final Object sperre = new Object();


public void test() {
    if (zaehler > 0) {
        System.out.println();
    } else if (zaehler == 0) {
        System.out.println();
    } else {
        System.out.println();
    }

    while (zaehler < 10) {
        zaehler++;
    }

    for (int i = 0; i < zaehler; i++) {
        System.out.println();
    }

    do {
        zaehler--;
    } while (zaehler > 0);

    int[] zahlen = {1, 2, 3, 4, 5};
    for (int zahl : zahlen) {
        System.out.println();
    }

    switch (zaehler) {
        case 0:
            System.out.println();
            break;
        case 1:
            System.out.println();
            break;
        default:
            System.out.println();
            break;
    }

    try {
        int ergebnis = 10 / zaehler;
    } catch (ArithmeticException e) {
        System.out.println();
    } finally {
        System.out.println();
    }

    synchronized (sperre) {
        zaehler++;
    }

    Runnable runnable = () -> {
        System.out.println();
    };
    runnable.run();

    {
        System.out.println();
    }

    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            if (i * j > 6) {
            }
            System.out.println();
        }
    }

    try {
        String text = null;
        text.length();
    } catch (NullPointerException e) {
        System.out.println();
    } catch (Exception e) {
        System.out.println();
    } finally {
        System.out.println();
    }

    {
        System.out.println();
    }
    if (zaehler > 0) {
        for (int i = 0; i < zaehler; i++) {
            while (i < 5) {
                System.out.println();
                i++;
            }
        }
    }

    lambdaVerwenden();
}

public void lambdaVerwenden() {
    verarbeiteLambda(() -> {
        System.out.println();
    });
}

private void verarbeiteLambda(Runnable runnable) {
    runnable.run();
}

Bugs:

@jakub-suliga jakub-suliga marked this pull request as draft July 31, 2024 07:29
@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 2 times, most recently from 08cd1d9 to afd4aed Compare September 25, 2024 07:09
@jakub-suliga
Copy link
Author

jakub-suliga commented Sep 25, 2024

Bug:

  • When you press enter or delete a line and the element is closed, the folding mechanism gets buggy

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 2 times, most recently from c2082f5 to 0390f1c Compare October 2, 2024 12:14
@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 10 times, most recently from c1ac59f to 80ee66d Compare October 8, 2024 09:00
@jakub-suliga jakub-suliga marked this pull request as ready for review October 8, 2024 11:59
@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 3 times, most recently from d5cf645 to a44a7e0 Compare October 8, 2024 17:24
@fedejeanne
Copy link
Contributor

The test failures seem to be unrelated: https://ci.eclipse.org/jdt/job/eclipse.jdt.ui-github/job/PR-1562/21/testReport/

The only test that fails with age == 1 (i.e. in this PR) is org.eclipse.jdt.text.tests.PluginsNotLoadedTest.pluginsNotLoaded but looking at its stack trace I don't see any hints that point to this PR either:

java.lang.AssertionError: 
Wrong bundles loaded:
- org.eclipse.jdt.junit
 expected:<0> but was:<24>
	at org.junit.Assert.fail(Assert.java:89)
	at org.junit.Assert.failNotEquals(Assert.java:835)
	at org.junit.Assert.assertEquals(Assert.java:647)
	at org.eclipse.jdt.text.tests.PluginsNotLoadedTest.pluginsNotLoaded(PluginsNotLoadedTest.java:278)
...

Does anyone know the reason for this failure?

In the meantime @jakub-suliga, try with another force-push to re-trigger the checks and see if the failure persists.

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch from a44a7e0 to b49f6c9 Compare October 9, 2024 07:46
@jakub-suliga jakub-suliga marked this pull request as draft October 9, 2024 08:15
@jakub-suliga jakub-suliga marked this pull request as ready for review October 9, 2024 08:16
@fedejeanne
Copy link
Contributor

fedejeanne commented Oct 9, 2024

In the meantime @jakub-suliga, try with another force-push to re-trigger the checks and see if the failure persists.

On a closer look, the test failures are because of the changes introduced in this PR. Run them locally and you will see it.

Here's (part of) the console output when running org.eclipse.jdt.ui.tests.quickfix.AnnotateAssistTest1d5.testAnnotateReturn2():

!STACK 0
java.lang.ClassCastException: class org.eclipse.jdt.internal.core.ClassFile cannot be cast to class org.eclipse.jdt.core.ICompilationUnit (org.eclipse.jdt.internal.core.ClassFile and org.eclipse.jdt.core.ICompilationUnit are in unnamed module of loader org.eclipse.osgi.internal.loader.EquinoxClassLoader @21452f5e)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.computeFoldingStructure(DefaultJavaFoldingStructureProvider.java:981)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.update(DefaultJavaFoldingStructureProvider.java:907)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.initialize(DefaultJavaFoldingStructureProvider.java:852)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider.handleProjectionEnabled(DefaultJavaFoldingStructureProvider.java:822)
	at org.eclipse.jdt.ui.text.folding.DefaultJavaFoldingStructureProvider$ProjectionListener.projectionEnabled(DefaultJavaFoldingStructureProvider.java:700)
...
	at org.eclipse.jdt.ui.tests.quickfix.AnnotateAssistTest1d5.testAnnotateReturn2(AnnotateAssistTest1d5.java:178)
...

It seems the fInput isn't always an ICompilationUnit as the new code assumes. You'll have to "fork" the execution (with an if (fPart instanceof ICompilationUnit)) and preserve the old code too (in the else block).

It would be interesting to know when exactly is fInput not and ICompilationUnit and if it's possible to turn them into ICompilationUnits (in a separate PR). By the looks of it, it might be when one opens a .class file, probably one that displays source code, like java.lang.String:

image

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 3 times, most recently from d68c88b to baf2632 Compare October 30, 2024 06:52
@fedejeanne
Copy link
Contributor

@iloveeclipse : Jakub and I were looking into the failed tests and we found the culprit: it was a null. After some debugging and evaluating we decided that a null-check would make sense since now (in this PR) it is possible to add folding structures for things that are not IJavaElements. This led to commit ade7b52.

Do you see any possible problem with this change? We couldn't come up with any but maybe you can?

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 6 times, most recently from 5205312 to 397df4a Compare January 17, 2025 09:30
Copy link
Contributor

@fedejeanne fedejeanne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor comments for the moment.

@@ -102,6 +102,12 @@ public Control createControl(Composite composite) {
addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_methods, PreferenceConstants.EDITOR_FOLDING_METHODS, 0);
addCheckBox(inner, FoldingMessages.DefaultJavaFoldingPreferenceBlock_imports, PreferenceConstants.EDITOR_FOLDING_IMPORTS, 0);

Label label2= new Label(inner, SWT.LEFT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need this. Try to improve the overall design of the whole configuration page and make it look more like the Content Assist page, which has Groups (with borders). You should have 2 groups:

  • Initially fold ...
  • Extended folding (Experimental) : This one is yours and has
    • A Label with an explanation like "Enable folding for other code blocks. Activating this feature may cause a significant performance degradation"
    • A checkbox: "Activate feature".

Copy link
Author

@jakub-suliga jakub-suliga Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want it like this?
image

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you let the groups adapt better to the size of the dialog, just like with the Content Assist?

resize_preferences_page

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • A checkbox: "Activate feature".

Probably better to explicitly say "Enable folding for if/for/while blocks" ?

Copy link
Author

@jakub-suliga jakub-suliga Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because it enables folding not only for if, for, and while blocks, but also for constructs such as try/catch blocks, lambdas et cetera.

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 2 times, most recently from 3f5b295 to 60dc8fb Compare January 17, 2025 10:08
@fedejeanne
Copy link
Contributor

The test failure is unrelated. #1095

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch 3 times, most recently from ac241c8 to e15cacf Compare January 17, 2025 13:36
@fedejeanne
Copy link
Contributor

The build failure seems to be unrelated, it's a timeout. Maybe it will work next time it runs (e.g. when you rebase and push again).

15:42:55  [ERROR] Failed to execute goal org.eclipse.tycho:tycho-apitools-plugin:4.0.11-SNAPSHOT:verify (verify) on project org.eclipse.jdt.ui: Execution verify of goal org.eclipse.tycho:tycho-apitools-plugin:4.0.11-SNAPSHOT:verify failed: Could not mirror artifact osgi.bundle,org.mortbay.jasper.apache-jsp.source,9.0.96 into the local Maven repository.See log output for details. request timed out -> [Help 1]

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch from e15cacf to 34817f9 Compare January 17, 2025 14:19
@fedejeanne
Copy link
Contributor

The code looks much better now, thank you for the corrections @jakub-suliga.

Maybe after you fix my last #1562 (comment), a JDT committer (@iloveeclipse?) would like to review again?

I'm off for today, have a nice weekend!

@iloveeclipse
Copy link
Member

I can't guarantee I will have time next week, I'm overloaded. The feature itself seems to be useful, so if the new test also covers existing functionality & is green, why not merge?

@jjohnstn : are you available to review this?

@jakub-suliga jakub-suliga force-pushed the feature/foldingStrucktur branch from 34817f9 to 4ae83f5 Compare January 17, 2025 15:05
@jjohnstn
Copy link
Contributor

@iloveeclipse Sure

@danthe1st danthe1st mentioned this pull request Jan 17, 2025
3 tasks
@jjohnstn
Copy link
Contributor

@jakub-suliga Just trying it out, it seems to work well. I tried the given test but it does not fold the switch statement or its cases. Is that expected or is that something that isn't working in my particular test?

I ran into a major bug with folding on my Linux platform which is likely Linux specific. If I fold, then hover over the plus and then click on the hover to focus it; there is no way out but Esc. This closes the hover but the flashing cursor is missing and the window pointer can get changed to the window expansion characters if I am on the edges of the hover area at the time of escape. I got similar experiences sometimes after entering via F2 to get focus in the hover window, but it seemed better and I often got the flashing cursor back. Once the cursor was gone, I could only get it back by switching into another Eclipse and its editor and then switching back. Again, likely Fedora specific, but I ask in case you have Windows/Mac and can confirm that it doesn't occur for you. It is not caused by this PR.

@jjohnstn
Copy link
Contributor

@jakub-suliga Just trying it out, it seems to work well. I tried the given test but it does not fold the switch statement or its cases. Is that expected or is that something that isn't working in my particular test?

Never mind. I can see from the code that switch statements aren't covered.

Copy link
Contributor

@jjohnstn jjohnstn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, code looks good, but 2 comments to address.

* 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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your removal of the CommentPosition class has changed functionality. The old folding for a Javadoc comment will show you the first line after the /** after folding but your code just shows /**

/**
 * Function comment
 *
 */

Old:

* Function comment ...

New:

/**
 */

@@ -0,0 +1,362 @@
/*******************************************************************************
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have at least one test that verifies the region values are as expected as opposed to just count (e.g. verify that finally region starts at the beginning of the finally keyword and not the block

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants