mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
KT-2145 Impossible to depend on Scala library
This commit is contained in:
@@ -16,10 +16,11 @@
|
||||
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.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.impl.source.JavaFileElementType;
|
||||
import com.intellij.psi.stubs.BinaryFileStubBuilder;
|
||||
import com.intellij.psi.stubs.PsiFileStub;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import com.intellij.util.cls.ClsFormatException;
|
||||
|
||||
@@ -29,11 +30,7 @@ import com.intellij.util.cls.ClsFormatException;
|
||||
public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
@Override
|
||||
public boolean acceptsFile(final VirtualFile file) {
|
||||
final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME);
|
||||
for (ClsStubBuilderFactory factory : factories) {
|
||||
if (!factory.isInnerClass(file)) return true;
|
||||
}
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -42,7 +39,8 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
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);
|
||||
PsiFileStub stub = factory.buildFileStub(file, content);
|
||||
if (stub != null) return stub;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -56,4 +54,4 @@ public class ClassFileStubBuilder implements BinaryFileStubBuilder {
|
||||
public int getStubVersion() {
|
||||
return JavaFileElementType.STUB_VERSION + 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-32
@@ -40,9 +40,15 @@ public class DefaultClsStubBuilderFactory extends ClsStubBuilderFactory {
|
||||
final PsiJavaFileStubImpl file = new PsiJavaFileStubImpl("do.not.know.yet", true);
|
||||
try {
|
||||
final ClassReader reader = new ClassReader(bytes);
|
||||
|
||||
final StubBuildingVisitor<VirtualFile> classVisitor =
|
||||
new StubBuildingVisitor<VirtualFile>(vFile, VirtualFileInnerClassStrategy.INSTANCE, file, 0);
|
||||
reader.accept(classVisitor, ClassReader.SKIP_FRAMES);
|
||||
try {
|
||||
reader.accept(classVisitor, ClassReader.SKIP_FRAMES);
|
||||
}
|
||||
catch (OutOfOrderInnerClassException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") final PsiClassStub<PsiClass> result = (PsiClassStub<PsiClass>)classVisitor.getResult();
|
||||
if (result == null) return null;
|
||||
@@ -63,40 +69,16 @@ public class DefaultClsStubBuilderFactory extends ClsStubBuilderFactory {
|
||||
|
||||
@Override
|
||||
public boolean isInnerClass(VirtualFile file) {
|
||||
return isInner(file.getNameWithoutExtension(), new ParentDirectory(file));
|
||||
}
|
||||
String name = file.getNameWithoutExtension();
|
||||
int len = name.length();
|
||||
int idx = name.indexOf('$');
|
||||
|
||||
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();
|
||||
while (idx > 0) {
|
||||
if (idx + 1 < len && Character.isDigit(name.charAt(idx + 1))) return true;
|
||||
idx = name.indexOf('$', idx + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(final String name) {
|
||||
final String fullName = myExtension == null ? name : name + "." + myExtension;
|
||||
return myDirectory != null && myDirectory.findChild(fullName) != null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class VirtualFileInnerClassStrategy implements InnerClassSourceStrategy<VirtualFile> {
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.compiled;
|
||||
|
||||
public class OutOfOrderInnerClassException extends RuntimeException {
|
||||
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -275,6 +275,9 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
|
||||
@Override
|
||||
public void visitOuterClass(final String owner, final String name, final String desc) {
|
||||
if (myParent instanceof PsiFileStub) {
|
||||
throw new OutOfOrderInnerClassException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -296,7 +299,16 @@ public class StubBuildingVisitor<T> extends ClassVisitor {
|
||||
if ((access & Opcodes.ACC_SYNTHETIC) != 0) return;
|
||||
if (!isCorrectName(innerName)) return;
|
||||
|
||||
if (innerName == null || outerName == null || !getClassName(outerName).equals(myResult.getQualifiedName())) return;
|
||||
if (innerName == null || outerName == null) return;
|
||||
if ((getClassName(outerName) + "." + innerName).equals(myResult.getQualifiedName())) {
|
||||
// Our result is inner class
|
||||
|
||||
if (myParent instanceof PsiFileStub) {
|
||||
throw new OutOfOrderInnerClassException();
|
||||
}
|
||||
}
|
||||
|
||||
if (!getClassName(outerName).equals(myResult.getQualifiedName())) return;
|
||||
|
||||
final T innerSource = myInnersStrategy.findInnerClass(innerName, mySource);
|
||||
if (innerSource == null) return;
|
||||
|
||||
@@ -1,146 +0,0 @@
|
||||
package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Pavel.Fatin, 18.02.2010
|
||||
*/
|
||||
public class ClassFileStubBuilderTest extends TestCase {
|
||||
public void testOneFile() {
|
||||
assertTopLevel("");
|
||||
assertTopLevel("$");
|
||||
assertTopLevel("$$");
|
||||
assertTopLevel("$$$");
|
||||
assertTopLevel("Foo");
|
||||
assertTopLevel("Foo$");
|
||||
assertTopLevel("$Foo");
|
||||
assertTopLevel("$Foo$");
|
||||
assertTopLevel("Foo$Bar");
|
||||
assertTopLevel("$Foo$Bar");
|
||||
assertTopLevel("Foo$Bar$");
|
||||
assertTopLevel("$Foo$Bar$");
|
||||
assertTopLevel("$$Foo$$Bar$$");
|
||||
}
|
||||
|
||||
public void testWrongCase() {
|
||||
assertTopLevel("Foo$Bar", "foo");
|
||||
assertTopLevel("foo$Bar", "Foo");
|
||||
}
|
||||
|
||||
public void testShortName() {
|
||||
assertTopLevel("A");
|
||||
|
||||
assertInner("Foo$B", "Foo");
|
||||
assertInner("A$Foo", "A");
|
||||
assertInner("A$B", "A");
|
||||
|
||||
assertTopLevel("A$B", "A$");
|
||||
assertTopLevel("A$B", "$B");
|
||||
assertTopLevel("A$B", "B");
|
||||
assertTopLevel("A$B", "$");
|
||||
}
|
||||
|
||||
public void testShortNames() {
|
||||
assertInner("A$B$C", "A");
|
||||
assertInner("A$B$C", "A$B");
|
||||
assertInner("A$B$C", "A", "A$B");
|
||||
|
||||
assertTopLevel("A$B$C", "A$");
|
||||
assertTopLevel("A$B$C", "A$B$");
|
||||
}
|
||||
|
||||
public void testEmptyFileName() {
|
||||
assertTopLevel("$Foo", "");
|
||||
}
|
||||
|
||||
public void testNoInnerName() {
|
||||
//assertTopLevel("Foo$", "Foo");
|
||||
//assertTopLevel("Foo$$", "Foo$");
|
||||
// an exception to the rule (to hide Scala "objects")
|
||||
assertInner("Foo$", "Foo");
|
||||
assertInner("Foo$$", "Foo$");
|
||||
}
|
||||
|
||||
public void testDollarsInName() {
|
||||
assertInner("$Foo$Bar", "$Foo");
|
||||
assertInner("Foo$$Bar", "Foo");
|
||||
assertInner("Foo$$Bar", "Foo");
|
||||
assertInner("$Foo$$Bar", "$Foo");
|
||||
assertInner("$Foo$$Bar", "$Foo$");
|
||||
}
|
||||
|
||||
public void testInner() {
|
||||
assertInner("Foo$Bar", "Foo");
|
||||
assertInner("Foo$bar", "Foo");
|
||||
assertInner("foo$Bar", "foo");
|
||||
assertInner("foo$bar", "foo");
|
||||
}
|
||||
|
||||
public void testInnerAndNoise() {
|
||||
assertInner("Foo$Bar", "Foo", "Foo$", "$Bar", "Bar");
|
||||
}
|
||||
|
||||
public void testTopLevel() {
|
||||
assertTopLevel("Foo$Bar");
|
||||
assertTopLevel("Foo$Bar", "Foo$");
|
||||
assertTopLevel("Foo$Bar", "$Bar");
|
||||
assertTopLevel("Foo$Bar", "Bar");
|
||||
assertTopLevel("Foo$Bar", "Foo$", "$Bar", "Bar");
|
||||
}
|
||||
|
||||
public void testInners() {
|
||||
assertInner("Foo$Bar$Moo", "Foo");
|
||||
assertInner("Foo$Bar$Moo", "Foo$Bar");
|
||||
assertInner("Foo$Bar$Moo", "Foo", "Foo$Bar");
|
||||
}
|
||||
|
||||
public void testInnersAndNoise() {
|
||||
assertInner("Foo$Bar$Moo", "Foo", "$Bar", "Bar", "$Moo", "Moo", "Bar$Moo", "$Bar$Moo");
|
||||
assertInner("Foo$Bar$Moo", "Foo$Bar", "$Bar", "Bar", "$Moo", "Moo", "Bar$Moo", "$Bar$Moo");
|
||||
assertInner("Foo$Bar$Moo", "Foo", "Foo$Bar", "$Bar", "Bar", "$Moo", "Moo", "Bar$Moo", "$Bar$Moo");
|
||||
}
|
||||
|
||||
public void testTopLevels() {
|
||||
assertTopLevel("Foo$Bar$Moo");
|
||||
assertTopLevel("Foo$Bar$Moo", "$Bar");
|
||||
assertTopLevel("Foo$Bar$Moo", "Bar");
|
||||
assertTopLevel("Foo$Bar$Moo", "$Moo");
|
||||
assertTopLevel("Foo$Bar$Moo", "Moo");
|
||||
assertTopLevel("Foo$Bar$Moo", "Bar$Moo");
|
||||
assertTopLevel("Foo$Bar$Moo", "$Bar$Moo");
|
||||
assertTopLevel("Foo$Bar$Moo", "$Bar", "Bar", "$Moo", "Moo", "Bar$Moo", "$Bar$Moo");
|
||||
}
|
||||
|
||||
private static void assertInner(String name, String... files) {
|
||||
assertTrue("Class " + name + " must be identified as inner", isInner(name, files));
|
||||
}
|
||||
|
||||
private static void assertTopLevel(String name, String... files) {
|
||||
assertFalse("Class " + name + " must be identified as top-level", isInner(name, files));
|
||||
}
|
||||
|
||||
private static boolean isInner(String name, String... files) {
|
||||
Set<String> all = new HashSet<String>();
|
||||
ContainerUtil.addAll(all, files);
|
||||
all.add(name);
|
||||
return DefaultClsStubBuilderFactory.isInner(name, new DirectoryMock(all));
|
||||
}
|
||||
|
||||
|
||||
private static class DirectoryMock implements DefaultClsStubBuilderFactory.Directory {
|
||||
private Set<String> myFiles;
|
||||
|
||||
private DirectoryMock(Set<String> files) {
|
||||
myFiles = files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(String name) {
|
||||
return myFiles.contains(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user