[java] IDEA-379571 Improve PsiPackageStatement.getAnnotationList() so it never returns null value.

#IDEA-379571 Fixed
Merge-request: IJ-MR-176432
Merged-by: Marcin Mikosik <marcin.mikosik@jetbrains.com>

GitOrigin-RevId: 0d575fd55751ccac0b098b189ba3e90bbb081299
This commit is contained in:
Marcin Mikosik
2025-09-26 08:03:20 +00:00
committed by intellij-monorepo-bot
parent a8569ff41b
commit 2ea0d03d4d
67 changed files with 160 additions and 63 deletions
@@ -19,7 +19,7 @@ import static com.intellij.psi.compiled.ClassFileDecompilers.Full;
public class ClassFileStubBuilder implements BinaryFileStubBuilder.CompositeBinaryFileStubBuilder<Full> {
private static final Logger LOG = Logger.getInstance(ClassFileStubBuilder.class);
public static final int STUB_VERSION = 29;
public static final int STUB_VERSION = 30;
@Override
public @NotNull VirtualFileFilter getFileFilter() {
@@ -4,11 +4,16 @@ package com.intellij.psi.impl.compiled;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiPackageStatementStub;
import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
import static java.util.Objects.requireNonNull;
public class ClsPackageStatementImpl extends ClsRepositoryPsiElement<PsiPackageStatementStub> implements PsiPackageStatement {
private final @NotNull String myPackageName;
@@ -24,16 +29,13 @@ public class ClsPackageStatementImpl extends ClsRepositoryPsiElement<PsiPackageS
}
@Override
public PsiModifierList getAnnotationList() {
@SuppressWarnings("unchecked") final StubElement<PsiModifierList> child =
(StubElement<PsiModifierList>)getStub().findChildStubByElementType(JavaStubElementTypes.MODIFIER_LIST);
return child == null ? null : child.getPsi();
public @NotNull PsiModifierList getAnnotationList() {
return (PsiModifierList)requireNonNull(getStub().findChildStubByElementType(JavaStubElementTypes.MODIFIER_LIST)).getPsi();
}
@Override
public PsiElement @NotNull [] getChildren() {
PsiModifierList list = getAnnotationList();
return list == null ? EMPTY_ARRAY : new PsiElement[]{list};
return new PsiElement[]{getAnnotationList()};
}
@Override
@@ -44,12 +46,9 @@ public class ClsPackageStatementImpl extends ClsRepositoryPsiElement<PsiPackageS
@Override
public void appendMirrorText(final int indentLevel, final @NotNull StringBuilder buffer) {
if (!myPackageName.isEmpty()) { // an empty package name should not happen for a well-formed class file
PsiModifierList list = getAnnotationList();
if (list != null) {
for (PsiAnnotation annotation : list.getAnnotations()) {
appendText(annotation, indentLevel, buffer);
buffer.append("\n");
}
for (PsiAnnotation annotation : getAnnotationList().getAnnotations()) {
appendText(annotation, indentLevel, buffer);
buffer.append("\n");
}
buffer.append("package ").append(getPackageName()).append(';');
}
@@ -102,17 +102,18 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
}
String packageName = !(myParent instanceof PsiFileStub) || name.lastIndexOf('/') == -1 ? "" :
name.substring(0, name.lastIndexOf('/')).replace('/', '.');
PsiPackageStatementStub packageStatement = null;
PsiModifierListStubImpl packageModList = null;
if (!packageName.isEmpty()) {
packageStatement = new PsiPackageStatementStubImpl(myParent, packageName);
PsiPackageStatementStub packageStatement = new PsiPackageStatementStubImpl(myParent, packageName);
packageModList = new PsiModifierListStubImpl(packageStatement, 0);
}
myResult =
new PsiClassStubImpl<>(JavaStubElementTypes.CLASS, myParent, fqn == null ? TypeInfo.SimpleTypeInfo.NULL : fqn, shortName, null,
stubFlags);
myModList = new PsiModifierListStubImpl(myResult, classFlags);
if (PsiPackage.PACKAGE_INFO_CLASS.equals(shortName)) {
if (PsiPackage.PACKAGE_INFO_CLASS.equals(shortName) && packageModList != null) {
// Attach annotations to the package statement
myModList = new PsiModifierListStubImpl(packageStatement, 0);
myModList = packageModList;
}
if (isRecord) {
myHeaderStub = new PsiRecordHeaderStubImpl(myResult);
@@ -429,7 +429,7 @@ public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Querya
if (file instanceof PsiJavaFile) {
PsiPackageStatement stmt = ((PsiJavaFile)file).getPackageStatement();
if (stmt != null) {
ContainerUtil.addIfNotNull(modifiers, stmt.getAnnotationList());
modifiers.add(stmt.getAnnotationList());
}
}
}
@@ -20,7 +20,7 @@ import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
public class JavaFileElementType extends IFileElementType {
public static final int STUB_VERSION = 64;
public static final int STUB_VERSION = 65;
public JavaFileElementType() {
super("java.FILE", JavaLanguage.INSTANCE);
@@ -158,7 +158,7 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
private void cleanupBrokenPackageKeyword() {
PsiElement child = getFirstChild();
while (child instanceof PsiWhiteSpace || child instanceof PsiComment || child instanceof PsiErrorElement) {
if (child instanceof PsiErrorElement && child.getFirstChild() != null && child.getFirstChild().textMatches(JavaKeywords.PACKAGE)) {
if (isErrorElementThatContainsPackageStatement(child)) {
child.delete();
break;
}
@@ -166,6 +166,17 @@ public abstract class PsiJavaFileBaseImpl extends PsiFileImpl implements PsiJava
}
}
private static boolean isErrorElementThatContainsPackageStatement(PsiElement element) {
if (!(element instanceof PsiErrorElement)) return false;
PsiElement firstChild = element.getFirstChild();
if (firstChild == null) return false;
if (firstChild.textMatches(JavaKeywords.PACKAGE)) return true;
if (!(firstChild instanceof PsiModifierList)) return false;
PsiElement secondChild = firstChild.getNextSibling();
if (secondChild == null) return false;
return secondChild.textMatches(JavaKeywords.PACKAGE);
}
@Override
public PsiImportList getImportList() {
return withGreenStubOrAst(
@@ -55,8 +55,8 @@ public class PsiPackageStatementImpl extends JavaStubPsiElement<PsiPackageStatem
}
@Override
public PsiModifierList getAnnotationList() {
return getStubOrPsiChild(JavaStubElementTypes.MODIFIER_LIST, PsiModifierList.class);
public @NotNull PsiModifierList getAnnotationList() {
return getRequiredStubOrPsiChild(JavaStubElementTypes.MODIFIER_LIST, PsiModifierList.class);
}
@Override