include package local methods into method hierarchy (IDEA-164557)

This commit is contained in:
Anna.Kozlova
2016-12-01 10:39:31 +01:00
parent c0349c4953
commit a17be30b79
8 changed files with 54 additions and 25 deletions
@@ -22,6 +22,7 @@ import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -68,7 +69,8 @@ public class ClassUtil {
&& !alreadyImplemented.contains(method)) {
return method;
}
final List<HierarchicalMethodSignature> superSignatures = signatureHierarchical.getSuperSignatures();
final List<HierarchicalMethodSignature> superSignatures = new ArrayList<HierarchicalMethodSignature>(signatureHierarchical.getInaccessibleSuperSignatures());
superSignatures.addAll(signatureHierarchical.getSuperSignatures());
for (HierarchicalMethodSignature superSignatureHierarchical : superSignatures) {
final PsiMethod superMethod = superSignatureHierarchical.getMethod();
if (superMethod.hasModifierProperty(PsiModifier.ABSTRACT) && !resolveHelper.isAccessible(superMethod, method, null)) {
@@ -77,21 +79,6 @@ public class ClassUtil {
}
}
return checkPackageLocalInSuperClass(aClass);
}
@Nullable
private static PsiMethod checkPackageLocalInSuperClass(@NotNull PsiClass aClass) {
// super class can have package-private abstract methods not accessible for overriding
PsiClass superClass = aClass.getSuperClass();
if (superClass == null) return null;
if (CommonClassNames.JAVA_LANG_OBJECT.equals(aClass.getQualifiedName())) return null;
if (JavaPsiFacade.getInstance(aClass.getProject()).arePackagesTheSame(aClass, superClass)) return null;
for (HierarchicalMethodSignature methodSignature : superClass.getVisibleSignatures()) {
PsiMethod method = methodSignature.getMethod();
if (method.hasModifierProperty(PsiModifier.ABSTRACT) && method.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) return method;
}
return null;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -18,6 +18,7 @@ package com.intellij.psi;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
@@ -48,4 +49,8 @@ public abstract class HierarchicalMethodSignature extends MethodSignatureBackedB
* Note that the list may include signatures for which isSubsignature() check returns false, but erasures are equal
*/
@NotNull public abstract List<HierarchicalMethodSignature> getSuperSignatures();
@NotNull public List<HierarchicalMethodSignature> getInaccessibleSuperSignatures() {
return Collections.emptyList();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
* 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.
@@ -261,7 +261,7 @@ public class PsiSuperMethodImplUtil {
for (Map.Entry<MethodSignature, HierarchicalMethodSignatureImpl> entry : map.entrySet()) {
HierarchicalMethodSignatureImpl hierarchicalMethodSignature = entry.getValue();
MethodSignature methodSignature = entry.getKey();
if (result.get(methodSignature) == null && PsiUtil.isAccessible(aClass.getProject(), hierarchicalMethodSignature.getMethod(), aClass, aClass)) {
if (result.get(methodSignature) == null) {
LOG.assertTrue(hierarchicalMethodSignature.getMethod().isValid());
result.put(methodSignature, hierarchicalMethodSignature);
}
@@ -275,7 +275,6 @@ public class PsiSuperMethodImplUtil {
@NotNull Map<MethodSignature, HierarchicalMethodSignatureImpl> map,
@NotNull HierarchicalMethodSignature hierarchicalMethodSignature,
@NotNull MethodSignature signature) {
if (!PsiUtil.isAccessible(aClass.getProject(), hierarchicalMethodSignature.getMethod(), aClass, aClass)) return;
HierarchicalMethodSignatureImpl existing = map.get(signature);
if (existing == null) {
HierarchicalMethodSignatureImpl copy = copy(hierarchicalMethodSignature);
@@ -334,7 +333,6 @@ public class PsiSuperMethodImplUtil {
PsiClass containingClass = method.getContainingClass();
if (!superMethod.isConstructor() &&
!aClass.equals(superClass) &&
PsiUtil.isAccessible(aClass.getProject(), superMethod, aClass, aClass) &&
MethodSignatureUtil.isSubsignature(superSignatureHierarchical, hierarchicalMethodSignature) && superClass != null) {
if (superClass.isInterface() ||
CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -16,7 +16,9 @@
package com.intellij.psi.impl.source;
import com.intellij.psi.HierarchicalMethodSignature;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
@@ -28,14 +30,23 @@ import java.util.List;
*/
public class HierarchicalMethodSignatureImpl extends HierarchicalMethodSignature {
private List<HierarchicalMethodSignature> mySupers;
private List<HierarchicalMethodSignature> myInaccessibleSupers;
public HierarchicalMethodSignatureImpl(@NotNull MethodSignatureBackedByPsiMethod signature) {
super(signature);
}
public void addSuperSignature(@NotNull HierarchicalMethodSignature superSignatureHierarchical) {
if (mySupers == null) mySupers = new SmartList<HierarchicalMethodSignature>();
mySupers.add(superSignatureHierarchical);
PsiMethod superMethod = superSignatureHierarchical.getMethod();
PsiMethod method = getMethod();
if (PsiUtil.isAccessible(method.getProject(), superMethod, method, null)) {
if (mySupers == null) mySupers = new SmartList<HierarchicalMethodSignature>();
mySupers.add(superSignatureHierarchical);
}
else {
if (myInaccessibleSupers == null) myInaccessibleSupers = new SmartList<HierarchicalMethodSignature>();
myInaccessibleSupers.add(superSignatureHierarchical);
}
}
@Override
@@ -43,4 +54,10 @@ public class HierarchicalMethodSignatureImpl extends HierarchicalMethodSignature
public List<HierarchicalMethodSignature> getSuperSignatures() {
return mySupers == null ? Collections.<HierarchicalMethodSignature>emptyList() : mySupers;
}
@NotNull
@Override
public List<HierarchicalMethodSignature> getInaccessibleSuperSignatures() {
return myInaccessibleSupers == null ? super.getInaccessibleSuperSignatures() : myInaccessibleSupers;
}
}
@@ -0,0 +1,4 @@
package foo;
public abstract class A {
abstract void foo();
}
@@ -0,0 +1,3 @@
package foo.bar;
import foo.A;
abstract class B extends A {}
@@ -0,0 +1,11 @@
package foo.bar;
<error descr="Class 'C' must either be declared abstract or implement abstract method 'foo()' in 'A'">class C extends B</error> {}
<error descr="Class 'C1' must either be declared abstract or implement abstract method 'foo()' in 'A'">class C1 extends B</error>{
public void foo(){}
}
<error descr="Class 'C2' must either be declared abstract or implement abstract method 'foo()' in 'A'">class C2 extends B</error> {
public int foo() throws java.io.IOException {
return 0;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* 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.
@@ -52,4 +52,8 @@ public class AdvHighlighting8Test extends DaemonAnalyzerTestCase {
doTest(BASE_PATH + "/unrelatedConcreteInConstructors/B.java", BASE_PATH + "/unrelatedConcreteInConstructors", false, false);
}
public void testPackageLocalMethodVisibleInHierarchy() throws Exception {
doTest(BASE_PATH + "/packageLocalMethod/foo/bar/C.java",
BASE_PATH + "/packageLocalMethod", false, false);
}
}