Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ contract.return.validator.return.type.must.be.boolean:
text: method return type must be 'boolean'
contract.return.validator.too.few.parameters:
text: not applicable for method that has {0, choice, 0#no parameters|1#one parameter|2#{0} parameters}
contract.return.value.validation.prefix:
text: 'Contract return value ''''{0}'''':'
contract.return.value.validation.problem:
text: 'Contract return value ''''{0}'''': {1}'
convert.0.to.float:
text: Convert ''{0}'' to float
custom.exception.class.should.have.a.constructor:
Expand Down Expand Up @@ -663,9 +663,9 @@ inspection.message.nullable.method.implements.non.null.method:
inspection.module.exports.package.to.itself:
text: Module exports/opens package to itself
inspection.non.final.field.in.immutable.display.name:
text: Non-final field in @Immutable class
text: Non-final field in '@Immutable' class
inspection.non.final.guard.display.name:
text: Non-final @GuardedBy field
text: Non-final '@GuardedBy' field
inspection.nullable.problems.NotNull.parameter.overrides.Nullable:
text: Parameter annotated @{0} must not override @{1} parameter
inspection.nullable.problems.NotNull.parameter.overrides.not.annotated:
Expand Down Expand Up @@ -877,11 +877,11 @@ mutation.signature.problem.static.method.cannot.mutate.this:
navigate.to.overridden.methods.title:
text: Overriding methods of {0}
non.final.field.code.ref.code.in.immutable.class.loc:
text: 'Non-final field <code>#ref</code> in @Immutable class #loc'
text: 'Non-final field <code>#ref</code> in ''@Immutable'' class #loc'
non.final.guarded.by.field.0.loc:
text: 'Non-final @GuardedBy field "{0}" #loc'
text: 'Non-final ''@GuardedBy'' field "{0}" #loc'
non.final.guarded.by.field.ref.loc:
text: 'Non-final @GuardedBy field #ref #loc'
text: 'Non-final ''@GuardedBy'' field #ref #loc'
non.null.type.argument.is.expected:
text: Non-null type argument is expected
not.annotated.method.is.used.as.an.override.for.a.method.annotated.with.0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
import com.intellij.java.language.codeInsight.TestFrameworks;
import com.intellij.java.language.psi.*;
import com.intellij.java.language.psi.util.InheritanceUtil;
import consulo.annotation.access.RequiredReadAction;
import consulo.annotation.component.ExtensionImpl;
import consulo.language.editor.inspection.LocalInspectionToolSession;
import consulo.language.editor.inspection.ProblemHighlightType;
import consulo.language.editor.inspection.ProblemsHolder;
import consulo.language.psi.PsiElementVisitor;
import consulo.localize.LocalizeValue;
Expand All @@ -37,107 +37,112 @@
*/
@ExtensionImpl
public class ClassHasNoToStringMethodInspection extends AbstractToStringInspection {
@Override
@Nonnull
public LocalizeValue getDisplayName() {
return LocalizeValue.localizeTODO("Class does not override 'toString()' method");
}
@Override
@Nonnull
public LocalizeValue getDisplayName() {
return LocalizeValue.localizeTODO("Class does not override 'toString()' method");
}

@Override
@Nonnull
public String getShortName() {
return "ClassHasNoToStringMethod";
}
@Override
@Nonnull
public String getShortName() {
return "ClassHasNoToStringMethod";
}

@Nonnull
@Override
public PsiElementVisitor buildVisitor(@Nonnull final ProblemsHolder holder,
boolean isOnTheFly,
LocalInspectionToolSession session,
Object state) {
ClassHasNoToStringMethodInspectionState inspectionState = (ClassHasNoToStringMethodInspectionState)state;
return new JavaElementVisitor() {
@Override
public void visitClass(PsiClass clazz) {
if (AbstractToStringInspection.log.isDebugEnabled()) {
AbstractToStringInspection.log.debug("checkClass: clazz=" + clazz);
}
@Nonnull
@Override
public PsiElementVisitor buildVisitor(
@Nonnull final ProblemsHolder holder,
boolean isOnTheFly,
@Nonnull LocalInspectionToolSession session,
@Nonnull Object state
) {
ClassHasNoToStringMethodInspectionState inspectionState = (ClassHasNoToStringMethodInspectionState) state;
return new JavaElementVisitor() {
@Override
@RequiredReadAction
public void visitClass(@Nonnull PsiClass clazz) {
if (AbstractToStringInspection.log.isDebugEnabled()) {
AbstractToStringInspection.log.debug("checkClass: clazz=" + clazz);
}

// must be a class
final PsiIdentifier nameIdentifier = clazz.getNameIdentifier();
if (nameIdentifier == null || clazz.getName() == null) {
return;
}
// must be a class
PsiIdentifier nameIdentifier = clazz.getNameIdentifier();
if (nameIdentifier == null || clazz.getName() == null) {
return;
}

if (inspectionState.excludeException && InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE)) {
return;
}
if (inspectionState.excludeDeprecated && clazz.isDeprecated()) {
return;
}
if (inspectionState.excludeEnum && clazz.isEnum()) {
return;
}
if (inspectionState.excludeAbstract && clazz.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
if (inspectionState.excludeTestCode && TestFrameworks.getInstance().isTestClass(clazz)) {
return;
}
if (inspectionState.excludeInnerClasses && clazz.getContainingClass() != null) {
return;
}
if (inspectionState.excludeException && InheritanceUtil.isInheritor(clazz, CommonClassNames.JAVA_LANG_THROWABLE)) {
return;
}
if (inspectionState.excludeDeprecated && clazz.isDeprecated()) {
return;
}
if (inspectionState.excludeEnum && clazz.isEnum()) {
return;
}
if (inspectionState.excludeAbstract && clazz.isAbstract()) {
return;
}
if (inspectionState.excludeTestCode && TestFrameworks.getInstance().isTestClass(clazz)) {
return;
}
if (inspectionState.excludeInnerClasses && clazz.getContainingClass() != null) {
return;
}

// if it is an excluded class - then skip
if (StringUtil.isNotEmpty(inspectionState.excludeClassNames)) {
String name = clazz.getName();
if (name != null && name.matches(inspectionState.excludeClassNames)) {
return;
}
}
// if it is an excluded class - then skip
if (StringUtil.isNotEmpty(inspectionState.excludeClassNames)) {
String name = clazz.getName();
if (name != null && name.matches(inspectionState.excludeClassNames)) {
return;
}
}

// must have fields
PsiField[] fields = clazz.getFields();
if (fields.length == 0) {
return;
}
// must have fields
PsiField[] fields = clazz.getFields();
if (fields.length == 0) {
return;
}

// get list of fields and getter methods supposed to be dumped in the toString method
fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern());
PsiMethod[] methods = null;
if (GenerateToStringContext.getConfig().isEnableMethods()) {
// okay 'getters in code generation' is enabled so check
methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern());
}
// get list of fields and getter methods supposed to be dumped in the toString method
fields = GenerateToStringUtils.filterAvailableFields(clazz, GenerateToStringContext.getConfig().getFilterPattern());
PsiMethod[] methods = null;
if (GenerateToStringContext.getConfig().isEnableMethods()) {
// okay 'getters in code generation' is enabled so check
methods = GenerateToStringUtils.filterAvailableMethods(clazz, GenerateToStringContext.getConfig().getFilterPattern());
}

// there should be any fields
if (Math.max(fields.length, methods == null ? 0 : methods.length) == 0) {
return;
}
// there should be any fields
if (Math.max(fields.length, methods == null ? 0 : methods.length) == 0) {
return;
}

// okay some fields/getter methods are supposed to dumped, does a toString method exist
final PsiMethod[] toStringMethods = clazz.findMethodsByName("toString", false);
for (PsiMethod method : toStringMethods) {
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() == 0) {
// toString() method found
return;
}
}
final PsiMethod[] superMethods = clazz.findMethodsByName("toString", true);
for (PsiMethod method : superMethods) {
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 0) {
continue;
}
if (method.hasModifierProperty(PsiModifier.FINAL)) {
// final toString() in super class found
return;
}
}
holder.registerProblem(nameIdentifier, "Class '" + clazz.getName() + "' does not override 'toString()' method",
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, GenerateToStringQuickFix.getInstance());
}
};
}
// okay some fields/getter methods are supposed to dumped, does a toString method exist
PsiMethod[] toStringMethods = clazz.findMethodsByName("toString", false);
for (PsiMethod method : toStringMethods) {
PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() == 0) {
// toString() method found
return;
}
}
PsiMethod[] superMethods = clazz.findMethodsByName("toString", true);
for (PsiMethod method : superMethods) {
PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() != 0) {
continue;
}
if (method.isFinal()) {
// final toString() in super class found
return;
}
}
holder.newProblem(LocalizeValue.of("Class '" + clazz.getName() + "' does not override 'toString()' method"))
.range(nameIdentifier)
.withFixes(GenerateToStringQuickFix.getInstance())
.create();
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1592,3 +1592,5 @@ xml.suppressable.for.file.title:
text: Suppress for file
xml.suppressable.for.tag.title:
text: Suppress for tag
inspection.message.redundant.default.parameter.value.assignment:
text: Redundant default parameter value assignment
Loading
Loading