[groovy] method may be static: add option to ignore trait methods, ignore methods with explicit abstract modifier

This commit is contained in:
Daniil Ovchinnikov
2016-03-29 13:38:27 +03:00
parent 6d39198b84
commit 678ec7a127
3 changed files with 55 additions and 14 deletions
@@ -101,6 +101,7 @@ anonymous.class=anonymous class
closure=closure
other.scope=Other scope
method.may.be.static=Method may be static
method.may.be.static.option.ignore.trait.methods=Ignore trait methods
method.may.be.static.only.private.or.final.option=Only check final or private methods
method.may.be.static.ignore.empty.method.option=Ignore empty methods
have.instance.refs.in.closure=(have instance references inside closure)
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,7 +28,6 @@ import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.codeInspection.bugs.GrModifierFix;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
@@ -37,24 +36,27 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTraitTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import javax.swing.*;
@SuppressWarnings("JavaStylePropertiesInvocation")
import static org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle.message;
public class GrMethodMayBeStaticInspection extends BaseInspection {
public boolean myIgnoreTraitMethods = true;
public boolean myOnlyPrivateOrFinal = false;
public boolean myIgnoreEmptyMethods = true;
@Override
public JComponent createOptionsPanel() {
final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
optionsPanel.addCheckbox(GroovyInspectionBundle.message("method.may.be.static.only.private.or.final.option"), "myOnlyPrivateOrFinal");
optionsPanel.addCheckbox(GroovyInspectionBundle.message("method.may.be.static.ignore.empty.method.option"), "myIgnoreEmptyMethods");
optionsPanel.addCheckbox(message("method.may.be.static.option.ignore.trait.methods"), "myIgnoreTraitMethods");
optionsPanel.addCheckbox(message("method.may.be.static.only.private.or.final.option"), "myOnlyPrivateOrFinal");
optionsPanel.addCheckbox(message("method.may.be.static.ignore.empty.method.option"), "myIgnoreEmptyMethods");
return optionsPanel;
}
@@ -74,7 +76,7 @@ public class GrMethodMayBeStaticInspection extends BaseInspection {
return ((GrMethod)parent).getModifierList();
}
});
registerError(method.getNameIdentifierGroovy(), GroovyInspectionBundle.message("method.may.be.static"), new LocalQuickFix[]{modifierFix}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
registerError(method.getNameIdentifierGroovy(), message("method.may.be.static"), new LocalQuickFix[]{modifierFix}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}
};
@@ -83,8 +85,13 @@ public class GrMethodMayBeStaticInspection extends BaseInspection {
private boolean checkMethod(final GrMethod method) {
if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
if (method.hasModifierProperty(PsiModifier.SYNCHRONIZED)) return false;
if (method.getModifierList().hasExplicitModifier(PsiModifier.ABSTRACT)) return false;
if (method.isConstructor()) return false;
if (method.getContainingClass() instanceof GroovyScriptClass) return false;
PsiClass containingClass = method.getContainingClass();
if (containingClass == null) return false;
if (myIgnoreTraitMethods && containingClass instanceof GrTraitTypeDefinition) return false;
if (SuperMethodsSearch.search(method, null, true, false).findFirst() != null) return false;
if (OverridingMethodsSearch.search(method).findFirst() != null) return false;
if (ignoreMethod(method)) return false;
@@ -97,8 +104,6 @@ public class GrMethodMayBeStaticInspection extends BaseInspection {
if (block == null) return false;
if (myIgnoreEmptyMethods && block.getStatements().length == 0) return false;
PsiClass containingClass = method.getContainingClass();
if (containingClass == null) return false;
if (containingClass.getContainingClass() != null && !containingClass.hasModifierProperty(PsiModifier.STATIC)) {
return false;
}
@@ -133,7 +138,6 @@ public class GrMethodMayBeStaticInspection extends BaseInspection {
private static boolean isPrintOrPrintln(PsiElement element) {
return element instanceof GrGdkMethod &&
element instanceof PsiMethod &&
("print".equals(((PsiMethod)element).getName()) || "println".equals(((PsiMethod)element).getName()));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,13 +15,21 @@
*/
package org.jetbrains.plugins.groovy.inspections
import com.intellij.testFramework.LightProjectDescriptor
import groovy.transform.CompileStatic
import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.codeInspection.declaration.GrMethodMayBeStaticInspection
/**
* @author Max Medvedev
*/
@CompileStatic
public class GrMethodMayBeStaticTest extends LightGroovyTestCase {
final String basePath = null
final LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_2_3_9
final GrMethodMayBeStaticInspection inspection = new GrMethodMayBeStaticInspection()
void testSimple() {
doTest('''\
@@ -68,10 +76,19 @@ class A {
''')
}
void 'test abstract method with code block no error'() {
doTest '''
abstract class A {
abstract foo() <error descr="Abstract methods must not have body">{
1 + 2
}</error>
}
'''
}
private void doTest(final String text) {
myFixture.configureByText('_.groovy', text)
myFixture.enableInspections(GrMethodMayBeStaticInspection)
myFixture.enableInspections(inspection)
myFixture.checkHighlighting(true, false, false)
}
@@ -141,4 +158,23 @@ class Bar {
}
''')
}
void 'test trait methods'() {
doTest '''\
trait A {
def foo() {1}
abstract bar()
}
'''
}
void 'test trait methods with'() {
inspection.myIgnoreTraitMethods = false
doTest '''\
trait A {
def <warning descr="Method may be static">foo</warning>() {1}
abstract bar()
}
'''
}
}