mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ensure external/inferred annotations are correctly shown on the gutter for decompiled files; test this
This commit is contained in:
+2
-9
@@ -20,7 +20,6 @@ import com.intellij.codeInspection.dataFlow.ContractInference;
|
||||
import com.intellij.codeInspection.dataFlow.MethodContract;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -34,16 +33,10 @@ import static com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer.ORG_JETBR
|
||||
|
||||
public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
|
||||
|
||||
@NotNull
|
||||
private static PsiModifierListOwner preferCompiledElement(@NotNull PsiModifierListOwner element) {
|
||||
PsiElement original = element.getOriginalElement();
|
||||
return original instanceof PsiModifierListOwner ? (PsiModifierListOwner)original : element;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiAnnotation findInferredAnnotation(@NotNull PsiModifierListOwner listOwner, @NotNull String annotationFQN) {
|
||||
listOwner = preferCompiledElement(listOwner);
|
||||
listOwner = BaseExternalAnnotationsManager.preferCompiledElement(listOwner);
|
||||
PsiAnnotation fromBytecode = ProjectBytecodeAnalysis.getInstance(listOwner.getProject()).findInferredAnnotation(listOwner, annotationFQN);
|
||||
if (fromBytecode != null) {
|
||||
return fromBytecode;
|
||||
@@ -66,7 +59,7 @@ public class InferredAnnotationsManagerImpl extends InferredAnnotationsManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiAnnotation[] findInferredAnnotations(@NotNull PsiModifierListOwner listOwner) {
|
||||
listOwner = preferCompiledElement(listOwner);
|
||||
listOwner = BaseExternalAnnotationsManager.preferCompiledElement(listOwner);
|
||||
List<PsiAnnotation> result = ContainerUtil.newArrayList();
|
||||
PsiAnnotation[] fromBytecode = ProjectBytecodeAnalysis.getInstance(listOwner.getProject()).findInferredAnnotations(listOwner);
|
||||
for (PsiAnnotation annotation : fromBytecode) {
|
||||
|
||||
@@ -70,6 +70,12 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
|
||||
return PsiFormatUtil.getExternalName(listOwner, showParamName, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static PsiModifierListOwner preferCompiledElement(@NotNull PsiModifierListOwner element) {
|
||||
PsiElement original = element.getOriginalElement();
|
||||
return original instanceof PsiModifierListOwner ? (PsiModifierListOwner)original : element;
|
||||
}
|
||||
|
||||
protected abstract boolean hasAnyAnnotationsRoots();
|
||||
|
||||
@Override
|
||||
@@ -213,7 +219,8 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner listOwner) {
|
||||
public List<PsiFile> findExternalAnnotationsFiles(@NotNull PsiModifierListOwner _listOwner) {
|
||||
final PsiModifierListOwner listOwner = preferCompiledElement(_listOwner);
|
||||
final PsiFile containingFile = listOwner.getContainingFile();
|
||||
if (!(containingFile instanceof PsiJavaFile)) {
|
||||
return null;
|
||||
@@ -235,10 +242,6 @@ public abstract class BaseExternalAnnotationsManager extends ExternalAnnotations
|
||||
}
|
||||
}
|
||||
|
||||
if (virtualFile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<PsiFile> possibleAnnotationsXmls = new THashSet<PsiFile>();
|
||||
for (VirtualFile root : getExternalAnnotationsRoots(virtualFile)) {
|
||||
final VirtualFile ext = root.findFileByRelativePath(packageName.replace('.', '/') + "/" + ANNOTATIONS_XML);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
<orderEntry type="module" module-name="junit_rt" scope="TEST" />
|
||||
<orderEntry type="module" module-name="xml-psi-impl" scope="TEST" />
|
||||
<orderEntry type="module" module-name="properties-psi-api" scope="TEST" />
|
||||
<orderEntry type="module" module-name="java-decompiler" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
+71
-30
@@ -18,6 +18,7 @@ package com.intellij.codeInspection.bytecodeAnalysis;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||
import com.intellij.codeInsight.InferredAnnotationsManager;
|
||||
import com.intellij.codeInsight.daemon.GutterMark;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
@@ -26,6 +27,8 @@ import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -36,10 +39,15 @@ import com.intellij.psi.util.PsiFormatUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import com.intellij.util.AsynchConsumer;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.java.decompiler.IdeaDecompiler;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -48,27 +56,24 @@ import java.util.List;
|
||||
public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestCase {
|
||||
public static final String ORG_JETBRAINS_ANNOTATIONS_CONTRACT = Contract.class.getName();
|
||||
|
||||
private InferredAnnotationsManager myInferredAnnotationsManager;
|
||||
private ExternalAnnotationsManager myExternalAnnotationsManager;
|
||||
private MessageDigest myMessageDigest;
|
||||
private List<String> diffs = new ArrayList<String>();
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
setUpLibraries();
|
||||
setUpExternalUpAnnotations();
|
||||
|
||||
myInferredAnnotationsManager = InferredAnnotationsManager.getInstance(myModule.getProject());
|
||||
myExternalAnnotationsManager = ExternalAnnotationsManager.getInstance(myModule.getProject());
|
||||
myMessageDigest = BytecodeAnalysisConverter.getMessageDigest();
|
||||
}
|
||||
|
||||
private void setUpLibraries() {
|
||||
@NotNull
|
||||
private static String getLibDirPath() {
|
||||
VirtualFile lib = LocalFileSystem.getInstance().refreshAndFindFileByPath(PathManagerEx.getTestDataPath() + "/../../../lib");
|
||||
assertNotNull(lib);
|
||||
PsiTestUtil.addLibrary(myModule, "velocity", lib.getPath(), new String[]{"/velocity.jar!/"}, new String[]{});
|
||||
return lib.getPath();
|
||||
}
|
||||
|
||||
private void setUpLibraries() {
|
||||
PsiTestUtil.addLibrary(myModule, "velocity", getLibDirPath(), new String[]{"/velocity.jar!/"}, new String[]{});
|
||||
}
|
||||
|
||||
private void setUpExternalUpAnnotations() {
|
||||
@@ -103,7 +108,46 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
annotationsDir.refresh(false, true);
|
||||
}
|
||||
|
||||
private void openDecompiledClass(String name) {
|
||||
PsiClass psiClass = JavaPsiFacade.getInstance(getProject()).findClass(name, GlobalSearchScope.allScope(getProject()));
|
||||
assertNotNull(psiClass);
|
||||
myFixture.openFileInEditor(psiClass.getContainingFile().getVirtualFile());
|
||||
|
||||
String documentText = myFixture.getEditor().getDocument().getText();
|
||||
assertTrue(documentText, documentText.startsWith(IdeaDecompiler.BANNER));
|
||||
}
|
||||
|
||||
public void testInferredAnnoGutter() {
|
||||
setUpLibraries();
|
||||
openDecompiledClass("org.apache.velocity.util.ExceptionUtils");
|
||||
checkHasGutter("<i>@org.jetbrains.annotations.Contract("null,_,_->null")</i>");
|
||||
}
|
||||
|
||||
public void testExternalAnnoGutter() {
|
||||
setUpExternalUpAnnotations();
|
||||
openDecompiledClass("java.lang.Boolean");
|
||||
checkHasGutter("@org.jetbrains.annotations.Contract("null->false") ");
|
||||
}
|
||||
|
||||
private void checkHasGutter(final String expectedText) {
|
||||
Collection<String> gutters = ContainerUtil.mapNotNull(myFixture.findAllGutters(), new Function<GutterMark, String>() {
|
||||
@Override
|
||||
public String fun(GutterMark mark) {
|
||||
return mark.getTooltipText();
|
||||
}
|
||||
});
|
||||
String contractMark = ContainerUtil.find(gutters, new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(String mark) {
|
||||
return mark.contains(expectedText);
|
||||
}
|
||||
});
|
||||
assertNotNull(StringUtil.join(gutters, "\n"), contractMark);
|
||||
}
|
||||
|
||||
public void testSdkAndLibAnnotations() {
|
||||
setUpLibraries();
|
||||
setUpExternalUpAnnotations();
|
||||
|
||||
final PsiPackage rootPackage = JavaPsiFacade.getInstance(getProject()).findPackage("");
|
||||
assert rootPackage != null;
|
||||
@@ -137,10 +181,8 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
|
||||
{
|
||||
// @NotNull method
|
||||
String externalNotNullMethodAnnotation =
|
||||
myExternalAnnotationsManager.findExternalAnnotation(method, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
String inferredNotNullMethodAnnotation =
|
||||
myInferredAnnotationsManager.findInferredAnnotation(method, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
String externalNotNullMethodAnnotation = findExternalAnnotation(method, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
String inferredNotNullMethodAnnotation = findInferredAnnotation(method, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
|
||||
if (!externalNotNullMethodAnnotation.equals(inferredNotNullMethodAnnotation)) {
|
||||
diffs.add(methodKey + ": " + externalNotNullMethodAnnotation + " != " + inferredNotNullMethodAnnotation);
|
||||
@@ -149,10 +191,8 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
|
||||
{
|
||||
// @Nullable method
|
||||
String externalNullableMethodAnnotation =
|
||||
myExternalAnnotationsManager.findExternalAnnotation(method, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
String inferredNullableMethodAnnotation =
|
||||
myInferredAnnotationsManager.findInferredAnnotation(method, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
String externalNullableMethodAnnotation = findExternalAnnotation(method, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
String inferredNullableMethodAnnotation = findInferredAnnotation(method, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
|
||||
if (!externalNullableMethodAnnotation.equals(inferredNullableMethodAnnotation)) {
|
||||
diffs.add(methodKey + ": " + externalNullableMethodAnnotation + " != " + inferredNullableMethodAnnotation);
|
||||
@@ -164,10 +204,8 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
|
||||
{
|
||||
// @NotNull parameter
|
||||
String externalNotNull =
|
||||
myExternalAnnotationsManager.findExternalAnnotation(parameter, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
String inferredNotNull =
|
||||
myInferredAnnotationsManager.findInferredAnnotation(parameter, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
String externalNotNull = findExternalAnnotation(parameter, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
String inferredNotNull = findInferredAnnotation(parameter, AnnotationUtil.NOT_NULL) == null ? "null" : "@NotNull";
|
||||
if (!externalNotNull.equals(inferredNotNull)) {
|
||||
diffs.add(parameterKey + ": " + externalNotNull + " != " + inferredNotNull);
|
||||
}
|
||||
@@ -175,10 +213,8 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
|
||||
{
|
||||
// @Nullable parameter
|
||||
String externalNullable =
|
||||
myExternalAnnotationsManager.findExternalAnnotation(parameter, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
String inferredNullable =
|
||||
myInferredAnnotationsManager.findInferredAnnotation(parameter, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
String externalNullable = findExternalAnnotation(parameter, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
String inferredNullable = findInferredAnnotation(parameter, AnnotationUtil.NULLABLE) == null ? "null" : "@Nullable";
|
||||
if (!externalNullable.equals(inferredNullable)) {
|
||||
diffs.add(parameterKey + ": " + externalNullable + " != " + inferredNullable);
|
||||
}
|
||||
@@ -186,10 +222,8 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
}
|
||||
|
||||
// @Contract
|
||||
PsiAnnotation externalContractAnnotation =
|
||||
myExternalAnnotationsManager.findExternalAnnotation(method, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
|
||||
PsiAnnotation inferredContractAnnotation =
|
||||
myInferredAnnotationsManager.findInferredAnnotation(method, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
|
||||
PsiAnnotation externalContractAnnotation = findExternalAnnotation(method, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
|
||||
PsiAnnotation inferredContractAnnotation = findInferredAnnotation(method, ORG_JETBRAINS_ANNOTATIONS_CONTRACT);
|
||||
|
||||
String externalContractAnnotationString =
|
||||
externalContractAnnotation == null ? "null" : "@Contract(" + AnnotationUtil.getStringAttributeValue(externalContractAnnotation, null) + ")";
|
||||
@@ -202,4 +236,11 @@ public class BytecodeAnalysisIntegrationTest extends JavaCodeInsightFixtureTestC
|
||||
|
||||
}
|
||||
|
||||
private PsiAnnotation findInferredAnnotation(PsiModifierListOwner owner, String fqn) {
|
||||
return InferredAnnotationsManager.getInstance(myModule.getProject()).findInferredAnnotation(owner, fqn);
|
||||
}
|
||||
|
||||
private PsiAnnotation findExternalAnnotation(PsiModifierListOwner owner, String fqn) {
|
||||
return ExternalAnnotationsManager.getInstance(myModule.getProject()).findExternalAnnotation(owner, fqn);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user