[java, import-module] Refactor import statement hierarchy IDEA-353091

IJ-CR-139321

GitOrigin-RevId: f5a2188b18afad7cb2912d3ff282ef9929f20ca6
This commit is contained in:
Aleksey Dobrynin
2024-07-19 12:20:22 +00:00
committed by intellij-monorepo-bot
parent 0fb89ef48e
commit 0a0e345835
25 changed files with 155 additions and 306 deletions
@@ -1,8 +1,6 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInspection.unusedImport;
import com.intellij.psi.PsiImportDeclaration;
import com.intellij.psi.PsiImportModuleStatement;
import com.intellij.psi.PsiImportStatementBase;
import com.siyeh.ig.psiutils.PsiElementOrderComparator;
@@ -11,7 +9,7 @@ import java.util.Comparator;
/**
* @author Bas Leijdekkers
*/
final class ImportStatementComparator implements Comparator<PsiImportDeclaration> {
final class ImportStatementComparator implements Comparator<PsiImportStatementBase> {
public static final ImportStatementComparator INSTANCE = new ImportStatementComparator();
private ImportStatementComparator() {}
@@ -21,34 +19,12 @@ final class ImportStatementComparator implements Comparator<PsiImportDeclaration
}
@Override
public int compare(PsiImportDeclaration importStatementDeclaration1, PsiImportDeclaration importStatementDeclaration2) {
int type1 = getCompareType(importStatementDeclaration1);
int type2 = getCompareType(importStatementDeclaration2);
if (type1 != type2) {
return type1 > type2 ? -1 : 1;
public int compare(PsiImportStatementBase importStatementBase1, PsiImportStatementBase importStatementBase2) {
final boolean onDemand = importStatementBase1.isOnDemand();
if (onDemand != importStatementBase2.isOnDemand()) {
return onDemand ? -1 : 1;
}
// just sort on demand imports first, and sort the rest in reverse file order.
return -PsiElementOrderComparator.getInstance().compare(importStatementDeclaration1, importStatementDeclaration2);
}
/**
* Returns the comparison type for a given import statement.
*
* @param importStatement the import statement to analyze
* @return an integer representing the type of import:
* 0 it's an import,
* 1 if it's an on-demand import,
* 2 if it's a module import,
* 4 otherwise
*/
private static int getCompareType(PsiImportDeclaration importStatement) {
if (importStatement instanceof PsiImportStatementBase importStatementBase) {
return importStatementBase.isOnDemand() ? 1 : 0;
}
else if (importStatement instanceof PsiImportModuleStatement) {
return 2;
} else {
return 4;
}
return -PsiElementOrderComparator.getInstance().compare(importStatementBase1, importStatementBase2);
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.editorActions.smartEnter;
import com.intellij.lang.ASTNode;
@@ -88,7 +88,8 @@ public class AfterSemicolonEnterProcessor implements ASTNodeEnterProcessor {
ASTNode node = BasicJavaAstTreeUtil.toNode(psiElement);
return
BasicJavaAstTreeUtil.is(node, BASIC_IMPORT_STATEMENT) ||
BasicJavaAstTreeUtil.is(node, BASIC_IMPORT_STATIC_STATEMENT);
BasicJavaAstTreeUtil.is(node, BASIC_IMPORT_STATIC_STATEMENT) ||
BasicJavaAstTreeUtil.is(node, BASIC_IMPORT_MODULE_STATEMENT);
}
private static int getErrorElementOffset(PsiElement elt) {
@@ -95,10 +95,8 @@ public interface BasicElementTypes extends JavaTokenType, JavaDocTokenType, Basi
BASIC_PROVIDES_STATEMENT);
ParentAwareTokenSet BASIC_IMPORT_STATEMENT_BASE_BIT_SET = ParentAwareTokenSet.create(BASIC_IMPORT_STATEMENT,
BASIC_IMPORT_STATIC_STATEMENT);
ParentAwareTokenSet BASIC_IMPORT_STATEMENT_DECLARATION_BIT_SET = ParentAwareTokenSet.create(BASIC_IMPORT_STATEMENT,
BASIC_IMPORT_STATIC_STATEMENT,
BASIC_IMPORT_MODULE_STATEMENT);
BASIC_IMPORT_STATIC_STATEMENT,
BASIC_IMPORT_MODULE_STATEMENT);
TokenSet BASIC_CLASS_KEYWORD_BIT_SET =
TokenSet.create(CLASS_KEYWORD, INTERFACE_KEYWORD, ENUM_KEYWORD, RECORD_KEYWORD);
ParentAwareTokenSet BASIC_MEMBER_BIT_SET = ParentAwareTokenSet.create(BASIC_CLASS, BASIC_FIELD, BASIC_ENUM_CONSTANT,
@@ -21,7 +21,7 @@ public class WhiteSpaceAndCommentSetHolder {
BasicElementTypes.BASIC_FULL_MEMBER_BIT_SET);
private static final ParentAwareTokenSet TRAILING_COMMENT_SET =
orSet(create(BasicJavaElementType.BASIC_PACKAGE_STATEMENT), BasicElementTypes.BASIC_IMPORT_STATEMENT_DECLARATION_BIT_SET,
orSet(create(BasicJavaElementType.BASIC_PACKAGE_STATEMENT), BasicElementTypes.BASIC_IMPORT_STATEMENT_BASE_BIT_SET,
BasicElementTypes.BASIC_FULL_MEMBER_BIT_SET, BasicElementTypes.BASIC_JAVA_STATEMENT_BIT_SET);
private WhiteSpaceAndCommentSetHolder() {
@@ -268,16 +268,16 @@ public abstract class ImportClassFixBase<T extends PsiElement, R extends PsiRefe
private static void filterAlreadyImportedButUnresolved(@NotNull Collection<PsiClass> list, @NotNull PsiFile containingFile) {
if (!(containingFile instanceof PsiJavaFile javaFile)) return;
PsiImportList importList = javaFile.getImportList();
PsiImportDeclaration[] importStatements = importList == null ? PsiImportStatementBase.EMPTY_ARRAY : importList.getAllImportDeclarations();
PsiImportStatementBase[] importStatements = importList == null ? PsiImportStatementBase.EMPTY_ARRAY : importList.getAllImportStatements();
Set<String> unresolvedImports = new HashSet<>(importStatements.length);
for (PsiImportDeclaration statement : importStatements) {
if (statement instanceof PsiImportStatementBase importStatementBase) {
PsiJavaCodeReferenceElement ref = importStatementBase.getImportReference();
String name = ref == null ? null : ref.getReferenceName();
if (name != null && ref.resolve() == null) unresolvedImports.add(name);
} else if (statement instanceof PsiImportModuleStatement importModuleStatement) {
for (PsiImportStatementBase statement : importStatements) {
if (statement instanceof PsiImportModuleStatement importModuleStatement) {
PsiJavaModuleReference ref = importModuleStatement.getModuleReference();
if (ref != null && ref.resolve() == null) unresolvedImports.add(importModuleStatement.getReferenceName());
} else {
PsiJavaCodeReferenceElement ref = statement.getImportReference();
String name = ref == null ? null : ref.getReferenceName();
if (name != null && ref.resolve() == null) unresolvedImports.add(name);
}
}
if (unresolvedImports.isEmpty()) return;
@@ -1,26 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi;
import com.intellij.util.ArrayFactory;
import org.jetbrains.annotations.Nullable;
public interface PsiImportDeclaration extends PsiElement {
/**
* The empty array of PSI base import statements which can be reused to avoid unnecessary allocations.
*/
PsiImportDeclaration[] EMPTY_ARRAY = new PsiImportDeclaration[0];
ArrayFactory<PsiImportDeclaration> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PsiImportDeclaration[count];
/**
* Resolves the reference to the imported class, package or member.
*
* @return the target element, or null if it was not possible to resolve the reference to a valid target.
*/
@Nullable
PsiElement resolve();
default boolean isForeignFileImport() {
return false;
}
}
@@ -37,21 +37,12 @@ public interface PsiImportList extends PsiElement {
PsiImportModuleStatement @NotNull [] getImportModuleStatements();
/**
* Returns all import statements (without import module statements) contained in the list.
* @deprecated Use {@link #getAllImportDeclarations()}
* Returns all import statements contained in the list.
*
* @return the array of import statements.
*/
@Deprecated
PsiImportStatementBase @NotNull [] getAllImportStatements();
/**
* Returns all import declarations contained in the list.
*
* @return the array of import declarations
*/
PsiImportDeclaration @NotNull [] getAllImportDeclarations();
/**
* Searches the list for a single-class import statement importing the specified class.
*
@@ -82,25 +73,13 @@ public interface PsiImportList extends PsiElement {
/**
* Searches the list for a single import or import static statement importing the specified
* identifier.
* @deprecated Use {@link #findSingleImportDeclaration(String)}
*
* @param name the name of the imported class or method.
* @return the import statement, or null if one was not found.
*/
@Deprecated
@Nullable
PsiImportStatementBase findSingleImportStatement(String name);
/**
* Searches the list for a single import or import static or import module statement importing the specified
* identifier.
*
* @param name the name of the imported class or method or module.
* @return the import statement, or null if one was not found.
*/
@Nullable
PsiImportDeclaration findSingleImportDeclaration(String name);
/**
* Checks if replacing this import list with the specified import list will cause no
* modifications to the file.
@@ -8,7 +8,7 @@ import org.jetbrains.annotations.Nullable;
* Represents a Java {@code import module} statement.
*/
@ApiStatus.Experimental
public interface PsiImportModuleStatement extends PsiImportDeclaration {
public interface PsiImportModuleStatement extends PsiImportStatementBase {
/**
* The empty array of PSI module import statements which can be reused to avoid unnecessary allocations.
*/
@@ -36,4 +36,19 @@ public interface PsiImportModuleStatement extends PsiImportDeclaration {
* @return the reference to the module imported, or null if the reference is not resolvable or missing.
*/
@Nullable PsiJavaModuleReference getModuleReference();
@Override
default boolean isOnDemand() {
return true;
}
@Override
@Nullable default PsiJavaCodeReferenceElement getImportReference() {
return null;
}
@Override
default boolean isForeignFileImport() {
return false;
}
}
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.Nullable;
/**
* Represents a Java {@code import} or {@code import static} statement.
*/
public interface PsiImportStatementBase extends PsiImportDeclaration {
public interface PsiImportStatementBase extends PsiElement {
/**
* The empty array of PSI base import statements which can be reused to avoid unnecessary allocations.
*/
@@ -16,9 +16,9 @@ public interface PsiImportStatementBase extends PsiImportDeclaration {
ArrayFactory<PsiImportStatementBase> ARRAY_FACTORY = count -> count == 0 ? EMPTY_ARRAY : new PsiImportStatementBase[count];
/**
* Checks if the statement represents a single element or on-demand import.
* Checks if the statement represents a single element or a group import (on-demand).
*
* @return true if the import statement is on-demand, false otherwise.
* @return true if the import statement is on-demand or module, false otherwise.
*/
boolean isOnDemand();
@@ -30,4 +30,14 @@ public interface PsiImportStatementBase extends PsiImportDeclaration {
*/
@Nullable
PsiJavaCodeReferenceElement getImportReference();
/**
* Resolves the reference to the imported class, package, module or member.
*
* @return the target element, or null if it was not possible to resolve the reference to a valid target.
*/
@Nullable
PsiElement resolve();
boolean isForeignFileImport();
}
@@ -44,11 +44,6 @@ public class ClsStubPsiFactory extends StubPsiFactory {
throw new UnsupportedOperationException();
}
@Override
public PsiImportModuleStatement createImportStatement(PsiImportModuleStatementStub stub) {
throw new UnsupportedOperationException();
}
@Override
public PsiMethod createMethod(PsiMethodStub stub) {
return new ClsMethodImpl(stub);
@@ -1,64 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.java.stubs;
import com.intellij.lang.ASTNode;
import com.intellij.lang.LighterAST;
import com.intellij.lang.LighterASTNode;
import com.intellij.psi.PsiImportModuleStatement;
import com.intellij.psi.impl.java.stubs.impl.PsiImportModuleStatementStubImpl;
import com.intellij.psi.impl.source.PsiImportModuleStatementImpl;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.JavaSourceUtil;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public abstract class JavaImportModuleStatementElementType extends JavaStubElementType<PsiImportModuleStatementStub, PsiImportModuleStatement> {
public JavaImportModuleStatementElementType(final @NonNls @NotNull String id, @NotNull IElementType parentElementType) {
super(id, parentElementType);
}
@Override
public PsiImportModuleStatement createPsi(final @NotNull PsiImportModuleStatementStub stub) {
return getPsiFactory(stub).createImportStatement(stub);
}
@Override
public PsiImportModuleStatement createPsi(final @NotNull ASTNode node) {
return new PsiImportModuleStatementImpl(node);
}
@Override
public @NotNull PsiImportModuleStatementStub createStub(@NotNull LighterAST tree, @NotNull LighterASTNode node, @NotNull StubElement<?> parentStub) {
String refText = null;
for (LighterASTNode child : tree.getChildren(node)) {
IElementType type = child.getTokenType();
if (type == JavaElementType.MODULE_REFERENCE) {
refText = JavaSourceUtil.getReferenceText(tree, child);
}
}
return new PsiImportModuleStatementStubImpl(parentStub, refText);
}
@Override
public void serialize(final @NotNull PsiImportModuleStatementStub stub, final @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getImportReferenceText());
}
@Override
public @NotNull PsiImportModuleStatementStub deserialize(final @NotNull StubInputStream dataStream, final StubElement parentStub) throws IOException {
String refText = dataStream.readNameString();
return new PsiImportModuleStatementStubImpl(parentStub, refText);
}
@Override
public void indexStub(final @NotNull PsiImportModuleStatementStub stub, final @NotNull IndexSink sink) {
}
}
@@ -7,10 +7,12 @@ import com.intellij.lang.LighterASTNode;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiImportStatementBase;
import com.intellij.psi.impl.java.stubs.impl.PsiImportStatementStubImpl;
import com.intellij.psi.impl.source.PsiImportModuleStatementImpl;
import com.intellij.psi.impl.source.PsiImportStatementImpl;
import com.intellij.psi.impl.source.PsiImportStaticStatementImpl;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.JavaSourceUtil;
import com.intellij.psi.impl.source.tree.java.ImportModuleStatementElement;
import com.intellij.psi.impl.source.tree.java.ImportStaticStatementElement;
import com.intellij.psi.stubs.IndexSink;
import com.intellij.psi.stubs.StubElement;
@@ -37,6 +39,9 @@ public abstract class JavaImportStatementElementType extends JavaStubElementType
if (node instanceof ImportStaticStatementElement) {
return new PsiImportStaticStatementImpl(node);
}
else if (node instanceof ImportModuleStatementElement) {
return new PsiImportModuleStatementImpl(node);
}
else {
return new PsiImportStatementImpl(node);
}
@@ -49,7 +54,9 @@ public abstract class JavaImportStatementElementType extends JavaStubElementType
for (LighterASTNode child : tree.getChildren(node)) {
IElementType type = child.getTokenType();
if (type == JavaElementType.JAVA_CODE_REFERENCE || type == JavaElementType.IMPORT_STATIC_REFERENCE) {
if (type == JavaElementType.JAVA_CODE_REFERENCE ||
type == JavaElementType.IMPORT_STATIC_REFERENCE ||
type == JavaElementType.MODULE_REFERENCE) {
refText = JavaSourceUtil.getReferenceText(tree, child);
}
else if (type == JavaTokenType.DOT) {
@@ -57,7 +64,8 @@ public abstract class JavaImportStatementElementType extends JavaStubElementType
}
}
byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT);
byte flags = PsiImportStatementStubImpl.packFlags(isOnDemand, node.getTokenType() == JavaElementType.IMPORT_STATIC_STATEMENT,
node.getTokenType() == JavaElementType.IMPORT_MODULE_STATEMENT);
return new PsiImportStatementStubImpl(parentStub, refText, flags);
}
@@ -187,8 +187,8 @@ public interface JavaStubElementTypes {
return new ImportStaticStatementElement();
}
};
JavaImportModuleStatementElementType IMPORT_MODULE_STATEMENT =
new JavaImportModuleStatementElementType("IMPORT_MODULE_STATEMENT", BasicJavaElementType.BASIC_IMPORT_MODULE_STATEMENT) {
JavaImportStatementElementType IMPORT_MODULE_STATEMENT =
new JavaImportStatementElementType("IMPORT_MODULE_STATEMENT", BasicJavaElementType.BASIC_IMPORT_MODULE_STATEMENT) {
@Override
public @NotNull ASTNode createCompositeNode() {
return new ImportModuleStatementElement();
@@ -1,14 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiImportDeclaration;
import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.Nullable;
public interface PsiImportDeclarationStub<T extends PsiImportDeclaration, R extends PsiElement> extends StubElement<T> {
@Nullable
String getImportReferenceText();
@Nullable
R getReference();
}
@@ -1,8 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.PsiImportModuleStatement;
import com.intellij.psi.PsiJavaModuleReferenceElement;
public interface PsiImportModuleStatementStub extends PsiImportDeclarationStub<PsiImportModuleStatement, PsiJavaModuleReferenceElement> {
}
@@ -7,8 +7,20 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.PsiImportStatementBase;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiJavaModuleReferenceElement;
import com.intellij.psi.stubs.StubElement;
import org.jetbrains.annotations.Nullable;
public interface PsiImportStatementStub extends PsiImportDeclarationStub<PsiImportStatementBase, PsiJavaCodeReferenceElement> {
public interface PsiImportStatementStub extends StubElement<PsiImportStatementBase> {
boolean isStatic();
boolean isOnDemand();
boolean isModule();
@Nullable
String getImportReferenceText();
@Nullable
PsiJavaCodeReferenceElement getReference();
@Nullable PsiJavaModuleReferenceElement getModuleReference();
}
@@ -43,12 +43,15 @@ public class SourceStubPsiFactory extends StubPsiFactory {
@Override
public PsiImportStatementBase createImportStatement(PsiImportStatementStub stub) {
return stub.isStatic()? new PsiImportStaticStatementImpl(stub) : new PsiImportStatementImpl(stub);
}
@Override
public PsiImportModuleStatement createImportStatement(PsiImportModuleStatementStub stub) {
return new PsiImportModuleStatementImpl(stub);
if (stub.isStatic()) {
return new PsiImportStaticStatementImpl(stub);
}
else if (stub.isModule()) {
return new PsiImportModuleStatementImpl(stub);
}
else {
return new PsiImportStatementImpl(stub);
}
}
@Override
@@ -18,8 +18,6 @@ public abstract class StubPsiFactory {
public abstract PsiImportStatementBase createImportStatement(PsiImportStatementStub stub);
public abstract PsiImportModuleStatement createImportStatement(PsiImportModuleStatementStub stub);
public abstract PsiMethod createMethod(PsiMethodStub stub);
public abstract PsiModifierList createModifierList(PsiModifierListStub stub);
@@ -1,60 +0,0 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiImportModuleStatement;
import com.intellij.psi.PsiJavaModuleReferenceElement;
import com.intellij.psi.PsiJavaParserFacade;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiImportModuleStatementStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.SoftReference;
import static com.intellij.reference.SoftReference.dereference;
public class PsiImportModuleStatementStubImpl extends StubBase<PsiImportModuleStatement> implements PsiImportModuleStatementStub {
private final String myText;
private SoftReference<PsiJavaModuleReferenceElement> myReference;
public PsiImportModuleStatementStubImpl(final StubElement parent, final String text) {
super(parent, JavaStubElementTypes.IMPORT_MODULE_STATEMENT);
myText = text;
}
@Override
public String getImportReferenceText() {
return myText;
}
@Override
public @Nullable PsiJavaModuleReferenceElement getReference() {
PsiJavaModuleReferenceElement ref = dereference(myReference);
if (ref == null) {
ref = createReference();
myReference = new SoftReference<>(ref);
}
return ref;
}
private @Nullable PsiJavaModuleReferenceElement createReference() {
final String refText = getImportReferenceText();
if (refText == null) return null;
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
try {
return parserFacade.createModuleReferenceFromText(refText, getPsi());
}
catch (IncorrectOperationException e) {
return null;
}
}
@Override
public String toString() {
return "PsiImportModuleStatementStub[" + getImportReferenceText() + "]";
}
}
@@ -1,10 +1,8 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiImportStatementBase;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiJavaParserFacade;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaImportStatementElementType;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiImportStatementStub;
import com.intellij.psi.impl.source.PsiJavaCodeReferenceElementImpl;
@@ -12,6 +10,7 @@ import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.BitUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.SoftReference;
@@ -22,16 +21,25 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
private final byte myFlags;
private final String myText;
private SoftReference<PsiJavaCodeReferenceElement> myReference;
private SoftReference<PsiJavaModuleReferenceElement> myModuleReference;
private static final int ON_DEMAND = 0x01;
private static final int STATIC = 0x02;
private static final int MODULE = 0x04;
public PsiImportStatementStubImpl(final StubElement parent, final String text, final byte flags) {
super(parent, isStatic(flags) ? JavaStubElementTypes.IMPORT_STATIC_STATEMENT : JavaStubElementTypes.IMPORT_STATEMENT);
super(parent, getImportType(flags));
myText = text;
myFlags = flags;
}
@NotNull
private static JavaImportStatementElementType getImportType(final byte flags) {
if (isStatic(flags)) return JavaStubElementTypes.IMPORT_STATIC_STATEMENT;
if (isModule(flags)) return JavaStubElementTypes.IMPORT_MODULE_STATEMENT;
return JavaStubElementTypes.IMPORT_STATEMENT;
}
@Override
public boolean isStatic() {
return isStatic(myFlags);
@@ -41,6 +49,15 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
return BitUtil.isSet(flags, STATIC);
}
@Override
public boolean isModule() {
return isModule(myFlags);
}
private static boolean isModule(final byte flags) {
return BitUtil.isSet(flags, MODULE);
}
@Override
public boolean isOnDemand() {
return BitUtil.isSet(myFlags, ON_DEMAND);
@@ -58,14 +75,25 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
@Override
public @Nullable PsiJavaCodeReferenceElement getReference() {
PsiJavaCodeReferenceElement ref = dereference(myReference);
if (ref == null) {
if (ref == null && !isModule()) {
ref = isStatic() ? getStaticReference() : getRegularReference();
myReference = new SoftReference<>(ref);
}
return ref;
}
public static byte packFlags(boolean isOnDemand, boolean isStatic) {
@Override
public @Nullable PsiJavaModuleReferenceElement getModuleReference() {
if (!isModule()) return null;
PsiJavaModuleReferenceElement ref = dereference(myModuleReference);
if (ref == null) {
ref = createModuleReference();
myModuleReference = new SoftReference<>(ref);
}
return ref;
}
public static byte packFlags(boolean isOnDemand, boolean isStatic, boolean isModule) {
byte flags = 0;
if (isOnDemand) {
flags |= ON_DEMAND;
@@ -73,6 +101,9 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
if (isStatic) {
flags |= STATIC;
}
if (isModule) {
flags |= MODULE;
}
return flags;
}
@@ -94,6 +125,18 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
return refElement;
}
private @Nullable PsiJavaModuleReferenceElement createModuleReference() {
final String refText = getImportReferenceText();
if (refText == null) return null;
try {
final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
return parserFacade.createModuleReferenceFromText(refText, getPsi());
}
catch (IncorrectOperationException ignore) {
return null;
}
}
private @Nullable PsiJavaCodeReferenceElement createReference() {
final String refText = getImportReferenceText();
if (refText == null) return null;
@@ -116,10 +159,13 @@ public class PsiImportStatementStubImpl extends StubBase<PsiImportStatementBase>
if (isStatic()) {
builder.append("static ");
}
if (isModule()) {
builder.append("module ");
}
builder.append(getImportReferenceText());
if (isOnDemand()) {
if (isOnDemand() && !isModule()) {
builder.append(".*");
}
@@ -18,7 +18,7 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
private volatile Map<String,PsiImportStatement> myClassNameToImportMap;
private volatile Map<String,PsiImportStatement> myPackageNameToImportMap;
private volatile Map<String,PsiImportModuleStatement> myModuleNameToImportMap;
private volatile Map<String,PsiImportDeclaration> myNameToSingleImportMap;
private volatile Map<String,PsiImportStatementBase> myNameToSingleImportMap;
public PsiImportListImpl(PsiImportListStub stub) {
super(stub, JavaStubElementTypes.IMPORT_LIST);
@@ -63,7 +63,7 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
@Override
public PsiImportModuleStatement @NotNull [] getImportModuleStatements() {
return getStubOrPsiChildren(IMPORT_MODULE_STATEMENT_BIT_SET, PsiImportModuleStatementImpl.EMPTY_ARRAY);
return getStubOrPsiChildren(IMPORT_MODULE_STATEMENT_BIT_SET, PsiImportModuleStatementImpl.ARRAY_FACTORY);
}
@Override
@@ -71,11 +71,6 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
return getStubOrPsiChildren(ElementType.IMPORT_STATEMENT_BASE_BIT_SET, PsiImportStatementBase.ARRAY_FACTORY);
}
@Override
public PsiImportDeclaration @NotNull [] getAllImportDeclarations() {
return getStubOrPsiChildren(ElementType.IMPORT_STATEMENT_DECLARATION_BIT_SET, PsiImportDeclaration.ARRAY_FACTORY);
}
@Override
public PsiImportStatement findSingleClassImportStatement(String name) {
while (true) {
@@ -116,27 +111,9 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
}
@Override
public PsiImportStatementBase findSingleImportStatement(String name) {
public @Nullable PsiImportStatementBase findSingleImportStatement(String name) {
while (true) {
Map<String, PsiImportDeclaration> map = myNameToSingleImportMap;
if (map == null) {
initializeMaps();
}
else {
PsiImportDeclaration importDeclaration = map.get(name);
if (importDeclaration instanceof PsiImportStatementBase) {
return (PsiImportStatementBase)importDeclaration;
} else {
return null;
}
}
}
}
@Override
public @Nullable PsiImportDeclaration findSingleImportDeclaration(String name) {
while (true) {
Map<String, PsiImportDeclaration> map = myNameToSingleImportMap;
Map<String, PsiImportStatementBase> map = myNameToSingleImportMap;
if (map == null) {
initializeMaps();
}
@@ -154,7 +131,7 @@ public class PsiImportListImpl extends JavaStubPsiElement<PsiImportListStub> imp
private void initializeMaps() {
Map<String, PsiImportStatement> classNameToImportMap = new HashMap<>();
Map<String, PsiImportStatement> packageNameToImportMap = new HashMap<>();
Map<String, PsiImportDeclaration> nameToSingleImportMap = new HashMap<>();
Map<String, PsiImportStatementBase> nameToSingleImportMap = new HashMap<>();
Map<String, PsiImportModuleStatement> moduleNameToImportMap = new HashMap<>();
PsiImportStatement[] imports = getImportStatements();
for (PsiImportStatement anImport : imports) {
@@ -4,7 +4,7 @@ package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.psi.*;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiImportModuleStatementStub;
import com.intellij.psi.impl.java.stubs.PsiImportStatementStub;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayFactory;
import org.jetbrains.annotations.NotNull;
@@ -15,14 +15,14 @@ import java.lang.ref.SoftReference;
import static com.intellij.openapi.util.text.StringUtil.nullize;
import static com.intellij.reference.SoftReference.dereference;
public class PsiImportModuleStatementImpl extends JavaStubPsiElement<PsiImportModuleStatementStub> implements PsiImportModuleStatement {
public class PsiImportModuleStatementImpl extends PsiImportStatementBaseImpl implements PsiImportModuleStatement {
public static final PsiImportModuleStatementImpl[] EMPTY_ARRAY = new PsiImportModuleStatementImpl[0];
public static final ArrayFactory<PsiImportModuleStatementImpl> ARRAY_FACTORY =
count -> count == 0 ? EMPTY_ARRAY : new PsiImportModuleStatementImpl[count];
private SoftReference<PsiJavaModuleReference> myReference;
public PsiImportModuleStatementImpl(PsiImportModuleStatementStub stub) {
public PsiImportModuleStatementImpl(PsiImportStatementStub stub) {
super(stub, JavaStubElementTypes.IMPORT_MODULE_STATEMENT);
}
@@ -46,7 +46,7 @@ public class PsiImportModuleStatementImpl extends JavaStubPsiElement<PsiImportMo
@Override
public @Nullable PsiJavaModuleReference getModuleReference() {
PsiImportModuleStatementStub stub = getStub();
PsiImportStatementStub stub = getStub();
if (stub != null) {
String refText = nullize(stub.getImportReferenceText());
if (refText == null) return null;
@@ -7,6 +7,7 @@ import com.intellij.psi.PsiImportStatementBase;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.impl.java.stubs.PsiImportStatementStub;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.PsiUtilCore;
@@ -28,7 +29,8 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement<PsiI
return stub.isOnDemand();
}
return calcTreeElement().findChildByRoleAsPsiElement(ChildRole.IMPORT_ON_DEMAND_DOT) != null;
return calcTreeElement().findChildByRoleAsPsiElement(ChildRole.IMPORT_ON_DEMAND_DOT) != null ||
calcTreeElement().findChildByType(JavaElementType.MODULE_REFERENCE) != null;
}
@Override
@@ -46,4 +48,9 @@ public abstract class PsiImportStatementBaseImpl extends JavaStubPsiElement<PsiI
PsiJavaCodeReferenceElement reference = getImportReference();
return reference == null ? null : reference.resolve();
}
@Override
public boolean isForeignFileImport() {
return false;
}
}
@@ -260,9 +260,6 @@ public class ClassResolverProcessor implements PsiScopeProcessor, NameHint, Elem
if (myCurrentFileContext instanceof PsiImportStatementBase) {
return ((PsiImportStatementBase)myCurrentFileContext).isOnDemand();
}
if (myCurrentFileContext instanceof PsiImportModuleStatement) {
return true;
}
return false;
}
@@ -63,8 +63,7 @@ public interface ElementType extends JavaTokenType, JavaDocTokenType, JavaElemen
TokenSet JAVA_MODULE_STATEMENT_BIT_SET = TokenSet.create(
REQUIRES_STATEMENT, EXPORTS_STATEMENT, OPENS_STATEMENT, USES_STATEMENT, PROVIDES_STATEMENT);
TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT);
TokenSet IMPORT_STATEMENT_DECLARATION_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT, IMPORT_MODULE_STATEMENT);
TokenSet IMPORT_STATEMENT_BASE_BIT_SET = TokenSet.create(IMPORT_STATEMENT, IMPORT_STATIC_STATEMENT, IMPORT_MODULE_STATEMENT);
TokenSet CLASS_KEYWORD_BIT_SET = BasicElementTypes.BASIC_CLASS_KEYWORD_BIT_SET;
TokenSet MEMBER_BIT_SET = TokenSet.create(CLASS, FIELD, ENUM_CONSTANT, METHOD, ANNOTATION_METHOD);
TokenSet FULL_MEMBER_BIT_SET = TokenSet.orSet(MEMBER_BIT_SET, TokenSet.create(