diff --git a/.idea/libraries/asm5.xml b/.idea/libraries/ASM.xml similarity index 68% rename from .idea/libraries/asm5.xml rename to .idea/libraries/ASM.xml index e4873676bb75..7ed029a31507 100644 --- a/.idea/libraries/asm5.xml +++ b/.idea/libraries/ASM.xml @@ -1,11 +1,11 @@ - + - + \ No newline at end of file diff --git a/build/asm/1_version_check.patch b/build/asm/1_version_check.patch index 63ec6e0278f8..45eb8373f4c7 100644 --- a/build/asm/1_version_check.patch +++ b/build/asm/1_version_check.patch @@ -5,7 +5,7 @@ Index: org/objectweb/asm/ClassReader.java @@ -167,7 +167,7 @@ this.b = b; // checks the class version - if (readShort(off + 6) > Opcodes.V1_8) { + if (readShort(off + 6) > Opcodes.V1_9) { - throw new IllegalArgumentException(); + //[JB: accept any version] throw new IllegalArgumentException(); } diff --git a/build/asm/repackage.xml b/build/asm/repackage.xml index 75336cfbe16b..6d72c6d4c53a 100644 --- a/build/asm/repackage.xml +++ b/build/asm/repackage.xml @@ -19,7 +19,7 @@ - + @@ -41,6 +41,7 @@ + diff --git a/build/build.iml b/build/build.iml index 9eb5b9dfb1fb..71b5f94898ed 100644 --- a/build/build.iml +++ b/build/build.iml @@ -13,7 +13,7 @@ - + diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 88f3bf933756..a673f8f7cd9d 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -171,11 +171,7 @@ libraryLicense(name: "Apache Commons Net", libraryName: "commons-net", version: libraryLicense(name: "Apache Lucene", libraryName: "lucene-core-2.4.1.jar", version: "2.4.1", license: "Apache 2.0", url: "http://lucene.apache.org/java") libraryLicense(name: "Apache Sanselan", libraryName: "Sanselan", version: "0.98", license: "Apache 2.0", url: "https://commons.apache.org/proper/commons-imaging/") libraryLicense(name: "Apache XML Graphics Commons", libraryName: "xmlgraphics-commons-1.3.1.jar", version: "1.3.1", license: "Apache 2.0", url: "http://xmlgraphics.apache.org/commons/", licenseUrl:"http://www.apache.org/licenses/LICENSE-2.0") -libraryLicense(name: "asm-4.0-all", libraryName: "asm-4.0-all", version: "4.0", attachedTo: "ByteCodeViewer", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") -libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm-tools", version: "4.0", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") -libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm", version: "3.3", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") -libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm4", version: "4.0", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") -libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm5", version: "5.0.3 (with patches by JetBrains)", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") +libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "ASM", version: "6.0-ALPHA (with patches by JetBrains)", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") libraryLicense(name: "assertJ", version: "3", license: "Apache 2.0", url: "https://github.com/joel-costigliola/assertj-core") libraryLicense(name: "Automaton", libraryName: "automaton.jar", version: "1.11", license: "BSD", url: "http://www.brics.dk/automaton/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php") libraryLicense(name: "Axis", libraryName: "axis-1.4", version: "1.4", license: "Apache 2.0", url: "http://ws.apache.org/axis/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.html") diff --git a/java/compiler/forms-compiler/forms-compiler.iml b/java/compiler/forms-compiler/forms-compiler.iml index 111123aaf886..9eec06a77713 100644 --- a/java/compiler/forms-compiler/forms-compiler.iml +++ b/java/compiler/forms-compiler/forms-compiler.iml @@ -10,7 +10,7 @@ - + diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index 481598a0c7ae..73e40393577b 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -16,7 +16,7 @@ - + diff --git a/java/compiler/instrumentation-util/instrumentation-util.iml b/java/compiler/instrumentation-util/instrumentation-util.iml index 293410b8d23a..eb96516e2f04 100644 --- a/java/compiler/instrumentation-util/instrumentation-util.iml +++ b/java/compiler/instrumentation-util/instrumentation-util.iml @@ -7,7 +7,6 @@ - + - - + \ No newline at end of file diff --git a/java/compiler/javac2/javac2.iml b/java/compiler/javac2/javac2.iml index 986d88e635fd..5376b3eff57f 100644 --- a/java/compiler/javac2/javac2.iml +++ b/java/compiler/javac2/javac2.iml @@ -10,7 +10,7 @@ - + @@ -165,5 +165,4 @@ - - + \ No newline at end of file diff --git a/java/java-analysis-impl/java-analysis-impl.iml b/java/java-analysis-impl/java-analysis-impl.iml index 95c129baadfb..8fd2b1787902 100644 --- a/java/java-analysis-impl/java-analysis-impl.iml +++ b/java/java-analysis-impl/java-analysis-impl.iml @@ -17,7 +17,6 @@ - + - - + \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java index 078e2fdff13d..d59741e42020 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/ModuleHighlightUtil.java @@ -29,7 +29,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaModule; -import com.intellij.psi.PsiJavaModuleReference; import com.intellij.psi.search.FilenameIndex; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,15 +36,15 @@ import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.Collections; -public class ModuleHighlightUtil { - private static final String MODULE_FILE_NAME = "module-info.java"; +import static com.intellij.psi.PsiJavaModule.MODULE_INFO_FILE; +public class ModuleHighlightUtil { @Nullable static HighlightInfo checkFileName(@NotNull PsiJavaModule element, @NotNull PsiFile file) { - if (!MODULE_FILE_NAME.equals(file.getName())) { + if (!MODULE_INFO_FILE.equals(file.getName())) { String message = JavaErrorMessages.message("module.file.wrong.name"); HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(element)).description(message).create(); - QuickFixAction.registerQuickFixAction(info, factory().createRenameFileFix(MODULE_FILE_NAME)); + QuickFixAction.registerQuickFixAction(info, factory().createRenameFileFix(MODULE_INFO_FILE)); return info; } @@ -60,7 +59,7 @@ public class ModuleHighlightUtil { Module module = ProjectFileIndex.SERVICE.getInstance(project).getModuleForFile(vFile); if (module != null) { Collection others = - FilenameIndex.getVirtualFilesByName(project, MODULE_FILE_NAME, new ModulesScope(Collections.singleton(module), project)); + FilenameIndex.getVirtualFilesByName(project, MODULE_INFO_FILE, new ModulesScope(Collections.singleton(module), project)); if (others.size() > 1) { String message = JavaErrorMessages.message("module.file.duplicate"); return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(element)).description(message).create(); @@ -93,7 +92,6 @@ public class ModuleHighlightUtil { } private static TextRange range(PsiJavaModule module) { - PsiJavaModuleReference name = module.getNameElement(); - return name != null ? new TextRange(module.getTextOffset(), name.getTextRange().getEndOffset()) : module.getTextRange(); + return new TextRange(module.getTextOffset(), module.getNameElement().getTextRange().getEndOffset()); } } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java index 9300b954c488..624659f1c90a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/JCiPUtil.java @@ -26,7 +26,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -class JCiPUtil { +public class JCiPUtil { static boolean isJCiPAnnotation(String ref) { return "Immutable".equals(ref) || "GuardedBy".equals(ref) || "ThreadSafe".equals(ref) || "NotThreadSafe".equals(ref); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java index d3bcce5c3671..e1aefce0e557 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/concurrencyAnnotations/NonFinalFieldInImmutableInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -59,7 +59,7 @@ public class NonFinalFieldInImmutableInspection extends BaseJavaBatchLocalInspec if (!JCiPUtil.isImmutable(containingClass)) { return; } - holder.registerProblem(field, "Non-final field #ref in @Immutable class #loc"); + holder.registerProblem(field.getNameIdentifier(), "Non-final field #ref in @Immutable class #loc"); } } }; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java index 36c8ea3485f6..198e462b1e77 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspectionBase.java @@ -92,7 +92,7 @@ public class UnusedDeclarationInspectionBase extends GlobalInspectionTool { List deadCodeAddIns = new ArrayList(extensions.length); for (EntryPoint entryPoint : extensions) { try { - deadCodeAddIns.add(entryPoint); + deadCodeAddIns.add(entryPoint.clone()); } catch (Exception e) { LOG.error(e); diff --git a/java/java-impl/java-impl.iml b/java/java-impl/java-impl.iml index 1be708c7149c..1f9fd8301eef 100644 --- a/java/java-impl/java-impl.iml +++ b/java/java-impl/java-impl.iml @@ -42,7 +42,7 @@ - + diff --git a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java index 974e9af8e9cb..3656ce32aba5 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiJavaModule.java @@ -15,7 +15,7 @@ */ package com.intellij.psi; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.NotNull; /** * Represents a Java module declaration. @@ -23,6 +23,9 @@ import org.jetbrains.annotations.Nullable; * @since 2016.3 */ public interface PsiJavaModule extends PsiElement { - @Nullable PsiJavaModuleReference getNameElement(); - @Nullable String getModuleName(); + String MODULE_INFO_CLASS = "module-info"; + String MODULE_INFO_FILE = MODULE_INFO_CLASS + ".java"; + + @NotNull PsiJavaModuleReference getNameElement(); + @NotNull String getModuleName(); } \ No newline at end of file diff --git a/java/java-psi-impl/java-psi-impl.iml b/java/java-psi-impl/java-psi-impl.iml index 40064b497c8b..3efdb8fa9616 100644 --- a/java/java-psi-impl/java-psi-impl.iml +++ b/java/java-psi-impl/java-psi-impl.iml @@ -11,7 +11,7 @@ - + \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java index 4905a52c18c4..fccb8b1202ad 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaModuleImpl.java @@ -15,29 +15,30 @@ */ package com.intellij.psi.impl.source; -import com.intellij.psi.*; +import com.intellij.psi.JavaElementVisitor; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiJavaModule; +import com.intellij.psi.PsiJavaModuleReference; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class PsiJavaModuleImpl extends CompositePsiElement implements PsiJavaModule { public PsiJavaModuleImpl() { super(JavaElementType.MODULE); } - @Nullable + @NotNull @Override public PsiJavaModuleReference getNameElement() { - return PsiTreeUtil.getChildOfType(this, PsiJavaModuleReference.class); + return PsiTreeUtil.getRequiredChildOfType(this, PsiJavaModuleReference.class); } - @Nullable + @NotNull @Override public String getModuleName() { - PsiJavaModuleReference nameElement = getNameElement(); - return nameElement != null ? nameElement.getReferenceText() : null; + return getNameElement().getReferenceText(); } @Override diff --git a/java/java-tests/java-tests.iml b/java/java-tests/java-tests.iml index b0496244a14f..1008e1276345 100644 --- a/java/java-tests/java-tests.iml +++ b/java/java-tests/java-tests.iml @@ -25,7 +25,7 @@ - + diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsStubBuilderTest.java similarity index 98% rename from java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.java rename to java/java-tests/testSrc/com/intellij/psi/ClsStubBuilderTest.java index 471f5e0ed630..d1d2f08d4559 100644 --- a/java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/ClsStubBuilderTest.java @@ -31,7 +31,7 @@ import java.io.File; /** * @author max */ -public class ClsBuilderTest extends LightIdeaTestCase { +public class ClsStubBuilderTest extends LightIdeaTestCase { public void testUtilList() { doTest("java/util/List.class"); } public void testNullable() { doTest("org/jetbrains/annotations/Nullable.class"); } public void testUtilCollections() { doTest("java/util/Collections.class"); } diff --git a/java/typeMigration/src/META-INF/TypeMigration.xml b/java/typeMigration/src/META-INF/TypeMigration.xml index c27c63eb1afc..46042d875b03 100644 --- a/java/typeMigration/src/META-INF/TypeMigration.xml +++ b/java/typeMigration/src/META-INF/TypeMigration.xml @@ -8,6 +8,7 @@ + diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java new file mode 100644 index 000000000000..27fe8801bec4 --- /dev/null +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/VoidConversionRule.java @@ -0,0 +1,84 @@ +/* + * 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.intellij.refactoring.typeMigration.rules; + +import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer; +import com.intellij.psi.*; +import com.intellij.psi.search.PsiElementProcessor; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase; +import com.intellij.refactoring.typeMigration.TypeEvaluator; +import com.intellij.refactoring.typeMigration.TypeMigrationLabeler; +import com.intellij.util.IncorrectOperationException; +import com.siyeh.ig.controlflow.UnnecessaryReturnInspection; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Dmitry Batkovich + */ +public class VoidConversionRule extends TypeConversionRule { + @Nullable + @Override + public TypeConversionDescriptorBase findConversion(PsiType from, + PsiType to, + PsiMember member, + PsiExpression context, + TypeMigrationLabeler labeler) { + if (PsiType.VOID.equals(to) && context.getParent() instanceof PsiReturnStatement) { + final boolean isPure = PsiTreeUtil.processElements(context, new PsiElementProcessor() { + @Override + public boolean execute(@NotNull PsiElement element) { + if (element instanceof PsiPrefixExpression) { + return analyzeUnaryExpressionOperand(((PsiPrefixExpression)element).getOperand()); + } + if (element instanceof PsiPostfixExpression) { + return analyzeUnaryExpressionOperand(((PsiPostfixExpression)element).getOperand()); + } + if (element instanceof PsiMethodCallExpression) { + final PsiMethod method = ((PsiMethodCallExpression)element).resolveMethod(); + return method != null && ControlFlowAnalyzer.isPure(method); + } + return true; + } + + private boolean analyzeUnaryExpressionOperand(PsiExpression operand) { + if (!(operand instanceof PsiReferenceExpression)) return false; + final PsiElement resolved = ((PsiReferenceExpression)operand).resolve(); + return !(resolved instanceof PsiField); + } + }); + if (isPure) { + return new TypeConversionDescriptorBase() { + @Override + public PsiExpression replace(PsiExpression expression, @NotNull TypeEvaluator evaluator) throws IncorrectOperationException { + final PsiElement parent = expression.getParent(); + if (parent instanceof PsiReturnStatement) { + expression.delete(); + if (UnnecessaryReturnInspection.isReturnRedundant((PsiReturnStatement)parent, false, null)) { + parent.delete(); + } + } + return null; + } + }; + } else { + return null; + } + } + return null; + } +} diff --git a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java index 2d999892902a..e91b68c1ff1d 100644 --- a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java +++ b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java @@ -826,6 +826,10 @@ public class TypeMigrationTest extends TypeMigrationTestBase { doTestFieldType("fooDontMigrateName", PsiType.BOOLEAN); } + public void testMethodMigrationToVoidWithUnusedReturns() { + doTestMethodType("toVoidMethod", PsiType.VOID); + } + public void testMigrationToSuper() { doTestFieldType("b", myJavaFacade.getElementFactory().createTypeFromText("Test.A", null)); } diff --git a/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/after/Test.items b/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/after/Test.items new file mode 100644 index 000000000000..af6da3191a83 --- /dev/null +++ b/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/after/Test.items @@ -0,0 +1,9 @@ +Types: +PsiMethod:toVoidMethod : void +PsiMethodCallExpression:toVoidMethod() : void + +Conversions: + +New expression type changes: +Fails: +"" + String.valueOf(999)->void diff --git a/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/after/test.java b/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/after/test.java new file mode 100644 index 000000000000..9a41034f67a0 --- /dev/null +++ b/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/after/test.java @@ -0,0 +1,11 @@ +class Test { + + public void toVoidMethod() { + int j = 0; + return "" + String.valueOf(999); + } + + public void main(String[] args) { + toVoidMethod(); + } +} diff --git a/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/before/test.java b/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/before/test.java new file mode 100644 index 000000000000..dc030e222267 --- /dev/null +++ b/java/typeMigration/testData/refactoring/typeMigration/methodMigrationToVoidWithUnusedReturns/before/test.java @@ -0,0 +1,11 @@ +class Test { + + public String toVoidMethod() { + int j = 0; + return "" + String.valueOf(999); + } + + public void main(String[] args) { + toVoidMethod(); + } +} diff --git a/jps/jps-builders/jps-builders.iml b/jps/jps-builders/jps-builders.iml index be7df797f0bb..f876b2a7e3cc 100644 --- a/jps/jps-builders/jps-builders.iml +++ b/jps/jps-builders/jps-builders.iml @@ -12,7 +12,7 @@ - + diff --git a/lib/asm-all.jar b/lib/asm-all.jar index b2f2849bae45..12f25c2c4220 100644 Binary files a/lib/asm-all.jar and b/lib/asm-all.jar differ diff --git a/lib/src/asm5-src.zip b/lib/src/asm-src.zip similarity index 57% rename from lib/src/asm5-src.zip rename to lib/src/asm-src.zip index ad405c1ca3e2..26dd8efc7fef 100644 Binary files a/lib/src/asm5-src.zip and b/lib/src/asm-src.zip differ diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java index 6c3216b019d8..4d5357597bee 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java @@ -722,7 +722,6 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren final HighlightDisplayKey key = HighlightDisplayKey.find(defaultToolWrapper.getShortName()); for (ScopeToolState state : myProvider.getTools(currentTools)) { InspectionToolWrapper toolWrapper = state.getTool(); - LOG.assertTrue(!ApplicationManager.getApplication().isReadAccessAllowed()); ReadAction.run(() -> { if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) { addTool(toolWrapper, diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java index 394c710de8eb..1735f08961d6 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/RefElementNode.java @@ -29,13 +29,14 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.MutableTreeNode; +import javax.swing.tree.TreeNode; /** * @author max */ public class RefElementNode extends SuppressableInspectionTreeNode { - private boolean myHasDescriptorsUnder = false; - private CommonProblemDescriptor mySingleDescriptor = null; + private volatile boolean myHasDescriptorsUnder; + private volatile CommonProblemDescriptor mySingleDescriptor; private final Icon myIcon; public RefElementNode(@Nullable RefEntity userObject, @NotNull InspectionToolPresentation presentation) { super(userObject, presentation); @@ -76,7 +77,6 @@ public class RefElementNode extends SuppressableInspectionTreeNode { @Override public void excludeElement(ExcludedInspectionTreeNodesManager excludedManager) { - myPresentation.ignoreCurrentElement(getElement()); super.excludeElement(excludedManager); } @@ -92,10 +92,14 @@ public class RefElementNode extends SuppressableInspectionTreeNode { @Override public void add(MutableTreeNode newChild) { + checkHasDescriptorUnder(newChild); super.add(newChild); - if (newChild instanceof ProblemDescriptionNode) { - myHasDescriptorsUnder = true; - } + } + + @Override + public InspectionTreeNode insertByOrder(InspectionTreeNode child, boolean allowDuplication) { + checkHasDescriptorUnder(child); + return super.insertByOrder(child, allowDuplication); } public void setProblem(@NotNull CommonProblemDescriptor descriptor) { @@ -142,4 +146,17 @@ public class RefElementNode extends SuppressableInspectionTreeNode { } return isLeaf() ? "" : null; } + + private void checkHasDescriptorUnder(MutableTreeNode newChild) { + if (myHasDescriptorsUnder) return; + if (newChild instanceof ProblemDescriptionNode || + newChild instanceof RefElementNode && ((RefElementNode)newChild).hasDescriptorsUnder()) { + myHasDescriptorsUnder = true; + TreeNode parent = getParent(); + while (parent instanceof RefElementNode) { + ((RefElementNode)parent).myHasDescriptorsUnder = true; + parent = parent.getParent(); + } + } + } } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java index 85deb8994189..68be8769956d 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java @@ -70,6 +70,8 @@ import java.io.File; import java.io.IOException; import java.util.*; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public abstract class InspectionToolsConfigurable extends BaseConfigurable implements ErrorsConfigurable, SearchableConfigurable, Configurable.NoScroll { @@ -78,7 +80,8 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable private static final String HEADER_TITLE = "Profile:"; private static final Logger LOG = Logger.getInstance(InspectionToolsConfigurable.class); - private static final String COPY_SUFFIX = "copy"; + private static final Pattern COPIED_PROFILE_SUFFIX_PATTERN = Pattern.compile("(.*\\s*copy)\\s*(\\d*)"); + protected final InspectionProfileManager myApplicationProfileManager; protected final InspectionProjectProfileManager myProjectProfileManager; private final CardLayout myLayout = new CardLayout(); @@ -115,15 +118,21 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable LOG.assertTrue(modifyLevel || modifyName); String profileDefaultName = selectedProfile.getName(); if (modifyName) { - if (!profileDefaultName.endsWith(COPY_SUFFIX)) { - profileDefaultName += " " + COPY_SUFFIX; + final Matcher matcher = COPIED_PROFILE_SUFFIX_PATTERN.matcher(profileDefaultName); + int nextIdx; + if (matcher.matches()) { + profileDefaultName = matcher.group(1); + nextIdx = matcher.group(2).isEmpty() ? 1 : Integer.valueOf(matcher.group(2)); + } + else { + profileDefaultName += " copy"; + nextIdx = 1; } if (hasName(profileDefaultName, modifyLevel != myPanels.get(selectedProfile).isProjectLevel())) { - int idx = 0; String currentProfileDefaultName; do { - idx++; - currentProfileDefaultName = profileDefaultName + " " + String.valueOf(idx); + currentProfileDefaultName = profileDefaultName + " " + String.valueOf(nextIdx); + nextIdx++; } while (hasName(currentProfileDefaultName, modifyLevel != myPanels.get(selectedProfile).isProjectLevel())); profileDefaultName = currentProfileDefaultName; diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiFileProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiFileProcessor.java index 678f3903b29d..527e33289838 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiFileProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenamePsiFileProcessor.java @@ -56,7 +56,7 @@ public class RenamePsiFileProcessor extends RenamePsiElementProcessor { return super.findReferences(element); } - protected static class PsiFileRenameDialog extends RenameWithOptionalReferencesDialog { + public static class PsiFileRenameDialog extends RenameWithOptionalReferencesDialog { public PsiFileRenameDialog(Project project, PsiElement element, PsiElement nameSuggestionContext, Editor editor) { super(project, element, nameSuggestionContext, editor); } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 1d3a8a7bc364..0be25906c1b2 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -2003,6 +2003,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { private UnindexedFilesFinder(@Nullable ProgressIndicator indicator) { myProgressIndicator = indicator; + if (!myInitialized) waitUntilIndicesAreInitialized(); } @NotNull diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java index 02f43bc8ba3b..d669a2b870f9 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexImpl.java @@ -163,7 +163,7 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn @Override public String getPackageNameByDirectory(@NotNull VirtualFile dir) { - LOG.assertTrue(dir.isDirectory(), dir.getPresentableUrl()); + if (!dir.isDirectory()) LOG.error(dir.getPresentableUrl()); return myDirectoryIndex.getPackageName(dir); } diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java index 3402920719ea..ea09f7f8bc66 100644 --- a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java +++ b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java @@ -34,6 +34,11 @@ public abstract class ServerType { @NotNull public abstract String getPresentableName(); + @NotNull + public String getHelpTopic() { + return "reference.settings.clouds"; + } + @NotNull public abstract Icon getIcon(); diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/SingleRemoteServerConfigurable.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/SingleRemoteServerConfigurable.java index 6031309cafd9..120db55c7726 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/SingleRemoteServerConfigurable.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/SingleRemoteServerConfigurable.java @@ -166,7 +166,7 @@ public class SingleRemoteServerConfigurable extends NamedConfigurable commands) { Collections.addAll(commands, String.valueOf(pid), String.valueOf(beforeRestart.length)); Collections.addAll(commands, beforeRestart); - Collections.addAll(commands, String.valueOf(argc.getValue())); + Collections.addAll(commands, String.valueOf(argv.length)); Collections.addAll(commands, argv); } }); @@ -147,11 +147,34 @@ public class Restarter { }); } + private static String[] getRestartArgv(String[] argv) { + int countArgs = argv.length; + for (int i = argv.length-1; i >=0; i--) { + if (argv[i].endsWith("com.intellij.idea.Main") || + argv[i].endsWith(".exe")) { + countArgs = i + 1; + if ("0".equals(argv[2])) { + // update number of args in according with removed cmd line args + argv[3] = String.valueOf(Integer.valueOf(argv[3]) - (argv.length - (i+1))); + } + if (argv[i].endsWith(".exe") && argv[i].indexOf(File.separator) < 0) { + //absolute path + argv[i] = new File(PathManager.getBinPath(), argv[i]).getPath(); + } + break; + } + } + String[] restartArg = new String[countArgs]; + System.arraycopy(argv, 0, restartArg, 0, countArgs); + return restartArg; + } + private static void doScheduleRestart(File restarterFile, Consumer> argumentsBuilder) throws IOException { List commands = new ArrayList(); commands.add(createTempExecutable(restarterFile).getPath()); argumentsBuilder.consume(commands); - Runtime.getRuntime().exec(ArrayUtil.toStringArray(commands)); + String[] argv = getRestartArgv(ArrayUtil.toStringArray(commands)); + Runtime.getRuntime().exec(argv); } public static String getRestarterDir() { diff --git a/plugins/ByteCodeViewer/ByteCodeViewer.iml b/plugins/ByteCodeViewer/ByteCodeViewer.iml index 022e24d30dc9..ecf022c8422d 100644 --- a/plugins/ByteCodeViewer/ByteCodeViewer.iml +++ b/plugins/ByteCodeViewer/ByteCodeViewer.iml @@ -7,7 +7,7 @@ - + @@ -19,5 +19,4 @@ - - + \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java index 5a91e861441a..193be4ee448f 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryReturnInspection.java @@ -16,6 +16,7 @@ package com.siyeh.ig.controlflow; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.util.FileTypeUtils; import com.intellij.psi.util.PsiTreeUtil; @@ -26,6 +27,7 @@ import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.fixes.DeleteUnnecessaryStatementFix; import com.siyeh.ig.psiutils.ControlFlowUtils; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -85,48 +87,59 @@ public class UnnecessaryReturnInspection extends BaseInspection { @Override public void visitReturnStatement(@NotNull PsiReturnStatement statement) { super.visitReturnStatement(statement); - if (statement.getReturnValue() != null) { - return; + final Ref constructorRef = Ref.create(); + if (isReturnRedundant(statement, ignoreInThenBranch, constructorRef)) { + registerStatementError(statement, constructorRef.get()); } - final PsiElement methodParent = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class); - PsiCodeBlock codeBlock = null; - final boolean constructor; - if (methodParent instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)methodParent; - codeBlock = method.getBody(); - constructor = method.isConstructor(); - } - else if (methodParent instanceof PsiLambdaExpression) { - constructor = false; - final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)methodParent; - final PsiElement lambdaBody = lambdaExpression.getBody(); - if (lambdaBody instanceof PsiCodeBlock) { - codeBlock = (PsiCodeBlock)lambdaBody; - } - } - else { - return; - } - if (codeBlock == null) { - return; - } - if (!ControlFlowUtils.blockCompletesWithStatement(codeBlock, statement)) { - return; - } - if (ignoreInThenBranch && isInThenBranch(statement)) { - return; - } - registerStatementError(statement, Boolean.valueOf(constructor)); } - private boolean isInThenBranch(PsiStatement statement) { - final PsiIfStatement ifStatement = - PsiTreeUtil.getParentOfType(statement, PsiIfStatement.class, true, PsiMethod.class, PsiLambdaExpression.class); - if (ifStatement == null) { - return false; - } - final PsiStatement elseBranch = ifStatement.getElseBranch(); - return elseBranch != null && !PsiTreeUtil.isAncestor(elseBranch, statement, true); + } + + public static boolean isReturnRedundant(@NotNull PsiReturnStatement statement, + boolean ignoreInThenBranch, + @Nullable Ref isInConstructorRef) { + if (statement.getReturnValue() != null) { + return false; } + final PsiElement methodParent = PsiTreeUtil.getParentOfType(statement, PsiMethod.class, PsiLambdaExpression.class); + PsiCodeBlock codeBlock = null; + if (methodParent instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)methodParent; + codeBlock = method.getBody(); + if (isInConstructorRef != null) { + isInConstructorRef.set(method.isConstructor()); + } + } + else if (methodParent instanceof PsiLambdaExpression) { + isInConstructorRef.set(false); + final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)methodParent; + final PsiElement lambdaBody = lambdaExpression.getBody(); + if (lambdaBody instanceof PsiCodeBlock) { + codeBlock = (PsiCodeBlock)lambdaBody; + } + } + else { + return false; + } + if (codeBlock == null) { + return false; + } + if (!ControlFlowUtils.blockCompletesWithStatement(codeBlock, statement)) { + return false; + } + if (ignoreInThenBranch && isInThenBranch(statement)) { + return false; + } + return true; + } + + private static boolean isInThenBranch(PsiStatement statement) { + final PsiIfStatement ifStatement = + PsiTreeUtil.getParentOfType(statement, PsiIfStatement.class, true, PsiMethod.class, PsiLambdaExpression.class); + if (ifStatement == null) { + return false; + } + final PsiStatement elseBranch = ifStatement.getElseBranch(); + return elseBranch != null && !PsiTreeUtil.isAncestor(elseBranch, statement, true); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java index 960460d28c93..abaa5582e5ed 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/TooBroadScopeInspectionBase.java @@ -20,6 +20,8 @@ import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.psi.*; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.FileTypeUtils; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.Query; @@ -27,7 +29,6 @@ import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.psiutils.*; -import com.intellij.psi.util.FileTypeUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -81,6 +82,15 @@ public class TooBroadScopeInspectionBase extends BaseInspection { if (PsiUtil.isConstantExpression(expression) || ExpressionUtils.isNullLiteral(expression)) { return true; } + if (expression instanceof PsiArrayInitializerExpression) { + final PsiArrayInitializerExpression arrayInitializerExpression = (PsiArrayInitializerExpression)expression; + for (PsiExpression initializer : arrayInitializerExpression.getInitializers()) { + if (!isMoveable(initializer)) { + return false; + } + } + return true; + } if (expression instanceof PsiNewExpression) { final PsiNewExpression newExpression = (PsiNewExpression)expression; final PsiExpression[] arrayDimensions = newExpression.getArrayDimensions(); @@ -93,32 +103,35 @@ public class TooBroadScopeInspectionBase extends BaseInspection { return true; } final PsiArrayInitializerExpression arrayInitializer = newExpression.getArrayInitializer(); - boolean result = true; if (arrayInitializer != null) { final PsiExpression[] initializers = arrayInitializer.getInitializers(); for (final PsiExpression initializerExpression : initializers) { - result &= isMoveable(initializerExpression); + if (!isMoveable(initializerExpression)) { + return false; + } } + return true; } final PsiType type = newExpression.getType(); if (type == null) { return false; } else if (!m_allowConstructorAsInitializer) { - // constructors located in library packages probably have no non-local side effects - if (!ClassUtils.isImmutable(type) && !LibraryUtil.isTypeInLibrary(type)) { + if (!isAllowedType(type)) { return false; } } final PsiExpressionList argumentList = newExpression.getArgumentList(); if (argumentList == null) { - return result; + return false; } final PsiExpression[] expressions = argumentList.getExpressions(); for (final PsiExpression argumentExpression : expressions) { - result &= isMoveable(argumentExpression); + if (!isMoveable(argumentExpression)) { + return false; + } } - return result; + return true; } if (expression instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression; @@ -147,10 +160,12 @@ public class TooBroadScopeInspectionBase extends BaseInspection { return true; } if (expression instanceof PsiMethodCallExpression) { - // methods located in library packages probably have no non-local side effects + if (!isAllowedType(expression.getType())) { + return false; + } final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression; final PsiMethod method = methodCallExpression.resolveMethod(); - if (!(method instanceof PsiCompiledElement)) { + if (!isAllowedMethod(method)) { return false; } final PsiExpressionList argumentList = methodCallExpression.getArgumentList(); @@ -164,6 +179,43 @@ public class TooBroadScopeInspectionBase extends BaseInspection { return false; } + private static boolean isAllowedMethod(PsiMethod method) { + if (method == null) { + return false; + } + final PsiClass aClass = method.getContainingClass(); + if (aClass == null) { + return false; + } + final String qualifiedName = aClass.getQualifiedName(); + if (qualifiedName == null || !qualifiedName.startsWith("java.")) { + return false; + } + final String methodName = method.getName(); + return !"now".equals(methodName) && !"currentTimeMillis".equals(methodName) && !"nanoTime".equals(methodName); + } + + private static boolean isAllowedType(PsiType type) { + if (ClassUtils.isImmutable(type)) { + return true; + } + if (!(type instanceof PsiClassType)) { + return false; + } + final PsiClassType classType = (PsiClassType)type; + final PsiClass aClass = classType.resolve(); + return isAllowedClass(aClass); + } + + private static boolean isAllowedClass(@Nullable PsiClass aClass) { + // allow some "safe" jdk types + if (InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_COLLECTION) || + InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_MAP)) { + return true; + } + return aClass != null && aClass.isEnum(); + } + @Override public BaseInspectionVisitor buildVisitor() { return new TooBroadScopeVisitor(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java index 0ded3aae25b1..a361fd33eb93 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2014 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2016 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.siyeh.ig.psiutils; +import com.intellij.codeInspection.concurrencyAnnotations.JCiPUtil; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.TypeConversionUtil; @@ -68,14 +69,22 @@ public class ClassUtils { immutableTypes.add(CommonClassNames.JAVA_LANG_BYTE); immutableTypes.add(CommonClassNames.JAVA_LANG_STRING); immutableTypes.add("java.awt.Font"); + immutableTypes.add("java.awt.BasicStroke"); immutableTypes.add("java.awt.Color"); + immutableTypes.add("java.awt.Cursor"); immutableTypes.add("java.math.BigDecimal"); immutableTypes.add("java.math.BigInteger"); immutableTypes.add("java.math.MathContext"); immutableTypes.add("java.nio.channels.FileLock"); immutableTypes.add("java.nio.charset.Charset"); immutableTypes.add("java.io.File"); + immutableTypes.add("java.net.Inet4Address"); + immutableTypes.add("java.net.Inet6Address"); + immutableTypes.add("java.net.InetSocketAddress"); immutableTypes.add("java.net.URI"); + immutableTypes.add("java.net.URL"); + immutableTypes.add("java.util.Locale"); + immutableTypes.add("java.util.UUID"); immutableTypes.add("java.util.regex.Pattern"); } @@ -107,8 +116,14 @@ public class ClassUtils { return false; } final PsiClassType classType = (PsiClassType)type; - final String className = classType.getCanonicalText(); - return immutableTypes.contains(className); + final PsiClass aClass = classType.resolve(); + if (aClass == null) { + return false; + } + if (immutableTypes.contains(aClass.getQualifiedName())) { + return true; + } + return JCiPUtil.isImmutable(aClass); } public static boolean inSamePackage(@Nullable PsiElement element1, diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/scope/TooBroadScope.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/scope/TooBroadScope.java index 44ffdf41a6e5..6b45d6f66368 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/scope/TooBroadScope.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/scope/TooBroadScope.java @@ -150,6 +150,7 @@ public class TooBroadScope } private final String[] EMPTY = {}; + private final String[] ONE = {"one"}; void abc() { String[] strings = EMPTY; System.out.println(); @@ -160,5 +161,41 @@ public class TooBroadScope System.out.println(); System.out.println(); System.out.println(list); + + String[] ss = new String[10]; + System.out.println(); + System.out.println(); + System.out.println(ss); + + String[] ss2 = new String[] {""}; + System.out.println(); + System.out.println(); + System.out.println(ss2); + + String[] ss3 = {}; + System.out.println(); + System.out.println(); + System.out.println(ss3); + + String[] ss3a = {ONE[0]}; + backgroundAction(); + System.out.println(); + System.out.println(ss3a); + + List ss4 = Arrays.asList(ONE); + backgroundAction(); + System.out.println(); + System.out.println(ss4); + } + + void backgroundAction() { + ONE[0] = "two"; + } + + void time() { + long start = System.currentTimeMillis(); + System.out.println(); + long end = System.currentTimeMillis(); + System.out.println("elapsed: " + (end - start)); } } \ No newline at end of file diff --git a/plugins/IntelliLang/IntelliLang-java.iml b/plugins/IntelliLang/IntelliLang-java.iml index 585a1f6d5a17..66a00fa603db 100644 --- a/plugins/IntelliLang/IntelliLang-java.iml +++ b/plugins/IntelliLang/IntelliLang-java.iml @@ -11,7 +11,7 @@ - + @@ -22,5 +22,4 @@ - - + \ No newline at end of file diff --git a/plugins/IntelliLang/IntelliLang-xml.iml b/plugins/IntelliLang/IntelliLang-xml.iml index 20db7d65ff08..1659417efc9d 100644 --- a/plugins/IntelliLang/IntelliLang-xml.iml +++ b/plugins/IntelliLang/IntelliLang-xml.iml @@ -10,7 +10,7 @@ - + @@ -22,5 +22,4 @@ - - + \ No newline at end of file diff --git a/plugins/coverage-common/coverage-common.iml b/plugins/coverage-common/coverage-common.iml index 0ce232bc7b7f..08567374ed2d 100644 --- a/plugins/coverage-common/coverage-common.iml +++ b/plugins/coverage-common/coverage-common.iml @@ -12,7 +12,7 @@ - + diff --git a/plugins/ui-designer/ui-designer.iml b/plugins/ui-designer/ui-designer.iml index e6a868e99465..eca27c766b69 100644 --- a/plugins/ui-designer/ui-designer.iml +++ b/plugins/ui-designer/ui-designer.iml @@ -19,7 +19,7 @@ - + @@ -35,5 +35,4 @@ - - + \ No newline at end of file diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py index c9078e14457d..bbc37965ec58 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py @@ -189,10 +189,13 @@ class BaseInterpreterInterface: return self.need_more_for_code(self.buffer.text) - def create_std_in(self): - return StdIn(self, self.host, self.client_port) + def create_std_in(self, debugger=None, original_std_in=None): + if debugger is None: + return StdIn(self, self.host, self.client_port) + else: + return DebugConsoleStdIn(dbg=debugger, original_stdin=original_std_in) - def add_exec(self, code_fragment): + def add_exec(self, code_fragment, debugger=None): original_in = sys.stdin try: help = None @@ -210,7 +213,7 @@ class BaseInterpreterInterface: more = False try: - sys.stdin = self.create_std_in() + sys.stdin = self.create_std_in(debugger, original_in) try: if help is not None: #This will enable the help() function to work. diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py index ec0c13d692b5..85d3267e9c73 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py @@ -1331,7 +1331,7 @@ class InternalConsoleExec(InternalThreadCommand): #don't trace new threads created by console command disable_trace_thread_modules() - result = pydevconsole.console_exec(self.thread_id, self.frame_id, self.expression) + result = pydevconsole.console_exec(self.thread_id, self.frame_id, self.expression, dbg) xml = "" xml += pydevd_vars.var_to_xml(result, "") xml += "" diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py index 2ef4df593fb6..5beab3126b80 100644 --- a/python/helpers/pydev/pydevconsole.py +++ b/python/helpers/pydev/pydevconsole.py @@ -374,7 +374,7 @@ def get_completions(text, token, globals, locals): # Debugger integration #=============================================================================== -def exec_code(code, globals, locals): +def exec_code(code, globals, locals, debugger): interpreterInterface = get_interpreter() interpreterInterface.interpreter.update(globals, locals) @@ -383,7 +383,7 @@ def exec_code(code, globals, locals): if res: return True - interpreterInterface.add_exec(code) + interpreterInterface.add_exec(code, debugger) return False @@ -443,7 +443,7 @@ class ConsoleWriter(InteractiveInterpreter): tblist = tb = None sys.stderr.write(''.join(lines)) -def console_exec(thread_id, frame_id, expression): +def console_exec(thread_id, frame_id, expression, dbg): """returns 'False' in case expression is partially correct """ frame = pydevd_vars.find_frame(thread_id, frame_id) @@ -458,7 +458,7 @@ def console_exec(thread_id, frame_id, expression): updated_globals.update(frame.f_locals) #locals later because it has precedence over the actual globals if IPYTHON: - need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals) + need_more = exec_code(CodeFragment(expression), updated_globals, frame.f_locals, dbg) if not need_more: pydevd_save_locals.save_locals(frame) return need_more diff --git a/python/helpers/tools/versions.xml b/python/helpers/tools/versions.xml index a89ba6e8d570..4c6bc1e9306d 100644 --- a/python/helpers/tools/versions.xml +++ b/python/helpers/tools/versions.xml @@ -112,7 +112,6 @@ bsddb.test.test_sequence build_class builtins - bz2 cProfile collections collections.__main__ @@ -859,7 +858,6 @@ bsddb.test.test_sequence build_class builtins - bz2 cProfile collections.__main__ collections.abc @@ -1548,7 +1546,6 @@ bsddb.test.test_replication build_class builtins - bz2 collections.__main__ collections.abc concurrent @@ -2128,7 +2125,6 @@ bsddb.test.test_fileid build_class builtins - bz2 collections.__main__ collections.abc concurrent @@ -2541,7 +2537,6 @@ bsddb.test.test_env_close build_class builtins - bz2 collections.__main__ collections.abc concurrent @@ -2941,7 +2936,6 @@ bsddb.test.test_replication bsddb.test.test_sequence bsddb.test.test_thread - bz2 cPickle cStringIO collections.__main__ @@ -3480,7 +3474,6 @@ bsddb.test.test_sequence bsddb.test.test_thread build_class - bz2 cPickle cStringIO collections.__main__ @@ -3926,7 +3919,6 @@ bsddb.test.test_sequence bsddb.test.test_thread build_class - bz2 cPickle cStringIO collections.__main__ @@ -4232,7 +4224,6 @@ _abcoll _bootlocale _bytesio - _bz2 _collections_abc _compression _fileio @@ -4597,7 +4588,6 @@ __main__ _abcoll _bytesio - _bz2 _compression _fileio _hotshot diff --git a/python/psi-api/src/com/jetbrains/python/PyNames.java b/python/psi-api/src/com/jetbrains/python/PyNames.java index 4b55f49acdb0..174db221d0c5 100644 --- a/python/psi-api/src/com/jetbrains/python/PyNames.java +++ b/python/psi-api/src/com/jetbrains/python/PyNames.java @@ -165,6 +165,7 @@ public class PyNames { public static final String DIV = "__div__"; public static final String TRUEDIV = "__truediv__"; public static final String AITER = "__aiter__"; + public static final String SIZEOF = "__sizeof__"; public static final String NAME = "__name__"; public static final String ENTER = "__enter__"; diff --git a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java index 8dba1d02da9b..46f07970447a 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java +++ b/python/psi-api/src/com/jetbrains/python/psi/impl/PyPsiUtils.java @@ -19,7 +19,6 @@ import com.google.common.base.Preconditions; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; @@ -604,6 +603,14 @@ public class PyPsiUtils { Preconditions.checkArgument(!module.isDisposed(), String.format("Module %s is disposed", module)); } + @NotNull + public static PsiFileSystemItem getFileSystemItem(@NotNull PsiElement element) { + if (element instanceof PsiFileSystemItem) { + return (PsiFileSystemItem)element; + } + return element.getContainingFile(); + } + private static abstract class TopLevelVisitor extends PyRecursiveElementVisitor { public void visitPyElement(final PyElement node) { super.visitPyElement(node); diff --git a/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java b/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java index e998ab07678a..02b95124f3dd 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java +++ b/python/src/com/jetbrains/python/codeInsight/imports/ImportFromExistingAction.java @@ -19,6 +19,7 @@ import com.intellij.codeInsight.hint.QuestionAction; import com.intellij.ide.DataManager; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.editor.colors.EditorColorsManager; @@ -28,7 +29,10 @@ import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.util.QualifiedName; import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; @@ -98,10 +102,12 @@ public class ImportFromExistingAction implements QuestionAction { return false; } // act - if (mySources.size() > 1) { + if (mySources.size() == 1 || ApplicationManager.getApplication().isUnitTestMode()) { + doWriteAction(mySources.get(0)); + } + else { selectSourceAndDo(); } - else doWriteAction(mySources.get(0)); return true; } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index b1e2ffe071d5..0fc1b2017a35 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -15,11 +15,11 @@ */ package com.jetbrains.python.packaging; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.execution.ExecutionException; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; @@ -50,9 +50,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import java.util.stream.Stream; -import java.util.concurrent.atomic.AtomicBoolean; /** * @author vlan @@ -314,8 +314,7 @@ public class PyPackageUtil { } manager.refreshAndGetPackages(true); } - catch (ExecutionException e) { - LOG.warn(e); + catch (ExecutionException ignored) { } finally { isUpdating.set(false); diff --git a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java index 7a69028df556..e408dae3ba34 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java +++ b/python/src/com/jetbrains/python/psi/impl/PyBuiltinCache.java @@ -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. @@ -371,6 +371,11 @@ public class PyBuiltinCache { return getObjectType("staticmethod"); } + @Nullable + public PyClassType getTypeType() { + return getObjectType("type"); + } + /** * @param target an element to check. * @return true iff target is inside the __builtins__.py diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java index c28e78734eae..ecdaa5164f10 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -240,6 +240,27 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference } } + // resolve implicit __class__ inside class function + if (myElement instanceof PyReferenceExpression && + PyNames.__CLASS__.equals(referencedName) && + LanguageLevel.forElement(myElement).isAtLeast(LanguageLevel.PYTHON30)) { + final PyFunction containingFunction = PsiTreeUtil.getParentOfType(myElement, PyFunction.class); + + if (containingFunction != null) { + final PyClass containingClass = containingFunction.getContainingClass(); + + if (containingClass != null) { + final PyResolveProcessor processor = new PyResolveProcessor(referencedName); + PyResolveUtil.scopeCrawlUp(processor, myElement, referencedName, containingFunction); + + if (processor.getElements().isEmpty()) { + ret.add(new RatedResolveResult(RatedResolveResult.RATE_NORMAL, containingClass)); + return ret; + } + } + } + } + // here we have an unqualified expr. it may be defined: // ...in current file final PyResolveProcessor processor = new PyResolveProcessor(referencedName); @@ -247,9 +268,24 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference // Use real context here to enable correct completion and resolve in case of PyExpressionCodeFragment final PsiElement realContext = PyPsiUtils.getRealContext(myElement); - PsiElement roof = findResolveRoof(referencedName, realContext); + final PsiElement roof = findResolveRoof(referencedName, realContext); PyResolveUtil.scopeCrawlUp(processor, myElement, referencedName, roof); - return getResultsFromProcessor(referencedName, processor, realContext, roof); + + final List resultsFromProcessor = getResultsFromProcessor(referencedName, processor, realContext, roof); + + // resolve to module __doc__ + if (resultsFromProcessor.isEmpty() && referencedName.equals(PyNames.DOC)) { + ret.addAll( + Optional + .ofNullable(PyBuiltinCache.getInstance(myElement).getObjectType()) + .map(type -> type.resolveMember(referencedName, myElement, AccessDirection.of(myElement), myContext)) + .orElse(Collections.emptyList()) + ); + + return ret; + } + + return resultsFromProcessor; } protected List getResultsFromProcessor(@NotNull String referencedName, diff --git a/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java b/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java index e87c189f361f..04029133f240 100644 --- a/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java +++ b/python/src/com/jetbrains/python/psi/resolve/QualifiedNameFinder.java @@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.util.QualifiedName; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; @@ -30,7 +31,6 @@ import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyFunction; -import com.intellij.psi.util.QualifiedName; import com.jetbrains.python.psi.impl.PyBuiltinCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -85,13 +85,7 @@ public class QualifiedNameFinder { @Nullable private static QualifiedName shortestQName(@NotNull List qNames) { - QualifiedName result = null; - for (QualifiedName name : qNames) { - if (result == null || name.getComponentCount() < result.getComponentCount()) { - result = name; - } - } - return result; + return qNames.stream().min((o1, o2) -> o1.getComponentCount() - o2.getComponentCount()).orElse(null); } @Nullable @@ -142,8 +136,13 @@ public class QualifiedNameFinder { if (initPy == null) { break; } - if (initPy instanceof PyFile && toplevel.equals(((PyFile)initPy).getElementNamed(((PsiNamedElement)toplevel).getName()))) { - virtualFile = dir.getVirtualFile(); + if (initPy instanceof PyFile) { + //noinspection ConstantConditions + final List resolved = ((PyFile)initPy).multiResolveName(((PsiNamedElement)toplevel).getName()); + final PsiElement finalTopLevel = toplevel; + if (resolved.stream().anyMatch(r -> r.getElement() == finalTopLevel)) { + virtualFile = dir.getVirtualFile(); + } } dir = dir.getParentDirectory(); } diff --git a/python/src/com/jetbrains/python/psi/resolve/QualifiedNameResolverImpl.java b/python/src/com/jetbrains/python/psi/resolve/QualifiedNameResolverImpl.java index 5592b58c61c5..58b594e264a1 100644 --- a/python/src/com/jetbrains/python/psi/resolve/QualifiedNameResolverImpl.java +++ b/python/src/com/jetbrains/python/psi/resolve/QualifiedNameResolverImpl.java @@ -28,15 +28,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDirectory; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil; import com.jetbrains.python.console.PydevConsoleRunner; import com.jetbrains.python.facet.PythonPathContributingFacet; +import com.jetbrains.python.psi.LanguageLevel; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyUtil; import com.jetbrains.python.psi.impl.PyBuiltinCache; @@ -44,6 +42,7 @@ import com.jetbrains.python.psi.impl.PyImportResolver; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,6 +51,8 @@ import java.util.Collections; import java.util.List; import java.util.Set; +import static com.jetbrains.python.psi.PyUtil.as; + /** * Resolves the specified qualified name in the specified context (module, all modules or a file) to a file or directory. * @@ -235,6 +236,7 @@ public class QualifiedNameResolverImpl implements RootVisitor, QualifiedNameReso final PsiFile footholdFile = myContext.getFootholdFile(); checkValidForTests(footholdFile); + boolean foundRelativeImport = false; if (myRelativeLevel >= 0 && footholdFile != null && !PyUserSkeletonsUtil.isUnderUserSkeletonsDirectory(footholdFile)) { PsiDirectory dir = footholdFile.getContainingDirectory(); checkValidForTests(dir); @@ -246,12 +248,13 @@ public class QualifiedNameResolverImpl implements RootVisitor, QualifiedNameReso PsiElement module = resolveModuleAt(dir); checkValidForTests(module); if (module != null) { + foundRelativeImport = isRelativeImportResult(dir, module); addRoot(module, true); } } final PythonPathCache cache = findMyCache(); - final boolean mayCache = cache != null && !myWithoutRoots && !myWithoutForeign; + final boolean mayCache = cache != null && !myWithoutRoots && !myWithoutForeign && !foundRelativeImport; if (mayCache) { final List cachedResults = cache.get(myQualifiedName); if (cachedResults != null) { @@ -293,6 +296,22 @@ public class QualifiedNameResolverImpl implements RootVisitor, QualifiedNameReso return results; } + + private boolean isRelativeImportResult(@NotNull PsiDirectory rootDirectory, @NotNull PsiElement result) { + if (myRelativeLevel > 0) { + return true; + } + final boolean isPython2 = LanguageLevel.forElement(rootDirectory).isOlderThan(LanguageLevel.PYTHON30); + if (myRelativeLevel == 0 && isPython2 && PyUtil.isPackage(rootDirectory, false, null)) { + // Candidate for implicit relative import doesn't necessarily means that the same module cannot be imported absolutely + final PsiFileSystemItem moduleOrPackage = as(result, PsiFileSystemItem.class); + if (moduleOrPackage != null && !myQualifiedName.equals(QualifiedNameFinder.findShortestImportableQName(moduleOrPackage))) { + return true; + } + } + return false; + } + /** * Resolve relative imports from sdk root to the skeleton dir */ @@ -421,6 +440,7 @@ public class QualifiedNameResolverImpl implements RootVisitor, QualifiedNameReso * * @param directory where to start from; top qualifier will be searched for here. */ + @Contract("null -> null") @Nullable public PsiElement resolveModuleAt(@Nullable PsiDirectory directory) { // prerequisites diff --git a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java index 3660c809f15f..2c1c75042b59 100644 --- a/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java +++ b/python/src/com/jetbrains/python/psi/types/PyClassTypeImpl.java @@ -195,10 +195,22 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { } classMember = resolveClassMember(myClass, myIsDefinition, name, location); + + if (PyNames.__CLASS__.equals(name)) { + return resolveDunderClass(context, classMember); + } + if (classMember != null) { return ResolveResultList.to(classMember); } + if (PyNames.DOC.equals(name)) { + return Optional + .ofNullable(PyBuiltinCache.getInstance(myClass).getObjectType()) + .map(type -> type.resolveMember(name, location, direction, resolveContext)) + .orElse(Collections.emptyList()); + } + classMember = resolveByOverridingAncestorsMembersProviders(this, name, location); if (classMember != null) { final ResolveResultList list = new ResolveResultList(); @@ -293,6 +305,36 @@ public class PyClassTypeImpl extends UserDataHolderBase implements PyClassType { return resultRef; } + @Nullable + private List resolveDunderClass(@NotNull TypeEvalContext context, @Nullable PsiElement classMember) { + final boolean newStyleClass = myClass.isNewStyleClass(context); + + if (!myIsDefinition) { + if (newStyleClass && classMember != null) { + return ResolveResultList.to(classMember); + } + + return ResolveResultList.to( + myClass.getAncestorClasses(context) + .stream() + .filter(cls -> !PyUtil.isObjectClass(cls)) + .map(cls -> cls.findClassAttribute(PyNames.__CLASS__, true, context)) + .filter(target -> target != null) + .findFirst() + .orElse(myClass) + ); + } + + if (LanguageLevel.forElement(myClass).isOlderThan(LanguageLevel.PYTHON30) && !newStyleClass) { + return ResolveResultList.to(classMember); + } + + return Optional + .ofNullable(PyBuiltinCache.getInstance(myClass).getTypeType()) + .map(typeType -> ResolveResultList.to(typeType.getPyClass())) + .orElse(null); + } + @Nullable @Override public PyClassLikeType getMetaClassType(@NotNull final TypeEvalContext context, boolean inherited) { diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java index e593af40baa9..edca9e70620f 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java @@ -133,6 +133,7 @@ public class PythonSdkUpdater implements StartupActivity { return true; } + @SuppressWarnings("ThrowableInstanceNeverThrown") final Throwable methodCallStacktrace = new Throwable(); application.invokeLater(() -> { synchronized (ourLock) { if (!ourScheduledToRefresh.contains(homePath)) { @@ -165,6 +166,7 @@ public class PythonSdkUpdater implements StartupActivity { PyPackageManager.getInstance(sdk12).refreshAndGetPackages(true); } catch (ExecutionException e) { + e.initCause(methodCallStacktrace); LOG.warn(e); } } diff --git a/python/testData/inspections/PyCompatibilityInspection/bz2Module.py b/python/testData/inspections/PyCompatibilityInspection/bz2Module.py new file mode 100644 index 000000000000..b4e4ac25b00a --- /dev/null +++ b/python/testData/inspections/PyCompatibilityInspection/bz2Module.py @@ -0,0 +1 @@ +from bz2 import BZ2File \ No newline at end of file diff --git a/python/testData/inspections/PyCompatibilityInspection/underscoreBz2Module.py b/python/testData/inspections/PyCompatibilityInspection/underscoreBz2Module.py new file mode 100644 index 000000000000..8ae8a0c2ad87 --- /dev/null +++ b/python/testData/inspections/PyCompatibilityInspection/underscoreBz2Module.py @@ -0,0 +1 @@ +import _bz2 \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection/dunderClass.py b/python/testData/inspections/PyUnresolvedReferencesInspection/dunderClass.py new file mode 100644 index 000000000000..293405bd59bd --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection/dunderClass.py @@ -0,0 +1,3 @@ +class A: + def foo(self): + return __class__ \ No newline at end of file diff --git a/python/testData/inspections/PyUnresolvedReferencesInspection3K/dunderClass.py b/python/testData/inspections/PyUnresolvedReferencesInspection3K/dunderClass.py new file mode 100644 index 000000000000..82edcc21ab81 --- /dev/null +++ b/python/testData/inspections/PyUnresolvedReferencesInspection3K/dunderClass.py @@ -0,0 +1,3 @@ +class A: + def foo(self): + return __class__ \ No newline at end of file diff --git a/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/bar/__init__.py b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/bar/__init__.py new file mode 100644 index 000000000000..3fdf6be7ca9b --- /dev/null +++ b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/bar/__init__.py @@ -0,0 +1 @@ +from mod import MyClass \ No newline at end of file diff --git a/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/bar/mod.py b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/bar/mod.py new file mode 100644 index 000000000000..6f75e663c7a6 --- /dev/null +++ b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/bar/mod.py @@ -0,0 +1,2 @@ +class MyClass(object): + pass \ No newline at end of file diff --git a/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/foo/__init__.py b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/foo/__init__.py new file mode 100644 index 000000000000..3fdf6be7ca9b --- /dev/null +++ b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/foo/__init__.py @@ -0,0 +1 @@ +from mod import MyClass \ No newline at end of file diff --git a/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/foo/mod.py b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/foo/mod.py new file mode 100644 index 000000000000..6f75e663c7a6 --- /dev/null +++ b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/foo/mod.py @@ -0,0 +1,2 @@ +class MyClass(object): + pass \ No newline at end of file diff --git a/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/main.py b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/main.py new file mode 100644 index 000000000000..3d0c10c7fceb --- /dev/null +++ b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/main.py @@ -0,0 +1 @@ +MyClass() \ No newline at end of file diff --git a/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/main_after.py b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/main_after.py new file mode 100644 index 000000000000..8683c5a7c50e --- /dev/null +++ b/python/testData/quickFixes/AddImportQuickFixTest/canonicalNamesFromHigherLevelPackage/main_after.py @@ -0,0 +1,3 @@ +from foo import MyClass + +MyClass() \ No newline at end of file diff --git a/python/testData/resolve/ClassAttrInDeclaration.py b/python/testData/resolve/ClassAttrInDeclaration.py new file mode 100644 index 000000000000..bf5499858801 --- /dev/null +++ b/python/testData/resolve/ClassAttrInDeclaration.py @@ -0,0 +1,4 @@ +class A: + my_attr = 17 + print(my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/ClassAttrInDeclarationNewStyleClass.py b/python/testData/resolve/ClassAttrInDeclarationNewStyleClass.py new file mode 100644 index 000000000000..fb3c9705a2bd --- /dev/null +++ b/python/testData/resolve/ClassAttrInDeclarationNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + my_attr = 17 + print(my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderClassInDeclaration.py b/python/testData/resolve/DunderClassInDeclaration.py new file mode 100644 index 000000000000..d5bcc9eb2794 --- /dev/null +++ b/python/testData/resolve/DunderClassInDeclaration.py @@ -0,0 +1,3 @@ +class A: + print(__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderClassInDeclarationInsideFunction.py b/python/testData/resolve/DunderClassInDeclarationInsideFunction.py new file mode 100644 index 000000000000..5a67313028ea --- /dev/null +++ b/python/testData/resolve/DunderClassInDeclarationInsideFunction.py @@ -0,0 +1,6 @@ +def foo(): + class A: + print(__class__) + # + + return A() \ No newline at end of file diff --git a/python/testData/resolve/DunderClassInDeclarationNewStyleClass.py b/python/testData/resolve/DunderClassInDeclarationNewStyleClass.py new file mode 100644 index 000000000000..317370258e67 --- /dev/null +++ b/python/testData/resolve/DunderClassInDeclarationNewStyleClass.py @@ -0,0 +1,3 @@ +class A(object): + print(__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderClassInDeclarationWithClassAttr.py b/python/testData/resolve/DunderClassInDeclarationWithClassAttr.py new file mode 100644 index 000000000000..9e790d60290f --- /dev/null +++ b/python/testData/resolve/DunderClassInDeclarationWithClassAttr.py @@ -0,0 +1,4 @@ +class A: + __class__ = 17 + print(__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderClassInDeclarationWithClassAttrNewStyleClass.py b/python/testData/resolve/DunderClassInDeclarationWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..1921ecd845da --- /dev/null +++ b/python/testData/resolve/DunderClassInDeclarationWithClassAttrNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + __class__ = 17 + print(__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderClassInDeclarationWithInheritedClassAttr.py b/python/testData/resolve/DunderClassInDeclarationWithInheritedClassAttr.py new file mode 100644 index 000000000000..cb3986d46517 --- /dev/null +++ b/python/testData/resolve/DunderClassInDeclarationWithInheritedClassAttr.py @@ -0,0 +1,6 @@ +class A(object): + __class__ = 17 + +class B(A): + print(__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderDocInDeclaration.py b/python/testData/resolve/DunderDocInDeclaration.py new file mode 100644 index 000000000000..f542971e0ce5 --- /dev/null +++ b/python/testData/resolve/DunderDocInDeclaration.py @@ -0,0 +1,3 @@ +class A: + print(__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderDocInDeclarationNewStyleClass.py b/python/testData/resolve/DunderDocInDeclarationNewStyleClass.py new file mode 100644 index 000000000000..8deaa6098586 --- /dev/null +++ b/python/testData/resolve/DunderDocInDeclarationNewStyleClass.py @@ -0,0 +1,3 @@ +class A(object): + print(__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderDocInDeclarationWithClassAttr.py b/python/testData/resolve/DunderDocInDeclarationWithClassAttr.py new file mode 100644 index 000000000000..3e195cbb44ad --- /dev/null +++ b/python/testData/resolve/DunderDocInDeclarationWithClassAttr.py @@ -0,0 +1,4 @@ +class A: + __doc__ = 17 + print(__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderDocInDeclarationWithClassAttrNewStyleClass.py b/python/testData/resolve/DunderDocInDeclarationWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..6a0dc30bd74f --- /dev/null +++ b/python/testData/resolve/DunderDocInDeclarationWithClassAttrNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + __doc__ = 17 + print(__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderDocInDeclarationWithInheritedClassAttr.py b/python/testData/resolve/DunderDocInDeclarationWithInheritedClassAttr.py new file mode 100644 index 000000000000..82af27afa69b --- /dev/null +++ b/python/testData/resolve/DunderDocInDeclarationWithInheritedClassAttr.py @@ -0,0 +1,6 @@ +class A(object): + __doc__ = 17 + +class B(A): + print(__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderSizeOfInDeclaration.py b/python/testData/resolve/DunderSizeOfInDeclaration.py new file mode 100644 index 000000000000..f15a8686048d --- /dev/null +++ b/python/testData/resolve/DunderSizeOfInDeclaration.py @@ -0,0 +1,3 @@ +class A: + print(__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderSizeOfInDeclarationNewStyleClass.py b/python/testData/resolve/DunderSizeOfInDeclarationNewStyleClass.py new file mode 100644 index 000000000000..52caeda412ac --- /dev/null +++ b/python/testData/resolve/DunderSizeOfInDeclarationNewStyleClass.py @@ -0,0 +1,3 @@ +class A(object): + print(__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderSizeOfInDeclarationWithClassAttr.py b/python/testData/resolve/DunderSizeOfInDeclarationWithClassAttr.py new file mode 100644 index 000000000000..9aa973e5cd79 --- /dev/null +++ b/python/testData/resolve/DunderSizeOfInDeclarationWithClassAttr.py @@ -0,0 +1,4 @@ +class A: + __sizeof__ = 17 + print(__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderSizeOfInDeclarationWithClassAttrNewStyleClass.py b/python/testData/resolve/DunderSizeOfInDeclarationWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..5daf08022681 --- /dev/null +++ b/python/testData/resolve/DunderSizeOfInDeclarationWithClassAttrNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + __sizeof__ = 17 + print(__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/DunderSizeOfInDeclarationWithInheritedClassAttr.py b/python/testData/resolve/DunderSizeOfInDeclarationWithInheritedClassAttr.py new file mode 100644 index 000000000000..4d8a27e1cb0a --- /dev/null +++ b/python/testData/resolve/DunderSizeOfInDeclarationWithInheritedClassAttr.py @@ -0,0 +1,6 @@ +class A(object): + __sizeof__ = 17 + +class B(A): + print(__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitClassAttr.py b/python/testData/resolve/ImplicitClassAttr.py new file mode 100644 index 000000000000..2d8a3eff40c1 --- /dev/null +++ b/python/testData/resolve/ImplicitClassAttr.py @@ -0,0 +1,6 @@ +class A: + my_attr = 15 + + def foo(self): + return my_attr +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitClassAttrNewStyleClass.py b/python/testData/resolve/ImplicitClassAttrNewStyleClass.py new file mode 100644 index 000000000000..070be0694552 --- /dev/null +++ b/python/testData/resolve/ImplicitClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + my_attr = 15 + + def foo(self): + return my_attr +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderClass.py b/python/testData/resolve/ImplicitDunderClass.py new file mode 100644 index 000000000000..2e68ba7b1f22 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderClass.py @@ -0,0 +1,4 @@ +class A: + def foo(self): + return __class__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderClassNewStyleClass.py b/python/testData/resolve/ImplicitDunderClassNewStyleClass.py new file mode 100644 index 000000000000..99a8a16771b7 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderClassNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + def foo(self): + return __class__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderClassWithClassAttr.py b/python/testData/resolve/ImplicitDunderClassWithClassAttr.py new file mode 100644 index 000000000000..81a09107ec71 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderClassWithClassAttr.py @@ -0,0 +1,6 @@ +class A: + __class__ = 15 + + def foo(self): + return __class__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderClassWithClassAttrNewStyleClass.py b/python/testData/resolve/ImplicitDunderClassWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..4e685fd46b6b --- /dev/null +++ b/python/testData/resolve/ImplicitDunderClassWithClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + __class__ = 15 + + def foo(self): + return __class__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderClassWithInheritedClassAttr.py b/python/testData/resolve/ImplicitDunderClassWithInheritedClassAttr.py new file mode 100644 index 000000000000..57cb96bf7405 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderClassWithInheritedClassAttr.py @@ -0,0 +1,7 @@ +class A(object): + __class__ = int + +class B(A): + def foo(self): + return __class__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderDoc.py b/python/testData/resolve/ImplicitDunderDoc.py new file mode 100644 index 000000000000..30d09c82fc71 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderDoc.py @@ -0,0 +1,4 @@ +class A: + def foo(self): + return __doc__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderDocNewStyleClass.py b/python/testData/resolve/ImplicitDunderDocNewStyleClass.py new file mode 100644 index 000000000000..1a93f8ff38b7 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderDocNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + def foo(self): + return __doc__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderDocWithClassAttr.py b/python/testData/resolve/ImplicitDunderDocWithClassAttr.py new file mode 100644 index 000000000000..821ed805f054 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderDocWithClassAttr.py @@ -0,0 +1,6 @@ +class A: + __doc__ = 15 + + def foo(self): + return __doc__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderDocWithClassAttrNewStyleClass.py b/python/testData/resolve/ImplicitDunderDocWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..545b55d94a2e --- /dev/null +++ b/python/testData/resolve/ImplicitDunderDocWithClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + __doc__ = 15 + + def foo(self): + return __doc__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderDocWithInheritedClassAttr.py b/python/testData/resolve/ImplicitDunderDocWithInheritedClassAttr.py new file mode 100644 index 000000000000..71701270e7fe --- /dev/null +++ b/python/testData/resolve/ImplicitDunderDocWithInheritedClassAttr.py @@ -0,0 +1,7 @@ +class A(object): + __doc__ = "abc" + +class B(A): + def foo(self): + return __doc__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderSizeOf.py b/python/testData/resolve/ImplicitDunderSizeOf.py new file mode 100644 index 000000000000..e53d68134d68 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderSizeOf.py @@ -0,0 +1,4 @@ +class A: + def foo(self): + return __sizeof__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderSizeOfNewStyleClass.py b/python/testData/resolve/ImplicitDunderSizeOfNewStyleClass.py new file mode 100644 index 000000000000..c0400c03bf45 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderSizeOfNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + def foo(self): + return __sizeof__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderSizeOfWithClassAttr.py b/python/testData/resolve/ImplicitDunderSizeOfWithClassAttr.py new file mode 100644 index 000000000000..46fe0e7ccd6e --- /dev/null +++ b/python/testData/resolve/ImplicitDunderSizeOfWithClassAttr.py @@ -0,0 +1,6 @@ +class A: + __sizeof__ = 15 + + def foo(self): + return __sizeof__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderSizeOfWithClassAttrNewStyleClass.py b/python/testData/resolve/ImplicitDunderSizeOfWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..3ed21284e59a --- /dev/null +++ b/python/testData/resolve/ImplicitDunderSizeOfWithClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + __sizeof__ = 15 + + def foo(self): + return __sizeof__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitDunderSizeOfWithInheritedClassAttr.py b/python/testData/resolve/ImplicitDunderSizeOfWithInheritedClassAttr.py new file mode 100644 index 000000000000..34e70e535cf8 --- /dev/null +++ b/python/testData/resolve/ImplicitDunderSizeOfWithInheritedClassAttr.py @@ -0,0 +1,7 @@ +class A(object): + __sizeof__ = 4 + +class B(A): + def foo(self): + return __sizeof__ +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitInheritedClassAttr.py b/python/testData/resolve/ImplicitInheritedClassAttr.py new file mode 100644 index 000000000000..2c72252ac833 --- /dev/null +++ b/python/testData/resolve/ImplicitInheritedClassAttr.py @@ -0,0 +1,7 @@ +class A(object): + my_attr = 4 + +class B(A): + def foo(self): + return my_attr +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitUndeclaredClassAttr.py b/python/testData/resolve/ImplicitUndeclaredClassAttr.py new file mode 100644 index 000000000000..d1c52ff2b51d --- /dev/null +++ b/python/testData/resolve/ImplicitUndeclaredClassAttr.py @@ -0,0 +1,4 @@ +class A: + def foo(self): + return my_attr +# \ No newline at end of file diff --git a/python/testData/resolve/ImplicitUndeclaredClassAttrNewStyleClass.py b/python/testData/resolve/ImplicitUndeclaredClassAttrNewStyleClass.py new file mode 100644 index 000000000000..557ef92b6202 --- /dev/null +++ b/python/testData/resolve/ImplicitUndeclaredClassAttrNewStyleClass.py @@ -0,0 +1,4 @@ +class A(object): + def foo(self): + return my_attr +# \ No newline at end of file diff --git a/python/testData/resolve/InheritedClassAttrInDeclaration.py b/python/testData/resolve/InheritedClassAttrInDeclaration.py new file mode 100644 index 000000000000..2b40795270fd --- /dev/null +++ b/python/testData/resolve/InheritedClassAttrInDeclaration.py @@ -0,0 +1,6 @@ +class A(object): + my_attr = 17 + +class B(A): + print(my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceClassAttr.py b/python/testData/resolve/InstanceClassAttr.py new file mode 100644 index 000000000000..6cd541bb959f --- /dev/null +++ b/python/testData/resolve/InstanceClassAttr.py @@ -0,0 +1,7 @@ +class A: + my_attr = 15 + + +a = A() +print(a.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceClassAttrNewStyleClass.py b/python/testData/resolve/InstanceClassAttrNewStyleClass.py new file mode 100644 index 000000000000..4dd67f501a87 --- /dev/null +++ b/python/testData/resolve/InstanceClassAttrNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + my_attr = 15 + + +a = A() +print(a.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderClass.py b/python/testData/resolve/InstanceDunderClass.py new file mode 100644 index 000000000000..3f671b0c854d --- /dev/null +++ b/python/testData/resolve/InstanceDunderClass.py @@ -0,0 +1,7 @@ +class A: + pass + + +a = A() +print(a.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderClassNewStyleClass.py b/python/testData/resolve/InstanceDunderClassNewStyleClass.py new file mode 100644 index 000000000000..d64ab5e20ec1 --- /dev/null +++ b/python/testData/resolve/InstanceDunderClassNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + pass + + +a = A() +print(a.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderClassWithClassAttr.py b/python/testData/resolve/InstanceDunderClassWithClassAttr.py new file mode 100644 index 000000000000..819e206ffab6 --- /dev/null +++ b/python/testData/resolve/InstanceDunderClassWithClassAttr.py @@ -0,0 +1,7 @@ +class A: + __class__ = 15 + + +a = A() +print(a.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderClassWithClassAttrNewStyleClass.py b/python/testData/resolve/InstanceDunderClassWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..a51fafbcb2a0 --- /dev/null +++ b/python/testData/resolve/InstanceDunderClassWithClassAttrNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + __class__ = 15 + + +a = A() +print(a.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderClassWithInheritedClassAttr.py b/python/testData/resolve/InstanceDunderClassWithInheritedClassAttr.py new file mode 100644 index 000000000000..c685bbd9ce87 --- /dev/null +++ b/python/testData/resolve/InstanceDunderClassWithInheritedClassAttr.py @@ -0,0 +1,10 @@ +class A(object): + __class__ = 15 + +class B(A): + pass + + +b = B() +print(b.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderDoc.py b/python/testData/resolve/InstanceDunderDoc.py new file mode 100644 index 000000000000..04da49b0da7e --- /dev/null +++ b/python/testData/resolve/InstanceDunderDoc.py @@ -0,0 +1,7 @@ +class A: + pass + + +a = A() +print(a.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderDocNewStyleClass.py b/python/testData/resolve/InstanceDunderDocNewStyleClass.py new file mode 100644 index 000000000000..7639c9ecb3a4 --- /dev/null +++ b/python/testData/resolve/InstanceDunderDocNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + pass + + +a = A() +print(a.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderDocWithClassAttr.py b/python/testData/resolve/InstanceDunderDocWithClassAttr.py new file mode 100644 index 000000000000..b83622ea787d --- /dev/null +++ b/python/testData/resolve/InstanceDunderDocWithClassAttr.py @@ -0,0 +1,7 @@ +class A: + __doc__ = 15 + + +a = A() +print(a.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderDocWithClassAttrNewStyleClass.py b/python/testData/resolve/InstanceDunderDocWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..8e71d90f7687 --- /dev/null +++ b/python/testData/resolve/InstanceDunderDocWithClassAttrNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + __doc__ = 15 + + +a = A() +print(a.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderDocWithInheritedClassAttr.py b/python/testData/resolve/InstanceDunderDocWithInheritedClassAttr.py new file mode 100644 index 000000000000..3fef6e9429dc --- /dev/null +++ b/python/testData/resolve/InstanceDunderDocWithInheritedClassAttr.py @@ -0,0 +1,10 @@ +class A(object): + __doc__ = 16 + +class B(A): + pass + + +b = B() +print(b.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderSizeOf.py b/python/testData/resolve/InstanceDunderSizeOf.py new file mode 100644 index 000000000000..9a34e386d031 --- /dev/null +++ b/python/testData/resolve/InstanceDunderSizeOf.py @@ -0,0 +1,7 @@ +class A: + pass + + +a = A() +print(a.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderSizeOfNewStyleClass.py b/python/testData/resolve/InstanceDunderSizeOfNewStyleClass.py new file mode 100644 index 000000000000..58611a25ba1f --- /dev/null +++ b/python/testData/resolve/InstanceDunderSizeOfNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + pass + + +a = A() +print(a.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderSizeOfWithClassAttr.py b/python/testData/resolve/InstanceDunderSizeOfWithClassAttr.py new file mode 100644 index 000000000000..7352e5b9b00d --- /dev/null +++ b/python/testData/resolve/InstanceDunderSizeOfWithClassAttr.py @@ -0,0 +1,7 @@ +class A: + __sizeof__ = 15 + + +a = A() +print(a.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderSizeOfWithClassAttrNewStyleClass.py b/python/testData/resolve/InstanceDunderSizeOfWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..3f89b2b1c9ba --- /dev/null +++ b/python/testData/resolve/InstanceDunderSizeOfWithClassAttrNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + __sizeof__ = 15 + + +a = A() +print(a.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceDunderSizeOfWithInheritedClassAttr.py b/python/testData/resolve/InstanceDunderSizeOfWithInheritedClassAttr.py new file mode 100644 index 000000000000..2e79cdfbf9ea --- /dev/null +++ b/python/testData/resolve/InstanceDunderSizeOfWithInheritedClassAttr.py @@ -0,0 +1,10 @@ +class A(object): + __sizeof__ = 17 + +class B(A): + pass + + +b = B() +print(b.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceInheritedClassAttr.py b/python/testData/resolve/InstanceInheritedClassAttr.py new file mode 100644 index 000000000000..5620fe5d471d --- /dev/null +++ b/python/testData/resolve/InstanceInheritedClassAttr.py @@ -0,0 +1,10 @@ +class A(object): + my_attr = 17 + +class B(A): + pass + + +b = B() +print(b.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceUndeclaredClassAttr.py b/python/testData/resolve/InstanceUndeclaredClassAttr.py new file mode 100644 index 000000000000..a2d386057902 --- /dev/null +++ b/python/testData/resolve/InstanceUndeclaredClassAttr.py @@ -0,0 +1,7 @@ +class A: + pass + + +a = A() +print(a.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/InstanceUndeclaredClassAttrNewStyleClass.py b/python/testData/resolve/InstanceUndeclaredClassAttrNewStyleClass.py new file mode 100644 index 000000000000..72dc3f781122 --- /dev/null +++ b/python/testData/resolve/InstanceUndeclaredClassAttrNewStyleClass.py @@ -0,0 +1,7 @@ +class A(object): + pass + + +a = A() +print(a.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/LocalDunderClass.py b/python/testData/resolve/LocalDunderClass.py new file mode 100644 index 000000000000..01f4adf4e65c --- /dev/null +++ b/python/testData/resolve/LocalDunderClass.py @@ -0,0 +1,5 @@ +class A: + def foo(self): + __class__ = 16 + return __class__ +# \ No newline at end of file diff --git a/python/testData/resolve/TypeClassAttr.py b/python/testData/resolve/TypeClassAttr.py new file mode 100644 index 000000000000..b24b8608b08a --- /dev/null +++ b/python/testData/resolve/TypeClassAttr.py @@ -0,0 +1,6 @@ +class A: + my_attr = 15 + + +print(A.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeClassAttrNewStyleClass.py b/python/testData/resolve/TypeClassAttrNewStyleClass.py new file mode 100644 index 000000000000..5fef732aff6d --- /dev/null +++ b/python/testData/resolve/TypeClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + my_attr = 15 + + +print(A.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderClass.py b/python/testData/resolve/TypeDunderClass.py new file mode 100644 index 000000000000..9dc04760f400 --- /dev/null +++ b/python/testData/resolve/TypeDunderClass.py @@ -0,0 +1,6 @@ +class A: + pass + + +print(A.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderClassNewStyleClass.py b/python/testData/resolve/TypeDunderClassNewStyleClass.py new file mode 100644 index 000000000000..2793517a5778 --- /dev/null +++ b/python/testData/resolve/TypeDunderClassNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + pass + + +print(A.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderClassWithClassAttr.py b/python/testData/resolve/TypeDunderClassWithClassAttr.py new file mode 100644 index 000000000000..3696e7afca7d --- /dev/null +++ b/python/testData/resolve/TypeDunderClassWithClassAttr.py @@ -0,0 +1,6 @@ +class A: + __class__ = 15 + + +print(A.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderClassWithClassAttrNewStyleClass.py b/python/testData/resolve/TypeDunderClassWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..402f7f3ee014 --- /dev/null +++ b/python/testData/resolve/TypeDunderClassWithClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + __class__ = 15 + + +print(A.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderClassWithInheritedClassAttr.py b/python/testData/resolve/TypeDunderClassWithInheritedClassAttr.py new file mode 100644 index 000000000000..907d30dddf17 --- /dev/null +++ b/python/testData/resolve/TypeDunderClassWithInheritedClassAttr.py @@ -0,0 +1,9 @@ +class A(object): + __class__ = 17 + +class B(A): + pass + + +print(B.__class__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderDoc.py b/python/testData/resolve/TypeDunderDoc.py new file mode 100644 index 000000000000..64c531c8b0ed --- /dev/null +++ b/python/testData/resolve/TypeDunderDoc.py @@ -0,0 +1,6 @@ +class A: + pass + + +print(A.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderDocNewStyleClass.py b/python/testData/resolve/TypeDunderDocNewStyleClass.py new file mode 100644 index 000000000000..2c71c76dbc5c --- /dev/null +++ b/python/testData/resolve/TypeDunderDocNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + pass + + +print(A.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderDocWithClassAttr.py b/python/testData/resolve/TypeDunderDocWithClassAttr.py new file mode 100644 index 000000000000..8440e5ded58e --- /dev/null +++ b/python/testData/resolve/TypeDunderDocWithClassAttr.py @@ -0,0 +1,6 @@ +class A: + __doc__ = 16 + + +print(A.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderDocWithClassAttrNewStyleClass.py b/python/testData/resolve/TypeDunderDocWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..a06a2e5e863a --- /dev/null +++ b/python/testData/resolve/TypeDunderDocWithClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + __doc__ = 16 + + +print(A.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderDocWithInheritedClassAttr.py b/python/testData/resolve/TypeDunderDocWithInheritedClassAttr.py new file mode 100644 index 000000000000..77211eb54174 --- /dev/null +++ b/python/testData/resolve/TypeDunderDocWithInheritedClassAttr.py @@ -0,0 +1,9 @@ +class A(object): + __doc__ = 17 + +class B(A): + pass + + +print(B.__doc__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderSizeOf.py b/python/testData/resolve/TypeDunderSizeOf.py new file mode 100644 index 000000000000..a301afe2804c --- /dev/null +++ b/python/testData/resolve/TypeDunderSizeOf.py @@ -0,0 +1,6 @@ +class A: + pass + + +print(A.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderSizeOfNewStyleClass.py b/python/testData/resolve/TypeDunderSizeOfNewStyleClass.py new file mode 100644 index 000000000000..711370afac64 --- /dev/null +++ b/python/testData/resolve/TypeDunderSizeOfNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + pass + + +print(A.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderSizeOfWithClassAttr.py b/python/testData/resolve/TypeDunderSizeOfWithClassAttr.py new file mode 100644 index 000000000000..8c6ef22596fe --- /dev/null +++ b/python/testData/resolve/TypeDunderSizeOfWithClassAttr.py @@ -0,0 +1,6 @@ +class A: + __sizeof__ = 16 + + +print(A.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderSizeOfWithClassAttrNewStyleClass.py b/python/testData/resolve/TypeDunderSizeOfWithClassAttrNewStyleClass.py new file mode 100644 index 000000000000..564f57a45a67 --- /dev/null +++ b/python/testData/resolve/TypeDunderSizeOfWithClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + __sizeof__ = 16 + + +print(A.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeDunderSizeOfWithInheritedClassAttr.py b/python/testData/resolve/TypeDunderSizeOfWithInheritedClassAttr.py new file mode 100644 index 000000000000..4d70493199b3 --- /dev/null +++ b/python/testData/resolve/TypeDunderSizeOfWithInheritedClassAttr.py @@ -0,0 +1,9 @@ +class A(object): + __sizeof__ = 17 + +class B(A): + pass + + +print(B.__sizeof__) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeInheritedClassAttr.py b/python/testData/resolve/TypeInheritedClassAttr.py new file mode 100644 index 000000000000..28b4092ceb6e --- /dev/null +++ b/python/testData/resolve/TypeInheritedClassAttr.py @@ -0,0 +1,9 @@ +class A(object): + my_attr = 17 + +class B(A): + pass + + +print(B.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeUndeclaredClassAttr.py b/python/testData/resolve/TypeUndeclaredClassAttr.py new file mode 100644 index 000000000000..91cfa64f5eae --- /dev/null +++ b/python/testData/resolve/TypeUndeclaredClassAttr.py @@ -0,0 +1,6 @@ +class A: + pass + + +print(A.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/TypeUndeclaredClassAttrNewStyleClass.py b/python/testData/resolve/TypeUndeclaredClassAttrNewStyleClass.py new file mode 100644 index 000000000000..3f2e26f1df93 --- /dev/null +++ b/python/testData/resolve/TypeUndeclaredClassAttrNewStyleClass.py @@ -0,0 +1,6 @@ +class A(object): + pass + + +print(A.my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/UndeclaredClassAttrInDeclaration.py b/python/testData/resolve/UndeclaredClassAttrInDeclaration.py new file mode 100644 index 000000000000..df3a528fd108 --- /dev/null +++ b/python/testData/resolve/UndeclaredClassAttrInDeclaration.py @@ -0,0 +1,3 @@ +class A: + print(my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/UndeclaredClassAttrInDeclarationNewStyleClass.py b/python/testData/resolve/UndeclaredClassAttrInDeclarationNewStyleClass.py new file mode 100644 index 000000000000..cf1bce79bcf8 --- /dev/null +++ b/python/testData/resolve/UndeclaredClassAttrInDeclarationNewStyleClass.py @@ -0,0 +1,3 @@ +class A(object): + print(my_attr) +# \ No newline at end of file diff --git a/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg/__init__.py b/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg/__init__.py new file mode 100644 index 000000000000..3074a5c357d1 --- /dev/null +++ b/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg/__init__.py @@ -0,0 +1,2 @@ +import mod + \ No newline at end of file diff --git a/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg/mod.py b/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg/mod.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg2/__init__.py b/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg2/__init__.py new file mode 100644 index 000000000000..3074a5c357d1 --- /dev/null +++ b/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg2/__init__.py @@ -0,0 +1,2 @@ +import mod + \ No newline at end of file diff --git a/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg2/mod.py b/python/testData/resolve/multiFile/ambiguousImplicitRelativeImport/pkg2/mod.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/Py3ResolveTest.java b/python/testSrc/com/jetbrains/python/Py3ResolveTest.java index 9edc7db4230c..4a7458f2ecad 100644 --- a/python/testSrc/com/jetbrains/python/Py3ResolveTest.java +++ b/python/testSrc/com/jetbrains/python/Py3ResolveTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -17,11 +17,15 @@ package com.jetbrains.python; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testFramework.LightProjectDescriptor; import com.jetbrains.python.fixtures.PyResolveTestCase; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; +import com.jetbrains.python.psi.PyTargetExpression; +import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; /** @@ -60,4 +64,297 @@ public class Py3ResolveTest extends PyResolveTestCase { public void testTrueDiv() { assertResolvesTo(PyFunction.class, "__truediv__"); } + + // PY-13734 + public void testImplicitDunderClass() { + assertResolvesTo(PyClass.class, "A"); + } + + public void testImplicitDunderDoc() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOf() { + assertUnresolved(); + } + + public void testImplicitUndeclaredClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testImplicitDunderClassWithClassAttr() { + assertResolvesTo(PyClass.class, "A"); + } + + public void testImplicitDunderDocWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOfWithClassAttr() { + assertUnresolved(); + } + + public void testImplicitClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testImplicitDunderClassWithInheritedClassAttr() { + assertResolvesTo(PyClass.class, "B"); + } + + public void testImplicitDunderDocWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOfWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testImplicitInheritedClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testInstanceDunderClass() { + assertResolvesTo(PyClass.class, "A"); + } + + public void testInstanceDunderDoc() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testInstanceDunderSizeOf() { + final PyFunction expression = assertResolvesTo(PyFunction.class, PyNames.SIZEOF); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testInstanceUndeclaredClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testInstanceDunderClassWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderDocWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderSizeOfWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testInstanceDunderClassWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderDocWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testInstanceDunderSizeOfWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testLocalDunderClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyFunction function = PsiTreeUtil.getParentOfType(expression, PyFunction.class); + assertNotNull(function); + assertEquals("foo", function.getName()); + } + + // PY-13734 + public void testTypeDunderClass() { + assertResolvesTo(PyClass.class, "type"); + } + + public void testTypeDunderDoc() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testTypeDunderSizeOf() { + final PyFunction expression = assertResolvesTo(PyFunction.class, PyNames.SIZEOF); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testTypeUndeclaredClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testTypeDunderClassWithClassAttr() { + assertResolvesTo(PyClass.class, "type"); + } + + public void testTypeDunderDocWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeDunderSizeOfWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testTypeDunderClassWithInheritedClassAttr() { + assertResolvesTo(PyClass.class, "type"); + } + + public void testTypeDunderDocWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testTypeDunderSizeOfWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testDunderClassInDeclaration() { + assertUnresolved(); + } + + public void testDunderDocInDeclaration() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testDunderSizeOfInDeclaration() { + assertUnresolved(); + } + + public void testUndeclaredClassAttrInDeclaration() { + assertUnresolved(); + } + + // PY-13734 + public void testDunderClassInDeclarationWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testDunderDocInDeclarationWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testDunderSizeOfInDeclarationWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testClassAttrInDeclaration() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testDunderClassInDeclarationWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testDunderDocInDeclarationWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE_3K, expression.getContainingFile().getName()); + } + + public void testDunderSizeOfInDeclarationWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testInheritedClassAttrInDeclaration() { + assertUnresolved(); + } + + // PY-13734 + public void testDunderClassInDeclarationInsideFunction() { + assertUnresolved(); + } } diff --git a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java index c0294660b7ff..6d61dfaed139 100644 --- a/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyMultiFileResolveTest.java @@ -18,6 +18,8 @@ package com.jetbrains.python; import com.google.common.collect.Lists; import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.source.PsiFileImpl; @@ -26,10 +28,14 @@ import com.jetbrains.python.fixtures.PyMultiFileResolveTestCase; import com.jetbrains.python.fixtures.PyResolveTestCase; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * @author yole @@ -459,4 +465,29 @@ public class PyMultiFileResolveTest extends PyMultiFileResolveTestCase { } } } + + // PY-19989 + public void testAmbiguousImplicitRelativeImport() { + prepareTestDirectory(); + assertSameElements(doMultiResolveAndGetFileUrls("pkg2/__init__.py"), "pkg2/mod.py"); + assertSameElements(doMultiResolveAndGetFileUrls("pkg/__init__.py"), "pkg/mod.py"); + } + + @NotNull + private List doMultiResolveAndGetFileUrls(@NotNull String currentFilePath) { + myFixture.configureByFile(currentFilePath); + final PsiReference reference = PyResolveTestCase.findReferenceByMarker(myFixture.getFile()); + final VirtualFile root = ModuleRootManager.getInstance(myFixture.getModule()).getSourceRoots()[0]; + + final Stream fileSystemItems; + if (reference instanceof PsiPolyVariantReference) { + final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false); + fileSystemItems = Arrays.stream(results).map(r -> PyPsiUtils.getFileSystemItem(r.getElement())); + } + else { + fileSystemItems = Stream.of(PyPsiUtils.getFileSystemItem(reference.resolve())); + } + return fileSystemItems.map(f -> VfsUtilCore.getRelativeLocation(f.getVirtualFile(), root)).collect(Collectors.toList()); + + } } \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index 0ba634018415..ea002c2e840b 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -26,6 +26,7 @@ import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.documentation.docstrings.DocStringFormat; import com.jetbrains.python.fixtures.PyResolveTestCase; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyBuiltinCache; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher; import com.jetbrains.python.psi.resolve.ImportedResolveResult; @@ -406,7 +407,7 @@ public class PyResolveTest extends PyResolveTestCase { public void testBuiltinVsClassMember() { // PY-1654 final PyFunction pyFunction = assertResolvesTo(PyFunction.class, "eval"); - assertEquals("__builtin__.py", pyFunction.getContainingFile().getName()); + assertEquals(PyBuiltinCache.BUILTIN_FILE, pyFunction.getContainingFile().getName()); } public void testLambdaToClass() { // PY-2182 @@ -740,4 +741,481 @@ public class PyResolveTest extends PyResolveTestCase { assertResolvesTo(PyTargetExpression.class, "foo"); } + // PY-13734 + public void testImplicitDunderClass() { + assertUnresolved(); + } + + public void testImplicitDunderDoc() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOf() { + assertUnresolved(); + } + + public void testImplicitUndeclaredClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testImplicitDunderClassNewStyleClass() { + assertUnresolved(); + } + + public void testImplicitDunderDocNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOfNewStyleClass() { + assertUnresolved(); + } + + public void testImplicitUndeclaredClassAttrNewStyleClass() { + assertUnresolved(); + } + + // PY-13734 + public void testImplicitDunderClassWithClassAttr() { + assertUnresolved(); + } + + public void testImplicitDunderDocWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOfWithClassAttr() { + assertUnresolved(); + } + + public void testImplicitClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testImplicitDunderClassWithClassAttrNewStyleClass() { + assertUnresolved(); + } + + public void testImplicitDunderDocWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOfWithClassAttrNewStyleClass() { + assertUnresolved(); + } + + public void testImplicitClassAttrNewStyleClass() { + assertUnresolved(); + } + + // PY-13734 + public void testImplicitDunderClassWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testImplicitDunderDocWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testImplicitDunderSizeOfWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testImplicitInheritedClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testInstanceDunderClass() { + assertResolvesTo(PyClass.class, "A"); + } + + public void testInstanceDunderDoc() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testInstanceDunderSizeOf() { + assertUnresolved(); + } + + public void testInstanceUndeclaredClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testInstanceDunderClassNewStyleClass() { + assertResolvesTo(PyClass.class, "A"); + } + + public void testInstanceDunderDocNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testInstanceDunderSizeOfNewStyleClass() { + final PyFunction expression = assertResolvesTo(PyFunction.class, PyNames.SIZEOF); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testInstanceUndeclaredClassAttrNewStyleClass() { + assertUnresolved(); + } + + // PY-13734 + public void testInstanceDunderClassWithClassAttr() { + assertResolvesTo(PyClass.class, "A"); + } + + public void testInstanceDunderDocWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderSizeOfWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testInstanceDunderClassWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderDocWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderSizeOfWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testInstanceDunderClassWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceDunderDocWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testInstanceDunderSizeOfWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testInstanceInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testLocalDunderClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyFunction function = PsiTreeUtil.getParentOfType(expression, PyFunction.class); + assertNotNull(function); + assertEquals("foo", function.getName()); + } + + // PY-13734 + public void testTypeDunderClass() { + assertUnresolved(); + } + + public void testTypeDunderDoc() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testTypeDunderSizeOf() { + assertUnresolved(); + } + + public void testTypeUndeclaredClassAttr() { + assertUnresolved(); + } + + // PY-13734 + public void testTypeDunderClassNewStyleClass() { + assertResolvesTo(PyClass.class, "type"); + } + + public void testTypeDunderDocNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testTypeDunderSizeOfNewStyleClass() { + final PyFunction expression = assertResolvesTo(PyFunction.class, PyNames.SIZEOF); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testTypeUndeclaredClassAttrNewStyleClass() { + assertUnresolved(); + } + + // PY-13734 + public void testTypeDunderClassWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeDunderDocWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeDunderSizeOfWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testTypeDunderClassWithClassAttrNewStyleClass() { + assertResolvesTo(PyClass.class, "type"); + } + + public void testTypeDunderDocWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeDunderSizeOfWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testTypeDunderClassWithInheritedClassAttr() { + assertResolvesTo(PyClass.class, "type"); + } + + public void testTypeDunderDocWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testTypeDunderSizeOfWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testTypeInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testDunderClassInDeclaration() { + assertUnresolved(); + } + + public void testDunderDocInDeclaration() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testDunderSizeOfInDeclaration() { + assertUnresolved(); + } + + public void testUndeclaredClassAttrInDeclaration() { + assertUnresolved(); + } + + // PY-13734 + public void testDunderClassInDeclarationNewStyleClass() { + assertUnresolved(); + } + + public void testDunderDocInDeclarationNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testDunderSizeOfInDeclarationNewStyleClass() { + assertUnresolved(); + } + + public void testUndeclaredClassAttrInDeclarationNewStyleClass() { + assertUnresolved(); + } + + // PY-13734 + public void testDunderClassInDeclarationWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testDunderDocInDeclarationWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testDunderSizeOfInDeclarationWithClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testClassAttrInDeclaration() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testDunderClassInDeclarationWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.__CLASS__); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testDunderDocInDeclarationWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testDunderSizeOfInDeclarationWithClassAttrNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.SIZEOF); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + public void testClassAttrInDeclarationNewStyleClass() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, "my_attr"); + + final PyClass cls = expression.getContainingClass(); + assertNotNull(cls); + assertEquals("A", cls.getName()); + } + + // PY-13734 + public void testDunderClassInDeclarationWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testDunderDocInDeclarationWithInheritedClassAttr() { + final PyTargetExpression expression = assertResolvesTo(PyTargetExpression.class, PyNames.DOC); + assertEquals(PyBuiltinCache.BUILTIN_FILE, expression.getContainingFile().getName()); + } + + public void testDunderSizeOfInDeclarationWithInheritedClassAttr() { + assertUnresolved(); + } + + public void testInheritedClassAttrInDeclaration() { + assertUnresolved(); + } + + // PY-13734 + public void testDunderClassInDeclarationInsideFunction() { + assertUnresolved(); + } } diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java index 99d5a35a43d5..953a21ee1313 100644 --- a/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java +++ b/python/testSrc/com/jetbrains/python/fixtures/PyResolveTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -89,6 +89,17 @@ public abstract class PyResolveTestCase extends PyTestCase { return assertResolveResult(element, aClass, name, containingFilePath); } + protected void assertUnresolved() { + final PsiElement element; + try { + element = doResolve(); + } + catch (Exception e) { + throw new RuntimeException(e); + } + assertNull(element); + } + public static T assertResolveResult(PsiElement element, Class aClass, String name) { diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java index dc43bc8b5f3a..0814f810f743 100644 --- a/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java @@ -136,4 +136,9 @@ public class Py3UnresolvedReferencesInspectionTest extends PyTestCase { public void testDecodeBytesAfterSlicing() { doTest(); } + + // PY-13734 + public void testDunderClass() { + doTest(); + } } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java index e869d715e5fe..0f0065f449ad 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -167,8 +167,17 @@ public class PyCompatibilityInspectionTest extends PyTestCase { doTest(LanguageLevel.PYTHON35); } + // PY-19523 + public void testBz2Module() { + doTest(); + } + + public void testUnderscoreBz2Module() { + doTest(); + } + private void doTest(@NotNull LanguageLevel level) { - runWithLanguageLevel(level, () -> doTest()); + runWithLanguageLevel(level, this::doTest); } private void doTest() { diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java index 471e48ecac7a..3b2548bddaeb 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnresolvedReferencesInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -234,17 +234,17 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { // PY-6745 public void testQualNameAttribute() { - runWithLanguageLevel(LanguageLevel.PYTHON33, () -> doTest()); + runWithLanguageLevel(LanguageLevel.PYTHON33, this::doTest); } // PY-7389 public void testComprehensionScope27() { - runWithLanguageLevel(LanguageLevel.PYTHON27, () -> doTest()); + runWithLanguageLevel(LanguageLevel.PYTHON27, this::doTest); } // PY-7389 public void testComprehensionScope33() { - runWithLanguageLevel(LanguageLevel.PYTHON33, () -> doTest()); + runWithLanguageLevel(LanguageLevel.PYTHON33, this::doTest); } // PY-7516 @@ -724,6 +724,11 @@ public class PyUnresolvedReferencesInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-13734 + public void testDunderClass() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() { diff --git a/python/testSrc/com/jetbrains/python/quickFixes/AddImportQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/AddImportQuickFixTest.java index 969b7cee4028..7eef13fc19a5 100644 --- a/python/testSrc/com/jetbrains/python/quickFixes/AddImportQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/quickFixes/AddImportQuickFixTest.java @@ -17,6 +17,7 @@ package com.jetbrains.python.quickFixes; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInspection.ex.QuickFixWrapper; +import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyQuickFixTestCase; import com.jetbrains.python.codeInsight.imports.AutoImportQuickFix; @@ -26,7 +27,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.function.Consumer; /** * @author Mikhail Golubev @@ -43,6 +43,17 @@ public class AddImportQuickFixTest extends PyQuickFixTestCase { final List candidates = fix.getCandidates(); final List names = ContainerUtil.map(candidates, c -> c.getPresentableText("join")); assertSameElements(names, "os.path.join(path, *paths)"); + return true; + }); + } + + // PY-19975 + public void testCanonicalNamesFromHigherLevelPackage() { + doMultiFileAutoImportTest("Import", fix -> { + final List candidates = fix.getCandidates(); + final List names = ContainerUtil.map(candidates, c -> c.getPresentableText("MyClass")); + assertSameElements(names, "foo.MyClass", "bar.MyClass"); + return true; }); } @@ -50,7 +61,7 @@ public class AddImportQuickFixTest extends PyQuickFixTestCase { doMultiFileAutoImportTest(hintPrefix, null); } - private void doMultiFileAutoImportTest(@NotNull String hintPrefix, @Nullable Consumer checkQuickfix) { + private void doMultiFileAutoImportTest(@NotNull String hintPrefix, @Nullable Processor checkQuickfix) { myFixture.copyDirectoryToProject(getTestName(true), ""); myFixture.enableInspections(PyUnresolvedReferencesInspection.class); final String entryPoint = "main"; @@ -62,10 +73,13 @@ public class AddImportQuickFixTest extends PyQuickFixTestCase { }); assertNotNull("Auto import quick fix starting with '" + hintPrefix + "' wasn't found", intention); final AutoImportQuickFix quickfix = (AutoImportQuickFix)((QuickFixWrapper)intention).getFix(); + boolean applyFix = true; if (checkQuickfix != null) { - checkQuickfix.accept(quickfix); + applyFix = checkQuickfix.process(quickfix); + } + if (applyFix) { + myFixture.launchAction(intention); + myFixture.checkResultByFile(getTestName(true) + "/" + entryPoint + "_after.py", true); } - myFixture.launchAction(intention); - myFixture.checkResultByFile(getTestName(true) + "/" + entryPoint + "_after.py", true); } }