From 24d2eeb3d09d4461fe042b6fc4aa4652cb0ae098 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 28 Mar 2012 19:41:18 +0200 Subject: [PATCH] service to detect java version; highlight access to private class members according to java version used (IDEA-83045) --- .../impl/analysis/GenericsHighlightUtil.java | 3 +- .../projectRoots/JavaVersionServiceImpl.java | 29 ++++++++++++++ .../openapi/projectRoots/JavaSdkVersion.java | 15 ------- .../projectRoots/JavaVersionService.java | 34 ++++++++++++++++ .../intellij/core/JavaCoreEnvironment.java | 3 ++ .../impl/source/resolve/JavaResolveUtil.java | 23 +++++++---- .../TypeParameterBoundVisibility.java | 9 +++++ .../TypeParameterBoundVisibilityJdk14.java | 9 +++++ .../daemon/GenericsHighlightingTest.java | 13 ++++++- .../projectRoots/JavaSdkVersionUtil.java | 39 +++++++++++++++++++ resources/src/META-INF/IdeaPlugin.xml | 3 ++ 11 files changed, 155 insertions(+), 25 deletions(-) create mode 100644 java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java rename java/{openapi => java-psi-api}/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java (77%) create mode 100644 java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java create mode 100644 java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index 4b7f8ce86cda..be5894779a33 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -27,6 +27,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaSdkVersionUtil; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; import com.intellij.pom.java.LanguageLevel; @@ -508,7 +509,7 @@ public class GenericsHighlightUtil { final PsiType retErasure2 = TypeConversionUtil.erasure(superMethod.getReturnType()); boolean differentReturnTypeErasure = !Comparing.equal(retErasure1, retErasure2); - if (checkEqualsSuper && JavaSdkVersion.isAtLeast(checkMethod, JavaSdkVersion.JDK_1_7)) { + if (checkEqualsSuper && JavaSdkVersionUtil.isAtLeast(checkMethod, JavaSdkVersion.JDK_1_7)) { if (retErasure1 != null && retErasure2 != null) { differentReturnTypeErasure = !TypeConversionUtil.isAssignable(retErasure1, retErasure2); } else { diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java new file mode 100644 index 000000000000..366a0b870404 --- /dev/null +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JavaVersionServiceImpl.java @@ -0,0 +1,29 @@ +/* + * 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.openapi.projectRoots; + +import com.intellij.psi.PsiElement; + +/** + * User: anna + * Date: 3/28/12 + */ +public class JavaVersionServiceImpl extends JavaVersionService { + @Override + public boolean isAtLeast(PsiElement element, JavaSdkVersion version) { + return JavaSdkVersionUtil.isAtLeast(element, version); + } +} diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java similarity index 77% rename from java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java rename to java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 2d7e6629ad3b..8d3ff5daaf60 100644 --- a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -15,11 +15,7 @@ */ package com.intellij.openapi.projectRoots; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtil; -import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -75,15 +71,4 @@ public enum JavaSdkVersion { ); } - public static boolean isAtLeast(PsiElement element, JavaSdkVersion minVersion) { - final Module module = ModuleUtil.findModuleForPsiElement(element); - if (module != null) { - final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); - if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { - final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk); - return version != null && version.isAtLeast(minVersion); - } - } - return false; - } } diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java new file mode 100644 index 000000000000..b1573f95da60 --- /dev/null +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaVersionService.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +/* + * @author max + */ +package com.intellij.openapi.projectRoots; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiUtil; + +public class JavaVersionService { + public static JavaVersionService getInstance() { + return ServiceManager.getService(JavaVersionService.class); + } + + public boolean isAtLeast(PsiElement element, JavaSdkVersion version) { + return PsiUtil.getLanguageLevel(element).isAtLeast(version.getMaxLanguageLevel()); + } +} \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java index 6c2a98db24b7..d6f0e06de710 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreEnvironment.java @@ -24,6 +24,8 @@ import com.intellij.lang.java.JavaLanguage; import com.intellij.lang.java.JavaParserDefinition; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.roots.PackageIndex; import com.intellij.openapi.vfs.VirtualFile; @@ -86,6 +88,7 @@ public class JavaCoreEnvironment extends CoreEnvironment { myApplication.registerService(EmptySubstitutor.class, new EmptySubstitutorImpl()); myApplication.registerService(JavaDirectoryService.class, new CoreJavaDirectoryService()); + myApplication.registerService(JavaVersionService.class, new JavaVersionService()); } public void addToClasspath(File path) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index df49e326cf5e..9d927c6832a4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -19,6 +19,8 @@ */ package com.intellij.psi.impl.source.resolve; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.psi.*; import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.javadoc.PsiDocComment; @@ -160,15 +162,20 @@ public class JavaResolveUtil { private static PsiClass getTopLevelClass(@NotNull PsiElement place, PsiClass memberClass) { PsiClass lastClass = null; + Boolean isAtLeast17 = null; for (PsiElement placeParent = place; placeParent != null; placeParent = placeParent.getContext()) { - if (placeParent instanceof PsiClass && - !(placeParent instanceof PsiAnonymousClass) && - !(placeParent instanceof PsiTypeParameter)) { - PsiClass aClass = (PsiClass)placeParent; - - if (memberClass != null && aClass.isInheritor(memberClass, true)) return aClass; - - lastClass = aClass; + if (placeParent instanceof PsiClass && !(placeParent instanceof PsiAnonymousClass)) { + final boolean isTypeParameter = placeParent instanceof PsiTypeParameter; + if (isTypeParameter && isAtLeast17 == null) { + isAtLeast17 = JavaVersionService.getInstance().isAtLeast(place, JavaSdkVersion.JDK_1_7); + } + if (!isTypeParameter || (isAtLeast17 != null && isAtLeast17)) { + PsiClass aClass = (PsiClass)placeParent; + + if (memberClass != null && aClass.isInheritor(memberClass, true)) return aClass; + + lastClass = aClass; + } } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java new file mode 100644 index 000000000000..82ab1a7f8cdf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibility.java @@ -0,0 +1,9 @@ +class A { + private int value = 1; + + static class B { + void print(T t) { + System.out.println(t.value); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java new file mode 100644 index 000000000000..ce2e57ded675 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeParameterBoundVisibilityJdk14.java @@ -0,0 +1,9 @@ +class A { + private int value = 1; + + static class B { + void print(T t) { + System.out.println(t.value); + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index af5988b5798e..cb955b02e898 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -32,7 +32,16 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { @Override protected void setUp() throws Exception { super.setUp(); - LanguageLevel level = getTestName(false).contains("Level6") ? LanguageLevel.JDK_1_6 : LanguageLevel.JDK_1_5; + LanguageLevel level; + final String testName = getTestName(false); + if (testName.contains("Level17")) { + level = LanguageLevel.JDK_1_7; + } else if (testName.contains("Level6")) { + level = LanguageLevel.JDK_1_6; + } + else { + level = LanguageLevel.JDK_1_5; + } LanguageLevelProjectExtension.getInstance(getJavaFacade().getProject()).setLanguageLevel(level); } @@ -107,6 +116,8 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testPrivateInnerClassRef() throws Exception { doTest(false); } public void testWideningCastToTypeParam() throws Exception { doTest(false); } public void testCapturedWildcardAssignments() throws Exception { doTest(false);} + public void testTypeParameterBoundVisibility() throws Exception { doTest(false);} + public void testTypeParameterBoundVisibilityJdk14() throws Exception { doTest(false);} public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); diff --git a/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java new file mode 100644 index 000000000000..859e269fbd1b --- /dev/null +++ b/java/openapi/src/com/intellij/openapi/projectRoots/JavaSdkVersionUtil.java @@ -0,0 +1,39 @@ +/* + * 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.openapi.projectRoots; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.psi.PsiElement; + +/** + * User: anna + * Date: 3/28/12 + */ +public class JavaSdkVersionUtil { + public static boolean isAtLeast(PsiElement element, JavaSdkVersion minVersion) { + final Module module = ModuleUtil.findModuleForPsiElement(element); + if (module != null) { + final Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk != null && sdk.getSdkType() instanceof JavaSdk) { + final JavaSdkVersion version = JavaSdk.getInstance().getVersion(sdk); + return version != null && version.isAtLeast(minVersion); + } + } + return false; + } +} diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index e30a42bfee3b..1dfda1b79956 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -297,6 +297,9 @@ + +