Fix and test RecursiveDescriptorProcessor

This commit is contained in:
Andrey Breslav
2013-06-10 20:54:13 +04:00
parent 1e0f926d39
commit 325946154b
4 changed files with 315 additions and 38 deletions
@@ -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;
}
}