Fix unused declaration record false positives in batch inspection (IDEA-293902)

GitOrigin-RevId: 9f6e745abc93560315c708cf3e6806f86533ac1e
This commit is contained in:
Bas Leijdekkers
2022-05-29 13:35:27 +00:00
committed by intellij-monorepo-bot
parent a7e54c330d
commit ae88c6cbb4
9 changed files with 110 additions and 11 deletions
@@ -12,12 +12,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.uast.*;
public class RefFieldImpl extends RefJavaElementImpl implements RefField {
private static final int USED_FOR_READING_MASK = 0b1_00000000_00000000; // 17th bit
private static final int USED_FOR_WRITING_MASK = 0b10_00000000_00000000; // 18th bit
private static final int USED_FOR_READING_MASK = 0b1_00000000_00000000; // 17th bit
private static final int USED_FOR_WRITING_MASK = 0b10_00000000_00000000; // 18th bit
private static final int ASSIGNED_ONLY_IN_INITIALIZER_MASK = 0b100_00000000_00000000; // 19th bit
private static final int IMPLICITLY_READ_MASK = 0b1000_00000000_00000000; // 20th bit
private static final int IMPLICITLY_WRITTEN_MASK = 0b10000_00000000_00000000; // 21st bit
private static final int IS_ENUM_CONSTANT = 0b100000_00000000_00000000; // 22nd bit
private static final int IMPLICITLY_READ_MASK = 0b1000_00000000_00000000; // 20th bit
private static final int IMPLICITLY_WRITTEN_MASK = 0b10000_00000000_00000000; // 21st bit
private static final int IS_ENUM_CONSTANT = 0b100000_00000000_00000000; // 22nd bit
RefFieldImpl(UField field, PsiElement psi, RefManager manager) {
super(field, psi, manager);
@@ -33,7 +33,13 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField {
LOG.assertTrue(psi != null);
UField uElement = getUastElement();
LOG.assertTrue(uElement != null);
this.setOwner((WritableRefEntity)RefMethodImpl.findParentRef(psi, uElement, myManager));
RefElement owner = RefMethodImpl.findParentRef(psi, uElement, myManager);
this.setOwner((WritableRefEntity)owner);
if (owner instanceof RefClass && ((RefClass)owner).isRecord()) {
// record fields are always implicitly written in constructor and read in hashCode() & equals()
setUsedForReading(true);
setUsedForWriting(true);
}
}
@Deprecated
@@ -3,6 +3,7 @@ package com.intellij.codeInspection.reference;
import com.intellij.analysis.AnalysisBundle;
import com.intellij.java.analysis.JavaAnalysisBundle;
import com.intellij.lang.Language;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiFormatUtil;
@@ -96,7 +97,10 @@ public abstract class RefJavaElementImpl extends RefElementImpl implements RefJa
if (element instanceof PsiMethod) {
if (element instanceof SyntheticElement) {
return JavaAnalysisBundle.message("inspection.reference.jsp.holder.method.anonymous.name");
Language language = element.getLanguage();
if (language.isKindOf("JSP") || language.isKindOf("JSPX")) {
return JavaAnalysisBundle.message("inspection.reference.jsp.holder.method.anonymous.name");
}
}
return PsiFormatUtil.formatMethod((PsiMethod)element,
PsiSubstitutor.EMPTY,
@@ -167,7 +167,11 @@ public class RefJavaUtilImpl extends RefJavaUtil {
visitClass(((UObjectLiteralExpression)node).getDeclaration());
}
if (node.getKind() == UastCallKind.CONSTRUCTOR_CALL) {
PsiMethod resolvedMethod = node.resolve();
PsiElement resolvedMethod = node.resolve();
if (resolvedMethod instanceof LightElement) {
UElement uElement = UastContextKt.toUElement(resolvedMethod);
resolvedMethod = uElement == null ? null : uElement.getSourcePsi();
}
final List<UExpression> argumentList = node.getValueArguments();
RefMethod refConstructor = processNewLikeConstruct(resolvedMethod, argumentList);
@@ -295,9 +299,10 @@ public class RefJavaUtilImpl extends RefJavaUtil {
}
@Nullable
private RefMethod processNewLikeConstruct(final PsiMethod javaConstructor, final List<UExpression> argumentList) {
private RefMethod processNewLikeConstruct(PsiElement javaConstructor, List<UExpression> argumentList) {
if (javaConstructor == null) return null;
RefMethodImpl refConstructor = (RefMethodImpl)refManager.getReference(javaConstructor.getOriginalElement());
RefMethodImpl refConstructor =
ObjectUtils.tryCast(refManager.getReference(javaConstructor.getOriginalElement()), RefMethodImpl.class);
refFrom.addReference(refConstructor, javaConstructor, decl, false, true, null);
for (UExpression arg : argumentList) {
@@ -7,6 +7,7 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierListOwner;
import com.intellij.psi.PsiRecordComponent;
import com.intellij.psi.PsiResolveHelper;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.ObjectUtils;
@@ -36,6 +37,10 @@ public class RefParameterImpl extends RefJavaElementImpl implements RefParameter
owner.add(this);
}
if (psi instanceof PsiRecordComponent) {
setUsedForReading();
}
//TODO kotlin receiver parameter must be used
if (myIndex == 0) {
String name = getName();
@@ -1,2 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems/>
<problems>
<problem>
<file>A.java</file>
<line>6</line>
<entry_point TYPE="method" FQNAME="R R()" />
<problem_class id="unused" severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">unused declaration</problem_class>
<description>Constructor is never used.</description>
</problem>
</problems>
@@ -3,3 +3,39 @@ record A(int i) {
System.out.println(new A(1));
}
}
record R() {}
public record MyRec(String name) {
public MyRec {
System.out.println("Constructing");
}
public void doSomething() {
System.out.println("Name is " + name);
}
public static void main(String[] args) {
final MyRec rec = new MyRec("Hello");
rec.doSomething();
}
}
record R1(int i) {
public static void main(String[] args){
new R1(1);
}
}
record R2(int i) {
R2 {}
public static void main(String[] args){
new R2(0);
}
}
record R3(int i) {
R3(int i) {
this.i = i;
}
public static void main(String... args){
new R3(-1);
}
}
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
<problem>
<file>R.java</file>
<line>2</line>
<problem_class id="unused" severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused declaration</problem_class>
<description>Parameter &lt;code&gt;i&lt;/code&gt; is not used</description>
<highlighted_element>i</highlighted_element>
<offset>15</offset>
<length>1</length>
</problem>
<problem>
<file>R.java</file>
<line>2</line>
<problem_class id="unused" severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unused declaration</problem_class>
<description>Parameter &lt;code&gt;s&lt;/code&gt; is not used</description>
<highlighted_element>s</highlighted_element>
<offset>25</offset>
<length>1</length>
</problem>
</problems>
@@ -0,0 +1,9 @@
public record R(int i) {
public R(int i, String s) {
this(1);
}
public static void main(String[]args){
new R(2, "asdf");
}
}
@@ -29,6 +29,10 @@ public class UnusedMethodParameterTest extends JavaInspectionTestCase {
doTest();
}
public void testRecordConstructorParameter() {
doTest();
}
public void testUsedForReading() {
doTest();
}