11package org .springframework .tooling .ls .eclipse .commons ;
22
33import java .net .URI ;
4+ import java .util .Arrays ;
45import java .util .LinkedList ;
56import java .util .List ;
67import java .util .Map ;
78import java .util .Optional ;
9+ import java .util .stream .Stream ;
810
911import org .eclipse .core .runtime .Assert ;
1012import org .eclipse .jdt .core .ICompilationUnit ;
11- import org .eclipse .jdt .core .IJavaElement ;
1213import org .eclipse .jdt .core .IJavaProject ;
1314import org .eclipse .jdt .core .IType ;
15+ import org .eclipse .jdt .core .JavaModelException ;
1416import org .eclipse .jdt .core .dom .AST ;
1517import 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 ;
1621import org .eclipse .jdt .core .dom .CompilationUnit ;
22+ import org .eclipse .jdt .core .dom .FieldAccess ;
1723import org .eclipse .jdt .core .dom .FieldDeclaration ;
24+ import org .eclipse .jdt .core .dom .IMethodBinding ;
25+ import org .eclipse .jdt .core .dom .MethodDeclaration ;
1826import org .eclipse .jdt .core .dom .Modifier ;
27+ import org .eclipse .jdt .core .dom .SingleVariableDeclaration ;
28+ import org .eclipse .jdt .core .dom .TypeDeclaration ;
1929import org .eclipse .jdt .core .dom .VariableDeclarationFragment ;
2030import org .eclipse .jdt .core .dom .rewrite .ImportRewrite ;
21- import org .eclipse .jdt .core .dom .rewrite .ImportRewrite .ImportRewriteContext ;
2231import org .eclipse .jdt .core .dom .rewrite .ListRewrite ;
2332import org .eclipse .jdt .core .refactoring .CompilationUnitChange ;
24- import org .eclipse .jdt .internal .corext .codemanipulation .ContextSensitiveImportRewriteContext ;
2533import org .eclipse .jdt .internal .corext .dom .IASTSharedValues ;
2634import org .eclipse .jdt .internal .corext .refactoring .RefactoringCoreMessages ;
2735import org .eclipse .jdt .internal .corext .refactoring .structure .CompilationUnitRewrite ;
2836import org .eclipse .jdt .internal .corext .refactoring .util .RefactoringASTParser ;
2937import org .eclipse .jdt .internal .ui .JavaPlugin ;
38+ import org .eclipse .jdt .internal .ui .text .java .MethodDeclarationCompletionProposal ;
3039import org .eclipse .lsp4e .LSPEclipseUtils ;
3140import org .eclipse .lsp4j .Position ;
3241import org .eclipse .lsp4j .Range ;
33- import org .eclipse .lsp4j .ResourceOperation ;
3442import org .eclipse .lsp4j .TextDocumentEdit ;
3543import org .eclipse .lsp4j .VersionedTextDocumentIdentifier ;
36- import org .eclipse .lsp4j .jsonrpc .messages .Either ;
3744import org .eclipse .text .edits .DeleteEdit ;
3845import org .eclipse .text .edits .InsertEdit ;
3946import org .eclipse .text .edits .ReplaceEdit ;
4451import org .springframework .tooling .jdt .ls .commons .Logger ;
4552import org .springframework .tooling .jdt .ls .commons .resources .ResourceUtils ;
4653
54+ @ SuppressWarnings ({ "restriction" , "unchecked" })
4755public 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
0 commit comments