1616
1717package com .goide .inspections .unresolved ;
1818
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 ;
2528import com .intellij .openapi .project .Project ;
2629import com .intellij .psi .PsiElement ;
2730import com .intellij .psi .PsiFile ;
31+ import com .intellij .psi .util .PsiTreeUtil ;
2832import com .intellij .util .ObjectUtils ;
2933import com .intellij .util .containers .ContainerUtil ;
3034import org .jetbrains .annotations .Nls ;
3337
3438import java .util .List ;
3539
36- public class GoAddStructFieldFix extends LocalQuickFixOnPsiElement {
40+ public class GoAddStructFieldFix extends LocalQuickFixAndIntentionActionOnPsiElement {
3741 public static final String QUICK_FIX_NAME = "Add missing field" ;
38- private final String myFieldText ;
39- private final String myTypeText ;
4042
41- protected GoAddStructFieldFix (String fieldText , String typeText , @ NotNull PsiElement element ) {
43+ protected GoAddStructFieldFix (@ NotNull PsiElement element ) {
4244 super (element );
43- myFieldText = fieldText ;
44- myTypeText = typeText ;
4545 }
4646
4747 @ NotNull
@@ -51,20 +51,59 @@ public String getText() {
5151 }
5252
5353 @ 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 ;
5662 if (structType == null ) return ;
63+
5764 List <GoFieldDeclaration > declarations = structType .getFieldDeclarationList ();
5865 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 ;
60100 }
61101
62102 @ 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 ;
68107 }
69108
70109 @ Nls
0 commit comments