1
1
package org .springframework .tooling .ls .eclipse .commons ;
2
2
3
3
import java .net .URI ;
4
+ import java .util .Arrays ;
4
5
import java .util .LinkedList ;
5
6
import java .util .List ;
6
7
import java .util .Map ;
7
8
import java .util .Optional ;
9
+ import java .util .stream .Stream ;
8
10
9
11
import org .eclipse .core .runtime .Assert ;
10
12
import org .eclipse .jdt .core .ICompilationUnit ;
11
- import org .eclipse .jdt .core .IJavaElement ;
12
13
import org .eclipse .jdt .core .IJavaProject ;
13
14
import org .eclipse .jdt .core .IType ;
15
+ import org .eclipse .jdt .core .JavaModelException ;
14
16
import org .eclipse .jdt .core .dom .AST ;
15
17
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 ;
16
21
import org .eclipse .jdt .core .dom .CompilationUnit ;
22
+ import org .eclipse .jdt .core .dom .FieldAccess ;
17
23
import org .eclipse .jdt .core .dom .FieldDeclaration ;
24
+ import org .eclipse .jdt .core .dom .IMethodBinding ;
25
+ import org .eclipse .jdt .core .dom .MethodDeclaration ;
18
26
import org .eclipse .jdt .core .dom .Modifier ;
27
+ import org .eclipse .jdt .core .dom .SingleVariableDeclaration ;
28
+ import org .eclipse .jdt .core .dom .TypeDeclaration ;
19
29
import org .eclipse .jdt .core .dom .VariableDeclarationFragment ;
20
30
import org .eclipse .jdt .core .dom .rewrite .ImportRewrite ;
21
- import org .eclipse .jdt .core .dom .rewrite .ImportRewrite .ImportRewriteContext ;
22
31
import org .eclipse .jdt .core .dom .rewrite .ListRewrite ;
23
32
import org .eclipse .jdt .core .refactoring .CompilationUnitChange ;
24
- import org .eclipse .jdt .internal .corext .codemanipulation .ContextSensitiveImportRewriteContext ;
25
33
import org .eclipse .jdt .internal .corext .dom .IASTSharedValues ;
26
34
import org .eclipse .jdt .internal .corext .refactoring .RefactoringCoreMessages ;
27
35
import org .eclipse .jdt .internal .corext .refactoring .structure .CompilationUnitRewrite ;
28
36
import org .eclipse .jdt .internal .corext .refactoring .util .RefactoringASTParser ;
29
37
import org .eclipse .jdt .internal .ui .JavaPlugin ;
38
+ import org .eclipse .jdt .internal .ui .text .java .MethodDeclarationCompletionProposal ;
30
39
import org .eclipse .lsp4e .LSPEclipseUtils ;
31
40
import org .eclipse .lsp4j .Position ;
32
41
import org .eclipse .lsp4j .Range ;
33
- import org .eclipse .lsp4j .ResourceOperation ;
34
42
import org .eclipse .lsp4j .TextDocumentEdit ;
35
43
import org .eclipse .lsp4j .VersionedTextDocumentIdentifier ;
36
- import org .eclipse .lsp4j .jsonrpc .messages .Either ;
37
44
import org .eclipse .text .edits .DeleteEdit ;
38
45
import org .eclipse .text .edits .InsertEdit ;
39
46
import org .eclipse .text .edits .ReplaceEdit ;
44
51
import org .springframework .tooling .jdt .ls .commons .Logger ;
45
52
import org .springframework .tooling .jdt .ls .commons .resources .ResourceUtils ;
46
53
54
+ @ SuppressWarnings ({ "restriction" , "unchecked" })
47
55
public final class InjectBean {
48
56
49
57
private final Logger logger ;
50
58
59
+ private String fieldTypeDeclarationName = null ;
60
+
51
61
public InjectBean (Logger logger ) {
52
62
this .logger = logger ;
53
63
}
54
64
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 ) {
56
177
try {
57
178
URI resourceUri = URI .create (docUri );
58
179
IJavaProject project = ResourceUtils .getJavaProject (resourceUri );
@@ -73,31 +194,9 @@ public TextDocumentEdit computeEdits(String docUri, String fieldType, String fie
73
194
74
195
CompilationUnitRewrite cuRewrite = new CompilationUnitRewrite (null , cu , domCu , Map .of ());
75
196
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 );
101
200
102
201
// TextEdit edit = cuRewrite.getASTRewrite().rewriteAST();
103
202
0 commit comments