shadowing of static imports (IDEA-142600)

This commit is contained in:
Anna Kozlova
2016-06-07 10:57:34 +03:00
parent 0b77aa0e5c
commit c83341f731
3 changed files with 89 additions and 5 deletions
@@ -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<String> myHiddenNames = new HashSet<String>();
private final Collection<String> myHiddenFieldNames = new HashSet<String>();
private final Collection<String> myHiddenMethodNames = new HashSet<String>();
private final Collection<String> myHiddenTypeNames = new HashSet<String>();
private final Collection<PsiElement> myCollectedElements = new HashSet<PsiElement>();
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<String> 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;
}
}
@@ -0,0 +1,8 @@
import static foo.Foo.*;
import static foo.Bar.foo;
class Usage {
{
foo(foo);
}
}
@@ -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;
}
}