IJ-MR-135481 [lombok] IDEA-352727 Support incomplete mode

- add javadocs
- improve `de.plushnikov.intellij.plugin.util.DumbIncompleteModeUtil.isIncompleteModeWithLombokAnnotation` and `hasQualifiedNameInDumbOrIncompleteMode`
- test without libraries for logs

GitOrigin-RevId: f5fab3c0fb3f659dada8cc1bed4161c4ba4c6560
This commit is contained in:
Mikhail Pyltsin
2024-06-04 20:59:39 +02:00
committed by intellij-monorepo-bot
parent 1ac9d8ac4e
commit 9531a30d8e
6 changed files with 63 additions and 24 deletions

View File

@@ -82,12 +82,12 @@ public final class DumbIncompleteModeUtil {
static boolean hasQualifiedNameInDumbOrIncompleteMode(PsiAnnotation annotation, @NotNull String fqn) {
PsiJavaCodeReferenceElement referenceElement = annotation.getNameReferenceElement();
if (referenceElement == null) return false;
String qualifiedName = referenceElement.getReferenceName();
if (qualifiedName == null) return false;
if (qualifiedName.equals(fqn) || ("java.lang." + qualifiedName).equals(fqn)) return true;
String annotationReferenceName = referenceElement.getReferenceName();
if (annotationReferenceName == null) return false;
if (annotationReferenceName.equals(fqn) || ("java.lang." + annotationReferenceName).equals(fqn)) return true;
String referenceElementText = referenceElement.getText();
if (!StringUtil.isShortNameOf(fqn, annotationReferenceName)) return false;
if (referenceElementText != null && referenceElementText.equals(fqn)) return true;
if (!fqn.endsWith(qualifiedName)) return false;
PsiFile containingFile = annotation.getContainingFile();
if (!(containingFile instanceof PsiJavaFile javaFile)) {
return false;
@@ -95,11 +95,11 @@ public final class DumbIncompleteModeUtil {
String packageName = StringUtil.getPackageName(fqn);
PsiImportList importList = javaFile.getImportList();
if (importList == null) return false;
int indexMayByOuterClass = fqn.length() - qualifiedName.length() - 1;
int indexMayByOuterClass = fqn.length() - annotationReferenceName.length() - 1;
String mayBeOuterClass = indexMayByOuterClass > 0 ? fqn.substring(0, indexMayByOuterClass) : null;
return importList.findOnDemandImportStatement(packageName) != null ||
importList.findSingleClassImportStatement(fqn) != null ||
(mayBeOuterClass!=null && importList.findSingleClassImportStatement(mayBeOuterClass) != null);
(mayBeOuterClass != null && importList.findSingleClassImportStatement(mayBeOuterClass) != null);
}
/**
@@ -120,12 +120,11 @@ public final class DumbIncompleteModeUtil {
return false;
}
if (context instanceof PsiModifierList modifierList && hasAnyLombokAnnotation(modifierList.getAnnotations())) {
if (context instanceof PsiModifierList modifierList && hasAnyFullyQualifiedLombokAnnotation(modifierList.getAnnotations())) {
return true;
}
PsiClass psiClass = context instanceof PsiClass castedClass ? castedClass :
PsiTreeUtil.getParentOfType(context, PsiClass.class);
PsiClass psiClass = PsiTreeUtil.getNonStrictParentOfType(context, PsiClass.class);
if (psiClass == null) return false;
@@ -140,9 +139,9 @@ public final class DumbIncompleteModeUtil {
}
while (psiElement != null) {
if (psiElement instanceof PsiExtensibleClass extensibleClass &&
(hasAnyLombokAnnotation(extensibleClass.getAnnotations()) ||
ContainerUtil.exists(extensibleClass.getOwnFields(), field -> hasAnyLombokAnnotation(field.getAnnotations())) ||
ContainerUtil.exists(extensibleClass.getOwnMethods(), method -> hasAnyLombokAnnotation(method.getAnnotations())) ||
(hasAnyFullyQualifiedLombokAnnotation(extensibleClass.getAnnotations()) ||
ContainerUtil.exists(extensibleClass.getOwnFields(), field -> hasAnyFullyQualifiedLombokAnnotation(field.getAnnotations())) ||
ContainerUtil.exists(extensibleClass.getOwnMethods(), method -> hasAnyFullyQualifiedLombokAnnotation(method.getAnnotations())) ||
(file.getImportList() != null && ContainerUtil.exists(file.getImportList().getAllImportStatements(), statement -> {
return canBeLombokImport(statement);
})))) {
@@ -160,13 +159,10 @@ public final class DumbIncompleteModeUtil {
}
/**
* Checks if the given PsiModifierListOwner has any Lombok annotation.
* It is used only for incomplete mode.
*
* @param annotations The annotations to check for Lombok annotations.
* @return true if the modifierListOwner has any Lombok annotation, otherwise false.
* @param annotations the array of annotations to check
* @return true if any of the annotations is a fully qualified Lombok annotation, false otherwise
*/
private static boolean hasAnyLombokAnnotation(PsiAnnotation @NotNull [] annotations) {
private static boolean hasAnyFullyQualifiedLombokAnnotation(PsiAnnotation @NotNull [] annotations) {
return ContainerUtil.exists(annotations, annotation -> {
if (annotation == null) {
return false;

View File

@@ -73,8 +73,21 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC
}
}
/**
* Represents the different modes for tests:
* <ul>
* <li>NORMAL - uses to test mode when downloading and indexing are finished (indexes are available)</li>
* <li>DUMB - uses to test dumb mode, indexing is in progress (all libraries are downloaded, indexes are not available)</li>
* <li>INCOMPLETE - uses to test incomplete mode (libraries are being downloaded, indexes are available, but they don't contain all data)</li>
* </ul>
*
* @see DumbService
* @see IncompleteDependenciesService
*/
public enum ModeRunnerType {
INCOMPLETE, DUMB, NORMAL
INCOMPLETE,
DUMB,
NORMAL
}
protected boolean shouldCompareAnnotations() {
@@ -83,10 +96,24 @@ public abstract class AbstractLombokParsingTestCase extends AbstractLombokLightC
@Override
protected final @NotNull LightProjectDescriptor getProjectDescriptor() {
return (myRunnerType == ModeRunnerType.INCOMPLETE) ? LombokTestUtil.WITHOUT_LOMBOK_DESCRIPTOR : getParsingDescriptor();
return (myRunnerType == ModeRunnerType.INCOMPLETE) ? getProjectDescriptorForIncompleteMode() : getProjectDescriptorForNormalMode();
}
protected @NotNull LightProjectDescriptor getParsingDescriptor() {
/**
* @return the project descriptor for incomplete mode
*
* @see ModeRunnerType
*/
protected @NotNull LightProjectDescriptor getProjectDescriptorForIncompleteMode() {
return LombokTestUtil.WITHOUT_LOMBOK_DESCRIPTOR;
}
/**
* @return the project descriptor for normal mode
*
* @see ModeRunnerType
*/
protected @NotNull LightProjectDescriptor getProjectDescriptorForNormalMode() {
return super.getProjectDescriptor();
}

View File

@@ -8,7 +8,7 @@ import org.jetbrains.annotations.NotNull;
public class Builder16Test extends AbstractLombokParsingTestCase {
@Override
protected @NotNull LightProjectDescriptor getParsingDescriptor() {
protected @NotNull LightProjectDescriptor getProjectDescriptorForNormalMode() {
return LombokTestUtil.LOMBOK_NEW_DESCRIPTOR;
}

View File

@@ -14,7 +14,7 @@ public class FieldNameConstantsOldTest extends AbstractLombokParsingTestCase {
@NotNull
@Override
protected LightProjectDescriptor getParsingDescriptor() {
protected LightProjectDescriptor getProjectDescriptorForNormalMode() {
return LombokTestUtil.LOMBOK_OLD_DESCRIPTOR;
}

View File

@@ -30,7 +30,7 @@ public class FieldNameConstantsTest extends AbstractLombokParsingTestCase {
@NotNull
@Override
protected LightProjectDescriptor getParsingDescriptor() {
protected LightProjectDescriptor getProjectDescriptorForNormalMode() {
return LombokTestUtil.LOMBOK_NEW_DESCRIPTOR;
}

View File

@@ -0,0 +1,16 @@
package de.plushnikov.intellij.plugin.processor;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
/**
* Unit tests for IntelliJPlugin for Lombok, based on lombok test classes,
* without actual libraries for incomplete mode
*/
public class LoggerIncompleteModeWithoutLibrariesTest extends LoggerTest {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptorForIncompleteMode() {
return JAVA_LATEST;
}
}