Skip to content

Commit

Permalink
Add setting to make variables/fields created via code action final.
Browse files Browse the repository at this point in the history
- Adds `java.codeGeneration.addFinalForNewDeclaration` setting
which changes the behavior of the "Assign statement to new (local
variable|field)", "Create (local variable|field)", "Assign parameter to
new field", "Assign all parameters to new fields".
- Possible values are  "none", "variables", "fields", "all"
  • Loading branch information
mfussenegger authored and rgrunber committed Apr 4, 2024
1 parent 24cd1ba commit fbdd01c
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,11 @@ private boolean getExtractVariableProposal(CodeActionParams params, IInvocationC
}

private boolean getAssignToVariableProposals(IInvocationContext context, ASTNode node, IProblemLocation[] locations, Collection<ProposalKindWrapper> resultingCollections, CodeActionParams params) {
String declsToFinal = this.preferenceManager.getPreferences().getCodeGenerationAddFinalForNewDeclaration();
try {
Map formatterOptions = null;
ProposalKindWrapper proposal = RefactorProposalUtility.getAssignVariableProposal(params, context, locations != null && locations.length != 0, formatterOptions,
this.preferenceManager.getClientPreferences().isAdvancedExtractRefactoringSupported(), locations);
this.preferenceManager.getClientPreferences().isAdvancedExtractRefactoringSupported(), locations, ("all".equals(declsToFinal) || "variables".equals(declsToFinal)));
if (proposal != null) {
resultingCollections.add(proposal);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
import org.eclipse.jdt.internal.corext.fix.LinkedProposalPositionGroupCore.PositionInformation;
import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceParameterRefactoring;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.RefactoringCorrectionProposalCore;
import org.eclipse.jdt.ls.core.internal.ChangeUtil;
Expand All @@ -49,6 +47,8 @@
import org.eclipse.jdt.ls.core.internal.handlers.InferSelectionHandler.SelectionInfo;
import org.eclipse.jdt.ls.core.internal.handlers.MoveHandler.PackageNode;
import org.eclipse.jdt.ls.core.internal.text.correction.RefactorProposalUtility;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.lsp4j.ChangeAnnotation;
import org.eclipse.lsp4j.CodeActionParams;
import org.eclipse.lsp4j.Command;
Expand Down Expand Up @@ -258,8 +258,10 @@ private static ProposalKindWrapper getExtractVariableProposal(CodeActionParams p

private static ProposalKindWrapper getAssignVariableProposal(GetRefactorEditParams params, IInvocationContext context, boolean problemsAtLocation, String refactorType, Map formatterOptions, IProblemLocation[] locations)
throws CoreException {
String declsToFinal = JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getCodeGenerationAddFinalForNewDeclaration();

if (RefactorProposalUtility.ASSIGN_VARIABLE_COMMAND.equals(refactorType)) {
return RefactorProposalUtility.getAssignVariableProposal(params.context, context, problemsAtLocation, formatterOptions, false, locations);
return RefactorProposalUtility.getAssignVariableProposal(params.context, context, problemsAtLocation, formatterOptions, false, locations, ("all".equals(declsToFinal) || "variables".equals(declsToFinal)));
}
if (RefactorProposalUtility.ASSIGN_FIELD_COMMAND.equals(refactorType)) {
return RefactorProposalUtility.getAssignFieldProposal(params.context, context, problemsAtLocation, formatterOptions, false, locations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ public class Preferences {
// A named preference that defines the location to insert the code generated by source actions.
public static final String JAVA_CODEGENERATION_INSERTIONLOCATION = "java.codeGeneration.insertionLocation";

// A named preference that defines that fields created via code generation should be declared final
public static final String JAVA_CODEGENERATION_ADD_FINAL_FOR_NEW_DECLARATION = "java.codeGeneration.addFinalForNewDeclaration";

// Specifies the file header snippets for new Java file.
public static final String JAVA_TEMPLATES_FILEHEADER = "java.templates.fileHeader";
// Specifies the type comment snippets for new Java type.
Expand Down Expand Up @@ -637,6 +640,7 @@ public class Preferences {
private boolean generateToStringListArrayContents;
private int generateToStringLimitElements;
private String codeGenerationInsertionLocation;
private String codeGenerationAddFinalForNewDeclaration;
private List<String> preferredContentProviderIds;
private boolean includeAccessors;
private boolean smartSemicolonDetection;
Expand Down Expand Up @@ -891,6 +895,7 @@ public Preferences() {
generateToStringSkipNullValues = false;
generateToStringListArrayContents = true;
generateToStringLimitElements = 0;
codeGenerationAddFinalForNewDeclaration = "none";
codeGenerationInsertionLocation = null;
preferredContentProviderIds = null;
javaImportExclusions = JAVA_IMPORT_EXCLUSIONS_DEFAULT;
Expand Down Expand Up @@ -1114,6 +1119,9 @@ public static Preferences createFrom(Map<String, Object> configuration) {
String insertionLocation = getString(configuration, JAVA_CODEGENERATION_INSERTIONLOCATION);
prefs.setCodeGenerationInsertionLocation(insertionLocation);

String newFieldsFinal = getString(configuration, JAVA_CODEGENERATION_ADD_FINAL_FOR_NEW_DECLARATION);
prefs.setCodeGenerationAddFinalForNewDeclaration(newFieldsFinal);

List<String> javaImportExclusions = getList(configuration, JAVA_IMPORT_EXCLUSIONS_KEY, JAVA_IMPORT_EXCLUSIONS_DEFAULT);
if (javaImportExclusions instanceof LinkedList) {
prefs.setJavaImportExclusions(javaImportExclusions);
Expand Down Expand Up @@ -1929,6 +1937,14 @@ public int getGenerateToStringLimitElements() {
return generateToStringLimitElements;
}

public String getCodeGenerationAddFinalForNewDeclaration() {
return codeGenerationAddFinalForNewDeclaration;
}

public void setCodeGenerationAddFinalForNewDeclaration(String declValue) {
this.codeGenerationAddFinalForNewDeclaration = declValue;
}

public String getCodeGenerationInsertionLocation() {
return codeGenerationInsertionLocation;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ public class AssignToVariableAssistCommandProposal extends AssignToVariableAssis
private String command;
private List<Object> commandArguments;

public AssignToVariableAssistCommandProposal(ICompilationUnit cu, int variableKind, ExpressionStatement node, ITypeBinding typeBinding, int relevance, String command, List<Object> commandArguments) {
super(cu, variableKind, node, typeBinding, relevance, false);
public AssignToVariableAssistCommandProposal(ICompilationUnit cu, int variableKind, ExpressionStatement node, ITypeBinding typeBinding, int relevance, String command, List<Object> commandArguments, boolean addFinal) {
super(cu, variableKind, node, typeBinding, relevance, addFinal);
this.command = command;
this.commandArguments = commandArguments;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,6 @@
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesAnalyzer;
import org.eclipse.jdt.internal.corext.refactoring.surround.SurroundWithTryWithResourcesRefactoringCore;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.internal.ui.text.correction.QuickAssistProcessorUtil;
import org.eclipse.jdt.internal.ui.text.correction.proposals.AssignToVariableAssistProposalCore;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposalCore;
Expand All @@ -138,6 +136,8 @@
import org.eclipse.jdt.ls.core.internal.corrections.proposals.JavadocTagsSubProcessor;
import org.eclipse.jdt.ls.core.internal.handlers.CodeActionHandler;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.jdt.ui.text.java.IInvocationContext;
import org.eclipse.jdt.ui.text.java.IProblemLocation;
import org.eclipse.jdt.ui.text.java.correction.ASTRewriteCorrectionProposalCore;
import org.eclipse.jface.text.link.LinkedPositionGroup;
import org.eclipse.lsp4j.CodeActionKind;
Expand Down Expand Up @@ -170,6 +170,7 @@ public QuickAssistProcessor(PreferenceManager preferenceManager) {

public List<ProposalKindWrapper> getAssists(CodeActionParams params, IInvocationContext context, IProblemLocation[] locations) throws CoreException {
ASTNode coveringNode = context.getCoveringNode();
String declsToFinal = this.preferenceManager.getPreferences().getCodeGenerationAddFinalForNewDeclaration();
if (coveringNode != null) {
// ArrayList<ASTNode> coveredNodes = getFullyCoveredNodes(context, coveringNode);
ArrayList<ProposalKindWrapper> resultingCollections = new ArrayList<>();
Expand All @@ -178,8 +179,8 @@ public List<ProposalKindWrapper> getAssists(CodeActionParams params, IInvocation
// getRenameLocalProposals(context, coveringNode, locations, resultingCollections);
// getRenameRefactoringProposal(context, coveringNode, locations, resultingCollections);
// getAssignToVariableProposals(context, coveringNode, locations, resultingCollections);
getAssignParamToFieldProposals(context, coveringNode, resultingCollections);
getAssignAllParamsToFieldsProposals(context, coveringNode, resultingCollections);
getAssignParamToFieldProposals(context, coveringNode, resultingCollections, ("all".equals(declsToFinal) || "fields".equals(declsToFinal)));
getAssignAllParamsToFieldsProposals(context, coveringNode, resultingCollections, ("all".equals(declsToFinal) || "fields".equals(declsToFinal)));
// getInferDiamondArgumentsProposal(context, coveringNode, locations, resultingCollections);
// getGenerateForLoopProposals(context, coveringNode, locations, resultingCollections);

Expand Down Expand Up @@ -300,7 +301,7 @@ private static boolean getConvertLambdaExpressionAndMethodRefCleanUpProposal(IIn
return true;
}

private static boolean getAssignParamToFieldProposals(IInvocationContext context, ASTNode node, Collection<ProposalKindWrapper> resultingCollections) {
private static boolean getAssignParamToFieldProposals(IInvocationContext context, ASTNode node, Collection<ProposalKindWrapper> resultingCollections, boolean addFinal) {
node = ASTNodes.getNormalizedNode(node);
ASTNode parent = node.getParent();
if (!(parent instanceof SingleVariableDeclaration) || !(parent.getParent() instanceof MethodDeclaration)) {
Expand Down Expand Up @@ -345,12 +346,12 @@ private static boolean getAssignParamToFieldProposals(IInvocationContext context
}
}

AssignToVariableAssistProposalCore fieldProposal = new AssignToVariableAssistProposalCore(context.getCompilationUnit(), paramDecl, null, typeBinding, IProposalRelevance.ASSIGN_PARAM_TO_NEW_FIELD, false);
AssignToVariableAssistProposalCore fieldProposal = new AssignToVariableAssistProposalCore(context.getCompilationUnit(), paramDecl, null, typeBinding, IProposalRelevance.ASSIGN_PARAM_TO_NEW_FIELD, addFinal);
resultingCollections.add(CodeActionHandler.wrap(fieldProposal, JavaCodeActionKind.QUICK_ASSIST));
return true;
}

private static boolean getAssignAllParamsToFieldsProposals(IInvocationContext context, ASTNode node, Collection<ProposalKindWrapper> resultingCollections) {
private static boolean getAssignAllParamsToFieldsProposals(IInvocationContext context, ASTNode node, Collection<ProposalKindWrapper> resultingCollections, boolean addFinal) {
node = ASTNodes.getNormalizedNode(node);
ASTNode parent = node.getParent();
if (!(parent instanceof SingleVariableDeclaration) || !(parent.getParent() instanceof MethodDeclaration)) {
Expand Down Expand Up @@ -378,7 +379,7 @@ private static boolean getAssignAllParamsToFieldsProposals(IInvocationContext co
return true;
}

AssignToVariableAssistProposalCore fieldProposal = new AssignToVariableAssistProposalCore(context.getCompilationUnit(), parameters, IProposalRelevance.ASSIGN_ALL_PARAMS_TO_NEW_FIELDS, false);
AssignToVariableAssistProposalCore fieldProposal = new AssignToVariableAssistProposalCore(context.getCompilationUnit(), parameters, IProposalRelevance.ASSIGN_ALL_PARAMS_TO_NEW_FIELDS, addFinal);
resultingCollections.add(CodeActionHandler.wrap(fieldProposal, JavaCodeActionKind.QUICK_ASSIST));
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ public static boolean containsMatchingProblem(IProblemLocation[] locations, int
}

public static ProposalKindWrapper getAssignVariableProposal(CodeActionParams params, IInvocationContext context, boolean problemsAtLocation, Map formatterOptions, boolean returnAsCommand,
IProblemLocation[] locations)
IProblemLocation[] locations, boolean addFinal)
throws CoreException {
ASTNode node = context.getCoveringNode();
Statement statement = ASTResolving.findParentStatement(node);
Expand Down Expand Up @@ -509,16 +509,17 @@ public static ProposalKindWrapper getAssignVariableProposal(CodeActionParams par
if (returnAsCommand) {
AssignToVariableAssistCommandProposal p = new AssignToVariableAssistCommandProposal(cu, AssignToVariableAssistProposalCore.LOCAL, expressionStatement, typeBinding, relevance,
APPLY_REFACTORING_COMMAND_ID,
Arrays.asList(ASSIGN_VARIABLE_COMMAND, params));
Arrays.asList(ASSIGN_VARIABLE_COMMAND, params), addFinal);
return CodeActionHandler.wrap(p, JavaCodeActionKind.REFACTOR_ASSIGN_VARIABLE);
} else {
AssignToVariableAssistProposalCore p = new AssignToVariableAssistProposalCore(cu, AssignToVariableAssistProposalCore.LOCAL, expressionStatement, typeBinding, relevance, false);
AssignToVariableAssistProposalCore p = new AssignToVariableAssistProposalCore(cu, AssignToVariableAssistProposalCore.LOCAL, expressionStatement, typeBinding, relevance, addFinal);
return CodeActionHandler.wrap(p, JavaCodeActionKind.REFACTOR_ASSIGN_VARIABLE);
}
}

public static ProposalKindWrapper getAssignFieldProposal(CodeActionParams params, IInvocationContext context, boolean problemsAtLocation, Map formatterOptions, boolean returnAsCommand,
IProblemLocation[] locations) throws CoreException {
String declsToFinal = JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getCodeGenerationAddFinalForNewDeclaration();
ASTNode node = context.getCoveringNode();
Statement statement = ASTResolving.findParentStatement(node);
if (!(statement instanceof ExpressionStatement)) {
Expand Down Expand Up @@ -548,12 +549,14 @@ public static ProposalKindWrapper getAssignFieldProposal(CodeActionParams params
} else {
relevance = IProposalRelevance.EXTRACT_LOCAL;
}

if (returnAsCommand) {
AssignToVariableAssistCommandProposal proposal = new AssignToVariableAssistCommandProposal(cu, AssignToVariableAssistProposalCore.FIELD, expressionStatement, typeBinding, relevance, APPLY_REFACTORING_COMMAND_ID,
Arrays.asList(ASSIGN_FIELD_COMMAND, params));
Arrays.asList(ASSIGN_FIELD_COMMAND, params), ("all".equals(declsToFinal) || "fields".equals(declsToFinal)));
return CodeActionHandler.wrap(proposal, JavaCodeActionKind.REFACTOR_ASSIGN_FIELD);
} else {
AssignToVariableAssistProposalCore proposal = new AssignToVariableAssistProposalCore(cu, AssignToVariableAssistProposalCore.FIELD, expressionStatement, typeBinding, relevance, false);
AssignToVariableAssistProposalCore proposal = new AssignToVariableAssistProposalCore(cu, AssignToVariableAssistProposalCore.FIELD, expressionStatement, typeBinding, relevance,
("all".equals(declsToFinal) || "fields".equals(declsToFinal)));
return CodeActionHandler.wrap(proposal, JavaCodeActionKind.REFACTOR_ASSIGN_FIELD);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,37 @@ public void testAssignParamToField() throws Exception {
assertCodeActions(cu, selection, e1);
}

@Test
public void testAssignParamToFieldWithFinalSetting() throws Exception {
preferences.setCodeGenerationAddFinalForNewDeclaration("fields");
try {
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
StringBuilder buf = new StringBuilder();
buf.append("package test1;\n");
buf.append("public class E {\n");
buf.append(" public E(int count) {\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("public class E {\n");
buf.append(" private final int count;\n");
buf.append("\n");
buf.append(" public E(int count) {\n");
buf.append(" this.count = count;\n");
buf.append(" }\n");
buf.append("}\n");
Expected e1 = new Expected("Assign parameter to new field", buf.toString());

Range selection = CodeActionUtil.getRange(cu, "count");
assertCodeActions(cu, selection, e1);
} finally {
preferences.setCodeGenerationAddFinalForNewDeclaration(null);
}
}

@Test
public void testAssignParamToField2() throws Exception {
IPackageFragment pack1 = fSourceFolder.createPackageFragment("test1", false, null);
Expand Down

0 comments on commit fbdd01c

Please sign in to comment.