mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
Extensible checking of is inner class file
This commit is contained in:
committed by
nik
parent
80b30ebcbe
commit
b23de45f73
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.impl.source.JavaFileElementType;
|
||||
@@ -28,26 +29,23 @@ import com.intellij.util.cls.ClsFormatException;
|
||||
public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
@Override
|
||||
public boolean acceptsFile(final VirtualFile file) {
|
||||
return !isInner(file.getNameWithoutExtension(), new ParentDirectory(file));
|
||||
}
|
||||
|
||||
static boolean isInner(final String name, final Directory directory) {
|
||||
return isInner(name, 0, directory);
|
||||
}
|
||||
|
||||
private static boolean isInner(final String name, final int from, final Directory directory) {
|
||||
final int index = name.indexOf('$', from);
|
||||
return index != -1 && (containsPart(directory, name, index) || isInner(name, index + 1, directory));
|
||||
}
|
||||
|
||||
private static boolean containsPart(Directory directory, String name, int endIndex) {
|
||||
return endIndex > 0 && directory.contains(name.substring(0, endIndex));
|
||||
final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME);
|
||||
for (ClsStubBuilderFactory factory : factories) {
|
||||
if (!factory.isInnerClass(file)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StubElement buildStubTree(final VirtualFile file, final byte[] content, final Project project) {
|
||||
try {
|
||||
return ClsStubBuilder.build(file, content);
|
||||
final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME);
|
||||
for (ClsStubBuilderFactory factory : factories) {
|
||||
if (!factory.isInnerClass(file) && factory.canBeProcessed(file, content)) {
|
||||
return factory.buildFileStub(file, content);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch (ClsFormatException e) {
|
||||
return null;
|
||||
@@ -58,25 +56,4 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
public int getStubVersion() {
|
||||
return JavaFileElementType.STUB_VERSION + 3;
|
||||
}
|
||||
|
||||
|
||||
interface Directory {
|
||||
boolean contains(String name);
|
||||
}
|
||||
|
||||
private static class ParentDirectory implements Directory {
|
||||
private final VirtualFile myDirectory;
|
||||
private final String myExtension;
|
||||
|
||||
private ParentDirectory(final VirtualFile file) {
|
||||
myDirectory = file.getParent();
|
||||
myExtension = file.getExtension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(final String name) {
|
||||
final String fullName = myExtension == null ? name : name + "." + myExtension;
|
||||
return myDirectory != null && myDirectory.findChild(fullName) != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,15 +19,26 @@ import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.util.cls.ClsFormatException;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
*/
|
||||
public interface ClsStubBuilderFactory<T extends PsiFile> {
|
||||
public abstract class ClsStubBuilderFactory<T extends PsiFile> {
|
||||
|
||||
ExtensionPointName<ClsStubBuilderFactory> EP_NAME = ExtensionPointName.create("com.intellij.clsStubBuilderFactory");
|
||||
public static final ExtensionPointName<ClsStubBuilderFactory> EP_NAME = ExtensionPointName.create("com.intellij.clsStubBuilderFactory");
|
||||
|
||||
PsiFileStub<T> buildFileStub(final VirtualFile file, byte[] bytes);
|
||||
@Nullable
|
||||
public abstract PsiFileStub<T> buildFileStub(final VirtualFile file, byte[] bytes) throws ClsFormatException;
|
||||
|
||||
boolean canBeProcessed(final VirtualFile file, byte[] bytes);
|
||||
public abstract boolean canBeProcessed(final VirtualFile file, byte[] bytes);
|
||||
|
||||
/**
|
||||
* Should be fast, because of processing file only according to the name.
|
||||
* It can be inconsistent with 'canBeProcessed' method.
|
||||
* @param file classFile
|
||||
* @return false in case if it's not inner class
|
||||
*/
|
||||
public abstract boolean isInnerClass(final VirtualFile file);
|
||||
}
|
||||
|
||||
+65
-33
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
@@ -32,8 +31,71 @@ import java.io.IOException;
|
||||
* @author max
|
||||
*/
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
public class ClsStubBuilder {
|
||||
private ClsStubBuilder() { }
|
||||
public class DefaultClsStubBuilderFactory extends ClsStubBuilderFactory {
|
||||
@Override
|
||||
public PsiFileStub buildFileStub(VirtualFile vFile, byte[] bytes) throws ClsFormatException {
|
||||
final PsiJavaFileStubImpl file = new PsiJavaFileStubImpl("do.not.know.yet", true);
|
||||
try {
|
||||
ClassReader reader = new ClassReader(bytes);
|
||||
|
||||
final StubBuildingVisitor<VirtualFile>
|
||||
classVisitor = new StubBuildingVisitor<VirtualFile>(vFile, VirtualFileInnerClassStrategy.INSTANCE, file, 0);
|
||||
reader.accept(classVisitor, 0);
|
||||
|
||||
final PsiClassStub result = classVisitor.getResult();
|
||||
if (result == null) return null;
|
||||
|
||||
//noinspection unchecked
|
||||
file.setPackageName(getPackageName(result));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new ClsFormatException();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeProcessed(VirtualFile file, byte[] bytes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInnerClass(VirtualFile file) {
|
||||
return isInner(file.getNameWithoutExtension(), new ParentDirectory(file));
|
||||
}
|
||||
|
||||
static boolean isInner(final String name, final Directory directory) {
|
||||
return isInner(name, 0, directory);
|
||||
}
|
||||
|
||||
private static boolean isInner(final String name, final int from, final Directory directory) {
|
||||
final int index = name.indexOf('$', from);
|
||||
return index != -1 && (containsPart(directory, name, index) || isInner(name, index + 1, directory));
|
||||
}
|
||||
|
||||
private static boolean containsPart(Directory directory, String name, int endIndex) {
|
||||
return endIndex > 0 && directory.contains(name.substring(0, endIndex));
|
||||
}
|
||||
|
||||
interface Directory {
|
||||
boolean contains(String name);
|
||||
}
|
||||
|
||||
private static class ParentDirectory implements Directory {
|
||||
private final VirtualFile myDirectory;
|
||||
private final String myExtension;
|
||||
|
||||
private ParentDirectory(final VirtualFile file) {
|
||||
myDirectory = file.getParent();
|
||||
myExtension = file.getExtension();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(final String name) {
|
||||
final String fullName = myExtension == null ? name : name + "." + myExtension;
|
||||
return myDirectory != null && myDirectory.findChild(fullName) != null;
|
||||
}
|
||||
}
|
||||
|
||||
private static class VirtualFileInnerClassStrategy implements InnerClassSourceStrategy<VirtualFile> {
|
||||
public static VirtualFileInnerClassStrategy INSTANCE = new VirtualFileInnerClassStrategy();
|
||||
@@ -60,35 +122,6 @@ public class ClsStubBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiFileStub build(final VirtualFile vFile, byte[] bytes) throws ClsFormatException {
|
||||
final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME);
|
||||
for (ClsStubBuilderFactory factory : factories) {
|
||||
if (factory.canBeProcessed(vFile, bytes)) {
|
||||
return factory.buildFileStub(vFile, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
final PsiJavaFileStubImpl file = new PsiJavaFileStubImpl("do.not.know.yet", true);
|
||||
try {
|
||||
ClassReader reader = new ClassReader(bytes);
|
||||
|
||||
final StubBuildingVisitor<VirtualFile>
|
||||
classVisitor = new StubBuildingVisitor<VirtualFile>(vFile, VirtualFileInnerClassStrategy.INSTANCE, file, 0);
|
||||
reader.accept(classVisitor, 0);
|
||||
|
||||
final PsiClassStub result = classVisitor.getResult();
|
||||
if (result == null) return null;
|
||||
|
||||
//noinspection unchecked
|
||||
file.setPackageName(getPackageName(result));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new ClsFormatException();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private static String getPackageName(final PsiClassStub<PsiClass> result) {
|
||||
final String fqn = result.getQualifiedName();
|
||||
final String shortName = result.getName();
|
||||
@@ -98,5 +131,4 @@ public class ClsStubBuilder {
|
||||
|
||||
return fqn.substring(0, fqn.lastIndexOf('.'));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user