Skip to content

Commit 61354e0

Browse files
committed
Constructor generated
1 parent 8bfaf9d commit 61354e0

File tree

4 files changed

+134
-34
lines changed

4 files changed

+134
-34
lines changed

eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/InjectBean.java

Lines changed: 130 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,46 @@
11
package org.springframework.tooling.ls.eclipse.commons;
22

33
import java.net.URI;
4+
import java.util.Arrays;
45
import java.util.LinkedList;
56
import java.util.List;
67
import java.util.Map;
78
import java.util.Optional;
9+
import java.util.stream.Stream;
810

911
import org.eclipse.core.runtime.Assert;
1012
import org.eclipse.jdt.core.ICompilationUnit;
11-
import org.eclipse.jdt.core.IJavaElement;
1213
import org.eclipse.jdt.core.IJavaProject;
1314
import org.eclipse.jdt.core.IType;
15+
import org.eclipse.jdt.core.JavaModelException;
1416
import org.eclipse.jdt.core.dom.AST;
1517
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
18+
import org.eclipse.jdt.core.dom.Assignment;
19+
import org.eclipse.jdt.core.dom.Block;
20+
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
1621
import org.eclipse.jdt.core.dom.CompilationUnit;
22+
import org.eclipse.jdt.core.dom.FieldAccess;
1723
import org.eclipse.jdt.core.dom.FieldDeclaration;
24+
import org.eclipse.jdt.core.dom.IMethodBinding;
25+
import org.eclipse.jdt.core.dom.MethodDeclaration;
1826
import org.eclipse.jdt.core.dom.Modifier;
27+
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
28+
import org.eclipse.jdt.core.dom.TypeDeclaration;
1929
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
2030
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
21-
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
2231
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
2332
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
24-
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
2533
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
2634
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
2735
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
2836
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
2937
import org.eclipse.jdt.internal.ui.JavaPlugin;
38+
import org.eclipse.jdt.internal.ui.text.java.MethodDeclarationCompletionProposal;
3039
import org.eclipse.lsp4e.LSPEclipseUtils;
3140
import org.eclipse.lsp4j.Position;
3241
import org.eclipse.lsp4j.Range;
33-
import org.eclipse.lsp4j.ResourceOperation;
3442
import org.eclipse.lsp4j.TextDocumentEdit;
3543
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
36-
import org.eclipse.lsp4j.jsonrpc.messages.Either;
3744
import org.eclipse.text.edits.DeleteEdit;
3845
import org.eclipse.text.edits.InsertEdit;
3946
import org.eclipse.text.edits.ReplaceEdit;
@@ -44,15 +51,129 @@
4451
import org.springframework.tooling.jdt.ls.commons.Logger;
4552
import org.springframework.tooling.jdt.ls.commons.resources.ResourceUtils;
4653

54+
@SuppressWarnings({ "restriction", "unchecked" })
4755
public final class InjectBean {
4856

4957
private final Logger logger;
5058

59+
private String fieldTypeDeclarationName = null;
60+
5161
public InjectBean(Logger logger) {
5262
this.logger = logger;
5363
}
5464

55-
public TextDocumentEdit computeEdits(String docUri, String fieldType, String fieldName) {
65+
private void createFieldDeclaration(IJavaProject project, CompilationUnitRewrite cuRewrite, CompilationUnit domCu,
66+
String typeName, String fieldType, String fieldName) throws JavaModelException {
67+
AST ast= cuRewrite.getAST();
68+
VariableDeclarationFragment variableDeclarationFragment= ast.newVariableDeclarationFragment();
69+
variableDeclarationFragment.setName(ast.newSimpleName(fieldName));
70+
71+
FieldDeclaration fieldDeclaration= ast.newFieldDeclaration(variableDeclarationFragment);
72+
73+
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
74+
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
75+
76+
IType itype = project.findType(fieldType);
77+
String fqn = itype.getFullyQualifiedName();
78+
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
79+
fieldTypeDeclarationName = importRewrite.addImport(fqn);
80+
fieldDeclaration.setType(ast.newSimpleType(ast.newName(fieldTypeDeclarationName)));
81+
82+
AbstractTypeDeclaration parent = ((Stream<AbstractTypeDeclaration>) domCu.types().stream()
83+
.filter(AbstractTypeDeclaration.class::isInstance)
84+
.map(AbstractTypeDeclaration.class::cast))
85+
.filter(td -> typeName.equals(td.getName().getIdentifier()))
86+
.findFirst()
87+
.orElse(null);
88+
Assert.isNotNull(parent);
89+
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(parent, parent.getBodyDeclarationsProperty());
90+
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
91+
listRewrite.insertFirst(fieldDeclaration, msg);
92+
}
93+
94+
private void maybeAddConstructor(IJavaProject project, CompilationUnitRewrite cuRewrite, CompilationUnit domCu,
95+
String typeName, String fieldType, String fieldName) {
96+
TypeDeclaration typeDom = (TypeDeclaration) ((Stream<AbstractTypeDeclaration>) domCu.types().stream()
97+
.filter(TypeDeclaration.class::isInstance)
98+
.map(TypeDeclaration.class::cast))
99+
.filter(td -> typeName.equals(td.getName().getIdentifier()))
100+
.findFirst()
101+
.orElse(null);
102+
103+
MethodDeclaration constructor = null;
104+
boolean parameterAdded = false;
105+
for (MethodDeclaration m : typeDom.getMethods()) {
106+
if (m.isConstructor()) {
107+
IMethodBinding methodBinding = m.resolveBinding();
108+
if (methodBinding != null) {
109+
boolean autowired = Arrays.stream(methodBinding.getAnnotations()).anyMatch(a -> "org.springframework.beans.factory.annotation.Autowired".equals(a.getAnnotationType().getQualifiedName()));
110+
boolean hasParameter = Arrays.stream(methodBinding.getParameterTypes()).anyMatch(t -> fieldType.equals(t.getQualifiedName()));
111+
if (autowired) {
112+
constructor = m;
113+
parameterAdded = hasParameter;
114+
break;
115+
} else {
116+
if (constructor == null && !parameterAdded) {
117+
constructor = m;
118+
parameterAdded = hasParameter;
119+
}
120+
}
121+
}
122+
}
123+
}
124+
125+
if (constructor == null) {
126+
AST ast = domCu.getAST();
127+
128+
MethodDeclaration newConstructor = ast.newMethodDeclaration();
129+
newConstructor.setConstructor(true);
130+
newConstructor.setName(ast.newSimpleName(typeName));
131+
newConstructor.parameters().add(createVariableDeclaration(ast, fieldName));
132+
newConstructor.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD));
133+
Block block = ast.newBlock();
134+
block.statements().add(ast.newExpressionStatement(createAssignment(ast, fieldName)));
135+
newConstructor.setBody(block);
136+
137+
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(typeDom, TypeDeclaration.BODY_DECLARATIONS_PROPERTY);
138+
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
139+
if (typeDom.getMethods().length == 0) {
140+
listRewrite.insertLast(newConstructor, msg);
141+
} else {
142+
listRewrite.insertBefore(newConstructor, typeDom.getMethods()[0], msg);
143+
}
144+
} else {
145+
AST ast = constructor.getAST();
146+
SingleVariableDeclaration newParam = createVariableDeclaration(ast, fieldName);
147+
148+
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(constructor, MethodDeclaration.PARAMETERS_PROPERTY);
149+
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
150+
List<SingleVariableDeclaration> parameters = constructor.parameters();
151+
listRewrite.insertAfter(newParam, parameters.get(parameters.size() - 1), msg);
152+
153+
Block block = constructor.getBody();
154+
listRewrite = cuRewrite.getASTRewrite().getListRewrite(block, Block.STATEMENTS_PROPERTY);
155+
listRewrite.insertLast(ast.newExpressionStatement(createAssignment(ast, fieldName)), msg);
156+
}
157+
}
158+
159+
private SingleVariableDeclaration createVariableDeclaration(AST ast, String fieldName) {
160+
SingleVariableDeclaration newParam = ast.newSingleVariableDeclaration();
161+
newParam.setName(ast.newSimpleName(fieldName));
162+
newParam.setType(ast.newSimpleType(ast.newSimpleName(fieldTypeDeclarationName)));
163+
return newParam;
164+
}
165+
166+
private Assignment createAssignment(AST ast, String fieldName) {
167+
Assignment assign = ast.newAssignment();
168+
assign.setRightHandSide(ast.newSimpleName(fieldName));
169+
FieldAccess thisField = ast.newFieldAccess();
170+
thisField.setName(ast.newSimpleName(fieldName));
171+
thisField.setExpression(ast.newThisExpression());
172+
assign.setLeftHandSide(thisField);
173+
return assign;
174+
}
175+
176+
public TextDocumentEdit computeEdits(String docUri, String typeName, String fieldType, String fieldName) {
56177
try {
57178
URI resourceUri = URI.create(docUri);
58179
IJavaProject project = ResourceUtils.getJavaProject(resourceUri);
@@ -73,31 +194,9 @@ public TextDocumentEdit computeEdits(String docUri, String fieldType, String fie
73194

74195
CompilationUnitRewrite cuRewrite = new CompilationUnitRewrite(null, cu, domCu, Map.of());
75196

76-
AST ast= cuRewrite.getAST();
77-
VariableDeclarationFragment variableDeclarationFragment= ast.newVariableDeclarationFragment();
78-
variableDeclarationFragment.setName(ast.newSimpleName(fieldName));
79-
80-
FieldDeclaration fieldDeclaration= ast.newFieldDeclaration(variableDeclarationFragment);
81-
82-
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PRIVATE_KEYWORD));
83-
fieldDeclaration.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.FINAL_KEYWORD));
84-
85-
IJavaElement el = project.findElement("L" + fieldType.replace(".", "/") + ";", null);
86-
IType itype = project.findType(fieldType);
87-
String packageName = itype.getPackageFragment().getElementName();
88-
String fqn = itype.getFullyQualifiedName();
89-
// org.eclipse.jdt.core.dom.ITypeBinding typeBinding= Bindings.normalizeForDeclarationUse(tb, ast);
90-
ImportRewrite importRewrite= cuRewrite.getImportRewrite();
91-
ImportRewriteContext context= new ContextSensitiveImportRewriteContext(cuRewrite.getRoot(), 0, importRewrite);
92-
// Type t = importRewrite.addImport(typeBinding, ast, context, TypeLocation.FIELD);
93-
String typeName = importRewrite.addImport(fqn);
94-
fieldDeclaration.setType(ast.newSimpleType(ast.newName(typeName)));
95-
96-
AbstractTypeDeclaration parent = (AbstractTypeDeclaration) domCu.types().get(0);
97-
Assert.isNotNull(parent);
98-
ListRewrite listRewrite= cuRewrite.getASTRewrite().getListRewrite(parent, parent.getBodyDeclarationsProperty());
99-
TextEditGroup msg= cuRewrite.createGroupDescription(RefactoringCoreMessages.ExtractConstantRefactoring_declare_constant);
100-
listRewrite.insertFirst(fieldDeclaration, msg);
197+
createFieldDeclaration(project, cuRewrite, domCu, typeName, fieldType, fieldName);
198+
199+
maybeAddConstructor(project, cuRewrite, domCu, typeName, fieldType, fieldName);
101200

102201
// TextEdit edit = cuRewrite.getASTRewrite().rewriteAST();
103202

eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageClientImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ public CompletableFuture<List<Gav>> projectGAV(ProjectGavParams params) {
652652
public CompletableFuture<TextDocumentEdit> injectBean(InjectBeanParams params) {
653653
return CompletableFuture
654654
.supplyAsync(() -> new InjectBean(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance))
655-
.computeEdits(params.docUri(), params.type(), params.name()));
655+
.computeEdits(params.docUri(), params.typeDeclarationName(), params.type(), params.name()));
656656
}
657657

658658
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package org.springframework.ide.vscode.commons.protocol.java;
22

3-
public record InjectBeanParams(String docUri, String type, String name) {
3+
public record InjectBeanParams(String docUri, String typeDeclarationName, String type, String name) {
44

55
}

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeanCompletionProposal.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ public Optional<Supplier<DocumentEdits>> getAdditionalEdit() {
315315
long start = System.currentTimeMillis();
316316
DocumentEdits additionalEdit = new DocumentEdits(doc, false);
317317
try {
318-
TextDocumentEdit beanInjectEdits = server.getClient().injectBean(new InjectBeanParams(doc.getUri(), beanType, fieldName)).get();
318+
TextDocumentEdit beanInjectEdits = server.getClient().injectBean(new InjectBeanParams(doc.getUri(),
319+
JavaType.ShallowClass.build(className).getClassName(), beanType, fieldName)).get();
319320
if (beanInjectEdits != null) {
320321
for (org.eclipse.lsp4j.TextEdit e : beanInjectEdits.getEdits()) {
321322
try {

0 commit comments

Comments
 (0)