@@ -3,6 +3,11 @@ package org.javacs.kt.resolve
3
3
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
4
4
import org.jetbrains.kotlin.psi.KtFile
5
5
import org.jetbrains.kotlin.psi.KtNamedFunction
6
+ import org.jetbrains.kotlin.psi.KtClass
7
+ import org.jetbrains.kotlin.psi.KtObjectDeclaration
8
+ import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
9
+ import org.jetbrains.kotlin.psi.KtClassOrObject
10
+ import org.jetbrains.kotlin.container.topologicalSort
6
11
import org.javacs.kt.CompiledFile
7
12
import org.javacs.kt.LOG
8
13
import org.javacs.kt.position.range
@@ -11,9 +16,8 @@ import com.intellij.openapi.util.TextRange
11
16
12
17
13
18
fun resolveMain (file : CompiledFile ): Map <String ,Any > {
14
- LOG .info(" Resolving main function! yay" )
15
-
16
19
val parsedFile = file.parse.copy() as KtFile
20
+
17
21
val mainFunction = findTopLevelMainFunction(parsedFile)
18
22
if (null != mainFunction) {
19
23
// the KtFiles name is weird. Full path. This causes the class to have full path in name as well. Correcting to top level only
@@ -22,6 +26,15 @@ fun resolveMain(file: CompiledFile): Map<String,Any> {
22
26
return mapOf (" mainClass" to JvmFileClassUtil .getFileClassInfoNoResolve(parsedFile).facadeClassFqName.asString(),
23
27
" range" to range(file.content, mainFunction.second))
24
28
}
29
+
30
+ val companionMain = findCompanionObjectMain(parsedFile)
31
+ if (null != companionMain) {
32
+ // TODO: any way we should handle the jvmname stuff here?
33
+ return mapOf (
34
+ " mainClass" to (companionMain.first ? : " " ),
35
+ " range" to range(file.content, companionMain.second)
36
+ )
37
+ }
25
38
26
39
return emptyMap()
27
40
}
@@ -31,6 +44,30 @@ private fun findTopLevelMainFunction(file: KtFile): Pair<String?, TextRange>? =
31
44
// TODO: any validations on arguments
32
45
it is KtNamedFunction && " main" == it.name
33
46
}?.let {
34
- // TODO: any better things to return?
35
47
Pair (it.name, it.textRangeInParent)
36
48
}
49
+
50
+ // TODO: can this and the previous be merged in any way? or is this approach the cleanest?
51
+ // finds a top level class that contains a companion object with a main function inside
52
+ private fun findCompanionObjectMain (file : KtFile ): Pair <String ?, TextRange >? = file.declarations.flatMap { topLevelDeclaration ->
53
+ if (topLevelDeclaration is KtClass ) {
54
+ topLevelDeclaration.companionObjects
55
+ } else {
56
+ emptyList<KtObjectDeclaration >()
57
+ }
58
+ }.flatMap { companionObject ->
59
+ companionObject.body?.children?.toList() ? : emptyList()
60
+ }.mapNotNull { companionObjectInternal ->
61
+ if (companionObjectInternal is KtNamedFunction && " main" == companionObjectInternal.name) { // && companionObjectInternal.annotations.any {
62
+ // LOG.info("Annotation!! {}", it.name)
63
+ // "JvmStatic" == it.name
64
+ // }
65
+ companionObjectInternal
66
+ } else {
67
+ null
68
+ }
69
+ }.firstOrNull()?.let {
70
+ // a little ugly, but because of success of the above, we know that "it" has 4 layers of parent objects (child of companion object body, companion object body, companion object, outer class)
71
+ // TODO: should we correct textRange start line manually? includes the JvmStatic annotation if present..
72
+ Pair ((it.parent.parent.parent.parent as KtClass ).fqName?.toString(), it.textRange)
73
+ }
0 commit comments