From 6296977feaa87ccd48a054363ade5507a00231bf Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 21 Jul 2015 14:15:14 +0200 Subject: [PATCH 01/41] Cleanup (formatting) --- .../daemon/impl/analysis/HighlightUtil.java | 6 +-- .../impl/analysis/HighlightVisitorImpl.java | 52 +++++++------------ .../codeInsight/ExpectedTypesProvider.java | 6 +-- .../completion/PreferByKindWeigher.java | 16 ++++-- .../com/intellij/psi/JavaElementVisitor.java | 6 +-- .../src/com/intellij/psi/PsiResourceList.java | 4 +- .../com/intellij/psi/PsiResourceVariable.java | 4 +- .../source/tree/java/PsiResourceListImpl.java | 14 ++--- .../completion/Normal17CompletionTest.groovy | 7 +-- 9 files changed, 54 insertions(+), 61 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index 1de77d6beee5..cf54d203924f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -784,9 +784,7 @@ public class HighlightUtil extends HighlightUtilBase { return highlight; } - private static void registerUnhandledExceptionFixes(@NotNull final PsiElement element, - final HighlightInfo errorResult, - @NotNull final List unhandled) { + private static void registerUnhandledExceptionFixes(PsiElement element, HighlightInfo errorResult, List unhandled) { QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionToCatchFix()); QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createAddExceptionToThrowsFix(element)); QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createSurroundWithTryCatchFix(element)); @@ -2920,7 +2918,7 @@ public class HighlightUtil extends HighlightUtilBase { private final LanguageLevel level; private final String key; - Feature(@NotNull LanguageLevel level, @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) final String key) { + Feature(@NotNull LanguageLevel level, @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String key) { this.level = level; this.key = key; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 92be0e06e8a3..d8a756786db2 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -220,8 +220,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } } @@ -568,8 +567,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(referenceExpression, results, list, resolved, result, expression, myResolveHelper, list)); } } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } } } @@ -841,8 +839,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } else if (parent instanceof PsiImportStatement && ((PsiImportStatement)parent).isOnDemand()) { // highlight on demand import as class @@ -862,8 +859,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh try { myHolder.add(HighlightMethodUtil.checkMethodCall(expression, myResolveHelper, myLanguageLevel,myJavaSdkVersion)); } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression)); @@ -892,8 +888,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } PsiClass aClass = method.getContainingClass(); if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass)); @@ -948,8 +943,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh try { if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, type, myHolder, myJavaSdkVersion); } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression, aClass)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, type)); if (!myHolder.hasErrorResults()) registerConstructorCall(expression); @@ -1198,8 +1192,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh try { myHolder.add(HighlightControlFlowUtil.checkVariableInitializedBeforeUsage(expression, (PsiVariable)resolved, myUninitializedVarProblems,myFile)); } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } PsiVariable variable = (PsiVariable)resolved; boolean isFinal = variable.hasModifierProperty(PsiModifier.FINAL); @@ -1224,8 +1217,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh .checkAmbiguousMethodCallArguments(expression, results, list, resolved, result, methodCallExpression, myResolveHelper, expression.getReferenceNameElement())); } } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } } @@ -1234,8 +1226,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh try { myHolder.add(HighlightUtil.checkIllegalForwardReferenceToField(expression, (PsiField)resolved)); } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved)); @@ -1424,8 +1415,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh try { myHolder.add(HighlightUtil.checkReturnStatementType(statement)); } - catch (IndexNotReadyException ignore) { - } + catch (IndexNotReadyException ignore) { } } @Override @@ -1485,13 +1475,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } - @Override - public void visitResourceVariable(final PsiResourceVariable resourceVariable) { - visitVariable(resourceVariable); - if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resourceVariable)); - if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resourceVariable)); - } - @Override public void visitResourceList(PsiResourceList resourceList) { super.visitResourceList(resourceList); @@ -1499,7 +1482,14 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } @Override - public void visitTypeElement(final PsiTypeElement type) { + public void visitResourceVariable(PsiResourceVariable variable) { + super.visitResourceVariable(variable); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(variable)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(variable)); + } + + @Override + public void visitTypeElement(PsiTypeElement type) { if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type, myLanguageLevel)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type)); @@ -1512,8 +1502,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIntersectionInTypeCast(typeCast, myLanguageLevel)); if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkInconvertibleTypeCast(typeCast)); } - catch (IndexNotReadyException ignore) { - } + catch (IndexNotReadyException ignored) { } } @Override @@ -1531,8 +1520,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh try { if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkVariableInitializerType(variable)); } - catch (IndexNotReadyException ignored) { - } + catch (IndexNotReadyException ignored) { } } private boolean isReassigned(@NotNull PsiVariable variable) { diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index 8b8fcd40619f..42aad6dd94c0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -502,8 +502,8 @@ public class ExpectedTypesProvider { @Override public void visitVariable(@NotNull PsiVariable variable) { PsiType type = variable.getType(); - myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, - variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON, null, getPropertyName(variable))); + TailType tail = variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON; + myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tail, null, getPropertyName(variable))); } @Override public void visitAssignmentExpression(@NotNull PsiAssignmentExpression assignment) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index f8b5bac76b4d..f539c061782e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -51,20 +51,25 @@ public class PreferByKindWeigher extends LookupElementWeigher { withParent(psiElement(PsiTypeElement.class). withParent(or(psiElement(PsiCatchSection.class), psiElement(PsiVariable.class).withParent(PsiCatchSection.class))))); + static final ElementPattern IN_MULTI_CATCH_TYPE = - or(psiElement().afterLeaf(psiElement().withText("|").withParent(PsiTypeElement.class).withSuperParent(2, PsiCatchSection.class)), - psiElement().afterLeaf(psiElement().withText("|").withParent(PsiTypeElement.class).withSuperParent(2, PsiParameter.class) - .withSuperParent(3, PsiCatchSection.class))); + or(psiElement().afterLeaf(psiElement().withText("|"). + withParent(PsiTypeElement.class).withSuperParent(2, PsiCatchSection.class)), + psiElement().afterLeaf(psiElement().withText("|"). + withParent(PsiTypeElement.class).withSuperParent(2, PsiParameter.class).withSuperParent(3, PsiCatchSection.class))); + static final ElementPattern INSIDE_METHOD_THROWS_CLAUSE = psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(psiElement(JavaElementType.THROWS_LIST)); + static final ElementPattern IN_RESOURCE_TYPE = psiElement().withParent(psiElement(PsiJavaCodeReferenceElement.class). withParent(psiElement(PsiTypeElement.class). withParent(or(psiElement(PsiResourceVariable.class), psiElement(PsiResourceList.class))))); + private final CompletionType myCompletionType; private final PsiElement myPosition; private final Set myNonInitializedFields; - @NotNull private final Condition myRequiredSuper; + private final Condition myRequiredSuper; public PreferByKindWeigher(CompletionType completionType, final PsiElement position) { super("kind"); @@ -74,6 +79,7 @@ public class PreferByKindWeigher extends LookupElementWeigher { myRequiredSuper = createSuitabilityCondition(position); } + @NotNull private static Condition createSuitabilityCondition(final PsiElement position) { if (IN_CATCH_TYPE.accepts(position) || IN_MULTI_CATCH_TYPE.accepts(position)) { PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(position, PsiTryStatement.class); diff --git a/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java b/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java index 1d96d87af18f..4182d783380c 100644 --- a/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java +++ b/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java @@ -17,7 +17,6 @@ package com.intellij.psi; import com.intellij.psi.javadoc.*; -@SuppressWarnings({"JavaDoc"}) public abstract class JavaElementVisitor extends PsiElementVisitor { public void visitAnonymousClass(PsiAnonymousClass aClass) { @@ -244,6 +243,7 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { * PsiRecursiveElement visitor works that around and implements this method accordingly. * All other visitor must decide themselves what implementation (visitReferenceElement() or visitExpression() or none or LOG.error()) * is appropriate for them. + * * @param expression */ public void visitReferenceExpression(PsiReferenceExpression expression) {} @@ -308,8 +308,8 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { visitElement(resourceList); } - public void visitResourceVariable(PsiResourceVariable resourceVariable) { - visitLocalVariable(resourceVariable); + public void visitResourceVariable(PsiResourceVariable variable) { + visitLocalVariable(variable); } public void visitTypeElement(PsiTypeElement type) { diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java b/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java index b1b0a1240ed3..da460b2a7929 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -23,7 +23,7 @@ import java.util.List; * Represents a resource list of try-with-resources statement (automatic resource management) introduced in JDK 7. * * @see PsiTryStatement#getResourceList() - * @since 10.5. + * @since 10.5 */ public interface PsiResourceList extends PsiElement { int getResourceVariablesCount(); diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java b/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java index 113d69c321e2..46db75e8438d 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,7 +21,7 @@ import org.jetbrains.annotations.NotNull; * Represents a resource variable of try-with-resources statement (automatic resource management) introduced in JDK 7. * * @see PsiResourceList#getResourceVariables() - * @since 10.5. + * @since 10.5 */ public interface PsiResourceVariable extends PsiLocalVariable { @NotNull diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java index 3f0878c3a18c..3f96b0c1fd41 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -47,7 +47,7 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou } @Override - public void accept(@NotNull final PsiElementVisitor visitor) { + public void accept(@NotNull PsiElementVisitor visitor) { if (visitor instanceof JavaElementVisitor) { ((JavaElementVisitor)visitor).visitResourceList(this); } @@ -57,15 +57,15 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou } @Override - public boolean processDeclarations(@NotNull final PsiScopeProcessor processor, - @NotNull final ResolveState state, - final PsiElement lastParent, - @NotNull final PsiElement place) { + public boolean processDeclarations(@NotNull PsiScopeProcessor processor, + @NotNull ResolveState state, + PsiElement lastParent, + @NotNull PsiElement place) { return PsiImplUtil.processDeclarationsInResourceList(this, processor, state, lastParent); } @Override - public void deleteChildInternal(@NotNull final ASTNode child) { + public void deleteChildInternal(@NotNull ASTNode child) { if (child.getPsi() instanceof PsiResourceVariable && getResourceVariablesCount() == 1) { getTreeParent().deleteChildInternal(this); return; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy index 60b09a41d6b8..1fd04dceac32 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -22,7 +22,7 @@ import org.jetbrains.annotations.NotNull public class Normal17CompletionTest extends LightFixtureCompletionTestCase { @Override protected String getBasePath() { - return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/normal/"; + return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/completion/normal/" } @NotNull @@ -47,7 +47,8 @@ public class Normal17CompletionTest extends LightFixtureCompletionTestCase { assert 'MyOuterResource' == myFixture.lookupElementStrings[0] assert 'MyClass' in myFixture.lookupElementStrings myFixture.type('C\n') - checkResultByFile(getTestName(false) + "_after.java") } + checkResultByFile(getTestName(false) + "_after.java") + } private void doTest() { configureByFile(getTestName(false) + ".java") From a508ffa4d02df5d2a2009f894143958dd9143d2d Mon Sep 17 00:00:00 2001 From: Nikolay Chashnikov Date: Wed, 22 Jul 2015 16:08:22 +0300 Subject: [PATCH 02/41] module management: ensure system independent module file path --- .../src/com/intellij/openapi/module/impl/ModuleManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java index 5aad6723bb1d..f0a0c9b687c6 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java @@ -701,7 +701,7 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project @NotNull public Module newModule(@NotNull String filePath, @NotNull final String moduleTypeId, @Nullable final Map options) { assertWritable(); - filePath = resolveShortWindowsName(filePath); + filePath = FileUtil.toSystemIndependentName(resolveShortWindowsName(filePath)); ModuleEx module = getModuleByFilePath(filePath); if (module == null) { From 56ba5f0fbecc4a227083a37d85f94b303a85cb85 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 22 Jul 2015 16:15:17 +0300 Subject: [PATCH 03/41] IDEA-141904 Consider renaming tabs in Files and Code Templates dialog --- .../platform-resources-en/src/messages/IdeBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 4dceab2e8552..c5fcd9447644 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -136,7 +136,7 @@ title.edit.file.template=Edit File Template checkbox.reformat.according.to.style=Reformat according to style label.description=Description item.file.templates=File templates -tab.filetemplates.templates=Templates +tab.filetemplates.templates=Files tab.filetemplates.includes=Includes tab.filetemplates.code=Code tab.filetemplates.j2ee=Other From 99f166b3c21552769743831d360a5ba94a1f53ec Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 11:34:21 +0200 Subject: [PATCH 04/41] diagnose invalid text offset (EA-64902 - assert: TextRange.) --- .../navigation/CtrlMouseHandler.java | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java index ea96905f470d..3e93f02fc39f 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java @@ -35,6 +35,7 @@ import com.intellij.openapi.actionSystem.impl.ActionButton; import com.intellij.openapi.actionSystem.impl.PresentationFactory; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.AbstractProjectComponent; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; @@ -102,6 +103,7 @@ import java.util.EventObject; import java.util.List; public class CtrlMouseHandler extends AbstractProjectComponent { + private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.navigation.CtrlMouseHandler"); private static final AbstractDocumentationTooltipAction[] ourTooltipActions = {new ShowQuickDocAtPinnedWindowFromTooltipAction()}; private final EditorColorsManager myEditorColorsManager; @@ -382,8 +384,19 @@ public class CtrlMouseHandler extends AbstractProjectComponent { } public Info(@NotNull PsiElement elementAtPointer) { - this(elementAtPointer, Collections.singletonList(new TextRange(elementAtPointer.getTextOffset(), - elementAtPointer.getTextOffset() + elementAtPointer.getTextLength()))); + this(elementAtPointer, Collections.singletonList(getReferenceRange(elementAtPointer))); + } + + @NotNull + private static TextRange getReferenceRange(@NotNull PsiElement elementAtPointer) { + int textOffset = elementAtPointer.getTextOffset(); + final TextRange range = elementAtPointer.getTextRange(); + if (textOffset < range.getStartOffset() || textOffset < 0) { + LOG.error("Invalid text offset " + textOffset + " of element " + elementAtPointer + " of " + elementAtPointer.getClass()); + textOffset = range.getStartOffset(); + } + + return new TextRange(textOffset, range.getEndOffset()); } boolean isSimilarTo(@NotNull Info that) { From 33aec2091abb9b27f09fb210870bb9ea88d307e3 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 12:01:55 +0200 Subject: [PATCH 05/41] import eclipse natures in smart mode (EA-70207 - INRE: FileBasedIndexImpl.handleDumbMode) --- .../idea/eclipse/importWizard/EclipseImportBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java index a83dad199d24..7cb9ca82a35e 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java @@ -31,6 +31,7 @@ import com.intellij.openapi.module.StdModuleTypes; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.impl.ProjectMacrosUtil; import com.intellij.openapi.roots.ModifiableRootModel; @@ -418,10 +419,10 @@ public class EclipseImportBuilder extends ProjectImportBuilder implement if (module2NatureNames.size() == 0) { return; } - ApplicationManager.getApplication().invokeLater(new Runnable() { + StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { @Override public void run() { - StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { + DumbService.getInstance(project).smartInvokeLater(new Runnable() { @Override public void run() { for (EclipseNatureImporter importer : EclipseNatureImporter.EP_NAME.getExtensions()) { From 47d401a667ed12d6ee98c39e161b47bb84767190 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 12:16:30 +0200 Subject: [PATCH 06/41] diagnose invalid parameter type (EA-68590 - PIEAE: PsiUtilCore.ensureValid) --- .../source/resolve/graphInference/InferenceSession.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index ecaa8736d001..2674f9e49b78 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -233,7 +233,14 @@ public class InferenceSession { private static PsiType getParameterType(PsiParameter[] parameters, int i, @Nullable PsiSubstitutor substitutor, boolean varargs) { if (substitutor == null) return null; - PsiType parameterType = substitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType()); + + final PsiParameter parameter = parameters[i < parameters.length ? i : parameters.length - 1]; + final PsiType type = parameter.getType(); + if (!type.isValid()) { + PsiUtil.ensureValidType(type, "Invalid type of parameter " + parameter + " of " + parameter.getClass()); + } + + PsiType parameterType = substitutor.substitute(type); if (parameterType instanceof PsiEllipsisType && varargs) { parameterType = ((PsiEllipsisType)parameterType).getComponentType(); } From 6eae6a5ed242e0d4474ae012ca35e0e6fd3007c7 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 12:32:12 +0200 Subject: [PATCH 07/41] more diagnostics for not surviving PsiAnchor (EA-66622 - assert: SymbolCollectingProcessor$ResultWithContext.getElement) --- .../src/com/intellij/psi/PsiAnchor.java | 42 ++++++++++++++++--- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/PsiAnchor.java b/platform/core-impl/src/com/intellij/psi/PsiAnchor.java index fed8191cd716..17a5c94f3c7d 100644 --- a/platform/core-impl/src/com/intellij/psi/PsiAnchor.java +++ b/platform/core-impl/src/com/intellij/psi/PsiAnchor.java @@ -19,8 +19,11 @@ package com.intellij.psi; import com.intellij.lang.ASTNode; import com.intellij.lang.Language; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.NullableComputable; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; @@ -34,6 +37,7 @@ import com.intellij.psi.stubs.StubElement; import com.intellij.psi.stubs.StubTree; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IStubFileElementType; +import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -436,7 +440,8 @@ public abstract class PsiAnchor { private final int myIndex; private final Language myLanguage; private final IStubElementType myElementType; - private final int myCreationModCount; + private final short myCreationModCount; + private final short myCreationStamp; private StubIndexReference(@NotNull final PsiFile file, final int index, @NotNull Language language, IStubElementType elementType) { myLanguage = language; @@ -444,7 +449,16 @@ public abstract class PsiAnchor { myVirtualFile = file.getVirtualFile(); myProject = file.getProject(); myIndex = index; - myCreationModCount = (int)file.getManager().getModificationTracker().getModificationCount(); + myCreationModCount = getModCount(); + myCreationStamp = (short)file.getModificationStamp(); + } + + private short getModCount() { + final PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker(); + if (myVirtualFile.getName().endsWith(".java")) { + return (short)tracker.getJavaStructureModificationCount(); + } + return (short)tracker.getModificationCount(); } @Override @@ -474,19 +488,35 @@ public abstract class PsiAnchor { } public String diagnoseNull() { + final PsiFile file = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiFile compute() { + return getFile(); + } + }); try { PsiElement element = ApplicationManager.getApplication().runReadAction(new NullableComputable() { @Override public PsiElement compute() { - return restoreFromStubIndex((PsiFileWithStubSupport)getFile(), myIndex, myElementType, true); + return restoreFromStubIndex((PsiFileWithStubSupport)file, myIndex, myElementType, true); } }); return "No diagnostics, element=" + element + "@" + (element == null ? 0 : System.identityHashCode(element)); } catch (AssertionError e) { - return e.getMessage() + - "; current modCount=" + PsiManager.getInstance(getProject()).getModificationTracker().getModificationCount() + - "; creation modCount=" + myCreationModCount; + String msg = e.getMessage(); + msg += "\n current (java)modCount=" + getModCount() + "; creation (java)modCount=" + myCreationModCount; + if (file == null) { + msg += "\n no PSI file"; + } else { + msg += "\n current file stamp=" + (short)file.getModificationStamp() + "; creation file stamp=" + myCreationStamp; + } + final Document document = FileDocumentManager.getInstance().getCachedDocument(myVirtualFile); + if (document != null) { + msg += "\n committed=" + PsiDocumentManager.getInstance(myProject).isCommitted(document); + msg += "\n saved=" + !FileDocumentManager.getInstance().isDocumentUnsaved(document); + } + return msg; } } From bfa1301900b2e57a72d06d7b823b8f2dec1237b1 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 13:39:51 +0200 Subject: [PATCH 08/41] GroovyDirectInheritorsSearcher: honor search parameter flags --- .../impl/GroovyDirectInheritorsSearcher.java | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java index 52fd8cf919a5..fcc4e61c4494 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java @@ -43,11 +43,8 @@ import java.util.List; */ public class GroovyDirectInheritorsSearcher implements QueryExecutor { - public GroovyDirectInheritorsSearcher() { - } - @NotNull - private static List getDerivingClassCandidates(PsiClass clazz, GlobalSearchScope scope) { + private static List getDerivingClassCandidates(PsiClass clazz, GlobalSearchScope scope, boolean includeAnonymous) { final String name = clazz.getName(); if (name == null) return Collections.emptyList(); final ArrayList inheritors = new ArrayList(); @@ -58,16 +55,18 @@ public class GroovyDirectInheritorsSearcher implements QueryExecutor classes = - StubIndex.getElements(GrAnonymousClassIndex.KEY, name, clazz.getProject(), scope, GrAnonymousClassDefinition.class); - for (GrAnonymousClassDefinition aClass : classes) { - inheritors.add(aClass); + if (includeAnonymous) { + final Collection classes = + StubIndex.getElements(GrAnonymousClassIndex.KEY, name, clazz.getProject(), scope, GrAnonymousClassDefinition.class); + for (GrAnonymousClassDefinition aClass : classes) { + inheritors.add(aClass); + } } return inheritors; } @Override - public boolean execute(@NotNull DirectClassInheritorsSearch.SearchParameters queryParameters, @NotNull final Processor consumer) { + public boolean execute(@NotNull final DirectClassInheritorsSearch.SearchParameters queryParameters, @NotNull final Processor consumer) { final PsiClass clazz = queryParameters.getClassToProcess(); final SearchScope scope = queryParameters.getScope(); if (scope instanceof GlobalSearchScope) { @@ -75,21 +74,11 @@ public class GroovyDirectInheritorsSearcher implements QueryExecutor compute() { if (!clazz.isValid()) return Collections.emptyList(); - return getDerivingClassCandidates(clazz, (GlobalSearchScope)scope); + return getDerivingClassCandidates(clazz, (GlobalSearchScope)scope, queryParameters.includeAnonymous()); } }); for (final PsiClass candidate : candidates) { - final boolean isInheritor; - AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock(); - - try { - isInheritor = candidate.isValid() && candidate.isInheritor(clazz, false); - } - finally { - accessToken.finish(); - } - - if (isInheritor) { + if (!queryParameters.isCheckInheritance() || isInheritor(clazz, candidate)) { if (!consumer.process(candidate)) { return false; } @@ -101,4 +90,14 @@ public class GroovyDirectInheritorsSearcher implements QueryExecutor Date: Wed, 22 Jul 2015 13:50:24 +0200 Subject: [PATCH 09/41] ClassInheritorsSearch: remove API not used by kotlin plugin --- .../searches/ClassInheritorsSearch.java | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java index 87cc8e38cb2f..6df92a2494e0 100644 --- a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java +++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java @@ -83,17 +83,6 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory myNameCondition; - private final InheritanceChecker myInheritanceChecker; public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, boolean includeAnonymous) { this(aClass, scope, checkDeep, checkInheritance, includeAnonymous, Conditions.alwaysTrue()); @@ -109,18 +97,12 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory nameCondition) { - this(aClass, scope, checkDeep, checkInheritance, includeAnonymous, nameCondition, InheritanceChecker.DEFAULT); - } - - public SearchParameters(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance, - boolean includeAnonymous, @NotNull final Condition nameCondition, @NotNull InheritanceChecker inheritanceChecker) { myClass = aClass; myScope = scope; myCheckDeep = checkDeep; myCheckInheritance = checkInheritance; myIncludeAnonymous = includeAnonymous; myNameCondition = nameCondition; - myInheritanceChecker = inheritanceChecker; } @NotNull @@ -231,7 +213,7 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory Date: Wed, 22 Jul 2015 14:22:56 +0200 Subject: [PATCH 10/41] move java class inheritor searcher to a separate class in impl --- .../searches/ClassInheritorsSearch.java | 180 +--------------- .../search/JavaClassInheritorsSearcher.java | 200 ++++++++++++++++++ resources/src/META-INF/IdeaPlugin.xml | 1 + 3 files changed, 205 insertions(+), 176 deletions(-) create mode 100644 java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java index 6df92a2494e0..f8b6aa3e5f35 100644 --- a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java +++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java @@ -16,73 +16,24 @@ package com.intellij.psi.search.searches; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.ProgressIndicatorProvider; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.*; -import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.search.PsiSearchScopeUtil; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Conditions; +import com.intellij.psi.PsiClass; import com.intellij.psi.search.SearchScope; -import com.intellij.psi.util.PsiUtilCore; -import com.intellij.reference.SoftReference; -import com.intellij.util.Processor; import com.intellij.util.Query; import com.intellij.util.QueryExecutor; -import com.intellij.util.containers.Stack; -import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.lang.ref.Reference; -import java.util.Set; /** * @author max */ public class ClassInheritorsSearch extends ExtensibleQueryFactory { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.classInheritorsSearch"); - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.search.searches.ClassInheritorsSearch"); - public static final ClassInheritorsSearch INSTANCE = new ClassInheritorsSearch(); - static { - INSTANCE.registerExecutor(new QueryExecutor() { - @Override - public boolean execute(@NotNull final SearchParameters parameters, @NotNull final Processor consumer) { - final PsiClass baseClass = parameters.getClassToProcess(); - final SearchScope searchScope = parameters.getScope(); - - LOG.assertTrue(searchScope != null); - - ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator(); - if (progress != null) { - progress.pushState(); - String className = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public String compute() { - return baseClass.getName(); - } - }); - progress.setText(className != null ? - PsiBundle.message("psi.search.inheritors.of.class.progress", className) : - PsiBundle.message("psi.search.inheritors.progress")); - } - - boolean result = processInheritors(consumer, baseClass, searchScope, parameters); - - if (progress != null) { - progress.popState(); - } - - return result; - } - }); - } - public static class SearchParameters { private final PsiClass myClass; private final SearchScope myScope; @@ -165,127 +116,4 @@ public class ClassInheritorsSearch extends ExtensibleQueryFactory consumer, - @NotNull final PsiClass baseClass, - @NotNull final SearchScope searchScope, - @NotNull final SearchParameters parameters) { - if (baseClass instanceof PsiAnonymousClass || isFinal(baseClass)) return true; - - final String qname = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public String compute() { - return baseClass.getQualifiedName(); - } - }); - if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) { - Project project = PsiUtilCore.getProjectInReadAction(baseClass); - return AllClassesSearch.search(searchScope, project, parameters.getNameCondition()).forEach(new Processor() { - @Override - public boolean process(final PsiClass aClass) { - ProgressIndicatorProvider.checkCanceled(); - final String qname1 = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - @Nullable - public String compute() { - return aClass.getQualifiedName(); - } - }); - return CommonClassNames.JAVA_LANG_OBJECT.equals(qname1) || consumer.process(aClass); - } - }); - } - - final Ref currentBase = Ref.create(null); - final Stack, String>> stack = new Stack, String>>(); - // there are two sets for memory optimization: it's cheaper to hold FQN than PsiClass - final Set processedFqns = new THashSet(); // FQN of processed classes if the class has one - final Set processed = new THashSet(); // processed classes without FQN (e.g. anonymous) - - final Processor processor = new Processor() { - @Override - public boolean process(final PsiClass candidate) { - ProgressIndicatorProvider.checkCanceled(); - - final Ref result = new Ref(); - final String[] fqn = new String[1]; - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - fqn[0] = candidate.getQualifiedName(); - if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) { - if (!candidate.isInheritor(currentBase.get(), false)) { - result.set(true); - return; - } - } - - if (PsiSearchScopeUtil.isInScope(searchScope, candidate)) { - if (candidate instanceof PsiAnonymousClass) { - result.set(consumer.process(candidate)); - } - else { - final String name = candidate.getName(); - if (name != null && parameters.getNameCondition().value(name) && !consumer.process(candidate)) result.set(false); - } - } - } - }); - if (!result.isNull()) return result.get().booleanValue(); - - if (parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass) && !isFinal(candidate)) { - Reference ref = fqn[0] == null ? createHardReference(candidate) : new SoftReference(candidate); - stack.push(Pair.create(ref, fqn[0])); - } - - return true; - } - }; - stack.push(Pair.create(createHardReference(baseClass), qname)); - final GlobalSearchScope projectScope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(baseClass)); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(projectScope.getProject()); - while (!stack.isEmpty()) { - ProgressIndicatorProvider.checkCanceled(); - - Pair, String> pair = stack.pop(); - PsiClass psiClass = pair.getFirst().get(); - final String fqn = pair.getSecond(); - if (psiClass == null) { - psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public PsiClass compute() { - return facade.findClass(fqn, projectScope); - } - }); - if (psiClass == null) continue; - } - if (fqn == null) { - if (!processed.add(psiClass)) continue; - } - else { - if (!processedFqns.add(fqn)) continue; - } - - currentBase.set(psiClass); - if (!DirectClassInheritorsSearch.search(psiClass, projectScope, parameters.isIncludeAnonymous(), false).forEach(processor)) return false; - } - return true; - } - - private static Reference createHardReference(final PsiClass candidate) { - return new SoftReference(candidate){ - @Override - public PsiClass get() { - return candidate; - } - }; - } - - private static boolean isFinal(@NotNull final PsiClass baseClass) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public Boolean compute() { - return Boolean.valueOf(baseClass.hasModifierProperty(PsiModifier.FINAL)); - } - }).booleanValue(); - } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java new file mode 100644 index 000000000000..2c2f254ece1e --- /dev/null +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java @@ -0,0 +1,200 @@ +/* + * Copyright 2000-2015 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.psi.impl.search; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.QueryExecutorBase; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressIndicatorProvider; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; +import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiSearchScopeUtil; +import com.intellij.psi.search.SearchScope; +import com.intellij.psi.search.searches.AllClassesSearch; +import com.intellij.psi.search.searches.ClassInheritorsSearch; +import com.intellij.psi.search.searches.DirectClassInheritorsSearch; +import com.intellij.psi.util.PsiUtilCore; +import com.intellij.reference.SoftReference; +import com.intellij.util.Processor; +import com.intellij.util.containers.Stack; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.Reference; +import java.util.Set; + +public class JavaClassInheritorsSearcher extends QueryExecutorBase { + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.search.JavaClassInheritorsSearcher"); + + @Override + public void processQuery(@NotNull ClassInheritorsSearch.SearchParameters parameters, @NotNull Processor consumer) { + final PsiClass baseClass = parameters.getClassToProcess(); + final SearchScope searchScope = parameters.getScope(); + + LOG.assertTrue(searchScope != null); + + ProgressIndicator progress = ProgressIndicatorProvider.getGlobalProgressIndicator(); + if (progress != null) { + progress.pushState(); + String className = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public String compute() { + return baseClass.getName(); + } + }); + progress.setText(className != null ? + PsiBundle.message("psi.search.inheritors.of.class.progress", className) : + PsiBundle.message("psi.search.inheritors.progress")); + } + + processInheritors(consumer, baseClass, searchScope, parameters); + + if (progress != null) { + progress.popState(); + } + } + + private static void processInheritors(@NotNull final Processor consumer, + @NotNull final PsiClass baseClass, + @NotNull final SearchScope searchScope, + @NotNull final ClassInheritorsSearch.SearchParameters parameters) { + if (baseClass instanceof PsiAnonymousClass || isFinal(baseClass)) return; + + final String qname = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public String compute() { + return baseClass.getQualifiedName(); + } + }); + if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) { + Project project = PsiUtilCore.getProjectInReadAction(baseClass); + AllClassesSearch.search(searchScope, project, parameters.getNameCondition()).forEach(new Processor() { + @Override + public boolean process(final PsiClass aClass) { + ProgressIndicatorProvider.checkCanceled(); + final String qname1 = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + @Nullable + public String compute() { + return aClass.getQualifiedName(); + } + }); + return CommonClassNames.JAVA_LANG_OBJECT.equals(qname1) || consumer.process(aClass); + } + }); + return; + } + + final Ref currentBase = Ref.create(null); + final Stack, String>> stack = new Stack, String>>(); + // there are two sets for memory optimization: it's cheaper to hold FQN than PsiClass + final Set processedFqns = new THashSet(); // FQN of processed classes if the class has one + final Set processed = new THashSet(); // processed classes without FQN (e.g. anonymous) + + final Processor processor = new Processor() { + @Override + public boolean process(final PsiClass candidate) { + ProgressIndicatorProvider.checkCanceled(); + + final Ref result = new Ref(); + final String[] fqn = new String[1]; + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + fqn[0] = candidate.getQualifiedName(); + if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) { + if (!candidate.isInheritor(currentBase.get(), false)) { + result.set(true); + return; + } + } + + if (PsiSearchScopeUtil.isInScope(searchScope, candidate)) { + if (candidate instanceof PsiAnonymousClass) { + result.set(consumer.process(candidate)); + } + else { + final String name = candidate.getName(); + if (name != null && parameters.getNameCondition().value(name) && !consumer.process(candidate)) result.set(false); + } + } + } + }); + if (!result.isNull()) return result.get().booleanValue(); + + if (parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass) && !isFinal(candidate)) { + Reference ref = fqn[0] == null ? createHardReference(candidate) : new SoftReference(candidate); + stack.push(Pair.create(ref, fqn[0])); + } + + return true; + } + }; + stack.push(Pair.create(createHardReference(baseClass), qname)); + final GlobalSearchScope projectScope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(baseClass)); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(projectScope.getProject()); + while (!stack.isEmpty()) { + ProgressIndicatorProvider.checkCanceled(); + + Pair, String> pair = stack.pop(); + PsiClass psiClass = pair.getFirst().get(); + final String fqn = pair.getSecond(); + if (psiClass == null) { + psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public PsiClass compute() { + return facade.findClass(fqn, projectScope); + } + }); + if (psiClass == null) continue; + } + if (fqn == null) { + if (!processed.add(psiClass)) continue; + } + else { + if (!processedFqns.add(fqn)) continue; + } + + currentBase.set(psiClass); + if (!DirectClassInheritorsSearch.search(psiClass, projectScope, parameters.isIncludeAnonymous(), false).forEach(processor)) return; + } + } + + private static Reference createHardReference(final PsiClass candidate) { + return new SoftReference(candidate){ + @Override + public PsiClass get() { + return candidate; + } + }; + } + + private static boolean isFinal(@NotNull final PsiClass baseClass) { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + return Boolean.valueOf(baseClass.hasModifierProperty(PsiModifier.FINAL)); + } + }).booleanValue(); + } + +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index fc7132fd3a79..74d9b8a0282c 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -335,6 +335,7 @@ + From b4ebd444e7a20f339ddb3ae289f5612f3c479447 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 14:41:30 +0200 Subject: [PATCH 11/41] JavaClassInheritorsSearcher: use PsiAnchor for stack, cleanup --- .../search/JavaClassInheritorsSearcher.java | 123 +++++++----------- 1 file changed, 46 insertions(+), 77 deletions(-) diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java index 2c2f254ece1e..7846f74651e2 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaClassInheritorsSearcher.java @@ -17,12 +17,12 @@ package com.intellij.psi.impl.search; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.QueryExecutorBase; +import com.intellij.openapi.application.ReadActionProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; @@ -32,14 +32,11 @@ import com.intellij.psi.search.searches.AllClassesSearch; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.search.searches.DirectClassInheritorsSearch; import com.intellij.psi.util.PsiUtilCore; -import com.intellij.reference.SoftReference; import com.intellij.util.Processor; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Stack; -import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.lang.ref.Reference; import java.util.Set; public class JavaClassInheritorsSearcher extends QueryExecutorBase { @@ -79,113 +76,85 @@ public class JavaClassInheritorsSearcher extends QueryExecutorBase() { - @Override - public String compute() { - return baseClass.getQualifiedName(); - } - }); - if (CommonClassNames.JAVA_LANG_OBJECT.equals(qname)) { - Project project = PsiUtilCore.getProjectInReadAction(baseClass); + Project project = PsiUtilCore.getProjectInReadAction(baseClass); + if (isJavaLangObject(baseClass)) { AllClassesSearch.search(searchScope, project, parameters.getNameCondition()).forEach(new Processor() { @Override public boolean process(final PsiClass aClass) { ProgressIndicatorProvider.checkCanceled(); - final String qname1 = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - @Nullable - public String compute() { - return aClass.getQualifiedName(); - } - }); - return CommonClassNames.JAVA_LANG_OBJECT.equals(qname1) || consumer.process(aClass); + return isJavaLangObject(aClass) || consumer.process(aClass); } }); return; } final Ref currentBase = Ref.create(null); - final Stack, String>> stack = new Stack, String>>(); - // there are two sets for memory optimization: it's cheaper to hold FQN than PsiClass - final Set processedFqns = new THashSet(); // FQN of processed classes if the class has one - final Set processed = new THashSet(); // processed classes without FQN (e.g. anonymous) + final Stack stack = new Stack(); + final Set processed = ContainerUtil.newTroveSet(); - final Processor processor = new Processor() { + final Processor processor = new ReadActionProcessor() { @Override - public boolean process(final PsiClass candidate) { + public boolean processInReadAction(PsiClass candidate) { ProgressIndicatorProvider.checkCanceled(); - final Ref result = new Ref(); - final String[] fqn = new String[1]; - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - fqn[0] = candidate.getQualifiedName(); - if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) { - if (!candidate.isInheritor(currentBase.get(), false)) { - result.set(true); - return; - } - } - - if (PsiSearchScopeUtil.isInScope(searchScope, candidate)) { - if (candidate instanceof PsiAnonymousClass) { - result.set(consumer.process(candidate)); - } - else { - final String name = candidate.getName(); - if (name != null && parameters.getNameCondition().value(name) && !consumer.process(candidate)) result.set(false); - } - } + if (parameters.isCheckInheritance() || parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass)) { + if (!candidate.isInheritor(currentBase.get(), false)) { + return true; } - }); - if (!result.isNull()) return result.get().booleanValue(); - - if (parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass) && !isFinal(candidate)) { - Reference ref = fqn[0] == null ? createHardReference(candidate) : new SoftReference(candidate); - stack.push(Pair.create(ref, fqn[0])); } + if (PsiSearchScopeUtil.isInScope(searchScope, candidate)) { + if (candidate instanceof PsiAnonymousClass) { + return consumer.process(candidate); + } + + final String name = candidate.getName(); + if (name != null && parameters.getNameCondition().value(name) && !consumer.process(candidate)) { + return false; + } + } + + if (parameters.isCheckDeep() && !(candidate instanceof PsiAnonymousClass) && !isFinal(candidate)) { + stack.push(PsiAnchor.create(candidate)); + } return true; } }; - stack.push(Pair.create(createHardReference(baseClass), qname)); - final GlobalSearchScope projectScope = GlobalSearchScope.allScope(PsiUtilCore.getProjectInReadAction(baseClass)); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(projectScope.getProject()); + + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + stack.push(PsiAnchor.create(baseClass)); + } + }); + final GlobalSearchScope projectScope = GlobalSearchScope.allScope(project); + while (!stack.isEmpty()) { ProgressIndicatorProvider.checkCanceled(); - Pair, String> pair = stack.pop(); - PsiClass psiClass = pair.getFirst().get(); - final String fqn = pair.getSecond(); - if (psiClass == null) { - psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { + final PsiAnchor anchor = stack.pop(); + if (!processed.add(anchor)) continue; + + PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable() { @Override public PsiClass compute() { - return facade.findClass(fqn, projectScope); + return (PsiClass)anchor.retrieve(); } }); - if (psiClass == null) continue; - } - if (fqn == null) { - if (!processed.add(psiClass)) continue; - } - else { - if (!processedFqns.add(fqn)) continue; - } + if (psiClass == null) continue; currentBase.set(psiClass); if (!DirectClassInheritorsSearch.search(psiClass, projectScope, parameters.isIncludeAnonymous(), false).forEach(processor)) return; } } - private static Reference createHardReference(final PsiClass candidate) { - return new SoftReference(candidate){ + private static boolean isJavaLangObject(@NotNull final PsiClass baseClass) { + return ApplicationManager.getApplication().runReadAction(new Computable() { @Override - public PsiClass get() { - return candidate; + public Boolean compute() { + return baseClass.isValid() && CommonClassNames.JAVA_LANG_OBJECT.equals(baseClass.getQualifiedName()); } - }; + }); } private static boolean isFinal(@NotNull final PsiClass baseClass) { From 36f19f9ca9f9c45beaf569d90f1b84d9cdc37bca Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 14:56:14 +0200 Subject: [PATCH 12/41] diagnose invalid completion replacement offset (EA-51297 - assert: DocumentImpl.createRangeMarker) --- .../completion/CompletionProgressIndicator.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index f2f5c6640d7a..544711a3613b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -40,6 +40,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Caret; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProcessCanceledException; @@ -56,6 +57,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.ElementPattern; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.ReferenceRange; @@ -229,7 +231,16 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement final int selectionEndOffset = initContext.getSelectionEndOffset(); final PsiReference reference = TargetElementUtil.findReference(myEditor, selectionEndOffset); if (reference != null) { - initContext.setReplacementOffset(findReplacementOffset(selectionEndOffset, reference)); + final int replacementOffset = findReplacementOffset(selectionEndOffset, reference); + final Document document = initContext.getEditor().getDocument(); + if (replacementOffset > document.getTextLength()) { + LOG.error("Invalid replacementOffset: " + replacementOffset + " returned by reference " + reference + " of " + reference.getClass() + + "; doc=" + document + + "; doc actual=" + (document == initContext.getFile().getViewProvider().getDocument()) + + "; doc committed=" + PsiDocumentManager.getInstance(getProject()).isCommitted(document)); + } else { + initContext.setReplacementOffset(replacementOffset); + } } } catch (IndexNotReadyException ignored) { From 836fa1ebdef9563fe50617d86f922bc775565d9c Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 14:57:41 +0200 Subject: [PATCH 13/41] when completing by tab, be prepared to invalid id end offset (EA-45428 - IAE: DocumentImpl.deleteString) --- .../codeInsight/completion/CodeCompletionHandlerBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index a8e13c97b80b..987389bf059c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -691,7 +691,7 @@ public class CodeCompletionHandlerBase { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - if (caretOffset != idEndOffset && completionChar == Lookup.REPLACE_SELECT_CHAR) { + if (caretOffset < idEndOffset && completionChar == Lookup.REPLACE_SELECT_CHAR) { editor.getDocument().deleteString(caretOffset, idEndOffset); } From 193ced8127bcca80c970635c46b23defeebd08cd Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 15:04:25 +0200 Subject: [PATCH 14/41] tolerate completion offsets gone wrong (EA-68152 - assert: DocumentImpl.createRangeMarker) --- .../codeInsight/completion/CodeCompletionHandlerBase.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 987389bf059c..2943c4751911 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -609,6 +609,7 @@ public class CodeCompletionHandlerBase { final Editor hostEditor = InjectedLanguageUtil.getTopLevelEditor(editor); final PsiFile originalFile = indicator.getParameters().getOriginalFile(); final PsiFile hostFile = InjectedLanguageUtil.getTopLevelFile(originalFile); + assert hostFile != null; final OffsetMap hostMap = translateOffsetMapToHost(originalFile, hostFile, hostEditor, indicator.getOffsetMap()); hostEditor.getCaretModel().runForEachCaret(new CaretAction() { @Override @@ -618,9 +619,13 @@ public class CodeCompletionHandlerBase { Editor targetEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(hostEditor, targetFile); int targetCaretOffset = targetEditor.getCaretModel().getOffset(); OffsetMap injectedMap = translateOffsetMapToInjected(hostMap, targetEditor.getDocument()); + int idEnd = targetCaretOffset + idEndOffsetDelta; + if (idEnd > targetEditor.getDocument().getTextLength()) { + idEnd = targetCaretOffset; // no replacement by Tab when offsets gone wrong for some reason + } CompletionAssertions.WatchingInsertionContext currentContext = insertItem(indicator, item, completionChar, items, update, targetEditor, targetFile == null ? hostFile : targetFile, - targetCaretOffset, targetCaretOffset + idEndOffsetDelta, + targetCaretOffset, idEnd, injectedMap); contexts.add(currentContext); } From 78b928fccc44a2e2fa80a8301588a1f4123eaa79 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 15:06:25 +0200 Subject: [PATCH 15/41] correct range when inserting lookup string (EA-55413 - IAE: DocumentImpl.replaceString) --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 63196a62a837..cf243d21e7b9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -536,7 +536,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, public void perform(Caret caret) { EditorModificationUtil.deleteSelectedText(hostEditor); final int caretOffset = hostEditor.getCaretModel().getOffset(); - int lookupStart = Math.max(caretOffset - prefix, 0); + int lookupStart = Math.max(Math.max(caretOffset - prefix, 0), caretOffset); int len = hostEditor.getDocument().getTextLength(); LOG.assertTrue(lookupStart >= 0 && lookupStart <= len, From 96d66a2ca083e3c6f6aefd75fa2df3ced3be257e Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 15:17:38 +0200 Subject: [PATCH 16/41] IDEA-142891 Ignore SLF4J output from Groovy compiler --- .../jps/incremental/groovy/GroovycOutputParser.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOutputParser.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOutputParser.java index ed4a787d8bfa..d1144dcfdcc6 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOutputParser.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovycOutputParser.java @@ -69,7 +69,7 @@ public class GroovycOutputParser { return; } - if (outputType == ProcessOutputTypes.STDERR && !text.startsWith("Picked up JAVA_TOOL_OPTIONS")) { + if (outputType == ProcessOutputTypes.STDERR && !isSafeStderr(text)) { stdErr.append(StringUtil.convertLineSeparators(text)); return; } @@ -78,6 +78,10 @@ public class GroovycOutputParser { parseOutput(text); } + private static boolean isSafeStderr(String line) { + return line.startsWith("SLF4J:") || line.startsWith("Picked up JAVA_TOOL_OPTIONS"); + } + private final StringBuffer outputBuffer = new StringBuffer(); private void updateStatus(@NotNull String status) { From 06ed9a37b7b1d985f6f76392a53c4a6a0df35f5b Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 22 Jul 2015 16:01:53 +0200 Subject: [PATCH 17/41] =?UTF-8?q?Use=20passed=20filepath=20as=20is,=20don'?= =?UTF-8?q?t=20attempt=20to=20use=20absolute=20file=20=E2=80=94=20in=20our?= =?UTF-8?q?=20tests=20we=20don't=20specify=20sometimes=20full=20path=20?= =?UTF-8?q?=E2=80=94=20we=20use=20"foo.iml"=20for=20example.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/intellij/roots/MultiModuleEditingTest.java | 14 +++++++------- .../impl/stores/StateStorageManagerImpl.java | 9 ++++----- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java b/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java index dd156cff1005..44c2597fc576 100644 --- a/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java +++ b/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java @@ -70,8 +70,8 @@ public class MultiModuleEditingTest extends ModuleTestCase { { final ModifiableModuleModel modifiableModel = moduleManager.getModifiableModel(); - moduleA = modifiableModel.newModule(new File("a.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); - moduleB = modifiableModel.newModule(new File("b.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); + moduleA = modifiableModel.newModule("a.iml", StdModuleTypes.JAVA.getId()); + moduleB = modifiableModel.newModule("b.iml", StdModuleTypes.JAVA.getId()); assertEquals("Changes are not applied until commit", 0, moduleManager.getModules().length); //noinspection SSBasedInspection moduleListener.assertCorrectEvents(new String[0][]); @@ -107,8 +107,8 @@ public class MultiModuleEditingTest extends ModuleTestCase { final Module moduleB; { final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel(); - moduleA = moduleModel.newModule(new File("a.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); - moduleB = moduleModel.newModule(new File("b.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); + moduleA = moduleModel.newModule("a.iml", StdModuleTypes.JAVA.getId()); + moduleB = moduleModel.newModule("b.iml", StdModuleTypes.JAVA.getId()); final ModifiableRootModel rootModelA = ModuleRootManager.getInstance(moduleA).getModifiableModel(); final ModifiableRootModel rootModelB = ModuleRootManager.getInstance(moduleB).getModifiableModel(); rootModelB.addModuleOrderEntry(moduleA); @@ -146,9 +146,9 @@ public class MultiModuleEditingTest extends ModuleTestCase { { final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel(); - moduleA = moduleModel.newModule(new File("a.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); - moduleB = moduleModel.newModule(new File("b.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); - final Module moduleC = moduleModel.newModule(new File("c.iml").getAbsolutePath(), StdModuleTypes.JAVA.getId()); + moduleA = moduleModel.newModule("a.iml", StdModuleTypes.JAVA.getId()); + moduleB = moduleModel.newModule("b.iml", StdModuleTypes.JAVA.getId()); + final Module moduleC = moduleModel.newModule("c.iml", StdModuleTypes.JAVA.getId()); final ModifiableRootModel rootModelB = ModuleRootManager.getInstance(moduleB).getModifiableModel(); rootModelB.addModuleOrderEntry(moduleC); moduleModel.disposeModule(moduleC); diff --git a/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java index f5d48c3bd316..af2a65e6550f 100644 --- a/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java +++ b/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java @@ -175,14 +175,13 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di ((MutablePicoContainer)myPicoContainer).registerComponentImplementation(key, storageClass); return (StateStorage)myPicoContainer.getComponentInstance(key); } - final String filePath = expandMacros(fileSpec); - File file = new File(filePath).getAbsoluteFile(); + + String filePath = expandMacros(fileSpec); + File file = new File(filePath); //noinspection deprecation if (!stateSplitter.equals(StateSplitter.class) && !stateSplitter.equals(StateSplitterEx.class)) { - @SuppressWarnings("deprecation") - StateSplitter splitter = ReflectionUtil.newInstance(stateSplitter); - return new DirectoryBasedStorage(myPathMacroSubstitutor, file, splitter, this, createStorageTopicListener()); + return new DirectoryBasedStorage(myPathMacroSubstitutor, file, ReflectionUtil.newInstance(stateSplitter), this, createStorageTopicListener()); } if (!ApplicationManager.getApplication().isHeadlessEnvironment() && PathUtilRt.getFileName(filePath).lastIndexOf('.') < 0) { From d139179915945a3bb0dc6dfc485c5292d6d663f3 Mon Sep 17 00:00:00 2001 From: irengrig Date: Wed, 22 Jul 2015 16:06:44 +0200 Subject: [PATCH 18/41] v8 cpu profiling: filter for cpu diff | top calls diff --- .../components/impl/stores/ModuleStateStorageManager.java | 2 +- .../openapi/components/impl/stores/StateStorageManagerImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java b/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java index 8fe6c9f15444..ced6c3b206cd 100644 --- a/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java +++ b/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/ModuleStateStorageManager.java @@ -25,7 +25,7 @@ import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; -class ModuleStateStorageManager extends StateStorageManagerImpl { +public class ModuleStateStorageManager extends StateStorageManagerImpl { @NonNls private static final String ROOT_TAG_NAME = "module"; private final Module myModule; diff --git a/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java index f5d48c3bd316..1d091eea5238 100644 --- a/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java +++ b/platform/configuration-store-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java @@ -135,7 +135,7 @@ public abstract class StateStorageManagerImpl implements StateStorageManager, Di } @NotNull - public Collection getCachedFileStorages(@NotNull Collection fileSpecs) { + Collection getCachedFileStorages(@NotNull Collection fileSpecs) { if (fileSpecs.isEmpty()) { return Collections.emptyList(); } From e5066f24732648b1bfb44a1f59d9311404f016d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yann=20C=C3=A9bron?= Date: Wed, 22 Jul 2015 16:25:14 +0200 Subject: [PATCH 19/41] temp revert 78b928fccc44 --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index cf243d21e7b9..63196a62a837 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -536,7 +536,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, public void perform(Caret caret) { EditorModificationUtil.deleteSelectedText(hostEditor); final int caretOffset = hostEditor.getCaretModel().getOffset(); - int lookupStart = Math.max(Math.max(caretOffset - prefix, 0), caretOffset); + int lookupStart = Math.max(caretOffset - prefix, 0); int len = hostEditor.getDocument().getTextLength(); LOG.assertTrue(lookupStart >= 0 && lookupStart <= len, From f7f0a5c0c4082c23b93a2acbcbc3af699d4b9844 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 22 Jul 2015 09:54:12 +0200 Subject: [PATCH 20/41] [java] adds support for Java 9's improved try-with-resources (IDEA-140266) PSI, parser, highlighting, exception analysis, control flow, completion. --- .../daemon/impl/analysis/HighlightUtil.java | 56 ++++++++++--- .../impl/analysis/HighlightVisitorImpl.java | 17 +++- .../dataFlow/ControlFlowAnalyzer.java | 23 ++++-- .../completion/PreferByKindWeigher.java | 11 +-- .../com/intellij/psi/JavaElementVisitor.java | 4 + .../intellij/psi/PsiResourceExpression.java | 29 +++++++ .../src/com/intellij/psi/PsiResourceList.java | 7 +- .../intellij/psi/PsiResourceListElement.java | 28 +++++++ .../com/intellij/psi/PsiResourceVariable.java | 4 +- .../src/com/intellij/psi/util/PsiUtil.java | 13 +++- .../intellij/codeInsight/ExceptionUtil.java | 78 ++++++++++--------- .../lang/java/parser/DeclarationParser.java | 12 +++ .../psi/controlFlow/ControlFlowAnalyzer.java | 12 ++- .../com/intellij/psi/impl/PsiImplUtil.java | 8 +- .../psi/impl/source/tree/JavaElementType.java | 1 + .../tree/java/PsiResourceExpressionImpl.java | 55 +++++++++++++ .../source/tree/java/PsiResourceListImpl.java | 13 +++- .../src/messages/JavaErrorMessages.properties | 2 + .../normal/OnlyResourcesInResourceList5.java | 8 ++ .../OnlyResourcesInResourceList5_after.java | 8 ++ .../advHighlighting8/UnsupportedFeatures.java | 8 ++ .../advHighlighting9/TryWithResources.java | 45 +++++++++++ .../annotations/receiverParameters.java | 1 - .../statements/TryIncomplete18.txt | 27 +++++++ .../parser-partial/statements/TryNormal10.txt | 14 ++++ .../parser-partial/statements/TryNormal7.txt | 14 ++++ .../parser-partial/statements/TryNormal8.txt | 15 ++++ .../parser-partial/statements/TryNormal9.txt | 31 ++++++++ .../completion/Normal17CompletionTest.groovy | 1 + .../daemon/LightAdvHighlightingJdk8Test.java | 1 + .../daemon/LightAdvHighlightingJdk9Test.java | 1 + .../parser/partial/StatementParserTest.java | 5 ++ .../com/intellij/psi/util/PsiTreeUtil.java | 25 ++++++ 33 files changed, 491 insertions(+), 86 deletions(-) create mode 100644 java/java-psi-api/src/com/intellij/psi/PsiResourceExpression.java create mode 100644 java/java-psi-api/src/com/intellij/psi/PsiResourceListElement.java create mode 100644 java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceExpressionImpl.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5_after.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/UnsupportedFeatures.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryIncomplete18.txt create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryNormal10.txt create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryNormal8.txt create mode 100644 java/java-tests/testData/psi/parser-partial/statements/TryNormal9.txt diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index cf54d203924f..ffc5c06107b1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -770,16 +770,15 @@ public class HighlightUtil extends HighlightUtilBase { } @Nullable - static HighlightInfo checkUnhandledCloserExceptions(@NotNull final PsiResourceVariable resource) { - final List unhandled = ExceptionUtil.getUnhandledCloserExceptions(resource, null); + static HighlightInfo checkUnhandledCloserExceptions(@NotNull PsiResourceListElement resource) { + List unhandled = ExceptionUtil.getUnhandledCloserExceptions(resource, null); if (unhandled.isEmpty()) return null; - final HighlightInfoType highlightType = getUnhandledExceptionHighlightType(resource); + HighlightInfoType highlightType = getUnhandledExceptionHighlightType(resource); if (highlightType == null) return null; - final String description = getUnhandledExceptionsDescriptor(unhandled, "auto-closeable resource"); - final HighlightInfo highlight = - HighlightInfo.newHighlightInfo(highlightType).range(resource).descriptionAndTooltip(description).create(); + String description = getUnhandledExceptionsDescriptor(unhandled, "auto-closeable resource"); + HighlightInfo highlight = HighlightInfo.newHighlightInfo(highlightType).range(resource).descriptionAndTooltip(description).create(); registerUnhandledExceptionFixes(resource, highlight, unhandled); return highlight; } @@ -1715,15 +1714,49 @@ public class HighlightUtil extends HighlightUtilBase { } @Nullable - static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull final PsiResourceVariable resource) { - final PsiType type = resource.getType(); - final PsiElementFactory factory = JavaPsiFacade.getInstance(resource.getProject()).getElementFactory(); - final PsiClassType autoCloseable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, resource.getResolveScope()); + static HighlightInfo checkTryResourceIsAutoCloseable(@NotNull PsiResourceListElement resource) { + PsiType type = resource.getType(); + if (type == null) return null; + + PsiElementFactory factory = JavaPsiFacade.getInstance(resource.getProject()).getElementFactory(); + PsiClassType autoCloseable = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE, resource.getResolveScope()); if (TypeConversionUtil.isAssignable(autoCloseable, type)) return null; return createIncompatibleTypeHighlightInfo(autoCloseable, type, resource.getTextRange(), 0); } + @Nullable + static HighlightInfo checkResourceVariableIsFinal(@NotNull PsiResourceExpression resource) { + PsiExpression expression = resource.getExpression(); + + if (expression instanceof PsiThisExpression) return null; + + if (expression instanceof PsiReferenceExpression) { + PsiElement target = ((PsiReferenceExpression)expression).resolve(); + if (target == null) return null; + + if (target instanceof PsiVariable) { + PsiVariable variable = (PsiVariable)target; + + PsiModifierList modifierList = variable.getModifierList(); + if (modifierList != null && modifierList.hasModifierProperty(PsiModifier.FINAL)) return null; + + PsiElement scope = null; + if (variable instanceof PsiParameter) scope = ((PsiParameter)variable).getDeclarationScope(); + else if (variable instanceof PsiResourceVariable) scope = variable.getParent().getParent(); + else if (variable instanceof PsiLocalVariable) scope = PsiTreeUtil.getParentOfType(variable, PsiCodeBlock.class); + if (scope != null) { + if (HighlightControlFlowUtil.isEffectivelyFinal(variable, scope, null)) return null; + } + } + + String text = JavaErrorMessages.message("resource.variable.must.be.final"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(text).create(); + } + + return null; + } + @Nullable static Collection checkArrayInitializer(final PsiExpression initializer, PsiType type) { if (!(initializer instanceof PsiArrayInitializerExpression)) return null; @@ -2913,7 +2946,8 @@ public class HighlightUtil extends HighlightUtilBase { METHOD_REFERENCES(LanguageLevel.JDK_1_8, "feature.method.references"), LAMBDA_EXPRESSIONS(LanguageLevel.JDK_1_8, "feature.lambda.expressions"), TYPE_ANNOTATIONS(LanguageLevel.JDK_1_8, "feature.type.annotations"), - RECEIVERS(LanguageLevel.JDK_1_8, "feature.type.receivers"); + RECEIVERS(LanguageLevel.JDK_1_8, "feature.type.receivers"), + REFS_AS_RESOURCE(LanguageLevel.JDK_1_9, "feature.try.with.resources.refs"); private final LanguageLevel level; private final String key; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index d8a756786db2..f2d7c4b22211 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1482,10 +1482,19 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } @Override - public void visitResourceVariable(PsiResourceVariable variable) { - super.visitResourceVariable(variable); - if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(variable)); - if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(variable)); + public void visitResourceVariable(PsiResourceVariable resource) { + super.visitResourceVariable(resource); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource)); + } + + @Override + public void visitResourceExpression(PsiResourceExpression resource) { + super.visitResourceExpression(resource); + if (!myHolder.hasErrorResults()) myHolder.add(checkFeature(resource, Feature.REFS_AS_RESOURCE)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkResourceVariableIsFinal(resource)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resource)); + if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resource)); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 34cf7603cb79..12616fda0607 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -350,8 +350,10 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { else if (parent instanceof PsiTryStatement) { PsiResourceList list = ((PsiTryStatement)parent).getResourceList(); if (list != null) { - for (PsiResourceVariable variable : list.getResourceVariables()) { - myCurrentFlow.removeVariable(variable); + for (PsiResourceListElement resource : list) { + if (resource instanceof PsiResourceVariable) { + myCurrentFlow.removeVariable((PsiVariable)resource); + } } } } @@ -1029,12 +1031,19 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { @Override public void visitResourceList(PsiResourceList resourceList) { - for (PsiResourceVariable variable : resourceList.getResourceVariables()) { - PsiExpression initializer = variable.getInitializer(); - if (initializer != null) { - initializeVariable(variable, initializer); + for (PsiResourceListElement resource : resourceList) { + if (resource instanceof PsiResourceVariable) { + PsiResourceVariable variable = (PsiResourceVariable)resource; + PsiExpression initializer = variable.getInitializer(); + if (initializer != null) { + initializeVariable(variable, initializer); + } } - PsiMethod closer = PsiUtil.getResourceCloserMethod(variable); + else if (resource instanceof PsiResourceExpression) { + ((PsiResourceExpression)resource).getExpression().accept(this); + } + + PsiMethod closer = PsiUtil.getResourceCloserMethod(resource); if (closer != null) { addMethodThrows(closer, null); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index f539c061782e..1e7ddb3eaee8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -61,10 +61,11 @@ public class PreferByKindWeigher extends LookupElementWeigher { static final ElementPattern INSIDE_METHOD_THROWS_CLAUSE = psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(psiElement(JavaElementType.THROWS_LIST)); - static final ElementPattern IN_RESOURCE_TYPE = - psiElement().withParent(psiElement(PsiJavaCodeReferenceElement.class). - withParent(psiElement(PsiTypeElement.class). - withParent(or(psiElement(PsiResourceVariable.class), psiElement(PsiResourceList.class))))); + static final ElementPattern IN_RESOURCE = + psiElement().withParent(or( + psiElement(PsiJavaCodeReferenceElement.class).withParent(PsiTypeElement.class). + withSuperParent(2, or(psiElement(PsiResourceVariable.class), psiElement(PsiResourceList.class))), + psiElement(PsiReferenceExpression.class).withParent(PsiResourceExpression.class))); private final CompletionType myCompletionType; private final PsiElement myPosition; @@ -115,7 +116,7 @@ public class PreferByKindWeigher extends LookupElementWeigher { }; } - if (IN_RESOURCE_TYPE.accepts(position)) { + if (IN_RESOURCE.accepts(position)) { return new Condition() { @Override public boolean value(PsiClass psiClass) { diff --git a/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java b/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java index 4182d783380c..3673dfa283a3 100644 --- a/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java +++ b/java/java-psi-api/src/com/intellij/psi/JavaElementVisitor.java @@ -312,6 +312,10 @@ public abstract class JavaElementVisitor extends PsiElementVisitor { visitLocalVariable(variable); } + public void visitResourceExpression(PsiResourceExpression expression) { + visitElement(expression); + } + public void visitTypeElement(PsiTypeElement type) { visitElement(type); } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResourceExpression.java b/java/java-psi-api/src/com/intellij/psi/PsiResourceExpression.java new file mode 100644 index 000000000000..03488884e0e2 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/psi/PsiResourceExpression.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2015 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.psi; + +import org.jetbrains.annotations.NotNull; + +/** + * Represents a resource expression of enhanced try-with-resources statement introduced in JDK 9. + * + * @see PsiResourceList + * @since 15 + */ +public interface PsiResourceExpression extends PsiResourceListElement { + @NotNull + PsiExpression getExpression(); +} diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java b/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java index da460b2a7929..0f2730e316ba 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiResourceList.java @@ -15,8 +15,6 @@ */ package com.intellij.psi; -import org.jetbrains.annotations.NotNull; - import java.util.List; /** @@ -25,9 +23,10 @@ import java.util.List; * @see PsiTryStatement#getResourceList() * @since 10.5 */ -public interface PsiResourceList extends PsiElement { +public interface PsiResourceList extends PsiElement, Iterable { int getResourceVariablesCount(); - @NotNull + /** @deprecated use {@link #iterator()} (to be removed in IDEA 17) */ + @SuppressWarnings("unused") List getResourceVariables(); } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResourceListElement.java b/java/java-psi-api/src/com/intellij/psi/PsiResourceListElement.java new file mode 100644 index 000000000000..62ef14b73a76 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/psi/PsiResourceListElement.java @@ -0,0 +1,28 @@ +/* + * Copyright 2000-2015 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.psi; + +import org.jetbrains.annotations.Nullable; + +/** + * Common interface for {@link PsiResourceVariable} and {@link PsiResourceExpression}. + * + * @since 15 + */ +public interface PsiResourceListElement extends PsiElement { + @Nullable + PsiType getType(); +} diff --git a/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java b/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java index 46db75e8438d..68023e0a7723 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiResourceVariable.java @@ -20,10 +20,10 @@ import org.jetbrains.annotations.NotNull; /** * Represents a resource variable of try-with-resources statement (automatic resource management) introduced in JDK 7. * - * @see PsiResourceList#getResourceVariables() + * @see PsiResourceList * @since 10.5 */ -public interface PsiResourceVariable extends PsiLocalVariable { +public interface PsiResourceVariable extends PsiLocalVariable, PsiResourceListElement { @NotNull PsiElement[] getDeclarationScope(); } diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index 9e571eeb2ad1..2d7501cf5e8d 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -1126,10 +1126,15 @@ public final class PsiUtil extends PsiUtilCore { } @Nullable - public static PsiMethod getResourceCloserMethod(@NotNull final PsiResourceVariable resource) { - final PsiType resourceType = resource.getType(); - if (!(resourceType instanceof PsiClassType)) return null; - return getResourceCloserMethodForType((PsiClassType)resourceType); + public static PsiMethod getResourceCloserMethod(@NotNull PsiResourceListElement resource) { + PsiType resourceType = resource.getType(); + return resourceType instanceof PsiClassType ? getResourceCloserMethodForType((PsiClassType)resourceType) : null; + } + + /** @deprecated use {@link #getResourceCloserMethod(PsiResourceListElement)} (to be removed in IDEA 17) */ + @SuppressWarnings("unused") + public static PsiMethod getResourceCloserMethod(@NotNull PsiResourceVariable resource) { + return getResourceCloserMethod((PsiResourceListElement)resource); } @Nullable diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java index 15f57c2dd018..6ebe05f9ed08 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/ExceptionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -118,14 +118,19 @@ public class ExceptionUtil { else if (element instanceof PsiTryStatement) { return getTryExceptions((PsiTryStatement)element); } - else if (element instanceof PsiResourceVariable) { - final PsiResourceVariable variable = (PsiResourceVariable)element; - final List types = ContainerUtil.newArrayList(); - addExceptions(types, getCloserExceptions(variable)); - final PsiExpression initializer = variable.getInitializer(); - if (initializer != null) addExceptions(types, getThrownExceptions(initializer)); + else if (element instanceof PsiResourceListElement) { + List types = ContainerUtil.newArrayList(); + addExceptions(types, getCloserExceptions((PsiResourceListElement)element)); + if (element instanceof PsiResourceVariable) { + PsiResourceVariable variable = (PsiResourceVariable)element; + PsiExpression initializer = variable.getInitializer(); + if (initializer != null) { + addExceptions(types, getThrownExceptions(initializer)); + } + } return types; } + return getThrownExceptions(element.getChildren()); } @@ -135,8 +140,8 @@ public class ExceptionUtil { PsiResourceList resourceList = tryStatement.getResourceList(); if (resourceList != null) { - for (PsiResourceVariable variable : resourceList.getResourceVariables()) { - addExceptions(array, getUnhandledCloserExceptions(variable, resourceList)); + for (PsiResourceListElement resource : resourceList) { + addExceptions(array, getUnhandledCloserExceptions(resource, resourceList)); } } @@ -303,16 +308,10 @@ public class ExceptionUtil { } unhandledExceptions = unhandled; } - - if (element instanceof PsiResourceVariable) { - final List unhandled = getUnhandledCloserExceptions((PsiResourceVariable)element, topElement); + else if (element instanceof PsiResourceListElement) { + final List unhandled = getUnhandledCloserExceptions((PsiResourceListElement)element, topElement); if (!unhandled.isEmpty()) { - if (unhandledExceptions == null) { - unhandledExceptions = ContainerUtil.newArrayList(unhandled); - } - else { - unhandledExceptions.addAll(unhandled); - } + unhandledExceptions = ContainerUtil.newArrayList(unhandled); } } @@ -356,6 +355,7 @@ public class ExceptionUtil { @NotNull public static List getUnhandledExceptions(final @NotNull PsiElement[] elements) { final List array = ContainerUtil.newArrayList(); + final PsiElementVisitor visitor = new JavaRecursiveElementWalkingVisitor() { @Override public void visitCallExpression(@NotNull PsiCallExpression expression) { @@ -377,9 +377,15 @@ public class ExceptionUtil { } @Override - public void visitResourceVariable(@NotNull PsiResourceVariable resourceVariable) { - addExceptions(array, getUnhandledCloserExceptions(resourceVariable, null)); - visitElement(resourceVariable); + public void visitResourceVariable(@NotNull PsiResourceVariable resource) { + addExceptions(array, getUnhandledCloserExceptions((PsiResourceListElement)resource, null)); + visitElement(resource); + } + + @Override + public void visitResourceExpression(@NotNull PsiResourceExpression resource) { + addExceptions(array, getUnhandledCloserExceptions(resource, null)); + visitElement(resource); } }; @@ -392,18 +398,6 @@ public class ExceptionUtil { @NotNull public static List getUnhandledExceptions(@NotNull PsiElement element) { - if (element instanceof PsiCallExpression) { - PsiCallExpression expression = (PsiCallExpression)element; - return getUnhandledExceptions(expression, null); - } - else if (element instanceof PsiThrowStatement) { - PsiThrowStatement throwStatement = (PsiThrowStatement)element; - return getUnhandledExceptions(throwStatement, null); - } - else if (element instanceof PsiResourceVariable) { - return getUnhandledCloserExceptions((PsiResourceVariable)element, null); - } - return getUnhandledExceptions(new PsiElement[]{element}); } @@ -532,19 +526,31 @@ public class ExceptionUtil { } @NotNull - public static List getCloserExceptions(@NotNull PsiResourceVariable resource) { + public static List getCloserExceptions(@NotNull PsiResourceListElement resource) { PsiMethod method = PsiUtil.getResourceCloserMethod(resource); PsiSubstitutor substitutor = PsiUtil.resolveGenericsClassInType(resource.getType()).getSubstitutor(); return method != null ? getExceptionsByMethod(method, substitutor, resource) : Collections.emptyList(); } + /** @deprecated use {@link #getCloserExceptions(PsiResourceListElement)} (to be removed in IDEA 16) */ + @SuppressWarnings("unused") + public static List getCloserExceptions(@NotNull PsiResourceVariable resource) { + return getCloserExceptions((PsiResourceListElement)resource); + } + @NotNull - public static List getUnhandledCloserExceptions(@NotNull PsiResourceVariable resource, @Nullable PsiElement topElement) { + public static List getUnhandledCloserExceptions(@NotNull PsiResourceListElement resource, @Nullable PsiElement topElement) { PsiMethod method = PsiUtil.getResourceCloserMethod(resource); PsiSubstitutor substitutor = PsiUtil.resolveGenericsClassInType(resource.getType()).getSubstitutor(); return method != null ? getUnhandledExceptions(method, resource, topElement, substitutor) : Collections.emptyList(); } + /** @deprecated use {@link #getUnhandledCloserExceptions(PsiResourceListElement, PsiElement)} (to be removed in IDEA 16) */ + @SuppressWarnings("unused") + public static List getUnhandledCloserExceptions(@NotNull PsiResourceVariable resource, @Nullable PsiElement topElement) { + return getUnhandledCloserExceptions((PsiResourceListElement)resource, topElement); + } + @NotNull public static List getUnhandledExceptions(@NotNull PsiThrowStatement throwStatement, @Nullable PsiElement topElement) { List unhandled = new SmartList(); @@ -574,7 +580,7 @@ public class ExceptionUtil { if (expression != null) { final PsiType type = expression.getType(); if (type != null) { - return Arrays.asList(type); + return Collections.singletonList(type); } } diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index d916d1d1cf4a..e684dbb76a63 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -48,6 +48,8 @@ public class DeclarationParser { JavaTokenType.RPARENTH, JavaTokenType.LBRACE, JavaTokenType.ARROW); private static final TokenSet TYPE_START = TokenSet.orSet( ElementType.PRIMITIVE_TYPE_BIT_SET, TokenSet.create(JavaTokenType.IDENTIFIER, JavaTokenType.AT)); + private static final TokenSet RESOURCE_EXPRESSIONS = TokenSet.create( + JavaElementType.REFERENCE_EXPRESSION, JavaElementType.THIS_EXPRESSION); private static final String WHITESPACES = "\n\r \t"; private static final String LINE_ENDS = "\n\r"; @@ -575,6 +577,16 @@ public class DeclarationParser { @Nullable public PsiBuilder.Marker parseResource(PsiBuilder builder) { + PsiBuilder.Marker marker = builder.mark(); + + PsiBuilder.Marker expr = myParser.getExpressionParser().parse(builder); + if (expr != null && RESOURCE_EXPRESSIONS.contains(exprType(expr)) && builder.getTokenType() != JavaTokenType.IDENTIFIER) { + marker.done(JavaElementType.RESOURCE_EXPRESSION); + return marker; + } + + marker.rollbackTo(); + return parseListElement(builder, true, false, false, true); } diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java index e75e488f83ea..572e2abc62cf 100644 --- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java +++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -1163,10 +1163,14 @@ class ControlFlowAnalyzer extends JavaElementVisitor { public void visitResourceList(final PsiResourceList resourceList) { startElement(resourceList); - final List resources = resourceList.getResourceVariables(); - for (PsiResourceVariable resource : resources) { + for (PsiResourceListElement resource : resourceList) { ProgressIndicatorProvider.checkCanceled(); - processVariable(resource); + if (resource instanceof PsiResourceVariable) { + processVariable((PsiVariable)resource); + } + else if (resource instanceof PsiResourceExpression) { + ((PsiResourceExpression)resource).getExpression().accept(this); + } } finishElement(resourceList); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index cba5c8d9db02..c483ec6eb576 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -239,11 +239,9 @@ public class PsiImplUtil { final ElementClassHint hint = processor.getHint(ElementClassHint.KEY); if (hint != null && !hint.shouldProcess(ElementClassHint.DeclarationKind.VARIABLE)) return true; - final List resources = resourceList.getResourceVariables(); - @SuppressWarnings({"SuspiciousMethodCalls"}) - final int lastIdx = lastParent instanceof PsiResourceVariable ? resources.indexOf(lastParent) : resources.size(); - for (int i = 0; i < lastIdx; i++) { - if (!processor.execute(resources.get(i), state)) return false; + for (PsiResourceListElement resource : resourceList) { + if (resource == lastParent) break; + if (resource instanceof PsiResourceVariable && !processor.execute(resource, state)) return false; } return true; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java index 237ccb7b2c2b..8f21b751455a 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/JavaElementType.java @@ -133,6 +133,7 @@ public interface JavaElementType { IElementType TRY_STATEMENT = new JavaCompositeElementType("TRY_STATEMENT", PsiTryStatementImpl.class); IElementType RESOURCE_LIST = new JavaCompositeElementType("RESOURCE_LIST", PsiResourceListImpl.class); IElementType RESOURCE_VARIABLE = new JavaCompositeElementType("RESOURCE_VARIABLE", PsiResourceVariableImpl.class); + IElementType RESOURCE_EXPRESSION = new JavaCompositeElementType("RESOURCE_EXPRESSION", PsiResourceExpressionImpl.class); IElementType CATCH_SECTION = new JavaCompositeElementType("CATCH_SECTION", PsiCatchSectionImpl.class); IElementType LABELED_STATEMENT = new JavaCompositeElementType("LABELED_STATEMENT", PsiLabeledStatementImpl.class); IElementType ASSERT_STATEMENT = new JavaCompositeElementType("ASSERT_STATEMENT", PsiAssertStatementImpl.class); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceExpressionImpl.java new file mode 100644 index 000000000000..45311a6840ac --- /dev/null +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceExpressionImpl.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2015 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.psi.impl.source.tree.java; + +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.CompositePsiElement; +import com.intellij.psi.impl.source.tree.JavaElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class PsiResourceExpressionImpl extends CompositePsiElement implements PsiResourceExpression { + public PsiResourceExpressionImpl() { + super(JavaElementType.RESOURCE_EXPRESSION); + } + + @NotNull + @Override + public PsiExpression getExpression() { + return (PsiExpression)getFirstChild(); + } + + @Nullable + @Override + public PsiType getType() { + return getExpression().getType(); + } + + @Override + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JavaElementVisitor) { + ((JavaElementVisitor)visitor).visitResourceExpression(this); + } + else { + visitor.visitElement(this); + } + } + + @Override + public String toString() { + return "PsiResourceExpression"; + } +} diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java index 3f96b0c1fd41..9b66c2c11c84 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiResourceListImpl.java @@ -24,6 +24,7 @@ import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import java.util.Iterator; import java.util.List; public class PsiResourceListImpl extends CompositePsiElement implements PsiResourceList { @@ -35,17 +36,23 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou public int getResourceVariablesCount() { int count = 0; for (PsiElement child = getFirstChild(); child != null; child = child.getNextSibling()) { - if (child instanceof PsiResourceVariable) ++count; + if (child instanceof PsiResourceListElement) ++count; } return count; } - @NotNull + @Deprecated @Override public List getResourceVariables() { return PsiTreeUtil.getChildrenOfTypeAsList(this, PsiResourceVariable.class); } + @NotNull + @Override + public Iterator iterator() { + return PsiTreeUtil.childIterator(this, PsiResourceListElement.class); + } + @Override public void accept(@NotNull PsiElementVisitor visitor) { if (visitor instanceof JavaElementVisitor) { @@ -66,7 +73,7 @@ public class PsiResourceListImpl extends CompositePsiElement implements PsiResou @Override public void deleteChildInternal(@NotNull ASTNode child) { - if (child.getPsi() instanceof PsiResourceVariable && getResourceVariablesCount() == 1) { + if (child.getPsi() instanceof PsiResourceListElement && getResourceVariablesCount() == 1) { getTreeParent().deleteChildInternal(this); return; } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 11f0bc186469..6888379c8844 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -144,6 +144,7 @@ assignment.to.final.variable=Cannot assign a value to final variable ''{0}'' variable.must.be.final=Variable ''{0}'' is accessed from within inner class, needs to be declared final variable.must.be.final.or.effectively.final=Variable ''{0}'' is accessed from within inner class, needs to be final or effectively final lambda.variable.must.be.final=Variable used in lambda expression should be final or effectively final +resource.variable.must.be.final=Variable used as a try-with-resources resource should be final or effectively final initializer.must.be.able.to.complete.normally=Initializer must be able to complete normally weaker.privileges={0}; attempting to assign weaker access privileges (''{1}''); was ''{2}'' incompatible.return.type=attempting to use incompatible return type @@ -397,4 +398,5 @@ feature.method.references=Method references feature.lambda.expressions=Lambda expressions feature.type.annotations=Type annotations feature.type.receivers=Receiver parameters +feature.try.with.resources.refs=Resource references insufficient.language.level={0} are not supported at this language level diff --git a/java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5.java b/java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5.java new file mode 100644 index 000000000000..815cbf239407 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5.java @@ -0,0 +1,8 @@ +class MyClass { + void f() { + String response; + AutoCloseable resource; + try (re) { + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5_after.java b/java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5_after.java new file mode 100644 index 000000000000..41313d5da27c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/OnlyResourcesInResourceList5_after.java @@ -0,0 +1,8 @@ +class MyClass { + void f() { + String response; + AutoCloseable resource; + try (resource) { + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/UnsupportedFeatures.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/UnsupportedFeatures.java new file mode 100644 index 000000000000..67f5e557f090 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting8/UnsupportedFeatures.java @@ -0,0 +1,8 @@ +import java.io.*; + +class UnsupportedFeatures { + void m() throws Exception { + Reader r1 = new FileReader("/dev/null"); + try (r1; Reader r2 = new FileReader("/dev/null")) { } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java new file mode 100644 index 000000000000..06fbe51f4f67 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/TryWithResources.java @@ -0,0 +1,45 @@ +import java.io.IOException; + +class TryWithResources { + final AutoCloseable f1 = null; + AutoCloseable f2 = null; + + void testFields() throws Exception { + try (f1; f2) { } + catch (Exception ignore) { } + } + + void testLocalVars() throws Exception { + final AutoCloseable r1 = null; + AutoCloseable r2 = null; + AutoCloseable r3 = null; + try (r1; r2; r3) { } + r3 = null; + } + + void testType() throws Exception { + String s = ""; + try (s; + this) { } + } + + void testUnhandled() { + class Resource implements AutoCloseable { + @Override public void close() throws IOException { } + } + Resource r = new Resource(); + try (r) { } + } + + void testResolve() throws Exception { + try (r; AutoCloseable r = null) { } + try (AutoCloseable r = null; r) { } + } + + void testUnassigned() throws Exception { + AutoCloseable r; + try (r) { + System.out.println(r); + } + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java index 8bebd698486f..d67833261818 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/receiverParameters.java @@ -15,7 +15,6 @@ class C { @interface Anno { String f(Anno this); } void m0() { - try (Object this) { } Runnable r = (C C.this) -> { }; } diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete18.txt b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete18.txt new file mode 100644 index 000000000000..fce2903d5bd2 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryIncomplete18.txt @@ -0,0 +1,27 @@ +PsiJavaFile:TryIncomplete18.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(R r) + PsiJavaToken:LPARENTH('(') + PsiResourceVariable:r + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiWhiteSpace(' ') + PsiIdentifier:r('r') + PsiErrorElement:'=' expected + + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal10.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal10.txt new file mode 100644 index 000000000000..c43b15ce7234 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal10.txt @@ -0,0 +1,14 @@ +PsiJavaFile:TryNormal10.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(this) + PsiJavaToken:LPARENTH('(') + PsiResourceExpression + PsiThisExpression:this + PsiReferenceParameterList + + PsiKeyword:this('this') + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt new file mode 100644 index 000000000000..aae469326dab --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal7.txt @@ -0,0 +1,14 @@ +PsiJavaFile:TryNormal7.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(r) + PsiJavaToken:LPARENTH('(') + PsiResourceExpression + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal8.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal8.txt new file mode 100644 index 000000000000..8d3c24c247f9 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal8.txt @@ -0,0 +1,15 @@ +PsiJavaFile:TryNormal8.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(r;) + PsiJavaToken:LPARENTH('(') + PsiResourceExpression + PsiReferenceExpression:r + PsiReferenceParameterList + + PsiIdentifier:r('r') + PsiJavaToken:SEMICOLON(';') + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/statements/TryNormal9.txt b/java/java-tests/testData/psi/parser-partial/statements/TryNormal9.txt new file mode 100644 index 000000000000..a5914a682971 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/statements/TryNormal9.txt @@ -0,0 +1,31 @@ +PsiJavaFile:TryNormal9.java + PsiTryStatement + PsiKeyword:try('try') + PsiResourceList:(r1; R r2 = 0) + PsiJavaToken:LPARENTH('(') + PsiResourceExpression + PsiReferenceExpression:r1 + PsiReferenceParameterList + + PsiIdentifier:r1('r1') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiResourceVariable:r2 + PsiModifierList: + + PsiTypeElement:R + PsiJavaCodeReferenceElement:R + PsiIdentifier:R('R') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:r2('r2') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiJavaToken:RPARENTH(')') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy index 1fd04dceac32..3f10302dacee 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/Normal17CompletionTest.groovy @@ -38,6 +38,7 @@ public class Normal17CompletionTest extends LightFixtureCompletionTestCase { public void testOnlyResourcesInResourceList2() { doTest() } public void testOnlyResourcesInResourceList3() { doTest() } public void testOnlyResourcesInResourceList4() { doTest() } + public void testOnlyResourcesInResourceList5() { doTest() } public void testMethodReferenceNoStatic() { doTest() } public void testMethodReferenceCallContext() { doTest() } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk8Test.java index b095a280ab02..dc3c391ef218 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk8Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk8Test.java @@ -48,4 +48,5 @@ public class LightAdvHighlightingJdk8Test extends LightDaemonAnalyzerTestCase { public void testMethodReferences() { doTest(false, true); } public void testUsedMethodsByMethodReferences() { enableInspectionTool(new UnusedDeclarationInspection()); doTest(true, true); } public void testLambdaExpressions() { doTest(false, true); } + public void testUnsupportedFeatures() { doTest(false, false); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java index 8a7f90174498..3a1ceb590e39 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java @@ -46,6 +46,7 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase { public void testSafeVarargsApplicability() { doTest(true, false); } public void testPrivateInInterfaces() { doTest(false, false); } + public void testTryWithResources() { doTest(false, false); } public void testValueTypes() { setLanguageLevel(LanguageLevel.JDK_X); doTest(false, false); } } diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java index eb6992696cb0..a5535eb0971f 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/StatementParserTest.java @@ -122,6 +122,10 @@ public class StatementParserTest extends JavaParsingTestCase { public void testTryNormal4() { doParserTest("try(R r = 0){}"); } public void testTryNormal5() { doParserTest("try(R1 r1 = 1; R2 r2 = 2){}"); } public void testTryNormal6() { doParserTest("try(R r = 0;){}"); } + public void testTryNormal7() { doParserTest("try(r){}"); } + public void testTryNormal8() { doParserTest("try(r;){}"); } + public void testTryNormal9() { doParserTest("try(r1; R r2 = 0){}"); } + public void testTryNormal10() { doParserTest("try(this){}"); } public void testTryIncomplete0() { doParserTest("try"); } public void testTryIncomplete1() { doParserTest("try{}"); } public void testTryIncomplete2() { doParserTest("try{}catch"); } @@ -140,6 +144,7 @@ public class StatementParserTest extends JavaParsingTestCase { public void testTryIncomplete15() { doParserTest("try(R r){}"); } public void testTryIncomplete16() { doParserTest("try(R r =){}"); } public void testTryIncomplete17() { doParserTest("try(R r = 0;;){}"); } + public void testTryIncomplete18() { doParserTest("try(R r){}"); } public void testWhileNormal() { doParserTest("while (true) foo();"); } public void testWhileIncomplete0() { doParserTest("while"); } diff --git a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java index f3cb61eb8ec9..5af86d7649f9 100644 --- a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java +++ b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java @@ -1044,4 +1044,29 @@ public class PsiTreeUtil { return res; } + + @NotNull + public static Iterator childIterator(@NotNull final PsiElement element, @NotNull final Class aClass) { + return new Iterator() { + private T next = getChildOfType(element, aClass); + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public T next() { + if (next == null) throw new NoSuchElementException(); + T current = this.next; + next = getNextSiblingOfType(current, aClass); + return current; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } } From b526a66917de64a37510eac93583ef350203bcad Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 22 Jul 2015 11:31:40 +0200 Subject: [PATCH 21/41] [java] 'remove try/finally' quick fix should not be available in a presence of a resource list --- .../EmptyFinallyBlockInspection.java | 13 ++--- .../com/siyeh/ig/LightInspectionTestCase.java | 44 +++++++++-------- .../EmptyFinallyBlockInspectionTest.java | 49 +++++++++++++++++++ 3 files changed, 76 insertions(+), 30 deletions(-) create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspectionTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java index 4f64120c309a..5abb492c0cee 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspection.java @@ -77,6 +77,10 @@ public class EmptyFinallyBlockInspection extends BaseInspection { if (tryStatement == null) { return; } + final PsiResourceList resources = tryStatement.getResourceList(); + if (resources != null) { + return; + } final PsiCodeBlock tryBlock = tryStatement.getTryBlock(); if (tryBlock == null) { return; @@ -86,15 +90,6 @@ public class EmptyFinallyBlockInspection extends BaseInspection { return; } - final PsiResourceList resources = tryStatement.getResourceList(); - if (resources != null) { - final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); - for (PsiResourceVariable resource : resources.getResourceVariables()) { - final PsiStatement statement = factory.createStatementFromText(resource.getText() + ";", parent); - parent.addBefore(statement, tryStatement); - } - } - final PsiElement first = tryBlock.getFirstBodyElement(); final PsiElement last = tryBlock.getLastBodyElement(); if (first != null && last != null) { diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java index 426af11e8d57..fa85710f0c14 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,6 @@ import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; import org.intellij.lang.annotations.Language; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,26 +43,26 @@ public abstract class LightInspectionTestCase extends LightCodeInsightFixtureTes @Nullable protected abstract InspectionProfileEntry getInspection(); - @NonNls @Language("JAVA") + @SuppressWarnings("LanguageMismatch") protected String[] getEnvironmentClasses() { return ArrayUtil.EMPTY_STRING_ARRAY; } - protected void addEnvironmentClass(@Language("JAVA") @NotNull @NonNls String classText) { + protected void addEnvironmentClass(@Language("JAVA") @NotNull String classText) { myFixture.addClass(classText); } - protected final void doStatementTest(@Language(value="JAVA", prefix="class X { void m() {", suffix="}}") @NotNull @NonNls String statementText) { + protected final void doStatementTest(@Language(value="JAVA", prefix="class X { void m() {", suffix="}}") @NotNull String statementText) { doTest("class X { void m() {" + statementText + "}}"); } - protected final void doMemberTest(@Language(value="JAVA", prefix="class X {", suffix="}") @NotNull @NonNls String memberText) { + protected final void doMemberTest(@Language(value="JAVA", prefix="class X {", suffix="}") @NotNull String memberText) { doTest("class X {" + memberText + "}"); } - protected final void doTest(@Language("JAVA") @NotNull @NonNls String classText) { - @NonNls final StringBuilder newText = new StringBuilder(); + protected final void doTest(@Language("JAVA") @NotNull String classText) { + final StringBuilder newText = new StringBuilder(); int start = 0; int end = classText.indexOf("/*"); while (end >= 0) { @@ -73,11 +72,15 @@ public abstract class LightInspectionTestCase extends LightCodeInsightFixtureTes if (end < 0) { throw new IllegalArgumentException("invalid class text"); } - final String warning = classText.substring(start, end); - if (warning.isEmpty()) { + final String text = classText.substring(start, end); + if (text.isEmpty()) { newText.append(""); - } else { - newText.append(""); + } + else if ("_".equals(text)) { + newText.append(""); + } + else { + newText.append(""); } start = end + 2; end = classText.indexOf("/*", end + 1); @@ -89,20 +92,19 @@ public abstract class LightInspectionTestCase extends LightCodeInsightFixtureTes @Override protected String getBasePath() { - final Class inspectionClass = getInspection().getClass(); - final String className = inspectionClass.getName(); + final InspectionProfileEntry inspection = getInspection(); + assertNotNull("File-based tests should either return an inspection or override this method", inspection); + final String className = inspection.getClass().getName(); final String[] words = className.split("\\."); - @NonNls final StringBuilder basePath = new StringBuilder("/plugins/InspectionGadgets/test/"); + final StringBuilder basePath = new StringBuilder("/plugins/InspectionGadgets/test/"); final int lastWordIndex = words.length - 1; for (int i = 0; i < lastWordIndex; i++) { - final String word = words[i]; + String word = words[i]; if (word.equals("ig")) { - basePath.append("igtest"); + //noinspection SpellCheckingInspection + word = "igtest"; } - else { - basePath.append(word); - } - basePath.append('/'); + basePath.append(word).append('/'); } String lastWord = words[lastWordIndex]; if (lastWord.endsWith("Inspection")) { diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspectionTest.java new file mode 100644 index 000000000000..459ded2da2aa --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyFinallyBlockInspectionTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2000-2015 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.siyeh.ig.errorhandling; + +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.InspectionGadgetsBundle; +import com.siyeh.ig.LightInspectionTestCase; + +public class EmptyFinallyBlockInspectionTest extends LightInspectionTestCase { + @Override + protected InspectionProfileEntry getInspection() { + return new EmptyFinallyBlockInspection(); + } + + @SuppressWarnings("EmptyFinallyBlock") + public void testSimple() { + doTest("class C {\n" + + " void m() throws Exception {\n" + + " try { throw new Exception(); }\n" + + " /*Empty 'finally' block*//*_*/finally/**/ { }\n" + + " }\n" + + "}"); + myFixture.findSingleIntention(InspectionGadgetsBundle.message("remove.try.finally.block.quickfix")); + } + + @SuppressWarnings("EmptyFinallyBlock") + public void testResources() { + doTest("class C {\n" + + " void m() throws Exception {\n" + + " try (AutoCloseable r = null) { throw new Exception(); }\n" + + " /*Empty 'finally' block*//*_*/finally/**/ { }\n" + + " }\n" + + "}"); + myFixture.findSingleIntention(InspectionGadgetsBundle.message("remove.finally.block.quickfix")); + } +} From 569ff3cb71967c880c4accdc5dd7f3fddd82abae Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 22 Jul 2015 14:44:04 +0200 Subject: [PATCH 22/41] Cleanup (heavy highlighting tests converted) --- .../unnecessary_local_variable/C.java | 157 ++++++++++++++++++ .../dataflow/unnecessary_local_vars/C.java | 142 ---------------- .../unnecessary_local_vars/expected.xml | 128 -------------- .../InstanceVariableUninitializedUse.java | 27 ++- .../expected.xml | 4 - .../StaticVariableUninitializedUse.java | 23 ++- .../expected.xml | 24 --- ...nnecessaryLocalVariableInspectionTest.java | 22 +-- ...ariableUninitializedUseInspectionTest.java | 29 +++- ...ariableUninitializedUseInspectionTest.java | 30 +++- 10 files changed, 248 insertions(+), 338 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_variable/C.java delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/expected.xml delete mode 100644 plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/expected.xml diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_variable/C.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_variable/C.java new file mode 100644 index 000000000000..b356ca51be45 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_variable/C.java @@ -0,0 +1,157 @@ +/* + * Copyright 2000-2015 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. + */ +class C { + void m() throws Exception { + String s1 = null; + String s2 = s1, s3 = null; + System.out.println(s2 + s3); + + AutoCloseable r1 = null; + try (AutoCloseable r2 = r1; AutoCloseable r3 = null) { + System.out.println(r2.toString() + r3.toString()); + } + } + + void n() throws Exception { + String s1 = null; + String s2 = s1, s3 = s1; + System.out.println(s2 + s3); + + AutoCloseable r1 = null; + try (AutoCloseable r2 = r1; AutoCloseable r3 = r1) { + System.out.println(r2 + r3); + } + } + + int boxing(Long l) { + long ll = l; + return (int) ll; + } + + public int foo() { + int a = 2; + int b = a; + return b; + } + + public int bar() { + int b = 3; + return b; + } + + public int bar2() throws Exception{ + final Exception b = new Exception(); + throw b; + } + + public int baz() { + int a; + int b = 3; + a = b; + return a; + } + + public int bazoom() { + final int i = foo(); + bar(); + final int value = i; + System.out.println(value); + return 3; + } + + double time() { + double time = 0.0, dt = time - 1.0; + System.out.println(time); + return dt; + } + + double time2() { + double time = 0.0, dt = time - 1.0; + return time; + } + + void time3() { + double time = 0.0, dt = time - 1.0; + double time2 = time; + time2 += 1; + } + + void through() throws Exception { + Exception e2 = instance(), e3 = new RuntimeException(e2); + throw e2; + } + + Exception instance() { + return null; + } + + public void neededResourceVariable(java.io.InputStream in) throws java.io.IOException { + try (java.io.InputStream inn = in) { + final int read = inn.read(); + // do stuff with in + } + } + + int parenthesized() { + final int i = 1 + 2; + return (i); + } + + void parenthesized2() { + final RuntimeException t = new RuntimeException(); + throw (t); + } + + void parenthesized3(int i) { + int j = (i); + } + + void parenthesized4(int k) { + final int j = 1; + k = (j); + } + + void parenthesized5() { + final int j = 1; + int k = (j); + System.out.println(k); + } + + void usedIn8Inner(int j) { + for (int i = 0; i < 7; i++) { + int k = i; + int n = j; + class F { + { + System.out.println(k + n); + } + } + } + } + + void nameShadow(final String name) { + final String child = name; + class A { + void foo(String s){} + } + + A a = new A() { + void foo(String name) { + System.out.println(child); + } + }; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java deleted file mode 100644 index b188ba7ea2ac..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java +++ /dev/null @@ -1,142 +0,0 @@ -class C { - void m() throws Exception { - String s1 = null; - String s2 = s1, s3 = null; - System.out.println(s2 + s3); - - AutoCloseable r1 = null; - try (AutoCloseable r2 = r1; AutoCloseable r3 = null) { - System.out.println(r2.toString() + r3.toString()); - } - } - - void n() throws Exception { - String s1 = null; - String s2 = s1, s3 = s1; - System.out.println(s2 + s3); - - AutoCloseable r1 = null; - try (AutoCloseable r2 = r1; AutoCloseable r3 = r1) { - System.out.println(r2 + r3); - } - } - - int boxing(Long l) { - long ll = l; - return (int) ll; - } - - public int foo() { - int a = 2; - int b = a; - return b; - } - - public int bar() { - int b = 3; - return b; - } - - public int bar2() throws Exception{ - final Exception b = new Exception(); - throw b; - } - - public int baz() { - int a; - int b = 3; - a = b; - return a; - } - - public int bazoom() { - final int i = foo(); - bar(); - final int value = i; - System.out.println(value); - return 3; - } - - double time() { - double time = 0.0, dt = time - 1.0; - System.out.println(time); - return dt; - } - - double time2() { - double time = 0.0, dt = time - 1.0; - return time; - } - - void time3() { - double time = 0.0, dt = time - 1.0; - double time2 = time; - time2 += 1; - } - - void through() throws Exception { - Exception e2 = instance(), e3 = new RuntimeException(e2); - throw e2; - } - - Exception instance() { - return null; - } - - public void neededResourceVariable(java.io.InputStream in) throws java.io.IOException { - try (java.io.InputStream inn = in) { - final int read = inn.read(); - // do stuff with in - } - } - - int parenthesized() { - final int i = 1 + 2; - return (i); - } - - void parenthesized2() { - final RuntimeException t = new RuntimeException(); - throw (t); - } - - void parenthesized3(int i) { - int j = (i); - } - - void parenthesized4(int k) { - final int j = 1; - k = (j); - } - - void parenthesized5() { - final int j = 1; - int k = (j); - System.out.println(k); - } - - void usedIn8Inner(int j) { - for (int i = 0; i < 7; i++) { - int k = i; - int n = j; - class F { - { - System.out.println(k + n); - } - } - } - } - - void nameShadow(final String name) { - final String child = name; - class A { - void foo(String s){} - } - - A a = new A() { - void foo(String name) { - System.out.println(child); - } - }; - } -} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml deleted file mode 100644 index aa7bda34c4c4..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/expected.xml +++ /dev/null @@ -1,128 +0,0 @@ - - - - C.java - 3 - Redundant local variable - Local variable <code>s1</code> is redundant #loc - - - - C.java - 4 - Redundant local variable - Local variable <code>s2</code> is redundant #loc - - - - C.java - 7 - Redundant local variable - Local variable <code>r1</code> is redundant #loc - - - - C.java - 15 - Redundant local variable - Local variable <code>s2</code> is redundant #loc - - - - C.java - 15 - Redundant local variable - Local variable <code>s3</code> is redundant #loc - - - - C.java - 30 - Redundant local variable - Local variable <code>a</code> is redundant #loc - - - - C.java - 31 - Redundant local variable - Local variable <code>b</code> is redundant #loc - - - - C.java - 36 - Redundant local variable - Local variable <code>b</code> is redundant #loc - - - - C.java - 41 - Redundant local variable - Local variable <code>b</code> is redundant #loc - - - - C.java - 47 - Redundant local variable - Local variable <code>b</code> is redundant #loc - - - - C.java - 55 - Redundant local variable - Local variable <code>value</code> is redundant #loc - - - - C.java - 94 - Redundant local variable - Local variable <code>i</code> is redundant #loc - - - - C.java - 99 - Redundant local variable - Local variable <code>t</code> is redundant #loc - - - - C.java - 108 - Redundant local variable - Local variable <code>j</code> is redundant #loc - - - - C.java - 104 - Redundant local variable - Local variable <code>j</code> is redundant #loc - - - - C.java - 113 - Redundant local variable - Local variable <code>j</code> is redundant #loc - - - - C.java - 114 - Redundant local variable - Local variable <code>k</code> is redundant #loc - - - - C.java - 121 - Redundant local variable - Local variable <code>n</code> is redundant #loc - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java index f43884c69be6..99d048471e38 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java @@ -1,22 +1,32 @@ +/* + * Copyright 2000-2015 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.siyeh.igtest.initialization.instance_variable_uninitialized_use; import java.io.IOException; - - - class InstanceVariableUnitializedUse { - int i; - InstanceVariableUnitializedUse() throws IOException { + InstanceVariableUnitializedUse() throws IOException { try (java.io.FileInputStream in = new java.io.FileInputStream("asdf" + (i=3) + "asdf")) {} System.out.println(i); - } } -class InstanceFieldVsDoWhile { +class InstanceFieldVsDoWhile { private Object object; public InstanceFieldVsDoWhile() { @@ -25,11 +35,12 @@ class InstanceFieldVsDoWhile { } while (object.hashCode() < 1000); // Instance field used before initialization } } + class FinalField { private final Object object; FinalField() { - System.out.println(object); + System.out.println(object); object = null; } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/expected.xml deleted file mode 100644 index e8f00e82629f..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/expected.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/StaticVariableUninitializedUse.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/StaticVariableUninitializedUse.java index 72b83d469012..91055e99897f 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/StaticVariableUninitializedUse.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/StaticVariableUninitializedUse.java @@ -1,22 +1,37 @@ +/* + * Copyright 2000-2015 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.siyeh.igtest.initialization.static_variable_uninitialized_use; public class StaticVariableUninitializedUse { - static Integer i; static String s; static { - System.out.println(StaticVariableUninitializedUse.s); + System.out.println(StaticVariableUninitializedUse.s); } + public static void main(String[] args) { if (s instanceof Object) {} - if (i == 42) { + if (i == 42) { System.out.println("Unbelievable"); } System.out.println("only warn once in a method" + i); } static int foo() { - return i; + return i; } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/expected.xml deleted file mode 100644 index f099eb98a6ac..000000000000 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_uninitialized_use/expected.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - StaticVariableUninitializedUse.java - 9 - Static field used before initialization - Static field <code>StaticVariableUninitializedUse.s</code> used before initialization #loc - - - - StaticVariableUninitializedUse.java - 13 - Static field used before initialization - Static field <code>i</code> used before initialization #loc - - - - StaticVariableUninitializedUse.java - 20 - Static field used before initialization - Static field <code>i</code> used before initialization #loc - - \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java index 4efbf1a23d4b..faffd9a83a4f 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -15,22 +15,14 @@ */ package com.siyeh.ig.dataflow; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.roots.LanguageLevelProjectExtension; -import com.intellij.pom.java.LanguageLevel; -import com.intellij.testFramework.IdeaTestUtil; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; -public class UnnecessaryLocalVariableInspectionTest extends IGInspectionTestCase { +public class UnnecessaryLocalVariableInspectionTest extends LightInspectionTestCase { @Override - protected Sdk getTestProjectSdk() { - final Sdk sdk = IdeaTestUtil.getMockJdk17(); - LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.HIGHEST); - return sdk; + protected InspectionProfileEntry getInspection() { + return new UnnecessaryLocalVariableInspection(); } - public void test() throws Exception { - doTest("com/siyeh/igtest/dataflow/unnecessary_local_vars", - new UnnecessaryLocalVariableInspection()); - } + public void test() { doNamedTest("C"); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspectionTest.java index afd90aea2e6f..acfac149b815 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspectionTest.java @@ -1,11 +1,28 @@ +/* + * Copyright 2000-2015 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.siyeh.ig.initialization; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; -public class InstanceVariableUninitializedUseInspectionTest - extends IGInspectionTestCase { - - public void test() throws Exception { - doTest("com/siyeh/igtest/initialization/instance_variable_uninitialized_use", new InstanceVariableUninitializedUseInspection()); +public class InstanceVariableUninitializedUseInspectionTest extends LightInspectionTestCase { + @Override + protected InspectionProfileEntry getInspection() { + return new InstanceVariableUninitializedUseInspection(); } + + public void test() { doNamedTest("InstanceVariableUninitializedUse"); } } diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/StaticVariableUninitializedUseInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/StaticVariableUninitializedUseInspectionTest.java index 3a61f5c07e80..31b6d0e6351c 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/StaticVariableUninitializedUseInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/StaticVariableUninitializedUseInspectionTest.java @@ -1,12 +1,28 @@ +/* + * Copyright 2000-2015 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.siyeh.ig.initialization; -import com.siyeh.ig.IGInspectionTestCase; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.siyeh.ig.LightInspectionTestCase; -public class StaticVariableUninitializedUseInspectionTest - extends IGInspectionTestCase { - - public void test() throws Exception { - doTest("com/siyeh/igtest/initialization/static_variable_uninitialized_use", - new StaticVariableUninitializedUseInspection()); +public class StaticVariableUninitializedUseInspectionTest extends LightInspectionTestCase { + @Override + protected InspectionProfileEntry getInspection() { + return new StaticVariableUninitializedUseInspection(); } + + public void test() { doNamedTest("StaticVariableUninitializedUse"); } } From c5f6925e5bbe79251fc42590aaf074631c25baa7 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 22 Jul 2015 15:26:38 +0200 Subject: [PATCH 23/41] [java] Java 9's try-with-resources in IG/IPP inspections and intentions (IDEA-140266) --- ...nnecessaryLocalVariableInspectionBase.java | 24 +-- .../siyeh/ig/psiutils/EquivalenceChecker.java | 26 +++- .../com/siyeh/ig/psiutils/ExceptionUtils.java | 4 +- .../ig/psiutils/InitializationUtils.java | 10 +- .../psiutils/UninitializedReadCollector.java | 12 +- .../MergeNestedTryStatementsIntention.java | 49 ++---- .../ReplaceArmWithTryFinallyIntention.java | 44 +++--- ...plitTryWithMultipleResourcesIntention.java | 21 +-- .../TryWithMultipleResourcesPredicate.java | 6 +- .../ipp/exceptions/mergeTry/OldStyle.java | 19 --- .../exceptions/mergeTry/OldStyle_after.java | 17 --- .../siyeh/ipp/exceptions/mergeTry/Simple.java | 16 -- .../ipp/exceptions/mergeTry/Simple_after.java | 14 -- .../mergeTry/WithoutAndWithResources.java | 21 --- .../WithoutAndWithResources_after.java | 19 --- .../siyeh/ipp/exceptions/splitTry/Simple.java | 11 -- .../ipp/exceptions/splitTry/Simple_after.java | 13 -- .../ipp/exceptions/splitTry/WithCatch.java | 13 -- .../exceptions/splitTry/WithCatch_after.java | 15 -- ...MergeNestedTryStatementsIntentionTest.java | 139 ++++++++++++++++-- ...ReplaceArmWithTryFinallyIntentionTest.java | 81 ++++++++++ ...TryWithMultipleResourcesIntentionTest.java | 106 +++++++++++-- 22 files changed, 392 insertions(+), 288 deletions(-) delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle_after.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple_after.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources_after.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple_after.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java create mode 100644 plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntentionTest.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java index 015e049ed087..e6e1541fa1da 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/UnnecessaryLocalVariableInspectionBase.java @@ -362,18 +362,20 @@ public class UnnecessaryLocalVariableInspectionBase extends BaseInspection { return false; } boolean referenceFound = false; - for (PsiResourceVariable resourceVariable : resourceList.getResourceVariables()) { - final PsiExpression initializer = resourceVariable.getInitializer(); - if (!referenceFound && initializer instanceof PsiReferenceExpression) { - final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)initializer; - final PsiElement referent = referenceExpression.resolve(); - if (variable.equals(referent)) { - referenceFound = true; - continue; + for (PsiResourceListElement resource : resourceList) { + if (resource instanceof PsiResourceVariable) { + final PsiExpression initializer = ((PsiResourceVariable)resource).getInitializer(); + if (!referenceFound && initializer instanceof PsiReferenceExpression) { + final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)initializer; + final PsiElement referent = referenceExpression.resolve(); + if (variable.equals(referent)) { + referenceFound = true; + continue; + } + } + if (VariableAccessUtils.variableIsUsed(variable, initializer)) { + return false; } - } - if (VariableAccessUtils.variableIsUsed(variable, initializer)) { - return false; } } if (!referenceFound) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java index e6f88ab42457..75b455c8fcd0 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java @@ -17,6 +17,7 @@ package com.siyeh.ig.psiutils; import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -206,16 +207,27 @@ public class EquivalenceChecker { if (resourceList1.getResourceVariablesCount() != resourceList2.getResourceVariablesCount()) { return false; } - final List resourceVariables1 = resourceList1.getResourceVariables(); - final List resourceVariables2 = resourceList2.getResourceVariables(); - for (int i1 = 0, size = resourceVariables1.size(); i1 < size; i1++) { - final PsiResourceVariable variable1 = resourceVariables1.get(i1); - final PsiResourceVariable variable2 = resourceVariables2.get(i1); - if (!localVariablesAreEquivalent(variable1, variable2)) { + final List resources1 = PsiTreeUtil.getChildrenOfTypeAsList(resourceList1, PsiResourceListElement.class); + final List resources2 = PsiTreeUtil.getChildrenOfTypeAsList(resourceList2, PsiResourceListElement.class); + for (int i = 0, size = resources1.size(); i < size; i++) { + final PsiResourceListElement resource1 = resources1.get(i); + final PsiResourceListElement resource2 = resources2.get(i); + if (resource1 instanceof PsiResourceVariable && resource2 instanceof PsiResourceVariable) { + if (!localVariablesAreEquivalent((PsiLocalVariable)resource1, (PsiLocalVariable)resource2)) { + return false; + } + } + else if (resource1 instanceof PsiResourceExpression && resource2 instanceof PsiResourceExpression) { + if (!expressionsAreEquivalent(((PsiResourceExpression)resource1).getExpression(), ((PsiResourceExpression)resource2).getExpression())) { + return false; + } + } + else { return false; } } - } else if (resourceList2 != null) { + } + else if (resourceList2 != null) { return false; } final PsiParameter[] catchParameters1 = statement1.getCatchBlockParameters(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExceptionUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExceptionUtils.java index 2f2166b765e8..fa53af81b2cd 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExceptionUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ExceptionUtils.java @@ -47,8 +47,8 @@ public class ExceptionUtils { if (element == null) return out; if (element instanceof PsiResourceList) { final PsiResourceList resourceList = (PsiResourceList)element; - for (PsiResourceVariable variable : resourceList.getResourceVariables()) { - final PsiMethod method = PsiUtil.getResourceCloserMethod(variable); + for (PsiResourceListElement resource : resourceList) { + final PsiMethod method = PsiUtil.getResourceCloserMethod(resource); collectExceptionsThrown(method, out); } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java index 67c6a32a60f1..53502db00bf3 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/InitializationUtils.java @@ -224,10 +224,12 @@ public class InitializationUtils { @NotNull Set checkedMethods, boolean strict) { final PsiResourceList resourceList = tryStatement.getResourceList(); if (resourceList != null) { - for (PsiResourceVariable resourceVariable : resourceList.getResourceVariables()) { - final PsiExpression initializer = resourceVariable.getInitializer(); - if (expressionAssignsVariableOrFails(initializer, variable, checkedMethods, strict)) { - return true; + for (PsiResourceListElement resource : resourceList) { + if (resource instanceof PsiResourceVariable) { + final PsiExpression initializer = ((PsiResourceVariable)resource).getInitializer(); + if (expressionAssignsVariableOrFails(initializer, variable, checkedMethods, strict)) { + return true; + } } } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/UninitializedReadCollector.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/UninitializedReadCollector.java index 2025bb443f3f..49379ba074b3 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/UninitializedReadCollector.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/UninitializedReadCollector.java @@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.HashSet; -import java.util.List; import java.util.Set; public class UninitializedReadCollector { @@ -222,11 +221,12 @@ public class UninitializedReadCollector { int stamp, @NotNull Set checkedMethods) { final PsiResourceList resourceList = tryStatement.getResourceList(); if (resourceList != null) { - final List resourceVariables = resourceList.getResourceVariables(); - for (PsiResourceVariable resourceVariable : resourceVariables) { - final PsiExpression initializer = resourceVariable.getInitializer(); - if (expressionAssignsVariable(initializer, variable, stamp, checkedMethods)) { - return true; + for (PsiResourceListElement resource : resourceList) { + if (resource instanceof PsiResourceVariable) { + final PsiExpression initializer = ((PsiResourceVariable)resource).getInitializer(); + if (expressionAssignsVariable(initializer, variable, stamp, checkedMethods)) { + return true; + } } } } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntention.java index f5b5344b032c..cce5d1767ef0 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,8 +21,6 @@ import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * @author Bas Leijdekkers */ @@ -39,21 +37,9 @@ public class MergeNestedTryStatementsIntention extends Intention { final PsiTryStatement tryStatement1 = (PsiTryStatement)element.getParent(); final StringBuilder newTryStatement = new StringBuilder("try "); final PsiResourceList list1 = tryStatement1.getResourceList(); - boolean semicolon = false; - boolean resourceList = false; + int resourceCount = 0; if (list1 != null) { - resourceList = true; - newTryStatement.append('('); - final List variables1 = list1.getResourceVariables(); - for (PsiResourceVariable variable : variables1) { - if (semicolon) { - newTryStatement.append(';'); - } - else { - semicolon = true; - } - newTryStatement.append(variable.getText()); - } + resourceCount = appendResources(newTryStatement, resourceCount, list1); } final PsiCodeBlock tryBlock1 = tryStatement1.getTryBlock(); if (tryBlock1 == null) { @@ -66,23 +52,10 @@ public class MergeNestedTryStatementsIntention extends Intention { final PsiTryStatement tryStatement2 = (PsiTryStatement)statements[0]; final PsiResourceList list2 = tryStatement2.getResourceList(); if (list2 != null) { - if (!resourceList) { - newTryStatement.append('('); - } - resourceList = true; - final List variables2 = list2.getResourceVariables(); - for (PsiResourceVariable variable : variables2) { - if (semicolon) { - newTryStatement.append(';'); - } - else { - semicolon = true; - } - newTryStatement.append(variable.getText()); - } + resourceCount = appendResources(newTryStatement, resourceCount, list2); } - if (resourceList) { - newTryStatement.append(")"); + if (resourceCount > 0) { + newTryStatement.append(')'); } final PsiCodeBlock tryBlock2 = tryStatement2.getTryBlock(); if (tryBlock2 == null) { @@ -101,4 +74,14 @@ public class MergeNestedTryStatementsIntention extends Intention { final PsiStatement newStatement = factory.createStatementFromText(newTryStatement.toString(), element); tryStatement1.replace(newStatement); } + + private static int appendResources(StringBuilder newTryStatement, int count, PsiResourceList list) { + for (PsiResourceListElement resource : list) { + if (count == 0) newTryStatement.append('('); + if (count > 0) newTryStatement.append(';'); + newTryStatement.append(resource.getText()); + ++count; + } + return count; + } } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntention.java index fb950a92eeb3..a310250952a4 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntention.java @@ -17,14 +17,14 @@ package com.siyeh.ipp.exceptions; import com.intellij.psi.*; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; import org.jetbrains.annotations.NotNull; import java.util.List; -public class ReplaceArmWithTryFinallyIntention - extends Intention { +public class ReplaceArmWithTryFinallyIntention extends Intention { @NotNull @Override @@ -33,11 +33,9 @@ public class ReplaceArmWithTryFinallyIntention } @Override - protected void processIntention(@NotNull PsiElement element) - throws IncorrectOperationException { + protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException { final PsiJavaToken token = (PsiJavaToken)element; - final PsiTryStatement tryStatement = - (PsiTryStatement)token.getParent(); + final PsiTryStatement tryStatement = (PsiTryStatement)token.getParent(); if (tryStatement == null) { return; } @@ -46,12 +44,17 @@ public class ReplaceArmWithTryFinallyIntention if (resourceList == null) { return; } - final List resourceVariables = - resourceList.getResourceVariables(); + final List resources = ContainerUtil.newArrayList(); final StringBuilder newTryStatement = new StringBuilder("{"); - for (PsiResourceVariable resourceVariable : resourceVariables) { - newTryStatement.append(resourceVariable.getText()); - newTryStatement.append(";\ntry {"); + for (PsiResourceListElement resource : resourceList) { + if (resource instanceof PsiResourceVariable) { + newTryStatement.append(resource.getText()).append(";\n"); + resources.add(((PsiResourceVariable)resource).getName()); + } + else { + resources.add(resource.getText()); + } + newTryStatement.append("try {"); } final PsiCodeBlock tryBlock = tryStatement.getTryBlock(); if (tryBlock == null) { @@ -62,24 +65,15 @@ public class ReplaceArmWithTryFinallyIntention final PsiElement child = children[i]; newTryStatement.append(child.getText()); } - final int resourceVariablesSize = resourceVariables.size(); - for (int i = resourceVariablesSize - 1; i >= 0; i--) { - final PsiResourceVariable resourceVariable = - resourceVariables.get(i); - newTryStatement.append("} finally {\n"); - newTryStatement.append(resourceVariable.getName()); - newTryStatement.append(".close();\n}"); + for (int i = resources.size() - 1; i >= 0; i--) { + newTryStatement.append("} finally {\n").append(resources.get(i)).append(".close();\n}"); } newTryStatement.append('}'); - final PsiElementFactory factory = - JavaPsiFacade.getElementFactory(element.getProject()); - final PsiCodeBlock newCodeBlock = - factory.createCodeBlockFromText( - newTryStatement.toString(), element); + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject()); + final PsiCodeBlock newCodeBlock = factory.createCodeBlockFromText(newTryStatement.toString(), element); if (replaceAll) { for (PsiStatement newStatement : newCodeBlock.getStatements()) { - tryStatement.getParent().addBefore(newStatement, - tryStatement); + tryStatement.getParent().addBefore(newStatement, tryStatement); } tryStatement.delete(); } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java index 9c737926ff50..2977d6b00f05 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,11 +20,8 @@ import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.PsiReplacementUtil; import com.siyeh.ipp.base.Intention; import com.siyeh.ipp.base.PsiElementPredicate; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * @author Bas Leijdekkers */ @@ -43,23 +40,21 @@ public class SplitTryWithMultipleResourcesIntention extends Intention { if (resourceList == null) { return; } - @NonNls final StringBuilder newTryStatementText = new StringBuilder(); - final List variables = resourceList.getResourceVariables(); - boolean braces = false; - for (PsiResourceVariable variable : variables) { - if (braces) { + final StringBuilder newTryStatementText = new StringBuilder(); + int count = 0; + for (PsiResourceListElement resource : resourceList) { + if (count > 0) { newTryStatementText.append("{\n"); - } else { - braces = true; } - newTryStatementText.append("try (").append(variable.getText()).append(")"); + ++count; + newTryStatementText.append("try (").append(resource.getText()).append(")"); } final PsiCodeBlock tryBlock = tryStatement.getTryBlock(); if (tryBlock == null) { return; } newTryStatementText.append(tryBlock.getText()); - for (int i = 1; i < variables.size(); i++) { + for (int i = 1; i < count; i++) { newTryStatementText.append("\n}"); } final PsiCatchSection[] catchSections = tryStatement.getCatchSections(); diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java index 647b56b28a8f..6e2b34ea0a5f 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/TryWithMultipleResourcesPredicate.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,8 +19,6 @@ import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.siyeh.ipp.base.PsiElementPredicate; -import java.util.List; - /** * @author Bas Leijdekkers */ @@ -56,6 +54,6 @@ class TryWithMultipleResourcesPredicate implements PsiElementPredicate { if (tryBlock == null) { return false; } - return resourceList.getResourceVariables().size() > 1; + return resourceList.getResourceVariablesCount() > 1; } } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle.java deleted file mode 100644 index d6e9600d64e2..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.siyeh.ipp.exceptions.mergeTry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; - -class OldStyle { - void foo(File file1) { - try { - try { - FileInputStream in = new FileInputStream(file1); - } catch (FileNotFoundException e) { - // log - } - } catch (Exception e) { - // log - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle_after.java deleted file mode 100644 index 062cf0bb0674..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/OldStyle_after.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.siyeh.ipp.exceptions.mergeTry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; - -class OldStyle { - void foo(File file1) { - try { - FileInputStream in = new FileInputStream(file1); - } catch (FileNotFoundException e) { - // log - } catch (Exception e) { - // log - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple.java deleted file mode 100644 index a51451b43edd..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.siyeh.ipp.exceptions.mergeTry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -public class Simple { - void foo(File file1, File file2) throws IOException { - try (FileInputStream in = new FileInputStream(file1)) { - try (FileOutputStream out = new FileOutputStream(file2)) { - // do something - } - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple_after.java deleted file mode 100644 index 9589542e4a52..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/Simple_after.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.siyeh.ipp.exceptions.mergeTry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -public class Simple { - void foo(File file1, File file2) throws IOException { - try (FileInputStream in = new FileInputStream(file1); FileOutputStream out = new FileOutputStream(file2)) { - // do something - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources.java deleted file mode 100644 index a0655f8b85e7..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.siyeh.ipp.exceptions.mergeTry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; - -class WithoutAndWithResources { - - - void foo(File file) { - try { - try (InputStreamReader reader = - new InputStreamReader(new FileInputStream(file), "utf-8")) { - // do work - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources_after.java deleted file mode 100644 index 6c240d9721cd..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/mergeTry/WithoutAndWithResources_after.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.siyeh.ipp.exceptions.mergeTry; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; - -class WithoutAndWithResources { - - - void foo(File file) { - try (InputStreamReader reader = - new InputStreamReader(new FileInputStream(file), "utf-8")) { - // do work - } catch (IOException e) { - throw new RuntimeException(e); - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple.java deleted file mode 100644 index 25d0048ba039..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.siyeh.ipp.exceptions.splitTry; - -import java.io.*; - -public class Simple { - void foo(File file1, File file2) throws IOException { - try (FileInputStream in = new FileInputStream(file1); FileOutputStream out = new FileOutputStream(file2)) { - - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple_after.java deleted file mode 100644 index 51b243a7748b..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/Simple_after.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.siyeh.ipp.exceptions.splitTry; - -import java.io.*; - -public class Simple { - void foo(File file1, File file2) throws IOException { - try (FileInputStream in = new FileInputStream(file1)) { - try (FileOutputStream out = new FileOutputStream(file2)) { - - } - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java deleted file mode 100644 index 3bdb9a4db5ad..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.siyeh.ipp.exceptions.splitTry; - -import java.io.*; - -public class WithCatch { - void foo(File file1, File file2) { - try (FileInputStream in = new FileInputStream(file1); FileOutputStream out = new FileOutputStream(file2)) { - - } catch (IOException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java deleted file mode 100644 index 08442f0a7203..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/exceptions/splitTry/WithCatch_after.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.siyeh.ipp.exceptions.splitTry; - -import java.io.*; - -public class WithCatch { - void foo(File file1, File file2) { - try (FileInputStream in = new FileInputStream(file1)) { - try (FileOutputStream out = new FileOutputStream(file2)) { - - } - } catch (IOException e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntentionTest.java index 958ba766faab..07e1968b3995 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/MergeNestedTryStatementsIntentionTest.java @@ -1,24 +1,137 @@ +/* + * Copyright 2000-2015 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.siyeh.ipp.exceptions; -import com.siyeh.IntentionPowerPackBundle; -import com.siyeh.ipp.IPPTestCase; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.intellij.lang.annotations.Language; /** * @author Bas Leijdekkers */ -public class MergeNestedTryStatementsIntentionTest extends IPPTestCase { +public class MergeNestedTryStatementsIntentionTest extends LightCodeInsightFixtureTestCase { + public void testSimple() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1, File file2) throws IOException {\n" + + " /*_*/try (FileInputStream in = new FileInputStream(file1)) {\n" + + " try (FileOutputStream out = new FileOutputStream(file2)) {\n" + + " System.out.println(in + \", \" + out);\n" + + " }\n" + + " }\n" + + " }\n" + + "}", - public void testSimple() { doTest(); } - public void testWithoutAndWithResources() { doTest(); } - public void testOldStyle() { doTest(); } - - @Override - protected String getIntentionName() { - return IntentionPowerPackBundle.message("merge.nested.try.statements.intention.name"); + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1, File file2) throws IOException {\n" + + " try (FileInputStream in = new FileInputStream(file1); FileOutputStream out = new FileOutputStream(file2)) {\n" + + " System.out.println(in + \", \" + out);\n" + + " }\n" + + " }\n" + + "}"); } - @Override - protected String getRelativePath() { - return "exceptions/mergeTry"; + public void testWithoutAndWithResources() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file) {\n" + + " /*_*/try {\n" + + " try (InputStreamReader r = new InputStreamReader(new FileInputStream(file), \"utf-8\")) {\n" + + " System.out.println(r);\n" + + " }\n" + + " } catch (IOException e) {\n" + + " throw new RuntimeException(e);\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file) {\n" + + " try (InputStreamReader r = new InputStreamReader(new FileInputStream(file), \"utf-8\")) {\n" + + " System.out.println(r);\n" + + " } catch (IOException e) {\n" + + " throw new RuntimeException(e);\n" + + " }\n" + + " }\n" + + "}"); + } + + @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") + public void testOldStyle() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1) {\n" + + " /*_*/try {\n" + + " try {\n" + + " FileInputStream in = new FileInputStream(file1);\n" + + " } catch (FileNotFoundException e) {\n" + + " // log\n" + + " }\n" + + " } catch (Exception e) {\n" + + " // log\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1) {\n" + + " try {\n" + + " FileInputStream in = new FileInputStream(file1);\n" + + " } catch (FileNotFoundException e) {\n" + + " // log\n" + + " } catch (Exception e) {\n" + + " // log\n" + + " }\n" + + " }\n" + + "}"); + } + + public void testMixedResources() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r1 = new StringReader();\n" + + " /*_*/try (r1) {\n" + + " try (Reader r2 = new StringReader()) {\n" + + " System.out.println(r1 + \", \" + r2);\n" + + " }\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r1 = new StringReader();\n" + + " try (r1; Reader r2 = new StringReader()) {\n" + + " System.out.println(r1 + \", \" + r2);\n" + + " }\n" + + " }\n" + + "}"); + } + + private void doTest(@Language("JAVA") String before, @Language("JAVA") String after) { + myFixture.configureByText("a.java", before.replace("/*_*/", "")); + myFixture.launchAction(myFixture.findSingleIntention(new MergeNestedTryStatementsIntention().getText())); + myFixture.checkResult(after); } } diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntentionTest.java new file mode 100644 index 000000000000..34f7c86ff3c0 --- /dev/null +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/ReplaceArmWithTryFinallyIntentionTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2015 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.siyeh.ipp.exceptions; + +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.intellij.lang.annotations.Language; + +public class ReplaceArmWithTryFinallyIntentionTest extends LightCodeInsightFixtureTestCase { + public void testSimple() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " /*_*/try (Reader r = new StringReader()) {\n" + + " System.out.println(r);\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r = new StringReader();\n" + + " try {\n" + + " System.out.println(r);\n" + + " } finally {\n" + + " r.close();\n" + + " }\n" + + " }\n" + + "}"); + } + + public void testMixedResources() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r1 = new StringReader();\n" + + " /*_*/try (r1; Reader r2 = new StringReader()) {\n" + + " System.out.println(r1 + \", \" + r2);\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r1 = new StringReader();\n" + + " try {\n" + + " Reader r2 = new StringReader();\n" + + " try {\n" + + " System.out.println(r1 + \", \" + r2);\n" + + " } finally {\n" + + " r2.close();\n" + + " }\n" + + " } finally {\n" + + " r1.close();\n" + + " }\n" + + " }\n" + + "}"); + } + + private void doTest(@Language("JAVA") String before, @Language("JAVA") String after) { + myFixture.configureByText("a.java", before.replace("/*_*/", "")); + myFixture.launchAction(myFixture.findSingleIntention(new ReplaceArmWithTryFinallyIntention().getText())); + myFixture.checkResult(after); + } +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java index 61a1fa54a6b2..5458d2032e31 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntentionTest.java @@ -1,23 +1,105 @@ +/* + * Copyright 2000-2015 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.siyeh.ipp.exceptions; -import com.siyeh.IntentionPowerPackBundle; -import com.siyeh.ipp.IPPTestCase; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.intellij.lang.annotations.Language; /** * @author Bas Leijdekkers */ -public class SplitTryWithMultipleResourcesIntentionTest extends IPPTestCase { +public class SplitTryWithMultipleResourcesIntentionTest extends LightCodeInsightFixtureTestCase { + public void testSimple() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1, File file2) throws IOException {\n" + + " /*_*/try (FileInputStream in = new FileInputStream(file1); FileOutputStream out = new FileOutputStream(file2)) {\n" + + " System.out.println(in + \", \" + out);\n" + + " }\n" + + " }\n" + + "}", - public void testSimple() { doTest(); } - public void testWithCatch() { doTest(); } - - @Override - protected String getIntentionName() { - return IntentionPowerPackBundle.message("split.try.with.multiple.resources.intention.name"); + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1, File file2) throws IOException {\n" + + " try (FileInputStream in = new FileInputStream(file1)) {\n" + + " try (FileOutputStream out = new FileOutputStream(file2)) {\n" + + " System.out.println(in + \", \" + out);\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); } - @Override - protected String getRelativePath() { - return "exceptions/splitTry"; + public void testWithCatch() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1, File file2) {\n" + + " try (FileInputStream in = new FileInputStream(file1); /*_*/FileOutputStream out = new FileOutputStream(file2)) {\n" + + " System.out.println(in + \", \" + out);\n" + + " } catch (IOException e) {\n" + + " e.printStackTrace();\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void foo(File file1, File file2) {\n" + + " try (FileInputStream in = new FileInputStream(file1)) {\n" + + " try (FileOutputStream out = new FileOutputStream(file2)) {\n" + + " System.out.println(in + \", \" + out);\n" + + " }\n" + + " } catch (IOException e) {\n" + + " e.printStackTrace();\n" + + " }\n" + + " }\n" + + "}"); + } + + public void testMixedResources() { + doTest( + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r2 = new StringReader();\n" + + " /*_*/try (Reader r1 = new StringReader(); r2) {\n" + + " System.out.println(r1 + \", \" + r2);\n" + + " }\n" + + " }\n" + + "}", + + "import java.io.*;\n" + + "class C {\n" + + " void m() throws Exception {\n" + + " Reader r2 = new StringReader();\n" + + " try (Reader r1 = new StringReader()) {\n" + + " try (r2) {\n" + + " System.out.println(r1 + \", \" + r2);\n" + + " }\n" + + " }\n" + + " }\n" + + "}"); + } + + private void doTest(@Language("JAVA") String before, @Language("JAVA") String after) { + myFixture.configureByText("a.java", before.replace("/*_*/", "")); + myFixture.launchAction(myFixture.findSingleIntention(new SplitTryWithMultipleResourcesIntention().getText())); + myFixture.checkResult(after); } } From 0afda7438991b857a83fd64e3e2030183d107316 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 22 Jul 2015 16:27:37 +0200 Subject: [PATCH 24/41] [java] Java 9's try-with-resources in structural search --- .../impl/matcher/JavaMatchingVisitor.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index d466f7525130..15a8491bd7b9 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2015 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.structuralsearch.impl.matcher; import com.intellij.dupLocator.iterators.ArrayBackedNodeIterator; @@ -1358,11 +1373,11 @@ public class JavaMatchingVisitor extends JavaElementVisitor { myMatchingVisitor.setResult(false); return; } - final List resourceVariables1 = resourceList1.getResourceVariables(); - final List resourceVariables2 = resourceList2.getResourceVariables(); + final List resources1 = PsiTreeUtil.getChildrenOfTypeAsList(resourceList1, PsiResourceListElement.class); + final List resources2 = PsiTreeUtil.getChildrenOfTypeAsList(resourceList2, PsiResourceListElement.class); myMatchingVisitor.setResult(myMatchingVisitor.matchInAnyOrder( - resourceVariables1.toArray(new PsiResourceVariable[resourceVariables1.size()]), - resourceVariables2.toArray(new PsiResourceVariable[resourceVariables2.size()]))); + resources1.toArray(new PsiResourceListElement[resources1.size()]), + resources2.toArray(new PsiResourceListElement[resources2.size()]))); if (!myMatchingVisitor.getResult()) return; } else if (resourceList2 != null){ From 20db2fdffcf2ee47a6eb41dddbbf3346a62ca90c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 22 Jul 2015 15:49:05 +0200 Subject: [PATCH 25/41] extract method: wording to make clear that extract would proceed --- .../extractMethod/ExtractMethodSignatureSuggester.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java index 7be6c5431a5e..07de9a3ddbad 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodSignatureSuggester.java @@ -380,6 +380,7 @@ public class ExtractMethodSignatureSuggester { myDuplicatesNumber = duplicatesNumber; setTitle("Extract Parameters to Replace Duplicates"); setOKButtonText("Accept Signature Change"); + setCancelButtonText("Keep Original Signature"); init(); } From b3d1dc5694f56162377862dd356dfaba5ba1bc3c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 22 Jul 2015 15:52:33 +0200 Subject: [PATCH 26/41] test discovery: prefix testng/junit tests to detect test frameworks which generated the tests --- .../TestDiscoveryConfiguration.java | 3 ++ .../TestDiscoveryConfigurationProducer.java | 12 ++++- .../TestDiscoverySearchHelper.java | 46 ++++++++++++------- .../execution/TestDiscoveryListener.java | 18 +++----- .../JUnitTestDiscoveryConfiguration.java | 8 +++- .../junit4/JUnitTestDiscoveryListener.java | 6 ++- .../TestNGTestDiscoveryConfiguration.java | 8 +++- .../testng/TestNGTestDiscoveryListener.java | 5 ++ 8 files changed, 73 insertions(+), 33 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfiguration.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfiguration.java index 3548ffbf46ad..c7412ed4fbfa 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfiguration.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfiguration.java @@ -219,4 +219,7 @@ public abstract class TestDiscoveryConfiguration extends JavaTestConfigurationBa public String getChangeList() { return myChangeList; } + + @NotNull + public abstract String getFrameworkPrefix(); } diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java index f5bd39cf5434..7437395ae729 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryConfigurationProducer.java @@ -22,6 +22,7 @@ import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.junit.JavaRunConfigurationProducerBase; import com.intellij.execution.testframework.TestSearchScope; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.registry.Registry; @@ -31,6 +32,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.testIntegration.TestFramework; +import com.intellij.util.containers.ContainerUtil; import java.io.IOException; import java.util.Collection; @@ -41,7 +43,7 @@ public abstract class TestDiscoveryConfigurationProducer extends JavaRunConfigur } @Override - protected boolean setupConfigurationFromContext(TestDiscoveryConfiguration configuration, + protected boolean setupConfigurationFromContext(final TestDiscoveryConfiguration configuration, ConfigurationContext configurationContext, Ref ref) { if (!Registry.is("testDiscovery.enabled")) { @@ -56,7 +58,13 @@ public abstract class TestDiscoveryConfigurationProducer extends JavaRunConfigur try { final Collection testsByMethodName = TestDiscoveryIndex .getInstance(configuration.getProject()).getTestsByMethodName(position.first, position.second); - if (testsByMethodName == null || testsByMethodName.isEmpty()) return false; + if (testsByMethodName == null || ContainerUtil.filter(testsByMethodName, new Condition() { + @Override + public boolean value(String s) { + return s.startsWith(configuration.getFrameworkPrefix()); + } + }).isEmpty()) return false; + } catch (IOException e) { return false; diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java index d852e5b20d57..fddb01777669 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoverySearchHelper.java @@ -18,6 +18,7 @@ package com.intellij.execution.testDiscovery; import com.intellij.codeInsight.actions.FormatChangedTextUtil; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vcs.changes.Change; @@ -27,6 +28,7 @@ import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,17 +37,14 @@ import java.io.IOException; import java.util.*; public class TestDiscoverySearchHelper { - public static Set search(final Project project, final Pair position, final String changeList) { + public static Set search(final Project project, + final Pair position, + final String changeList, + final String frameworkPrefix) { final Set patterns = new LinkedHashSet(); if (position != null) { try { - final Collection testsByMethodName = TestDiscoveryIndex - .getInstance(project).getTestsByMethodName(position.first, position.second); - if (testsByMethodName != null) { - for (String pattern : testsByMethodName) { - patterns.add(pattern.replace('-', ',')); - } - } + collectPatterns(project, patterns, position.first, position.second, frameworkPrefix); } catch (IOException ignore) { } @@ -73,7 +72,7 @@ public class TestDiscoverySearchHelper { methods.add(containingMethod); } for (PsiMethod changedMethod : methods) { - final LinkedHashSet detectedPatterns = collectPatterns(changedMethod); + final LinkedHashSet detectedPatterns = collectPatterns(changedMethod, frameworkPrefix); if (detectedPatterns != null) { patterns.addAll(detectedPatterns); } @@ -90,6 +89,25 @@ public class TestDiscoverySearchHelper { return patterns; } + private static void collectPatterns(final Project project, + final Set patterns, + final String classFQName, + final String methodName, + final String frameworkId) throws IOException { + final Collection testsByMethodName = TestDiscoveryIndex + .getInstance(project).getTestsByMethodName(classFQName, methodName); + if (testsByMethodName != null) { + for (String pattern : ContainerUtil.filter(testsByMethodName, new Condition() { + @Override + public boolean value(String s) { + return s.startsWith(frameworkId); + } + })) { + patterns.add(pattern.substring(frameworkId.length()).replace('-', ',')); + } + } + } + @NotNull private static List getAffectedFiles(String changeListName, Project project) { final ChangeListManager changeListManager = ChangeListManager.getInstance(project); @@ -115,20 +133,14 @@ public class TestDiscoverySearchHelper { } @Nullable - private static LinkedHashSet collectPatterns(PsiMethod psiMethod) { + private static LinkedHashSet collectPatterns(PsiMethod psiMethod, String frameworkId) { LinkedHashSet patterns = new LinkedHashSet(); final PsiClass containingClass = psiMethod.getContainingClass(); if (containingClass != null) { final String qualifiedName = containingClass.getQualifiedName(); if (qualifiedName != null) { try { - final Collection testsByMethodName - = TestDiscoveryIndex.getInstance(containingClass.getProject()).getTestsByMethodName(qualifiedName, psiMethod.getName()); - if (testsByMethodName != null) { - for (String pattern : testsByMethodName) { - patterns.add(pattern.replace('-', ',')); - } - } + collectPatterns(psiMethod.getProject(), patterns, qualifiedName, psiMethod.getName(), frameworkId); } catch (IOException e) { return null; diff --git a/java/java-runtime/src/com/intellij/execution/TestDiscoveryListener.java b/java/java-runtime/src/com/intellij/execution/TestDiscoveryListener.java index 11730f119a99..7d33ce1ec650 100644 --- a/java/java-runtime/src/com/intellij/execution/TestDiscoveryListener.java +++ b/java/java-runtime/src/com/intellij/execution/TestDiscoveryListener.java @@ -17,10 +17,11 @@ package com.intellij.execution; import java.lang.reflect.Method; -public class TestDiscoveryListener { +public abstract class TestDiscoveryListener { + public abstract String getFrameworkId(); public void testStarted(String className, String methodName) { - final Object data = getData(); try { + final Object data = getData(); Method testStarted = data.getClass().getMethod("testStarted", new Class[] {String.class}); testStarted.invoke(data, new Object[] {className + "-" + methodName}); } catch (Throwable t) { @@ -29,24 +30,19 @@ public class TestDiscoveryListener { } public void testFinished(String className, String methodName) { - final Object data = getData(); try { + final Object data = getData(); Method testEnded = data.getClass().getMethod("testEnded", new Class[] {String.class}); - testEnded.invoke(data, new Object[] {className + "-" + methodName}); + testEnded.invoke(data, new Object[] {getFrameworkId() + className + "-" + methodName}); } catch (Throwable t) { t.printStackTrace(); } } - protected Object getData() { - try { - return Class.forName("org.jetbrains.testme.instrumentation.ProjectData") + protected Object getData() throws Exception { + return Class.forName("org.jetbrains.testme.instrumentation.ProjectData") .getMethod("getProjectData", new Class[0]) .invoke(null, new Object[0]); - - } catch (Exception e) { - return null; //should not happen - } } public void testRunStarted(String name) {} diff --git a/plugins/junit/src/com/intellij/execution/junit/testDiscovery/JUnitTestDiscoveryConfiguration.java b/plugins/junit/src/com/intellij/execution/junit/testDiscovery/JUnitTestDiscoveryConfiguration.java index 5d4fbdc3993a..4605b9959ea5 100644 --- a/plugins/junit/src/com/intellij/execution/junit/testDiscovery/JUnitTestDiscoveryConfiguration.java +++ b/plugins/junit/src/com/intellij/execution/junit/testDiscovery/JUnitTestDiscoveryConfiguration.java @@ -61,6 +61,12 @@ public class JUnitTestDiscoveryConfiguration extends TestDiscoveryConfiguration return null; } + @NotNull + @Override + public String getFrameworkPrefix() { + return "j"; + } + private class JUnitTestDiscoveryRunnableState extends TestObject { public JUnitTestDiscoveryRunnableState(ExecutionEnvironment environment) { super(((JUnitConfiguration)myDelegate), environment); @@ -71,7 +77,7 @@ public class JUnitTestDiscoveryConfiguration extends TestDiscoveryConfiguration return new SearchForTestsTask(getProject(), myServerSocket) { @Override protected void search() throws ExecutionException { - final Set patterns = TestDiscoverySearchHelper.search(getProject(), getPosition(), getChangeList()); + final Set patterns = TestDiscoverySearchHelper.search(getProject(), getPosition(), getChangeList(), getFrameworkPrefix()); addClassesListToJavaParameters(patterns, FunctionUtil.id(), "", false, getJavaParameters()); } diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnitTestDiscoveryListener.java b/plugins/junit_rt/src/com/intellij/junit4/JUnitTestDiscoveryListener.java index 609f84a4c8cc..b72d225899f3 100644 --- a/plugins/junit_rt/src/com/intellij/junit4/JUnitTestDiscoveryListener.java +++ b/plugins/junit_rt/src/com/intellij/junit4/JUnitTestDiscoveryListener.java @@ -18,4 +18,8 @@ package com.intellij.junit4; import com.intellij.execution.TestDiscoveryListener; import com.intellij.rt.execution.junit.IDEAJUnitListenerEx; -public class JUnitTestDiscoveryListener extends TestDiscoveryListener implements IDEAJUnitListenerEx {} +public class JUnitTestDiscoveryListener extends TestDiscoveryListener implements IDEAJUnitListenerEx { + public String getFrameworkId() { + return "j"; + } +} diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/testDiscovery/TestNGTestDiscoveryConfiguration.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/testDiscovery/TestNGTestDiscoveryConfiguration.java index d6234376b4df..5406f280093f 100644 --- a/plugins/testng/src/com/theoryinpractice/testng/configuration/testDiscovery/TestNGTestDiscoveryConfiguration.java +++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/testDiscovery/TestNGTestDiscoveryConfiguration.java @@ -65,6 +65,12 @@ public class TestNGTestDiscoveryConfiguration extends TestDiscoveryConfiguration return null; } + @NotNull + @Override + public String getFrameworkPrefix() { + return "g"; + } + private class TestNGTestDiscoveryRunnableState extends TestNGRunnableState { public TestNGTestDiscoveryRunnableState(ExecutionEnvironment environment) { super(environment, ((TestNGConfiguration)myDelegate)); @@ -76,7 +82,7 @@ public class TestNGTestDiscoveryConfiguration extends TestDiscoveryConfiguration @Override protected void search() throws CantRunException { myClasses.clear(); - final Set patterns = TestDiscoverySearchHelper.search(getProject(), getPosition(), getChangeList()); + final Set patterns = TestDiscoverySearchHelper.search(getProject(), getPosition(), getChangeList(), getFrameworkPrefix()); final Module module = getConfigurationModule().getModule(); final GlobalSearchScope searchScope = module != null ? GlobalSearchScope.moduleWithDependenciesScope(module) : GlobalSearchScope.projectScope(getProject()); diff --git a/plugins/testng_rt/src/org/testng/TestNGTestDiscoveryListener.java b/plugins/testng_rt/src/org/testng/TestNGTestDiscoveryListener.java index 3dd69dacd85b..64b318a448a0 100644 --- a/plugins/testng_rt/src/org/testng/TestNGTestDiscoveryListener.java +++ b/plugins/testng_rt/src/org/testng/TestNGTestDiscoveryListener.java @@ -53,4 +53,9 @@ public class TestNGTestDiscoveryListener extends TestDiscoveryListener implement public void onFinish(ISuite suite) { testRunFinished(suite.getName()); } + + @Override + public String getFrameworkId() { + return "g"; + } } From 67327364e5187796e8811d70f33f7bc322630f5d Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 22 Jul 2015 17:42:36 +0300 Subject: [PATCH 27/41] maven importing: dispose modifiable models if exception is thrown to avoid many failures in tests --- .../maven/importing/MavenProjectImporter.java | 47 +++++++++++++------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java index 2fb6d9c0ab0a..9ee85b83fcc5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java @@ -17,9 +17,11 @@ package org.jetbrains.idea.maven.importing; import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.LibraryOrderEntry; import com.intellij.openapi.roots.ModifiableRootModel; @@ -52,6 +54,7 @@ import java.io.IOException; import java.util.*; public class MavenProjectImporter { + private static final Logger LOG = Logger.getInstance(MavenProjectImporter.class); private final Project myProject; private final MavenProjectsTree myProjectsTree; private final Map myFileToModuleMapping; @@ -118,17 +121,25 @@ public class MavenProjectImporter { if (myProject.isDisposed()) return null; - boolean modulesDeleted = deleteObsoleteModules(); - hasChanges |= modulesDeleted; - if (hasChanges) { - removeUnusedProjectLibraries(); + try { + boolean modulesDeleted = deleteObsoleteModules(); + hasChanges |= modulesDeleted; + if (hasChanges) { + removeUnusedProjectLibraries(); + } + } + catch (ProcessCanceledException e) { + throw e; + } + catch (Exception e) { + disposeModifiableModels(); + LOG.error(e); + return null; } - final boolean finalHasChanges = hasChanges; - - MavenUtil.invokeAndWaitWriteAction(myProject, new Runnable() { - public void run() { - if (finalHasChanges) { + if (hasChanges) { + MavenUtil.invokeAndWaitWriteAction(myProject, new Runnable() { + public void run() { myModelsProvider.commit(); if (projectsHaveChanges) { @@ -146,15 +157,23 @@ public class MavenProjectImporter { } } } - else { - myModelsProvider.dispose(); - } - } - }); + }); + } + else { + disposeModifiableModels(); + } return postTasks; } + private void disposeModifiableModels() { + MavenUtil.invokeAndWaitWriteAction(myProject, new Runnable() { + public void run() { + myModelsProvider.dispose(); + } + }); + } + private boolean projectsToImportHaveChanges() { for (MavenProjectChanges each : myProjectsToImportWithChanges.values()) { if (each.hasChanges()) return true; From 0039f2498b6537485219b6bbcd4ca13bc5e12acf Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 16:39:17 +0200 Subject: [PATCH 28/41] remove some hard references to lookup elements during completion --- .../codeInsight/completion/CompletionService.java | 11 ++++------- .../completion/CompletionProgressIndicator.java | 8 +++----- .../intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionService.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionService.java index cfc2e27a8179..d8f61a9535a7 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionService.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionService.java @@ -20,12 +20,12 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.util.Key; import com.intellij.psi.Weigher; import com.intellij.util.Consumer; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; -import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; /** * For completion FAQ, see {@link CompletionContributor}. @@ -103,11 +103,9 @@ public abstract class CompletionService { * The main method that is invoked to collect all the completion variants * @param parameters Parameters specifying current completion environment * @param consumer This consumer will directly add lookup elements to the lookup - * @return all suitable lookup elements */ - @NotNull - public LookupElement[] performCompletion(final CompletionParameters parameters, final Consumer consumer) { - final Collection lookupSet = new LinkedHashSet(); + public void performCompletion(final CompletionParameters parameters, final Consumer consumer) { + final Set lookupSet = ContainerUtil.newConcurrentSet(); getVariantsFromContributors(parameters, null, new Consumer() { @Override @@ -117,7 +115,6 @@ public abstract class CompletionService { } } }); - return lookupSet.toArray(new LookupElement[lookupSet.size()]); } public abstract CompletionSorter defaultSorter(CompletionParameters parameters, PrefixMatcher matcher); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index 544711a3613b..8b40766a4244 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -132,7 +132,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement private volatile boolean myHasPsiElements; private boolean myLookupUpdated; private final ConcurrentMap myItemSorters = - ContainerUtil.newConcurrentMap(ContainerUtil.identityStrategy()); + ContainerUtil.createConcurrentWeakMap(ContainerUtil.identityStrategy()); private final PropertyChangeListener myLookupManagerListener; private final Queue myAdvertiserChanges = new ConcurrentLinkedQueue(); private final List myDelayedMiddleMatches = ContainerUtil.newArrayList(); @@ -829,17 +829,15 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement strategy.startThread(this, new CalculateItems()); } - private LookupElement[] calculateItems(CompletionInitializationContext initContext, WeighingDelegate weigher) { + private void calculateItems(CompletionInitializationContext initContext, WeighingDelegate weigher) { duringCompletion(initContext); ProgressManager.checkCanceled(); - LookupElement[] result = CompletionService.getCompletionService().performCompletion(myParameters, weigher); + CompletionService.getCompletionService().performCompletion(myParameters, weigher); ProgressManager.checkCanceled(); weigher.waitFor(); ProgressManager.checkCanceled(); - - return result; } public void addAdvertisement(@NotNull final String text, @Nullable final Color bgColor) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 63196a62a837..aaccd0167cc2 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -116,7 +116,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, private volatile LookupArranger myArranger; private LookupArranger myPresentableArranger; private final Map myMatchers = - ContainerUtil.newConcurrentMap(ContainerUtil.identityStrategy()); + ContainerUtil.createConcurrentWeakMap(ContainerUtil.identityStrategy()); private final Map myCustomFonts = ContainerUtil.createConcurrentWeakMap(10, 0.75f, Runtime.getRuntime().availableProcessors(), ContainerUtil.identityStrategy()); private boolean myStartCompletionWhenNothingMatches; From 62922dffee57e9d49c006cba610c085cc8ce6aab Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 16:55:35 +0200 Subject: [PATCH 29/41] correct range when inserting lookup string (EA-55413 - IAE: DocumentImpl.replaceString) --- .../src/com/intellij/codeInsight/lookup/impl/LookupImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index aaccd0167cc2..c6ef64c7083a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -536,7 +536,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, public void perform(Caret caret) { EditorModificationUtil.deleteSelectedText(hostEditor); final int caretOffset = hostEditor.getCaretModel().getOffset(); - int lookupStart = Math.max(caretOffset - prefix, 0); + int lookupStart = Math.min(caretOffset, Math.max(caretOffset - prefix, 0)); int len = hostEditor.getDocument().getTextLength(); LOG.assertTrue(lookupStart >= 0 && lookupStart <= len, From 8700e51ac9ce35afd0ac3080be1cb11730b10121 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 22 Jul 2015 16:56:49 +0200 Subject: [PATCH 30/41] when a dumb mode is requested inside a modal dialog, do it under a modal progress unless requested otherwise --- .../ui/configuration/ModulesConfigurator.java | 33 +++-- .../intellij/openapi/project/DumbService.java | 21 +++ .../com/intellij/mock/MockDumbService.java | 5 + .../util/AbstractProgressIndicatorExBase.java | 2 +- .../openapi/project/DumbServiceImpl.java | 134 +++++++++++++----- 5 files changed, 141 insertions(+), 54 deletions(-) diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java index d65c1a62b267..965512c4a382 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java @@ -32,6 +32,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.ShowSettingsUtil; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.projectRoots.Sdk; @@ -300,23 +301,27 @@ public class ModulesConfigurator implements ModulesProvider, ModuleEditor.Change } myFacetsConfigurator.applyEditors(); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override + DumbService.getInstance(myProject).allowStartingDumbModeInside(DumbService.DumbModePermission.MAY_START_BACKGROUND, new Runnable() { public void run() { - try { - final ModifiableRootModel[] rootModels = models.toArray(new ModifiableRootModel[models.size()]); - ModifiableModelCommitter.multiCommit(rootModels, myModuleModel); - myModuleModelCommitted = true; - myFacetsConfigurator.commitFacets(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + try { + final ModifiableRootModel[] rootModels = models.toArray(new ModifiableRootModel[models.size()]); + ModifiableModelCommitter.multiCommit(rootModels, myModuleModel); + myModuleModelCommitted = true; + myFacetsConfigurator.commitFacets(); - } - finally { - ModuleStructureConfigurable.getInstance(myProject).getFacetEditorFacade().clearMaps(false); + } + finally { + ModuleStructureConfigurable.getInstance(myProject).getFacetEditorFacade().clearMaps(false); - myFacetsConfigurator = createFacetsConfigurator(); - myModuleModel = ModuleManager.getInstance(myProject).getModifiableModel(); - myModuleModelCommitted = false; - } + myFacetsConfigurator = createFacetsConfigurator(); + myModuleModel = ModuleManager.getInstance(myProject).getModifiableModel(); + myModuleModelCommitted = false; + } + } + }); } }); diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index efd18fbf8805..aa899f1c6674 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -265,6 +265,27 @@ public abstract class DumbService { */ public abstract boolean isAlternativeResolveEnabled(); + /** + * By default, dumb mode tasks (including indexing) are allowed in non-modal state only. The reason is that + * when some code shows a dialog, it probably does't expect that after the dialog is closed the dumb mode will be on. + * Therefore any dumb mode started within a dialog is considered a mistake, performed under modal progress and reported as an exception.

+ * + * If the dialog (e.g. Project Structure) starting background dumb mode is an expected situation, the dumb mode should be started inside the runnable + * passed to this method. This will suppress the exception and allow either modal or background indexing. Note that this will only affect the invocation time + * modality state, so showing other dialogs from within the runnable and starting dumb mode from them would still result in an assertion failure. + */ + public abstract void allowStartingDumbModeInside(@NotNull DumbModePermission permission, @NotNull Runnable runnable); + + /** + * Permits the dumb mode to start at a specific moment, either modally or in background. + * @see #allowStartingDumbModeInside(DumbModePermission, Runnable) + */ + public enum DumbModePermission { + MAY_START_MODAL, + MAY_START_BACKGROUND + } + + /** * @see #DUMB_MODE */ diff --git a/platform/core-impl/src/com/intellij/mock/MockDumbService.java b/platform/core-impl/src/com/intellij/mock/MockDumbService.java index e97a9f64c7f3..12a1afa24b34 100644 --- a/platform/core-impl/src/com/intellij/mock/MockDumbService.java +++ b/platform/core-impl/src/com/intellij/mock/MockDumbService.java @@ -90,6 +90,11 @@ public class MockDumbService extends DumbService { return false; } + @Override + public void allowStartingDumbModeInside(@NotNull DumbModePermission permission, @NotNull Runnable runnable) { + runnable.run(); + } + public void smartInvokeLater(@NotNull final Runnable runnable) { runnable.run(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorExBase.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorExBase.java index c9246376689d..a4f2cb6aba8e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorExBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorExBase.java @@ -299,7 +299,7 @@ public class AbstractProgressIndicatorExBase extends AbstractProgressIndicatorBa } } - private void delegateProgressChange(@NotNull IndicatorAction action) { + protected void delegateProgressChange(@NotNull IndicatorAction action) { delegate(action); onProgressChange(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 948d347913da..28c0cef35537 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -16,11 +16,9 @@ package com.intellij.openapi.project; import com.intellij.ide.IdeBundle; +import com.intellij.ide.startup.StartupManagerEx; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.AccessToken; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.progress.*; @@ -63,6 +61,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica private final Queue myRunWhenSmartQueue = new Queue(5); private final Project myProject; private final ThreadLocal myAlternativeResolution = new ThreadLocal(); + private final Map myPermissions = ContainerUtil.newHashMap(); public DumbServiceImpl(Project project) { myProject = project; @@ -109,6 +108,23 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica return myAlternativeResolution.get() != null; } + @Override + public void allowStartingDumbModeInside(@NotNull DumbModePermission permission, @NotNull Runnable runnable) { + ApplicationManager.getApplication().assertIsDispatchThread(); + ModalityState modality = ModalityState.current(); + DumbModePermission prev = myPermissions.put(modality, permission); + try { + runnable.run(); + } + finally { + if (prev == null) { + myPermissions.remove(modality); + } else { + myPermissions.put(modality, prev); + } + } + } + @Override public void setAlternativeResolveEnabled(boolean enabled) { Integer oldValue = myAlternativeResolution.get(); @@ -151,7 +167,8 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica } private void scheduleCacheUpdate(@NotNull final DumbModeTask task, boolean forceDumbMode) { - if (LOG.isDebugEnabled()) LOG.debug("Scheduling task " + task, new Throwable()); + final Throwable trace = new Throwable(); + if (LOG.isDebugEnabled()) LOG.debug("Scheduling task " + task, trace); final Application application = ApplicationManager.getApplication(); if (application.isUnitTestMode() || @@ -181,13 +198,14 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica if (myProject.isDisposed()) { return; } - final ProgressIndicatorBase indicator = new ProgressIndicatorBase() { - @Override - protected void delegateRunningChange(@NotNull AbstractProgressIndicatorExBase.IndicatorAction action) { - // don't delegate lifecycle events to the global indicator as several independent tasks may run under it sequentially - } - }; - myProgresses.put(task, indicator); + + ModalityState modality = ModalityState.current(); + final DumbModePermission permission = getDumbModePermission(modality); + if (permission == null) { + LOG.error("Dumb mode not permitted in modal envirnonment; please use DumbService.allowStartingDumbModeInside in your dialog or invokeLater(..., NON_MODAL)", trace); + } + + myProgresses.put(task, new ProgressIndicatorBase()); Disposer.register(task, new Disposable() { @Override public void dispose() { @@ -200,37 +218,60 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica if (!myDumb) { // always change dumb status inside write action. // This will ensure all active read actions are completed before the app goes dumb - boolean startSuccess = - application.runWriteAction(new Computable() { - @Override - public Boolean compute() { - myDumb = true; - myModificationCount++; - try { - myPublisher.enteredDumbMode(); - } - catch (Throwable e) { - LOG.error(e); - } - - try { - startBackgroundProcess(); - } - catch (Throwable e) { - LOG.error("Failed to start background index update task", e); - return false; - } - return true; + application.runWriteAction(new Runnable() { + @Override + public void run() { + myDumb = true; + myModificationCount++; + try { + myPublisher.enteredDumbMode(); } - }); - if (!startSuccess) { - updateFinished(); - } + catch (Throwable e) { + LOG.error(e); + } + } + }); + + // later because we're likely in a write action and can't start a modal progress immediately + // and for a background progress, it doesn't matter if it starts several milliseconds later; dumb mode is already on + application.invokeLater(new Runnable() { + @Override + public void run() { + boolean modal = permission != DumbModePermission.MAY_START_BACKGROUND; + boolean shouldFinish = modal; + try { + startBackgroundProcess(modal); + } + catch (Throwable e) { + shouldFinish = true; + LOG.error("Failed to start background index update task", e); + } + finally { + if (shouldFinish) { + updateFinished(); + } + } + } + }, modality, myProject.getDisposed()); } } }); } + @Nullable + private DumbModePermission getDumbModePermission(ModalityState modality) { + DumbModePermission permission = myPermissions.get(modality); + if (permission != null) { + return permission; + } + + if (modality == ModalityState.NON_MODAL || !StartupManagerEx.getInstanceEx(myProject).postStartupActivityPassed()) { + return DumbModePermission.MAY_START_BACKGROUND; + } + + return null; + } + private void updateFinished() { myDumb = false; myModificationCount++; @@ -349,7 +390,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica }, modalityState, myProject.getDisposed()); } - private void startBackgroundProcess() { + private void startBackgroundProcess(final boolean modal) { ProgressManager.getInstance().run(new Task.Backgroundable(myProject, IdeBundle.message("progress.indexing"), false) { @Override @@ -372,7 +413,13 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica task = pair.first; ProgressIndicatorEx taskIndicator = pair.second; if (visibleIndicator instanceof ProgressIndicatorEx) { - taskIndicator.addStateDelegate((ProgressIndicatorEx)visibleIndicator); + taskIndicator.addStateDelegate(new AbstractProgressIndicatorExBase() { + @Override + protected void delegateProgressChange(@NotNull IndicatorAction action) { + super.delegateProgressChange(action); + action.execute((ProgressIndicatorEx)visibleIndicator); + } + }); } runSingleTask(task, taskIndicator); } @@ -385,6 +432,15 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica token.finish(); } } + + public boolean isConditionalModal() { + return modal; + } + + @Override + public boolean shouldStartInBackground() { + return !modal; + } }); } From 0e437776e40c2f687c1cee21ed94e0e14cdfe666 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 22 Jul 2015 18:41:09 +0300 Subject: [PATCH 31/41] IDEA-142968 Auto-completion list on black background since latest EAP build --- .../lookup/impl/LookupCellRenderer.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java index adfe43f65c30..38f41f7d79c5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java @@ -36,14 +36,15 @@ import com.intellij.ui.components.JBList; import com.intellij.ui.speedSearch.SpeedSearchUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FList; -import com.intellij.util.ui.*; +import com.intellij.util.ui.EmptyIcon; +import com.intellij.util.ui.GraphicsUtil; +import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; -import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -483,18 +484,17 @@ public class LookupCellRenderer implements ListCellRenderer { @Override public void paint(Graphics g){ + super.paint(g); if (!myLookup.isFocused() && myLookup.isCompletion()) { - ((Graphics2D)g).setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.6f)); - - // sub-pixel antialiasing does not work with alpha composite, so we workaround this by painting to RGB image first - BufferedImage image = UIUtil.createImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB); - Graphics2D imageGraphics = image.createGraphics(); - super.paint(imageGraphics); - imageGraphics.dispose(); - UIUtil.drawImage(g, image, 0, 0, null); - } - else { - super.paint(g); + g = g.create(); + try { + g.setColor(ColorUtil.withAlpha(BACKGROUND_COLOR, .4)); + Rectangle r = new Rectangle(getSize()); + g.fillRect(r.x, r.y, r.width, r.height); + } + finally { + g.dispose(); + } } } } From 1799d65637e8dc286d5d4a837646e5a7ac075d5f Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 22 Jul 2015 18:52:16 +0300 Subject: [PATCH 32/41] IDEA-142866 Gradle: misleading message is shown on "Ignore Gradle Project" action --- .../resources/i18n/ExternalSystemBundle.properties | 2 +- .../service/project/manage/ModuleDataService.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties index bd6a05ce4668..bc068a158b75 100644 --- a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties +++ b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties @@ -2,7 +2,7 @@ import.title=Import {0} Projects module.type.title={0} Module module.type.description={0} modules are used for developing JVM-based applications with dependencies managed by {0} -orphan.modules.text=The modules below are not backed by {0} anymore.
Check those to be removed from the ide project too: +orphan.modules.text=The modules below are not imported from {0} anymore.
Check those to be removed from the ide project too: # Settings. setting.type.location.deduced={0} location is deduced diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java index b976aa3e3b6b..8f63cd1237c1 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java @@ -356,6 +356,11 @@ public class ModuleDataService extends AbstractProjectDataService Date: Wed, 22 Jul 2015 19:16:17 +0300 Subject: [PATCH 33/41] Make CompoundRunConfiguration available for junior IDEs --- .../intellij/execution/compound/CompoundRunConfiguration.java | 0 .../compound/CompoundRunConfigurationSettingsEditor.java | 0 .../execution/compound/CompoundRunConfigurationType.java | 0 platform/platform-resources/src/META-INF/LangExtensions.xml | 1 + resources/src/META-INF/IdeaPlugin.xml | 1 - 5 files changed, 1 insertion(+), 1 deletion(-) rename {java/execution/impl => platform/lang-impl}/src/com/intellij/execution/compound/CompoundRunConfiguration.java (100%) rename {java/execution/impl => platform/lang-impl}/src/com/intellij/execution/compound/CompoundRunConfigurationSettingsEditor.java (100%) rename {java/execution/impl => platform/lang-impl}/src/com/intellij/execution/compound/CompoundRunConfigurationType.java (100%) diff --git a/java/execution/impl/src/com/intellij/execution/compound/CompoundRunConfiguration.java b/platform/lang-impl/src/com/intellij/execution/compound/CompoundRunConfiguration.java similarity index 100% rename from java/execution/impl/src/com/intellij/execution/compound/CompoundRunConfiguration.java rename to platform/lang-impl/src/com/intellij/execution/compound/CompoundRunConfiguration.java diff --git a/java/execution/impl/src/com/intellij/execution/compound/CompoundRunConfigurationSettingsEditor.java b/platform/lang-impl/src/com/intellij/execution/compound/CompoundRunConfigurationSettingsEditor.java similarity index 100% rename from java/execution/impl/src/com/intellij/execution/compound/CompoundRunConfigurationSettingsEditor.java rename to platform/lang-impl/src/com/intellij/execution/compound/CompoundRunConfigurationSettingsEditor.java diff --git a/java/execution/impl/src/com/intellij/execution/compound/CompoundRunConfigurationType.java b/platform/lang-impl/src/com/intellij/execution/compound/CompoundRunConfigurationType.java similarity index 100% rename from java/execution/impl/src/com/intellij/execution/compound/CompoundRunConfigurationType.java rename to platform/lang-impl/src/com/intellij/execution/compound/CompoundRunConfigurationType.java diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ff25d4f8ab52..f137a0fdea50 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -574,6 +574,7 @@ + diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 74d9b8a0282c..10736417b2d4 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -1302,7 +1302,6 @@ - From dbb75b138d1a868230f309505de1a17f731bcaac Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 22 Jul 2015 19:13:28 +0300 Subject: [PATCH 34/41] IDEA-142862 Gradle Tool Window: it is not obvious that "Open Project Structure" button opens '''Gradle Project Data To Import'' dialog --- ...nalSystemSelectProjectDataToImportAction.java} | 15 ++++----------- .../AbstractExternalProjectImportBuilder.java | 4 ++-- ...orm => ExternalProjectDataSelectorDialog.form} | 2 +- ...ava => ExternalProjectDataSelectorDialog.java} | 14 ++++++-------- .../src/idea/ExternalSystemActions.xml | 6 +++--- 5 files changed, 16 insertions(+), 25 deletions(-) rename platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/{ExternalSystemOpenProjectStructureAction.java => ExternalSystemSelectProjectDataToImportAction.java} (76%) rename platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/{ExternalProjectStructureDialog.form => ExternalProjectDataSelectorDialog.form} (97%) rename platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/{ExternalProjectStructureDialog.java => ExternalProjectDataSelectorDialog.java} (97%) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemOpenProjectStructureAction.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java similarity index 76% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemOpenProjectStructureAction.java rename to platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java index 9c83c49c2463..0528ca44fe40 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemOpenProjectStructureAction.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/action/ExternalSystemSelectProjectDataToImportAction.java @@ -21,7 +21,7 @@ import com.intellij.openapi.externalSystem.model.ExternalSystemDataKeys; import com.intellij.openapi.externalSystem.model.ProjectSystemId; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; -import com.intellij.openapi.externalSystem.service.ui.ExternalProjectStructureDialog; +import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelectorDialog; import com.intellij.openapi.externalSystem.view.ExternalSystemNode; import com.intellij.openapi.externalSystem.view.ProjectNode; import com.intellij.openapi.project.Project; @@ -33,14 +33,7 @@ import java.util.List; * @author Vladislav.Soroka * @since 5/12/2015 */ -public class ExternalSystemOpenProjectStructureAction extends ExternalSystemAction { - - public ExternalSystemOpenProjectStructureAction() { - //super(AbstractExternalEntityData.class); - //getTemplatePresentation().setText(ExternalSystemBundle.message("action.detach.external.project.text", "external")); - //getTemplatePresentation().setDescription(ExternalSystemBundle.message("action.detach.external.project.description")); - //getTemplatePresentation().setIcon(SystemInfoRt.isMac ? AllIcons.ToolbarDecorator.Mac.Remove : AllIcons.ToolbarDecorator.Remove); - } +public class ExternalSystemSelectProjectDataToImportAction extends ExternalSystemAction { @Override public void actionPerformed(AnActionEvent e) { @@ -65,9 +58,9 @@ public class ExternalSystemOpenProjectStructureAction extends ExternalSystemActi ProjectDataManager.getInstance().getExternalProjectData(project, projectSystemId, projectData.getLinkedExternalProjectPath()); } - final ExternalProjectStructureDialog dialog; + final ExternalProjectDataSelectorDialog dialog; if (projectInfo != null) { - dialog = new ExternalProjectStructureDialog(project, projectInfo, externalSystemNode != null ? externalSystemNode.getData() : null); + dialog = new ExternalProjectDataSelectorDialog(project, projectInfo, externalSystemNode != null ? externalSystemNode.getData() : null); dialog.showAndGet(); } } diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java index 1fd23a3a7af3..b1a9268b2070 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java @@ -18,7 +18,7 @@ import com.intellij.openapi.externalSystem.service.project.PlatformFacadeImpl; import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManager; import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager; import com.intellij.openapi.externalSystem.service.settings.AbstractImportFromExternalSystemControl; -import com.intellij.openapi.externalSystem.service.ui.ExternalProjectStructureDialog; +import com.intellij.openapi.externalSystem.service.ui.ExternalProjectDataSelectorDialog; import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; @@ -158,7 +158,7 @@ public abstract class AbstractExternalProjectImportBuilder -

+ diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectStructureDialog.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java similarity index 97% rename from platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectStructureDialog.java rename to platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java index 907cec5d8512..3dde3df4eba0 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectStructureDialog.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java @@ -33,7 +33,6 @@ import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataMan import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; -import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.openapi.ui.DialogWrapper; @@ -69,7 +68,7 @@ import java.util.Set; * @author Vladislav.Soroka * @since 5/12/2015 */ -public class ExternalProjectStructureDialog extends DialogWrapper { +public class ExternalProjectDataSelectorDialog extends DialogWrapper { private static final int MAX_PATH_LENGTH = 50; private static final Set> DATA_KEYS = ContainerUtil.set(ProjectKeys.PROJECT, ProjectKeys.MODULE); @@ -107,14 +106,14 @@ public class ExternalProjectStructureDialog extends DialogWrapper { private boolean myShowSelectedRowsOnly; private int myModulesCount; - public ExternalProjectStructureDialog(@NotNull Project project, - @NotNull ExternalProjectInfo projectInfo) { + public ExternalProjectDataSelectorDialog(@NotNull Project project, + @NotNull ExternalProjectInfo projectInfo) { this(project, projectInfo, null); } - public ExternalProjectStructureDialog(@NotNull Project project, - @NotNull ExternalProjectInfo projectInfo, - @Nullable Object preselectedNodeDataObject) { + public ExternalProjectDataSelectorDialog(@NotNull Project project, + @NotNull ExternalProjectInfo projectInfo, + @Nullable Object preselectedNodeDataObject) { super(project, true); myProject = project; myIgnorableKeys = getIgnorableKeys(); @@ -220,7 +219,6 @@ public class ExternalProjectStructureDialog extends DialogWrapper { }); } }); - //ExternalSystemUtil.scheduleExternalViewStructureUpdate(myProject, myProjectInfo.getProjectSystemId()); } } diff --git a/platform/platform-resources/src/idea/ExternalSystemActions.xml b/platform/platform-resources/src/idea/ExternalSystemActions.xml index db393ffb1870..42f49f71d807 100644 --- a/platform/platform-resources/src/idea/ExternalSystemActions.xml +++ b/platform/platform-resources/src/idea/ExternalSystemActions.xml @@ -38,8 +38,8 @@ text="Collapse All" icon="AllIcons.Actions.Collapseall" use-shortcut-of="CollapseAll"/> - - + From af804b42bdde9b60304cb7221b664036fe7f2b98 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 22 Jul 2015 19:17:03 +0300 Subject: [PATCH 35/41] external system: allow starting dumb mode inside project data selector modal dialog --- .../ui/ExternalProjectDataSelectorDialog.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java index 3dde3df4eba0..0257a368513d 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ui/ExternalProjectDataSelectorDialog.java @@ -33,6 +33,7 @@ import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataMan import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil; +import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ex.ProjectRootManagerEx; import com.intellij.openapi.ui.DialogWrapper; @@ -211,12 +212,17 @@ public class ExternalProjectDataSelectorDialog extends DialogWrapper { ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(myProject) { @Override public void execute() { - ProjectRootManagerEx.getInstanceEx(myProject).mergeRootsChangesDuring(new Runnable() { - @Override - public void run() { - ServiceManager.getService(ProjectDataManager.class).importData(projectStructure, myProject, true); - } - }); + DumbService.getInstance(myProject).allowStartingDumbModeInside( + DumbService.DumbModePermission.MAY_START_BACKGROUND, new Runnable() { + public void run() { + ProjectRootManagerEx.getInstanceEx(myProject).mergeRootsChangesDuring(new Runnable() { + @Override + public void run() { + ServiceManager.getService(ProjectDataManager.class).importData(projectStructure, myProject, true); + } + }); + } + }); } }); } From cff7efd5d1e9ae91e035d03c21b717d0715c9f0b Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 22 Jul 2015 18:23:28 +0200 Subject: [PATCH 36/41] [java] since Java 9, underscore identifiers are completely prohibited (IDEA-132278) --- .../daemon/impl/analysis/HighlightUtil.java | 19 ++++++++++++------- .../impl/analysis/HighlightVisitorImpl.java | 4 ++-- .../JavacQuirksInspectionVisitor.java | 17 ++++++++++------- .../com/intellij/pom/java/LanguageLevel.java | 4 ++++ .../src/messages/JavaErrorMessages.properties | 3 ++- .../advHighlighting9/Underscore.java | 3 +++ .../daemon/LightAdvHighlightingJdk9Test.java | 4 ++-- 7 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/Underscore.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index ffc5c06107b1..bfd70140ba25 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -725,13 +725,18 @@ public class HighlightUtil extends HighlightUtilBase { } @Nullable - static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, - @NotNull PsiVariable variable, - @NotNull LanguageLevel languageLevel) { - if ("_".equals(variable.getName()) && languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { - if (variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiLambdaExpression) { - String message = JavaErrorMessages.message("underscore.lambda.identifier"); - return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create(); + static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull LanguageLevel languageLevel) { + if ("_".equals(identifier.getText())) { + if (languageLevel.isAtLeast(LanguageLevel.JDK_1_9)) { + String text = JavaErrorMessages.message("underscore.identifier.error"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(text).create(); + } + else if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { + PsiElement parent = identifier.getParent(); + if (parent instanceof PsiParameter && ((PsiParameter)parent).getDeclarationScope() instanceof PsiLambdaExpression) { + String text = JavaErrorMessages.message("underscore.lambda.identifier"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(text).create(); + } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index f2d7c4b22211..59d316734a15 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -621,8 +621,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh myHolder.add(HighlightNamesUtil.highlightVariableName(variable, identifier, colorsScheme)); } } - - myHolder.add(HighlightUtil.checkUnderscore(identifier, variable, myLanguageLevel)); } else if (parent instanceof PsiClass) { PsiClass aClass = (PsiClass)parent; @@ -650,6 +648,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh } } + myHolder.add(HighlightUtil.checkUnderscore(identifier, myLanguageLevel)); + super.visitIdentifier(identifier); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java index 92cbca249a75..97577bcb2d4f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/compiler/JavacQuirksInspectionVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -34,9 +34,13 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor { psiElement().withParent(PsiJavaCodeReferenceElement.class).withSuperParent(2, PsiJavaCodeReferenceElement.class); private final ProblemsHolder myHolder; + private final LanguageLevel myLanguageLevel; + private final JavaSdkVersion mySdkVersion; public JavacQuirksInspectionVisitor(ProblemsHolder holder) { myHolder = holder; + mySdkVersion = JavaVersionService.getInstance().getJavaSdkVersion(myHolder.getFile()); + myLanguageLevel = PsiUtil.getLanguageLevel(myHolder.getFile()); } @Override @@ -72,12 +76,11 @@ public class JavacQuirksInspectionVisitor extends JavaElementVisitor { @Override public void visitIdentifier(PsiIdentifier identifier) { super.visitIdentifier(identifier); - final JavaSdkVersion version = JavaVersionService.getInstance().getJavaSdkVersion(identifier); - if (version != null && version.isAtLeast(JavaSdkVersion.JDK_1_8)) { - if ("_".equals(identifier.getText())) { - myHolder.registerProblem(identifier, JavaErrorMessages.message("underscore.identifier"), - version.isAtLeast(JavaSdkVersion.JDK_1_9) ? ProblemHighlightType.ERROR : ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } + if ("_".equals(identifier.getText()) && + mySdkVersion != null && mySdkVersion.isAtLeast(JavaSdkVersion.JDK_1_8) && + myLanguageLevel.isLessThan(LanguageLevel.JDK_1_9)) { + final String message = JavaErrorMessages.message("underscore.identifier.warn"); + myHolder.registerProblem(identifier, message, ProblemHighlightType.GENERIC_ERROR_OR_WARNING); } } } diff --git a/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java b/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java index b0e03a7c8824..32b3cf06aa21 100644 --- a/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java +++ b/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java @@ -64,6 +64,10 @@ public enum LanguageLevel { return compareTo(level) >= 0; } + public boolean isLessThan(@NotNull LanguageLevel level) { + return compareTo(level) < 0; + } + @Nullable public static LanguageLevel parse(@Nullable String value) { if ("1.3".equals(value)) return JDK_1_3; diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index 6888379c8844..75438aaa7322 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -379,7 +379,8 @@ override.not.allowed.in.interfaces=@Override is not allowed when implementing in wildcard.not.expected=Unexpected wildcard bound.not.expected=Unexpected bound -underscore.identifier=Use of '_' as an identifier might not be supported in releases after Java 8 +underscore.identifier.warn=Use of '_' as an identifier might not be supported in releases after Java 8 +underscore.identifier.error=As of Java 9, '_' is a keyword, and may not be used as an identifier underscore.lambda.identifier=Use of '_' as a lambda parameter name is not allowed feature.generics=Generics diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/Underscore.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/Underscore.java new file mode 100644 index 000000000000..19594fa8ba55 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/Underscore.java @@ -0,0 +1,3 @@ +class Undescore { + void _() { } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java index 3a1ceb590e39..727de167f7b7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java @@ -15,7 +15,6 @@ */ package com.intellij.codeInsight.daemon; -import com.intellij.codeInspection.compiler.JavacQuirksInspection; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; import com.intellij.codeInspection.redundantCast.RedundantCastInspection; import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection; @@ -30,7 +29,7 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase { @Override protected void setUp() throws Exception { super.setUp(); - enableInspectionTools(new UnusedDeclarationInspection(), new UncheckedWarningLocalInspection(), new JavacQuirksInspection(), new RedundantCastInspection()); + enableInspectionTools(new UnusedDeclarationInspection(), new UncheckedWarningLocalInspection(), new RedundantCastInspection()); setLanguageLevel(LanguageLevel.JDK_1_9); IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_9, getModule(), getTestRootDisposable()); } @@ -46,6 +45,7 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase { public void testSafeVarargsApplicability() { doTest(true, false); } public void testPrivateInInterfaces() { doTest(false, false); } + public void testUnderscore() { doTest(false, false); } public void testTryWithResources() { doTest(false, false); } public void testValueTypes() { setLanguageLevel(LanguageLevel.JDK_X); doTest(false, false); } From 0b2c3013b7571d86bd2a0a68c5b93700cc5f8f4d Mon Sep 17 00:00:00 2001 From: Konstantin Ulitin Date: Wed, 22 Jul 2015 19:34:09 +0300 Subject: [PATCH 37/41] WEB-17364 IllegalArgumentException when add .es6 extension to ECMAScript6 file type --- .../openapi/fileTypes/impl/FileTypeConfigurable.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java index a35b8eaeca0c..4a6449a68c39 100644 --- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java +++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java @@ -277,7 +277,9 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable FileTypesBundle.message("filetype.edit.add.pattern.reassign.button"), CommonBundle.getCancelButtonText(), Messages.getQuestionIcon())) { myTempPatternsTable.removeAssociation(matcher, registeredFileType); - myTempTemplateDataLanguages.removeAssociation(matcher, oldLanguage); + if (oldLanguage != null) { + myTempTemplateDataLanguages.removeAssociation(matcher, oldLanguage); + } myReassigned.put(matcher, registeredFileType); } else { @@ -289,7 +291,9 @@ public class FileTypeConfigurable extends BaseConfigurable implements Searchable if (item != null) { final FileNameMatcher oldMatcher = FileTypeManager.parseFromString(item); myTempPatternsTable.removeAssociation(oldMatcher, type); - myTempTemplateDataLanguages.removeAssociation(oldMatcher, oldLanguage); + if (oldLanguage != null) { + myTempTemplateDataLanguages.removeAssociation(oldMatcher, oldLanguage); + } } myTempPatternsTable.addAssociation(matcher, type); myTempTemplateDataLanguages.addAssociation(matcher, dialog.getTemplateDataLanguage()); From 51ca4c34c484bf7ba13a49147df69528723e858b Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 22 Jul 2015 19:35:45 +0300 Subject: [PATCH 38/41] fixes after review IDEA-CR-3613 --- .../daemon/impl/PsiElementListNavigator.java | 4 ++-- .../codeInsight/navigation/GotoTargetHandler.java | 4 ++-- .../codeInsight/navigation/NavigationUtil.java | 4 ++-- .../ide/util/gotoByName/ChooseByNameBase.java | 13 ++----------- .../intellij/openapi/editor/ex/util/EditorUtil.java | 9 +++++++++ 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java index 7e2d15f2affc..ba0163e0ac91 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiElementListNavigator.java @@ -20,9 +20,9 @@ import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask; import com.intellij.find.FindUtil; import com.intellij.ide.PsiCopyPasteManager; import com.intellij.ide.util.PsiElementListCellRenderer; -import com.intellij.ide.util.gotoByName.ChooseByNameBase; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.ui.popup.JBPopup; import com.intellij.openapi.ui.popup.PopupChooserBuilder; @@ -128,7 +128,7 @@ public class PsiElementListNavigator { }); list.setCellRenderer(listRenderer); - list.setFont(ChooseByNameBase.getEditorFont()); + list.setFont(EditorUtil.getEditorFont()); final PopupChooserBuilder builder = new PopupChooserBuilder(list); if (listRenderer instanceof PsiElementListCellRenderer) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java index 8e52e10390d0..562b6ad544a8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/GotoTargetHandler.java @@ -22,11 +22,11 @@ import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.find.FindUtil; import com.intellij.ide.util.EditSourceUtil; import com.intellij.ide.util.PsiElementListCellRenderer; -import com.intellij.ide.util.gotoByName.ChooseByNameBase; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; @@ -130,7 +130,7 @@ public abstract class GotoTargetHandler implements CodeInsightActionHandler { } }; - list.setFont(ChooseByNameBase.getEditorFont()); + list.setFont(EditorUtil.getEditorFont()); list.setCellRenderer(new DefaultListCellRenderer() { @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java index a196f9666b87..69c5183b5271 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java @@ -19,7 +19,6 @@ package com.intellij.codeInsight.navigation; import com.intellij.ide.util.DefaultPsiElementCellRenderer; import com.intellij.ide.util.EditSourceUtil; import com.intellij.ide.util.PsiElementListCellRenderer; -import com.intellij.ide.util.gotoByName.ChooseByNameBase; import com.intellij.navigation.GotoRelatedItem; import com.intellij.navigation.GotoRelatedProvider; import com.intellij.navigation.NavigationItem; @@ -27,6 +26,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.MarkupModelEx; import com.intellij.openapi.editor.ex.RangeHighlighterEx; +import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.DocumentMarkupModel; import com.intellij.openapi.editor.markup.HighlighterTargetArea; import com.intellij.openapi.editor.markup.MarkupModel; @@ -116,7 +116,7 @@ public final class NavigationUtil { }; list.setCellRenderer(renderer); - list.setFont(ChooseByNameBase.getEditorFont()); + list.setFont(EditorUtil.getEditorFont()); if (selection != null) { list.setSelectedValue(selection, true); diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java index 858d2144dd88..97f1376089a8 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java @@ -26,7 +26,6 @@ import com.intellij.ide.IdeEventQueue; import com.intellij.ide.actions.CopyReferenceAction; import com.intellij.ide.actions.GotoFileAction; import com.intellij.ide.actions.WindowAction; -import com.intellij.ide.ui.UISettings; import com.intellij.ide.ui.laf.darcula.ui.DarculaTextBorder; import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI; import com.intellij.openapi.Disposable; @@ -35,8 +34,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.fileTypes.UnknownFileType; import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx; import com.intellij.openapi.keymap.Keymap; @@ -490,7 +488,7 @@ public abstract class ChooseByNameBase { myTextField.setActionMap(actionMap); myTextFieldPanel.add(myTextField); - Font editorFont = getEditorFont(); + Font editorFont = EditorUtil.getEditorFont(); myTextField.setFont(editorFont); if (checkBoxName != null) { @@ -1824,11 +1822,4 @@ public abstract class ChooseByNameBase { public JTextField getTextField() { return myTextField; } - - public static Font getEditorFont() { - EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); - int size = UISettings.getInstance().PRESENTATION_MODE - ? UISettings.getInstance().PRESENTATION_MODE_FONT_SIZE - 4 : scheme.getEditorFontSize(); - return new Font(scheme.getEditorFontName(), Font.PLAIN, size); - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java index ed980b0530f7..8a57be0eb3f5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EditorUtil.java @@ -17,10 +17,12 @@ package com.intellij.openapi.editor.ex.util; import com.intellij.diagnostic.Dumpable; import com.intellij.diagnostic.LogMessageEx; +import com.intellij.ide.ui.UISettings; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.ComplementaryFontsRegistry; @@ -899,6 +901,13 @@ public final class EditorUtil { } editor.getSelectionModel().setSelection(startOffset, endOffset); } + + public static Font getEditorFont() { + EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); + int size = UISettings.getInstance().PRESENTATION_MODE + ? UISettings.getInstance().PRESENTATION_MODE_FONT_SIZE - 4 : scheme.getEditorFontSize(); + return new Font(scheme.getEditorFontName(), Font.PLAIN, size); + } } From 01ee3d5990a8e634b9bb5da7198c0e8269669f96 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 22 Jul 2015 19:38:23 +0300 Subject: [PATCH 39/41] IDEA-142968 Auto-completion list on black background since latest EAP build Make this code a bit simpler --- .../intellij/codeInsight/lookup/impl/LookupCellRenderer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java index 38f41f7d79c5..863c718a78c6 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java @@ -489,8 +489,7 @@ public class LookupCellRenderer implements ListCellRenderer { g = g.create(); try { g.setColor(ColorUtil.withAlpha(BACKGROUND_COLOR, .4)); - Rectangle r = new Rectangle(getSize()); - g.fillRect(r.x, r.y, r.width, r.height); + g.fillRect(0, 0, getWidth(), getHeight()); } finally { g.dispose(); From 4c6f8353cb935bfbc22457db6cb4a456a1960674 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 22 Jul 2015 18:16:11 +0200 Subject: [PATCH 40/41] fix predicted test names --- .../execution/testDiscovery/TestDiscoveryExtension.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryExtension.java b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryExtension.java index 2c5cedca5a94..484d746e6432 100644 --- a/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryExtension.java +++ b/java/execution/impl/src/com/intellij/execution/testDiscovery/TestDiscoveryExtension.java @@ -85,7 +85,7 @@ public class TestDiscoveryExtension extends RunConfigurationExtension { if ((root == null || root.getHandler() == handler)) { final String fullTestName = test.getLocationUrl(); if (fullTestName != null && fullTestName.startsWith(JavaTestLocator.TEST_PROTOCOL)) { - myCompletedMethodNames.add(fullTestName.substring(JavaTestLocator.TEST_PROTOCOL.length() + 3)); + myCompletedMethodNames.add(((TestDiscoveryConfiguration)configuration).getFrameworkPrefix() + fullTestName.substring(JavaTestLocator.TEST_PROTOCOL.length() + 3)); if (myCompletedMethodNames.size() > 50) { final String[] fullTestNames = ArrayUtil.toStringArray(myCompletedMethodNames); myCompletedMethodNames.clear(); From b65583d8e4f005ca0a48575fe6ba039f73873afe Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 22 Jul 2015 18:57:29 +0200 Subject: [PATCH 41/41] EclipseModuleManagerImpl is a service, so, must be registered as a service --- .../openapi/module/ModuleServiceManager.java | 21 ++++++++++++++++++- plugins/eclipse/resources/META-INF/plugin.xml | 7 ++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/module/ModuleServiceManager.java b/platform/core-api/src/com/intellij/openapi/module/ModuleServiceManager.java index ab234bacd290..ad7e3b7265e6 100644 --- a/platform/core-api/src/com/intellij/openapi/module/ModuleServiceManager.java +++ b/platform/core-api/src/com/intellij/openapi/module/ModuleServiceManager.java @@ -16,6 +16,9 @@ package com.intellij.openapi.module; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,12 +26,28 @@ import org.jetbrains.annotations.Nullable; * @author yole */ public class ModuleServiceManager { + private static final Logger LOG = Logger.getInstance(ModuleServiceManager.class); + private ModuleServiceManager() { } @Nullable public static T getService(@NotNull Module module, @NotNull Class serviceClass) { //noinspection unchecked - return (T)module.getPicoContainer().getComponentInstance(serviceClass.getName()); + T instance = (T)module.getPicoContainer().getComponentInstance(serviceClass.getName()); + if (instance == null) { + instance = module.getComponent(serviceClass); + if (instance != null) { + Application app = ApplicationManager.getApplication(); + String message = serviceClass.getName() + " requested as a service, but it is a component - convert it to a service or change call to module.getComponent()"; + if (app.isUnitTestMode()) { + LOG.error(message); + } + else { + LOG.warn(message); + } + } + } + return instance; } } \ No newline at end of file diff --git a/plugins/eclipse/resources/META-INF/plugin.xml b/plugins/eclipse/resources/META-INF/plugin.xml index 3c9da31159d6..f53e46d90cbd 100644 --- a/plugins/eclipse/resources/META-INF/plugin.xml +++ b/plugins/eclipse/resources/META-INF/plugin.xml @@ -30,12 +30,9 @@ name="Eclipse XML Profile" implementationClass="org.jetbrains.idea.eclipse.importer.EclipseCodeStyleSchemeImporter" schemeClass="com.intellij.psi.codeStyle.CodeStyleScheme"/> + + - - - org.jetbrains.idea.eclipse.config.EclipseModuleManagerImpl - -