Validate descriptors loaded in tests

This commit is contained in:
Andrey Breslav
2013-06-07 14:14:42 +04:00
parent d50300dedc
commit a6edc21c49
11 changed files with 682 additions and 4 deletions
@@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.test.TestCaseWithTmpdir;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.jetbrains.jet.test.util.NamespaceComparator;
import org.junit.Assert;
@@ -70,6 +71,7 @@ public abstract class AbstractCompileKotlinAgainstCustomJavaTest extends TestCas
NamespaceDescriptor namespaceDescriptor = bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, namespaceFqn);
assertNotNull("Failed to find namespace: " + namespaceFqn, namespaceDescriptor);
DescriptorValidator.validate(namespaceDescriptor);
compareNamespaceWithFile(namespaceDescriptor, NamespaceComparator.DONT_INCLUDE_METHODS_OF_OBJECT, expectedFile);
}
@@ -23,6 +23,7 @@ import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.test.TestCaseWithTmpdir;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.jetbrains.jet.test.util.NamespaceComparator;
import java.io.File;
@@ -55,8 +56,12 @@ public abstract class AbstractLoadCompiledKotlinTest extends TestCaseWithTmpdir
TEST_PACKAGE_FQNAME);
assert namespaceFromSource != null;
Assert.assertEquals("test", namespaceFromSource.getName().asString());
DescriptorValidator.validate(namespaceFromSource);
NamespaceDescriptor namespaceFromClass = LoadDescriptorUtil.loadTestNamespaceAndBindingContextFromJavaRoot(
tmpdir, getTestRootDisposable(), ConfigurationKind.JDK_ONLY).first;
compareNamespaces(namespaceFromSource, namespaceFromClass,
NamespaceComparator.DONT_INCLUDE_METHODS_OF_OBJECT
.checkPrimaryConstructors(true)
@@ -42,6 +42,7 @@ import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM;
import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.test.TestCaseWithTmpdir;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.junit.Assert;
import java.io.File;
@@ -164,6 +165,7 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir {
LoadDescriptorUtil.TEST_PACKAGE_FQNAME, DescriptorSearchRule.INCLUDE_KOTLIN);
assert namespaceDescriptor != null : "Test namespace not found";
DescriptorValidator.validate(namespaceDescriptor);
checkJavaNamespace(expectedFile, namespaceDescriptor, trace.getBindingContext(), DONT_INCLUDE_METHODS_OF_OBJECT);
}
@@ -28,9 +28,9 @@ import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.cli.jvm.compiler.CompileEnvironmentUtil;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.codegen.GenerationUtils;
import org.jetbrains.jet.codegen.forTestCompile.ForTestCompileRuntime;
import org.jetbrains.jet.codegen.state.GenerationState;
import org.jetbrains.jet.config.CompilerConfiguration;
import org.jetbrains.jet.di.InjectorForJavaSemanticServices;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
@@ -42,13 +42,15 @@ import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.test.util.DescriptorValidator;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import static org.jetbrains.jet.JetTestUtils.createEnvironmentWithMockJdkAndIdeaAnnotations;
import static org.jetbrains.jet.lang.psi.JetPsiFactory.createFile;
public final class LoadDescriptorUtil {
@@ -105,6 +107,8 @@ public final class LoadDescriptorUtil {
NamespaceDescriptor namespaceDescriptor =
javaDescriptorResolver.resolveNamespace(TEST_PACKAGE_FQNAME, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
assert namespaceDescriptor != null;
DescriptorValidator.validate(namespaceDescriptor);
return Pair.create(namespaceDescriptor, injector.getBindingTrace().getBindingContext());
}
@@ -137,6 +141,7 @@ public final class LoadDescriptorUtil {
NamespaceDescriptor namespace =
fileAndExhaust.getExhaust().getBindingContext().get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, TEST_PACKAGE_FQNAME);
assert namespace != null: TEST_PACKAGE_FQNAME + " package not found in " + ktFile.getName();
DescriptorValidator.validate(namespace);
return namespace;
}
@@ -22,6 +22,7 @@ import org.jetbrains.jet.analyzer.AnalyzeExhaust;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.test.TestCaseWithTmpdir;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.jetbrains.jet.test.util.NamespaceComparator;
import java.io.File;
@@ -44,7 +45,6 @@ public final class LoadKotlinCustomTest extends TestCaseWithTmpdir {
throws Exception {
NamespaceDescriptor namespaceFromClass =
compileKotlinAndLoadTestNamespaceDescriptorFromBinary(kotlinFile, tmpdir, myTestRootDisposable, ConfigurationKind.JDK_ONLY);
compareNamespaceWithFile(namespaceFromClass, DONT_INCLUDE_METHODS_OF_OBJECT, expectedFile);
}
@@ -54,6 +54,7 @@ public final class LoadKotlinCustomTest extends TestCaseWithTmpdir {
NamespaceDescriptor namespaceFromSource = exhaust.getBindingContext().get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR,
TEST_PACKAGE_FQNAME);
assert namespaceFromSource != null;
DescriptorValidator.validate(namespaceFromSource);
compareNamespaceWithFile(namespaceFromSource, NamespaceComparator.DONT_INCLUDE_METHODS_OF_OBJECT.checkPrimaryConstructors(true),
expectedFile);
}
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.test.util.DescriptorValidator;
import java.io.File;
import java.util.List;
@@ -46,6 +47,7 @@ public abstract class AbstractLazyResolveDiagnosticsTest extends AbstractJetDiag
String path = JetTestUtils.getFilePath(new File(FileUtil.getRelativePath(TEST_DATA_DIR, testDataFile)));
NamespaceDescriptor expected = eagerModule.getNamespace(FqName.ROOT);
NamespaceDescriptor actual = lazyModule.getNamespace(FqName.ROOT);
DescriptorValidator.validate(expected, actual);
String txtFileRelativePath = path.replaceAll("\\.kt$|\\.ktscript", ".txt");
File txtFile = new File("compiler/testData/lazyResolve/diagnostics/" + txtFileRelativePath);
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.jetbrains.jet.test.util.NamespaceComparator;
import org.junit.Assert;
@@ -77,6 +78,8 @@ public abstract class AbstractLazyResolveNamespaceComparingTest extends KotlinTe
File serializeResultsTo = new File(FileUtil.getNameWithoutExtension(testFileName) + ".txt");
DescriptorValidator.validate(expected, actual);
NamespaceComparator.compareNamespaces(
expected, actual, NamespaceComparator.DONT_INCLUDE_METHODS_OF_OBJECT.filterRecursion(
new Predicate<FqNameUnsafe>() {
@@ -20,6 +20,7 @@ import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.junit.Test;
import java.io.File;
@@ -36,6 +37,7 @@ public class LazyResolveBuiltinClassesTest extends KotlinTestWithEnvironment {
@Test
public void testBuiltIns() throws Exception {
NamespaceDescriptor builtInsPackage = KotlinBuiltIns.getInstance().getBuiltInsPackage();
DescriptorValidator.validate(builtInsPackage);
compareNamespaceWithFile(builtInsPackage, RECURSIVE, new File("compiler/testData/builtin-classes.txt"));
}
}
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.test.util.DescriptorValidator;
import org.jetbrains.jet.test.util.NamespaceComparator;
import java.io.File;
@@ -59,6 +60,7 @@ public class LazyResolveStdlibLoadingTest extends KotlinTestWithEnvironmentManag
for (Name name : namespaceShortNames) {
NamespaceDescriptor eager = module.getNamespace(FqName.topLevel(name));
NamespaceDescriptor lazy = lazyModule.getNamespace(FqName.topLevel(name));
DescriptorValidator.validate(eager, lazy);
NamespaceComparator.compareNamespaces(eager, lazy, NamespaceComparator.RECURSIVE, null);
}
}
@@ -0,0 +1,506 @@
/*
* 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 junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class DescriptorValidator {
private DescriptorValidator() {}
public static void validate(DeclarationDescriptor... descriptors) {
validate(Arrays.asList(descriptors));
}
public static void validate(@NotNull Collection<DeclarationDescriptor> descriptors) {
DiagnosticCollectorForTests collector = new DiagnosticCollectorForTests();
for (DeclarationDescriptor descriptor : descriptors) {
validate(descriptor, collector);
}
collector.done();
}
public static void validate(@NotNull Collection<? extends DeclarationDescriptor> descriptors, @NotNull DiagnosticCollector collector) {
for (DeclarationDescriptor descriptor : descriptors) {
validate(descriptor, collector);
}
}
public static void validate(@NotNull DeclarationDescriptor descriptor, @NotNull DiagnosticCollector collector) {
RecursiveDescriptorProcessor.process(descriptor, collector, ValidationVisitor.INSTANCE);
}
public interface DiagnosticCollector {
void report(@NotNull Diagnostic diagnostic);
}
private static void report(@NotNull DiagnosticCollector collector, @NotNull DeclarationDescriptor descriptor, @NotNull String message) {
collector.report(new Diagnostic(descriptor, message));
}
private static class ValidationVisitor implements DeclarationDescriptorVisitor<Boolean, DiagnosticCollector> {
public static final ValidationVisitor INSTANCE = new ValidationVisitor();
private ValidationVisitor() {}
private static void validateScope(@NotNull JetScope scope, @NotNull DiagnosticCollector collector) {
for (DeclarationDescriptor descriptor : scope.getAllDescriptors()) {
descriptor.accept(new ScopeValidatorVisitor(collector), scope);
}
}
private static void validateType(
@NotNull DeclarationDescriptor descriptor,
@Nullable JetType type,
@NotNull DiagnosticCollector collector
) {
if (type == null) {
report(collector, descriptor, "No type");
return;
}
if (ErrorUtils.isErrorType(type)) {
report(collector, descriptor, "Error type: " + type);
return;
}
validateScope(type.getMemberScope(), collector);
}
private static void validateReturnType(CallableDescriptor descriptor, DiagnosticCollector collector) {
validateType(descriptor, descriptor.getReturnType(), collector);
}
private static void validateTypeParameters(DiagnosticCollector collector, List<TypeParameterDescriptor> parameters) {
for (int i = 0; i < parameters.size(); i++) {
TypeParameterDescriptor typeParameterDescriptor = parameters.get(i);
if (typeParameterDescriptor.getIndex() != i) {
report(collector, typeParameterDescriptor, "Incorrect index: " + typeParameterDescriptor.getIndex() + " but must be " + i);
}
}
}
private static void validateValueParameters(DiagnosticCollector collector, List<ValueParameterDescriptor> parameters) {
for (int i = 0; i < parameters.size(); i++) {
ValueParameterDescriptor valueParameterDescriptor = parameters.get(i);
if (valueParameterDescriptor.getIndex() != i) {
report(collector, valueParameterDescriptor, "Incorrect index: " + valueParameterDescriptor.getIndex() + " but must be " + i);
}
}
}
private static void validateTypes(
DeclarationDescriptor descriptor,
DiagnosticCollector collector,
Collection<JetType> types
) {
for (JetType type : types) {
validateType(descriptor, type, collector);
}
}
private static void validateCallable(CallableDescriptor descriptor, DiagnosticCollector collector) {
validateReturnType(descriptor, collector);
validateTypeParameters(collector, descriptor.getTypeParameters());
validateValueParameters(collector, descriptor.getValueParameters());
}
private static <T> void assertEquals(
DeclarationDescriptor descriptor,
DiagnosticCollector collector,
String name,
T expected,
T actual
) {
if (!expected.equals(actual)) {
report(collector, descriptor, "Wrong " + name + ": " + actual + " must be " + expected);
}
}
private static void validateAccessor(
PropertyDescriptor descriptor,
DiagnosticCollector collector,
PropertyAccessorDescriptor accessor,
String name
) {
// TODO
//assertEquals(accessor, collector, name + " visibility", descriptor.getVisibility(), accessor.getVisibility());
//assertEquals(accessor, collector, name + " modality", descriptor.getModality(), accessor.getModality());
assertEquals(accessor, collector, "corresponding property", descriptor, accessor.getCorrespondingProperty());
}
@Override
public Boolean visitNamespaceDescriptor(
NamespaceDescriptor descriptor, DiagnosticCollector collector
) {
validateScope(descriptor.getMemberScope(), collector);
return true;
}
@Override
public Boolean visitVariableDescriptor(
VariableDescriptor descriptor, DiagnosticCollector collector
) {
validateReturnType(descriptor, collector);
return true;
}
@Override
public Boolean visitFunctionDescriptor(
FunctionDescriptor descriptor, DiagnosticCollector collector
) {
validateCallable(descriptor, collector);
return true;
}
@Override
public Boolean visitTypeParameterDescriptor(
TypeParameterDescriptor descriptor, DiagnosticCollector collector
) {
validateTypes(descriptor, collector, descriptor.getUpperBounds());
return true;
}
@Override
public Boolean visitClassDescriptor(
ClassDescriptor descriptor, DiagnosticCollector collector
) {
validateTypeParameters(collector, descriptor.getTypeConstructor().getParameters());
validateTypes(descriptor, collector, descriptor.getTypeConstructor().getSupertypes());
validateType(descriptor, descriptor.getDefaultType(), collector);
validateScope(descriptor.getUnsubstitutedInnerClassesScope(), collector);
List<ConstructorDescriptor> primary = Lists.newArrayList();
for (ConstructorDescriptor constructorDescriptor : descriptor.getConstructors()) {
if (constructorDescriptor.isPrimary()) {
primary.add(constructorDescriptor);
}
}
if (primary.size() > 1) {
report(collector, descriptor, "Many primary constructors: " + primary);
}
ConstructorDescriptor primaryConstructor = descriptor.getUnsubstitutedPrimaryConstructor();
if (primaryConstructor != null) {
if (!descriptor.getConstructors().contains(primaryConstructor)) {
report(collector, primaryConstructor,
"Primary constructor not in getConstructors() result: " + descriptor.getConstructors());
}
}
return true;
}
@Override
public Boolean visitModuleDeclaration(
ModuleDescriptor descriptor, DiagnosticCollector collector
) {
return true;
}
@Override
public Boolean visitConstructorDescriptor(
ConstructorDescriptor constructorDescriptor, DiagnosticCollector collector
) {
visitFunctionDescriptor(constructorDescriptor, collector);
assertEquals(constructorDescriptor, collector,
"return type",
constructorDescriptor.getContainingDeclaration().getDefaultType(),
constructorDescriptor.getReturnType());
return true;
}
@Override
public Boolean visitScriptDescriptor(
ScriptDescriptor scriptDescriptor, DiagnosticCollector collector
) {
return true;
}
@Override
public Boolean visitPropertyDescriptor(
PropertyDescriptor descriptor, DiagnosticCollector collector
) {
validateCallable(descriptor, collector);
PropertyGetterDescriptor getter = descriptor.getGetter();
if (getter != null) {
assertEquals(getter, collector, "getter return type", descriptor.getType(), getter.getReturnType());
validateAccessor(descriptor, collector, getter, "getter");
}
PropertySetterDescriptor setter = descriptor.getSetter();
if (setter != null) {
assertEquals(setter, collector, "setter parameter count", 1, setter.getValueParameters().size());
assertEquals(setter, collector, "setter parameter type", descriptor.getType(), setter.getValueParameters().get(0).getType());
}
return true;
}
@Override
public Boolean visitValueParameterDescriptor(
ValueParameterDescriptor descriptor, DiagnosticCollector collector
) {
visitVariableDescriptor(descriptor, collector);
return true;
}
@Override
public Boolean visitPropertyGetterDescriptor(
PropertyGetterDescriptor descriptor, DiagnosticCollector collector
) {
return visitFunctionDescriptor(descriptor, collector);
}
@Override
public Boolean visitPropertySetterDescriptor(
PropertySetterDescriptor descriptor, DiagnosticCollector collector
) {
return visitFunctionDescriptor(descriptor, collector);
}
@Override
public Boolean visitReceiverParameterDescriptor(
ReceiverParameterDescriptor descriptor, DiagnosticCollector collector
) {
validateType(descriptor, descriptor.getType(), collector);
if (!descriptor.getValue().exists()) {
report(collector, descriptor, "Receiver value does not exist: " + descriptor.getValue());
}
return true;
}
}
private static class ScopeValidatorVisitor implements DeclarationDescriptorVisitor<Void, JetScope> {
private final DiagnosticCollector collector;
public ScopeValidatorVisitor(DiagnosticCollector collector) {
this.collector = collector;
}
private void report(DeclarationDescriptor expected, String message) {
DescriptorValidator.report(collector, expected, message);
}
private void assertFound(
@NotNull JetScope scope,
@NotNull DeclarationDescriptor expected,
@Nullable DeclarationDescriptor found
) {
if (found == null) {
report(expected, "Not found in " + scope);
}
if (expected != found) {
report(expected, "Lookup error in " + scope + ": " + found);
}
}
private void assertFound(
@NotNull JetScope scope,
@NotNull DeclarationDescriptor expected,
@NotNull Collection<? extends DeclarationDescriptor> found
) {
if (!found.contains(expected)) {
report(expected, "Not found in " + scope + ": " + found);
}
}
@Override
public Void visitNamespaceDescriptor(
NamespaceDescriptor descriptor, JetScope scope
) {
assertFound(scope, descriptor, scope.getNamespace(descriptor.getName()));
return null;
}
@Override
public Void visitVariableDescriptor(
VariableDescriptor descriptor, JetScope scope
) {
assertFound(scope, descriptor, scope.getProperties(descriptor.getName()));
return null;
}
@Override
public Void visitFunctionDescriptor(
FunctionDescriptor descriptor, JetScope scope
) {
assertFound(scope, descriptor, scope.getFunctions(descriptor.getName()));
return null;
}
@Override
public Void visitTypeParameterDescriptor(
TypeParameterDescriptor descriptor, JetScope scope
) {
assertFound(scope, descriptor, scope.getClassifier(descriptor.getName()));
return null;
}
@Override
public Void visitClassDescriptor(
ClassDescriptor descriptor, JetScope scope
) {
if (descriptor.getKind().isObject()) {
assertFound(scope, descriptor, scope.getObjectDescriptor(descriptor.getName()));
}
else {
assertFound(scope, descriptor, scope.getClassifier(descriptor.getName()));
}
return null;
}
@Override
public Void visitModuleDeclaration(
ModuleDescriptor descriptor, JetScope scope
) {
report(descriptor, "Module found in scope: " + scope);
return null;
}
@Override
public Void visitConstructorDescriptor(
ConstructorDescriptor descriptor, JetScope scope
) {
report(descriptor, "Constructor found in scope: " + scope);
return null;
}
@Override
public Void visitScriptDescriptor(
ScriptDescriptor descriptor, JetScope scope
) {
report(descriptor, "Script found in scope: " + scope);
return null;
}
@Override
public Void visitPropertyDescriptor(
PropertyDescriptor descriptor, JetScope scope
) {
return visitVariableDescriptor(descriptor, scope);
}
@Override
public Void visitValueParameterDescriptor(
ValueParameterDescriptor descriptor, JetScope scope
) {
return visitVariableDescriptor(descriptor, scope);
}
@Override
public Void visitPropertyGetterDescriptor(
PropertyGetterDescriptor descriptor, JetScope scope
) {
report(descriptor, "Getter found in scope: " + scope);
return null;
}
@Override
public Void visitPropertySetterDescriptor(
PropertySetterDescriptor descriptor, JetScope scope
) {
report(descriptor, "Setter found in scope: " + scope);
return null;
}
@Override
public Void visitReceiverParameterDescriptor(
ReceiverParameterDescriptor descriptor, JetScope scope
) {
report(descriptor, "Receiver parameter found in scope: " + scope);
return null;
}
}
public static class Diagnostic {
private final DeclarationDescriptor descriptor;
private final String message;
private final Throwable stackTrace;
private Diagnostic(@NotNull DeclarationDescriptor descriptor, @NotNull String message) {
this.descriptor = descriptor;
this.message = message;
this.stackTrace = new Throwable();
}
@NotNull
public DeclarationDescriptor getDescriptor() {
return descriptor;
}
@NotNull
public String getMessage() {
return message;
}
@NotNull
public Throwable getStackTrace() {
return stackTrace;
}
public void printStackTrace(@NotNull PrintStream out) {
out.println(descriptor);
out.println(message);
stackTrace.printStackTrace(out);
}
@Override
public String toString() {
return descriptor + " > " + message;
}
}
private static class DiagnosticCollectorForTests implements DiagnosticCollector {
private boolean errorsFound = false;
@Override
public void report(@NotNull Diagnostic diagnostic) {
diagnostic.printStackTrace(System.err);
errorsFound = true;
}
public void done() {
if (errorsFound) {
Assert.fail("Descriptor validation failed (see messages above)");
}
}
}
}
@@ -0,0 +1,148 @@
/*
* 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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
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);
}
private static class RecursiveVisitor<D> implements DeclarationDescriptorVisitor<Boolean, D> {
private final DeclarationDescriptorVisitor<Boolean, D> worker;
private RecursiveVisitor(@NotNull DeclarationDescriptorVisitor<Boolean, D> worker) {
this.worker = worker;
}
private boolean doProcess(Collection<? extends DeclarationDescriptor> descriptors, D data) {
return process(descriptors, data, worker);
}
private boolean doProcess(@Nullable DeclarationDescriptor receiverParameter, D data) {
if (receiverParameter == null) {
return true;
}
return receiverParameter.accept(worker, data);
}
private boolean processCallable(CallableDescriptor descriptor, D data) {
return doProcess(descriptor.getTypeParameters(), data)
&& doProcess(descriptor.getReceiverParameter(), data)
&& doProcess(descriptor.getValueParameters(), data);
}
@Override
public Boolean visitNamespaceDescriptor(NamespaceDescriptor descriptor, D data) {
return doProcess(descriptor.getMemberScope().getAllDescriptors(), data);
}
@Override
public Boolean visitVariableDescriptor(VariableDescriptor descriptor, D data) {
return processCallable(descriptor, data);
}
@Override
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, D data) {
return processCallable(descriptor, data)
&& doProcess(descriptor.getGetter(), data)
&& doProcess(descriptor.getSetter(), data);
}
@Override
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, D data) {
return processCallable(descriptor, data);
}
@Override
public Boolean visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, D data) {
return true;
}
@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);
}
@Override
public Boolean visitModuleDeclaration(ModuleDescriptor descriptor, D data) {
return doProcess(descriptor.getNamespace(FqName.ROOT), data);
}
@Override
public Boolean visitConstructorDescriptor(ConstructorDescriptor constructorDescriptor, D data) {
return visitFunctionDescriptor(constructorDescriptor, data);
}
@Override
public Boolean visitScriptDescriptor(ScriptDescriptor scriptDescriptor, D data) {
return visitClassDescriptor(scriptDescriptor.getClassDescriptor(), data);
}
@Override
public Boolean visitValueParameterDescriptor(ValueParameterDescriptor descriptor, D data) {
return visitVariableDescriptor(descriptor, data);
}
@Override
public Boolean visitPropertyGetterDescriptor(PropertyGetterDescriptor descriptor, D data) {
return visitFunctionDescriptor(descriptor, data);
}
@Override
public Boolean visitPropertySetterDescriptor(PropertySetterDescriptor descriptor, D data) {
return visitFunctionDescriptor(descriptor, data);
}
@Override
public Boolean visitReceiverParameterDescriptor(ReceiverParameterDescriptor descriptor, D data) {
return true;
}
}
}