added Make public quick fix for the protected member access inspection

This commit is contained in:
Ekaterina Tuzova
2014-03-07 16:37:23 +04:00
parent 155f99a1a3
commit 823897267c
7 changed files with 152 additions and 4 deletions
@@ -22,6 +22,8 @@ QFIX.add.super=Add super class call
QFIX.add.property=Add property for the field
QFIX.use.property=Use property for the field
QFIX.make.public=Make public
QFIX.add.encoding=Add encoding declaration
QFIX.NAME.parameters=Parameters of functions and methods
@@ -30,12 +30,14 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.codeInsight.stdlib.PyNamedTupleType;
import com.jetbrains.python.inspections.quickfix.PyAddPropertyForFieldQuickFix;
import com.jetbrains.python.inspections.quickfix.PyMakePublicQuickFix;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyExpression;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.types.PyModuleType;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
import com.jetbrains.python.testing.pytest.PyTestUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +45,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
@@ -89,19 +92,24 @@ public class PyProtectedMemberInspection extends PyInspection {
final PsiReference reference = node.getReference(getResolveContext());
if (reference == null) return;
final PsiElement resolvedExpression = reference.resolve();
final PyClass resolvedClass = getClassOwner(resolvedExpression);
if (resolvedExpression instanceof PyTargetExpression) {
final PyClass containingClass = ((PyTargetExpression)resolvedExpression).getContainingClass();
if (containingClass != null) {
final String qFixName = containingClass.getProperties().containsKey(StringUtil.trimLeading(name, '_')) ?
final String newName = StringUtil.trimLeading(name, '_');
if (resolvedClass != null) {
final String qFixName = resolvedClass.getProperties().containsKey(newName) ?
PyBundle.message("QFIX.use.property") : PyBundle.message("QFIX.add.property");
quickFixes.add(new PyAddPropertyForFieldQuickFix(qFixName));
final Collection<String> usedNames = PyRefactoringUtil.collectUsedNames(resolvedClass);
if (!usedNames.contains(newName)) {
quickFixes.add(new PyMakePublicQuickFix());
}
}
}
final PyClass parentClass = getClassOwner(node);
if (parentClass != null) {
if (PyTestUtil.isPyTestClass(parentClass) && ignoreTestFunctions) return;
final PyClass resolvedClass = getClassOwner(resolvedExpression);
if (parentClass.isSubclass(resolvedClass))
return;
@@ -0,0 +1,62 @@
/*
* 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.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.refactoring.rename.RenameProcessor;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyReferenceExpression;
import com.jetbrains.python.psi.PyTargetExpression;
import org.jetbrains.annotations.NotNull;
public class PyMakePublicQuickFix implements LocalQuickFix {
@NotNull
@Override
public String getName() {
return PyBundle.message("QFIX.make.public");
}
@NotNull
@Override
public String getFamilyName() {
return PyBundle.message("QFIX.make.public");
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getPsiElement();
if (element instanceof PyReferenceExpression) {
final PsiReference reference = element.getReference();
if (reference == null) return;
element = reference.resolve();
}
if (element instanceof PyTargetExpression) {
final String name = ((PyTargetExpression)element).getName();
if (name == null) return;
final VirtualFile virtualFile = element.getContainingFile().getVirtualFile();
if (virtualFile != null) {
final String publicName = StringUtil.trimLeading(name, '_');
new RenameProcessor(project, element, publicName, false, false).run();
}
}
}
}
@@ -0,0 +1,16 @@
class A:
@property
def x(self):
return self._x
def __init__(self):
self._x = 1
def _foo(self):
print(self._x)
a = A()
a._foo()
print(a.x)
print(a.<caret>_x)
@@ -0,0 +1,11 @@
class A:
def __init__(self):
self._x = 1
def _foo(self):
print(self._x)
a = A()
a._foo()
print(a.<caret>_x)
@@ -0,0 +1,11 @@
class A:
def __init__(self):
self.x = 1
def _foo(self):
print(self.x)
a = A()
a._foo()
print(a.x)
@@ -0,0 +1,38 @@
/*
* 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.quickFixes;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyQuickFixTestCase;
import com.jetbrains.python.inspections.PyProtectedMemberInspection;
@TestDataPath("$CONTENT_ROOT/../testData/quickFixes/PyMakePublicQuickFixTest")
public class PyMakePublicQuickFixTest extends PyQuickFixTestCase {
public void testPositive() {
doQuickFixTest(PyProtectedMemberInspection.class, PyBundle.message("QFIX.make.public"));
}
public void testNegative() {
final String testFileName = getTestName(true);
myFixture.enableInspections(PyProtectedMemberInspection.class);
myFixture.configureByFile(testFileName + ".py");
myFixture.checkHighlighting(true, false, false);
final IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.make.public"));
assertNull(intentionAction);
}
}