Skip to content

Commit 07a5cc5

Browse files
committed
发布 2.0版本,支持解析字段里的泛型
1 parent 7c37bdf commit 07a5cc5

File tree

5 files changed

+172
-23
lines changed

5 files changed

+172
-23
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group 'org.intellij.sdk'
9-
version '1.0'
9+
version '2.0'
1010

1111
sourceCompatibility = 1.8
1212

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package com.github.hwhaocool.codeInspection.deadcode;
2+
3+
import com.intellij.codeInspection.GlobalInspectionContext;
4+
import com.intellij.codeInspection.reference.RefClass;
5+
import com.intellij.codeInspection.reference.RefClassImpl;
6+
import com.intellij.codeInspection.reference.RefElement;
7+
import com.intellij.codeInspection.reference.RefEntity;
8+
import com.intellij.codeInspection.reference.RefFieldImpl;
9+
import com.intellij.psi.PsiClass;
10+
import com.intellij.psi.PsiElement;
11+
import com.intellij.psi.PsiType;
12+
import com.intellij.psi.impl.source.PsiClassReferenceType;
13+
import com.intellij.psi.impl.source.PsiFieldImpl;
14+
import org.jetbrains.annotations.NotNull;
15+
16+
import java.util.List;
17+
import java.util.Set;
18+
19+
/**
20+
* 通过属性 递归设置 Reachable
21+
* @author YellowTail
22+
* @since 2020-12-14
23+
*/
24+
public class RecursionField implements RecursionReachable {
25+
26+
public void setReachable(final GlobalInspectionContext globalContext, final RefClass refClass, final Set<RefClass> processedRefclass) {
27+
28+
directField(globalContext, refClass, processedRefclass);
29+
30+
genericField(globalContext, refClass, processedRefclass);
31+
}
32+
33+
/**
34+
* 直接寻找 refClass 的 字段, 字段为 T field, T就是当前project的类
35+
* @param globalContext
36+
* @param refClass
37+
* @param processedRefclass
38+
* @author YellowTail
39+
* @since 2020-12-14
40+
*/
41+
private void directField(final GlobalInspectionContext globalContext, final RefClass refClass, final Set<RefClass> processedRefclass) {
42+
43+
// 得到字段的 class 类型
44+
for (RefClass outTypeReference : refClass.getOutTypeReferences()) {
45+
46+
process(globalContext, refClass, processedRefclass, outTypeReference);
47+
}
48+
49+
}
50+
51+
/**
52+
* 寻找 refClass 的泛型字段, 字段为 R &lt;T&gt; field, R就是集合之类的可以包含泛型的对象,如List Map等, T就是当前project的类
53+
* @param globalContext
54+
* @param refClass
55+
* @param processedRefclass
56+
* @author YellowTail
57+
* @since 2020-12-14
58+
*/
59+
private void genericField(final GlobalInspectionContext globalContext, final RefClass refClass, final Set<RefClass> processedRefclass) {
60+
61+
List<RefEntity> children = refClass.getChildren();
62+
63+
for (RefEntity refEntity : children) {
64+
65+
if (! (refEntity instanceof RefFieldImpl)) {
66+
//不是字段,跳过
67+
continue;
68+
}
69+
70+
// 1. 得到 psi
71+
PsiElement psiElement = RefFieldImpl.class.cast(refEntity).getPsiElement();
72+
73+
PsiType psiFieldType = PsiFieldImpl.class.cast(psiElement).getType();
74+
75+
if (!(psiFieldType instanceof PsiClassReferenceType)) {
76+
//跳过
77+
continue;
78+
}
79+
80+
// 2. 通过 psi 得到 参数列表,列表里就有 T
81+
// https://stackoverflow.com/a/36443859
82+
@NotNull PsiType[] parameters = PsiClassReferenceType.class.cast(psiFieldType).getParameters();
83+
84+
for (PsiType parameter : parameters) {
85+
86+
try {
87+
PsiClassReferenceType cast = PsiClassReferenceType.class.cast(parameter);
88+
PsiClass resolve = cast.resolve();
89+
90+
RefElement reference = globalContext.getRefManager().getReference(resolve);
91+
92+
if (!(reference instanceof RefClass)) {
93+
//跳过
94+
continue;
95+
}
96+
97+
RefClass genericRefClass = RefClassImpl.class.cast(reference);
98+
99+
process(globalContext, refClass, processedRefclass, genericRefClass);
100+
101+
102+
} catch (Exception e) {
103+
System.out.println(e);
104+
}
105+
106+
}
107+
}
108+
}
109+
110+
private void process(final GlobalInspectionContext globalContext, final RefClass refClass, final Set<RefClass> processedRefclass, final RefClass outTypeReference) {
111+
if (refClass.equals(outTypeReference)) {
112+
//如果是自己的话,添加到已分析里面,且跳过当前,继续下一次循环
113+
processedRefclass.add(outTypeReference);
114+
return;
115+
}
116+
117+
if (processedRefclass.contains(outTypeReference)) {
118+
//已经处理了,直接下一个
119+
return;
120+
}
121+
processedRefclass.add(outTypeReference);
122+
123+
//设置为 Reachable
124+
addEntryPoint(globalContext, outTypeReference);
125+
126+
// 递归处理
127+
setReachable(globalContext, outTypeReference, processedRefclass);
128+
}
129+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.github.hwhaocool.codeInspection.deadcode;
2+
3+
import com.intellij.codeInspection.GlobalInspectionContext;
4+
import com.intellij.codeInspection.GlobalJavaInspectionContext;
5+
import com.intellij.codeInspection.reference.RefClass;
6+
7+
import java.util.Set;
8+
9+
public interface RecursionReachable {
10+
11+
/**
12+
* 使用递归模式设置 Reachable
13+
* @param globalContext 上下文
14+
* @param refClass 当前搜索出来的具有 Reachable 的 refClass
15+
* @param processedRefclass 已经处理过的 refClass 集合
16+
* @author YellowTail
17+
* @since 2020-12-14
18+
*/
19+
void setReachable(GlobalInspectionContext globalContext, RefClass refClass, final Set<RefClass> processedRefclass);
20+
21+
/**
22+
* 设置 outTypeReference 为 Reachable
23+
* @param context
24+
* @param outTypeReference
25+
* @author YellowTail
26+
* @since 2020-12-14
27+
*/
28+
default void addEntryPoint(final GlobalInspectionContext context, RefClass outTypeReference) {
29+
context.getExtension(GlobalJavaInspectionContext.CONTEXT).getEntryPointsManager(context.getRefManager()).addEntryPoint(outTypeReference, false);
30+
}
31+
}

src/main/java/com/github/hwhaocool/codeInspection/fromsdk/UnusedDeclarationInspectionBase.java

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
package com.github.hwhaocool.codeInspection.fromsdk;
33

44
import com.github.hwhaocool.codeInspection.deadcode.Constants;
5+
import com.github.hwhaocool.codeInspection.deadcode.RecursionField;
6+
import com.github.hwhaocool.codeInspection.deadcode.RecursionReachable;
57
import com.github.hwhaocool.codeInspection.fromsdk.unusedSymbol.UnusedSymbolLocalInspectionImpl;
68
import com.intellij.analysis.AnalysisBundle;
79
import com.intellij.analysis.AnalysisScope;
@@ -535,7 +537,7 @@ public void visitElement(@NotNull RefEntity refEntity) {
535537
@Override
536538
public void visitField(@NotNull final RefField refField) {
537539

538-
printName("UnusedDeclarationInspectionBase queryExternalUsagesRequests visitField %s", refField);
540+
// printName("UnusedDeclarationInspectionBase queryExternalUsagesRequests visitField %s", refField);
539541

540542
processedSuspicious.add(refField);
541543
UField uField = refField.getUastElement();
@@ -553,7 +555,7 @@ public void visitField(@NotNull final RefField refField) {
553555
@Override
554556
public void visitMethod(@NotNull final RefMethod refMethod) {
555557

556-
printName("UnusedDeclarationInspectionBase queryExternalUsagesRequests visitMethod %s", refMethod);
558+
// printName("UnusedDeclarationInspectionBase queryExternalUsagesRequests visitMethod %s", refMethod);
557559

558560
processedSuspicious.add(refMethod);
559561
if (refMethod instanceof RefImplicitConstructor) {
@@ -604,7 +606,7 @@ public void visitClass(@NotNull final RefClass refClass) {
604606
globalContext.getExtension(GlobalJavaInspectionContext.CONTEXT)
605607
.enqueueClassUsagesProcessor(refClass, psiReference -> {
606608

607-
printName("UnusedDeclarationInspectionBase queryExternalUsagesRequests visitClass enqueueClassUsagesProcessor %s", refClass);
609+
printName("UnusedDeclarationInspectionBase class_has_been_used visitClass %s", refClass);
608610

609611
// 这里的 false, 会让 com.intellij.codeInspection.ex.EntryPointsManagerBase.addEntryPoint 383行
610612
// 执行 this.myTemporaryEntryPoints.add(newEntryPoint);
@@ -614,7 +616,7 @@ public void visitClass(@NotNull final RefClass refClass) {
614616

615617
// 通过方法 getOutTypeReferences 得到字段的 class 类型
616618
// 需要考虑嵌套
617-
recursionSetReachable(globalContext, refClass);
619+
RECURSION_REACHABLE.setReachable(globalContext, refClass, PROCESSED_REFCLASS);
618620

619621
// 这个返回值没看出来有什么作用
620622
return false;
@@ -732,7 +734,7 @@ private static class CodeScanner extends RefJavaVisitor {
732734
@Override
733735
public void visitMethod(@NotNull RefMethod method) {
734736

735-
printName("UnusedDeclarationInspectionBase CodeScanner visitMethod %s", method);
737+
// printName("UnusedDeclarationInspectionBase CodeScanner visitMethod %s", method);
736738

737739
if (!myProcessedMethods.contains(method)) {
738740
// Process class's static initializers
@@ -792,7 +794,7 @@ public void visitClass(@NotNull RefClass refClass) {
792794
@Override
793795
public void visitField(@NotNull RefField field) {
794796

795-
printName("UnusedDeclarationInspectionBase CodeScanner visitField %s", field);
797+
// printName("UnusedDeclarationInspectionBase CodeScanner visitField %s", field);
796798

797799
// Process class's static initializers.
798800
if (!field.isReachable()) {
@@ -881,21 +883,7 @@ public static String getDisplayNameText() {
881883
*/
882884
private final static Set<RefClass> PROCESSED_REFCLASS = new HashSet<>();
883885

884-
private static void recursionSetReachable(final @NotNull GlobalInspectionContext globalContext, final @NotNull RefClass refClass) {
885-
// 得到字段的 class 类型
886-
for (RefClass outTypeReference : refClass.getOutTypeReferences()) {
887-
888-
if (PROCESSED_REFCLASS.contains(outTypeReference)) {
889-
//已经处理了,直接下一个
890-
continue;
891-
}
892-
PROCESSED_REFCLASS.add(outTypeReference);
893-
894-
getEntryPointsManager(globalContext).addEntryPoint(outTypeReference, false);
895-
896-
recursionSetReachable(globalContext, outTypeReference);
897-
}
898-
}
886+
private final static RecursionReachable RECURSION_REACHABLE = new RecursionField();
899887

900888
public static void printName(String format, RefJavaElement refJavaElement) {
901889

src/main/resources/META-INF/plugin.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
使用递归模式尽可能的设置一些类状态为『可达』, 和原生插件『unused declaration』的不同是: <br>
1919
原生插件会尽可能多的提醒 <br><br>
2020
本插件是: <b>宁放过,勿杀错。<b><br><br>
21-
扫描出来的东西绝对是 dead code, 可以放心的 Safe Delete <br>
21+
扫描出来的东西大概率是 dead code, 可以比较放心的 Safe Delete (删除代码有风险,删除请谨慎) <br>
2222
<b>Preferences | Editor | Inspections | Java | Probable Bugs</b>.<br><br>
2323
使用: Analyze -- Run Inspection By Name -- Yellow Tail
2424
]]>
@@ -27,6 +27,7 @@
2727
<![CDATA[
2828
<ul>
2929
<li><b>1.0</b> Release 1.0, can find unused VO in recursion mode</li>
30+
<li><b>2.0</b> Release 2.0, 扫描的时候增加了解析泛型的步骤</li>
3031
</ul>
3132
]]>
3233
</change-notes>

0 commit comments

Comments
 (0)