Skip to content

Commit 8bfaf9d

Browse files
committed
Add field declaration and import
1 parent ce9820b commit 8bfaf9d

File tree

9 files changed

+287
-42
lines changed

9 files changed

+287
-42
lines changed

eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/META-INF/MANIFEST.MF

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0",
2323
org.eclipse.ui.editors,
2424
org.springsource.ide.eclipse.commons.core,
2525
org.eclipse.e4.ui.css.swt.theme,
26-
org.eclipse.swt
26+
org.eclipse.swt,
27+
org.eclipse.ui.workbench,
28+
org.eclipse.jdt.core.manipulation,
29+
org.eclipse.ltk.core.refactoring
2730
Bundle-RequiredExecutionEnvironment: JavaSE-21
2831
Bundle-ActivationPolicy: lazy
2932
Export-Package: org.springframework.tooling.ls.eclipse.commons,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package org.springframework.tooling.ls.eclipse.commons;
2+
3+
import java.net.URI;
4+
import java.util.LinkedList;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.Optional;
8+
9+
import org.eclipse.core.runtime.Assert;
10+
import org.eclipse.jdt.core.ICompilationUnit;
11+
import org.eclipse.jdt.core.IJavaElement;
12+
import org.eclipse.jdt.core.IJavaProject;
13+
import org.eclipse.jdt.core.IType;
14+
import org.eclipse.jdt.core.dom.AST;
15+
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
16+
import org.eclipse.jdt.core.dom.CompilationUnit;
17+
import org.eclipse.jdt.core.dom.FieldDeclaration;
18+
import org.eclipse.jdt.core.dom.Modifier;
19+
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
20+
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
21+
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
22+
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
23+
import org.eclipse.jdt.core.refactoring.CompilationUnitChange;
24+
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
25+
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
26+
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
27+
import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
28+
import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
29+
import org.eclipse.jdt.internal.ui.JavaPlugin;
30+
import org.eclipse.lsp4e.LSPEclipseUtils;
31+
import org.eclipse.lsp4j.Position;
32+
import org.eclipse.lsp4j.Range;
33+
import org.eclipse.lsp4j.ResourceOperation;
34+
import org.eclipse.lsp4j.TextDocumentEdit;
35+
import org.eclipse.lsp4j.VersionedTextDocumentIdentifier;
36+
import org.eclipse.lsp4j.jsonrpc.messages.Either;
37+
import org.eclipse.text.edits.DeleteEdit;
38+
import org.eclipse.text.edits.InsertEdit;
39+
import org.eclipse.text.edits.ReplaceEdit;
40+
import org.eclipse.text.edits.TextEdit;
41+
import org.eclipse.text.edits.TextEditGroup;
42+
import org.eclipse.ui.IEditorInput;
43+
import org.eclipse.ui.PartInitException;
44+
import org.springframework.tooling.jdt.ls.commons.Logger;
45+
import org.springframework.tooling.jdt.ls.commons.resources.ResourceUtils;
46+
47+
public final class InjectBean {
48+
49+
private final Logger logger;
50+
51+
public InjectBean(Logger logger) {
52+
this.logger = logger;
53+
}
54+
55+
public TextDocumentEdit computeEdits(String docUri, String fieldType, String fieldName) {
56+
try {
57+
URI resourceUri = URI.create(docUri);
58+
IJavaProject project = ResourceUtils.getJavaProject(resourceUri);
59+
60+
Optional<IEditorInput> optEditorInput = LSPEclipseUtils.findOpenEditorsFor(resourceUri).stream().map(e -> {
61+
try {
62+
return e.getEditorInput();
63+
} catch (PartInitException e1) {
64+
return null;
65+
}
66+
}).findFirst();
67+
68+
if (project != null && optEditorInput.isPresent()) {
69+
ICompilationUnit cu = JavaPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(optEditorInput.get());
70+
RefactoringASTParser parser= new RefactoringASTParser(IASTSharedValues.SHARED_AST_LEVEL);
71+
CompilationUnit domCu = parser.parse(cu, true);
72+
73+
74+
CompilationUnitRewrite cuRewrite = new CompilationUnitRewrite(null, cu, domCu, Map.of());
75+
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);
101+
102+
// TextEdit edit = cuRewrite.getASTRewrite().rewriteAST();
103+
104+
CompilationUnitChange c = cuRewrite.createChange(false);
105+
List<org.eclipse.lsp4j.TextEdit> textEdits = convertTextEdit(domCu, c.getEdit());
106+
107+
logger.log("Here");
108+
return textEdits.isEmpty() ? null : new TextDocumentEdit(new VersionedTextDocumentIdentifier(docUri, 0), textEdits);
109+
}
110+
111+
} catch (Exception e) {
112+
logger.log(e);
113+
}
114+
return null;
115+
}
116+
117+
private List<org.eclipse.lsp4j.TextEdit> convertTextEdit(CompilationUnit domCu, TextEdit te) {
118+
LinkedList<org.eclipse.lsp4j.TextEdit> edits = new LinkedList<>();
119+
org.eclipse.lsp4j.TextEdit edit = convertSingleEdit(domCu, te);
120+
if (edit != null) {
121+
edits.add(edit);
122+
}
123+
for (TextEdit c : te.getChildren()) {
124+
edits.addAll(convertTextEdit(domCu, c));
125+
}
126+
return edits;
127+
}
128+
129+
private org.eclipse.lsp4j.TextEdit convertSingleEdit(CompilationUnit domCu, TextEdit te) {
130+
if (te instanceof DeleteEdit de) {
131+
org.eclipse.lsp4j.TextEdit edit = new org.eclipse.lsp4j.TextEdit();
132+
int startLine = domCu.getLineNumber(de.getOffset());
133+
int startColumn = domCu.getColumnNumber(de.getOffset()) - 1;
134+
int endLine = domCu.getLineNumber(de.getOffset() + de.getLength());
135+
int endColumn = domCu.getColumnNumber(de.getOffset() + de.getLength()) - 1;
136+
edit.setNewText("");
137+
edit.setRange(new Range(new Position(startLine, startColumn), new Position(endLine, endColumn)));
138+
return edit;
139+
} else if (te instanceof ReplaceEdit re) {
140+
org.eclipse.lsp4j.TextEdit edit = new org.eclipse.lsp4j.TextEdit();
141+
int startLine = domCu.getLineNumber(re.getOffset());
142+
int startColumn = domCu.getColumnNumber(re.getOffset()) - 1;
143+
int endLine = domCu.getLineNumber(re.getOffset() + re.getLength());
144+
int endColumn = domCu.getColumnNumber(re.getOffset() + re.getLength()) - 1;
145+
edit.setNewText(re.getText());
146+
edit.setRange(new Range(new Position(startLine, startColumn), new Position(endLine, endColumn)));
147+
return edit;
148+
} else if (te instanceof InsertEdit ie) {
149+
org.eclipse.lsp4j.TextEdit edit = new org.eclipse.lsp4j.TextEdit();
150+
int startLine = domCu.getLineNumber(ie.getOffset());
151+
int startColumn = domCu.getColumnNumber(ie.getOffset()) - 1;
152+
edit.setNewText(ie.getText());
153+
edit.setRange(new Range(new Position(startLine, startColumn), new Position(startLine, startColumn)));
154+
return edit;
155+
}
156+
return null;
157+
}
158+
159+
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.eclipse.lsp4j.MarkupContent;
6060
import org.eclipse.lsp4j.MarkupKind;
6161
import org.eclipse.lsp4j.Range;
62+
import org.eclipse.lsp4j.TextDocumentEdit;
6263
import org.eclipse.lsp4j.jsonrpc.messages.Either;
6364
import org.eclipse.swt.custom.StyledText;
6465
import org.eclipse.swt.widgets.Display;
@@ -77,6 +78,7 @@
7778
import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient;
7879
import org.springframework.ide.vscode.commons.protocol.java.ClasspathListenerParams;
7980
import org.springframework.ide.vscode.commons.protocol.java.Gav;
81+
import org.springframework.ide.vscode.commons.protocol.java.InjectBeanParams;
8082
import org.springframework.ide.vscode.commons.protocol.java.JavaCodeCompleteData;
8183
import org.springframework.ide.vscode.commons.protocol.java.JavaCodeCompleteParams;
8284
import org.springframework.ide.vscode.commons.protocol.java.JavaDataParams;
@@ -646,4 +648,11 @@ public CompletableFuture<List<Gav>> projectGAV(ProjectGavParams params) {
646648
return BuildInfo.projectGAV(params, executor, Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance));
647649
}
648650

651+
@Override
652+
public CompletableFuture<TextDocumentEdit> injectBean(InjectBeanParams params) {
653+
return CompletableFuture
654+
.supplyAsync(() -> new InjectBean(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance))
655+
.computeEdits(params.docUri(), params.type(), params.name()));
656+
}
657+
649658
}

headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/STS4LanguageClient.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515

1616
import org.eclipse.lsp4j.Location;
1717
import org.eclipse.lsp4j.MarkupContent;
18+
import org.eclipse.lsp4j.ResourceOperation;
19+
import org.eclipse.lsp4j.TextDocumentEdit;
1820
import org.eclipse.lsp4j.jsonrpc.json.ResponseJsonAdapter;
1921
import org.eclipse.lsp4j.jsonrpc.messages.Either;
2022
import org.eclipse.lsp4j.jsonrpc.services.JsonNotification;
2123
import org.eclipse.lsp4j.jsonrpc.services.JsonRequest;
2224
import org.eclipse.lsp4j.services.LanguageClient;
2325
import org.springframework.ide.vscode.commons.protocol.java.ClasspathListenerParams;
2426
import org.springframework.ide.vscode.commons.protocol.java.Gav;
27+
import org.springframework.ide.vscode.commons.protocol.java.InjectBeanParams;
2528
import org.springframework.ide.vscode.commons.protocol.java.JavaCodeCompleteData;
2629
import org.springframework.ide.vscode.commons.protocol.java.JavaCodeCompleteParams;
2730
import org.springframework.ide.vscode.commons.protocol.java.JavaDataParams;
@@ -101,4 +104,7 @@ public interface STS4LanguageClient extends LanguageClient, SpringIndexLanguageC
101104
@JsonRequest("sts/project/gav")
102105
CompletableFuture<List<Gav>> projectGAV(ProjectGavParams params);
103106

107+
@JsonRequest("sts/java/injectBean")
108+
CompletableFuture<TextDocumentEdit> injectBean(InjectBeanParams params);
109+
104110
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.springframework.ide.vscode.commons.protocol.java;
2+
3+
public record InjectBeanParams(String docUri, String type, String name) {
4+
5+
}

headless-services/commons/language-server-test-harness/src/main/java/org/springframework/ide/vscode/languageserver/testharness/LanguageServerHarness.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient;
130130
import org.springframework.ide.vscode.commons.protocol.java.ClasspathListenerParams;
131131
import org.springframework.ide.vscode.commons.protocol.java.Gav;
132+
import org.springframework.ide.vscode.commons.protocol.java.InjectBeanParams;
132133
import org.springframework.ide.vscode.commons.protocol.java.JavaCodeCompleteData;
133134
import org.springframework.ide.vscode.commons.protocol.java.JavaCodeCompleteParams;
134135
import org.springframework.ide.vscode.commons.protocol.java.JavaDataParams;
@@ -486,6 +487,11 @@ public CompletableFuture<Void> refreshInlayHints() {
486487
// TODO: perhaps at some point the client would need to ask the server for new inlay-hints for opened documents.
487488
return CompletableFuture.completedFuture(null);
488489
}
490+
491+
@Override
492+
public CompletableFuture<TextDocumentEdit> injectBean(InjectBeanParams params) {
493+
return CompletableFuture.completedFuture(null);
494+
}
489495
});
490496

491497
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ BootJavaCompletionEngine javaCompletionEngine(
117117
CompilationUnitCache cuCache,
118118
SpringMetamodelIndex springIndex,
119119
RewriteRefactorings rewriteRefactorings,
120-
BootJavaConfig config) {
120+
BootJavaConfig config,
121+
SimpleLanguageServer server) {
121122

122123
SpringPropertyIndexProvider indexProvider = params.indexProvider;
123124
JavaProjectFinder javaProjectFinder = params.projectFinder;
@@ -172,7 +173,7 @@ BootJavaCompletionEngine javaCompletionEngine(
172173
providers.put(Annotations.SCHEDULED, new AnnotationAttributeCompletionProcessor(javaProjectFinder, Map.of(
173174
"cron", new CronExpressionCompletionProvider())));
174175

175-
providers.put(Annotations.BEAN, new BeanCompletionProvider(javaProjectFinder, springIndex, rewriteRefactorings, config, cuCache));
176+
providers.put(Annotations.BEAN, new BeanCompletionProvider(javaProjectFinder, springIndex, rewriteRefactorings, config, cuCache, server));
176177

177178
return new BootJavaCompletionEngine(cuCache, providers, snippetManager);
178179
}

0 commit comments

Comments
 (0)