mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Revert "[java-inspection] IDEA-264141 Warn if compact constructor calls methods that access fields"
This reverts commit 30612508e6ae8a2bf3f7951880430144a2a7481a. GitOrigin-RevId: 543b8b881b1a973000121d6f749a62fe2138a905
This commit is contained in:
committed by
intellij-monorepo-bot
parent
51e1cc8b49
commit
de0e95a46b
-131
@@ -1,131 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingFeature;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.modcommand.ActionContext;
|
||||
import com.intellij.modcommand.ModCommand;
|
||||
import com.intellij.modcommand.Presentation;
|
||||
import com.intellij.modcommand.PsiBasedModCommandAction;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightRecordMember;
|
||||
import com.intellij.psi.util.JavaPsiRecordUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CompactRecordConstructorAccessFieldsInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
|
||||
@Override
|
||||
public boolean runForWholeFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
if (!HighlightingFeature.RECORDS.isAvailable(holder.getFile())) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitClass(@NotNull PsiClass aClass) {
|
||||
if (!aClass.isRecord()) {
|
||||
return;
|
||||
}
|
||||
if (aClass.getRecordComponents().length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
PsiMethod[] methods = aClass.getMethods();
|
||||
for (PsiMethod method : methods) {
|
||||
if (!JavaPsiRecordUtil.isCompactConstructor(method)) {
|
||||
continue;
|
||||
}
|
||||
List<ProblemInfo> problemInfos = processCompactConstructor(method);
|
||||
for (ProblemInfo problemInfo : problemInfos) {
|
||||
if (isOnTheFly) {
|
||||
LocalQuickFix fix = LocalQuickFix.from(new NavigateToUsageFix(problemInfo.reference));
|
||||
holder.registerProblem(problemInfo.callExpression,
|
||||
JavaBundle.message("inspection.record.compact.constructor.access.fields.display.name"),
|
||||
fix);
|
||||
}
|
||||
else {
|
||||
holder.registerProblem(problemInfo.callExpression,
|
||||
JavaBundle.message("inspection.record.compact.constructor.access.fields.display.name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
record ProblemInfo(@NotNull PsiCallExpression callExpression, @NotNull PsiReferenceExpression reference) {
|
||||
}
|
||||
|
||||
private static List<ProblemInfo> processCompactConstructor(PsiMethod compactConstructor) {
|
||||
List<ProblemInfo> result = new ArrayList<>();
|
||||
PsiManager psiManager = compactConstructor.getManager();
|
||||
PsiClass containingClass = compactConstructor.getContainingClass();
|
||||
MultiMap<PsiMethod, PsiCallExpression> nestedMethods = new MultiMap<>();
|
||||
final JavaRecursiveElementWalkingVisitor visitor = new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitCallExpression(@NotNull PsiCallExpression callExpression) {
|
||||
PsiMethod resolvedMethod = callExpression.resolveMethod();
|
||||
if (resolvedMethod != null &&
|
||||
!resolvedMethod.hasModifierProperty(PsiModifier.STATIC) &&
|
||||
psiManager.areElementsEquivalent(resolvedMethod.getContainingClass(), containingClass)) {
|
||||
nestedMethods.putValue(resolvedMethod, callExpression);
|
||||
}
|
||||
}
|
||||
};
|
||||
compactConstructor.accept(visitor);
|
||||
for (PsiMethod method : nestedMethods.keySet()) {
|
||||
Ref<PsiReferenceExpression> found = new Ref<>();
|
||||
PsiTreeUtil.processElements(method.getBody(), e -> {
|
||||
if (e instanceof PsiReferenceExpression referenceExpression) {
|
||||
PsiElement resolved = referenceExpression.resolve();
|
||||
if (resolved instanceof LightRecordMember) {
|
||||
found.set(referenceExpression);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (!found.isNull()) {
|
||||
nestedMethods.get(method).forEach(expr -> {
|
||||
result.add(new ProblemInfo(expr, found.get()));
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class NavigateToUsageFix extends PsiBasedModCommandAction<PsiReferenceExpression> {
|
||||
private NavigateToUsageFix(@NotNull PsiReferenceExpression reference) {
|
||||
super(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return JavaBundle.message("inspection.record.compact.constructor.access.fields.navigate.usages.family");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable Presentation getPresentation(@NotNull ActionContext context, @NotNull PsiReferenceExpression reference) {
|
||||
return Presentation.of(JavaBundle.message("inspection.record.compact.constructor.access.fields.navigate.usages.declaration.text",
|
||||
reference.getCanonicalText()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ModCommand perform(@NotNull ActionContext context, @NotNull PsiReferenceExpression reference) {
|
||||
return ModCommand.select(reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1607,10 +1607,6 @@
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs"
|
||||
bundle="messages.JavaBundle" key="inspection.meaningless.record.annotation.description"
|
||||
implementationClass="com.intellij.codeInspection.MeaninglessRecordAnnotationInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="CompactRecordConstructorAccessFieldsInspection" enabledByDefault="true" level="WARNING"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs"
|
||||
bundle="messages.JavaBundle" key="inspection.record.compact.constructor.access.fields.description"
|
||||
implementationClass="com.intellij.codeInspection.CompactRecordConstructorAccessFieldsInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="RecordCanBeClass" enabledByDefault="true" level="INFORMATION"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.code.style.issues"
|
||||
bundle="messages.JavaBundle" key="inspection.message.record.can.be.converted.to.class"
|
||||
|
||||
-22
@@ -1,22 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports method calls within record compact constructors if these methods access fields.
|
||||
<p>These calls look suspicious because record fields may not be initialized at the time of these calls.</p>
|
||||
<p><b>Example:</b></p>
|
||||
<pre><code>
|
||||
public record MyRecord(String name, int id) {
|
||||
public MyRecord {
|
||||
validateMyFields(); // it looks suspicious
|
||||
}
|
||||
|
||||
private void validateMyFields() {
|
||||
if (this.name.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre>
|
||||
<!-- tooltip end -->
|
||||
<p><small>New in 2024.1</small></p>
|
||||
</body>
|
||||
</html>
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
class RecordMain {
|
||||
public record MyRecord(String name, int id) {
|
||||
|
||||
public MyRecord {
|
||||
<warning descr="Calling method can access non-initialized fields">validateMyFields()</warning>;
|
||||
<warning descr="Calling method can access non-initialized fields">validateMyFieldsWithGetter()</warning>;
|
||||
nothing();
|
||||
}
|
||||
|
||||
private void nothing() {
|
||||
|
||||
}
|
||||
|
||||
private static void t() {
|
||||
|
||||
}
|
||||
private void validateMyFields() {
|
||||
if (this.name.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
private void validateMyFieldsWithGetter() {
|
||||
if (this.name().isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
MyRecord myRecord = new MyRecord("s", 2);
|
||||
System.out.println(myRecord);
|
||||
}
|
||||
}
|
||||
-26
@@ -1,26 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.codeInspection;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.CompactRecordConstructorAccessFieldsInspection;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
|
||||
|
||||
public class CompactRecordConstructorAccessFieldsInspectionTest extends LightJavaCodeInsightFixtureTestCase {
|
||||
public void testNestedCalls() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
myFixture.enableInspections(new CompactRecordConstructorAccessFieldsInspection());
|
||||
myFixture.testHighlighting(getTestName(false) + ".java");
|
||||
}
|
||||
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_21;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return JavaTestUtil.getRelativeJavaTestDataPath()+"/inspection/compactRecordConstructorAccessFields";
|
||||
}
|
||||
}
|
||||
-13
@@ -19,10 +19,7 @@ import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCa
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.SimplifyStreamApiCallChainsInspection;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.LightProjectDescriptor;
|
||||
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class SimplifyStreamApiCallChainsInspectionFixTest extends LightQuickFixParameterizedTestCase {
|
||||
@@ -37,16 +34,6 @@ public class SimplifyStreamApiCallChainsInspectionFixTest extends LightQuickFixP
|
||||
return IdeaTestUtil.getMockJdk11();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return LanguageLevel.JDK_21;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
|
||||
return LightJavaCodeInsightFixtureTestCase.JAVA_21;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/inspection/streamApiCallChains";
|
||||
|
||||
@@ -1705,10 +1705,6 @@ inspection.redundant.unmodifiable.call.description=Redundant usage of unmodifiab
|
||||
inspection.redundant.unmodifiable.call.unwrap.argument.quickfix=Unwrap argument
|
||||
completion.override.implement.methods=Override/Implement methods...
|
||||
lambda.tree.node.presentation=Lambda
|
||||
inspection.record.compact.constructor.access.fields.description=Compact constructor access components
|
||||
inspection.record.compact.constructor.access.fields.display.name=Calling method can access non-initialized fields
|
||||
inspection.record.compact.constructor.access.fields.navigate.usages.family=Navigate to a component usage
|
||||
inspection.record.compact.constructor.access.fields.navigate.usages.declaration.text=Navigate to a component usage ''{0}''
|
||||
inspection.meaningless.record.annotation.description=Meaningless record annotation
|
||||
inspection.meaningless.record.annotation.message.method.and.parameter=Annotation has no effect: its targets are METHOD and PARAMETER but both accessor and canonical constructor are explicitly declared
|
||||
inspection.meaningless.record.annotation.message.method=Annotation has no effect: its target is METHOD but the corresponding accessor is explicitly declared
|
||||
|
||||
Reference in New Issue
Block a user