[java] language level moved to file stub

Needed for accessing language level of module-info.class files.
This commit is contained in:
Roman Shevchenko
2016-07-12 16:50:11 +02:00
parent ddfa8c5540
commit fa9e98cd84
12 changed files with 92 additions and 96 deletions
@@ -38,7 +38,7 @@ import static com.intellij.psi.compiled.ClassFileDecompilers.Full;
public class ClassFileStubBuilder implements BinaryFileStubBuilder {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder");
public static final int STUB_VERSION = 15;
public static final int STUB_VERSION = 16;
@Override
public boolean acceptsFile(@NotNull VirtualFile file) {
@@ -34,7 +34,6 @@ import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.Pair;
@@ -75,7 +74,6 @@ import org.jetbrains.org.objectweb.asm.ClassReader;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -100,7 +98,6 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
private volatile SoftReference<StubTree> myStub;
private volatile TreeElement myMirrorFileElement;
private volatile ClsPackageStatementImpl myPackageStatement;
private volatile LanguageLevel myLanguageLevel;
private boolean myIsPhysical = true;
private boolean myInvalidated;
@@ -244,17 +241,14 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
@Override
@NotNull
public LanguageLevel getLanguageLevel() {
LanguageLevel level = myLanguageLevel;
if (level == null) {
List classes = ApplicationManager.getApplication().runReadAction(new Computable<List>() {
@Override
public List compute() {
return getStub().getChildrenStubs();
}
});
myLanguageLevel = level = !classes.isEmpty() ? ((PsiClassStub<?>)classes.get(0)).getLanguageLevel() : LanguageLevel.HIGHEST;
PsiClassHolderFileStub<?> stub = getStub();
if (stub instanceof PsiJavaFileStub) {
LanguageLevel level = ((PsiJavaFileStub)stub).getLanguageLevel();
if (level != null) {
return level;
}
}
return level;
return LanguageLevel.HIGHEST;
}
@Nullable
@@ -541,8 +535,6 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
myMirrorFileElement = null;
myPackageStatement = packageStatement;
}
myLanguageLevel = null;
}
@Override
@@ -590,10 +582,12 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
@Nullable
public static PsiJavaFileStub buildFileStub(@NotNull VirtualFile file, @NotNull byte[] bytes) throws ClsFormatException {
return buildFileStub(file, bytes, new Function<String, PsiJavaFileStub>() {
return buildFileStub(file, bytes, new Function<ClassReader, PsiJavaFileStub>() {
@Override
public PsiJavaFileStub fun(String packageName) {
return new PsiJavaFileStubImpl(packageName, true);
public PsiJavaFileStub fun(ClassReader reader) {
String packageName = getPackageName(reader.getClassName());
LanguageLevel level = ClsParsingUtil.getLanguageLevelByVersion(reader.readShort(6));
return new PsiJavaFileStubImpl(null, packageName, level, true);
}
});
}
@@ -601,7 +595,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
@Nullable
public static PsiJavaFileStub buildFileStub(@NotNull VirtualFile file,
@NotNull byte[] bytes,
@NotNull Function<String, PsiJavaFileStub> stubBuilder) throws ClsFormatException {
@NotNull Function<ClassReader, PsiJavaFileStub> stubBuilder) throws ClsFormatException {
try {
if (ClassFileViewProvider.isInnerClass(file, bytes)) {
return null;
@@ -609,8 +603,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
ClassReader reader = new ClassReader(bytes);
String className = file.getNameWithoutExtension();
String packageName = getPackageName(reader.getClassName());
PsiJavaFileStub stub = stubBuilder.fun(packageName);
PsiJavaFileStub stub = stubBuilder.fun(reader);
try {
FileContentPair source = new FileContentPair(file, bytes);
@@ -108,10 +108,6 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
byte stubFlags = PsiClassStubImpl.packFlags(isDeprecated, isInterface, isEnum, false, false, isAnnotationType, false, false);
myResult = new PsiClassStubImpl(JavaStubElementTypes.CLASS, myParent, fqn, shortName, null, stubFlags);
LanguageLevel languageLevel = ClsParsingUtil.getLanguageLevelByVersion(version);
if (languageLevel == null) languageLevel = LanguageLevel.HIGHEST;
((PsiClassStubImpl)myResult).setLanguageLevel(languageLevel);
myModList = new PsiModifierListStubImpl(myResult, packClassFlags(flags));
ClassInfo info = null;
@@ -18,7 +18,6 @@ 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.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiNameHelper;
@@ -39,7 +38,6 @@ import com.intellij.psi.stubs.StubInputStream;
import com.intellij.psi.stubs.StubOutputStream;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -48,7 +46,7 @@ import java.io.IOException;
* @author max
*/
public abstract class JavaClassElementType extends JavaStubElementType<PsiClassStub, PsiClass> {
public JavaClassElementType(@NotNull @NonNls final String id) {
public JavaClassElementType(@NotNull String id) {
super(id);
}
@@ -148,12 +146,11 @@ public abstract class JavaClassElementType extends JavaStubElementType<PsiClassS
}
@Override
public void serialize(@NotNull final PsiClassStub stub, @NotNull final StubOutputStream dataStream) throws IOException {
public void serialize(@NotNull PsiClassStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeByte(((PsiClassStubImpl)stub).getFlags());
if (!stub.isAnonymous()) {
dataStream.writeName(stub.getName());
dataStream.writeName(stub.getQualifiedName());
dataStream.writeByte(stub.getLanguageLevel().ordinal());
dataStream.writeName(stub.getSourceFileName());
}
else {
@@ -163,7 +160,7 @@ public abstract class JavaClassElementType extends JavaStubElementType<PsiClassS
@NotNull
@Override
public PsiClassStub deserialize(@NotNull final StubInputStream dataStream, final StubElement parentStub) throws IOException {
public PsiClassStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
byte flags = dataStream.readByte();
boolean isAnonymous = PsiClassStubImpl.isAnonymous(flags);
boolean isEnumConst = PsiClassStubImpl.isEnumConstInitializer(flags);
@@ -172,11 +169,9 @@ public abstract class JavaClassElementType extends JavaStubElementType<PsiClassS
if (!isAnonymous) {
StringRef name = dataStream.readName();
StringRef qname = dataStream.readName();
int languageLevelId = dataStream.readByte();
StringRef sourceFileName = dataStream.readName();
PsiClassStubImpl classStub = new PsiClassStubImpl(type, parentStub, StringRef.toString(qname), StringRef.toString(name), null, flags);
classStub.setLanguageLevel(LanguageLevel.values()[languageLevelId]);
classStub.setSourceFileName(sourceFileName);
classStub.setSourceFileName(StringRef.toString(sourceFileName));
return classStub;
}
else {
@@ -186,7 +181,7 @@ public abstract class JavaClassElementType extends JavaStubElementType<PsiClassS
}
@Override
public void indexStub(@NotNull final PsiClassStub stub, @NotNull final IndexSink sink) {
public void indexStub(@NotNull PsiClassStub stub, @NotNull IndexSink sink) {
boolean isAnonymous = stub.isAnonymous();
if (isAnonymous) {
String baseRef = stub.getBaseClassReferenceText();
@@ -212,4 +207,4 @@ public abstract class JavaClassElementType extends JavaStubElementType<PsiClassS
final String name = stub.getName();
return name != null ? name : super.getId(stub);
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,17 +21,11 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiClass;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
public interface PsiClassStub<T extends PsiClass> extends PsiMemberStub<T> {
@NonNls
@Nullable
String getQualifiedName();
@NonNls
@Nullable
String getBaseClassReferenceText();
@Nullable String getQualifiedName();
@Nullable String getBaseClassReferenceText();
boolean hasDeprecatedAnnotation();
boolean isInterface();
@@ -41,6 +35,8 @@ public interface PsiClassStub<T extends PsiClass> extends PsiMemberStub<T> {
boolean isAnonymousInQualifiedNew();
boolean isAnnotationType();
@Nullable String getSourceFileName();
/** @deprecated use {@link PsiJavaFileStub#getLanguageLevel()} (to be removed in IDEA 18) */
LanguageLevel getLanguageLevel();
String getSourceFileName();
}
@@ -19,15 +19,18 @@
*/
package com.intellij.psi.impl.java.stubs;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.stubs.PsiClassHolderFileStub;
public interface PsiJavaFileStub extends PsiClassHolderFileStub<PsiJavaFile> {
String getPackageName();
LanguageLevel getLanguageLevel();
boolean isCompiled();
StubPsiFactory getPsiFactory();
/** @deprecated override {@link #getPsiFactory()} instead (to be removed in IDEA 17) */
/** @deprecated override {@link #getPsiFactory()} instead (to be removed in IDEA 18) */
@SuppressWarnings("unused")
void setPsiFactory(StubPsiFactory factory);
}
@@ -21,21 +21,16 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.java.stubs.JavaClassElementType;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.BitUtil;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.Nullable;
/**
* @author max
*/
public class PsiClassStubImpl<T extends PsiClass> extends StubBase<T> implements PsiClassStub<T> {
private final String myQualifiedName;
private final String myName;
private final String myBaseRefText;
private final byte myFlags;
private static final int DEPRECATED = 0x01;
private static final int INTERFACE = 0x02;
private static final int ENUM = 0x04;
@@ -45,8 +40,11 @@ public class PsiClassStubImpl<T extends PsiClass> extends StubBase<T> implements
private static final int IN_QUALIFIED_NEW = 0x40;
private static final int DEPRECATED_ANNOTATION = 0x80;
private LanguageLevel myLanguageLevel;
private StringRef mySourceFileName;
private final String myQualifiedName;
private final String myName;
private final String myBaseRefText;
private final byte myFlags;
private String mySourceFileName;
public PsiClassStubImpl(final JavaClassElementType type,
final StubElement parent,
@@ -125,26 +123,25 @@ public class PsiClassStubImpl<T extends PsiClass> extends StubBase<T> implements
@Override
public LanguageLevel getLanguageLevel() {
return myLanguageLevel != null ? myLanguageLevel : LanguageLevel.HIGHEST;
StubElement parent = getParentStub();
if (parent instanceof PsiJavaFileStub) {
LanguageLevel level = ((PsiJavaFileStub)parent).getLanguageLevel();
if (level != null) {
return level;
}
}
return LanguageLevel.HIGHEST;
}
@Override
public String getSourceFileName() {
return StringRef.toString(mySourceFileName);
return mySourceFileName;
}
public void setLanguageLevel(final LanguageLevel languageLevel) {
myLanguageLevel = languageLevel;
}
public void setSourceFileName(final StringRef sourceFileName) {
public void setSourceFileName(String sourceFileName) {
mySourceFileName = sourceFileName;
}
public void setSourceFileName(final String sourceFileName) {
mySourceFileName = StringRef.fromString(sourceFileName);
}
@Override
public boolean isAnonymousInQualifiedNew() {
return BitUtil.isSet(myFlags, IN_QUALIFIED_NEW);
@@ -174,7 +171,8 @@ public class PsiClassStubImpl<T extends PsiClass> extends StubBase<T> implements
return flags;
}
@SuppressWarnings({"HardCodedStringLiteral"})
@Override
@SuppressWarnings("SpellCheckingInspection")
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("PsiClassStub[");
@@ -15,31 +15,33 @@
*/
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.impl.java.stubs.*;
import com.intellij.psi.stubs.PsiFileStubImpl;
import com.intellij.psi.tree.IStubFileElementType;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NotNull;
/**
* @author max
*/
public class PsiJavaFileStubImpl extends PsiFileStubImpl<PsiJavaFile> implements PsiJavaFileStub {
private final StringRef myPackageName;
private final String myPackageName;
private final LanguageLevel myLanguageLevel;
private final boolean myCompiled;
private StubPsiFactory myFactory;
public PsiJavaFileStubImpl(PsiJavaFile file, StringRef packageName, boolean compiled) {
super(file);
myPackageName = packageName;
myCompiled = compiled;
myFactory = compiled ? ClsStubPsiFactory.INSTANCE : SourceStubPsiFactory.INSTANCE;
public PsiJavaFileStubImpl(String packageName, boolean compiled) {
this(null, packageName, null, compiled);
}
public PsiJavaFileStubImpl(String packageName, boolean compiled) {
this(null, StringRef.fromString(packageName), compiled);
public PsiJavaFileStubImpl(PsiJavaFile file, String packageName, LanguageLevel languageLevel, boolean compiled) {
super(file);
myPackageName = packageName;
myLanguageLevel = languageLevel;
myCompiled = compiled;
myFactory = compiled ? ClsStubPsiFactory.INSTANCE : SourceStubPsiFactory.INSTANCE;
}
@NotNull
@@ -56,7 +58,12 @@ public class PsiJavaFileStubImpl extends PsiFileStubImpl<PsiJavaFile> implements
@Override
public String getPackageName() {
return StringRef.toString(myPackageName);
return myPackageName;
}
@Override
public LanguageLevel getLanguageLevel() {
return myLanguageLevel;
}
@Override
@@ -74,11 +81,6 @@ public class PsiJavaFileStubImpl extends PsiFileStubImpl<PsiJavaFile> implements
myFactory = factory;
}
@Override
public String toString() {
return "PsiJavaFileStub [" + myPackageName + "]";
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -88,6 +90,7 @@ public class PsiJavaFileStubImpl extends PsiFileStubImpl<PsiJavaFile> implements
if (myCompiled != stub.myCompiled) return false;
if (myPackageName != null ? !myPackageName.equals(stub.myPackageName) : stub.myPackageName != null) return false;
if (myLanguageLevel != stub.myLanguageLevel) return false;
return true;
}
@@ -95,7 +98,13 @@ public class PsiJavaFileStubImpl extends PsiFileStubImpl<PsiJavaFile> implements
@Override
public int hashCode() {
int result = myPackageName != null ? myPackageName.hashCode() : 0;
result = 31 * result + (myLanguageLevel != null ? myLanguageLevel.hashCode() : 0);
result = 31 * result + (myCompiled ? 1 : 0);
return result;
}
@Override
public String toString() {
return "PsiJavaFileStub [" + myPackageName + "]";
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ import java.io.IOException;
* @author max
*/
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
public static final int STUB_VERSION = 24;
public static final int STUB_VERSION = 25;
public JavaFileElementType() {
super("java.FILE", JavaLanguage.INSTANCE);
@@ -92,20 +92,23 @@ public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileSt
}
@Override
public void serialize(@NotNull final PsiJavaFileStub stub, @NotNull final StubOutputStream dataStream) throws IOException {
public void serialize(@NotNull PsiJavaFileStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeBoolean(stub.isCompiled());
LanguageLevel level = stub.getLanguageLevel();
dataStream.writeByte(level != null ? level.ordinal() : -1);
dataStream.writeName(stub.getPackageName());
}
@NotNull
@Override
public PsiJavaFileStub deserialize(@NotNull final StubInputStream dataStream, final StubElement parentStub) throws IOException {
public PsiJavaFileStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
boolean compiled = dataStream.readBoolean();
StringRef packName = dataStream.readName();
return new PsiJavaFileStubImpl(null, packName, compiled);
int level = dataStream.readByte();
StringRef packageName = dataStream.readName();
return new PsiJavaFileStubImpl(null, StringRef.toString(packageName), level >= 0 ? LanguageLevel.values()[level] : null, compiled);
}
@Override
public void indexStub(@NotNull final PsiJavaFileStub stub, @NotNull final IndexSink sink) {
}
}
@SuppressWarnings("LambdaUnfriendlyMethodOverload")
public void indexStub(@NotNull PsiJavaFileStub stub, @NotNull IndexSink sink) { }
}
@@ -28,7 +28,6 @@ import com.intellij.psi.stubs.LightStubBuilder;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.io.StringRef;
import org.jetbrains.annotations.NotNull;
public class JavaLightStubBuilder extends LightStubBuilder {
@@ -47,7 +46,7 @@ public class JavaLightStubBuilder extends LightStubBuilder {
refText = JavaSourceUtil.getReferenceText(tree, ref);
}
}
return new PsiJavaFileStubImpl((PsiJavaFile)file, StringRef.fromString(refText), false);
return new PsiJavaFileStubImpl((PsiJavaFile)file, refText, null, false);
}
@Override
@@ -122,6 +121,7 @@ public class JavaLightStubBuilder extends LightStubBuilder {
private boolean seenNew;
@Override
@SuppressWarnings("IfStatementWithIdenticalBranches")
public boolean visit(IElementType type) {
if (ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(type)) {
return true;
@@ -150,4 +150,4 @@ public class JavaLightStubBuilder extends LightStubBuilder {
return true;
}
}
}
}
@@ -113,7 +113,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
catch (IOException ignored) { }
}
};
PsiJavaFileStubImpl stub = new PsiJavaFileStubImpl("do.not.know.yet", true);
PsiJavaFileStubImpl stub = new PsiJavaFileStubImpl("java.lang", true);
StubBuildingVisitor<VirtualFile> visitor = new StubBuildingVisitor<>(file, strategy, stub, 0, null);
new ClassReader(file.contentsToByteArray()).accept(visitor, ClassReader.SKIP_FRAMES);
}
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.IoTestUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.impl.compiled.ClsFileImpl;
import com.intellij.psi.impl.compiled.ClsParameterImpl;
import com.intellij.psi.impl.java.stubs.PsiMethodStub;
@@ -87,6 +88,8 @@ public class ClsPsiTest extends LightIdeaTestCase {
assertTrue(file.isValid());
assertEquals("pack", file.getPackageName());
assertEquals(1, file.getClasses().length);
file = getFile("MyEnum");
assertEquals(LanguageLevel.JDK_1_5, file.getLanguageLevel());
}
public void testClassBasics() {