From 625698ef979118b632fb339834cc7e3391a5dcf0 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 9 Oct 2012 21:36:31 +0400 Subject: [PATCH 01/12] Support maven 3 Implement resolving of plugins. --- .../server/Maven3ServerEmbedderImpl.java | 101 ++++++++++-------- 1 file changed, 59 insertions(+), 42 deletions(-) diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java index f868af77791b..ef973e590521 100644 --- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java +++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerEmbedderImpl.java @@ -18,24 +18,29 @@ package org.jetbrains.idea.maven.server; import com.intellij.util.SystemProperties; import gnu.trove.THashMap; import gnu.trove.THashSet; +import org.apache.maven.DefaultMaven; +import org.apache.maven.Maven; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepositoryFactory; -import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; -import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; import org.apache.maven.artifact.resolver.*; import org.apache.maven.cli.MavenCli; import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequestPopulationException; +import org.apache.maven.execution.MavenExecutionRequestPopulator; import org.apache.maven.model.Activation; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.Profile; import org.apache.maven.model.profile.DefaultProfileInjector; -import org.apache.maven.plugin.PluginManager; +import org.apache.maven.plugin.MavenPluginManager; import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.version.DefaultPluginVersionRequest; +import org.apache.maven.plugin.version.PluginVersionRequest; +import org.apache.maven.plugin.version.PluginVersionResolver; import org.apache.maven.profiles.activation.*; import org.apache.maven.project.*; import org.apache.maven.project.inheritance.DefaultModelInheritanceAssembler; @@ -44,8 +49,8 @@ import org.apache.maven.project.interpolation.ModelInterpolationException; import org.apache.maven.project.path.DefaultPathTranslator; import org.apache.maven.project.path.PathTranslator; import org.apache.maven.project.validation.ModelValidationResult; +import org.apache.maven.repository.RepositorySystem; import org.apache.maven.settings.Settings; -import org.apache.maven.settings.SettingsUtils; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuilder; import org.apache.maven.settings.building.SettingsBuildingException; @@ -68,6 +73,7 @@ import org.jetbrains.idea.maven.model.*; import org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator; import org.jetbrains.idea.maven.server.embedder.FieldAccessor; import org.jetbrains.idea.maven.server.embedder.MavenExecutionResult; +import org.sonatype.aether.RepositorySystemSession; import java.io.File; import java.lang.reflect.Constructor; @@ -208,21 +214,28 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven } private ArtifactRepository createLocalRepository(MavenServerSettings.UpdatePolicy snapshotUpdatePolicy) { - ArtifactRepositoryLayout layout = getComponent(ArtifactRepositoryLayout.class, "default"); - ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class); - - String url = myMavenSettings.getLocalRepository(); - if (!url.startsWith("file:")) url = "file://" + url; - - ArtifactRepository localRepository = factory.createArtifactRepository("local", url, layout, null, null); - - boolean snapshotPolicySet = myMavenSettings.isOffline(); - if (!snapshotPolicySet && snapshotUpdatePolicy == MavenServerSettings.UpdatePolicy.ALWAYS_UPDATE) { - factory.setGlobalUpdatePolicy(ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS); + try { + return getComponent(RepositorySystem.class).createLocalRepository(new File(myMavenSettings.getLocalRepository())); } - factory.setGlobalChecksumPolicy(ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN); - - return localRepository; + catch (InvalidRepositoryException e) { + throw new RuntimeException(e); + // Legacy code. + } + //ArtifactRepositoryLayout layout = getComponent(ArtifactRepositoryLayout.class, "default"); + //ArtifactRepositoryFactory factory = getComponent(ArtifactRepositoryFactory.class); + // + //String url = myMavenSettings.getLocalRepository(); + //if (!url.startsWith("file:")) url = "file://" + url; + // + //ArtifactRepository localRepository = factory.createArtifactRepository("local", url, layout, null, null); + // + //boolean snapshotPolicySet = myMavenSettings.isOffline(); + //if (!snapshotPolicySet && snapshotUpdatePolicy == MavenServerSettings.UpdatePolicy.ALWAYS_UPDATE) { + // factory.setGlobalUpdatePolicy(ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS); + //} + //factory.setGlobalChecksumPolicy(ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN); + // + //return localRepository; } @Override @@ -262,27 +275,12 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven return createExecutionResult(file, result, listener.getRootNode()); } - private static void setProfilesFromSettings(MavenExecutionRequest request, Settings settings) { - List settingsProfiles = settings.getProfiles(); - - request.setActiveProfiles(settings.getActiveProfiles()); - - if (settingsProfiles != null) { - for (org.apache.maven.settings.Profile rawProfile : settingsProfiles) { - Profile profile = SettingsUtils.convertFromSettingsProfile(rawProfile); - request.addProfile(profile); - } - } - } - @NotNull public MavenExecutionResult doResolveProject(@NotNull final File file, @NotNull final List activeProfiles, - List listeners) { + List listeners) throws RemoteException { MavenExecutionRequest request = createRequest(file, activeProfiles, Collections.emptyList(), Collections.emptyList()); - setProfilesFromSettings(request, myMavenSettings); - ProjectBuildingRequest config = request.getProjectBuildingRequest(); List exceptions = new ArrayList(); @@ -327,25 +325,31 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven catch (Exception e) { return handleException(e); } - - } - private MavenExecutionRequest createRequest(File file, List activeProfiles, List inactiveProfiles, List goals) { + private MavenExecutionRequest createRequest(File file, List activeProfiles, List inactiveProfiles, List goals) + throws RemoteException { //Properties executionProperties = myMavenSettings.getProperties(); //if (executionProperties == null) { // executionProperties = new Properties(); //} MavenExecutionRequest result = new DefaultMavenExecutionRequest(); - result.setLocalRepository(myLocalRepository); - result.setGoals(goals); - result.setBaseDirectory(file.getParentFile()); + try { + getComponent(MavenExecutionRequestPopulator.class).populateFromSettings(result, myMavenSettings); - result.setPom(file); + result.setGoals(goals); + + result.setPom(file); + + getComponent(MavenExecutionRequestPopulator.class).populateDefaults(result); return result; + } + catch (MavenExecutionRequestPopulationException e) { + throw new RuntimeException(e); + } } private static MavenExecutionResult handleException(Throwable e) { @@ -471,7 +475,20 @@ public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements Maven mavenPlugin.setVersion(plugin.getVersion()); MavenProject project = RemoteNativeMavenProjectHolder.findProjectById(nativeMavenProjectId); - PluginDescriptor result = getComponent(PluginManager.class).verifyPlugin(mavenPlugin, project, myMavenSettings, myLocalRepository); + MavenExecutionRequest request = createRequest(null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + + DefaultMaven maven = (DefaultMaven)getComponent(Maven.class); + RepositorySystemSession repositorySystemSession = maven.newRepositorySession(request); + + if (plugin.getVersion() == null) { + PluginVersionRequest versionRequest = + new DefaultPluginVersionRequest(mavenPlugin, repositorySystemSession, project.getRemotePluginRepositories()); + mavenPlugin.setVersion(getComponent(PluginVersionResolver.class).resolve(versionRequest).getVersion()); + } + + PluginDescriptor result = getComponent(MavenPluginManager.class).getPluginDescriptor(mavenPlugin, + project.getRemotePluginRepositories(), + repositorySystemSession); Map resolvedArtifacts = new THashMap(); From 90a8c088cb4139eb7520de7f430d81cec1ee34a7 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 9 Oct 2012 20:13:53 +0200 Subject: [PATCH 02/12] fix test and remove duplicate test --- .../convert2NestedIfs/Staircase_after.java | 10 ----- .../OneLevelStaircase.java | 2 + .../convert_to_nested_if}/Staircase.java | 2 + .../convert_to_nested_if/Staircase_after.java | 8 ++++ .../bool/ConvertToNestedIfsIntentionTest.java | 39 ------------------- .../ConvertToNestedIfIntentionTest.java | 2 + 6 files changed, 14 insertions(+), 49 deletions(-) delete mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase_after.java rename plugins/IntentionPowerPak/test/com/siyeh/ipp/{bool/convert2NestedIfs => trivialif/convert_to_nested_if}/OneLevelStaircase.java (59%) rename plugins/IntentionPowerPak/test/com/siyeh/ipp/{bool/convert2NestedIfs => trivialif/convert_to_nested_if}/Staircase.java (60%) create mode 100644 plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase_after.java delete mode 100644 plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/bool/ConvertToNestedIfsIntentionTest.java diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase_after.java deleted file mode 100644 index a3bf486ac164..000000000000 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase_after.java +++ /dev/null @@ -1,10 +0,0 @@ -public class X { - boolean f(boolean a, boolean b) { - if (a) { - if (b) { - return true; - } - } - return false; - } -} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/OneLevelStaircase.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/OneLevelStaircase.java similarity index 59% rename from plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/OneLevelStaircase.java rename to plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/OneLevelStaircase.java index 2e44ca28543a..9b5c570eae63 100644 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/OneLevelStaircase.java +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/OneLevelStaircase.java @@ -1,3 +1,5 @@ +package com.siyeh.ipp.trivialif.convert_to_nested_if; + public class X { boolean f(boolean a, boolean b) { return a; diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase.java similarity index 60% rename from plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase.java rename to plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase.java index ced47e2ecfa7..a6ab34537b11 100644 --- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/bool/convert2NestedIfs/Staircase.java +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase.java @@ -1,3 +1,5 @@ +package com.siyeh.ipp.trivialif.convert_to_nested_if; + public class X { boolean f(boolean a, boolean b) { return a && b; diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase_after.java new file mode 100644 index 000000000000..1b3a326fcbe9 --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/trivialif/convert_to_nested_if/Staircase_after.java @@ -0,0 +1,8 @@ +package com.siyeh.ipp.trivialif.convert_to_nested_if; + +public class X { + boolean f(boolean a, boolean b) { + if (a) if (b) return true; + return false; + } +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/bool/ConvertToNestedIfsIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/bool/ConvertToNestedIfsIntentionTest.java deleted file mode 100644 index 937499bcff3a..000000000000 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/bool/ConvertToNestedIfsIntentionTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2000-2012 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.bool; - -import com.intellij.codeInsight.intention.IntentionAction; -import com.siyeh.IntentionPowerPackBundle; -import com.siyeh.ipp.IPPTestCase; - -public class ConvertToNestedIfsIntentionTest extends IPPTestCase { - public void testStaircase() { doTest(); } - public void testOneLevelStaircase() { - final String testName = getTestName(false); - final IntentionAction intention = myFixture.getAvailableIntention(getIntentionName(), testName + ".java"); - assertTrue(intention == null); - } - - @Override - protected String getIntentionName() { - return IntentionPowerPackBundle.message("convert.to.nested.if.intention.name"); - } - - @Override - protected String getRelativePath() { - return "bool/convert2NestedIfs"; - } -} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ConvertToNestedIfIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ConvertToNestedIfIntentionTest.java index 79c6e9129775..338f4da9b4e9 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ConvertToNestedIfIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/trivialif/ConvertToNestedIfIntentionTest.java @@ -21,6 +21,8 @@ import com.siyeh.ipp.IPPTestCase; public class ConvertToNestedIfIntentionTest extends IPPTestCase { public void testNested() { doTest(); } + public void testStaircase() { doTest(); } + public void testOneLevelStaircase() { assertIntentionNotAvailable(); } @Override protected String getIntentionName() { From e0504f5cc35f05d12a999184668b19f8982d664a Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 9 Oct 2012 18:41:28 +0200 Subject: [PATCH 03/12] plugins browser: more place for date (IDEA-92630) --- .../com/intellij/ide/plugins/AvailablePluginsManagerMain.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java index ad6b174055e8..71d0cb4b8723 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java @@ -88,7 +88,7 @@ public class AvailablePluginsManagerMain extends PluginManagerMain { pluginTable.getTableHeader().setReorderingAllowed(false); pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_DOWNLOADS, 70); pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_DATE, 50); - pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_RATE, 60); + pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_RATE, 80); return ScrollPaneFactory.createScrollPane(pluginTable); } From 2e599091fdd8aef6c30d87ca7bb962be4ad64029 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 9 Oct 2012 19:22:15 +0200 Subject: [PATCH 04/12] methods refs: check if default constructor is acceptable --- .../tree/java/PsiMethodReferenceExpressionImpl.java | 13 +++++++++++-- .../lambda/methodRef/DefaultConstructor.java | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 9c2e94b5c42b..5e9b995e3c9f 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -279,6 +279,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult); + final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(resolveResult.getSubstitutor()) : null; final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType); final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(PsiMethodReferenceExpressionImpl.this); if (isConstructor && interfaceMethod != null) { @@ -293,11 +294,19 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase if (containingClass.getConstructors().length == 0 && !containingClass.isEnum() && !containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) { - return new JavaResolveResult[]{new ClassCandidateInfo(containingClass, substitutor)}; + boolean hasReceiver = false; + final PsiType[] parameterTypes = signature.getParameterTypes(); + + if (parameterTypes.length == 1 && LambdaUtil.isReceiverType(parameterTypes[0], containingClass, substitutor)) { + hasReceiver = true; + } + if (parameterTypes.length == 0 || hasReceiver && !(containingClass.getContainingClass() == null || containingClass.hasModifierProperty(PsiModifier.STATIC))) { + return new JavaResolveResult[]{new ClassCandidateInfo(containingClass, substitutor)}; + } + return JavaResolveResult.EMPTY_ARRAY; } } - final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(resolveResult.getSubstitutor()) : null; final MethodReferenceConflictResolver conflictResolver = new MethodReferenceConflictResolver(containingClass, substitutor, signature, beginsWithReferenceType); final PsiConflictResolver[] resolvers; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/DefaultConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/DefaultConstructor.java index 84a3de3b8280..d216021ee7ca 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/DefaultConstructor.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/DefaultConstructor.java @@ -44,3 +44,15 @@ class DefaultConstructor1 { Runnable b1 = DefaultConstructor1 :: new; } } + +class DefaultConstructor2 { + interface I { + void foo(DefaultConstructor2 e); + } + + + void f() { + I i1 = DefaultConstructor2 :: new; + I i2 = this::new; + } +} From fced71498b5259e6b25f8fdaad5e890891993432 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 9 Oct 2012 20:22:06 +0200 Subject: [PATCH 05/12] anonymous can be method reference inspection --- ...onymousCanBeMethodReferenceInspection.java | 135 ++++++++++ .../LambdaCanBeMethReferenceInspection.java | 250 ++++++++++-------- .../anonymous2methodReference/after1.java | 13 + .../afterInsertCast.java | 14 + .../anonymous2methodReference/before1.java | 18 ++ .../beforeInsertCast.java | 19 ++ .../beforeRecursive.java | 15 ++ ...onymous2MethodReferenceInspectionTest.java | 37 +++ .../Anonymous2MethodRef.html | 7 + resources/src/META-INF/IdeaPlugin.xml | 3 + 10 files changed, 401 insertions(+), 110 deletions(-) create mode 100644 java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/after1.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterInsertCast.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/before1.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeInsertCast.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeRecursive.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java create mode 100644 resources-en/src/inspectionDescriptions/Anonymous2MethodRef.html diff --git a/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java new file mode 100644 index 000000000000..d4fddb4068d2 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInspection/AnonymousCanBeMethodReferenceInspection.java @@ -0,0 +1,135 @@ +/* + * Copyright 2000-2012 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.codeInspection; + +import com.intellij.codeInsight.daemon.GroupNames; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.RedundantCastUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; + +/** + * User: anna + */ +public class AnonymousCanBeMethodReferenceInspection extends BaseJavaLocalInspectionTool { + public static final Logger LOG = Logger.getInstance("#" + AnonymousCanBeMethodReferenceInspection.class.getName()); + + @Nls + @NotNull + @Override + public String getGroupDisplayName() { + return GroupNames.LANGUAGE_LEVEL_SPECIFIC_GROUP_NAME; + } + + @Nls + @NotNull + @Override + public String getDisplayName() { + return "Anonymous type can be replaced with method reference"; + } + + @Override + public boolean isEnabledByDefault() { + return true; + } + + @NotNull + @Override + public String getShortName() { + return "Anonymous2MethodRef"; + } + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { + return new JavaElementVisitor() { + @Override + public void visitAnonymousClass(PsiAnonymousClass aClass) { + super.visitAnonymousClass(aClass); + if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) { + final PsiClassType baseClassType = aClass.getBaseClassType(); + final String functionalInterfaceErrorMessage = LambdaUtil.checkInterfaceFunctional(baseClassType); + if (functionalInterfaceErrorMessage == null) { + final PsiMethod[] methods = aClass.getMethods(); + if (methods.length == 1 && aClass.getFields().length == 0) { + final PsiCodeBlock body = methods[0].getBody(); + final PsiCallExpression callExpression = + LambdaCanBeMethReferenceInspection.canBeMethodReferenceProblem(body, methods[0].getParameterList().getParameters()); + if (callExpression != null && callExpression.resolveMethod() != methods[0]) { + final PsiElement parent = aClass.getParent(); + if (parent instanceof PsiNewExpression) { + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)parent).getClassOrAnonymousClassReference(); + if (classReference != null) { + holder.registerProblem(classReference, + "Anonymous type can be replaced with method reference", new ReplaceWithMethodRefFix()); + } + } + } + } + } + } + } + }; + } + + private static class ReplaceWithMethodRefFix implements LocalQuickFix { + @NotNull + @Override + public String getName() { + return "Replace with method reference"; + } + + @NotNull + @Override + public String getFamilyName() { + return getName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement element = descriptor.getPsiElement(); + final PsiAnonymousClass anonymousClass = PsiTreeUtil.getParentOfType(element, PsiAnonymousClass.class); + if (anonymousClass == null) return; + final PsiMethod[] methods = anonymousClass.getMethods(); + if (methods.length != 1) return; + + final PsiParameter[] parameters = methods[0].getParameterList().getParameters(); + final PsiCallExpression callExpression = LambdaCanBeMethReferenceInspection.canBeMethodReferenceProblem(methods[0].getBody(), parameters); + if (callExpression == null) return; + final String methodRefText = + LambdaCanBeMethReferenceInspection.createMethodReferenceText(callExpression, parameters); + + if (methodRefText != null) { + final String canonicalText = anonymousClass.getBaseClassType().getCanonicalText(); + final PsiExpression psiExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText("(" + canonicalText + ")" + methodRefText, anonymousClass); + + PsiElement castExpr = anonymousClass.getParent().replace(psiExpression); + if (RedundantCastUtil.isCastRedundant((PsiTypeCastExpression)castExpr)) { + final PsiExpression operand = ((PsiTypeCastExpression)castExpr).getOperand(); + LOG.assertTrue(operand != null); + castExpr = castExpr.replace(operand); + } + JavaCodeStyleManager.getInstance(project).shortenClassReferences(castExpr); + } + } + } +} diff --git a/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java b/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java index 056e6cbac9b7..fda1b3f8af09 100644 --- a/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/LambdaCanBeMethReferenceInspection.java @@ -25,6 +25,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * User: anna @@ -66,87 +67,148 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT super.visitLambdaExpression(expression); if (PsiUtil.getLanguageLevel(expression).isAtLeast(LanguageLevel.JDK_1_8)) { final PsiElement body = expression.getBody(); - PsiCallExpression methodCall = null; - if (body instanceof PsiCallExpression) { - methodCall = (PsiCallExpression)body; - } else if (body instanceof PsiCodeBlock) { - final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements(); - if (statements.length == 1) { - if (statements[0] instanceof PsiReturnStatement) { - final PsiExpression returnValue = ((PsiReturnStatement)statements[0]).getReturnValue(); - if (returnValue instanceof PsiCallExpression) { - methodCall = (PsiCallExpression)returnValue; - } - } else if (statements[0] instanceof PsiExpressionStatement) { - final PsiExpression expr = ((PsiExpressionStatement)statements[0]).getExpression(); - if (expr instanceof PsiCallExpression) { - methodCall = (PsiCallExpression)expr; - } - } - } - } - - if (methodCall != null) { - final PsiExpressionList argumentList = methodCall.getArgumentList(); - if (argumentList != null) { - final PsiParameter[] parameters = expression.getParameterList().getParameters(); - final PsiExpression[] expressions = argumentList.getExpressions(); - - final PsiMethod psiMethod = methodCall.resolveMethod(); - final PsiClass containingClass; - boolean isConstructor; - if (psiMethod == null) { - isConstructor = true; - if (!(methodCall instanceof PsiNewExpression)) return; - final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)methodCall).getClassOrAnonymousClassReference(); - if (classReference == null) return; - containingClass = (PsiClass)classReference.resolve(); - } else { - containingClass = psiMethod.getContainingClass(); - isConstructor = psiMethod.isConstructor(); - } - if (containingClass == null) return; - boolean isReceiverType = parameters.length > 0 && LambdaUtil.isReceiverType(parameters[0].getType(), containingClass, PsiUtil.resolveGenericsClassInType(parameters[0].getType()).getSubstitutor()); - final boolean staticOrValidConstructorRef; - if (isConstructor) { - staticOrValidConstructorRef = - (containingClass.getContainingClass() == null || containingClass.hasModifierProperty(PsiModifier.STATIC)); - } else { - staticOrValidConstructorRef = psiMethod.hasModifierProperty(PsiModifier.STATIC); - } - - final int offset = isReceiverType && !staticOrValidConstructorRef ? 1 : 0; - if (parameters.length != expressions.length + offset) return; - - for (int i = 0; i < expressions.length; i++) { - PsiExpression psiExpression = expressions[i]; - if (!(psiExpression instanceof PsiReferenceExpression)) return; - final PsiElement resolve = ((PsiReferenceExpression)psiExpression).resolve(); - if (resolve == null) return; - if (parameters[i + offset] != resolve) return; - } - - if (offset > 0) { - final PsiExpression qualifierExpression; - if (methodCall instanceof PsiMethodCallExpression) { - qualifierExpression = ((PsiMethodCallExpression)methodCall).getMethodExpression().getQualifierExpression(); - } else if (methodCall instanceof PsiNewExpression) { - qualifierExpression = ((PsiNewExpression)methodCall).getQualifier(); - } else { - qualifierExpression = null; - } - if (!(qualifierExpression instanceof PsiReferenceExpression) || ((PsiReferenceExpression)qualifierExpression).resolve() != parameters[0]) return; - } - holder.registerProblem(methodCall, - "Can be replaced with method reference", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithMethodRefFix()); - } + final PsiCallExpression callExpression = canBeMethodReferenceProblem(body, expression.getParameterList().getParameters()); + if (callExpression != null) { + holder.registerProblem(callExpression, + "Can be replaced with method reference", + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new ReplaceWithMethodRefFix()); } } } }; } + @Nullable + protected static PsiCallExpression canBeMethodReferenceProblem(@Nullable final PsiElement body, final PsiParameter[] parameters) { + PsiCallExpression methodCall = null; + if (body instanceof PsiCallExpression) { + methodCall = (PsiCallExpression)body; + } + else if (body instanceof PsiCodeBlock) { + final PsiStatement[] statements = ((PsiCodeBlock)body).getStatements(); + if (statements.length == 1) { + if (statements[0] instanceof PsiReturnStatement) { + final PsiExpression returnValue = ((PsiReturnStatement)statements[0]).getReturnValue(); + if (returnValue instanceof PsiCallExpression) { + methodCall = (PsiCallExpression)returnValue; + } + } + else if (statements[0] instanceof PsiExpressionStatement) { + final PsiExpression expr = ((PsiExpressionStatement)statements[0]).getExpression(); + if (expr instanceof PsiCallExpression) { + methodCall = (PsiCallExpression)expr; + } + } + } + } + + if (methodCall != null) { + final PsiExpressionList argumentList = methodCall.getArgumentList(); + if (argumentList != null) { + final PsiExpression[] expressions = argumentList.getExpressions(); + + final PsiMethod psiMethod = methodCall.resolveMethod(); + final PsiClass containingClass; + boolean isConstructor; + if (psiMethod == null) { + isConstructor = true; + if (!(methodCall instanceof PsiNewExpression)) return null; + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)methodCall).getClassOrAnonymousClassReference(); + if (classReference == null) return null; + containingClass = (PsiClass)classReference.resolve(); + } + else { + containingClass = psiMethod.getContainingClass(); + isConstructor = psiMethod.isConstructor(); + } + if (containingClass == null) return null; + boolean isReceiverType = parameters.length > 0 && LambdaUtil.isReceiverType(parameters[0].getType(), containingClass, PsiUtil + .resolveGenericsClassInType(parameters[0].getType()).getSubstitutor()); + final boolean staticOrValidConstructorRef; + if (isConstructor) { + staticOrValidConstructorRef = + (containingClass.getContainingClass() == null || containingClass.hasModifierProperty(PsiModifier.STATIC)); + } + else { + staticOrValidConstructorRef = psiMethod.hasModifierProperty(PsiModifier.STATIC); + } + + final int offset = isReceiverType && !staticOrValidConstructorRef ? 1 : 0; + if (parameters.length != expressions.length + offset) return null; + + for (int i = 0; i < expressions.length; i++) { + PsiExpression psiExpression = expressions[i]; + if (!(psiExpression instanceof PsiReferenceExpression)) return null; + final PsiElement resolve = ((PsiReferenceExpression)psiExpression).resolve(); + if (resolve == null) return null; + if (parameters[i + offset] != resolve) return null; + } + + if (offset > 0) { + final PsiExpression qualifierExpression; + if (methodCall instanceof PsiMethodCallExpression) { + qualifierExpression = ((PsiMethodCallExpression)methodCall).getMethodExpression().getQualifierExpression(); + } + else if (methodCall instanceof PsiNewExpression) { + qualifierExpression = ((PsiNewExpression)methodCall).getQualifier(); + } + else { + qualifierExpression = null; + } + if (!(qualifierExpression instanceof PsiReferenceExpression) || + ((PsiReferenceExpression)qualifierExpression).resolve() != parameters[0]) { + return null; + } + } + return methodCall; + } + } + return null; + } + + @Nullable + protected static String createMethodReferenceText(PsiElement element, final PsiParameter[] parameters) { + String methodRefText = null; + if (element instanceof PsiMethodCallExpression) { + final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element; + final PsiMethod psiMethod = methodCall.resolveMethod(); + LOG.assertTrue(psiMethod != null); + final PsiClass containingClass = psiMethod.getContainingClass(); + LOG.assertTrue(containingClass != null); + final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); + final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); + final String methodReferenceName = methodExpression.getReferenceName(); + if (qualifierExpression != null) { + boolean isReceiverType = parameters.length > 0 && LambdaUtil.isReceiverType(parameters[0].getType(), containingClass, PsiUtil + .resolveGenericsClassInType(parameters[0].getType()).getSubstitutor()); + methodRefText = (isReceiverType ? containingClass.getQualifiedName() : qualifierExpression.getText()) + "::" + methodReferenceName; + } + else { + methodRefText = + (psiMethod.hasModifierProperty(PsiModifier.STATIC) ? containingClass.getQualifiedName() : "this") + "::" + methodReferenceName; + } + } + else if (element instanceof PsiNewExpression) { + final PsiMethod constructor = ((PsiNewExpression)element).resolveConstructor(); + if (constructor != null) { + final PsiClass containingClass = constructor.getContainingClass(); + LOG.assertTrue(containingClass != null); + methodRefText = containingClass.getQualifiedName() + "::new"; + } + else { + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)element).getClassOrAnonymousClassReference(); + if (classReference != null) { + final JavaResolveResult resolve = classReference.advancedResolve(false); + final PsiElement containingClass = resolve.getElement(); + if (containingClass instanceof PsiClass) { + methodRefText = ((PsiClass)containingClass).getQualifiedName() + "::new"; + } + } + } + } + return methodRefText; + } + private static class ReplaceWithMethodRefFix implements LocalQuickFix { @NotNull @Override @@ -165,43 +227,11 @@ public class LambdaCanBeMethReferenceInspection extends BaseJavaLocalInspectionT final PsiElement element = descriptor.getPsiElement(); final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class); if (lambdaExpression == null) return; - String methodRefText = null; - if (element instanceof PsiMethodCallExpression) { - final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element; - final PsiMethod psiMethod = methodCall.resolveMethod(); - LOG.assertTrue(psiMethod != null); - final PsiClass containingClass = psiMethod.getContainingClass(); - LOG.assertTrue(containingClass != null); - final PsiReferenceExpression methodExpression = methodCall.getMethodExpression(); - final PsiExpression qualifierExpression = methodExpression.getQualifierExpression(); - final String methodReferenceName = methodExpression.getReferenceName(); - if (qualifierExpression != null) { - final PsiParameter[] parameters = lambdaExpression.getParameterList().getParameters(); - boolean isReceiverType = parameters.length > 0 && LambdaUtil.isReceiverType(parameters[0].getType(), containingClass, PsiUtil.resolveGenericsClassInType(parameters[0].getType()).getSubstitutor()); - methodRefText = (isReceiverType ? containingClass.getQualifiedName() : qualifierExpression.getText()) + "::" + methodReferenceName; - } else { - methodRefText = (psiMethod.hasModifierProperty(PsiModifier.STATIC) ? containingClass.getQualifiedName() : "this") + "::" + methodReferenceName; - } - } else if (element instanceof PsiNewExpression) { - final PsiMethod constructor = ((PsiNewExpression)element).resolveConstructor(); - if (constructor != null) { - final PsiClass containingClass = constructor.getContainingClass(); - LOG.assertTrue(containingClass != null); - methodRefText = containingClass.getQualifiedName() + "::new"; - } else { - final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)element).getClassOrAnonymousClassReference(); - if (classReference != null) { - final JavaResolveResult resolve = classReference.advancedResolve(false); - final PsiElement containingClass = resolve.getElement(); - if (containingClass instanceof PsiClass) { - methodRefText = ((PsiClass)containingClass).getQualifiedName() + "::new"; - } - } - } - } + final String methodRefText = createMethodReferenceText(element, lambdaExpression.getParameterList().getParameters()); if (methodRefText != null) { - final PsiExpression psiExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText(methodRefText, lambdaExpression); + final PsiExpression psiExpression = + JavaPsiFacade.getElementFactory(project).createExpressionFromText(methodRefText, lambdaExpression); JavaCodeStyleManager.getInstance(project).shortenClassReferences(lambdaExpression.replace(psiExpression)); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/after1.java new file mode 100644 index 000000000000..d5d6320a0e94 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/after1.java @@ -0,0 +1,13 @@ +// "Replace with method reference" "true" +class Test { + interface Bar { + int compare(String o1, String o2); + } + static int c(String o1, String o2) { + return 0; + } + + { + Bar bar2 = Test::c; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterInsertCast.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterInsertCast.java new file mode 100644 index 000000000000..f0dffef5fb5a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/afterInsertCast.java @@ -0,0 +1,14 @@ +// "Replace with method reference" "true" +class Test { + interface I {} + interface Bar extends I { + int compare(String o1, String o2); + } + static int c(String o1, String o2) { + return 0; + } + + { + I bar2 = (Bar) Test::c; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/before1.java new file mode 100644 index 000000000000..7ca24f152943 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/before1.java @@ -0,0 +1,18 @@ +// "Replace with method reference" "true" +class Test { + interface Bar { + int compare(String o1, String o2); + } + static int c(String o1, String o2) { + return 0; + } + + { + Bar bar2 = new Bar() { + @Override + public int compare(final String o1, final String o2) { + return c(o1, o2); + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeInsertCast.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeInsertCast.java new file mode 100644 index 000000000000..9a0caa2d6fc3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeInsertCast.java @@ -0,0 +1,19 @@ +// "Replace with method reference" "true" +class Test { + interface I {} + interface Bar extends I { + int compare(String o1, String o2); + } + static int c(String o1, String o2) { + return 0; + } + + { + I bar2 = new Bar() { + @Override + public int compare(final String o1, final String o2) { + return c(o1, o2); + } + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeRecursive.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeRecursive.java new file mode 100644 index 000000000000..6b58d667789c --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference/beforeRecursive.java @@ -0,0 +1,15 @@ +// "Replace with method reference" "false" +class Test { + public interface I { + int m(); + } + { + I i = new I() { + @Override + public int m() { + return m(); + } + }; + + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java new file mode 100644 index 000000000000..e7fb3bedbf44 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java @@ -0,0 +1,37 @@ +/* + * Copyright 2000-2012 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.codeInsight.daemon.quickFix; + +import com.intellij.codeInspection.AnonymousCanBeMethodReferenceInspection; +import com.intellij.codeInspection.LocalInspectionTool; + + +public class Anonymous2MethodReferenceInspectionTest extends LightQuickFixTestCase { + @Override + protected LocalInspectionTool[] configureLocalInspectionTools() { + return new LocalInspectionTool[]{ + new AnonymousCanBeMethodReferenceInspection(), + }; + } + + public void test() throws Exception { doAllTests(); } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2methodReference"; + } + +} \ No newline at end of file diff --git a/resources-en/src/inspectionDescriptions/Anonymous2MethodRef.html b/resources-en/src/inspectionDescriptions/Anonymous2MethodRef.html new file mode 100644 index 000000000000..c290c39e344d --- /dev/null +++ b/resources-en/src/inspectionDescriptions/Anonymous2MethodRef.html @@ -0,0 +1,7 @@ + + +This inspection reports anonymous types which can be replaced with method references +

+Method references syntax is not supported under Java 1.7 or earlier JVMs. + + \ No newline at end of file diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e3565e6938d2..6e543b53851f 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -540,6 +540,9 @@ + From 96e8aafa0c94095370944764acfdf4bfb78384be Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Tue, 9 Oct 2012 20:31:42 +0200 Subject: [PATCH 06/12] small help icon + regenerate icons classes --- platform/icons/src/general/help_small.png | Bin 0 -> 329 bytes .../intellij/codeInsight/hint/HintUtil.java | 2 +- .../util/src/com/intellij/icons/AllIcons.java | 1 + .../tasks-core/src/icons/TasksIcons.java | 32 +++++++++++++----- 4 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 platform/icons/src/general/help_small.png diff --git a/platform/icons/src/general/help_small.png b/platform/icons/src/general/help_small.png new file mode 100644 index 0000000000000000000000000000000000000000..6c04835138fa869edd4c1af4bd3800cd007b499f GIT binary patch literal 329 zcmV-P0k-~$P)q$gGRCwBA{Qv(y10{fofkHsB0W8=A zt&95Em|0kwn3upMU}9mpOL8EZ=JaI!{rh+QpWnaV{rdSUkt72QGde0++1aK71N6rCZ$C`-HKm*- z$_p^S%Fdq8!p{C5XtV3luI$&?)G*RCCF&)&uF^|sT|ja|f}7676w2`b|3`dk7>9ml b0thew)Vozq?n}|P00000NkvXXu0mjfk2jVT literal 0 HcmV?d00001 diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java index 160202b9d053..e199dc37ca11 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java @@ -113,7 +113,7 @@ public class HintUtil { HintLabel label = new HintLabel(); label.setText(text, hintHint); - label.setIcon(AllIcons.Actions.Help); + label.setIcon(AllIcons.General.Help_small); if (!hintHint.isAwtTooltip()) { label.setBorder(createHintBorder()); diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java index 851591055471..4116ba558672 100644 --- a/platform/util/src/com/intellij/icons/AllIcons.java +++ b/platform/util/src/com/intellij/icons/AllIcons.java @@ -383,6 +383,7 @@ public class AllIcons { public static final Icon GearHover = IconLoader.getIcon("/general/gearHover.png"); // 21x16 public static final Icon GetProjectfromVCS = IconLoader.getIcon("/general/getProjectfromVCS.png"); // 48x48 public static final Icon Help = IconLoader.getIcon("/general/help.png"); // 10x10 + public static final Icon Help_small = IconLoader.getIcon("/general/help_small.png"); // 16x16 public static final Icon HideDown = IconLoader.getIcon("/general/hideDown.png"); // 16x16 public static final Icon HideDownHover = IconLoader.getIcon("/general/hideDownHover.png"); // 16x16 public static final Icon HideDownPart = IconLoader.getIcon("/general/hideDownPart.png"); // 16x16 diff --git a/plugins/tasks/tasks-core/src/icons/TasksIcons.java b/plugins/tasks/tasks-core/src/icons/TasksIcons.java index 319c687910dc..eb92b1bc83b3 100644 --- a/plugins/tasks/tasks-core/src/icons/TasksIcons.java +++ b/plugins/tasks/tasks-core/src/icons/TasksIcons.java @@ -1,3 +1,18 @@ +/* + * Copyright 2000-2012 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 icons; import com.intellij.openapi.util.IconLoader; @@ -16,19 +31,12 @@ public class TasksIcons { public static final Icon Bug = load("/icons/bug.png"); // 16x16 public static final Icon Exception = load("/icons/exception.png"); // 16x16 public static final Icon Feature = load("/icons/feature.png"); // 16x16 - public static final Icon Other = load("/icons/other.png"); // 16x16 - public static final Icon Unknown = load("/icons/unknown.png"); // 16x16 - public static final Icon SavedContext = load("/icons/savedContext.png"); // 16x16 - public static final Icon Fogbugz = load("/icons/fogbugz.png"); // 16x16 public static final Icon Github = load("/icons/github.png"); // 16x16 public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16 public static final Icon Mantis = load("/icons/mantis.png"); // 16x16 - public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16 - public static final Icon Redmine = load("/icons/redmine.png"); // 16x16 - public static final Icon Trac = load("/icons/trac.png"); // 16x16 - public static final Icon Youtrack = load("/icons/youtrack.png"); // 16x16 - + public static final Icon Other = load("/icons/other.png"); // 16x16 + public static class Pivotal { public static final Icon Bug = load("/icons/pivotal/bug.png"); // 14x14 public static final Icon Chore = load("/icons/pivotal/chore.png"); // 14x14 @@ -36,4 +44,10 @@ public class TasksIcons { public static final Icon Release = load("/icons/pivotal/release.png"); // 14x14 } + public static final Icon Pivotal = load("/icons/pivotal.png"); // 16x16 + public static final Icon Redmine = load("/icons/redmine.png"); // 16x16 + public static final Icon SavedContext = load("/icons/savedContext.png"); // 16x16 + public static final Icon Trac = load("/icons/trac.png"); // 16x16 + public static final Icon Unknown = load("/icons/unknown.png"); // 16x16 + public static final Icon Youtrack = load("/icons/youtrack.png"); // 16x16 } From 821ff7155c395c9ade84ae6241b73a89f87b66f7 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 9 Oct 2012 20:38:04 +0200 Subject: [PATCH 07/12] EA-39675 - CCE: ActionsTreeUtil.fillGroupIgnorePopupFlag --- .../src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java index 6517c49b261f..4965ae040380 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java @@ -160,6 +160,7 @@ public class ActionsTreeUtil { ? ((DefaultActionGroup)actionGroup).getChildActionsOrStubs() : actionGroup.getChildren(null); for (AnAction action : mainMenuTopGroups) { + if (!(action instanceof ActionGroup)) continue; Group subGroup = createGroup((ActionGroup)action, false, filtered); if (subGroup.getSize() > 0) { group.addGroup(subGroup); From acc41142c1e52ceb710e8674fbcb498d21986820 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 9 Oct 2012 20:39:56 +0200 Subject: [PATCH 08/12] logging for EA-39655 - assert: MoveClassToInnerProcessor.performRefactoring --- .../move/moveClassesOrPackages/MoveClassToInnerProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java index 5fbfa3313d35..7aed2d8a03bc 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassToInnerProcessor.java @@ -144,7 +144,7 @@ public class MoveClassToInnerProcessor extends BaseRefactoringProcessor { newClass = handler.moveClass(classToMove, myTargetClass); if (newClass != null) break; } - LOG.assertTrue(newClass != null, "There is no appropriate MoveClassToInnerHandler!"); + LOG.assertTrue(newClass != null, "There is no appropriate MoveClassToInnerHandler for " + myTargetClass + "; " + classToMove); oldToNewElementsMapping.put(classToMove, newClass); } From 253967845c94634b30b82d96040ead51294c2cc6 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 9 Oct 2012 12:40:11 +0200 Subject: [PATCH 09/12] new dummy project is internal action (IDEA-92604) --- platform/platform-resources/src/idea/PlatformActions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml index 43099147515f..d1cb91fecc37 100644 --- a/platform/platform-resources/src/idea/PlatformActions.xml +++ b/platform/platform-resources/src/idea/PlatformActions.xml @@ -137,7 +137,7 @@ - + From bb1a413d86c60fae11e538ffba570d588f2058fe Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 9 Oct 2012 21:25:58 +0200 Subject: [PATCH 10/12] casing --- .../platform-resources-en/src/messages/CommonBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/CommonBundle.properties b/platform/platform-resources-en/src/messages/CommonBundle.properties index e17f4416c622..fb8dd67fc4ba 100644 --- a/platform/platform-resources-en/src/messages/CommonBundle.properties +++ b/platform/platform-resources-en/src/messages/CommonBundle.properties @@ -14,7 +14,7 @@ checkbox.remember.password=&Remember password editbox.login=&Login: checkbox.use.http.proxy=&Use HTTP proxy checkbox.proxy.authentication=Proxy &authentication -checkbox.use.http.proxy.pac=Auto-Detect Proxy Settings +checkbox.use.http.proxy.pac=Auto-detect proxy settings tooltip.http.proxy.pac=This will attempt to use your system settings and is useful if your system uses a proxy autoconfiguration file (.pac). editbox.port.number= Port &number: editbox.host.name= &Host name: From 8dd16279c13d3ca80eaaf816496190d64903fd36 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 9 Oct 2012 21:37:51 +0200 Subject: [PATCH 11/12] IDEA-71186 (Inspections / Imports / Redundant import: false positive with static imports of deeply nested elements) --- .../ig/imports/RedundantImportInspection.java | 55 +++++++------------ 1 file changed, 21 insertions(+), 34 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/RedundantImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/RedundantImportInspection.java index a755713227d0..d7efafe91620 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/RedundantImportInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/RedundantImportInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,15 +32,13 @@ public class RedundantImportInspection extends BaseInspection { @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "redundant.import.display.name"); + return InspectionGadgetsBundle.message("redundant.import.display.name"); } @Override @NotNull public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "redundant.import.problem.descriptor"); + return InspectionGadgetsBundle.message("redundant.import.problem.descriptor"); } @Override @@ -73,51 +71,42 @@ public class RedundantImportInspection extends BaseInspection { checkStaticImports(importList, javaFile); } - private void checkStaticImports(PsiImportList importList, - PsiJavaFile javaFile) { - final PsiImportStaticStatement[] importStaticStatements = - importList.getImportStaticStatements(); - final Set staticImports = - new HashSet(importStaticStatements.length); - for (PsiImportStaticStatement importStaticStatement : - importStaticStatements) { - final String referenceName = - importStaticStatement.getReferenceName(); - final PsiClass targetClass = - importStaticStatement.resolveTargetClass(); + private void checkStaticImports(PsiImportList importList, PsiJavaFile javaFile) { + final PsiImportStaticStatement[] importStaticStatements = importList.getImportStaticStatements(); + final Set onDemandStaticImports = new HashSet(); + final Set singleMemberStaticImports = new HashSet(); + for (PsiImportStaticStatement importStaticStatement : importStaticStatements) { + final PsiClass targetClass = importStaticStatement.resolveTargetClass(); if (targetClass == null) { continue; } final String qualifiedName = targetClass.getQualifiedName(); + final String referenceName = importStaticStatement.getReferenceName(); if (referenceName == null) { - if (staticImports.contains(qualifiedName)) { + if (onDemandStaticImports.contains(qualifiedName)) { registerError(importStaticStatement); continue; } - staticImports.add(qualifiedName); + onDemandStaticImports.add(qualifiedName); } else { - final String qualifiedReferenceName = - qualifiedName + '.' + referenceName; - if (staticImports.contains(qualifiedReferenceName)) { + final String qualifiedReferenceName = qualifiedName + '.' + referenceName; + if (singleMemberStaticImports.contains(qualifiedReferenceName)) { registerError(importStaticStatement); continue; } - if (staticImports.contains(qualifiedName)) { - if (!ImportUtils.hasOnDemandImportConflict( - qualifiedReferenceName, javaFile)) { + if (onDemandStaticImports.contains(qualifiedName)) { + if (!ImportUtils.hasOnDemandImportConflict(qualifiedReferenceName, javaFile)) { registerError(importStaticStatement); } } - staticImports.add(qualifiedReferenceName); + singleMemberStaticImports.add(qualifiedReferenceName); } } } - private void checkNonStaticImports(PsiImportList importList, - PsiJavaFile javaFile) { - final PsiImportStatement[] importStatements = - importList.getImportStatements(); + private void checkNonStaticImports(PsiImportList importList, PsiJavaFile javaFile) { + final PsiImportStatement[] importStatements = importList.getImportStatements(); final Set onDemandImports = new HashSet(); final Set singleClassImports = new HashSet(); for (final PsiImportStatement importStatement : importStatements) { @@ -157,10 +146,8 @@ public class RedundantImportInspection extends BaseInspection { continue; } if (onDemandImports.contains(contextName) && - !ImportUtils.hasOnDemandImportConflict(qualifiedName, - javaFile) && - !ImportUtils.hasDefaultImportConflict(qualifiedName, - javaFile)) { + !ImportUtils.hasOnDemandImportConflict(qualifiedName, javaFile) && + !ImportUtils.hasDefaultImportConflict(qualifiedName, javaFile)) { registerError(importStatement); } singleClassImports.add(qualifiedName); From f541ed314a866c12f6148af90db54b3e98bf06ab Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Tue, 9 Oct 2012 22:28:43 +0200 Subject: [PATCH 12/12] IDEA-71293 (Inspections / Imports / Redundant Import: no warning for type import redundant due to static import) --- .../ig/imports/ImportsAreUsedVisitor.java | 112 +++++++++++------ .../imports/StaticImportsAreUsedVisitor.java | 115 ------------------ .../ig/imports/UnusedImportInspection.java | 46 ++----- .../igtest/imports/unused/UnusedImport.java | 3 + .../siyeh/igtest/imports/unused/expected.xml | 7 +- 5 files changed, 93 insertions(+), 190 deletions(-) delete mode 100644 plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java index bb97ed202bc2..6753839eb83d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/ImportsAreUsedVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,7 +15,9 @@ */ package com.siyeh.ig.imports; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -25,9 +27,10 @@ import java.util.List; class ImportsAreUsedVisitor extends JavaRecursiveElementVisitor { - private final List importStatements; + private final List importStatements; + private final List usedImportStatements = new ArrayList(); - ImportsAreUsedVisitor(PsiImportStatement[] importStatements) { + ImportsAreUsedVisitor(PsiImportStatementBase[] importStatements) { this.importStatements = new ArrayList(Arrays.asList(importStatements)); Collections.reverse(this.importStatements); } @@ -57,43 +60,81 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementVisitor { // during typing there can be incomplete code final JavaResolveResult resolveResult = reference.advancedResolve(true); final PsiElement element = resolveResult.getElement(); - if (!(element instanceof PsiClass)) { + if (element == null) { return; } - final PsiClass referencedClass = (PsiClass)element; - final String qualifiedName = referencedClass.getQualifiedName(); - if (qualifiedName == null) { + if (findImport(element, usedImportStatements) != null) { return; } - final List importStatementsCopy = - new ArrayList(importStatements); - for (PsiImportStatement importStatement : importStatementsCopy) { - final String importName = importStatement.getQualifiedName(); - if (importName == null) { - return; - } - if (importStatement.isOnDemand()) { - final int lastComponentIndex = - qualifiedName.lastIndexOf((int)'.'); - if (lastComponentIndex > 0) { - final String packageName = qualifiedName.substring(0, - lastComponentIndex); - if (importName.equals(packageName)) { - removeAll(importStatement); - break; - } - } - } - else if (importName.equals(qualifiedName)) { - removeAll(importStatement); - break; - } + final PsiImportStatementBase foundImport = findImport(element, importStatements); + if (foundImport != null) { + removeAll(foundImport); + usedImportStatements.add(foundImport); } } - private void removeAll(@NotNull PsiImportStatement importStatement) { + private static PsiImportStatementBase findImport(PsiElement element, List importStatements) { + final String qualifiedName; + final String packageName; + if (element instanceof PsiClass) { + final PsiClass referencedClass = (PsiClass)element; + qualifiedName = referencedClass.getQualifiedName(); + packageName = qualifiedName != null ? StringUtil.getPackageName(qualifiedName) : null; + } + else { + qualifiedName = null; + packageName = null; + } + final PsiClass referenceClass; + final String referenceName; + if (element instanceof PsiMember) { + final PsiMember member = (PsiMember)element; + referenceClass = member.getContainingClass(); + referenceName = member.getName(); + } + else { + referenceClass = null; + referenceName = null; + } + for (PsiImportStatementBase importStatementBase : importStatements) { + if (importStatementBase instanceof PsiImportStatement && qualifiedName != null && packageName != null) { + final PsiImportStatement importStatement = (PsiImportStatement)importStatementBase; + final String importName = importStatement.getQualifiedName(); + if (importName != null) { + if (importStatement.isOnDemand()) { + if (importName.equals(packageName)) { + return importStatement; + } + } + else if (importName.equals(qualifiedName)) { + return importStatement; + } + } + } + if (importStatementBase instanceof PsiImportStaticStatement && referenceClass != null && referenceName != null) { + final PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)importStatementBase; + if (importStaticStatement.isOnDemand()) { + final PsiClass targetClass = importStaticStatement.resolveTargetClass(); + if (InheritanceUtil.isInheritorOrSelf(targetClass, referenceClass, true)) { + return importStaticStatement; + } + } + else { + final String importReferenceName = importStaticStatement.getReferenceName(); + if (importReferenceName != null) { + if (importReferenceName.equals(referenceName)) { + return importStaticStatement; + } + } + } + } + } + return null; + } + + private void removeAll(@NotNull PsiImportStatementBase importStatement) { for (int i = importStatements.size() - 1; i >= 0; i--) { - final PsiImportStatement statement = importStatements.get(i); + final PsiImportStatementBase statement = importStatements.get(i); final String statementText = statement.getText(); final String importText = importStatement.getText(); if (importText.equals(statementText)) { @@ -102,11 +143,10 @@ class ImportsAreUsedVisitor extends JavaRecursiveElementVisitor { } } - public PsiImportStatement[] getUnusedImportStatements() { + public PsiImportStatementBase[] getUnusedImportStatements() { if (importStatements.isEmpty()) { - return PsiImportStatement.EMPTY_ARRAY; + return PsiImportStatementBase.EMPTY_ARRAY; } - return importStatements.toArray( - new PsiImportStatement[importStatements.size()]); + return importStatements.toArray(new PsiImportStatementBase[importStatements.size()]); } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java deleted file mode 100644 index 7f791e4eff0a..000000000000 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportsAreUsedVisitor.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2005-2008 Bas Leijdekkers - * - * 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.imports; - -import com.intellij.psi.*; -import com.intellij.psi.util.InheritanceUtil; -import org.jetbrains.annotations.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -class StaticImportsAreUsedVisitor extends JavaRecursiveElementVisitor { - - private final List importStatements; - - StaticImportsAreUsedVisitor(PsiImportStaticStatement[] importStatements) { - this.importStatements = new ArrayList(Arrays.asList(importStatements)); - Collections.reverse(this.importStatements); - } - - @Override - public void visitElement(PsiElement element) { - if (importStatements.isEmpty()) { - return; - } - super.visitElement(element); - } - - @Override - public void visitReferenceElement( - @NotNull PsiJavaCodeReferenceElement reference) { - followReferenceToImport(reference); - super.visitReferenceElement(reference); - } - - private void followReferenceToImport( - PsiJavaCodeReferenceElement reference) { - if (reference.getQualifier() != null) { - //it's already qualified, so the import statement wasn't - // responsible - return; - } - final String referenceName = reference.getReferenceName(); - if (referenceName == null) { - return; - } - final PsiElement element = reference.resolve(); - if (!(element instanceof PsiMember)) { - return; - } - final PsiMember member = (PsiMember)element; - final PsiClass containingClass = member.getContainingClass(); - if (containingClass == null) { - return; - } - for (PsiImportStaticStatement importStatement : importStatements) { - if (importStatement.isOnDemand()) { - final PsiClass targetClass = - importStatement.resolveTargetClass(); - if (InheritanceUtil.isInheritorOrSelf(targetClass, - containingClass, true)) { - removeAll(importStatement); - break; - } - } - else { - final String importReferenceName = - importStatement.getReferenceName(); - if (importReferenceName == null) { - continue; - } - if (importReferenceName.equals(referenceName)) { - removeAll(importStatement); - break; - } - } - } - } - - private void removeAll( - @NotNull PsiImportStaticStatement importStaticStatement) { - for (int i = importStatements.size() - 1; i >= 0; i--) { - final PsiImportStaticStatement statement = importStatements.get(i); - final String text = statement.getText(); - if (importStaticStatement.getText().equals(text)) { - importStatements.remove(i); - } - } - } - - public PsiImportStaticStatement[] getUnusedImportStaticStatements() { - if (importStatements.isEmpty()) { - return PsiImportStaticStatement.EMPTY_ARRAY; - } - else { - return importStatements.toArray( - new PsiImportStaticStatement[importStatements.size()]); - } - } -} diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java index 932186fb99ed..d745f3927339 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/UnusedImportInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,7 @@ public class UnusedImportInspection extends BaseInspection { @Override @NotNull public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "unused.import.problem.descriptor"); + return InspectionGadgetsBundle.message("unused.import.problem.descriptor"); } @Override @@ -66,8 +65,7 @@ public class UnusedImportInspection extends BaseInspection { return; } final PsiClass[] classes = file.getClasses(); - final PsiPackageStatement packageStatement = - file.getPackageStatement(); + final PsiPackageStatement packageStatement = file.getPackageStatement(); final PsiModifierList annotationList; if (packageStatement != null) { annotationList = packageStatement.getAnnotationList(); @@ -75,51 +73,23 @@ public class UnusedImportInspection extends BaseInspection { else { annotationList = null; } - final PsiImportStatement[] importStatements = - importList.getImportStatements(); + final PsiImportStatementBase[] importStatements = importList.getAllImportStatements(); checkImports(importStatements, classes, annotationList); - final PsiImportStaticStatement[] importStaticStatements = - importList.getImportStaticStatements(); - checkStaticImports(importStaticStatements, classes); } - private void checkStaticImports( - PsiImportStaticStatement[] importStaticStatements, - PsiClass[] classes) { - if (importStaticStatements.length == 0) { - return; - } - final StaticImportsAreUsedVisitor visitor = - new StaticImportsAreUsedVisitor(importStaticStatements); - for (PsiClass aClass : classes) { - aClass.accept(visitor); - } - final PsiImportStaticStatement[] unusedImportStaticStatements = - visitor.getUnusedImportStaticStatements(); - for (PsiImportStaticStatement importStaticStatement : - unusedImportStaticStatements) { - registerError(importStaticStatement); - } - } - - private void checkImports(PsiImportStatement[] importStatements, - PsiClass[] classes, - @Nullable PsiModifierList annotationList) { + private void checkImports(PsiImportStatementBase[] importStatements, PsiClass[] classes, @Nullable PsiModifierList annotationList) { if (importStatements.length == 0) { return; } - final ImportsAreUsedVisitor visitor = - new ImportsAreUsedVisitor(importStatements); + final ImportsAreUsedVisitor visitor = new ImportsAreUsedVisitor(importStatements); for (PsiClass aClass : classes) { aClass.accept(visitor); } if (annotationList != null) { annotationList.accept(visitor); } - final PsiImportStatement[] unusedImportStatements = - visitor.getUnusedImportStatements(); - for (PsiImportStatement unusedImportStatement : - unusedImportStatements) { + final PsiImportStatementBase[] unusedImportStatements = visitor.getUnusedImportStatements(); + for (PsiImportStatementBase unusedImportStatement : unusedImportStatements) { registerError(unusedImportStatement); } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java index 4c6d3d0a263a..adab39f11837 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/UnusedImport.java @@ -1,5 +1,7 @@ package com.siyeh.igtest.imports.unused; +import java.util.Map.*; +import static java.util.Map.*; import static java.lang.Math.*; import static java.lang.Integer.SIZE; import java.util.List; @@ -18,5 +20,6 @@ public class UnusedImport { public void add(int i) { list.add(i); + Entry entry; } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml index b89ca9b58144..50ba5aa23f0f 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/imports/unused/expected.xml @@ -1,4 +1,9 @@ - + + UnusedImport.java + 3 + Unused import + Unused import <code>import java.util.Map.*;</code> #loc + \ No newline at end of file