diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/NewCUProposal.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/NewCUProposal.java index bcb8472411..5ffaf573a5 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/NewCUProposal.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/NewCUProposal.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Iterator; +import java.util.List; import java.util.Objects; import org.eclipse.core.runtime.CoreException; @@ -35,6 +36,8 @@ import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.Expression; +import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.ParameterizedType; @@ -82,6 +85,8 @@ public class NewCUProposal extends ChangeCorrectionProposalCore { private int fTypeKind; private IJavaElement fTypeContainer; // IType or IPackageFragment private String fTypeNameWithParameters; + private List fArguments; + /** * Construct a new compilation unit proposal. * @@ -111,6 +116,36 @@ public NewCUProposal(ICompilationUnit cu, Name node, int typeKind, IJavaElement setDisplayName(); } + /** + * Construct a new compilation unit proposal. + * + * @param cu + * current compilation unit. + * @param node + * {@link Name} corresponding to the compilation unit to be created. + * @param typeKind + * possible values: { K_CLASS, K_INTERFACE, K_ENUM, K_ANNOTATION } + * @param typeContainer + * enclosing {@link IJavaElement} of the target compilation unit, can + * be {@link IType} or {@link IPackageFragment}. + * @param relevance + * the relevance of this proposal + * @param arguments + * the list of {@link Expression} nodes + */ + public NewCUProposal(ICompilationUnit cu, Name node, int typeKind, IJavaElement typeContainer, int relevance, List arguments) { + super("", null, relevance); //$NON-NLS-1$ + fCompilationUnit = cu; + fNode = node; + fTypeKind = typeKind; + fTypeContainer = typeContainer; + if (fNode != null) { + fTypeNameWithParameters = getTypeName(typeKind, node); + } + fArguments = arguments; + setDisplayName(); + } + private void setDisplayName() { String containerName; if (fNode != null) { @@ -508,7 +543,22 @@ private String constructTypeStub(ICompilationUnit parentCU, String name, int mod buf.append(name); if (fTypeKind == K_RECORD) { - buf.append("()"); + buf.append("("); + if (fArguments != null && !fArguments.isEmpty()) { + for (int i = 0; i < fArguments.size(); i++) { + if (i > 0) { + buf.append(", "); //$NON-NLS-1$ + } + Expression arg = fArguments.get(i); + ITypeBinding typeBinding = arg.resolveTypeBinding(); + String typeName = typeBinding != null && !typeBinding.isRecovered() + ? typeBinding.getName() + : "Object"; //$NON-NLS-1$ + String argName = "arg" + (i + 1); //$NON-NLS-1$ + buf.append(typeName).append(' ').append(argName); + } + } + buf.append(")"); } if (isPermitted) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/UnresolvedElementsSubProcessor.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/UnresolvedElementsSubProcessor.java index cb27e11d08..13ffcfa924 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/UnresolvedElementsSubProcessor.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/corrections/proposals/UnresolvedElementsSubProcessor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2024 IBM Corporation and others. + * Copyright (c) 2000, 2026 IBM Corporation and others. * All rights reserved. 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 @@ -24,12 +24,17 @@ import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.core.dom.ASTNode; +import org.eclipse.jdt.core.dom.ClassInstanceCreation; import org.eclipse.jdt.core.dom.CompilationUnit; +import org.eclipse.jdt.core.dom.Expression; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.NodeFinder; +import org.eclipse.jdt.core.dom.SimpleType; import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.VariableDeclarationFragment; +import org.eclipse.jdt.core.dom.VariableDeclarationStatement; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; @@ -40,7 +45,6 @@ import org.eclipse.jdt.internal.core.manipulation.JavaElementLabelsCore; import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; import org.eclipse.jdt.internal.corext.util.Messages; -import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages; import org.eclipse.jdt.internal.ui.text.correction.ReorgCorrectionsBaseSubProcessor; import org.eclipse.jdt.internal.ui.text.correction.TypeMismatchBaseSubProcessor; import org.eclipse.jdt.internal.ui.text.correction.UnresolvedElementsBaseSubProcessor; @@ -58,6 +62,7 @@ import org.eclipse.jdt.internal.ui.text.correction.proposals.ReplaceCorrectionProposalCore; import org.eclipse.jdt.ls.core.internal.JDTUtils; import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin; +import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages; import org.eclipse.jdt.ls.core.internal.corrections.ProposalKindWrapper; import org.eclipse.jdt.ls.core.internal.handlers.CodeActionHandler; import org.eclipse.jdt.ui.text.java.IInvocationContext; @@ -111,13 +116,39 @@ public static void getAnnotationMemberProposals(IInvocationContext context, IPro /* (non-Javadoc) * @see org.eclipse.jdt.internal.ui.text.correction.UnresolvedElementsBaseSubProcessor#addNewTypeProposalsInteractiveInnerLoop(org.eclipse.jdt.core.ICompilationUnit, org.eclipse.jdt.core.dom.Name, org.eclipse.jdt.core.IJavaElement, int, int, org.eclipse.jdt.core.dom.Name, java.util.Collection) */ + @SuppressWarnings("unchecked") @Override protected void addNewTypeProposalsInteractiveInnerLoop(ICompilationUnit cu, Name node, IJavaElement enclosing, int rel, int kind, Name refNode, Collection proposals) throws CoreException { if ((kind & TypeKinds.CLASSES) != 0) { NewCUProposal proposal = new NewCUProposal(cu, node, NewCUProposal.K_CLASS, enclosing, rel + 3); proposals.add(CodeActionHandler.wrap(proposal, CodeActionKind.QuickFix)); if (canUseRecord(cu.getJavaProject(), refNode)) { - proposal = new NewCUProposal(cu, node, NewCUProposal.K_RECORD, enclosing, rel + 3); + + List arguments = null; + ASTNode parent = node.getParent(); + if (parent instanceof SimpleType) { + parent = parent.getParent(); + } + if (parent instanceof VariableDeclarationStatement stmt) { + for (Object o : stmt.fragments()) { + if (o instanceof VariableDeclarationFragment frag) { + Expression init = frag.getInitializer(); + if (init instanceof ClassInstanceCreation creation) { + arguments = creation.arguments(); + } + } + + } + } + if (parent instanceof ClassInstanceCreation creation) { + arguments = creation.arguments(); + } + + if (arguments != null && arguments.isEmpty()) { + proposal = new NewCUProposal(cu, node, NewCUProposal.K_RECORD, enclosing, rel + 3); + } else { + proposal = new NewCUProposal(cu, node, NewCUProposal.K_RECORD, enclosing, rel + 3, arguments); + } proposals.add(CodeActionHandler.wrap(proposal, CodeActionKind.QuickFix)); } } diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/UnresolvedTypesQuickFixTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/UnresolvedTypesQuickFixTest.java index 8564adaf47..827af4fd4f 100644 --- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/UnresolvedTypesQuickFixTest.java +++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/correction/UnresolvedTypesQuickFixTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2013 IBM Corporation and others. + * Copyright (c) 2000, 2026 IBM Corporation and others. * All rights reserved. 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 @@ -1632,4 +1632,34 @@ void foo() { assertCodeActions(cu, e1); } + @Test + public void testTypeInStatementCreateRecordWithComponents() throws Exception { + Map options17 = new HashMap<>(); + JavaModelUtil.setComplianceOptions(options17, JavaCore.VERSION_17); + fJProject1.setOptions(options17); + + IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null); + StringBuilder buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("public class E {\n"); + buf.append(" void foo() {\n"); + buf.append(" Re1 obj = new Re1(1, \"hello\");\n"); + buf.append(" }\n"); + buf.append("}\n"); + ICompilationUnit cu = pack1.createCompilationUnit("E.java", buf.toString(), false, null); + + buf = new StringBuilder(); + buf.append("package test1;\n"); + buf.append("\n"); + buf.append("/**\n"); + buf.append(" * Re1\n"); + buf.append(" */\n"); + buf.append("public record Re1(int arg1, String arg2) {\n"); + buf.append("\n"); + buf.append("}\n"); + Expected e1 = new Expected("Create record 'Re1'", buf.toString()); + + assertCodeActionExists(cu, e1); + } + } \ No newline at end of file