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

Netbeans "Refactor/Introduce/Extract Method" creates not-compilable / wrong method declaration in case of parametrized lambda expression #6311

Open
Honza-cz opened this issue Aug 7, 2023 · 5 comments · May be fixed by #6595
Labels
hints Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form) kind:bug Bug report or fix

Comments

@Honza-cz
Copy link

Honza-cz commented Aug 7, 2023

Apache NetBeans version

Apache NetBeans 18

What happened

When using Optional/Stream and other monads, netbeans is not able to extract method correctly from lambda expression. Input parameters are missing (in some cases).

I am willing to fix it if you can provide a pointer, which module/java class is responsible for that.

How to reproduce

Assume following code:

public class ExtractMethodDemo {

    public static void main(String[] args) {
        String first = "hello";
        String second = "world";

        System.out.println(
                java.util.Optional.ofNullable("-")
                        .map(t -> first + t + second)
                        .orElseThrow()
        );
    }
}

I would like to move code t -> first + t + second to a new method, some kind or parametrized factory, so I select it ALT SHIFT M (extract method)

It creates following not compilable method

public class ExtractMethodDemo {

    public static void main(String[] args) {
        String first = "hello";
        String second = "world";

        System.out.println(java.util.Optional.ofNullable("-")
                        .map(factory())
                        .orElseThrow()
        );
    }

    private static Function<String, String> factory() {
        return t -> first + t + second;
    }
}

Function lacks input parameters as Function<String, String> factory(String first, String second)

Did this work correctly in an earlier version?

No / Don't know

Operating System

Ubuntu

JDK

8/17

Apache NetBeans packaging

Apache NetBeans binary zip

Anything else

No response

Are you willing to submit a pull request?

Yes

@Honza-cz Honza-cz added kind:bug Bug report or fix needs:triage Requires attention from one of the committers labels Aug 7, 2023
@Honza-cz Honza-cz changed the title Netbeans "Refactor/Introduce/Extract Method" creates not-compilable / wrong method declaration in case of lambda expression Netbeans "Refactor/Introduce/Extract Method" creates not-compilable / wrong method declaration in case of parametrized lambda expression Aug 7, 2023
@mbien mbien added the Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form) label Aug 7, 2023
@Honza-cz
Copy link
Author

Honza-cz commented Aug 7, 2023

I was able to find a class which is responsible for a such refactoring
/netbeans/java/java.hints/src/org/netbeans/modules/java/hints/introduce/IntroduceExpressionBasedMethodFix.java

@Honza-cz
Copy link
Author

Honza-cz commented Aug 21, 2023

That code is quite hard to understand. So far, I am bit lost. What I discovered is, that no input params is found. I suspect something is nok in ScanStatement, but not sure what.

@Honza-cz
Copy link
Author

So a bit of progress. It seems, all what is needed is to put references to variables into "usedLocalVariable". I made a simple POC, I added the "tempForceUsedLocalVariable" to be able to change the behavior while debugging netbeans:

ScanStatement.java

    @Override
    public Void visitIdentifier(IdentifierTree node, Void p) {
        Element e = info.getTrees().getElement(getCurrentPath());
        if (e != null) {
            boolean tempForceUsedLocalVariable = false;
            if (tempForceUsedLocalVariable){
                usedLocalVariables.put((VariableElement) e, true);
            }

After this modification, input parameters appeared in newly created method. So it seems it points to right direction:

    private static Supplier<String> concatSup(String first, String second) {
        return ()->first+second;
    }

Anyway, I am still a bit confused by the code itself.

@Honza-cz
Copy link
Author

I fought with code base to be able to extract lambda expression with {} but I failed.

If I extract return t + text + m1;

from

private int dummy(final String text) {
    Function<String, String> test2 = t -> {
        return t + text + m1;
    };

    return test2.apply(text).length();
}

Netbeans wrongly deduct the return type from method, whic int:

private int dummy(final String text) {
    Function<String, String> test2 = t -> {
        return inner(t, text);
    };

    return test2.apply(text).length();
}

private int inner(String t, final String text) {
    return t + text + m1;
}

I haven't found a way how to make it working so far :(

@Honza-cz
Copy link
Author

But at least it works for lambda without {}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hints Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form) kind:bug Bug report or fix
Projects
None yet
2 participants