Java: cleanup

GitOrigin-RevId: 43fa2943741c545c44685c2a1d096ea04f01eceb
This commit is contained in:
Bas Leijdekkers
2025-09-25 18:47:50 +00:00
committed by intellij-monorepo-bot
parent ed3b87c98b
commit 5fe59fe456
3 changed files with 68 additions and 129 deletions
@@ -1,51 +1,55 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
/*
* Copyright 2003-2025 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.classlayout;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.UtilityClassUtil;
import org.jetbrains.annotations.NotNull;
public final class UtilityClassWithPublicConstructorInspection
extends BaseInspection {
public final class UtilityClassWithPublicConstructorInspection extends BaseInspection {
@Override
protected @NotNull String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"utility.class.with.public.constructor.problem.descriptor");
return InspectionGadgetsBundle.message("utility.class.with.public.constructor.problem.descriptor");
}
@Override
protected LocalQuickFix buildFix(Object... infos) {
final PsiClass psiClass = (PsiClass)infos[0];
final boolean hasInheritors = (Boolean)infos[1];
if (psiClass.getConstructors().length > 1) {
return new UtilityClassWithPublicConstructorFix(true, hasInheritors);
}
else {
return new UtilityClassWithPublicConstructorFix(false, hasInheritors);
}
return new UtilityClassWithPublicConstructorFix(psiClass.getConstructors().length > 1, hasInheritors);
}
private static class UtilityClassWithPublicConstructorFix
extends PsiUpdateModCommandQuickFix {
private static class UtilityClassWithPublicConstructorFix extends PsiUpdateModCommandQuickFix {
private final boolean m_multipleConstructors;
private final boolean m_hasInheritors;
UtilityClassWithPublicConstructorFix(boolean multipleConstructors, boolean hasInheritors) {
super();
m_multipleConstructors = multipleConstructors;
m_hasInheritors = hasInheritors;
}
@@ -71,13 +75,9 @@ public final class UtilityClassWithPublicConstructorInspection
return;
}
String modifier = m_hasInheritors? PsiModifier.PROTECTED : PsiModifier.PRIVATE;
final PsiMethod[] constructors = psiClass.getConstructors();
for (PsiMethod constructor : constructors) {
final PsiModifierList modifierList =
constructor.getModifierList();
modifierList.setModifierProperty(modifier, true);
String modifier = m_hasInheritors ? PsiModifier.PROTECTED : PsiModifier.PRIVATE;
for (PsiMethod constructor : psiClass.getConstructors()) {
constructor.getModifierList().setModifierProperty(modifier, true);
}
}
}
@@ -87,30 +87,20 @@ public final class UtilityClassWithPublicConstructorInspection
return new StaticClassWithPublicConstructorVisitor();
}
private static class StaticClassWithPublicConstructorVisitor
extends BaseInspectionVisitor {
private static class StaticClassWithPublicConstructorVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (!UtilityClassUtil.isUtilityClass(aClass)) {
return;
}
if (!hasPublicConstructor(aClass)) {
if (!UtilityClassUtil.isUtilityClass(aClass) || !hasPublicConstructor(aClass)) {
return;
}
final SearchScope scope = GlobalSearchScope.projectScope(aClass.getProject());
final Query<PsiClass> query = ClassInheritorsSearch.search(aClass, scope, false);
final PsiClass subclass = query.findFirst();
Boolean hasInheritors = subclass != null;
boolean hasInheritors = ClassInheritorsSearch.search(aClass, aClass.getUseScope(), false).findFirst() != null;
registerClassError(aClass, aClass, hasInheritors);
}
private static boolean hasPublicConstructor(PsiClass aClass) {
final PsiMethod[] constructors = aClass.getConstructors();
for (final PsiMethod constructor : constructors) {
for (PsiMethod constructor : aClass.getConstructors()) {
if (constructor.hasModifierProperty(PsiModifier.PUBLIC)) {
return true;
}
@@ -1,19 +1,14 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.classlayout;
import com.intellij.codeInsight.intention.ReplaceConstructorWithFactoryAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiParameterList;
import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.SerializationUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
@@ -21,18 +16,16 @@ import org.jetbrains.annotations.Nullable;
public final class PublicConstructorInspection extends BaseInspection {
@Override
protected @Nullable LocalQuickFix buildFix(Object... infos) {
protected @NotNull LocalQuickFix buildFix(Object... infos) {
return LocalQuickFix.from(new ReplaceConstructorWithFactoryAction());
}
@Override
protected @NotNull String buildErrorString(Object... infos) {
if (((Boolean)infos[0]).booleanValue()) {
return InspectionGadgetsBundle.message("public.default.constructor.problem.descriptor");
}
else {
return InspectionGadgetsBundle.message("public.constructor.problem.descriptor");
}
boolean defaultConstructor = ((Boolean)infos[0]).booleanValue();
return defaultConstructor
? InspectionGadgetsBundle.message("public.default.constructor.problem.descriptor")
: InspectionGadgetsBundle.message("public.constructor.problem.descriptor");
}
@Override
@@ -47,45 +40,28 @@ public final class PublicConstructorInspection extends BaseInspection {
private static class PublicConstructorVisitor extends BaseInspectionVisitor {
@Override
public void visitMethod(@NotNull PsiMethod method) {
super.visitMethod(method);
if (!method.isConstructor()) {
return;
}
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
return;
}
final PsiClass aClass = method.getContainingClass();
if (aClass == null || aClass.hasModifierProperty(PsiModifier.ABSTRACT) || aClass.isRecord()) {
return;
}
if (SerializationUtils.isExternalizable(aClass)) {
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.isEmpty()) {
return;
}
}
registerMethodError(method, Boolean.FALSE);
}
@Override
public void visitClass(@NotNull PsiClass aClass) {
super.visitClass(aClass);
if (aClass.isInterface() || aClass.isEnum() || aClass.isRecord()) {
return;
}
if (!aClass.hasModifierProperty(PsiModifier.PUBLIC) || aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
if (aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
final PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length > 0) {
return;
PsiMethod[] constructors = aClass.getConstructors();
for (PsiMethod constructor : constructors) {
if (!constructor.hasModifierProperty(PsiModifier.PUBLIC)) {
continue;
}
if (SerializationUtils.isExternalizable(aClass) && constructor.getParameterList().isEmpty()) {
continue;
}
registerMethodError(constructor, Boolean.FALSE);
}
if (SerializationUtils.isExternalizable(aClass)) {
return;
if (constructors.length == 0 && aClass.hasModifierProperty(PsiModifier.PUBLIC) && !SerializationUtils.isExternalizable(aClass)) {
registerClassError(aClass, Boolean.TRUE);
}
registerClassError(aClass, Boolean.TRUE);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2021 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2025 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,8 +25,6 @@ import com.intellij.modcommand.PsiUpdateModCommandQuickFix;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.util.Query;
@@ -65,14 +63,13 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
protected LocalQuickFix @NotNull [] buildFixes(Object... infos) {
final List<LocalQuickFix> fixes = new ArrayList<>();
final PsiClass aClass = (PsiClass)infos[0];
final PsiMethod constructor = getNullArgConstructor(aClass);
final PsiMethod constructor = getNoArgConstructor(aClass);
if (constructor == null) {
fixes.add(new CreateEmptyPrivateConstructor());
}
else {
final Query<PsiReference> query = ReferencesSearch.search(constructor, constructor.getUseScope());
final PsiReference reference = query.findFirst();
if (reference == null) {
boolean hasInstantiation = ReferencesSearch.search(constructor, constructor.getUseScope()).findFirst() == null;
if (hasInstantiation) {
fixes.add(new MakeConstructorPrivateFix());
}
}
@@ -95,11 +92,9 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
return query.anyMatch(ref -> ref != null && ref.getElement().getParent() instanceof PsiNewExpression);
}
static @Nullable PsiMethod getNullArgConstructor(PsiClass aClass) {
final PsiMethod[] constructors = aClass.getConstructors();
for (final PsiMethod constructor : constructors) {
final PsiParameterList params = constructor.getParameterList();
if (params.isEmpty()) {
private static @Nullable PsiMethod getNoArgConstructor(PsiClass aClass) {
for (PsiMethod constructor : aClass.getConstructors()) {
if (constructor.getParameterList().isEmpty()) {
return constructor;
}
}
@@ -115,22 +110,19 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
@Override
protected void applyFix(@NotNull Project project, @NotNull PsiElement classNameIdentifier, @NotNull ModPsiUpdater updater) {
final PsiElement parent = classNameIdentifier.getParent();
if (!(parent instanceof PsiClass aClass)) {
if (!(classNameIdentifier.getParent() instanceof PsiClass aClass)) {
return;
}
if (hasImplicitConstructorUsage(aClass)) {
updater.cancel(InspectionGadgetsBundle.message("utility.class.without.private.constructor.cant.generate.constructor.message"));
return;
}
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final PsiElementFactory factory = psiFacade.getElementFactory();
final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
final PsiMethod constructor = factory.createConstructor();
final PsiModifierList modifierList = constructor.getModifierList();
modifierList.setModifierProperty(PsiModifier.PRIVATE, true);
aClass.add(constructor);
final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
styleManager.reformat(constructor);
CodeStyleManager.getInstance(project).reformat(constructor);
}
}
@@ -147,10 +139,8 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
if (!(parent instanceof PsiClass aClass)) {
return;
}
final PsiMethod[] constructors = aClass.getConstructors();
for (final PsiMethod constructor : constructors) {
final PsiParameterList parameterList = constructor.getParameterList();
if (parameterList.isEmpty()) {
for (PsiMethod constructor : aClass.getConstructors()) {
if (constructor.getParameterList().isEmpty()) {
final PsiModifierList modifiers = constructor.getModifierList();
modifiers.setModifierProperty(PsiModifier.PUBLIC, false);
modifiers.setModifierProperty(PsiModifier.PROTECTED, false);
@@ -164,7 +154,6 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
@Override
public void visitClass(@NotNull PsiClass aClass) {
// no call to super, so that it doesn't drill down to inner classes
if (aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
@@ -183,10 +172,8 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
if (aClass.hasModifierProperty(PsiModifier.PRIVATE) && aClass.getConstructors().length == 0) {
return;
}
final SearchScope scope = GlobalSearchScope.projectScope(aClass.getProject());
final Query<PsiClass> query = ClassInheritorsSearch.search(aClass, scope, true);
final PsiClass subclass = query.findFirst();
if (subclass != null) {
boolean hasInheritor = ClassInheritorsSearch.search(aClass, aClass.getUseScope(), true).findFirst() != null;
if (hasInheritor) {
return;
}
registerClassError(aClass, aClass);
@@ -198,33 +185,20 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
return false;
}
for (PsiMethod method : methods) {
if (method.isConstructor()) {
if (method.isConstructor() || method.hasModifierProperty(PsiModifier.PRIVATE)) {
continue;
}
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
if (!method.hasModifierProperty(PsiModifier.STATIC) || !method.hasModifierProperty(PsiModifier.PUBLIC)) {
return false;
}
if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
continue;
}
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
return false;
}
final String name = method.getName();
if (!name.equals(HardcodedMethodConstants.MAIN)) {
return false;
}
final PsiType returnType = method.getReturnType();
if (!PsiTypes.voidType().equals(returnType)) {
if (!HardcodedMethodConstants.MAIN.equals(method.getName()) || !PsiTypes.voidType().equals(method.getReturnType())) {
return false;
}
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 1) {
return false;
}
final PsiParameter[] parameters = parameterList.getParameters();
final PsiParameter parameter = parameters[0];
final PsiType type = parameter.getType();
final PsiType type = parameterList.getParameters()[0].getType();
final @NonNls String stringArray = "java.lang.String[]";
if (!type.equalsToText(stringArray)) {
return false;
@@ -234,8 +208,7 @@ public final class UtilityClassWithoutPrivateConstructorInspection extends BaseI
}
boolean hasPrivateConstructor(PsiClass aClass) {
final PsiMethod[] constructors = aClass.getConstructors();
for (final PsiMethod constructor : constructors) {
for (PsiMethod constructor : aClass.getConstructors()) {
if (constructor.hasModifierProperty(PsiModifier.PRIVATE)) {
return true;
}