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
@@ -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;
}
}