JavacWrapper: add support for JvmPackageName annotation

This fixes previously added testWithStdLib/streams.kt test
This commit is contained in:
Mikhail Glukhikh
2019-09-10 17:17:22 +03:00
parent e8cf0b5d4f
commit bbd8fb8b23
6 changed files with 132 additions and 51 deletions
@@ -319,7 +319,7 @@ class KotlinCoreEnvironment private constructor(
): Boolean {
return JavacWrapperRegistrar.registerJavac(
projectEnvironment.project, configuration, javaFiles, kotlinFiles, arguments, bootClasspath, sourcePath,
LightClassGenerationSupport.getInstance(project)
LightClassGenerationSupport.getInstance(project), packagePartProviders
)
}
@@ -21,6 +21,7 @@ import com.sun.tools.javac.util.Context
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -39,7 +40,8 @@ object JavacWrapperRegistrar {
arguments: Array<String>?,
bootClasspath: List<File>?,
sourcePath: List<File>?,
lightClassGenerationSupport: LightClassGenerationSupport
lightClassGenerationSupport: LightClassGenerationSupport,
packagePartsProviders: List<JvmPackagePartProvider>
): Boolean {
val messageCollector = configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
@@ -60,7 +62,7 @@ object JavacWrapperRegistrar {
val javacWrapper = JavacWrapper(
javaFiles, kotlinFiles, arguments, jvmClasspathRoots, bootClasspath, sourcePath,
kotlinSupertypesResolver, compileJava, outputDirectory, context
kotlinSupertypesResolver, packagePartsProviders, compileJava, outputDirectory, context
)
project.registerService(JavacWrapper::class.java, javacWrapper)
@@ -37,13 +37,12 @@ import com.sun.tools.javac.util.Context
import com.sun.tools.javac.util.Log
import com.sun.tools.javac.util.Names
import com.sun.tools.javac.util.Options
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.javac.resolve.ClassifierResolver
import org.jetbrains.kotlin.javac.resolve.IdentifierResolver
import org.jetbrains.kotlin.javac.resolve.KotlinClassifiersCache
import org.jetbrains.kotlin.javac.resolve.classId
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedClass
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedClassifierType
import org.jetbrains.kotlin.javac.wrappers.symbols.SymbolBasedPackage
import org.jetbrains.kotlin.javac.wrappers.symbols.*
import org.jetbrains.kotlin.javac.wrappers.trees.*
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.*
@@ -65,6 +64,7 @@ class JavacWrapper(
bootClasspath: List<File>?,
sourcePath: List<File>?,
val kotlinResolver: JavacWrapperKotlinResolver,
private val packagePartsProviders: List<JvmPackagePartProvider>,
private val compileJava: Boolean,
private val outputDirectory: File?,
private val context: Context
@@ -229,7 +229,7 @@ class JavacWrapper(
fun findSubPackages(fqName: FqName): List<JavaPackage> =
symbols.packages
.filterKeys { it.toString().startsWith("$fqName.") }
.map { SymbolBasedPackage(it.value, this) } +
.map { SimpleSymbolBasedPackage(it.value, this) } +
javaPackages
.filterKeys { it.isSubpackageOf(fqName) && it != fqName }
.map { it.value }
@@ -301,12 +301,39 @@ class JavacWrapper(
private fun findPackageInSymbols(fqName: String): SymbolBasedPackage? {
if (symbolBasedPackagesCache.containsKey(fqName)) return symbolBasedPackagesCache[fqName]
elements.getPackageElement(fqName)?.let { symbol ->
SymbolBasedPackage(symbol, this)
}.let { symbolBasedPackage ->
fun findSimplePackageInSymbols(fqName: String): SimpleSymbolBasedPackage? {
elements.getPackageElement(fqName)?.let { symbol ->
SimpleSymbolBasedPackage(symbol, this)
}.let { symbolBasedPackage ->
symbolBasedPackagesCache[fqName] = symbolBasedPackage
return symbolBasedPackage
}
}
val mappedPackages = mutableListOf<SimpleSymbolBasedPackage>()
for (provider in packagePartsProviders) {
val jvmPackageNames = provider.findPackageParts(fqName)
.map { it.substringBeforeLast("/").replace('/', '.') }.filter { it != fqName }.distinct()
// TODO: check situation with multiple package parts like this (search by FQ name of 'p1')
// FILE: foo.kt
// @file:JvmPackageName("aaa")
// package p1
// fun foo() {}
// ------------
// FILE: bar.kt
// package aaa
// fun bar() {}
mappedPackages += jvmPackageNames.mapNotNull { jvmPackageName ->
findSimplePackageInSymbols(jvmPackageName)
}
}
if (mappedPackages.isNotEmpty()) {
val symbolBasedPackage = MappedSymbolBasedPackage(FqName(fqName), mappedPackages, this)
symbolBasedPackagesCache[fqName] = symbolBasedPackage
return symbolBasedPackage
}
return findSimplePackageInSymbols(fqName)
}
private fun JavacFileManager.setClassPathForCompilation(outDir: File?) = apply {
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.PackageElement
// Useful only for packages with JvmPackageName annotation
class MappedSymbolBasedPackage(
private val originalFqName: FqName,
private val childrenPackages: List<SimpleSymbolBasedPackage>,
javac: JavacWrapper
) : SymbolBasedElement<PackageElement>(childrenPackages.first().element, javac), SymbolBasedPackage {
override val fqName: FqName
get() = originalFqName
override val subPackages: Collection<JavaPackage>
get() = childrenPackages.flatMap { javac.findSubPackages(it.fqName) }
override val annotations: Collection<JavaAnnotation>
get() = childrenPackages.map { childrenPackage ->
childrenPackage.element.annotationMirrors.map { annotationMirror -> SymbolBasedAnnotation(annotationMirror, javac) }
}.flatten()
override val annotationsByFqName: Map<FqName?, JavaAnnotation> by buildLazyValueForMap()
// @JvmPackageName-annotated files cannot have classes
override fun getClasses(nameFilter: (Name) -> Boolean): List<JavaClass> = emptyList()
override fun toString() = originalFqName.toString()
}
@@ -0,0 +1,49 @@
/*
* Copyright 2010-2017 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.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.load.java.structure.buildLazyValueForMap
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.PackageElement
class SimpleSymbolBasedPackage(
element: PackageElement,
javac: JavacWrapper
) : SymbolBasedElement<PackageElement>(element, javac), SymbolBasedPackage {
override val fqName: FqName
get() = FqName(element.qualifiedName.toString())
override val subPackages: Collection<JavaPackage>
get() = javac.findSubPackages(fqName)
override val annotations: Collection<JavaAnnotation>
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
override val annotationsByFqName: Map<FqName?, JavaAnnotation> by buildLazyValueForMap()
override fun getClasses(nameFilter: (Name) -> Boolean) =
javac.findClassesFromPackage(fqName).filter { nameFilter(it.name) }
override fun toString() = element.qualifiedName.toString()
}
@@ -1,50 +1,14 @@
/*
* Copyright 2010-2017 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.
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.javac.wrappers.symbols
import org.jetbrains.kotlin.javac.JavacWrapper
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation
import org.jetbrains.kotlin.load.java.structure.JavaPackage
import org.jetbrains.kotlin.load.java.structure.MapBasedJavaAnnotationOwner
import org.jetbrains.kotlin.load.java.structure.buildLazyValueForMap
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import javax.lang.model.element.PackageElement
class SymbolBasedPackage(
element: PackageElement,
javac: JavacWrapper
) : SymbolBasedElement<PackageElement>(element, javac), JavaPackage, MapBasedJavaAnnotationOwner {
override val fqName: FqName
get() = FqName(element.qualifiedName.toString())
override val subPackages: Collection<JavaPackage>
get() = javac.findSubPackages(fqName)
override val annotations: Collection<JavaAnnotation>
get() = element.annotationMirrors.map { SymbolBasedAnnotation(it, javac) }
override val annotationsByFqName: Map<FqName?, JavaAnnotation> by buildLazyValueForMap()
override fun getClasses(nameFilter: (Name) -> Boolean) =
javac.findClassesFromPackage(fqName).filter { nameFilter(it.name) }
override fun toString() = element.qualifiedName.toString()
}
interface SymbolBasedPackage : JavaPackage, MapBasedJavaAnnotationOwner {
val element: PackageElement
}