From 05cf9041afb79ac03e34e186ea9ca983cdf4b0d2 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Mon, 14 Jan 2013 17:24:37 +0400 Subject: [PATCH] Tests to make sure that light classes compute the data properly --- .../testData/asJava/lightClasses/Declared.kt | 33 +++ .../lightClasses/DeclaredWithGenerics.kt | 11 + .../testData/asJava/lightClasses/Package.kt | 3 + .../jet/asJava/KotlinLightClassTest.java | 279 ++++++++++++++++++ 4 files changed, 326 insertions(+) create mode 100644 compiler/testData/asJava/lightClasses/Declared.kt create mode 100644 compiler/testData/asJava/lightClasses/DeclaredWithGenerics.kt create mode 100644 compiler/testData/asJava/lightClasses/Package.kt create mode 100644 compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTest.java diff --git a/compiler/testData/asJava/lightClasses/Declared.kt b/compiler/testData/asJava/lightClasses/Declared.kt new file mode 100644 index 00000000000..0b972197680 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/Declared.kt @@ -0,0 +1,33 @@ +package test + +class NoModifiers + +// Visibility +public class Public +private class Private +internal class Internal +class Outer { + public class Public + protected class Protected + private class Private + internal class Internal +} + +// Modality +abstract class Abstract +open class Open +final class Final + +// Special +annotation class Annotation +enum class Enum +trait Trait + +// Deprecation +deprecated class Deprecated +[deprecated] class DeprecatedWithBrackets + +// Generic +class Generic1 +class Generic2 + diff --git a/compiler/testData/asJava/lightClasses/DeclaredWithGenerics.kt b/compiler/testData/asJava/lightClasses/DeclaredWithGenerics.kt new file mode 100644 index 00000000000..acbe5e7799d --- /dev/null +++ b/compiler/testData/asJava/lightClasses/DeclaredWithGenerics.kt @@ -0,0 +1,11 @@ +package test + +class Generic1 +class Generic1WithBounds + +class Generic2 +class Generic2WithBounds where A: Bound1, A: Bound2, B: Generic1 + +class Bound1 +class Bound2 + diff --git a/compiler/testData/asJava/lightClasses/Package.kt b/compiler/testData/asJava/lightClasses/Package.kt new file mode 100644 index 00000000000..2e45a628214 --- /dev/null +++ b/compiler/testData/asJava/lightClasses/Package.kt @@ -0,0 +1,3 @@ +package test + +fun foo() \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTest.java b/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTest.java new file mode 100644 index 00000000000..25b835b6d2e --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/asJava/KotlinLightClassTest.java @@ -0,0 +1,279 @@ +/* + * 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.asJava; + +import com.google.common.base.Function; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiTypeParameter; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.config.CommonConfigurationKeys; +import org.jetbrains.jet.config.CompilerConfiguration; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment; +import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import static org.jetbrains.jet.asJava.KotlinLightClassTest.ClassProperty.*; + +public abstract class KotlinLightClassTest extends KotlinTestWithEnvironment { + + public static class Declared extends KotlinLightClassTest { + public Declared() { + super(new File("compiler/testData/asJava/lightClasses/Declared.kt")); + } + + public void testNoModifiers() { + checkModifiers("test.NoModifiers", PUBLIC, FINAL); + } + + public void testTopLevelVisibilities() { + checkModifiers("test.Public", PUBLIC, FINAL); + checkModifiers("test.Private", PUBLIC, FINAL); + checkModifiers("test.Internal", PUBLIC, FINAL); + } + + public void testNestedVisibilities() { + checkModifiers("test.Outer.Public", PUBLIC, FINAL, INNER); + checkModifiers("test.Outer.Protected", PROTECTED, FINAL, INNER); + checkModifiers("test.Outer.Internal", PUBLIC, FINAL, INNER); + checkModifiers("test.Outer.Private", PRIVATE, FINAL, INNER); + } + public void testModalities() { + checkModifiers("test.Abstract", PUBLIC, ABSTRACT); + checkModifiers("test.Open", PUBLIC); + checkModifiers("test.Final", PUBLIC, FINAL); + } + + public void testAnnotation() { + checkModifiers("test.Annotation", PUBLIC, FINAL, ANNOTATION, INTERFACE); + } + + public void testEnum() { + checkModifiers("test.Enum", PUBLIC, FINAL, ENUM); + } + public void testTrait() { + checkModifiers("test.Trait", PUBLIC, ABSTRACT, INTERFACE); + } + + public void testDeprecation() { + checkModifiers("test.Deprecated", PUBLIC, FINAL, DEPRECATED); + checkModifiers("test.DeprecatedWithBrackets", PUBLIC, FINAL, DEPRECATED); + } + + public void testGenericity() { + checkModifiers("test.Generic1", PUBLIC, FINAL, GENERIC); + checkModifiers("test.Generic2", PUBLIC, FINAL, GENERIC); + } + } + + public static class DeclaredWithGenerics extends KotlinLightClassTest { + + public DeclaredWithGenerics() { + super(new File("compiler/testData/asJava/lightClasses/DeclaredWithGenerics.kt")); + } + + public void testGeneric1() throws Exception { + checkGenericParameter("test.Generic1", 0, "T"); + } + + public void testGeneric1WithBounds() throws Exception { + checkGenericParameter("test.Generic1WithBounds", 0, "T", "test.Bound1"); + } + + public void testGeneric2() throws Exception { + checkGenericParameter("test.Generic2", 0, "A"); + checkGenericParameter("test.Generic2", 1, "B"); + } + + public void testGeneric2WithBounds() throws Exception { + checkGenericParameter("test.Generic2WithBounds", 0, "A", "test.Bound1", "test.Bound2"); + checkGenericParameter("test.Generic2WithBounds", 1, "B", "test.Generic1"); + } + } + + public static class Package extends KotlinLightClassTest { + + public Package() { + super(new File("compiler/testData/asJava/lightClasses/Package.kt")); + } + + public void testPackage() throws Exception { + checkModifiers("test.namespace", PUBLIC, FINAL); + } + } + + private final File path; + private JavaElementFinder finder; + + protected KotlinLightClassTest(File path) { + this.path = path; + } + + @Override + protected JetCoreEnvironment createEnvironment() { + CompilerConfiguration configuration = new CompilerConfiguration(); + + configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, path.getPath()); + + return new JetCoreEnvironment(getTestRootDisposable(), configuration); + } + + @Override + public void setUp() throws Exception { + super.setUp(); + + finder = JavaElementFinder.getInstance(getProject()); + + // We need to resolve all the files in order to fill in the trace that sits inside LightClassGenerationSupport + List paths = getEnvironment().getConfiguration().get(CommonConfigurationKeys.SOURCE_ROOTS_KEY); + assert paths != null; + List jetFiles = Lists.newArrayList(); + for (String path : paths) { + jetFiles.add(JetTestUtils.loadJetFile(getProject(), new File(path))); + } + LazyResolveTestUtil.resolveEagerly(jetFiles, getEnvironment()); + } + + @NotNull + protected PsiClass findClass(String qualifiedName) { + PsiClass psiClass = finder.findClass(qualifiedName, GlobalSearchScope.allScope(getProject())); + assertNotNull(psiClass); + + assertEquals("Wrong fqn", qualifiedName, psiClass.getQualifiedName()); + + return psiClass; + } + + protected static void checkModifiers(PsiClass psiClass, ClassProperty... properties) { + Set modifiersSet = Sets.newHashSet(properties); + for (ClassProperty property : values()) { + boolean present = property.present(psiClass); + if (modifiersSet.contains(property)) { + assertTrue("Property " + property + " not present on " + psiClass, present); + } + else { + assertFalse("Property " + property + " must not be present on " + psiClass, present); + } + } + } + + protected void checkModifiers(String classFqName, ClassProperty... properties) { + checkModifiers(findClass(classFqName), properties); + } + + protected static void checkGenericParameter(PsiClass psiClass, int index, String name, String... bounds) { + PsiTypeParameter typeParameter = psiClass.getTypeParameters()[index]; + assertEquals(name, typeParameter.getName()); + assertEquals(index, typeParameter.getIndex()); + Set expectedBounds = Sets.newHashSet(bounds); + Set actualBounds = Sets.newHashSet(Collections2.transform( + Arrays.asList(typeParameter.getExtendsListTypes()), + new Function() { + @Override + public String apply(PsiClassType input) { + return input.getCanonicalText(); + } + } + )); + + assertEquals(expectedBounds, actualBounds); + } + + protected void checkGenericParameter(String classFqName, int index, String name, String... bounds) { + checkGenericParameter(findClass(classFqName), index, name, bounds); + } + + enum ClassProperty { + PUBLIC(PsiModifier.PUBLIC), + PROTECTED(PsiModifier.PROTECTED), + PRIVATE(PsiModifier.PRIVATE), + STATIC(PsiModifier.STATIC), + ABSTRACT(PsiModifier.ABSTRACT), + FINAL(PsiModifier.FINAL), + NATIVE(PsiModifier.NATIVE), + SYNCHRONIZED(PsiModifier.SYNCHRONIZED), + STRICTFP(PsiModifier.STRICTFP), + TRANSIENT(PsiModifier.TRANSIENT), + VOLATILE(PsiModifier.VOLATILE), + DEFAULT(PsiModifier.DEFAULT), + INTERFACE { + @Override + public boolean present(@NotNull PsiClass psiClass) { + return psiClass.isInterface(); + } + }, + ENUM { + @Override + public boolean present(@NotNull PsiClass psiClass) { + return psiClass.isInterface(); + } + }, + ANNOTATION { + @Override + public boolean present(@NotNull PsiClass psiClass) { + return psiClass.isAnnotationType(); + } + }, + DEPRECATED { + @Override + public boolean present(@NotNull PsiClass psiClass) { + return psiClass.isDeprecated(); + } + }, + INNER { + @Override + public boolean present(@NotNull PsiClass psiClass) { + return psiClass.getContainingClass() != null; + } + }, + GENERIC { + @Override + public boolean present(@NotNull PsiClass psiClass) { + return psiClass.hasTypeParameters(); + } + }; + + private final String modifier; + + private ClassProperty(@Nullable String modifier) { + this.modifier = modifier; + } + + private ClassProperty() { + this(null); + } + + public boolean present(@NotNull PsiClass psiClass) { + assert modifier != null : "No modifier specified for " + this + ". Override this method."; + return psiClass.hasModifierProperty(modifier); + } + } + +}