diff --git a/compiler/testData/readJavaBinaryClass/FieldAsVar.java b/compiler/testData/readJavaBinaryClass/FieldAsVar.java new file mode 100644 index 00000000000..9c2662efce4 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/FieldAsVar.java @@ -0,0 +1,5 @@ +package test; + +final class FieldAsVar { + public int f; +} diff --git a/compiler/testData/readJavaBinaryClass/FieldAsVar.kt b/compiler/testData/readJavaBinaryClass/FieldAsVar.kt new file mode 100644 index 00000000000..358ad58ff61 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/FieldAsVar.kt @@ -0,0 +1,5 @@ +package test + +class FieldAsVar() { + var f: Int = 1 +} diff --git a/compiler/testData/readJavaBinaryClass/Simple.java b/compiler/testData/readJavaBinaryClass/Simple.java new file mode 100644 index 00000000000..fd436f0c133 --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/Simple.java @@ -0,0 +1,5 @@ +package test; + +public final class Simple { + public Simple() { } +} diff --git a/compiler/testData/readJavaBinaryClass/Simple.kt b/compiler/testData/readJavaBinaryClass/Simple.kt new file mode 100644 index 00000000000..8e2814732aa --- /dev/null +++ b/compiler/testData/readJavaBinaryClass/Simple.kt @@ -0,0 +1,3 @@ +package test + +class Simple() diff --git a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java new file mode 100644 index 00000000000..196f8a587e0 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java @@ -0,0 +1,476 @@ +package org.jetbrains.jet; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.PropertyCodegen; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.Modality; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeProjection; +import org.jetbrains.jet.lang.types.Variance; +import org.junit.Assert; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Stepan Koltsov + */ +class NamespaceComparator { + + private final boolean includeObject; + + private NamespaceComparator(boolean includeObject) { + this.includeObject = includeObject; + } + + public static void compareNamespaces(@NotNull NamespaceDescriptor nsa, @NotNull NamespaceDescriptor nsb, boolean includeObject) { + new NamespaceComparator(includeObject).doCompareNamespaces(nsa, nsb); + } + + private void doCompareNamespaces(@NotNull NamespaceDescriptor nsa, @NotNull NamespaceDescriptor nsb) { + Assert.assertEquals(nsa.getName(), nsb.getName()); + System.out.println("namespace " + nsa.getName()); + + Assert.assertTrue(!nsa.getMemberScope().getAllDescriptors().isEmpty()); + + Set classifierNames = new HashSet(); + Set propertyNames = new HashSet(); + Set functionNames = new HashSet(); + + for (DeclarationDescriptor ad : nsa.getMemberScope().getAllDescriptors()) { + if (ad instanceof ClassifierDescriptor) { + classifierNames.add(ad.getName()); + } else if (ad instanceof PropertyDescriptor) { + propertyNames.add(ad.getName()); + } else if (ad instanceof FunctionDescriptor) { + functionNames.add(ad.getName()); + } else { + throw new AssertionError("unknown member: " + ad); + } + } + + for (String name : classifierNames) { + ClassifierDescriptor ca = nsa.getMemberScope().getClassifier(name); + ClassifierDescriptor cb = nsb.getMemberScope().getClassifier(name); + Assert.assertTrue(ca != null); + Assert.assertTrue(cb != null); + compareClassifiers(ca, cb); + } + + for (String name : propertyNames) { + Set pa = nsa.getMemberScope().getProperties(name); + Set pb = nsb.getMemberScope().getProperties(name); + compareDeclarationSets(pa, pb); + + Assert.assertTrue(nsb.getMemberScope().getFunctions(PropertyCodegen.getterName(name)).isEmpty()); + Assert.assertTrue(nsb.getMemberScope().getFunctions(PropertyCodegen.setterName(name)).isEmpty()); + } + + for (String name : functionNames) { + Set fa = nsa.getMemberScope().getFunctions(name); + Set fb = nsb.getMemberScope().getFunctions(name); + compareDeclarationSets(fa, fb); + } + } + + private static void compareDeclarationSets(Set a, Set b) { + String at = serializedDeclarationSets(a); + String bt = serializedDeclarationSets(b); + Assert.assertEquals(at, bt); + System.out.print(at); + } + + private static String serializedDeclarationSets(Collection ds) { + List strings = new ArrayList(); + for (DeclarationDescriptor d : ds) { + StringBuilder sb = new StringBuilder(); + new Serializer(sb).serialize(d); + strings.add(sb.toString()); + } + + Collections.sort(strings); + + StringBuilder r = new StringBuilder(); + for (String string : strings) { + r.append(string); + r.append("\n"); + } + return r.toString(); + } + + private void compareClassifiers(@NotNull ClassifierDescriptor a, @NotNull ClassifierDescriptor b) { + StringBuilder sba = new StringBuilder(); + StringBuilder sbb = new StringBuilder(); + + new FullContentSerialier(sba).serialize((ClassDescriptor) a); + new FullContentSerialier(sbb).serialize((ClassDescriptor) b); + + String as = sba.toString(); + String bs = sbb.toString(); + + Assert.assertEquals(as, bs); + System.out.println(as); + } + + private void compareDescriptors(@NotNull DeclarationDescriptor a, @NotNull DeclarationDescriptor b) { + StringBuilder sba = new StringBuilder(); + StringBuilder sbb = new StringBuilder(); + new Serializer(sba).serialize(a); + new Serializer(sbb).serialize(b); + + String as = sba.toString(); + String bs = sbb.toString(); + + Assert.assertEquals(as, bs); + System.out.println(as); + } + + + + + private static class Serializer { + + protected final StringBuilder sb; + + public Serializer(StringBuilder sb) { + this.sb = sb; + } + + public void serialize(ClassKind kind) { + switch (kind) { + case CLASS: + sb.append("class"); + break; + case TRAIT: + sb.append("trait"); + break; + default: + throw new IllegalStateException(); + } + } + + + private static Object invoke(Method method, Object thiz, Object... args) { + try { + return method.invoke(thiz, args); + } catch (Exception e) { + throw new RuntimeException("failed to invoke " + method + ": " + e, e); + } + } + + + public void serialize(FunctionDescriptor fun) { + serialize(fun.getModality()); + sb.append(" "); + + if (fun instanceof ConstructorDescriptor) { + sb.append("/*constructor*/ "); + } + sb.append("fun "); + if (!fun.getTypeParameters().isEmpty()) { + sb.append("<"); + new Serializer(sb).serializeCommaSeparated(fun.getTypeParameters()); + sb.append(">"); + } + + if (fun.getReceiverParameter().exists()) { + new Serializer(sb).serialize(fun.getReceiverParameter()); + sb.append("."); + } + + sb.append(fun.getName()); + sb.append("("); + new ValueParameterSerializer(sb).serializeCommaSeparated(fun.getValueParameters()); + sb.append("): "); + new Serializer(sb).serialize(fun.getReturnType()); + } + + public void serialize(ExtensionReceiver extensionReceiver) { + serialize(extensionReceiver.getType()); + } + + public void serialize(PropertyDescriptor prop) { + if (prop.isVar()) { + sb.append("var "); + } else { + sb.append("val "); + } + if (prop.getReceiverParameter().exists()) { + new Serializer(sb).serialize(prop.getReceiverParameter().getType()); + sb.append("."); + } + sb.append(prop.getName()); + sb.append(": "); + new Serializer(sb).serialize(prop.getOutType()); + } + + public void serialize(ValueParameterDescriptor valueParameter) { + sb.append("/*"); + sb.append(valueParameter.getIndex()); + sb.append("*/ "); + if (valueParameter.getVarargElementType() != null) { + sb.append("vararg "); + } + sb.append(valueParameter.getName()); + sb.append(": "); + if (valueParameter.getVarargElementType() != null) { + serialize(valueParameter.getVarargElementType()); + } else { + serialize(valueParameter.getOutType()); + } + if (valueParameter.hasDefaultValue()) { + sb.append(" = ?"); + } + } + + public void serialize(Variance variance) { + if (variance == Variance.INVARIANT) { + + } else { + sb.append(variance); + sb.append(' '); + } + } + + public void serialize(Modality modality) { + sb.append(modality.name().toLowerCase()); + } + + public void serialize(JetType type) { + serialize(type.getConstructor().getDeclarationDescriptor()); + if (!type.getArguments().isEmpty()) { + sb.append("<"); + boolean first = true; + for (TypeProjection proj : type.getArguments()) { + if (!first) { + sb.append(", "); + } + serialize(proj.getProjectionKind()); + serialize(proj.getType()); + first = false; + } + sb.append(">"); + } + } + + public void serializeCommaSeparated(List list) { + serializeSeparated(list, ", "); + } + + public void serializeSeparated(List list, String sep) { + boolean first = true; + for (Object o : list) { + if (!first) { + sb.append(sep); + } + serialize(o); + first = false; + } + } + + private Method getMethodToSerialize(Object o) { + // TODO: cache + for (Method method : this.getClass().getMethods()) { + if (!method.getName().equals("serialize")) { + continue; + } + if (method.getParameterTypes().length != 1) { + continue; + } + if (method.getParameterTypes()[0].equals(Object.class)) { + continue; + } + if (method.getParameterTypes()[0].isInstance(o)) { + method.setAccessible(true); + return method; + } + } + throw new IllegalStateException("don't know how to serialize " + o + " (of " + o.getClass() + ")"); + } + + public void serialize(Object o) { + Method method = getMethodToSerialize(o); + invoke(method, this, o); + } + + public void serialize(String s) { + sb.append(s); + } + + public void serialize(ModuleDescriptor module) { + // nop + } + + public void serialize(ClassDescriptor clazz) { + new NamespacePrefixSerializer(sb).serialize(clazz.getContainingDeclaration()); + sb.append(clazz.getName()); + } + + public void serialize(NamespaceDescriptor ns) { + if (ns.getContainingDeclaration() == null) { + // root ns + return; + } + new NamespacePrefixSerializer(sb).serialize(ns.getContainingDeclaration()); + sb.append(ns.getName()); + } + + public void serialize(TypeParameterDescriptor param) { + sb.append("/*").append(param.getIndex()).append("*/ "); + serialize(param.getVariance()); + sb.append(param.getName()); + if (!param.getUpperBounds().isEmpty()) { + sb.append(" : "); + List list = new ArrayList(); + for (JetType upper : param.getUpperBounds()) { + StringBuilder sb = new StringBuilder(); + new ValueParameterSerializer(sb).serialize(upper); + list.add(sb.toString()); + } + Collections.sort(list); + serializeSeparated(list, " & "); // TODO: use where + } + // TODO: lower bounds + } + + } + + private static class NamespacePrefixSerializer extends Serializer { + + public NamespacePrefixSerializer(StringBuilder sb) { + super(sb); + } + + @Override + public void serialize(NamespaceDescriptor ns) { + if (ns.getContainingDeclaration() == null) { + // root ns + return; + } + super.serialize(ns); + sb.append("."); + } + + @Override + public void serialize(ClassDescriptor clazz) { + super.serialize(clazz); + sb.append("."); + } + } + + private static class ValueParameterSerializer extends Serializer { + + public ValueParameterSerializer(StringBuilder sb) { + super(sb); + } + + @Override + public void serialize(TypeParameterDescriptor param) { + sb.append(param.getName()); + } + } + + private class FullContentSerialier extends Serializer { + private FullContentSerialier(StringBuilder sb) { + super(sb); + } + + public void serialize(ClassDescriptor klass) { + + serialize(klass.getModality()); + sb.append(" "); + + serialize(klass.getKind()); + sb.append(" "); + + new Serializer(sb).serialize(klass); + + if (!klass.getTypeConstructor().getParameters().isEmpty()) { + sb.append("<"); + serializeCommaSeparated(klass.getTypeConstructor().getParameters()); + sb.append(">"); + } + + // TODO: supers + // TODO: constructors + + sb.append(" {\n"); + + List typeArguments = new ArrayList(); + for (TypeParameterDescriptor param : klass.getTypeConstructor().getParameters()) { + typeArguments.add(new TypeProjection(Variance.INVARIANT, param.getDefaultType())); + } + + List memberStrings = new ArrayList(); + + for (ConstructorDescriptor constructor : klass.getConstructors()) { + StringBuilder constructorSb = new StringBuilder(); + new Serializer(constructorSb).serialize(constructor); + memberStrings.add(constructorSb.toString()); + } + + JetScope memberScope = klass.getMemberScope(typeArguments); + for (DeclarationDescriptor member : memberScope.getAllDescriptors()) { + if (!includeObject) { + if (member.getName().matches("equals|hashCode|finalize|wait|notify(All)?|toString|clone|getClass")) { + continue; + } + } + StringBuilder memberSb = new StringBuilder(); + new FullContentSerialier(memberSb).serialize(member); + memberStrings.add(memberSb.toString()); + } + + Collections.sort(memberStrings); + + for (String memberString : memberStrings) { + sb.append(indent(memberString)); + } + + sb.append("}\n"); + } + } + + + private static String indent(String string) { + try { + StringBuilder r = new StringBuilder(); + BufferedReader reader = new BufferedReader(new StringReader(string)); + for (;;) { + String line = reader.readLine(); + if (line == null) { + break; + } + r.append(" "); + r.append(line); + r.append("\n"); + } + return r.toString(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + +} diff --git a/compiler/tests/org/jetbrains/jet/ReadJavaBinaryClassTest.java b/compiler/tests/org/jetbrains/jet/ReadJavaBinaryClassTest.java new file mode 100644 index 00000000000..66e4ddf1ded --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/ReadJavaBinaryClassTest.java @@ -0,0 +1,115 @@ +package org.jetbrains.jet; + +import com.google.common.base.Predicates; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.CharsetToolkit; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.impl.PsiFileFactoryImpl; +import com.intellij.testFramework.LightVirtualFile; +import junit.framework.Test; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.GenerationState; +import org.jetbrains.jet.compiler.JetCoreEnvironment; +import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.AnalyzingUtils; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices; +import org.jetbrains.jet.plugin.JetLanguage; +import org.junit.Assert; + +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import java.io.File; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Locale; + +/** + * @author Stepan Koltsov + */ +public class ReadJavaBinaryClassTest extends TestCaseWithTmpdir { + + private final File ktFile; + private final File javaFile; + + public ReadJavaBinaryClassTest(File ktFile) { + this.ktFile = ktFile; + Assert.assertTrue(ktFile.getName().endsWith(".kt")); + this.javaFile = new File(ktFile.getPath().replaceFirst("\\.kt$", ".java")); + setName(javaFile.getName()); + } + + + @Override + public void runTest() throws Exception { + NamespaceDescriptor nsa = compileKotlin(); + NamespaceDescriptor nsb = compileJava(); + NamespaceComparator.compareNamespaces(nsa, nsb, false); + } + + private NamespaceDescriptor compileKotlin() throws Exception { + JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + + String text = FileUtil.loadFile(ktFile); + + LightVirtualFile virtualFile = new LightVirtualFile(ktFile.getName(), JetLanguage.INSTANCE, text); + virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); + JetFile psiFile = (JetFile) ((PsiFileFactoryImpl) PsiFileFactory.getInstance(jetCoreEnvironment.getProject())).trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); + + BindingContext bindingContext = AnalyzerFacade.analyzeOneFileWithJavaIntegration(psiFile, JetControlFlowDataTraceFactory.EMPTY); + AnalyzingUtils.throwExceptionOnErrors(bindingContext); + return bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, "test"); + } + + private NamespaceDescriptor compileJava() throws Exception { + JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); + + StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(null, Locale.ENGLISH, Charset.forName("utf-8")); + try { + Iterable javaFileObjectsFromFiles = fileManager.getJavaFileObjectsFromFiles(Collections.singleton(javaFile)); + List options = Arrays.asList( + "-classpath", "out/production/stdlib", + "-d", tmpdir.getPath() + ); + JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, null, options, null, javaFileObjectsFromFiles); + + Assert.assertTrue(task.call()); + } finally { + fileManager.close(); + } + + JetCoreEnvironment jetCoreEnvironment = JetTestUtils.createEnvironmentWithMockJdk(myTestRootDisposable); + + jetCoreEnvironment.addToClasspath(tmpdir); + jetCoreEnvironment.addToClasspath(new File("out/production/stdlib")); + + JetSemanticServices jetSemanticServices = JetSemanticServices.createSemanticServices(jetCoreEnvironment.getProject()); + JavaSemanticServices semanticServices = new JavaSemanticServices(jetCoreEnvironment.getProject(), jetSemanticServices, new BindingTraceContext()); + + JavaDescriptorResolver javaDescriptorResolver = semanticServices.getDescriptorResolver(); + return javaDescriptorResolver.resolveNamespace("test"); + } + + public static Test suite() { + return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/readJavaBinaryClass", true, new JetTestCaseBuilder.NamedTestFactory() { + @NotNull + @Override + public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) { + return new ReadJavaBinaryClassTest(file); + } + }); + } + +} diff --git a/compiler/tests/org/jetbrains/jet/ReadKotlinBinaryClassTest.java b/compiler/tests/org/jetbrains/jet/ReadKotlinBinaryClassTest.java index bea9ed9477c..82fdc19e162 100644 --- a/compiler/tests/org/jetbrains/jet/ReadKotlinBinaryClassTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadKotlinBinaryClassTest.java @@ -106,426 +106,7 @@ public class ReadKotlinBinaryClassTest extends TestCaseWithTmpdir { JavaDescriptorResolver javaDescriptorResolver = semanticServices.getDescriptorResolver(); NamespaceDescriptor namespaceFromClass = javaDescriptorResolver.resolveNamespace("test"); - compareNamespaces(namespaceFromSource, namespaceFromClass); - } - - private void compareNamespaces(@NotNull NamespaceDescriptor nsa, @NotNull NamespaceDescriptor nsb) { - Assert.assertEquals(nsa.getName(), nsb.getName()); - System.out.println("namespace " + nsa.getName()); - - Assert.assertTrue(!nsa.getMemberScope().getAllDescriptors().isEmpty()); - - Set classifierNames = new HashSet(); - Set propertyNames = new HashSet(); - Set functionNames = new HashSet(); - - for (DeclarationDescriptor ad : nsa.getMemberScope().getAllDescriptors()) { - if (ad instanceof ClassifierDescriptor) { - classifierNames.add(ad.getName()); - } else if (ad instanceof PropertyDescriptor) { - propertyNames.add(ad.getName()); - } else if (ad instanceof FunctionDescriptor) { - functionNames.add(ad.getName()); - } else { - throw new AssertionError("unknown member: " + ad); - } - } - - for (String name : classifierNames) { - ClassifierDescriptor ca = nsa.getMemberScope().getClassifier(name); - ClassifierDescriptor cb = nsb.getMemberScope().getClassifier(name); - Assert.assertTrue(ca != null); - Assert.assertTrue(cb != null); - compareClassifiers(ca, cb); - } - - for (String name : propertyNames) { - Set pa = nsa.getMemberScope().getProperties(name); - Set pb = nsb.getMemberScope().getProperties(name); - compareDeclarationSets(pa, pb); - - Assert.assertTrue(nsb.getMemberScope().getFunctions(PropertyCodegen.getterName(name)).isEmpty()); - Assert.assertTrue(nsb.getMemberScope().getFunctions(PropertyCodegen.setterName(name)).isEmpty()); - } - - for (String name : functionNames) { - Set fa = nsa.getMemberScope().getFunctions(name); - Set fb = nsb.getMemberScope().getFunctions(name); - compareDeclarationSets(fa, fb); - } - } - - private void compareDeclarationSets(Set a, Set b) { - String at = serializedDeclarationSets(a); - String bt = serializedDeclarationSets(b); - Assert.assertEquals(at, bt); - System.out.print(at); - } - - private String serializedDeclarationSets(Collection ds) { - List strings = new ArrayList(); - for (DeclarationDescriptor d : ds) { - StringBuilder sb = new StringBuilder(); - new Serializer(sb).serialize(d); - strings.add(sb.toString()); - } - - Collections.sort(strings); - - StringBuilder r = new StringBuilder(); - for (String string : strings) { - r.append(string); - r.append("\n"); - } - return r.toString(); - } - - private void compareClassifiers(@NotNull ClassifierDescriptor a, @NotNull ClassifierDescriptor b) { - StringBuilder sba = new StringBuilder(); - StringBuilder sbb = new StringBuilder(); - - new FullContentSerialier(sba).serialize((ClassDescriptor) a); - new FullContentSerialier(sbb).serialize((ClassDescriptor) b); - - String as = sba.toString(); - String bs = sbb.toString(); - - Assert.assertEquals(as, bs); - System.out.println(as); - } - - private void compareDescriptors(@NotNull DeclarationDescriptor a, @NotNull DeclarationDescriptor b) { - StringBuilder sba = new StringBuilder(); - StringBuilder sbb = new StringBuilder(); - new Serializer(sba).serialize(a); - new Serializer(sbb).serialize(b); - - String as = sba.toString(); - String bs = sbb.toString(); - - Assert.assertEquals(as, bs); - System.out.println(as); - } - - - - - private static class Serializer { - - protected final StringBuilder sb; - - public Serializer(StringBuilder sb) { - this.sb = sb; - } - - public void serialize(ClassKind kind) { - switch (kind) { - case CLASS: - sb.append("class"); - break; - case TRAIT: - sb.append("trait"); - break; - default: - throw new IllegalStateException(); - } - } - - - private static Object invoke(Method method, Object thiz, Object... args) { - try { - return method.invoke(thiz, args); - } catch (Exception e) { - throw new RuntimeException("failed to invoke " + method + ": " + e, e); - } - } - - - public void serialize(FunctionDescriptor fun) { - serialize(fun.getModality()); - sb.append(" "); - - if (fun instanceof ConstructorDescriptor) { - sb.append("/*constructor*/ "); - } - sb.append("fun "); - if (!fun.getTypeParameters().isEmpty()) { - sb.append("<"); - new Serializer(sb).serializeCommaSeparated(fun.getTypeParameters()); - sb.append(">"); - } - - if (fun.getReceiverParameter().exists()) { - new Serializer(sb).serialize(fun.getReceiverParameter()); - sb.append("."); - } - - sb.append(fun.getName()); - sb.append("("); - new ValueParameterSerializer(sb).serializeCommaSeparated(fun.getValueParameters()); - sb.append("): "); - new Serializer(sb).serialize(fun.getReturnType()); - } - - public void serialize(ExtensionReceiver extensionReceiver) { - serialize(extensionReceiver.getType()); - } - - public void serialize(PropertyDescriptor prop) { - if (prop.isVar()) { - sb.append("var "); - } else { - sb.append("val "); - } - if (prop.getReceiverParameter().exists()) { - new Serializer(sb).serialize(prop.getReceiverParameter().getType()); - sb.append("."); - } - sb.append(prop.getName()); - sb.append(": "); - new Serializer(sb).serialize(prop.getOutType()); - } - - public void serialize(ValueParameterDescriptor valueParameter) { - sb.append("/*"); - sb.append(valueParameter.getIndex()); - sb.append("*/ "); - if (valueParameter.getVarargElementType() != null) { - sb.append("vararg "); - } - sb.append(valueParameter.getName()); - sb.append(": "); - if (valueParameter.getVarargElementType() != null) { - serialize(valueParameter.getVarargElementType()); - } else { - serialize(valueParameter.getOutType()); - } - if (valueParameter.hasDefaultValue()) { - sb.append(" = ?"); - } - } - - public void serialize(Variance variance) { - if (variance == Variance.INVARIANT) { - - } else { - sb.append(variance); - sb.append(' '); - } - } - - public void serialize(Modality modality) { - sb.append(modality.name().toLowerCase()); - } - - public void serialize(JetType type) { - serialize(type.getConstructor().getDeclarationDescriptor()); - if (!type.getArguments().isEmpty()) { - sb.append("<"); - boolean first = true; - for (TypeProjection proj : type.getArguments()) { - if (!first) { - sb.append(", "); - } - serialize(proj.getProjectionKind()); - serialize(proj.getType()); - first = false; - } - sb.append(">"); - } - } - - public void serializeCommaSeparated(List list) { - serializeSeparated(list, ", "); - } - - public void serializeSeparated(List list, String sep) { - boolean first = true; - for (Object o : list) { - if (!first) { - sb.append(sep); - } - serialize(o); - first = false; - } - } - - private Method getMethodToSerialize(Object o) { - // TODO: cache - for (Method method : this.getClass().getMethods()) { - if (!method.getName().equals("serialize")) { - continue; - } - if (method.getParameterTypes().length != 1) { - continue; - } - if (method.getParameterTypes()[0].equals(Object.class)) { - continue; - } - if (method.getParameterTypes()[0].isInstance(o)) { - method.setAccessible(true); - return method; - } - } - throw new IllegalStateException("don't know how to serialize " + o + " (of " + o.getClass() + ")"); - } - - public void serialize(Object o) { - Method method = getMethodToSerialize(o); - invoke(method, this, o); - } - - public void serialize(String s) { - sb.append(s); - } - - public void serialize(ModuleDescriptor module) { - // nop - } - - public void serialize(ClassDescriptor clazz) { - new NamespacePrefixSerializer(sb).serialize(clazz.getContainingDeclaration()); - sb.append(clazz.getName()); - } - - public void serialize(NamespaceDescriptor ns) { - if (ns.getContainingDeclaration() == null) { - // root ns - return; - } - new NamespacePrefixSerializer(sb).serialize(ns.getContainingDeclaration()); - sb.append(ns.getName()); - } - - public void serialize(TypeParameterDescriptor param) { - sb.append("/*").append(param.getIndex()).append("*/ "); - serialize(param.getVariance()); - sb.append(param.getName()); - if (!param.getUpperBounds().isEmpty()) { - sb.append(" : "); - List list = new ArrayList(); - for (JetType upper : param.getUpperBounds()) { - StringBuilder sb = new StringBuilder(); - new ValueParameterSerializer(sb).serialize(upper); - list.add(sb.toString()); - } - Collections.sort(list); - serializeSeparated(list, " & "); // TODO: use where - } - // TODO: lower bounds - } - - } - - private static class NamespacePrefixSerializer extends Serializer { - - public NamespacePrefixSerializer(StringBuilder sb) { - super(sb); - } - - @Override - public void serialize(NamespaceDescriptor ns) { - if (ns.getContainingDeclaration() == null) { - // root ns - return; - } - super.serialize(ns); - sb.append("."); - } - - @Override - public void serialize(ClassDescriptor clazz) { - super.serialize(clazz); - sb.append("."); - } - } - - private static class ValueParameterSerializer extends Serializer { - - public ValueParameterSerializer(StringBuilder sb) { - super(sb); - } - - @Override - public void serialize(TypeParameterDescriptor param) { - sb.append(param.getName()); - } - } - - private static class FullContentSerialier extends Serializer { - private FullContentSerialier(StringBuilder sb) { - super(sb); - } - - public void serialize(ClassDescriptor klass) { - - serialize(klass.getModality()); - sb.append(" "); - - serialize(klass.getKind()); - sb.append(" "); - - new Serializer(sb).serialize(klass); - - if (!klass.getTypeConstructor().getParameters().isEmpty()) { - sb.append("<"); - serializeCommaSeparated(klass.getTypeConstructor().getParameters()); - sb.append(">"); - } - - // TODO: supers - // TODO: constructors - - sb.append(" {\n"); - - List typeArguments = new ArrayList(); - for (TypeParameterDescriptor param : klass.getTypeConstructor().getParameters()) { - typeArguments.add(new TypeProjection(Variance.INVARIANT, param.getDefaultType())); - } - - List memberStrings = new ArrayList(); - - for (ConstructorDescriptor constructor : klass.getConstructors()) { - StringBuilder constructorSb = new StringBuilder(); - new Serializer(constructorSb).serialize(constructor); - memberStrings.add(constructorSb.toString()); - } - - JetScope memberScope = klass.getMemberScope(typeArguments); - for (DeclarationDescriptor member : memberScope.getAllDescriptors()) { - StringBuilder memberSb = new StringBuilder(); - new FullContentSerialier(memberSb).serialize(member); - memberStrings.add(memberSb.toString()); - } - - Collections.sort(memberStrings); - - for (String memberString : memberStrings) { - sb.append(indent(memberString)); - } - - sb.append("}\n"); - } - } - - - private static String indent(String string) { - try { - StringBuilder r = new StringBuilder(); - BufferedReader reader = new BufferedReader(new StringReader(string)); - for (;;) { - String line = reader.readLine(); - if (line == null) { - break; - } - r.append(" "); - r.append(line); - r.append("\n"); - } - return r.toString(); - } catch (IOException e) { - throw new RuntimeException(e); - } + NamespaceComparator.compareNamespaces(namespaceFromSource, namespaceFromClass, false); } public static Test suite() {