Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
import org.openide.text.NbDocument;
import org.openide.util.Exceptions;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.YieldTree;
import com.sun.source.util.TreePathScanner;
import com.sun.source.util.Trees;
import com.sun.tools.javac.api.JavacScope;
Expand Down Expand Up @@ -1447,6 +1448,11 @@ public Boolean visitReturn(ReturnTree node, Void p) {
return true;
}

@Override
public Boolean visitYield(YieldTree node, Void p) {
return true;
}

@Override
public Boolean visitBreak(BreakTree node, Void p) {
Tree target = info.getTreeUtilities().getBreakContinueTarget(getCurrentPath());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import com.sun.source.tree.Tree;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.tree.YieldTree;
import com.sun.source.util.SourcePositions;
import com.sun.source.util.TreePath;
import java.awt.GraphicsEnvironment;
Expand Down Expand Up @@ -262,6 +263,25 @@ static Fix computeIntroduceMethod(CompilationInfo info, int start, int end, Map<
returnType = methodReturnType;
returnAssignTo = null;
declareVariableForReturnValue = false;
} else if (exitsFromAllBranches && scanner.hasYields) {
returnType = info.getTypes().getNullType();
for (TreePath exit : scanner.selectionExits) {
if (exit.getLeaf().getKind() == Tree.Kind.YIELD) {
Tree target = info.getTreeUtilities().getBreakContinueTargetTree(exit);
TreePath switchExpr = exit;

while (switchExpr != null && switchExpr.getLeaf() != target) {
switchExpr = switchExpr.getParentPath();
}

if (switchExpr != null) {
returnType = info.getTrees().getTypeMirror(switchExpr);
break;
}
}
}
returnAssignTo = null;
declareVariableForReturnValue = false;
} else {
returnType = info.getTypes().getNoType(TypeKind.VOID);
returnAssignTo = null;
Expand Down Expand Up @@ -628,7 +648,11 @@ private void generateMethodInvocation(List<StatementTree> nueStatements, List<Ex
}
if (branchExit != null) {
if (returnSingleValue) {
nueStatements.add(make.Return(invocation));
if (branchExit.getLeaf().getKind() == Tree.Kind.YIELD) {
nueStatements.add(make.Yield(invocation));
} else {
nueStatements.add(make.Return(invocation));
}
} else {
StatementTree branch = null;
switch (branchExit.getLeaf().getKind()) {
Expand All @@ -641,6 +665,9 @@ private void generateMethodInvocation(List<StatementTree> nueStatements, List<Ex
case RETURN:
branch = make.Return(((ReturnTree) branchExit.getLeaf()).getExpression());
break;
case YIELD:
branch = make.Yield(((YieldTree) branchExit.getLeaf()).getValue());
break;
}
if (remappedReturn != null || exitsFromAllBranches) {
nueStatements.add(make.ExpressionStatement(invocation));
Expand Down Expand Up @@ -674,6 +701,13 @@ private ReturnTree makeExtractedReturn(boolean forceReturn) {
*/
private void makeReturnsFromExtractedMethod(List<StatementTree> methodStatements) {
if (returnSingleValue) {
for (TreePath resolved : resolvedExits) {
if (resolved.getLeaf().getKind() == Tree.Kind.YIELD) {
YieldTree yield = (YieldTree) resolved.getLeaf();

copy.rewrite(resolved.getLeaf(), make.Return(yield.getValue()));
}
}
return;
}
if (resolvedExits != null) {
Expand Down Expand Up @@ -728,7 +762,7 @@ private boolean resolveAndInitialize() {
resolvedExits.add(resolved);
}

returnSingleValue = exitsFromAllBranches && branchExit.getLeaf().getKind() == Tree.Kind.RETURN && outcomeVariable == null && returnType.getKind() != TypeKind.VOID;
returnSingleValue = exitsFromAllBranches && (branchExit.getLeaf().getKind() == Tree.Kind.RETURN || branchExit.getLeaf().getKind() == Tree.Kind.YIELD) && outcomeVariable == null && returnType.getKind() != TypeKind.VOID;
}
// initialization
make = copy.getTreeMaker();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.sun.source.tree.Tree;
import com.sun.source.tree.VariableTree;
import com.sun.source.tree.WhileLoopTree;
import com.sun.source.tree.YieldTree;
import com.sun.source.util.TreePath;
import org.netbeans.api.java.source.support.ErrorAwareTreePathScanner;
import java.util.ArrayList;
Expand Down Expand Up @@ -71,6 +72,7 @@ final class ScanStatement extends ErrorAwareTreePathScanner<Void, Void> {
private final Map<Tree, Iterable<? extends TreePath>> assignmentsForUse;
final Set<TreePathHandle> usedTypeVariables = new HashSet<TreePathHandle>();
boolean hasReturns = false;
boolean hasYields = false;
private boolean hasBreaks = false;
private boolean hasContinues = false;
private boolean secondPass = false;
Expand Down Expand Up @@ -236,6 +238,15 @@ public Void visitReturn(ReturnTree node, Void p) {
return super.visitReturn(node, p);
}

@Override
public Void visitYield(YieldTree node, Void p) {
if (isMethodCode() && phase == PHASE_INSIDE_SELECTION) {
selectionExits.add(getCurrentPath());
hasYields = true;
}
return super.visitYield(node, p);
}

@Override
public Void visitBreak(BreakTree node, Void p) {
if (isMethodCode() && phase == PHASE_INSIDE_SELECTION && !treesSeensInSelection.contains(info.getTreeUtilities().getBreakContinueTargetTree(getCurrentPath()))) {
Expand Down Expand Up @@ -313,6 +324,7 @@ String verifyExits(boolean exitsFromAllBranches) {
i += hasReturns ? 1 : 0;
i += hasBreaks ? 1 : 0;
i += hasContinues ? 1 : 0;
i += hasYields ? 1 : 0;
if (i > 1) {
return "ERR_Too_Many_Different_Exits"; // NOI18N
}
Expand All @@ -325,6 +337,7 @@ String verifyExits(boolean exitsFromAllBranches) {
for (TreePath tp : selectionExits) {
if (tp.getLeaf().getKind() == Tree.Kind.RETURN) {
if (!exitsFromAllBranches) {
//TODO: the same for yield
ReturnTree rt = (ReturnTree) tp.getLeaf();
TreePath currentReturnValue = rt.getExpression() != null ? new TreePath(tp, rt.getExpression()) : null;
if (!returnValueComputed) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,27 @@ public void testExitsAllBranchesSwitchDefaultMissing() throws Exception {
false);
}

public void testExitsAllBranchesYield() throws Exception {
performExitsTest(
"""
package test;
public class Test {
public int test(int param) {
return switch (param) {
default -> {
i|f (param == 0) {
yield 0;
} else {
yield 1;
}
}
};
}
}
""",
true);
}

private void performExitsTest(String code, boolean expected) throws Exception {
int caretPos = code.indexOf('|');
code = code.replace("|", "");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2618,6 +2618,151 @@ public void testIntroduceMethodReturn233433() throws Exception {
1, 0);
}

public void testYield1() throws Exception {
sourceLevel = "17";
performFixTest("""
package test;
public class Test {
private int convert(int a) {
return switch (a) {
case 0 -> {
int i = 0;
|System.err.println(i);
int j = 0;
yield i + j;|
}
default -> -1;
};
}
}
""",
"""
package test;
public class Test {
private int convert(int a) {
return switch (a) {
case 0 -> {
int i = 0;
yield name(i);
}
default -> -1;
};
}
private int name(int i) {
System.err.println(i);
int j = 0;
return i + j;
}
}
""",
new DialogDisplayerImpl3("name", null, true),
1, 0);
}

public void testYield2() throws Exception {
sourceLevel = "17";
performFixTest("""
package test;
public class Test {
private Object convert(int a) {
return switch (a) {
case 0 -> {
int i = 0;
|System.err.println(i);
if (i == 0) {
yield "";
} else {
yield 1;
}|
}
default -> -1;
};
}
}
""",
"""
package test;
public class Test {
private Object convert(int a) {
return switch (a) {
case 0 -> {
int i = 0;
yield name(i);
}
default -> -1;
};
}
private Object name(int i) {
System.err.println(i);
if (i == 0) {
return "";
} else {
return 1;
}
}
}
""",
new DialogDisplayerImpl3("name", null, true),
1, 0);
}

public void testYield3() throws Exception {
sourceLevel = "17";
performFixTest("""
package test;
public class Test {
private Object convert(int a) {
return switch (a) {
case 0 -> {
int i = 0;
|System.err.println(i);
if (i <= 0) {
if (i == 0) {
yield "";
} else {
System.err.println("wrong");
yield "";
}
}|
yield 1;
}
default -> -1;
};
}
}
""",
"""
package test;
public class Test {
private Object convert(int a) {
return switch (a) {
case 0 -> {
int i = 0;
if (name(i))
yield "";
yield 1;
}
default -> -1;
};
}
private boolean name(int i) {
System.err.println(i);
if (i <= 0) {
if (i == 0) {
return true;
} else {
System.err.println("wrong");
return true;
}
}
return false;
}
}
""",
new DialogDisplayerImpl3("name", null, true),
1, 0);
}

protected void prepareTest(String code) throws Exception {
clearWorkDir();

Expand Down
12 changes: 12 additions & 0 deletions java/java.source.base/apichanges.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,18 @@
<apidef name="javasource_base">Java Source API</apidef>
</apidefs>
<changes>
<change id="TreeMaker.Yield">
<api name="javasource_base" />
<summary>Added TreeMaker.Yield</summary>
<version major="1" minor="2.81"/>
<date day="10" month="10" year="2025"/>
<author login="jlahoda"/>
<compatibility addition="yes" binary="compatible" source="compatible"/>
<description>
Adding TreeMaker.Yield.
</description>
<class name="TreeMaker" package="org.netbeans.api.java.source"/>
</change>
<change id="ModuleImports">
<api name="javasource_base" />
<summary>API Support for module imports</summary>
Expand Down
2 changes: 1 addition & 1 deletion java/java.source.base/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ javadoc.name=Java Source Base
javadoc.title=Java Source Base
javadoc.arch=${basedir}/arch.xml
javadoc.apichanges=${basedir}/apichanges.xml
spec.version.base=2.80.0
spec.version.base=2.81.0
test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar
test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\
${o.n.core.dir}/lib/boot.jar:\
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,17 @@ public ReturnTree Return(ExpressionTree expression) {
return delegate.Return(expression);
}

/**
* Creates a new YieldTree.
*
* @param expression the expression to be yielded.
* @see com.sun.source.tree.YieldTree
* @since 2.81
*/
public YieldTree Yield(ExpressionTree expression) {
return delegate.Yield(expression);
}

/**
* Creates a new SwitchTree.
*
Expand Down
Loading