Constructor generated

This commit is contained in:
aboyko
2025-03-12 10:59:55 -04:00
committed by BoykoAlex
parent 8bfaf9d16d
commit 61354e097a
4 changed files with 133 additions and 33 deletions

View File

@@ -1,39 +1,46 @@
package org.springframework.tooling.ls.eclipse.commons;
import java.net.URI;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.text.java.MethodDeclarationCompletionProposal;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.TextDocumentEdit;
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.text.edits.DeleteEdit;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.ReplaceEdit;
@@ -44,15 +51,129 @@ import org.eclipse.ui.PartInitException;
import org.springframework.tooling.jdt.ls.commons.Logger;
import org.springframework.tooling.jdt.ls.commons.resources.ResourceUtils;
@SuppressWarnings({ "restriction", "unchecked" })
public final class InjectBean {
private final Logger logger;
private String fieldTypeDeclarationName = null;
public InjectBean(Logger logger) {
this.logger = logger;
}
public TextDocumentEdit computeEdits(String docUri, String fieldType, String fieldName) {
private void createFieldDeclaration(IJavaProject project, CompilationUnitRewrite cuRewrite, CompilationUnit domCu,
String typeName, String fieldType, String fieldName) throws JavaModelException {
AST ast= cuRewrite.getAST();
VariableDeclarationFragment variableDeclarationFragment= ast.newVariableDeclarationFragment();
variableDeclarationFragment.setName(ast.newSimpleName(fieldName));
FieldDeclaration fieldDeclaration= ast.newFieldDeclaration(variableDeclarationFragment);
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
IType itype = project.findType(fieldType);
String fqn = itype.getFullyQualifiedName();
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
fieldTypeDeclarationName = importRewrite.addImport(fqn);
fieldDeclaration.setType(ast.newSimpleType(ast.newName(fieldTypeDeclarationName)));
AbstractTypeDeclaration parent = ((Stream<AbstractTypeDeclaration>) domCu.types().stream()
.filter(AbstractTypeDeclaration.class::isInstance)
.map(AbstractTypeDeclaration.class::cast))
.filter(td -> typeName.equals(td.getName().getIdentifier()))
.findFirst()
.orElse(null);
Assert.isNotNull(parent);
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(parent, parent.getBodyDeclarationsProperty());
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
listRewrite.insertFirst(fieldDeclaration, msg);
}
private void maybeAddConstructor(IJavaProject project, CompilationUnitRewrite cuRewrite, CompilationUnit domCu,
String typeName, String fieldType, String fieldName) {
TypeDeclaration typeDom = (TypeDeclaration) ((Stream<AbstractTypeDeclaration>) domCu.types().stream()
.filter(TypeDeclaration.class::isInstance)
.map(TypeDeclaration.class::cast))
.filter(td -> typeName.equals(td.getName().getIdentifier()))
.findFirst()
.orElse(null);
MethodDeclaration constructor = null;
boolean parameterAdded = false;
for (MethodDeclaration m : typeDom.getMethods()) {
if (m.isConstructor()) {
IMethodBinding methodBinding = m.resolveBinding();
if (methodBinding != null) {
boolean autowired = Arrays.stream(methodBinding.getAnnotations()).anyMatch(a -> "org.springframework.beans.factory.annotation.Autowired".equals(a.getAnnotationType().getQualifiedName()));
boolean hasParameter = Arrays.stream(methodBinding.getParameterTypes()).anyMatch(t -> fieldType.equals(t.getQualifiedName()));
if (autowired) {
constructor = m;
parameterAdded = hasParameter;
break;
} else {
if (constructor == null && !parameterAdded) {
constructor = m;
parameterAdded = hasParameter;
}
}
}
}
}
if (constructor == null) {
AST ast = domCu.getAST();
MethodDeclaration newConstructor = ast.newMethodDeclaration();
newConstructor.setConstructor(true);
newConstructor.setName(ast.newSimpleName(typeName));
newConstructor.parameters().add(createVariableDeclaration(ast, fieldName));
newConstructor.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
Block block = ast.newBlock();
block.statements().add(ast.newExpressionStatement(createAssignment(ast, fieldName)));
newConstructor.setBody(block);
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(typeDom, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
if (typeDom.getMethods().length == 0) {
listRewrite.insertLast(newConstructor, msg);
} else {
listRewrite.insertBefore(newConstructor, typeDom.getMethods()[0], msg);
}
} else {
AST ast = constructor.getAST();
SingleVariableDeclaration newParam = createVariableDeclaration(ast, fieldName);
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(constructor, MethodDeclaration.PARAMETERS_PROPERTY);
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
List<SingleVariableDeclaration> parameters = constructor.parameters();
listRewrite.insertAfter(newParam, parameters.get(parameters.size() - 1), msg);
Block block = constructor.getBody();
listRewrite = cuRewrite.getASTRewrite().getListRewrite(block, Block.STATEMENTS_PROPERTY);
listRewrite.insertLast(ast.newExpressionStatement(createAssignment(ast, fieldName)), msg);
}
}
private SingleVariableDeclaration createVariableDeclaration(AST ast, String fieldName) {
SingleVariableDeclaration newParam = ast.newSingleVariableDeclaration();
newParam.setName(ast.newSimpleName(fieldName));
newParam.setType(ast.newSimpleType(ast.newSimpleName(fieldTypeDeclarationName)));
return newParam;
}
private Assignment createAssignment(AST ast, String fieldName) {
Assignment assign = ast.newAssignment();
assign.setRightHandSide(ast.newSimpleName(fieldName));
FieldAccess thisField = ast.newFieldAccess();
thisField.setName(ast.newSimpleName(fieldName));
thisField.setExpression(ast.newThisExpression());
assign.setLeftHandSide(thisField);
return assign;
}
public TextDocumentEdit computeEdits(String docUri, String typeName, String fieldType, String fieldName) {
try {
URI resourceUri = URI.create(docUri);
IJavaProject project = ResourceUtils.getJavaProject(resourceUri);
@@ -73,31 +194,9 @@ public final class InjectBean {
CompilationUnitRewrite cuRewrite = new CompilationUnitRewrite(null, cu, domCu, Map.of());
AST ast= cuRewrite.getAST();
VariableDeclarationFragment variableDeclarationFragment= ast.newVariableDeclarationFragment();
variableDeclarationFragment.setName(ast.newSimpleName(fieldName));
createFieldDeclaration(project, cuRewrite, domCu, typeName, fieldType, fieldName);
FieldDeclaration fieldDeclaration= ast.newFieldDeclaration(variableDeclarationFragment);
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
IJavaElement el = project.findElement("L" + fieldType.replace(".", "/") + ";", null);
IType itype = project.findType(fieldType);
String packageName = itype.getPackageFragment().getElementName();
String fqn = itype.getFullyQualifiedName();
// org.eclipse.jdt.core.dom.ITypeBinding typeBinding= Bindings.normalizeForDeclarationUse(tb, ast);
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
ImportRewriteContext context= new ContextSensitiveImportRewriteContext(cuRewrite.getRoot(), 0, importRewrite);
// Type t = importRewrite.addImport(typeBinding, ast, context, TypeLocation.FIELD);
String typeName = importRewrite.addImport(fqn);
fieldDeclaration.setType(ast.newSimpleType(ast.newName(typeName)));
AbstractTypeDeclaration parent = (AbstractTypeDeclaration) domCu.types().get(0);
Assert.isNotNull(parent);
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(parent, parent.getBodyDeclarationsProperty());
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
listRewrite.insertFirst(fieldDeclaration, msg);
maybeAddConstructor(project, cuRewrite, domCu, typeName, fieldType, fieldName);
// TextEdit edit = cuRewrite.getASTRewrite().rewriteAST();

View File

@@ -652,7 +652,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
public CompletableFuture<TextDocumentEdit> injectBean(InjectBeanParams params) {
return CompletableFuture
.supplyAsync(() -> new InjectBean(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance))
.computeEdits(params.docUri(), params.type(), params.name()));
.computeEdits(params.docUri(), params.typeDeclarationName(), params.type(), params.name()));
}
}