16
16
17
17
package com .goide .inspections .unresolved ;
18
18
19
- import com .goide .psi .GoFieldDeclaration ;
20
- import com .goide .psi .GoReferenceExpression ;
21
- import com .goide .psi .GoStructType ;
22
- import com .goide .psi .GoType ;
23
- import com .goide .psi .impl .GoElementFactory ;
24
- import com .intellij .codeInspection .LocalQuickFixOnPsiElement ;
19
+ import com .goide .GoConstants ;
20
+ import com .goide .psi .*;
21
+ import com .goide .psi .impl .GoPsiImplUtil ;
22
+ import com .goide .util .GoUtil ;
23
+ import com .intellij .codeInsight .template .Template ;
24
+ import com .intellij .codeInsight .template .TemplateManager ;
25
+ import com .intellij .codeInsight .template .impl .ConstantNode ;
26
+ import com .intellij .codeInspection .LocalQuickFixAndIntentionActionOnPsiElement ;
27
+ import com .intellij .openapi .editor .Editor ;
25
28
import com .intellij .openapi .project .Project ;
26
29
import com .intellij .psi .PsiElement ;
27
30
import com .intellij .psi .PsiFile ;
31
+ import com .intellij .psi .util .PsiTreeUtil ;
28
32
import com .intellij .util .ObjectUtils ;
29
33
import com .intellij .util .containers .ContainerUtil ;
30
34
import org .jetbrains .annotations .Nls ;
33
37
34
38
import java .util .List ;
35
39
36
- public class GoAddStructFieldFix extends LocalQuickFixOnPsiElement {
40
+ public class GoAddStructFieldFix extends LocalQuickFixAndIntentionActionOnPsiElement {
37
41
public static final String QUICK_FIX_NAME = "Add missing field" ;
38
- private final String myFieldText ;
39
- private final String myTypeText ;
40
42
41
- protected GoAddStructFieldFix (String fieldText , String typeText , @ NotNull PsiElement element ) {
43
+ protected GoAddStructFieldFix (@ NotNull PsiElement element ) {
42
44
super (element );
43
- myFieldText = fieldText ;
44
- myTypeText = typeText ;
45
45
}
46
46
47
47
@ NotNull
@@ -51,20 +51,59 @@ public String getText() {
51
51
}
52
52
53
53
@ Override
54
- public void invoke (@ NotNull Project project , @ NotNull PsiFile file , @ NotNull PsiElement startElement , @ NotNull PsiElement endElement ) {
55
- GoStructType structType = resolveStructType (startElement );
54
+ public void invoke (@ NotNull Project project ,
55
+ @ NotNull PsiFile file ,
56
+ @ Nullable Editor editor ,
57
+ @ NotNull PsiElement startElement ,
58
+ @ NotNull PsiElement endElement ) {
59
+ if (editor == null ) return ;
60
+ GoReferenceExpression referenceExpression = ObjectUtils .tryCast (startElement , GoReferenceExpression .class );
61
+ GoStructType structType = referenceExpression != null ? resolveStructType (referenceExpression ) : null ;
56
62
if (structType == null ) return ;
63
+
57
64
List <GoFieldDeclaration > declarations = structType .getFieldDeclarationList ();
58
65
PsiElement anchor = !declarations .isEmpty () ? ContainerUtil .getLastItem (declarations ) : structType .getLbrace ();
59
- structType .addAfter (GoElementFactory .createFieldDeclaration (project , myFieldText , myTypeText ), anchor );
66
+ if (anchor == null ) return ;
67
+
68
+ startTemplate (project , editor , file , referenceExpression , anchor );
69
+ }
70
+
71
+ private static void startTemplate (@ NotNull Project project ,
72
+ @ NotNull Editor editor ,
73
+ @ NotNull PsiFile file ,
74
+ GoReferenceExpression referenceExpression ,
75
+ PsiElement anchor ) {
76
+ Template template = TemplateManager .getInstance (project ).createTemplate ("" , "" );
77
+ template .addTextSegment (referenceExpression .getReference ().getCanonicalText () + " " );
78
+ template .addVariable (new ConstantNode (getTypeName (referenceExpression , file )), true );
79
+ template .addTextSegment ("\n " );
80
+ editor .getCaretModel ().moveToOffset (anchor .getTextRange ().getEndOffset () + 1 );
81
+ template .setToReformat (true );
82
+ TemplateManager .getInstance (project ).startTemplate (editor , template );
83
+ }
84
+
85
+
86
+ private static String getTypeName (GoReferenceExpression referenceExpression , PsiFile file ) {
87
+ GoAssignmentStatement assignment = PsiTreeUtil .getParentOfType (referenceExpression , GoAssignmentStatement .class );
88
+ if (assignment == null ) return GoConstants .INTERFACE_TYPE ;
89
+ GoExpression expression = GoPsiImplUtil .getRightExpression (assignment , referenceExpression );
90
+ GoType type = expression != null ? expression .getGoType (null ) : null ;
91
+
92
+ if (type instanceof GoSpecType ) {
93
+ GoSpecType spec = (GoSpecType )type ;
94
+ GoFile typeFile = ObjectUtils .tryCast (spec .getContainingFile (), GoFile .class );
95
+ if (typeFile != null && (file .isEquivalentTo (typeFile ) || GoUtil .inSamePackage (typeFile , file ))) {
96
+ return spec .getIdentifier ().getText ();
97
+ }
98
+ }
99
+ return type != null ? GoPsiImplUtil .getText (type ) : GoConstants .INTERFACE_TYPE ;
60
100
}
61
101
62
102
@ Nullable
63
- private static GoStructType resolveStructType (@ NotNull PsiElement startElement ) {
64
- GoReferenceExpression referenceExpression = ObjectUtils .tryCast (startElement , GoReferenceExpression .class );
65
- GoReferenceExpression qualifier = referenceExpression != null ? referenceExpression .getQualifier () : null ;
66
- GoType type = qualifier != null ? qualifier .getGoType (null ) : null ;
67
- return type != null ? ObjectUtils .tryCast (type .getUnderlyingType (), GoStructType .class ) : null ;
103
+ private static GoStructType resolveStructType (@ NotNull GoReferenceExpression referenceExpression ) {
104
+ GoReferenceExpression qualifier = referenceExpression .getQualifier ();
105
+ GoSpecType type = qualifier != null ? ObjectUtils .tryCast (qualifier .getGoType (null ), GoSpecType .class ) : null ;
106
+ return type != null ? ObjectUtils .tryCast (type .getType (), GoStructType .class ) : null ;
68
107
}
69
108
70
109
@ Nls
0 commit comments