blob: 0c4333a6f2e3edf983d984741900d44274c859f2 [file] [log] [blame]
/*
* Copyright 2000-2013 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.
* 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.jetbrains.python.inspections;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.inspections.quickfix.PyMakeFunctionFromMethodQuickFix;
import com.jetbrains.python.inspections.quickfix.PyMakeMethodStaticQuickFix;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.search.PyOverridingMethodsSearch;
import com.jetbrains.python.psi.search.PySuperMethodsSearch;
import com.jetbrains.python.testing.PythonUnitTestUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* User: ktisha
*
*/
public class PyMethodMayBeStaticInspection extends PyInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return PyBundle.message("INSP.NAME.method.may.be.static");
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
boolean isOnTheFly,
@NotNull LocalInspectionToolSession session) {
return new Visitor(holder, session);
}
private static class Visitor extends PyInspectionVisitor {
public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) {
super(holder, session);
}
@Override
public void visitPyFunction(PyFunction node) {
if (PyNames.getBuiltinMethods(LanguageLevel.forElement(node)).containsKey(node.getName())) return;
final PyClass containingClass = node.getContainingClass();
if (containingClass == null) return;
if (PythonUnitTestUtil.isUnitTestCaseClass(containingClass)) return;
final PsiElement firstSuper = PySuperMethodsSearch.search(node).findFirst();
if (firstSuper != null) return;
final PyFunction firstOverride = PyOverridingMethodsSearch.search(node, true).findFirst();
if (firstOverride != null) return;
final PyDecoratorList decoratorList = node.getDecoratorList();
if (decoratorList != null) return;
if (node.getModifier() != null) return;
final Property property = containingClass.findPropertyByCallable(node);
if (property != null) return;
final PyStatementList statementList = node.getStatementList();
final PyStatement[] statements = statementList.getStatements();
if (statements.length == 1 && statements[0] instanceof PyPassStatement) return;
final PyParameter[] parameters = node.getParameterList().getParameters();
final String selfName;
if (parameters.length > 0) {
final String name = parameters[0].getName();
selfName = name != null ? name : parameters[0].getText();
}
else {
selfName = PyNames.CANONICAL_SELF;
}
final boolean[] mayBeStatic = {true};
PyRecursiveElementVisitor visitor = new PyRecursiveElementVisitor() {
@Override
public void visitPyRaiseStatement(PyRaiseStatement node) {
super.visitPyRaiseStatement(node);
final PyExpression[] expressions = node.getExpressions();
if (expressions.length == 1) {
final PyExpression expression = expressions[0];
if (expression instanceof PyCallExpression) {
final PyExpression callee = ((PyCallExpression)expression).getCallee();
if (callee != null && PyNames.NOT_IMPLEMENTED_ERROR.equals(callee.getText()))
mayBeStatic[0] = false;
}
else if (PyNames.NOT_IMPLEMENTED_ERROR.equals(expression.getText())) {
mayBeStatic[0] = false;
}
}
}
@Override
public void visitPyReferenceExpression(PyReferenceExpression node) {
super.visitPyReferenceExpression(node);
if (selfName.equals(node.getName())) {
mayBeStatic[0] = false;
}
}
};
node.accept(visitor);
final PsiElement identifier = node.getNameIdentifier();
if (mayBeStatic[0] && identifier != null) {
registerProblem(identifier, PyBundle.message("INSP.method.may.be.static"), ProblemHighlightType.WEAK_WARNING,
null, new PyMakeMethodStaticQuickFix(), new PyMakeFunctionFromMethodQuickFix());
}
}
}
}