From b4525c6ecfc21aeef5acd87b0f8bf9af3fb9f01b Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Thu, 3 Aug 2017 14:53:39 +0300 Subject: [PATCH] PY-24436 Fixed: False positive: "Class has not __init__ method" if A inherits B which inherits another A with __init__ Use type eval context in PyClassHasNoInitInspection while looking for __init__ or __new__ method --- .../inspections/PyClassHasNoInitInspection.java | 6 +++--- .../a.py | 10 ++++++++++ .../lib.py | 6 ++++++ .../PyClassHasNoInitInspectionTest.java | 17 ++++++++++++++++- 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/a.py create mode 100644 python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/lib.py diff --git a/python/src/com/jetbrains/python/inspections/PyClassHasNoInitInspection.java b/python/src/com/jetbrains/python/inspections/PyClassHasNoInitInspection.java index 06e73c177988..5c422d000cfe 100644 --- a/python/src/com/jetbrains/python/inspections/PyClassHasNoInitInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyClassHasNoInitInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -73,10 +73,10 @@ public class PyClassHasNoInitInspection extends PyInspection { if (!(type instanceof PyClassType)) return; } - final PyFunction init = node.findInitOrNew(true, null); + final PyFunction init = node.findInitOrNew(true, myTypeEvalContext); if (init == null) { registerProblem(node.getNameIdentifier(), PyBundle.message("INSP.class.has.no.init"), - new AddMethodQuickFix("__init__", node.getName(), false)); + new AddMethodQuickFix(PyNames.INIT, node.getName(), false)); } } } diff --git a/python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/a.py b/python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/a.py new file mode 100644 index 000000000000..ffb71b07ea8d --- /dev/null +++ b/python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/a.py @@ -0,0 +1,10 @@ +from lib import Alice + + +class Intermediary(Alice): + pass + + +class Alice(Intermediary): + def __str__(self): + return 'New Alice' \ No newline at end of file diff --git a/python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/lib.py b/python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/lib.py new file mode 100644 index 000000000000..2d7ff58c9e95 --- /dev/null +++ b/python/testData/inspections/PyClassHasNoInitInspection/AInheritsBAndBInheritsImportedAWithDunderInit/lib.py @@ -0,0 +1,6 @@ +class Alice: + def __init__(self): + pass + + def __str__(self): + return 'Old Alice' \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyClassHasNoInitInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyClassHasNoInitInspectionTest.java index c1b44803b603..3bb8c8b604a9 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyClassHasNoInitInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyClassHasNoInitInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -16,6 +16,7 @@ package com.jetbrains.python.inspections; import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.psi.LanguageLevel; public class PyClassHasNoInitInspectionTest extends PyTestCase { @@ -51,9 +52,23 @@ public class PyClassHasNoInitInspectionTest extends PyTestCase { doTest(); } + // PY-24436 + public void testAInheritsBAndBInheritsImportedAWithDunderInit() { + runWithLanguageLevel(LanguageLevel.PYTHON30, this::doMultiFileTest); + } + private void doTest() { myFixture.configureByFile("inspections/PyClassHasNoInitInspection/" + getTestName(true) + ".py"); myFixture.enableInspections(PyClassHasNoInitInspection.class); myFixture.checkHighlighting(false, false, true); } + + private void doMultiFileTest() { + final String folderPath = "inspections/PyClassHasNoInitInspection/" + getTestName(false) + "/"; + + myFixture.copyDirectoryToProject(folderPath, ""); + myFixture.configureFromTempProjectFile("a.py"); + myFixture.enableInspections(PyClassHasNoInitInspection.class); + myFixture.checkHighlighting(false, false, true); + } }