@@ -61,11 +61,32 @@ private static Data getData(@NotNull PsiElement element) {
61
61
if (!element .isValid () || !element .isWritable ()) return null ;
62
62
GoAssignmentStatement assignment = getValidAssignmentParent (element );
63
63
GoReferenceExpression selectedFieldReference = assignment != null ? getFieldReferenceExpression (element , assignment ) : null ;
64
- GoCompositeLit compositeLit = selectedFieldReference != null ? getStructLiteralByReference (selectedFieldReference , assignment ) : null ;
65
- if (compositeLit == null ) return null ;
64
+ if (selectedFieldReference == null ) return null ;
66
65
67
- List <GoReferenceExpression > references = getUninitializedSingleFieldReferences (assignment , selectedFieldReference , compositeLit );
68
- return !references .isEmpty () ? new Data (assignment , compositeLit , references ) : null ;
66
+ GoVarDefinition structDefinition = getDefinition (selectedFieldReference );
67
+ GoStatement previousStatement = PsiTreeUtil .getPrevSiblingOfType (assignment , GoStatement .class );
68
+ boolean needReplaceDeclarationWithShortVar = isUnassigned (getSingleVarSpecByDefinition (previousStatement , structDefinition ));
69
+
70
+ GoCompositeLit compositeLit = needReplaceDeclarationWithShortVar
71
+ ? createStructLiteral (structDefinition , previousStatement .getProject ())
72
+ : getStructLiteralByReference (selectedFieldReference , assignment );
73
+ if (compositeLit == null || structDefinition == null ) return null ;
74
+
75
+ List <GoReferenceExpression > references = getUninitializedSingleFieldReferences (assignment , structDefinition , compositeLit );
76
+ return !references .isEmpty () ? new Data (assignment , compositeLit , references , previousStatement , structDefinition .getText (),
77
+ needReplaceDeclarationWithShortVar ) : null ;
78
+ }
79
+
80
+ @ Nullable
81
+ private static GoCompositeLit createStructLiteral (@ NotNull GoVarDefinition definition , @ NotNull Project project ) {
82
+ GoType type = definition .getGoType (null );
83
+ return type != null ? GoElementFactory .createCompositeLit (project , type ) : null ;
84
+ }
85
+
86
+ @ Nullable
87
+ @ Contract ("null -> null" )
88
+ private static GoVarDefinition getDefinition (@ Nullable GoReferenceExpression referenceExpressions ) {
89
+ return ObjectUtils .tryCast (resolveQualifier (referenceExpressions ), GoVarDefinition .class );
69
90
}
70
91
71
92
@ Nullable
@@ -104,6 +125,22 @@ private static GoReferenceExpression unwrapParensAndCast(@Nullable PsiElement e)
104
125
return ObjectUtils .tryCast (e , GoReferenceExpression .class );
105
126
}
106
127
128
+ @ Nullable
129
+ @ Contract ("_, null -> null; null, _ -> null" )
130
+ private static GoVarSpec getSingleVarSpecByDefinition (@ Nullable GoStatement statement ,
131
+ @ Nullable GoVarDefinition definition ) {
132
+ GoVarDeclaration declaration = statement != null ? statement .getVarDeclaration () : null ;
133
+ List <GoVarSpec > varSpecs = declaration != null ? declaration .getVarSpecList () : emptyList ();
134
+ GoVarSpec singleVarSpec = varSpecs .size () == 1 ? getFirstItem (varSpecs ) : null ;
135
+ List <GoVarDefinition > varDefinitions = singleVarSpec != null ? singleVarSpec .getVarDefinitionList () : emptyList ();
136
+ return varDefinitions .size () == 1 && definition == getFirstItem (varDefinitions ) ? singleVarSpec : null ;
137
+ }
138
+
139
+ @ Contract ("null -> false" )
140
+ private static boolean isUnassigned (@ Nullable GoVarSpec varSpec ) {
141
+ return varSpec != null && varSpec .getExpressionList ().isEmpty ();
142
+ }
143
+
107
144
@ Contract ("null -> false" )
108
145
private static boolean isFieldReferenceExpression (@ Nullable PsiElement element ) {
109
146
return element instanceof GoReferenceExpression && isFieldDefinition (((GoReferenceExpression )element ).resolve ());
@@ -138,11 +175,10 @@ private static boolean isResolvedTo(@Nullable PsiElement e, @Nullable PsiElement
138
175
139
176
@ NotNull
140
177
private static List <GoReferenceExpression > getUninitializedSingleFieldReferences (@ NotNull GoAssignmentStatement assignment ,
141
- @ NotNull GoReferenceExpression fieldReferenceExpression ,
178
+ @ Nullable GoVarDefinition definition ,
142
179
@ NotNull GoCompositeLit compositeLit ) {
143
- PsiElement resolve = resolveQualifier (fieldReferenceExpression );
144
180
List <GoReferenceExpression > uninitializedFieldReferencesByQualifier =
145
- filter (getUninitializedFieldReferenceExpressions (assignment , compositeLit ), e -> isResolvedTo (e .getQualifier (), resolve ));
181
+ filter (getUninitializedFieldReferenceExpressions (assignment , compositeLit ), e -> isResolvedTo (e .getQualifier (), definition ));
146
182
MultiMap <PsiElement , GoReferenceExpression > resolved = groupBy (uninitializedFieldReferencesByQualifier , GoReferenceExpression ::resolve );
147
183
return map (filter (resolved .entrySet (), set -> set .getValue ().size () == 1 ), set -> getFirstItem (set .getValue ()));
148
184
}
@@ -151,13 +187,15 @@ private static List<GoReferenceExpression> getUninitializedSingleFieldReferences
151
187
private static GoCompositeLit getStructLiteralByReference (@ NotNull GoReferenceExpression fieldReferenceExpression ,
152
188
@ NotNull GoAssignmentStatement assignment ) {
153
189
GoStatement previousStatement = PsiTreeUtil .getPrevSiblingOfType (assignment , GoStatement .class );
190
+ if (previousStatement == null ) return null ;
191
+
154
192
if (previousStatement instanceof GoSimpleStatement ) {
155
193
return getStructLiteral (fieldReferenceExpression , (GoSimpleStatement )previousStatement );
156
194
}
157
195
if (previousStatement instanceof GoAssignmentStatement ) {
158
196
return getStructLiteral (fieldReferenceExpression , (GoAssignmentStatement )previousStatement );
159
197
}
160
- return null ;
198
+ return getStructLiteral ( previousStatement , fieldReferenceExpression ) ;
161
199
}
162
200
163
201
@ Nullable
@@ -172,15 +210,16 @@ private static GoCompositeLit getStructLiteral(@NotNull GoReferenceExpression fi
172
210
}
173
211
174
212
@ Nullable
175
- private static PsiElement resolveQualifier (@ NotNull GoReferenceExpression fieldReferenceExpression ) {
176
- GoReferenceExpression qualifier = fieldReferenceExpression .getQualifier ();
213
+ @ Contract ("null -> null" )
214
+ private static PsiElement resolveQualifier (@ Nullable GoReferenceExpression fieldReferenceExpression ) {
215
+ GoReferenceExpression qualifier = fieldReferenceExpression != null ? fieldReferenceExpression .getQualifier () : null ;
177
216
return qualifier != null ? qualifier .resolve () : null ;
178
217
}
179
218
180
219
@ Nullable
181
220
private static GoCompositeLit getStructLiteral (@ NotNull GoReferenceExpression fieldReferenceExpression ,
182
221
@ NotNull GoAssignmentStatement structAssignment ) {
183
- GoVarDefinition varDefinition = ObjectUtils . tryCast ( resolveQualifier ( fieldReferenceExpression ), GoVarDefinition . class );
222
+ GoVarDefinition varDefinition = getDefinition ( fieldReferenceExpression );
184
223
PsiElement field = fieldReferenceExpression .resolve ();
185
224
if (varDefinition == null || !isFieldDefinition (field ) || !hasStructTypeWithField (varDefinition , (GoNamedElement )field )) {
186
225
return null ;
@@ -193,6 +232,14 @@ private static GoCompositeLit getStructLiteral(@NotNull GoReferenceExpression fi
193
232
return ObjectUtils .tryCast (compositeLit , GoCompositeLit .class );
194
233
}
195
234
235
+ @ Nullable
236
+ private static GoCompositeLit getStructLiteral (@ NotNull GoStatement statement ,
237
+ @ NotNull GoReferenceExpression fieldReferenceExpression ) {
238
+ GoVarDefinition definition = getDefinition (fieldReferenceExpression );
239
+ GoVarSpec varSpec = definition != null ? getSingleVarSpecByDefinition (statement , definition ) : null ;
240
+ return varSpec != null ? ObjectUtils .tryCast (getFirstItem (varSpec .getRightExpressionsList ()), GoCompositeLit .class ) : null ;
241
+ }
242
+
196
243
private static boolean hasStructTypeWithField (@ NotNull GoVarDefinition structVarDefinition , @ NotNull GoNamedElement field ) {
197
244
GoType type = structVarDefinition .getGoType (null );
198
245
GoStructType structType = type != null ? ObjectUtils .tryCast (type .getUnderlyingType (), GoStructType .class ) : null ;
@@ -239,6 +286,10 @@ public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement
239
286
Data data = getData (element );
240
287
if (data == null ) return ;
241
288
moveFieldReferenceExpressions (data );
289
+
290
+ if (!data .needReplaceDeclarationWithShortVar ()) return ;
291
+ data .getStructDeclaration ()
292
+ .replace (GoElementFactory .createShortVarDeclarationStatement (project , data .getStructVarName (), data .getCompositeLit ().getText ()));
242
293
}
243
294
244
295
private static void moveFieldReferenceExpressions (@ NotNull Data data ) {
@@ -272,13 +323,22 @@ private static class Data {
272
323
private final GoCompositeLit myCompositeLit ;
273
324
private final GoAssignmentStatement myAssignment ;
274
325
private final List <GoReferenceExpression > myReferenceExpressions ;
326
+ private final GoStatement myStructDeclaration ;
327
+ private final String myStructVarName ;
328
+ private final boolean myNeedReplaceDeclarationWithShortVar ;
275
329
276
330
public Data (@ NotNull GoAssignmentStatement assignment ,
277
- @ NotNull GoCompositeLit compositeLit ,
278
- @ NotNull List <GoReferenceExpression > referenceExpressions ) {
331
+ @ Nullable GoCompositeLit compositeLit ,
332
+ @ NotNull List <GoReferenceExpression > referenceExpressions ,
333
+ @ Nullable GoStatement structDeclaration ,
334
+ @ Nullable String structVarName ,
335
+ boolean needReplaceDeclarationWithShortVar ) {
279
336
myCompositeLit = compositeLit ;
280
337
myAssignment = assignment ;
281
338
myReferenceExpressions = referenceExpressions ;
339
+ myStructDeclaration = structDeclaration ;
340
+ myStructVarName = structVarName ;
341
+ myNeedReplaceDeclarationWithShortVar = needReplaceDeclarationWithShortVar ;
282
342
}
283
343
284
344
public GoCompositeLit getCompositeLit () {
@@ -292,5 +352,19 @@ public GoAssignmentStatement getAssignment() {
292
352
public List <GoReferenceExpression > getReferenceExpressions () {
293
353
return myReferenceExpressions ;
294
354
}
355
+
356
+ public GoStatement getStructDeclaration () {
357
+ return myStructDeclaration ;
358
+ }
359
+
360
+ public String getStructVarName () {
361
+ return myStructVarName ;
362
+ }
363
+
364
+ public boolean needReplaceDeclarationWithShortVar () {
365
+ return myNeedReplaceDeclarationWithShortVar ;
366
+ }
295
367
}
296
368
}
369
+
370
+
0 commit comments