Skip to content

Commit c39fe57

Browse files
committed
Add self import inspection
1 parent 5cfb9b9 commit c39fe57

File tree

11 files changed

+201
-2
lines changed

11 files changed

+201
-2
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<html>
2+
<body>
3+
Inspects file for own path imports
4+
</body>
5+
</html>

src/META-INF/plugin.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@
243243
<localInspection language="go" displayName="Wrong test declaration"
244244
groupName="Go" enabledByDefault="true" level="ERROR"
245245
implementationClass="com.goide.inspections.GoTestSignaturesInspection"/>
246+
<localInspection language="go" displayName="Self import"
247+
groupName="Go" enabledByDefault="true" level="ERROR"
248+
implementationClass="com.goide.inspections.GoSelfImportInspection" />
246249
</extensions>
247250
<actions>
248251
<action id="Go.NewGoFile" class="com.goide.actions.GoCreateFileAction"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Florin Patan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.goide.inspections;
18+
19+
import com.goide.psi.GoFile;
20+
import com.goide.psi.GoImportSpec;
21+
import com.goide.runconfig.testing.GoTestFinder;
22+
import com.intellij.codeInspection.ProblemsHolder;
23+
import org.jetbrains.annotations.NotNull;
24+
25+
public class GoSelfImportInspection extends GoInspectionBase {
26+
@Override
27+
protected void checkFile(@NotNull GoFile file, @NotNull ProblemsHolder problemsHolder) {
28+
if (GoTestFinder.isTestFile(file) && GoTestFinder.isTestPackageName(file.getPackageName())) return;
29+
30+
GoImportSpec selfImportSpec = file.getImportedPackagesMap().get(file.getImportPath());
31+
if (selfImportSpec != null) {
32+
problemsHolder.registerProblem(selfImportSpec, "Self import is not allowed", new GoSelfImportQuickFix("Remove self import"));
33+
}
34+
}
35+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2013-2015 Sergey Ignatov, Alexander Zolotov, Florin Patan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.goide.inspections;
18+
19+
import com.goide.psi.*;
20+
import com.goide.psi.impl.GoElementFactory;
21+
import com.intellij.codeInspection.LocalQuickFixBase;
22+
import com.intellij.codeInspection.ProblemDescriptor;
23+
import com.intellij.openapi.command.WriteCommandAction;
24+
import com.intellij.openapi.project.Project;
25+
import com.intellij.psi.PsiElement;
26+
import com.intellij.psi.PsiFile;
27+
import com.intellij.psi.PsiRecursiveElementVisitor;
28+
import com.intellij.psi.PsiReference;
29+
import com.intellij.psi.util.PsiTreeUtil;
30+
import com.intellij.util.containers.ContainerUtil;
31+
import org.jetbrains.annotations.NotNull;
32+
33+
import java.util.Map;
34+
35+
public class GoSelfImportQuickFix extends LocalQuickFixBase {
36+
37+
protected GoSelfImportQuickFix(@NotNull String name) {
38+
super(name);
39+
}
40+
41+
@Override
42+
public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) {
43+
final PsiElement element = descriptor.getPsiElement();
44+
final PsiFile file = element != null ? element.getContainingFile() : null;
45+
if (!(element instanceof GoImportSpec && file instanceof GoFile)) return;
46+
47+
final Map<GoReferenceExpressionBase, String> usages = ContainerUtil.newHashMap();
48+
file.acceptChildren(new PsiRecursiveElementVisitor() {
49+
public void visitElement(@NotNull PsiElement element) {
50+
if (element instanceof GoReferenceExpression || element instanceof GoTypeReferenceExpression) {
51+
PsiReference reference = element.getReference();
52+
PsiElement definition = reference != null ? reference.resolve() : null;
53+
PsiFile definitionFile = definition instanceof GoNamedElement ? definition.getContainingFile() : null;
54+
if (definitionFile != null && definitionFile.getParent() == file.getParent()) {
55+
usages.put((GoReferenceExpressionBase)element, ((GoNamedElement)definition).getName());
56+
return;
57+
}
58+
}
59+
super.visitElement(element);
60+
}
61+
});
62+
WriteCommandAction.runWriteCommandAction(project, new Runnable() {
63+
@Override
64+
public void run() {
65+
for (Map.Entry<GoReferenceExpressionBase, String> usage : usages.entrySet()) {
66+
GoReferenceExpressionBase expression = usage.getKey();
67+
expression.replace(expression instanceof GoReferenceExpression
68+
? GoElementFactory.createReferenceExpression(project, usage.getValue())
69+
: GoElementFactory.createTypeReferenceExpression(project, usage.getValue()));
70+
}
71+
GoImportDeclaration importDeclaration = PsiTreeUtil.getParentOfType(element, GoImportDeclaration.class);
72+
assert importDeclaration != null;
73+
PsiElement elementToDelete = importDeclaration.getImportSpecList().size() == 1 ? importDeclaration : element;
74+
elementToDelete.delete();
75+
}
76+
});
77+
}
78+
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,14 @@ public static GoStatement createShortVarDeclarationStatement(@NotNull Project pr
111111
}
112112

113113
@NotNull
114-
public static GoReferenceExpression createVarReference(@NotNull Project project, @NotNull String name) {
114+
public static GoReferenceExpression createReferenceExpression(@NotNull Project project, @NotNull String name) {
115115
GoFile file = createFileFromText(project, "package a; var a = " + name);
116116
return PsiTreeUtil.findChildOfType(file, GoReferenceExpression.class);
117117
}
118+
119+
@NotNull
120+
public static GoTypeReferenceExpression createTypeReferenceExpression(@NotNull Project project, @NotNull String name) {
121+
GoFile file = createFileFromText(project, "package a; type " + name + " struct {}; func f() { " + name + "{} }");
122+
return PsiTreeUtil.findChildOfType(file, GoTypeReferenceExpression.class);
123+
}
118124
}

src/com/goide/refactor/GoIntroduceVariableBase.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ public void run() {
182182
for (PsiElement occurrence : occurrences) {
183183
PsiElement occurrenceParent = occurrence.getParent();
184184
if (occurrenceParent instanceof GoParenthesesExpr) occurrence = occurrenceParent;
185-
newOccurrences.add(occurrence.replace(GoElementFactory.createVarReference(project, name)));
185+
newOccurrences.add(occurrence.replace(GoElementFactory.createReferenceExpression(project, name)));
186186
}
187187
}
188188
});

src/com/goide/runconfig/testing/GoTestFinder.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public static boolean isTestFile(@Nullable VirtualFile file) {
4646
return file != null && file.getFileType() == GoFileType.INSTANCE && file.getNameWithoutExtension().endsWith(GoConstants.TEST_SUFFIX);
4747
}
4848

49+
public static boolean isTestPackageName(@Nullable String packageName) {
50+
return packageName != null && packageName.endsWith(GoConstants.TEST_SUFFIX);
51+
}
52+
4953
@Nullable
5054
public static String getTestFunctionName(@NotNull GoFunctionOrMethodDeclaration function) {
5155
return GoTestFunctionType.fromName(function.getName()) == GoTestFunctionType.TEST ? StringUtil.notNullize(function.getName()) : null;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package a
2+
3+
var Var = 42
4+
type MyType struct{}
5+
func Func(i int) {}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package a
2+
3+
func f() {
4+
Func(Var)
5+
Type{}
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package a
2+
import "."
3+
4+
func f() {
5+
a.Func(a.Var)
6+
a.Type{}
7+
}

0 commit comments

Comments
 (0)