mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
javadoc references must resolve despite current resolve scope (Too often javadoc for interface references implementation which should not show up red)
This commit is contained in:
@@ -8,10 +8,13 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTagValue;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.StringTokenizer;
|
||||
@@ -70,12 +73,12 @@ public class JavaDocUtil {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement findReferenceTarget(PsiManager manager, String refText, PsiElement context) {
|
||||
public static PsiElement findReferenceTarget(@NotNull PsiManager manager, @NotNull String refText, PsiElement context) {
|
||||
return findReferenceTarget(manager, refText, context, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement findReferenceTarget(PsiManager manager, String refText, PsiElement context, boolean useNavigationElement) {
|
||||
public static PsiElement findReferenceTarget(@NotNull PsiManager manager, @NotNull String refText, PsiElement context, boolean useNavigationElement) {
|
||||
LOG.assertTrue(context == null || context.isValid());
|
||||
if (context != null) {
|
||||
context = context.getNavigationElement();
|
||||
@@ -84,9 +87,7 @@ public class JavaDocUtil {
|
||||
int poundIndex = refText.indexOf('#');
|
||||
final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
|
||||
if (poundIndex < 0) {
|
||||
PsiClass aClass = facade.getResolveHelper().resolveReferencedClass(refText, context);
|
||||
|
||||
if (aClass == null) aClass = facade.findClass(refText, context.getResolveScope());
|
||||
PsiClass aClass = findClassFromRef(manager, facade, refText, context);
|
||||
|
||||
if (aClass != null) {
|
||||
return useNavigationElement ? aClass.getNavigationElement() : aClass;
|
||||
@@ -98,9 +99,7 @@ public class JavaDocUtil {
|
||||
else {
|
||||
String classRef = refText.substring(0, poundIndex).trim();
|
||||
if (!classRef.isEmpty()) {
|
||||
PsiClass aClass = facade.getResolveHelper().resolveReferencedClass(classRef, context);
|
||||
|
||||
if (aClass == null) aClass = facade.findClass(classRef, context.getResolveScope());
|
||||
PsiClass aClass = findClassFromRef(manager, facade, classRef, context);
|
||||
|
||||
if (aClass == null) return null;
|
||||
PsiElement member = findReferencedMember(aClass, refText.substring(poundIndex + 1), context);
|
||||
@@ -110,7 +109,7 @@ public class JavaDocUtil {
|
||||
String memberRefText = refText.substring(1);
|
||||
PsiElement scope = context;
|
||||
while (true) {
|
||||
if (scope instanceof PsiFile) break;
|
||||
if (scope instanceof PsiFile || scope == null) break;
|
||||
if (scope instanceof PsiClass) {
|
||||
PsiElement member = findReferencedMember((PsiClass)scope, memberRefText, context);
|
||||
if (member != null) {
|
||||
@@ -124,6 +123,23 @@ public class JavaDocUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static PsiClass findClassFromRef(@NotNull PsiManager manager,
|
||||
@NotNull JavaPsiFacade facade,
|
||||
@NotNull String refText, PsiElement context) {
|
||||
PsiClass aClass = facade.getResolveHelper().resolveReferencedClass(refText, context);
|
||||
|
||||
GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
|
||||
if (aClass == null) aClass = facade.findClass(refText, projectScope);
|
||||
if (aClass == null && refText.indexOf('.') == -1 && context != null) {
|
||||
// find short-named class in the same package (maybe in the different module)
|
||||
PsiFile file = context.getContainingFile();
|
||||
PsiDirectory directory = file == null ? null : file.getContainingDirectory();
|
||||
PsiPackage aPackage = directory == null ? null : JavaDirectoryService.getInstance().getPackage(directory);
|
||||
aClass = aPackage == null ? null : ArrayUtil.getFirstElement(aPackage.findClassByShortName(refText, projectScope));
|
||||
}
|
||||
return aClass;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findReferencedMember(PsiClass aClass, String memberRefText, PsiElement context) {
|
||||
int parenthIndex = memberRefText.indexOf('(');
|
||||
|
||||
@@ -289,7 +289,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
|
||||
@NotNull ResolveState state,
|
||||
PsiElement lastParent,
|
||||
@NotNull PsiElement place) {
|
||||
GlobalSearchScope scope = place.getResolveScope();
|
||||
GlobalSearchScope scope = PsiUtil.isInsideJavadocComment(place) ? allScope() : place.getResolveScope();
|
||||
|
||||
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this);
|
||||
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
|
||||
@@ -336,7 +336,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
|
||||
private static boolean processClasses(@NotNull PsiScopeProcessor processor,
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiClass[] classes,
|
||||
@NotNull Condition<String> nameCondition) {
|
||||
@NotNull Condition<? super String> nameCondition) {
|
||||
for (PsiClass aClass : classes) {
|
||||
String name = aClass.getName();
|
||||
if (name != null && nameCondition.value(name)) {
|
||||
|
||||
@@ -314,7 +314,8 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
|
||||
|
||||
if (processor instanceof ClassResolverProcessor &&
|
||||
isPhysical() &&
|
||||
(getUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING) == Boolean.TRUE || myResolveCache.hasUpToDateValue())) {
|
||||
(getUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING) == Boolean.TRUE || myResolveCache.hasUpToDateValue()) &&
|
||||
!PsiUtil.isInsideJavadocComment(place)) {
|
||||
final ClassResolverProcessor hint = (ClassResolverProcessor)processor;
|
||||
String name = hint.getName(state);
|
||||
MostlySingularMultiMap<String, SymbolCollectingProcessor.ResultWithContext> cache = myResolveCache.getValue();
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package pkg;
|
||||
|
||||
/**
|
||||
* @see pkg1.PackageLocal - package local class in other package should resolve
|
||||
* @see java.io.ObjectStreamClass.WeakClassKey - and JDK package local class too
|
||||
* @see java.io.ObjectStreamClass.Caches - and even JDK private classes
|
||||
*
|
||||
* - but don't go over the top, of course:
|
||||
* @see java.io.ObjectStreamClass.<error descr="Cannot resolve symbol 'java.io.ObjectStreamClass.XXXXXX'">XXXXXX</error>
|
||||
*/
|
||||
class JavadocMustResolveEvenOtherPackageLocalClasses {
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
package pkg1;
|
||||
|
||||
class PackageLocal {}
|
||||
@@ -4,7 +4,9 @@ package com.intellij.java.codeInsight.daemon;
|
||||
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
|
||||
import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
|
||||
public class JavadocResolveTest extends DaemonAnalyzerTestCase {
|
||||
private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/javaDoc/resolve";
|
||||
@@ -16,6 +18,7 @@ public class JavadocResolveTest extends DaemonAnalyzerTestCase {
|
||||
public void testPackageInfo() { doTest("/pkg/package-info.java"); }
|
||||
public void testBrokenPackageInfo() { doTest("/pkg1/package-info.java"); }
|
||||
public void testModuleInfo() { setLanguageLevel(LanguageLevel.JDK_1_9); doTest("/module-info.java"); }
|
||||
public void testOtherPackageLocal() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
doTest("/pkg/" + getTestName(false) + ".java");
|
||||
@@ -28,4 +31,9 @@ public class JavadocResolveTest extends DaemonAnalyzerTestCase {
|
||||
}
|
||||
catch (Exception e) { throw new RuntimeException(e); }
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getTestProjectJdk() {
|
||||
return IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user