as31: Misc: Fix compilation

This commit is contained in:
Alexey Sedunov
2017-07-25 16:47:09 +03:00
committed by Nikolay Krasko
parent 8568bde4df
commit a9cdccc6de
8 changed files with 1531 additions and 0 deletions
@@ -0,0 +1,133 @@
/*
* 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.load.java.structure.impl
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiTypeParameter
import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.asJava.KtLightClassMarker
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.load.java.structure.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.psiUtil.contains
class JavaClassImpl(psiClass: PsiClass) : JavaClassifierImpl<PsiClass>(psiClass), VirtualFileBoundJavaClass, JavaAnnotationOwnerImpl, JavaModifierListOwnerImpl {
init {
assert(psiClass !is PsiTypeParameter) { "PsiTypeParameter should be wrapped in JavaTypeParameter, not JavaClass: use JavaClassifier.create()" }
}
override val innerClassNames: Collection<Name>
get() = psi.innerClasses.mapNotNull { it.name?.takeIf(Name::isValidIdentifier)?.let(Name::identifier) }
override fun findInnerClass(name: Name): JavaClass? {
return psi.findInnerClassByName(name.asString(), false)?.let(::JavaClassImpl)
}
override val fqName: FqName?
get() {
val qualifiedName = psi.qualifiedName
return if (qualifiedName == null) null else FqName(qualifiedName)
}
override val name: Name
get() = KtPsiUtil.safeName(psi.name)
override val isInterface: Boolean
get() = psi.isInterface
override val isAnnotationType: Boolean
get() = psi.isAnnotationType
override val isEnum: Boolean
get() = psi.isEnum
override val outerClass: JavaClassImpl?
get() {
val outer = psi.containingClass
return if (outer == null) null else JavaClassImpl(outer)
}
override val typeParameters: List<JavaTypeParameter>
get() = typeParameters(psi.typeParameters)
override val supertypes: Collection<JavaClassifierType>
get() = classifierTypes(psi.superTypes)
override val methods: Collection<JavaMethod>
get() {
assertNotLightClass()
// We apply distinct here because PsiClass#getMethods() can return duplicate PSI methods, for example in Lombok (see KT-11778)
// Return type seems to be null for example for the 'clone' Groovy method generated by @AutoClone (see EA-73795)
return methods(psi.methods.filter { method -> !method.isConstructor && method.returnType != null }).distinct()
}
override val fields: Collection<JavaField>
get() {
assertNotLightClass()
return fields(psi.fields.filter { field ->
val name = field.name
// ex. Android plugin generates LightFields for resources started from '.' (.DS_Store file etc)
name != null && Name.isValidIdentifier(name)
})
}
override val constructors: Collection<JavaConstructor>
get() {
assertNotLightClass()
// See for example org.jetbrains.plugins.scala.lang.psi.light.ScFunctionWrapper,
// which is present in getConstructors(), but its isConstructor() returns false
return constructors(psi.constructors.filter { method -> method.isConstructor })
}
override val isAbstract: Boolean
get() = JavaElementUtil.isAbstract(this)
override val isStatic: Boolean
get() = JavaElementUtil.isStatic(this)
override val isFinal: Boolean
get() = JavaElementUtil.isFinal(this)
override val visibility: Visibility
get() = JavaElementUtil.getVisibility(this)
override val lightClassOriginKind: LightClassOriginKind?
get() = (psi as? KtLightClassMarker)?.originKind
override val virtualFile: VirtualFile?
get() = psi.containingFile?.virtualFile
override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = psi.containingFile in scope
override fun getAnnotationOwnerPsi() = psi.modifierList
private fun assertNotLightClass() {
val psiClass = psi
if (psiClass !is KtLightClassMarker) return
val message = "Querying members of JavaClass created for $psiClass of type ${psiClass::class.java} defined in file ${psiClass.containingFile?.virtualFile?.canonicalPath}"
LOGGER.error(message)
}
companion object {
private val LOGGER = Logger.getInstance(JavaClassImpl::class.java)
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2015 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.load.kotlin
import com.intellij.ide.highlighter.JavaClassFileType
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.util.Computable
import com.intellij.openapi.vfs.VirtualFile
class KotlinBinaryClassCache : Disposable {
private class RequestCache {
internal var virtualFile: VirtualFile? = null
internal var modificationStamp: Long = 0
internal var virtualFileKotlinClass: VirtualFileKotlinClass? = null
fun cache(file: VirtualFile, aClass: VirtualFileKotlinClass?): VirtualFileKotlinClass? {
virtualFile = file
virtualFileKotlinClass = aClass
modificationStamp = file.modificationStamp
return aClass
}
}
private val cache = object : ThreadLocal<RequestCache>() {
override fun initialValue(): RequestCache {
return RequestCache()
}
}
override fun dispose() {
// This is only relevant for tests. We create a new instance of Application for each test, and so a new instance of this service is
// also created for each test. However all tests share the same event dispatch thread, which would collect all instances of this
// thread-local if they're not removed properly. Each instance would transitively retain VFS resulting in OutOfMemoryError
cache.remove()
}
companion object {
fun getKotlinBinaryClass(file: VirtualFile, fileContent: ByteArray? = null): KotlinJvmBinaryClass? {
if (file.fileType !== JavaClassFileType.INSTANCE) return null
val service = ServiceManager.getService(KotlinBinaryClassCache::class.java)
val requestCache = service.cache.get()
if (file.modificationStamp == requestCache.modificationStamp && file == requestCache.virtualFile) {
return requestCache.virtualFileKotlinClass
}
val aClass = ApplicationManager.getApplication().runReadAction(Computable {
@Suppress("DEPRECATION")
VirtualFileKotlinClass.create(file, fileContent)
})
return requestCache.cache(file, aClass)
}
}
}
@@ -0,0 +1,89 @@
/*
* 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.resolve.jvm.modules
import com.intellij.openapi.vfs.VirtualFile
//import com.intellij.psi.PsiJavaModule
import com.intellij.psi.PsiModifier
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.compact
import org.jetbrains.org.objectweb.asm.ClassReader
import org.jetbrains.org.objectweb.asm.ClassVisitor
//import org.jetbrains.org.objectweb.asm.ModuleVisitor
import org.jetbrains.org.objectweb.asm.Opcodes
//import org.jetbrains.org.objectweb.asm.Opcodes.ACC_TRANSITIVE
import java.io.IOException
class JavaModuleInfo(
val moduleName: String,
val requires: List<Requires>,
val exports: List<Exports>
) {
data class Requires(val moduleName: String, val isTransitive: Boolean)
data class Exports(val packageFqName: FqName, val toModules: List<String>)
override fun toString(): String =
"Module $moduleName (${requires.size} requires, ${exports.size} exports)"
companion object {
/*fun create(psiJavaModule: PsiJavaModule): JavaModuleInfo {
return JavaModuleInfo(
psiJavaModule.name,
psiJavaModule.requires.mapNotNull { statement ->
statement.moduleName?.let { moduleName ->
JavaModuleInfo.Requires(moduleName, statement.hasModifierProperty(PsiModifier.TRANSITIVE))
}
},
psiJavaModule.exports.mapNotNull { statement ->
statement.packageName?.let { packageName ->
JavaModuleInfo.Exports(FqName(packageName), statement.moduleNames)
}
}
)
}*/
/*fun read(file: VirtualFile): JavaModuleInfo? {
val contents = try { file.contentsToByteArray() } catch (e: IOException) { return null }
var moduleName: String? = null
val requires = arrayListOf<Requires>()
val exports = arrayListOf<Exports>()
ClassReader(contents).accept(object : ClassVisitor(Opcodes.ASM6) {
override fun visitModule(name: String, access: Int, version: String?): ModuleVisitor {
moduleName = name
return object : ModuleVisitor(Opcodes.ASM6) {
override fun visitRequire(module: String, access: Int, version: String?) {
requires.add(Requires(module, (access and ACC_TRANSITIVE) != 0))
}
override fun visitExport(packageFqName: String, access: Int, modules: Array<String>?) {
// For some reason, '/' is the delimiter in packageFqName here
exports.add(Exports(FqName(packageFqName.replace('/', '.')), modules?.toList().orEmpty()))
}
}
}
}, ClassReader.SKIP_DEBUG or ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES)
return if (moduleName != null)
JavaModuleInfo(moduleName!!, requires.compact(), exports.compact())
else null
}*/
}
}