diff --git a/compiler/tests/org/jetbrains/jet/JetTestUtils.java b/compiler/tests/org/jetbrains/jet/JetTestUtils.java index 044781889d2..28fc7071f6a 100644 --- a/compiler/tests/org/jetbrains/jet/JetTestUtils.java +++ b/compiler/tests/org/jetbrains/jet/JetTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 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. @@ -267,6 +267,10 @@ public class JetTestUtils { return new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/rt.jar"); } + public static File findAndroidApiJar() { + return new File(JetTestCaseBuilder.getHomeDirectory(), "dependencies/android.jar"); + } + public static File getAnnotationsJar() { return new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK/jre/lib/annotations.jar"); } @@ -280,6 +284,15 @@ public class JetTestUtils { return jdkAnnotations; } + @NotNull + public static File getAndroidSdkAnnotationsJar() { + File androidSdkAnnotations = new File("dependencies/annotations/kotlin-android-sdk-annotations.jar"); + if (!androidSdkAnnotations.exists()) { + throw new RuntimeException("Kotlin Android SDK annotations jar not found; please run 'ant dist' to build it"); + } + return androidSdkAnnotations; + } + public static void mkdirs(File file) throws IOException { if (file.isDirectory()) { return; @@ -369,6 +382,9 @@ public class JetTestUtils { if (jdkKind == TestJdkKind.MOCK_JDK) { configuration.add(CLASSPATH_KEY, findMockJdkRtJar()); } + else if (jdkKind == TestJdkKind.ANDROID_API) { + configuration.add(CLASSPATH_KEY, findAndroidApiJar()); + } else { configuration.addAll(CLASSPATH_KEY, PathUtil.getJdkClassesRoots()); } @@ -378,7 +394,11 @@ public class JetTestUtils { configuration.addAll(CLASSPATH_KEY, extraClasspath); if (configurationKind == ALL || configurationKind == JDK_AND_ANNOTATIONS) { - configuration.add(ANNOTATIONS_PATH_KEY, getJdkAnnotationsJar()); + if (jdkKind == TestJdkKind.ANDROID_API) { + configuration.add(ANNOTATIONS_PATH_KEY, getAndroidSdkAnnotationsJar()); + } else { + configuration.add(ANNOTATIONS_PATH_KEY, getJdkAnnotationsJar()); + } } return configuration; diff --git a/compiler/tests/org/jetbrains/jet/TestJdkKind.java b/compiler/tests/org/jetbrains/jet/TestJdkKind.java index dc9f15d047e..f2997a1c925 100644 --- a/compiler/tests/org/jetbrains/jet/TestJdkKind.java +++ b/compiler/tests/org/jetbrains/jet/TestJdkKind.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2013 JetBrains s.r.o. + * Copyright 2010-2014 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. @@ -19,4 +19,5 @@ package org.jetbrains.jet; public enum TestJdkKind { MOCK_JDK, FULL_JDK, + ANDROID_API, } diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractSdkAnnotationsValidityTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractSdkAnnotationsValidityTest.java new file mode 100644 index 00000000000..73c381a5be2 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractSdkAnnotationsValidityTest.java @@ -0,0 +1,164 @@ +/* + * Copyright 2010-2014 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.jvm.compiler; + +import com.google.common.collect.Maps; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.util.Disposer; +import com.intellij.testFramework.UsefulTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver; +import org.jetbrains.jet.di.InjectorForJavaDescriptorResolverUtil; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.java.JavaBindingContext; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.kotlinSignature.TypeTransformingVisitor; +import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.renderer.DescriptorRenderer; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +public abstract class AbstractSdkAnnotationsValidityTest extends UsefulTestCase { + + private static final int CLASSES_IN_CHUNK = 100; + + protected abstract JetCoreEnvironment createEnvironment(Disposable parentDisposable); + + protected abstract List getClassesToValidate() throws IOException; + + @Override + protected void setUp() throws Exception { + super.setUp(); + TypeTransformingVisitor.setStrictMode(true); + } + + @Override + protected void tearDown() throws Exception { + TypeTransformingVisitor.setStrictMode(false); + super.tearDown(); + } + + public void testNoErrorsInAlternativeSignatures() throws IOException { + List affectedClasses = getClassesToValidate(); + + Map> errors = Maps.newLinkedHashMap(); + + for (int chunkIndex = 0; chunkIndex < affectedClasses.size() / CLASSES_IN_CHUNK + 1; chunkIndex++) { + Disposable parentDisposable = Disposer.newDisposable(); + + try { + JetCoreEnvironment commonEnvironment = createEnvironment(parentDisposable); + + BindingTrace trace = new BindingTraceContext(); + InjectorForJavaDescriptorResolver injector = + InjectorForJavaDescriptorResolverUtil.create(commonEnvironment.getProject(), trace); + + BindingContext bindingContext = trace.getBindingContext(); + JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); + + AlternativeSignatureErrorFindingVisitor visitor = new AlternativeSignatureErrorFindingVisitor(bindingContext, errors); + + int chunkStart = chunkIndex * CLASSES_IN_CHUNK; + for (FqName javaClass : affectedClasses.subList(chunkStart, Math.min(chunkStart + CLASSES_IN_CHUNK, affectedClasses.size()))) { + ClassDescriptor topLevelClass = javaDescriptorResolver.resolveClass(javaClass); + PackageViewDescriptor topLevelPackage = injector.getModule().getPackage(javaClass); + if (topLevelClass == null) { + continue; + } + + topLevelClass.acceptVoid(visitor); + + if (topLevelPackage != null) { + topLevelPackage.acceptVoid(visitor); + } + } + } + finally { + Disposer.dispose(parentDisposable); + } + } + + + if (!errors.isEmpty()) { + StringBuilder sb = new StringBuilder("Error(s) in SDK alternative signatures: \n"); + for (Map.Entry> entry : errors.entrySet()) { + sb.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n"); + } + fail(sb.toString()); + } + } + + private static class AlternativeSignatureErrorFindingVisitor extends DeclarationDescriptorVisitorEmptyBodies { + private final BindingContext bindingContext; + private final Map> errors; + + public AlternativeSignatureErrorFindingVisitor(BindingContext bindingContext, Map> errors) { + this.bindingContext = bindingContext; + this.errors = errors; + } + + @Override + public Void visitPackageViewDescriptor(PackageViewDescriptor descriptor, Void data) { + return visitDeclarationRecursively(descriptor, descriptor.getMemberScope()); + } + + @Override + public Void visitClassDescriptor(ClassDescriptor descriptor, Void data) { + // skip java.util.Collection, etc. + if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(DescriptorUtils.getFqNameSafe(descriptor)).isEmpty()) { + return null; + } + + return visitDeclarationRecursively(descriptor, descriptor.getDefaultType().getMemberScope()); + } + + @Override + public Void visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) { + return visitDeclaration(descriptor); + } + + @Override + public Void visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) { + return visitDeclaration(descriptor); + } + + private Void visitDeclaration(@NotNull DeclarationDescriptor descriptor) { + List errors = bindingContext.get(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, descriptor); + if (errors != null) { + this.errors.put(DescriptorRenderer.TEXT.render(descriptor), errors); + } + return null; + } + + private Void visitDeclarationRecursively(@NotNull DeclarationDescriptor descriptor, @NotNull JetScope memberScope) { + for (DeclarationDescriptor member : memberScope.getAllDescriptors()) { + member.acceptVoid(this); + } + return visitDeclaration(descriptor); + } + } +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/AndroidSdkAnnotationsValidityTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/AndroidSdkAnnotationsValidityTest.java new file mode 100644 index 00000000000..33ae4367c58 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/AndroidSdkAnnotationsValidityTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2014 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.jvm.compiler; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.intellij.openapi.Disposable; +import org.jetbrains.jet.ConfigurationKind; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.TestJdkKind; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; +import org.jetbrains.jet.config.CompilerConfiguration; +import org.jetbrains.jet.lang.resolve.name.FqName; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class AndroidSdkAnnotationsValidityTest extends AbstractSdkAnnotationsValidityTest { + + @Override + protected JetCoreEnvironment createEnvironment(Disposable parentDisposable) { + CompilerConfiguration configuration = JetTestUtils.compilerConfigurationForTests( + ConfigurationKind.JDK_AND_ANNOTATIONS, TestJdkKind.ANDROID_API, JetTestUtils.getAnnotationsJar()); + return JetCoreEnvironment.createForTests(parentDisposable, configuration); + } + + @Override + protected List getClassesToValidate() throws IOException { + JarFile jar = new JarFile(JetTestUtils.findAndroidApiJar()); + try { + Enumeration entries = jar.entries(); + Set result = Sets.newLinkedHashSet(); + while (entries.hasMoreElements()){ + JarEntry entry = entries.nextElement(); + String entryName = entry.getName(); + if (!entry.isDirectory() && entryName.endsWith(".class")) { + String className = entryName.substring(0, entryName.length() - ".class".length()).replace("/", ".").replace("$", "."); + result.add(new FqName(className)); + } + } + return Lists.newArrayList(result); + } finally { + jar.close(); + } + } + +} diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/JdkAnnotationsValidityTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/JdkAnnotationsValidityTest.java index ad109c6392f..51c2d31707e 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/JdkAnnotationsValidityTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/JdkAnnotationsValidityTest.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.jvm.compiler; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.codeInsight.ExternalAnnotationsManager; import com.intellij.openapi.Disposable; @@ -27,7 +26,6 @@ import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileVisitor; -import com.intellij.testFramework.UsefulTestCase; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.JetTestUtils; @@ -35,31 +33,18 @@ import org.jetbrains.jet.TestJdkKind; import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.config.CompilerConfiguration; -import org.jetbrains.jet.di.InjectorForJavaDescriptorResolver; -import org.jetbrains.jet.di.InjectorForJavaDescriptorResolverUtil; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.BindingTraceContext; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.resolve.java.JavaBindingContext; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; -import org.jetbrains.jet.lang.resolve.java.kotlinSignature.TypeTransformingVisitor; -import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap; import org.jetbrains.jet.lang.resolve.name.FqName; -import org.jetbrains.jet.lang.resolve.scopes.JetScope; -import org.jetbrains.jet.renderer.DescriptorRenderer; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; -public class JdkAnnotationsValidityTest extends UsefulTestCase { - - private static final int CLASSES_IN_CHUNK = 500; +public class JdkAnnotationsValidityTest extends AbstractSdkAnnotationsValidityTest { // KT-4359 Alternative signature checking problem: Set is incompatible with Set // @@ -81,7 +66,7 @@ public class JdkAnnotationsValidityTest extends UsefulTestCase { // [Incompatible types in superclasses: [Any?, Any, Any], Incompatible projection kinds in type arguments of super methods' return types: [out Any?, Any, Any]] private static final Set classesToIgnore = new HashSet(Arrays.asList("javax.management.openmbean.TabularDataSupport")); - private static JetCoreEnvironment createEnvironment(Disposable parentDisposable) { + private static JetCoreEnvironment createFullJdkEnvironment(Disposable parentDisposable) { CompilerConfiguration configuration = JetTestUtils.compilerConfigurationForTests( ConfigurationKind.JDK_AND_ANNOTATIONS, TestJdkKind.FULL_JDK, JetTestUtils.getAnnotationsJar()); configuration.add(JVMConfigurationKeys.ANNOTATIONS_PATH_KEY, new File("ideaSDK/lib/jdkAnnotations.jar")); @@ -89,72 +74,20 @@ public class JdkAnnotationsValidityTest extends UsefulTestCase { } @Override - protected void setUp() throws Exception { - super.setUp(); - TypeTransformingVisitor.setStrictMode(true); + protected JetCoreEnvironment createEnvironment(Disposable parentDisposable) { + return createFullJdkEnvironment(parentDisposable); } @Override - protected void tearDown() throws Exception { - TypeTransformingVisitor.setStrictMode(false); - super.tearDown(); - } - - public void testNoErrorsInAlternativeSignatures() { - List affectedClasses = getAffectedClasses("jar://dependencies/annotations/kotlin-jdk-annotations.jar!/"); - - Map> errors = Maps.newLinkedHashMap(); - - for (int chunkIndex = 0; chunkIndex < affectedClasses.size() / CLASSES_IN_CHUNK + 1; chunkIndex++) { - Disposable parentDisposable = Disposer.newDisposable(); - - try { - JetCoreEnvironment commonEnvironment = createEnvironment(parentDisposable); - - BindingTrace trace = new BindingTraceContext(); - InjectorForJavaDescriptorResolver injector = - InjectorForJavaDescriptorResolverUtil.create(commonEnvironment.getProject(), trace); - - BindingContext bindingContext = trace.getBindingContext(); - JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver(); - - AlternativeSignatureErrorFindingVisitor visitor = new AlternativeSignatureErrorFindingVisitor(bindingContext, errors); - - int chunkStart = chunkIndex * CLASSES_IN_CHUNK; - for (FqName javaClass : affectedClasses.subList(chunkStart, Math.min(chunkStart + CLASSES_IN_CHUNK, affectedClasses.size()))) { - ClassDescriptor topLevelClass = javaDescriptorResolver.resolveClass(javaClass); - PackageViewDescriptor topLevelPackage = injector.getModule().getPackage(javaClass); - if (topLevelClass == null) { - continue; - } - - topLevelClass.acceptVoid(visitor); - - if (topLevelPackage != null) { - topLevelPackage.acceptVoid(visitor); - } - } - } - finally { - Disposer.dispose(parentDisposable); - } - } - - - if (!errors.isEmpty()) { - StringBuilder sb = new StringBuilder("Error(s) in JDK alternative signatures: \n"); - for (Map.Entry> entry : errors.entrySet()) { - sb.append(entry.getKey()).append(" : ").append(entry.getValue()).append("\n"); - } - fail(sb.toString()); - } + protected List getClassesToValidate() throws IOException { + return getAffectedClasses("jar://dependencies/annotations/kotlin-jdk-annotations.jar!/"); } static List getAffectedClasses(String rootUrl) { Disposable myDisposable = Disposer.newDisposable(); try { - createEnvironment(myDisposable); + createFullJdkEnvironment(myDisposable); VirtualFile root = VirtualFileManager.getInstance().findFileByUrl(rootUrl); assert root != null; @@ -189,58 +122,4 @@ public class JdkAnnotationsValidityTest extends UsefulTestCase { } } - - private static class AlternativeSignatureErrorFindingVisitor extends DeclarationDescriptorVisitorEmptyBodies { - private final BindingContext bindingContext; - private final Map> errors; - - public AlternativeSignatureErrorFindingVisitor(BindingContext bindingContext, Map> errors) { - this.bindingContext = bindingContext; - this.errors = errors; - } - - @Override - public Void visitPackageViewDescriptor(PackageViewDescriptor descriptor, Void data) { - return visitDeclarationRecursively(descriptor, descriptor.getMemberScope()); - } - - @Override - public Void visitClassDescriptor(ClassDescriptor descriptor, Void data) { - // skip java.util.Collection, etc. - if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(DescriptorUtils.getFqNameSafe(descriptor)).isEmpty()) { - return null; - } - - return visitDeclarationRecursively(descriptor, descriptor.getDefaultType().getMemberScope()); - } - - @Override - public Void visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) { - return visitDeclaration(descriptor); - } - - @Override - public Void visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) { - return visitDeclaration(descriptor); - } - - private Void visitDeclaration(@NotNull DeclarationDescriptor descriptor) { - List errors = bindingContext.get(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, descriptor); - if (errors != null) { - this.errors.put(DescriptorRenderer.TEXT.render(descriptor), errors); - } - return null; - } - - private Void visitDeclarationRecursively(@NotNull DeclarationDescriptor descriptor, @NotNull JetScope memberScope) { - for (DeclarationDescriptor member : memberScope.getAllDescriptors()) { - if (member instanceof DeclarationDescriptorWithVisibility - && ((DeclarationDescriptorWithVisibility) member).getVisibility().isPublicAPI()) { - member.acceptVoid(this); - } - } - - return visitDeclaration(descriptor); - } - } } diff --git a/update_dependencies.xml b/update_dependencies.xml index fe22d6c286d..27f81537f18 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -187,6 +187,16 @@ + + + + + + + + +