Skip to content

Commit a2737bd

Browse files
committed
Add templates
1 parent 9f63fbf commit a2737bd

File tree

8 files changed

+86
-37
lines changed

8 files changed

+86
-37
lines changed

src/com/goide/inspections/unresolved/GoAddStructFieldFix.java

+59-20
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,19 @@
1616

1717
package 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;
2528
import com.intellij.openapi.project.Project;
2629
import com.intellij.psi.PsiElement;
2730
import com.intellij.psi.PsiFile;
31+
import com.intellij.psi.util.PsiTreeUtil;
2832
import com.intellij.util.ObjectUtils;
2933
import com.intellij.util.containers.ContainerUtil;
3034
import org.jetbrains.annotations.Nls;
@@ -33,15 +37,11 @@
3337

3438
import 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

src/com/goide/inspections/unresolved/GoUnresolvedReferenceInspection.java

+1-10
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import com.goide.codeInsight.imports.GoImportPackageQuickFix;
2121
import com.goide.inspections.GoInspectionBase;
2222
import com.goide.psi.*;
23-
import com.goide.psi.impl.GoPsiImplUtil;
2423
import com.goide.psi.impl.GoReference;
2524
import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector;
2625
import com.intellij.codeInspection.LocalInspectionToolSession;
@@ -79,7 +78,7 @@ else if (reference.resolve() == null) {
7978
GoType type = qualifier != null ? qualifier.getGoType(null) : null;
8079
GoStructType structType = type != null ? ObjectUtils.tryCast(type.getUnderlyingType(), GoStructType.class) : null;
8180
if (!"_".equals(reference.getCanonicalText()) && structType != null) {
82-
fixes = new LocalQuickFix[]{new GoAddStructFieldFix(reference.getCanonicalText(), getTypeName(o), o)};
81+
fixes = new LocalQuickFix[]{new GoAddStructFieldFix(o)};
8382
}
8483
else if (isProhibited(o, qualifier)) {
8584
fixes = createImportPackageFixes(o, reference, holder.isOnTheFly());
@@ -166,14 +165,6 @@ else if (holder.isOnTheFly()) {
166165
};
167166
}
168167

169-
private static String getTypeName(GoReferenceExpression referenceExpression) {
170-
GoAssignmentStatement assignment = PsiTreeUtil.getParentOfType(referenceExpression, GoAssignmentStatement.class);
171-
if (assignment == null) return "interface {}";
172-
GoExpression expression = GoPsiImplUtil.getRightExpression(assignment, referenceExpression);
173-
GoType type = expression != null ? expression.getGoType(null) : null;
174-
return type != null ? type.getText() : "interface {}";
175-
}
176-
177168
@NotNull
178169
private static LocalQuickFix[] createImportPackageFixes(@NotNull PsiElement target, @NotNull PsiReference reference, boolean onTheFly) {
179170
if (onTheFly) {

src/com/goide/psi/impl/GoElementFactory.java

-5
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,4 @@ public static GoTypeDeclaration createTypeDeclaration(@NotNull Project project,
266266
GoFile file = createFileFromText(project, "package a; type " + name + " " + type.getText());
267267
return PsiTreeUtil.findChildOfType(file, GoTypeDeclaration.class);
268268
}
269-
270-
public static GoFieldDeclaration createFieldDeclaration(@NotNull Project project, @NotNull String fieldText, @NotNull String typeText) {
271-
GoFile file = createFileFromText(project, "package a; var _ = struct { " + fieldText + " " + typeText + " }");
272-
return PsiTreeUtil.findChildOfType(file, GoFieldDeclaration.class);
273-
}
274269
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
type S struct {
4+
bb interface{}
5+
cc interface{}
6+
aa S
7+
}
8+
9+
func main() {
10+
s := S{}
11+
s.aa = S{}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package main
2+
3+
type S struct {
4+
bb interface{}
5+
cc interface{}
6+
}
7+
8+
func main() {
9+
s := S{}
10+
s.aa<caret> = S{}
11+
}

testData/quickfixes/add-struct-field/withoutAssignment-after.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ type S struct {
88

99
func main() {
1010
s := S{}
11-
s.aa<caret>
11+
s.aa
1212
}

testData/quickfixes/add-struct-field/withoutElements-after.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ type S struct {
66

77
func main() {
88
s := S{}
9-
s.aa<caret> = "aa"
9+
s.aa = "aa"
1010
}

tests/com/goide/quickfix/GoAddStructFieldQuickFixTest.java

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ protected String getBasePath() {
3939

4040
public void testSimple() { doTest(ADD_STRUCT_FIELD); }
4141
public void testWithoutElements() { doTest(ADD_STRUCT_FIELD); }
42+
public void testComplexType() { doTest(ADD_STRUCT_FIELD); }
4243
public void testWithoutAssignment() { doTest(ADD_STRUCT_FIELD); }
4344
public void testBlank() { doTestNoFix(ADD_STRUCT_FIELD, true); }
4445
}

0 commit comments

Comments
 (0)