diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java index 71fe67fba36d..b61dae5a2053 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaFileBaseImpl.java @@ -218,7 +218,9 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava private static class StaticImportFilteringProcessor implements PsiScopeProcessor { private final PsiScopeProcessor myDelegate; private boolean myIsProcessingOnDemand; - private final Collection myHiddenNames = new HashSet(); + private final Collection myHiddenFieldNames = new HashSet(); + private final Collection myHiddenMethodNames = new HashSet(); + private final Collection myHiddenTypeNames = new HashSet(); private final Collection myCollectedElements = new HashSet(); public StaticImportFilteringProcessor(final PsiScopeProcessor delegate) { @@ -235,19 +237,43 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava if (JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT.equals(event) && associated instanceof PsiImportStaticStatement) { final PsiImportStaticStatement importStaticStatement = (PsiImportStaticStatement)associated; myIsProcessingOnDemand = importStaticStatement.isOnDemand(); - if (!myIsProcessingOnDemand) { - myHiddenNames.add(importStaticStatement.getReferenceName()); - } } myDelegate.handleEvent(event, associated); } + /** + * JLS 6.4 Shadowing and Obscuring + * A single-static-import declaration d in a compilation unit c of package p that imports a field named n shadows the declaration of any + * static field named n imported by a static-import-on-demand declaration in c, throughout c. + * + * A single-static-import declaration d in a compilation unit c of package p that imports a method named n with signature s shadows the + * declaration of any static method named n with signature s imported by a static-import-on-demand declaration in c, throughout c. + * + * A single-static-import declaration d in a compilation unit c of package p that imports a type named n shadows, throughout c, the declarations of: + * - any static type named n imported by a static-import-on-demand declaration in c; + * - any top level type (§7.6) named n declared in another compilation unit (§7.3) of p; + * - any type named n imported by a type-import-on-demand declaration (§7.5.2) in c. + */ + private void registerSingleStaticImportHiding(JavaResolveResult result, String referenceName) { + getHiddenMembers(result.getElement()).add(referenceName); + } + + private Collection getHiddenMembers(PsiElement element) { + if (element instanceof PsiField) { + return myHiddenFieldNames; + } + else { + return element instanceof PsiClass ? myHiddenTypeNames + : myHiddenMethodNames; + } + } + @Override public boolean execute(@NotNull final PsiElement element, @NotNull final ResolveState state) { if (element instanceof PsiModifierListOwner && ((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.STATIC)) { if (element instanceof PsiNamedElement && myIsProcessingOnDemand) { final String name = ((PsiNamedElement)element).getName(); - if (myHiddenNames.contains(name)) return true; + if (getHiddenMembers(element).contains(name)) return true; } if (myCollectedElements.add(element)) { return myDelegate.execute(element, state); @@ -346,7 +372,9 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava final JavaResolveResult[] results = reference.multiResolve(false); if (results.length > 0) { staticImportProcessor.handleEvent(JavaScopeProcessorEvent.SET_CURRENT_FILE_CONTEXT, importStaticStatement); + final String referenceName = importStaticStatement.getReferenceName(); for (JavaResolveResult result : results) { + staticImportProcessor.registerSingleStaticImportHiding(result, referenceName); if (!staticImportProcessor.execute(result.getElement(), state)) return false; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/HidingOnDemandImports.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/HidingOnDemandImports.java new file mode 100644 index 000000000000..6dfd5376b5ac --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advFixture/HidingOnDemandImports.java @@ -0,0 +1,8 @@ +import static foo.Foo.*; +import static foo.Bar.foo; + +class Usage { + { + foo(foo); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingFixtureTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingFixtureTest.java new file mode 100644 index 000000000000..515e877bccaa --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingFixtureTest.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInsight.daemon; + +import com.intellij.JavaTestUtil; +import com.intellij.testFramework.LightProjectDescriptor; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; + +public class LightAdvHighlightingFixtureTest extends LightCodeInsightFixtureTestCase { + + public void testHidingOnDemandImports() throws Exception { + myFixture.addClass("package foo; public class Foo {" + + " public static String foo;" + + "}"); + + myFixture.addClass("package foo; public class Bar {" + + " public static void foo(String s) {}" + + "}"); + + myFixture.configureByFile(getTestName(false) + ".java"); + myFixture.checkHighlighting(false, false, false); + } + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/daemonCodeAnalyzer/advFixture"; + } + + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_8; + } +}