diff --git a/compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/duplicateObjectInBinaryAndSources.kt b/compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/duplicateObjectInBinaryAndSources.kt new file mode 100644 index 00000000000..0159dca051f --- /dev/null +++ b/compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/duplicateObjectInBinaryAndSources.kt @@ -0,0 +1,10 @@ +package test + +public object Lol { + fun c() { + + } +} + + + diff --git a/compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/objectBinaries.jar b/compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/objectBinaries.jar new file mode 100644 index 00000000000..afff7f23872 Binary files /dev/null and b/compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/objectBinaries.jar differ diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.java index a16320c1873..2472064108f 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/AbstractCompileKotlinAgainstCustomBinariesTest.java @@ -54,19 +54,12 @@ public abstract class AbstractCompileKotlinAgainstCustomBinariesTest extends Tes File ktFile = new File(ktFilePath); String testFileWithoutExtension = FileUtil.getNameWithoutExtension(ktFile); - checkCompiledNamespace(ktFile, LoadDescriptorUtil.TEST_PACKAGE_FQNAME, - new File(ktFile.getParentFile(), testFileWithoutExtension + ".txt")); + checkNamespace(ktFile, LoadDescriptorUtil.TEST_PACKAGE_FQNAME, + new File(ktFile.getParentFile(), testFileWithoutExtension + ".txt")); } - private void checkCompiledNamespace(File ktFile, FqName namespaceFqn, File expectedFile) throws IOException { - JetCoreEnvironment environment = getEnvironment(ktFile); - Project project = environment.getProject(); - - List jetFiles = Collections.singletonList(JetTestUtils.loadJetFile(project, ktFile)); - - BindingContext bindingContext = AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( - project, jetFiles, Collections.emptyList(), - Predicates.alwaysTrue()).getBindingContext(); + private void checkNamespace(File ktFile, FqName namespaceFqn, File expectedFile) throws IOException { + BindingContext bindingContext = analyzeFile(ktFile); NamespaceDescriptor namespaceDescriptor = bindingContext.get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, namespaceFqn); assertNotNull("Failed to find namespace: " + namespaceFqn, namespaceDescriptor); @@ -75,6 +68,17 @@ public abstract class AbstractCompileKotlinAgainstCustomBinariesTest extends Tes DescriptorValidator.ValidationVisitor.ALLOW_ERROR_TYPES), expectedFile); } + protected BindingContext analyzeFile(File ktFile) throws IOException { + JetCoreEnvironment environment = getEnvironment(ktFile); + Project project = environment.getProject(); + + List jetFiles = Collections.singletonList(JetTestUtils.loadJetFile(project, ktFile)); + + return AnalyzerFacadeForJVM.analyzeFilesWithJavaIntegration( + project, jetFiles, Collections.emptyList(), + Predicates.alwaysTrue()).getBindingContext(); + } + private JetCoreEnvironment getEnvironment(File ktFile) { File dir = ktFile.getParentFile(); diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstBinariesCustomTest.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstBinariesCustomTest.java new file mode 100644 index 00000000000..2d3692db6fd --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/CompileKotlinAgainstBinariesCustomTest.java @@ -0,0 +1,46 @@ +/* + * 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.jvm.compiler; + +import junit.framework.Assert; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptorForObject; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.types.ErrorUtils; + +import java.io.File; +import java.util.Collection; + +import static org.jetbrains.jet.jvm.compiler.LoadDescriptorUtil.TEST_PACKAGE_FQNAME; +import static org.jetbrains.jet.lang.resolve.BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR; + +public final class CompileKotlinAgainstBinariesCustomTest extends AbstractCompileKotlinAgainstCustomBinariesTest { + + public void testDuplicateObjectInSourcesAndBinaries() throws Exception { + BindingContext context = analyzeFile(new File( + "compiler/testData/compileKotlinAgainstBinariesCustom/duplicateObjectInBinaryAndSources/duplicateObjectInBinaryAndSources.kt")); + NamespaceDescriptor namespaceDescriptor = context.get(FQNAME_TO_NAMESPACE_DESCRIPTOR, TEST_PACKAGE_FQNAME); + assert namespaceDescriptor != null; + Collection allDescriptors = namespaceDescriptor.getMemberScope().getAllDescriptors(); + Assert.assertEquals(allDescriptors.size(), 2); + for (DeclarationDescriptor descriptor : allDescriptors) { + Assert.assertTrue(descriptor.getName().asString().equals("Lol")); + Assert.assertTrue(descriptor instanceof VariableDescriptorForObject); + Assert.assertFalse("Object property should have valid class", ErrorUtils.isError(((VariableDescriptorForObject) descriptor).getObjectClass())); + } + } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorSearchRule.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorSearchRule.java index 3611d9b86ec..763c8a5c4dd 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorSearchRule.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorSearchRule.java @@ -16,21 +16,18 @@ package org.jetbrains.jet.lang.resolve.java; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; - +/* +* This class indicates whether we should look into kotlin sources when searching for descriptors in JavaDescriptorResolver. +* This is a hack because it should be done via correct scopes. +* Order in which we attempt to resolve descriptors is also should be taken care of. (though it is correct for the most part now) +* */ public enum DescriptorSearchRule { - INCLUDE_KOTLIN_SOURCES { - @Override - public T processFoundInKotlin(T foundDescriptor) { - return foundDescriptor; - } - }, - IGNORE_KOTLIN_SOURCES { - @Override - public T processFoundInKotlin(T foundDescriptor) { - return null; - } - }; - - public abstract T processFoundInKotlin(T foundDescriptor); + //Return immediately if you found descriptor in kotlin sources, if not continue + INCLUDE_KOTLIN_SOURCES, + //Do not try to find descriptors in kotlin sources. + //This flag is mostly used when resolving descriptors from binaries or java descriptors. + //It will not prevent from looking into java sources which is often desirable behaviour. + //It is not correct because sometimes class from sources can override class from binary since it comes earlier in classpath + //and for a thousand more reasons. + IGNORE_KOTLIN_SOURCES } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java index 95573ec7fed..fc287dff91b 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java @@ -149,9 +149,11 @@ public final class JavaClassResolver { return builtinClassDescriptor; } - ClassDescriptor kotlinClassDescriptor = cache.getClassResolvedFromSource(qualifiedName); - if (kotlinClassDescriptor != null) { - return searchRule.processFoundInKotlin(kotlinClassDescriptor); + if (searchRule == INCLUDE_KOTLIN_SOURCES) { + ClassDescriptor kotlinClassDescriptor = cache.getClassResolvedFromSource(qualifiedName); + if (kotlinClassDescriptor != null) { + return kotlinClassDescriptor; + } } FqNameUnsafe fqName = javaClassToKotlinFqName(qualifiedName); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java index cf9863076d3..b34445215f3 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java @@ -90,10 +90,11 @@ public final class JavaNamespaceResolver { @Nullable public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName, @NotNull DescriptorSearchRule searchRule) { - // First, let's check that there is no Kotlin package: - NamespaceDescriptor kotlinNamespaceDescriptor = cache.getPackageResolvedFromSource(qualifiedName); - if (kotlinNamespaceDescriptor != null) { - return searchRule.processFoundInKotlin(kotlinNamespaceDescriptor); + if (searchRule == INCLUDE_KOTLIN_SOURCES) { + NamespaceDescriptor kotlinNamespaceDescriptor = cache.getPackageResolvedFromSource(qualifiedName); + if (kotlinNamespaceDescriptor != null) { + return kotlinNamespaceDescriptor; + } } if (unresolvedCache.contains(qualifiedName)) {