[java] module stub, module name index, module-info.class files reading

This commit is contained in:
Roman Shevchenko
2016-07-12 18:30:57 +02:00
parent fa9e98cd84
commit 25610a8713
29 changed files with 595 additions and 76 deletions
@@ -0,0 +1,61 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @author max
*/
package com.intellij.psi.impl.java.stubs.index;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public class JavaModuleNameIndex extends StringStubIndexExtension<PsiJavaModule> {
private static final JavaModuleNameIndex ourInstance = new JavaModuleNameIndex();
public static JavaModuleNameIndex getInstance() {
return ourInstance;
}
@Override
public int getVersion() {
return super.getVersion() + (FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping ? 2 : 0);
}
@NotNull
@Override
public StubIndexKey<String, PsiJavaModule> getKey() {
return JavaStubIndexKeys.MODULE_NAMES;
}
@Override
public Collection<PsiJavaModule> get(@NotNull String name, @NotNull Project project, @NotNull GlobalSearchScope scope) {
return StubIndex.getElements(getKey(), name, project, new JavaSourceFilterScope(scope), PsiJavaModule.class);
}
@Override
public boolean traceKeyHashToVirtualFileMapping() {
return FileBasedIndex.ourEnableTracingOfKeyHashToVirtualFileMapping;
}
}
@@ -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 = 16;
public static final int STUB_VERSION = 17;
@Override
public boolean acceptsFile(@NotNull VirtualFile file) {
@@ -45,7 +45,7 @@ import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.JavaPsiImplementationHelper;
import com.intellij.psi.impl.PsiFileEx;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
@@ -63,7 +63,7 @@ import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiUtil;
import com.intellij.reference.SoftReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.BitUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.cls.ClsFormatException;
import org.jetbrains.annotations.NonNls;
@@ -71,6 +71,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.org.objectweb.asm.Attribute;
import org.jetbrains.org.objectweb.asm.ClassReader;
import org.jetbrains.org.objectweb.asm.Opcodes;
import java.io.IOException;
import java.util.Collections;
@@ -164,7 +165,14 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
@Override
@NotNull
public PsiElement[] getChildren() {
return getClasses(); // TODO : package statement?
PsiJavaModule module = getModuleDeclaration();
if (module != null) {
return new PsiElement[]{module};
}
else {
PsiPackageStatement pkg = getPackageStatement();
return pkg != null ? ArrayUtil.prepend(pkg, getClasses(), PsiElement.class) : getClasses();
}
}
@Override
@@ -175,11 +183,41 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
@Override
public PsiPackageStatement getPackageStatement() {
getStub(); // Make sure myPackageStatement initializes.
ClsPackageStatementImpl statement = myPackageStatement;
if (statement == null) statement = new ClsPackageStatementImpl(this);
return statement.getPackageName() != null ? statement : null;
if (statement == null) {
statement = ClsPackageStatementImpl.NULL_PACKAGE;
PsiClassHolderFileStub<?> stub = getStub();
if (!(stub instanceof PsiJavaFileStub) || stub.findChildStubByType(JavaStubElementTypes.MODULE) == null) {
String packageName = findPackageName(stub);
if (packageName != null) {
statement = new ClsPackageStatementImpl(this, packageName);
}
}
myPackageStatement = statement;
}
return statement != ClsPackageStatementImpl.NULL_PACKAGE ? statement : null;
}
private static String findPackageName(PsiClassHolderFileStub<?> stub) {
String packageName = null;
if (stub instanceof PsiJavaFileStub) {
packageName = ((PsiJavaFileStub)stub).getPackageName();
}
else {
PsiClass[] psiClasses = stub.getClasses();
if (psiClasses.length > 0) {
String className = psiClasses[0].getQualifiedName();
if (className != null) {
int index = className.lastIndexOf('.');
if (index >= 0) {
packageName = className.substring(0, index);
}
}
}
}
return !StringUtil.isEmpty(packageName) ? packageName : null;
}
@Override
@@ -254,7 +292,8 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
@Nullable
@Override
public PsiJavaModule getModuleDeclaration() {
return null;
PsiClassHolderFileStub<?> stub = getStub();
return stub instanceof PsiJavaFileStub ? ((PsiJavaFileStub)stub).getModule() : null;
}
@Override
@@ -276,11 +315,17 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
buffer.append(BANNER);
appendText(getPackageStatement(), 0, buffer, "\n\n");
PsiJavaModule module = getModuleDeclaration();
if (module != null) {
appendText(module, 0, buffer);
}
else {
appendText(getPackageStatement(), 0, buffer, "\n\n");
PsiClass[] classes = getClasses();
if (classes.length > 0) {
appendText(classes[0], 0, buffer);
PsiClass[] classes = getClasses();
if (classes.length > 0) {
appendText(classes[0], 0, buffer);
}
}
}
@@ -292,13 +337,19 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
}
PsiJavaFile mirrorFile = (PsiJavaFile)mirrorElement;
setMirrorIfPresent(getPackageStatement(), mirrorFile.getPackageStatement());
setMirrors(getClasses(), mirrorFile.getClasses());
PsiJavaModule module = getModuleDeclaration();
if (module != null) {
setMirror(module, mirrorFile.getModuleDeclaration());
}
else {
setMirrorIfPresent(getPackageStatement(), mirrorFile.getPackageStatement());
setMirrors(getClasses(), mirrorFile.getClasses());
}
}
@SuppressWarnings("deprecation")
@Override
@NotNull
@SuppressWarnings("deprecation")
public PsiElement getNavigationElement() {
for (ClsCustomNavigationPolicy customNavigationPolicy : Extensions.getExtensions(ClsCustomNavigationPolicy.EP_NAME)) {
if (customNavigationPolicy instanceof ClsCustomNavigationPolicyEx) {
@@ -529,11 +580,10 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
}
}
ClsPackageStatementImpl packageStatement = new ClsPackageStatementImpl(this);
synchronized (myMirrorLock) {
putUserData(CLS_DOCUMENT_LINK_KEY, null);
myMirrorFileElement = null;
myPackageStatement = packageStatement;
myPackageStatement = null;
}
}
@@ -582,20 +632,6 @@ 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<ClassReader, PsiJavaFileStub>() {
@Override
public PsiJavaFileStub fun(ClassReader reader) {
String packageName = getPackageName(reader.getClassName());
LanguageLevel level = ClsParsingUtil.getLanguageLevelByVersion(reader.readShort(6));
return new PsiJavaFileStubImpl(null, packageName, level, true);
}
});
}
@Nullable
public static PsiJavaFileStub buildFileStub(@NotNull VirtualFile file,
@NotNull byte[] bytes,
@NotNull Function<ClassReader, PsiJavaFileStub> stubBuilder) throws ClsFormatException {
try {
if (ClassFileViewProvider.isInnerClass(file, bytes)) {
return null;
@@ -603,20 +639,29 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
ClassReader reader = new ClassReader(bytes);
String className = file.getNameWithoutExtension();
PsiJavaFileStub stub = stubBuilder.fun(reader);
String internalName = reader.getClassName();
boolean module = internalName.endsWith("/module-info") && BitUtil.isSet(reader.getAccess(), Opcodes.ACC_MODULE);
String packageName = getPackageName(internalName);
LanguageLevel level = ClsParsingUtil.getLanguageLevelByVersion(reader.readShort(6));
try {
FileContentPair source = new FileContentPair(file, bytes);
StubBuildingVisitor<FileContentPair> visitor = new StubBuildingVisitor<FileContentPair>(source, STRATEGY, stub, 0, className);
if (module) {
PsiJavaFileStub stub = new PsiJavaFileStubImpl(null, "", level, true);
ModuleStubBuildingVisitor visitor = new ModuleStubBuildingVisitor(stub, packageName);
reader.accept(visitor, EMPTY_ATTRIBUTES, ClassReader.SKIP_FRAMES);
PsiClassStub<?> result = visitor.getResult();
if (result == null) return null;
if (visitor.getResult() != null) return stub;
}
catch (OutOfOrderInnerClassException e) {
return null;
else {
PsiJavaFileStub stub = new PsiJavaFileStubImpl(null, packageName, level, true);
try {
FileContentPair source = new FileContentPair(file, bytes);
StubBuildingVisitor<FileContentPair> visitor = new StubBuildingVisitor<FileContentPair>(source, STRATEGY, stub, 0, className);
reader.accept(visitor, EMPTY_ATTRIBUTES, ClassReader.SKIP_FRAMES);
if (visitor.getResult() != null) return stub;
}
catch (OutOfOrderInnerClassException ignored) { }
}
return stub;
return null;
}
catch (Exception e) {
throw new ClsFormatException(file.getPath() + ": " + e.getMessage(), e);
@@ -0,0 +1,73 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.compiled;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.PsiJavaModuleReference;
import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import org.jetbrains.annotations.NotNull;
public class ClsJavaModuleImpl extends ClsRepositoryPsiElement<PsiJavaModuleStub> implements PsiJavaModule {
private PsiJavaModuleReference myReference;
public ClsJavaModuleImpl(PsiJavaModuleStub stub) {
super(stub);
myReference = new ClsJavaModuleReferenceImpl(this, stub.getName());
}
@NotNull
@Override
public PsiJavaModuleReference getNameElement() {
return myReference;
}
@NotNull
@Override
public String getModuleName() {
return myReference.getReferenceText();
}
@Override
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
buffer.append("module ").append(getModuleName()).append(" { /* compiled code */ }");
}
@Override
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
setMirrorCheckingType(element, JavaElementType.MODULE);
setMirror(getNameElement(), SourceTreeToPsiMap.<PsiJavaModule>treeToPsiNotNull(element).getNameElement());
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitModule(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiJavaModule:" + getModuleName();
}
}
@@ -0,0 +1,76 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.compiled;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiJavaModuleReference;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import org.jetbrains.annotations.NotNull;
public class ClsJavaModuleReferenceImpl extends ClsElementImpl implements PsiJavaModuleReference {
private final PsiElement myParent;
private final String myText;
public ClsJavaModuleReferenceImpl(PsiElement parent, String text) {
myParent = parent;
myText = text;
}
@NotNull
@Override
public PsiElement[] getChildren() {
return EMPTY_ARRAY;
}
@Override
public PsiElement getParent() {
return myParent;
}
@Override
public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
buffer.append(getReferenceText());
}
@Override
public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
setMirrorCheckingType(element, JavaElementType.MODULE_REFERENCE);
}
@NotNull
@Override
public String getReferenceText() {
return myText;
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitModuleReference(this);
}
else {
visitor.visitElement(this);
}
}
@Override
public String toString() {
return "PsiJavaModuleReference";
}
}
@@ -21,22 +21,18 @@ import com.intellij.psi.impl.source.tree.TreeElement;
import org.jetbrains.annotations.NotNull;
class ClsPackageStatementImpl extends ClsElementImpl implements PsiPackageStatement {
static ClsPackageStatementImpl NULL_PACKAGE = new ClsPackageStatementImpl();
private final ClsFileImpl myFile;
private final String myPackageName;
public ClsPackageStatementImpl(@NotNull ClsFileImpl file) {
private ClsPackageStatementImpl() {
myFile = null;
myPackageName = null;
}
public ClsPackageStatementImpl(@NotNull ClsFileImpl file, String packageName) {
myFile = file;
String packageName = null;
PsiClass[] psiClasses = file.getClasses();
if (psiClasses.length > 0) {
String className = psiClasses[0].getQualifiedName();
if (className != null) {
int index = className.lastIndexOf('.');
if (index >= 0) {
packageName = className.substring(0, index);
}
}
}
myPackageName = packageName;
}
@@ -69,7 +65,7 @@ class ClsPackageStatementImpl extends ClsElementImpl implements PsiPackageStatem
@Override
public void appendMirrorText(final int indentLevel, @NotNull final StringBuilder buffer) {
if (myPackageName != null) {
buffer.append("package ").append(getPackageName()).append(";");
buffer.append("package ").append(getPackageName()).append(';');
}
}
@@ -0,0 +1,45 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.compiled;
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub;
import com.intellij.psi.impl.java.stubs.impl.PsiJavaModuleStubImpl;
import org.jetbrains.org.objectweb.asm.ClassVisitor;
import org.jetbrains.org.objectweb.asm.ModuleVisitor;
import org.jetbrains.org.objectweb.asm.Opcodes;
public class ModuleStubBuildingVisitor extends ClassVisitor {
private final PsiJavaFileStub myParent;
private final String myModuleName;
private PsiJavaModuleStub myResult;
public ModuleStubBuildingVisitor(PsiJavaFileStub parent, String moduleName) {
super(Opcodes.ASM6);
myParent = parent;
myModuleName = moduleName;
}
public PsiJavaModuleStub getResult() {
return myResult;
}
@Override
public ModuleVisitor visitModule() {
myResult = new PsiJavaModuleStubImpl(myParent, myModuleName);
return null;
}
}
@@ -21,6 +21,7 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.*;
import com.intellij.psi.impl.compiled.*;
import com.intellij.psi.impl.compiled.ClsJavaModuleImpl;
public class ClsStubPsiFactory extends StubPsiFactory {
public static final ClsStubPsiFactory INSTANCE = new ClsStubPsiFactory();
@@ -99,4 +100,9 @@ public class ClsStubPsiFactory extends StubPsiFactory {
public PsiNameValuePair createNameValuePair(PsiNameValuePairStub stub) {
return null; // todo
}
@Override
public PsiJavaModule createModule(PsiJavaModuleStub stub) {
return new ClsJavaModuleImpl(stub);
}
}
@@ -0,0 +1,81 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the 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.PsiJavaModule;
import com.intellij.psi.impl.java.stubs.impl.PsiJavaModuleStubImpl;
import com.intellij.psi.impl.java.stubs.index.JavaStubIndexKeys;
import com.intellij.psi.impl.source.PsiJavaModuleImpl;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.JavaSourceUtil;
import com.intellij.psi.impl.source.tree.LightTreeUtil;
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.util.io.StringRef;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class JavaModuleElementType extends JavaStubElementType<PsiJavaModuleStub, PsiJavaModule> {
public JavaModuleElementType() {
super("MODULE");
}
@NotNull
@Override
public ASTNode createCompositeNode() {
return new CompositeElement(this);
}
@Override
public PsiJavaModule createPsi(@NotNull PsiJavaModuleStub stub) {
return getPsiFactory(stub).createModule(stub);
}
@Override
public PsiJavaModule createPsi(@NotNull ASTNode node) {
return new PsiJavaModuleImpl(node);
}
@Override
public PsiJavaModuleStub createStub(LighterAST tree, LighterASTNode node, StubElement parentStub) {
LighterASTNode ref = LightTreeUtil.requiredChildOfType(tree, node, JavaElementType.MODULE_REFERENCE);
return new PsiJavaModuleStubImpl(parentStub, JavaSourceUtil.getReferenceText(tree, ref));
}
@Override
public void serialize(@NotNull PsiJavaModuleStub stub, @NotNull StubOutputStream dataStream) throws IOException {
dataStream.writeName(stub.getName());
}
@NotNull
@Override
public PsiJavaModuleStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
String name = StringRef.toString(dataStream.readName());
return new PsiJavaModuleStubImpl(parentStub, name);
}
@Override
public void indexStub(@NotNull PsiJavaModuleStub stub, @NotNull IndexSink sink) {
sink.occurrence(JavaStubIndexKeys.MODULE_NAMES, stub.getName());
}
}
@@ -36,6 +36,7 @@ public interface JavaStubElementTypes {
JavaTypeParameterListElementType TYPE_PARAMETER_LIST = new JavaTypeParameterListElementType();
JavaClassInitializerElementType CLASS_INITIALIZER = new JavaClassInitializerElementType();
JavaImportListElementType IMPORT_LIST = new JavaImportListElementType();
JavaModuleElementType MODULE = new JavaModuleElementType();
JavaClassElementType CLASS = new JavaClassElementType("CLASS") {
@NotNull
@@ -21,9 +21,12 @@ package com.intellij.psi.impl.java.stubs;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.stubs.PsiClassHolderFileStub;
public interface PsiJavaFileStub extends PsiClassHolderFileStub<PsiJavaFile> {
PsiJavaModule getModule();
String getPackageName();
LanguageLevel getLanguageLevel();
boolean isCompiled();
@@ -0,0 +1,23 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.java.stubs;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.stubs.StubElement;
public interface PsiJavaModuleStub extends StubElement<PsiJavaModule> {
String getName();
}
@@ -111,4 +111,9 @@ public class SourceStubPsiFactory extends StubPsiFactory {
public PsiNameValuePair createNameValuePair(PsiNameValuePairStub stub) {
return new PsiNameValuePairImpl(stub);
}
@Override
public PsiJavaModule createModule(PsiJavaModuleStub stub) {
return new PsiJavaModuleImpl(stub);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 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.
@@ -51,4 +51,8 @@ public abstract class StubPsiFactory {
public abstract PsiAnnotationParameterList createAnnotationParameterList(PsiAnnotationParameterListStub stub);
public abstract PsiNameValuePair createNameValuePair(PsiNameValuePairStub stub);
}
public PsiJavaModule createModule(PsiJavaModuleStub stub) {
return null;
}
}
@@ -18,8 +18,10 @@ 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.PsiJavaModule;
import com.intellij.psi.impl.java.stubs.*;
import com.intellij.psi.stubs.PsiFileStubImpl;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.tree.IStubFileElementType;
import org.jetbrains.annotations.NotNull;
@@ -56,6 +58,12 @@ public class PsiJavaFileStubImpl extends PsiFileStubImpl<PsiJavaFile> implements
return getChildrenByType(JavaStubElementTypes.CLASS, PsiClass.ARRAY_FACTORY);
}
@Override
public PsiJavaModule getModule() {
StubElement<PsiJavaModule> moduleStub = findChildStubByType(JavaStubElementTypes.MODULE);
return moduleStub != null ? moduleStub.getPsi() : null;
}
@Override
public String getPackageName() {
return myPackageName;
@@ -0,0 +1,41 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.java.stubs.impl;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
public class PsiJavaModuleStubImpl extends StubBase<PsiJavaModule> implements PsiJavaModuleStub {
private final String myName;
public PsiJavaModuleStubImpl(StubElement parent, String name) {
super(parent, JavaStubElementTypes.MODULE);
myName = name;
}
@Override
public String getName() {
return myName;
}
@Override
public String toString() {
return "PsiJavaModuleStub:" + getName();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 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.
@@ -31,8 +31,8 @@ public class JavaStubIndexKeys {
public static final StubIndexKey<String, PsiAnonymousClass> ANONYMOUS_BASEREF = StubIndexKey.createIndexKey("java.anonymous.baseref");
public static final StubIndexKey<String, PsiMethod> METHOD_TYPES = StubIndexKey.createIndexKey("java.method.parameter.types");
public static final StubIndexKey<String, PsiClass> CLASS_SHORT_NAMES = StubIndexKey.createIndexKey("java.class.shortname");
public static final StubIndexKey<Integer,PsiClass> CLASS_FQN = StubIndexKey.createIndexKey("java.class.fqn");
public static final StubIndexKey<Integer, PsiClass> CLASS_FQN = StubIndexKey.createIndexKey("java.class.fqn");
public static final StubIndexKey<String, PsiJavaModule> MODULE_NAMES = StubIndexKey.createIndexKey("java.module.name");
private JavaStubIndexKeys() {
}
}
private JavaStubIndexKeys() { }
}
@@ -38,7 +38,7 @@ import java.io.IOException;
* @author max
*/
public class JavaFileElementType extends ILightStubFileElementType<PsiJavaFileStub> {
public static final int STUB_VERSION = 25;
public static final int STUB_VERSION = 26;
public JavaFileElementType() {
super("java.FILE", JavaLanguage.INSTANCE);
@@ -15,18 +15,23 @@
*/
package com.intellij.psi.impl.source;
import com.intellij.lang.ASTNode;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiJavaModule;
import com.intellij.psi.PsiJavaModuleReference;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.java.stubs.PsiJavaModuleStub;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
public class PsiJavaModuleImpl extends CompositePsiElement implements PsiJavaModule {
public PsiJavaModuleImpl() {
super(JavaElementType.MODULE);
public class PsiJavaModuleImpl extends JavaStubPsiElement<PsiJavaModuleStub> implements PsiJavaModule {
public PsiJavaModuleImpl(@NotNull PsiJavaModuleStub stub) {
super(stub, JavaStubElementTypes.MODULE);
}
public PsiJavaModuleImpl(@NotNull ASTNode node) {
super(node);
}
@NotNull
@@ -38,6 +43,11 @@ public class PsiJavaModuleImpl extends CompositePsiElement implements PsiJavaMod
@NotNull
@Override
public String getModuleName() {
PsiJavaModuleStub stub = getStub();
if (stub != null) {
return stub.getName();
}
return getNameElement().getReferenceText();
}
@@ -83,6 +83,7 @@ public interface JavaElementType {
IElementType PARAMETER_LIST = JavaStubElementTypes.PARAMETER_LIST;
IElementType EXTENDS_BOUND_LIST = JavaStubElementTypes.EXTENDS_BOUND_LIST;
IElementType THROWS_LIST = JavaStubElementTypes.THROWS_LIST;
IElementType MODULE = JavaStubElementTypes.MODULE;
IElementType IMPORT_STATIC_REFERENCE = new JavaCompositeElementType("IMPORT_STATIC_REFERENCE", PsiImportStaticReferenceElementImpl.class);
IElementType TYPE = new JavaCompositeElementType("TYPE", PsiTypeElementImpl.class);
@@ -139,7 +140,6 @@ public interface JavaElementType {
IElementType ANNOTATION_ARRAY_INITIALIZER = new JavaCompositeElementType("ANNOTATION_ARRAY_INITIALIZER", PsiArrayInitializerMemberValueImpl.class);
IElementType RECEIVER_PARAMETER = new JavaCompositeElementType("RECEIVER", PsiReceiverParameterImpl.class);
IElementType MODULE = new JavaCompositeElementType("MODULE", PsiJavaModuleImpl.class);
IElementType MODULE_REFERENCE = new JavaCompositeElementType("MODULE_NAME", PsiJavaModuleReferenceImpl.class);
IElementType REQUIRES_STATEMENT = new JavaCompositeElementType("REQUIRES_STATEMENT", PsiRequiresStatementImpl.class);
IElementType EXPORTS_STATEMENT = new JavaCompositeElementType("EXPORTS_STATEMENT", PsiExportsStatementImpl.class);
@@ -0,0 +1,5 @@
// IntelliJ API Decompiler stub source generated from a class file
// Implementation of methods is not available
module M.N { /* compiled code */ }
@@ -0,0 +1,2 @@
PsiJavaFileStub []
PsiJavaModuleStub:M.N
@@ -175,6 +175,11 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
assertFalse(isInner("weird/ToStringStyle"));
}
public void testModuleInfo() {
String testDir = getTestDataDir();
doTest(testDir + "../stubBuilder/module-info.class", testDir + "module-info.txt");
}
private static String getTestDataDir() {
return JavaTestUtil.getJavaTestDataPath() + "/psi/cls/mirror/";
}
@@ -412,6 +412,18 @@ public class ClsPsiTest extends LightIdeaTestCase {
assertEquals("@pkg.TypeAnnotations.TA(\"parameter\") int", p1.getType().getCanonicalText(true));
}
public void testModuleInfo() {
PsiJavaFile file = getFile("../../stubBuilder/module-info");
assertEquals(LanguageLevel.JDK_1_9, file.getLanguageLevel());
PsiJavaModule module = file.getModuleDeclaration();
assertNotNull(module);
assertEquals("M.N", module.getModuleName());
assertNull(file.getPackageStatement());
assertEquals(0, file.getClasses().length);
}
private PsiJavaFile getFile() {
return getFile(getTestName(false));
}
@@ -51,6 +51,13 @@ public class ClsStubBuilderTest extends LightIdeaTestCase {
doTest(clsFile, getTestName(false) + ".txt");
}
public void testModuleInfo() {
String clsFilePath = JavaTestUtil.getJavaTestDataPath() + "/psi/cls/stubBuilder/module-info.class";
VirtualFile clsFile = LocalFileSystem.getInstance().findFileByPath(clsFilePath);
assertNotNull(clsFile);
doTest(clsFile, "module-info.txt");
}
private void doTest(String className) {
VirtualFile clsFile = findFile(className);
assertNotNull(clsFile);
@@ -79,7 +86,7 @@ public class ClsStubBuilderTest extends LightIdeaTestCase {
try {
PsiFileStub stub = ClsFileImpl.buildFileStub(clsFile, clsFile.contentsToByteArray());
assertNotNull(stub);
String actual = ((StubBase)stub).printTree();
String actual = ((StubBase)stub).printTree().trim();
File resultFile = new File(JavaTestUtil.getJavaTestDataPath() + "/psi/cls/stubBuilder/" + resultFileName);
if (!resultFile.exists()) {
@@ -88,7 +95,7 @@ public class ClsStubBuilderTest extends LightIdeaTestCase {
fail("No test data found. Created one");
}
String expected = StringUtil.convertLineSeparators(FileUtil.loadFile(resultFile));
String expected = StringUtil.convertLineSeparators(FileUtil.loadFile(resultFile)).trim();
assertEquals(expected, actual);
}
@@ -486,6 +486,15 @@ public class JavaStubBuilderTest extends LightIdeaTestCase {
" IMPLEMENTS_LIST:PsiRefListStub[IMPLEMENTS_LIST:]\n");
}
public void testModuleInfo() {
doTest("module M. /*ignore me*/ N {\n" +
" requires A.B;\n" +
"}",
"PsiJavaFileStub []\n" +
" MODULE:PsiJavaModuleStub:M.N\n");
}
public void testSOEProof() {
StringBuilder sb = new StringBuilder();
SecureRandom random = new SecureRandom();
@@ -133,7 +133,7 @@ class IdeaDecompiler : ClassFileDecompilers.Light() {
else ClsFileImpl.decompile(file)
private fun decompile(file: VirtualFile): CharSequence {
if ("package-info.class" == file.name) {
if ("package-info.class" == file.name || "module-info.class" == file.name) {
return ClsFileImpl.decompile(file)
}
+6 -5
View File
@@ -62,7 +62,7 @@
<interface-class>com.intellij.psi.RefResolveService</interface-class>
<implementation-class>com.intellij.psi.refResolve.RefResolveServiceImpl</implementation-class>
</component>
<component>
<implementation-class>com.intellij.execution.testDiscovery.TestDiscoveryIndex</implementation-class>
</component>
@@ -367,7 +367,7 @@
<definitionsScopedSearch implementation="com.intellij.codeInsight.navigation.MethodImplementationsSearch"/>
<definitionsScopedSearch implementation="com.intellij.codeInsight.navigation.ClassImplementationsSearch"/>
<functionalExpressionSearch implementation="com.intellij.psi.impl.search.JavaFunctionalExpressionSearcher"/>
<fileBasedIndex implementation="com.intellij.psi.impl.search.JavaFunctionalExpressionIndex"/>
@@ -1183,7 +1183,7 @@
<stacktrace.fold substring="at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege("/>
<stacktrace.fold substring="at com.jgoodies.binding.beans.ExtendedPropertyChangeSupport.firePropertyChange0("/>
<stacktrace.fold substring="at javax.swing.plaf.basic.BasicComboPopup$Handler.mouseReleased("/>
<stacktrace.fold substring="at java.util.stream.ReferencePipeline$"/>
<stacktrace.fold substring="at java.util.Spliterators$"/>
<stacktrace.fold substring="at java.util.stream.AbstractPipeline.evaluate("/>
@@ -1206,9 +1206,9 @@
<quoteHandler fileType="JAVA" className="com.intellij.codeInsight.editorActions.JavaQuoteHandler"/>
<typedHandler implementation="com.intellij.codeInsight.editorActions.JavaTypedHandler" id="java"/>
<typedHandler implementation="com.intellij.codeInsight.editorActions.JavadocTypedHandler" id="javadoc"/>
<editorTypedHandler implementationClass="com.intellij.codeInsight.editorActions.AutoFormatTypedHandler"/>
<editorSmartKeysConfigurable instance="com.intellij.application.options.JavadocOptionsProvider"
id="editor.preferences.javadocOptions"
key="javadoc.generate.message.title"
@@ -1540,6 +1540,7 @@
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaShortClassNameIndex"/>
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaSuperClassNameOccurenceIndex"/>
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaMethodParameterTypesIndex"/>
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaModuleNameIndex"/>
<fileBasedIndex implementation="com.intellij.codeInspection.bytecodeAnalysis.BytecodeAnalysisIndex"/>
<fileBasedIndex implementation="com.intellij.psi.RefQueueIndex"/>