mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
include package local methods into method hierarchy (IDEA-164557)
This commit is contained in:
@@ -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())) {
|
||||
|
||||
+20
-3
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package foo;
|
||||
public abstract class A {
|
||||
abstract void foo();
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package foo.bar;
|
||||
import foo.A;
|
||||
abstract class B extends A {}
|
||||
+11
@@ -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;
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user