mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Move PyPropertyAccessInspection functionality which relates to __slots__ to PyDunderSlotsInspection
This commit is contained in:
@@ -21,6 +21,8 @@ import com.intellij.psi.PsiElementVisitor
|
||||
import com.jetbrains.python.PyNames
|
||||
import com.jetbrains.python.psi.*
|
||||
import com.jetbrains.python.psi.impl.PyPsiUtils
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext
|
||||
import com.jetbrains.python.psi.types.PyClassType
|
||||
|
||||
class PyDunderSlotsInspection : PyInspection() {
|
||||
|
||||
@@ -31,6 +33,8 @@ class PyDunderSlotsInspection : PyInspection() {
|
||||
private class Visitor(holder: ProblemsHolder, session: LocalInspectionToolSession) : PyInspectionVisitor(holder, session) {
|
||||
|
||||
override fun visitPyClass(node: PyClass?) {
|
||||
super.visitPyClass(node)
|
||||
|
||||
if (node != null && LanguageLevel.forElement(node).isAtLeast(LanguageLevel.PYTHON30)) {
|
||||
val slots = findSlotsValue(node)
|
||||
|
||||
@@ -47,6 +51,14 @@ class PyDunderSlotsInspection : PyInspection() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPyTargetExpression(node: PyTargetExpression?) {
|
||||
super.visitPyTargetExpression(node)
|
||||
|
||||
if (node != null) {
|
||||
checkAttributeExpression(node)
|
||||
}
|
||||
}
|
||||
|
||||
private fun findSlotsValue(pyClass: PyClass): PyExpression? {
|
||||
val target = pyClass.findClassAttribute(PyNames.SLOTS, false, myTypeEvalContext) as? PyTargetExpression
|
||||
val value = target?.findAssignedValue()
|
||||
@@ -61,6 +73,57 @@ class PyDunderSlotsInspection : PyInspection() {
|
||||
registerProblem(slot, "'$name' in __slots__ conflicts with class variable")
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAttributeExpression(target: PyTargetExpression) {
|
||||
val targetName = target.name
|
||||
val qualifier = target.qualifier
|
||||
|
||||
if (targetName == null || qualifier == null) {
|
||||
return
|
||||
}
|
||||
|
||||
val qualifierType = myTypeEvalContext.getType(qualifier)
|
||||
if (qualifierType is PyClassType && !qualifierType.isDefinition) {
|
||||
val reference = target.getReference(PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext))
|
||||
val qualifierClass = qualifierType.pyClass
|
||||
|
||||
val classWithReadOnlyAttr = PyUtil
|
||||
.multiResolveTopPriority(reference)
|
||||
.asSequence()
|
||||
.filterIsInstance<PyTargetExpression>()
|
||||
.map { declaration -> declaration.containingClass }
|
||||
.filterNotNull()
|
||||
.find { declaringClass -> !attributeIsWritable(qualifierClass, declaringClass, targetName) }
|
||||
|
||||
if (classWithReadOnlyAttr != null) {
|
||||
registerProblem(target, "'${qualifierClass.name}' object attribute '$targetName' is read-only")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun attributeIsWritable(qualifierClass: PyClass, declaringClass: PyClass, targetName: String): Boolean {
|
||||
return attributeIsWritableInClass(qualifierClass, declaringClass, targetName) ||
|
||||
qualifierClass
|
||||
.getAncestorClasses(myTypeEvalContext)
|
||||
.asSequence()
|
||||
.filter { ancestorClass -> !PyUtil.isObjectClass(ancestorClass) }
|
||||
.any { ancestorClass -> attributeIsWritableInClass(ancestorClass, declaringClass, targetName) }
|
||||
}
|
||||
|
||||
private fun attributeIsWritableInClass(cls: PyClass, declaringClass: PyClass, targetName: String): Boolean {
|
||||
val ownSlots = cls.ownSlots
|
||||
|
||||
if (ownSlots == null || ownSlots.contains(PyNames.DICT)) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (!cls.equals(declaringClass) || !ownSlots.contains(targetName)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return LanguageLevel.forElement(declaringClass).isAtLeast(LanguageLevel.PYTHON30) ||
|
||||
declaringClass.findClassAttribute(targetName, false, myTypeEvalContext) == null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,18 +22,14 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.inspections.quickfix.PyCreatePropertyQuickFix;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.resolve.PyResolveContext;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.toolbox.Maybe;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Checks that properties are accessed correctly.
|
||||
* User: dcheryasov
|
||||
@@ -75,7 +71,6 @@ public class PyPropertyAccessInspection extends PyInspection {
|
||||
public void visitPyTargetExpression(PyTargetExpression node) {
|
||||
super.visitPyTargetExpression(node);
|
||||
checkPropertyExpression(node);
|
||||
checkAttributeExpression(node);
|
||||
}
|
||||
|
||||
private void checkPropertyExpression(PyQualifiedExpression node) {
|
||||
@@ -126,59 +121,5 @@ public class PyPropertyAccessInspection extends PyInspection {
|
||||
registerProblem(node, message, new PyCreatePropertyQuickFix(dir));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAttributeExpression(@NotNull PyTargetExpression target) {
|
||||
final String targetName = target.getName();
|
||||
final PyExpression qualifier = target.getQualifier();
|
||||
|
||||
if (targetName == null || qualifier == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final PyType qualifierType = myTypeEvalContext.getType(qualifier);
|
||||
|
||||
if (qualifierType instanceof PyClassType) {
|
||||
final PyClassType qualifierClassType = (PyClassType)qualifierType;
|
||||
|
||||
if (!qualifierClassType.isDefinition()) {
|
||||
final PyClass qualifierClass = qualifierClassType.getPyClass();
|
||||
|
||||
PyUtil
|
||||
.multiResolveTopPriority(target.getReference(PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext)))
|
||||
.stream()
|
||||
.filter(PyTargetExpression.class::isInstance)
|
||||
.map(declaration -> ((PyTargetExpression)declaration).getContainingClass())
|
||||
.filter(declaringClass -> declaringClass != null && !attributeIsWritable(qualifierClass, declaringClass, targetName))
|
||||
.findFirst()
|
||||
.ifPresent(
|
||||
cls -> registerProblem(target, String.format("'%s' object attribute '%s' is read-only", qualifierClass.getName(), targetName))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean attributeIsWritable(@NotNull PyClass qualifierClass, @NotNull PyClass declaringClass, @NotNull String targetName) {
|
||||
return attributeIsWritableInClass(qualifierClass, declaringClass, targetName) ||
|
||||
qualifierClass
|
||||
.getAncestorClasses(myTypeEvalContext)
|
||||
.stream()
|
||||
.filter(ancestorClass -> !PyUtil.isObjectClass(ancestorClass))
|
||||
.anyMatch(ancestorClass -> attributeIsWritableInClass(ancestorClass, declaringClass, targetName));
|
||||
}
|
||||
|
||||
private boolean attributeIsWritableInClass(@NotNull PyClass cls, @NotNull PyClass declaringClass, @NotNull String targetName) {
|
||||
final List<String> ownSlots = cls.getOwnSlots();
|
||||
|
||||
if (ownSlots == null || ownSlots.contains(PyNames.DICT)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!cls.equals(declaringClass) || !ownSlots.contains(targetName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return LanguageLevel.forElement(declaringClass).isAtLeast(LanguageLevel.PYTHON30) ||
|
||||
declaringClass.findClassAttribute(targetName, false, myTypeEvalContext) == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class B(object):
|
||||
__slots__ = ['f', 'b']
|
||||
|
||||
class C(B):
|
||||
attr = 'baz'
|
||||
__slots__ = [<warning descr="'attr' in __slots__ conflicts with class variable">'attr'</warning>, 'bar']
|
||||
|
||||
C.attr = 'spam'
|
||||
print(C.attr)
|
||||
|
||||
c = C()
|
||||
c.attr = 'spam'
|
||||
print(c.attr)
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Foo(object):
|
||||
attr = 'baz'
|
||||
__slots__ = [<warning descr="'attr' in __slots__ conflicts with class variable">'attr'</warning>, 'bar']
|
||||
|
||||
Foo.attr = 'spam'
|
||||
print(Foo.attr)
|
||||
|
||||
foo = Foo()
|
||||
foo.attr = 'spam'
|
||||
print(foo.attr)
|
||||
-4
@@ -1,7 +1,3 @@
|
||||
# Py3: OK
|
||||
# Py2:
|
||||
# ValueError: 'attr' in __slots__ conflicts with class variable
|
||||
# This is not responsibility of current inspection
|
||||
class B(object):
|
||||
attr = 'baz'
|
||||
__slots__ = ['f', 'attr', '__dict__']
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class B(object):
|
||||
attr = 'baz'
|
||||
__slots__ = ['f', <warning descr="'attr' in __slots__ conflicts with class variable">'attr'</warning>, '__dict__']
|
||||
|
||||
class C(B):
|
||||
__slots__ = ['foo', 'bar']
|
||||
|
||||
C.attr = 'spam'
|
||||
print(C.attr)
|
||||
|
||||
c = C()
|
||||
c.attr = 'spam'
|
||||
print(c.attr)
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
# ValueError: 'attr' in __slots__ conflicts with class variable
|
||||
# This is not responsibility of current inspection
|
||||
class B(object):
|
||||
attr = 'baz'
|
||||
__slots__ = ['attr', 'b']
|
||||
__slots__ = [<warning descr="'attr' in __slots__ conflicts with class variable">'attr'</warning>, 'b']
|
||||
|
||||
class C(B):
|
||||
__slots__ = ['foo', 'bar']
|
||||
-4
@@ -1,7 +1,3 @@
|
||||
# Py2: OK
|
||||
# Py3:
|
||||
# ValueError: 'attr' in __slots__ conflicts with class variable
|
||||
# This is not responsibility of current inspection
|
||||
class B(object):
|
||||
attr = 'baz'
|
||||
__slots__ = ['f', 'attr']
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
class B(object):
|
||||
attr = 'baz'
|
||||
__slots__ = ['f', <warning descr="'attr' in __slots__ conflicts with class variable">'attr'</warning>]
|
||||
|
||||
class C(B):
|
||||
__slots__ = ['foo', 'bar', '__dict__']
|
||||
|
||||
C.attr = 'spam'
|
||||
print(C.attr)
|
||||
|
||||
c = C()
|
||||
c.attr = 'spam'
|
||||
print(c.attr)
|
||||
-15
@@ -1,15 +0,0 @@
|
||||
class B(object):
|
||||
__slots__ = ['f', 'b']
|
||||
|
||||
# ValueError: 'attr' in __slots__ conflicts with class variable
|
||||
# This is not responsibility of current inspection
|
||||
class C(B):
|
||||
attr = 'baz'
|
||||
__slots__ = ['attr', 'bar']
|
||||
|
||||
C.attr = 'spam'
|
||||
print(C.attr)
|
||||
|
||||
c = C()
|
||||
c.attr = 'spam'
|
||||
print(c.attr)
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
# ValueError: 'attr' in __slots__ conflicts with class variable
|
||||
# This is not responsibility of current inspection
|
||||
class Foo(object):
|
||||
attr = 'baz'
|
||||
__slots__ = ['attr', 'bar']
|
||||
|
||||
Foo.attr = 'spam'
|
||||
print(Foo.attr)
|
||||
|
||||
foo = Foo()
|
||||
foo.attr = 'spam'
|
||||
print(foo.attr)
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* 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.
|
||||
* 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.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
public class PyDunderSlotsInspectionTest extends PyTestCase {
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlotsWithDict() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlotsWithAttrPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlotsWithAttrPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnSlotsAndEmptyParent() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithDictAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithDictAndInheritedWithAttrSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedWithDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithAttrAndInheritedSlotsPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithAttrAndInheritedSlotsPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedWithAttrSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedWithAttrAndDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithAttrAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithDictAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithAttrAndDictAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrSlotsPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrSlotsPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrAndDictSlotsPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrAndDictSlotsPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithAttrAndInheritedWithDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithDictAndInheritedWithAttrSlotsPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithDictAndInheritedWithAttrSlotsPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-19956
|
||||
public void testWriteToAttrInSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
private void doTestPy2() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON26, this::doTestPy);
|
||||
}
|
||||
|
||||
private void doTestPy3() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, this::doTestPy);
|
||||
}
|
||||
|
||||
private void doTestPy() {
|
||||
final String path = "inspections/PyDunderSlotsInspectionTest/" + getTestName(true) + ".py";
|
||||
|
||||
final VirtualFile file = myFixture.getTempDirFixture().getFile(path);
|
||||
if (file != null) {
|
||||
try {
|
||||
WriteAction.run(() -> file.delete(this));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
myFixture.configureByFile(path);
|
||||
myFixture.enableInspections(PyDunderSlotsInspection.class);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
}
|
||||
+5
-185
@@ -15,205 +15,25 @@
|
||||
*/
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.jetbrains.python.fixtures.PyTestCase;
|
||||
import com.jetbrains.python.psi.LanguageLevel;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
public class PyPropertyAccessInspectionTest extends PyTestCase {
|
||||
public void testTest() {
|
||||
doTestPy2();
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-2313
|
||||
public void testOverrideAssignment() {
|
||||
doTestPy2();
|
||||
doTest();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlotsWithDict() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlotsWithAttrPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndSlotsWithAttrPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnSlotsAndEmptyParent() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithDictAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithDictAndInheritedWithAttrSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedWithDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithAttrAndInheritedSlotsPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnWithAttrAndInheritedSlotsPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedWithAttrSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testClassAttrAssignmentAndOwnAndInheritedWithAttrAndDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithAttrAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithDictAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithAttrAndDictAndInheritedSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrSlotsPy2() {
|
||||
doTestPy2();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrSlotsPy3() {
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnAndInheritedWithAttrAndDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithAttrAndInheritedWithDictSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-12773
|
||||
public void testInheritedClassAttrAssignmentAndOwnWithDictAndInheritedWithAttrSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
// PY-19956
|
||||
public void testWriteToAttrInSlots() {
|
||||
doTestPy2();
|
||||
doTestPy3();
|
||||
}
|
||||
|
||||
private void doTestPy2() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON26, this::doTestPy);
|
||||
}
|
||||
|
||||
private void doTestPy3() {
|
||||
runWithLanguageLevel(LanguageLevel.PYTHON30, this::doTestPy);
|
||||
}
|
||||
|
||||
private void doTestPy() {
|
||||
final String path = "inspections/PyPropertyAccessInspection/" + getTestName(true) + ".py";
|
||||
|
||||
final VirtualFile file = myFixture.getTempDirFixture().getFile(path);
|
||||
if (file != null) {
|
||||
try {
|
||||
WriteAction.run(() -> file.delete(this));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
myFixture.configureByFile(path);
|
||||
private void doTest() {
|
||||
setLanguageLevel(LanguageLevel.PYTHON26);
|
||||
myFixture.configureByFile("inspections/PyPropertyAccessInspection/" + getTestName(true) + ".py");
|
||||
myFixture.enableInspections(PyPropertyAccessInspection.class);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user