fix KT-10064 Regression: Error with multiple main functions within a single package

#KT-10064 Fixed
This commit is contained in:
Michael Nedzelsky
2015-11-19 02:19:57 +03:00
parent 49f0953898
commit aa8f3df9a8
9 changed files with 48 additions and 24 deletions
@@ -80,13 +80,19 @@ public class MainFunctionDetector {
return false; return false;
} }
FunctionDescriptor functionDescriptor = getFunctionDescriptor.fun(function); return isMain(getFunctionDescriptor.fun(function));
}
public static boolean isMain(@NotNull DeclarationDescriptor descriptor) {
if (!(descriptor instanceof FunctionDescriptor)) return false;
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
if (!getJVMFunctionName(functionDescriptor).equals("main")) { if (!getJVMFunctionName(functionDescriptor).equals("main")) {
return false; return false;
} }
List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters(); List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
if (parameters.size() != 1) return false; if (parameters.size() != 1 || !functionDescriptor.getTypeParameters().isEmpty()) return false;
ValueParameterDescriptor parameter = parameters.get(0); ValueParameterDescriptor parameter = parameters.get(0);
KotlinType parameterType = parameter.getType(); KotlinType parameterType = parameter.getType();
@@ -17,16 +17,17 @@
package org.jetbrains.kotlin.resolve package org.jetbrains.kotlin.resolve
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.psi.KtAnnotationEntry import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.resolve.source.getPsi
import java.util.ArrayList import java.util.*
public object DescriptorToSourceUtils { public object DescriptorToSourceUtils {
private fun collectEffectiveReferencedDescriptors(result: MutableList<DeclarationDescriptor>, descriptor: DeclarationDescriptor) { private fun collectEffectiveReferencedDescriptors(result: MutableList<DeclarationDescriptor>, descriptor: DeclarationDescriptor) {
@@ -80,16 +81,6 @@ public object DescriptorToSourceUtils {
return declaration.getContainingFile() as? KtFile return declaration.getContainingFile() as? KtFile
} }
@JvmStatic
public fun isTopLevelMainFunction(declarationDescriptor: DeclarationDescriptor, mainFunctionDetector: MainFunctionDetector): Boolean {
if (declarationDescriptor !is FunctionDescriptor ||
!DescriptorUtils.isTopLevelDeclaration(declarationDescriptor) ||
declarationDescriptor.name.asString() != "main") return false
val element = descriptorToDeclaration(declarationDescriptor)
return element is KtNamedFunction && mainFunctionDetector.isMain(element)
}
private fun findTopLevelParent(declarationDescriptor: DeclarationDescriptor): DeclarationDescriptor? { private fun findTopLevelParent(declarationDescriptor: DeclarationDescriptor): DeclarationDescriptor? {
var descriptor: DeclarationDescriptor? = declarationDescriptor var descriptor: DeclarationDescriptor? = declarationDescriptor
if (declarationDescriptor is PropertyAccessorDescriptor) { if (declarationDescriptor is PropertyAccessorDescriptor) {
@@ -36,7 +36,6 @@ import static org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName;
public class OverloadResolver { public class OverloadResolver {
@NotNull private final BindingTrace trace; @NotNull private final BindingTrace trace;
@NotNull private final OverloadFilter overloadFilter; @NotNull private final OverloadFilter overloadFilter;
@NotNull private final MainFunctionDetector mainFunctionDetector;
public OverloadResolver( public OverloadResolver(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@@ -44,8 +43,6 @@ public class OverloadResolver {
) { ) {
this.trace = trace; this.trace = trace;
this.overloadFilter = overloadFilter; this.overloadFilter = overloadFilter;
mainFunctionDetector = new MainFunctionDetector(trace.getBindingContext());
} }
public void process(@NotNull BodiesResolveContext c) { public void process(@NotNull BodiesResolveContext c) {
@@ -160,7 +157,7 @@ public class OverloadResolver {
} }
@NotNull @NotNull
private Set<Pair<KtDeclaration, CallableMemberDescriptor>> findRedeclarations(@NotNull Collection<? extends CallableMemberDescriptor> members) { private static Set<Pair<KtDeclaration, CallableMemberDescriptor>> findRedeclarations(@NotNull Collection<? extends CallableMemberDescriptor> members) {
Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations = Sets.newLinkedHashSet(); Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations = Sets.newLinkedHashSet();
for (CallableMemberDescriptor member : members) { for (CallableMemberDescriptor member : members) {
for (CallableMemberDescriptor member2 : members) { for (CallableMemberDescriptor member2 : members) {
@@ -195,13 +192,15 @@ public class OverloadResolver {
member.getContainingDeclaration().getContainingDeclaration().equals(member2.getContainingDeclaration().getContainingDeclaration()); member.getContainingDeclaration().getContainingDeclaration().equals(member2.getContainingDeclaration().getContainingDeclaration());
} }
private boolean isTopLevelMainInDifferentFiles(@NotNull CallableMemberDescriptor member, @NotNull CallableMemberDescriptor member2) { private static boolean isTopLevelMainInDifferentFiles(@NotNull CallableMemberDescriptor member, @NotNull CallableMemberDescriptor member2) {
if (!DescriptorToSourceUtils.isTopLevelMainFunction(member, mainFunctionDetector) || if (!MainFunctionDetector.isMain(member) ||
!DescriptorToSourceUtils.isTopLevelMainFunction(member2, mainFunctionDetector)) { !MainFunctionDetector.isMain(member2)) {
return false; return false;
} }
return DescriptorToSourceUtils.getContainingFile(member) != DescriptorToSourceUtils.getContainingFile(member2); KtFile file = DescriptorToSourceUtils.getContainingFile(member);
KtFile file2 = DescriptorToSourceUtils.getContainingFile(member2);
return file == null || file2 == null || file != file2;
} }
private void reportRedeclarations(@NotNull String functionContainer, private void reportRedeclarations(@NotNull String functionContainer,
@@ -395,6 +395,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
doTest(fileName); doTest(fileName);
} }
@TestMetadata("mainRedeclaration")
public void testMainRedeclaration() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/mainRedeclaration/");
doTest(fileName);
}
@TestMetadata("moveClass") @TestMetadata("moveClass")
public void testMoveClass() throws Exception { public void testMoveClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/moveClass/"); String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/moveClass/");
@@ -395,6 +395,12 @@ public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("mainRedeclaration")
public void testMainRedeclaration() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/mainRedeclaration/");
doTest(fileName);
}
@TestMetadata("moveClass") @TestMetadata("moveClass")
public void testMoveClass() throws Exception { public void testMoveClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/moveClass/"); String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/pureKotlin/moveClass/");
@@ -0,0 +1,3 @@
package foo
fun main(args: Array<String>) = println("a")
@@ -0,0 +1,3 @@
package foo
fun main(args: Array<String>) = println("A")
@@ -0,0 +1,3 @@
package foo
fun main(args: Array<String>) = println("b")
@@ -0,0 +1,7 @@
Cleaning output files:
out/production/module/META-INF/module.kotlin_module
out/production/module/foo/AKt.class
End of files
Compiling files:
src/a.kt
End of files