Fix and test RecursiveDescriptorProcessor
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
package test.innerTest
|
||||
|
||||
fun <T1> T1.func(a: T1): T1 = a
|
||||
val <T2> T2.prop: T2? = null
|
||||
var propVar: Any? = null
|
||||
|
||||
trait Trait<T3> {
|
||||
fun traitFunc(): Unit {}
|
||||
val traitProp: Any?
|
||||
}
|
||||
|
||||
abstract class Class<T4> : Trait<Any> {
|
||||
fun classFunc(): Unit {}
|
||||
val classProp: Any? = null
|
||||
|
||||
class object {
|
||||
fun classObjFunc(): Unit {}
|
||||
val classObjProp: Any? = null
|
||||
}
|
||||
}
|
||||
|
||||
object Object {
|
||||
fun objFunc(): Unit {}
|
||||
val objProp: Any? = null
|
||||
}
|
||||
|
||||
trait Outer {
|
||||
trait NestedTrait {
|
||||
fun nestedTraitFun() {}
|
||||
}
|
||||
|
||||
abstract class NestedClass {
|
||||
class object {
|
||||
fun nestedClassObjFunc(): Unit {}
|
||||
}
|
||||
}
|
||||
|
||||
object Object {
|
||||
fun nestedFunc(): Unit {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<class-object-for-Class>.<get-classObjProp>:PropertyGetterDescriptor
|
||||
<class-object-for-Class>.<init>():ConstructorDescriptor
|
||||
<class-object-for-Class>.classObjFunc:SimpleFunctionDescriptor
|
||||
<class-object-for-Class>.classObjProp:PropertyDescriptor
|
||||
<class-object-for-Class>.this:ReceiverParameterDescriptor
|
||||
<class-object-for-Class>:ClassDescriptor
|
||||
<class-object-for-NestedClass>.<init>():ConstructorDescriptor
|
||||
<class-object-for-NestedClass>.nestedClassObjFunc:SimpleFunctionDescriptor
|
||||
<class-object-for-NestedClass>.this:ReceiverParameterDescriptor
|
||||
<class-object-for-NestedClass>:ClassDescriptor
|
||||
<set-?>:MutableValueParameterDescriptor
|
||||
Class.<get-classProp>:PropertyGetterDescriptor
|
||||
Class.<init>():ConstructorDescriptor
|
||||
Class.classFunc:SimpleFunctionDescriptor
|
||||
Class.classProp:PropertyDescriptor
|
||||
Class.this:ReceiverParameterDescriptor
|
||||
Class:ClassDescriptor
|
||||
NestedClass.<init>():ConstructorDescriptor
|
||||
NestedClass.this:ReceiverParameterDescriptor
|
||||
NestedClass:ClassDescriptor
|
||||
NestedTrait.nestedTraitFun:SimpleFunctionDescriptor
|
||||
NestedTrait.this:ReceiverParameterDescriptor
|
||||
NestedTrait:ClassDescriptor
|
||||
Object.<init>():ConstructorDescriptor
|
||||
Object.nestedFunc:SimpleFunctionDescriptor
|
||||
Object.this:ReceiverParameterDescriptor
|
||||
Object:ClassDescriptor
|
||||
Outer.Object:PropertyDescriptor
|
||||
Outer.this:ReceiverParameterDescriptor
|
||||
Outer:ClassDescriptor
|
||||
T1:TypeParameterDescriptor
|
||||
T2:TypeParameterDescriptor
|
||||
T3:TypeParameterDescriptor
|
||||
T4:TypeParameterDescriptor
|
||||
T4:TypeParameterDescriptor
|
||||
Trait.<get-traitProp>:PropertyGetterDescriptor
|
||||
Trait.this:ReceiverParameterDescriptor
|
||||
Trait.traitFunc:SimpleFunctionDescriptor
|
||||
Trait.traitProp:PropertyDescriptor
|
||||
Trait:ClassDescriptor
|
||||
a:MutableValueParameterDescriptor
|
||||
fake Class.<get-traitProp>:PropertyGetterDescriptor
|
||||
fake Class.traitFunc:SimpleFunctionDescriptor
|
||||
fake Class.traitProp:PropertyDescriptor
|
||||
func.this:ReceiverParameterDescriptor
|
||||
innerTest.<get-prop>:PropertyGetterDescriptor
|
||||
innerTest.<get-propVar>:PropertyGetterDescriptor
|
||||
innerTest.<set-propVar>:PropertySetterDescriptor
|
||||
innerTest.Object:PropertyDescriptor
|
||||
innerTest.func:SimpleFunctionDescriptor
|
||||
innerTest.prop:PropertyDescriptor
|
||||
innerTest.propVar:PropertyDescriptor
|
||||
innerTest:NamespaceDescriptor
|
||||
prop.this:ReceiverParameterDescriptor
|
||||
prop.this:ReceiverParameterDescriptor
|
||||
test:NamespaceDescriptor
|
||||
@@ -22,30 +22,15 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class RecursiveDescriptorProcessor {
|
||||
public static <D> boolean process(
|
||||
@NotNull Collection<? extends DeclarationDescriptor> descriptors,
|
||||
D data,
|
||||
@NotNull DeclarationDescriptorVisitor<Boolean, D> visitor
|
||||
) {
|
||||
RecursiveVisitor<D> recursive = new RecursiveVisitor<D>(visitor);
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (!descriptor.accept(visitor, data)) {
|
||||
return false;
|
||||
}
|
||||
descriptor.accept(recursive, data);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static <D> boolean process(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
D data,
|
||||
@NotNull DeclarationDescriptorVisitor<Boolean, D> visitor
|
||||
) {
|
||||
return process(Collections.singletonList(descriptor), data, visitor);
|
||||
return descriptor.accept(new RecursiveVisitor<D>(visitor), data);
|
||||
}
|
||||
|
||||
private static class RecursiveVisitor<D> implements DeclarationDescriptorVisitor<Boolean, D> {
|
||||
@@ -56,26 +41,34 @@ public class RecursiveDescriptorProcessor {
|
||||
this.worker = worker;
|
||||
}
|
||||
|
||||
private boolean doProcess(Collection<? extends DeclarationDescriptor> descriptors, D data) {
|
||||
return process(descriptors, data, worker);
|
||||
private boolean visitChildren(Collection<? extends DeclarationDescriptor> descriptors, D data) {
|
||||
for (DeclarationDescriptor descriptor : descriptors) {
|
||||
if (!descriptor.accept(this, data)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean doProcess(@Nullable DeclarationDescriptor receiverParameter, D data) {
|
||||
if (receiverParameter == null) {
|
||||
return true;
|
||||
}
|
||||
return receiverParameter.accept(worker, data);
|
||||
private boolean visitChildren(@Nullable DeclarationDescriptor descriptor, D data) {
|
||||
if (descriptor == null) return true;
|
||||
|
||||
return descriptor.accept(this, data);
|
||||
}
|
||||
|
||||
private boolean applyWorker(@NotNull DeclarationDescriptor descriptor, D data) {
|
||||
return descriptor.accept(worker, data);
|
||||
}
|
||||
|
||||
private boolean processCallable(CallableDescriptor descriptor, D data) {
|
||||
return doProcess(descriptor.getTypeParameters(), data)
|
||||
&& doProcess(descriptor.getReceiverParameter(), data)
|
||||
&& doProcess(descriptor.getValueParameters(), data);
|
||||
return applyWorker(descriptor, data)
|
||||
&& visitChildren(descriptor.getTypeParameters(), data)
|
||||
&& visitChildren(descriptor.getReceiverParameter(), data)
|
||||
&& visitChildren(descriptor.getValueParameters(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitNamespaceDescriptor(NamespaceDescriptor descriptor, D data) {
|
||||
return doProcess(descriptor.getMemberScope().getAllDescriptors(), data);
|
||||
return applyWorker(descriptor, data)
|
||||
&& visitChildren(descriptor.getMemberScope().getAllDescriptors(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,8 +79,8 @@ public class RecursiveDescriptorProcessor {
|
||||
@Override
|
||||
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, D data) {
|
||||
return processCallable(descriptor, data)
|
||||
&& doProcess(descriptor.getGetter(), data)
|
||||
&& doProcess(descriptor.getSetter(), data);
|
||||
&& visitChildren(descriptor.getGetter(), data)
|
||||
&& visitChildren(descriptor.getSetter(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,22 +90,24 @@ public class RecursiveDescriptorProcessor {
|
||||
|
||||
@Override
|
||||
public Boolean visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, D data) {
|
||||
return true;
|
||||
return applyWorker(descriptor, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitClassDescriptor(ClassDescriptor descriptor, D data) {
|
||||
return doProcess(descriptor.getThisAsReceiverParameter(), data)
|
||||
&& doProcess(descriptor.getConstructors(), data)
|
||||
&& doProcess(descriptor.getTypeConstructor().getParameters(), data)
|
||||
&& doProcess(descriptor.getClassObjectDescriptor(), data)
|
||||
&& doProcess(descriptor.getDefaultType().getMemberScope().getObjectDescriptors(), data)
|
||||
&& doProcess(descriptor.getDefaultType().getMemberScope().getAllDescriptors(), data);
|
||||
return applyWorker(descriptor, data)
|
||||
&& visitChildren(descriptor.getThisAsReceiverParameter(), data)
|
||||
&& visitChildren(descriptor.getConstructors(), data)
|
||||
&& visitChildren(descriptor.getTypeConstructor().getParameters(), data)
|
||||
&& visitChildren(descriptor.getClassObjectDescriptor(), data)
|
||||
&& visitChildren(descriptor.getDefaultType().getMemberScope().getObjectDescriptors(), data)
|
||||
&& visitChildren(descriptor.getDefaultType().getMemberScope().getAllDescriptors(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitModuleDeclaration(ModuleDescriptor descriptor, D data) {
|
||||
return doProcess(descriptor.getNamespace(FqName.ROOT), data);
|
||||
return applyWorker(descriptor, data)
|
||||
&& visitChildren(descriptor.getNamespace(FqName.ROOT), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -142,7 +137,7 @@ public class RecursiveDescriptorProcessor {
|
||||
|
||||
@Override
|
||||
public Boolean visitReceiverParameterDescriptor(ReceiverParameterDescriptor descriptor, D data) {
|
||||
return true;
|
||||
return applyWorker(descriptor, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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 org.jetbrains.jet.test.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.utils.Printer;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class RecursiveDescriptorProcessorTest extends KotlinTestWithEnvironment {
|
||||
@Override
|
||||
protected JetCoreEnvironment createEnvironment() {
|
||||
return JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations(getTestRootDisposable());
|
||||
}
|
||||
|
||||
public void testRecursive() throws Exception {
|
||||
File ktFile = new File("compiler/testData/recursiveProcessor/declarations.kt");
|
||||
File txtFile = new File("compiler/testData/recursiveProcessor/declarations.txt");
|
||||
String text = FileUtil.loadFile(ktFile);
|
||||
JetFile jetFile = JetTestUtils.createFile("declarations.kt", text, getEnvironment().getProject());
|
||||
AnalyzeExhaust exhaust = JetTestUtils.analyzeFile(jetFile);
|
||||
NamespaceDescriptor testPackage = exhaust.getModuleDescriptor().getNamespace(FqName.topLevel(Name.identifier("test")));
|
||||
assert testPackage != null;
|
||||
|
||||
List<String> descriptors = recursivelyCollectDescriptors(testPackage);
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Printer p = new Printer(builder);
|
||||
for (String descriptor : descriptors) {
|
||||
p.println(descriptor);
|
||||
}
|
||||
String actualText = builder.toString();
|
||||
|
||||
if (!txtFile.exists()) {
|
||||
FileUtil.writeToFile(txtFile, actualText);
|
||||
fail("Test data file did not exist and was created from the results of the test: " + txtFile);
|
||||
}
|
||||
|
||||
assertEquals(FileUtil.loadFile(txtFile), actualText);
|
||||
}
|
||||
|
||||
private static Class closestInterface(Class<?> aClass) {
|
||||
if (aClass == null) return null;
|
||||
if (aClass.isInterface()) return aClass;
|
||||
|
||||
Class<?>[] interfaces = aClass.getInterfaces();
|
||||
if (interfaces.length > 0) return interfaces[0];
|
||||
|
||||
return closestInterface(aClass.getSuperclass());
|
||||
}
|
||||
|
||||
private static List<String> recursivelyCollectDescriptors(NamespaceDescriptor testPackage) {
|
||||
final List<String> lines = Lists.newArrayList();
|
||||
RecursiveDescriptorProcessor.process(testPackage, null, new DeclarationDescriptorVisitor<Boolean, Void>() {
|
||||
|
||||
private void add(DeclarationDescriptor descriptor) {
|
||||
add(descriptor.getName().asString(), descriptor);
|
||||
}
|
||||
|
||||
private void add(String name, DeclarationDescriptor descriptor) {
|
||||
lines.add(name + ":" + closestInterface(descriptor.getClass()).getSimpleName());
|
||||
}
|
||||
|
||||
private void addCallable(CallableMemberDescriptor descriptor) {
|
||||
String prefix = descriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE ? "fake " : "";
|
||||
add(prefix + descriptor.getContainingDeclaration().getName() + "." + descriptor.getName(), descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitNamespaceDescriptor(NamespaceDescriptor descriptor, Void data) {
|
||||
add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitVariableDescriptor(VariableDescriptor descriptor, Void data) {
|
||||
add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
|
||||
addCallable(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, Void data) {
|
||||
add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitClassDescriptor(ClassDescriptor descriptor, Void data) {
|
||||
add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitModuleDeclaration(ModuleDescriptor descriptor, Void data) {
|
||||
add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitConstructorDescriptor(
|
||||
ConstructorDescriptor constructorDescriptor, Void data
|
||||
) {
|
||||
add(constructorDescriptor.getContainingDeclaration().getName() + ".<init>()", constructorDescriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitScriptDescriptor(ScriptDescriptor scriptDescriptor, Void data) {
|
||||
add(scriptDescriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
|
||||
addCallable(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitValueParameterDescriptor(
|
||||
ValueParameterDescriptor descriptor, Void data
|
||||
) {
|
||||
add(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitPropertyGetterDescriptor(
|
||||
PropertyGetterDescriptor descriptor, Void data
|
||||
) {
|
||||
addCallable(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitPropertySetterDescriptor(
|
||||
PropertySetterDescriptor descriptor, Void data
|
||||
) {
|
||||
addCallable(descriptor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean visitReceiverParameterDescriptor(
|
||||
ReceiverParameterDescriptor descriptor, Void data
|
||||
) {
|
||||
add(descriptor.getContainingDeclaration().getName() + ".this", descriptor);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
Collections.sort(lines);
|
||||
return lines;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user