diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/AnnotationLoaderForKotlinJavaScriptStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/AnnotationLoaderForKotlinJavaScriptStubBuilder.kt new file mode 100644 index 00000000000..f97db57b72e --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/AnnotationLoaderForKotlinJavaScriptStubBuilder.kt @@ -0,0 +1,64 @@ +/* + * 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.idea.decompiler + +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.serialization.ProtoBuf +import org.jetbrains.kotlin.serialization.deserialization.AnnotatedCallableKind +import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader +import org.jetbrains.kotlin.serialization.deserialization.NameResolver +import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer +import org.jetbrains.kotlin.serialization.js.JsProtoBuf +import org.jetbrains.kotlin.types.JetType + +public class AnnotationLoaderForKotlinJavaScriptStubBuilder() : AnnotationAndConstantLoader { + + override fun loadClassAnnotations( + classProto: ProtoBuf.Class, nameResolver: NameResolver + ): List = + classProto.getExtension(JsProtoBuf.classAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) } + + override fun loadCallableAnnotations( + container: ProtoContainer, + proto: ProtoBuf.Callable, + nameResolver: NameResolver, + kind: AnnotatedCallableKind + ): List = + proto.getExtension(JsProtoBuf.callableAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) } + + override fun loadValueParameterAnnotations( + container: ProtoContainer, + callable: ProtoBuf.Callable, + nameResolver: NameResolver, + kind: AnnotatedCallableKind, + proto: ProtoBuf.Callable.ValueParameter + ): List = + proto.getExtension(JsProtoBuf.parameterAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) } + + override fun loadTypeAnnotations( + proto: ProtoBuf.Type, + nameResolver: NameResolver + ): List = + proto.getExtension(JsProtoBuf.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) } + + override fun loadPropertyConstant( + container: ProtoContainer, + proto: ProtoBuf.Callable, + nameResolver: NameResolver, + expectedType: JetType + ): Unit {} +} diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/KotlinJavascriptMetaFileDecompiler.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/KotlinJavascriptMetaFileDecompiler.java index ca64482a9ca..1c2608e56ed 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/KotlinJavascriptMetaFileDecompiler.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/KotlinJavascriptMetaFileDecompiler.java @@ -21,24 +21,16 @@ import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiManager; import com.intellij.psi.compiled.ClassFileDecompilers; import com.intellij.psi.compiled.ClsStubBuilder; -import com.intellij.psi.stubs.PsiFileStub; -import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.kotlin.idea.decompiler.stubBuilder.KotlinClsStubBuilder; +import org.jetbrains.kotlin.idea.decompiler.stubBuilder.KotlinJavascriptStubBuilder; +import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil; public class KotlinJavascriptMetaFileDecompiler extends ClassFileDecompilers.Full { - private final ClsStubBuilder stubBuilder = new KotlinClsStubBuilder() { - @Nullable - @Override - public PsiFileStub buildFileStub(@NotNull FileContent fileContent) { - return null; - } - }; + private final ClsStubBuilder stubBuilder = new KotlinJavascriptStubBuilder(); @Override public boolean accepts(@NotNull VirtualFile file) { - return file.getName().endsWith(".meta"); + return file.getName().endsWith("." + KotlinJavascriptSerializationUtil.CLASS_METADATA_FILE_EXTENSION); } @NotNull @@ -50,6 +42,7 @@ public class KotlinJavascriptMetaFileDecompiler extends ClassFileDecompilers.Ful @NotNull @Override public FileViewProvider createFileViewProvider(@NotNull VirtualFile file, @NotNull PsiManager manager, boolean physical) { - return new KotlinJavascriptMetaFileViewProvider(manager, file, physical, DecompilerPackage.isKotlinInternalCompiledFile(file)); + return new KotlinJavascriptMetaFileViewProvider(manager, file, physical, DecompilerPackage.isKotlinJavaScriptInternalCompiledFile( + file)); } } diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt index b9afcf42adf..69dde295f70 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/ClsStubBuilderContext.kt @@ -27,10 +27,12 @@ import org.jetbrains.kotlin.serialization.deserialization.ClassDataFinder import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter import org.jetbrains.kotlin.serialization.deserialization.NameResolver import org.jetbrains.kotlin.storage.LockBasedStorageManager +import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass +import org.jetbrains.kotlin.serialization.deserialization.AnnotationAndConstantLoader class ClsStubBuilderComponents( val classDataFinder: ClassDataFinder, - val annotationLoader: AnnotationLoaderForStubBuilder + val annotationLoader: AnnotationAndConstantLoader ) { fun createContext( nameResolver: NameResolver, diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinJavaScriptStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinJavaScriptStubBuilder.kt new file mode 100644 index 00000000000..6b554d9001a --- /dev/null +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/KotlinJavaScriptStubBuilder.kt @@ -0,0 +1,87 @@ +/* + * 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.idea.decompiler.stubBuilder + +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.compiled.ClsStubBuilder +import com.intellij.psi.impl.compiled.ClassFileStubBuilder +import com.intellij.psi.stubs.PsiFileStub +import com.intellij.util.indexing.FileContent +import org.jetbrains.kotlin.idea.decompiler.AnnotationLoaderForKotlinJavaScriptStubBuilder +import org.jetbrains.kotlin.idea.decompiler.isKotlinJavaScriptInternalCompiledFile +import org.jetbrains.kotlin.idea.decompiler.navigation.JsMetaFileUtils +import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedKotlinJavaScriptDataFinder +import org.jetbrains.kotlin.idea.decompiler.textBuilder.DirectoryBasedKotlinJavaScriptMetaFileFinder +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.serialization.deserialization.NameResolver +import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializedResourcePaths +import org.jetbrains.kotlin.serialization.js.toClassData +import org.jetbrains.kotlin.serialization.js.toPackageData +import java.io.ByteArrayInputStream + +public open class KotlinJavaScriptStubBuilder : ClsStubBuilder() { + override fun getStubVersion() = ClassFileStubBuilder.STUB_VERSION + 1 + + override fun buildFileStub(content: FileContent): PsiFileStub<*>? { + val file = content.getFile() + + if (isKotlinJavaScriptInternalCompiledFile(file)) return null + + return doBuildFileStub(file) + } + + fun doBuildFileStub(file: VirtualFile): PsiFileStub? { + val packageFqName = JsMetaFileUtils.getPackageFqName(file) + + val content = file.contentsToByteArray(false) + val isPackageHeader = JsMetaFileUtils.isPackageHeader(file) + + val moduleDirectory = JsMetaFileUtils.getModuleDirectory(file) + val stringsFileName = KotlinJavascriptSerializedResourcePaths.getStringTableFilePath(packageFqName) + val stringsFile = moduleDirectory.findFileByRelativePath(stringsFileName) + assert(stringsFile != null, "strings file not found: $stringsFileName") + + val nameResolver = NameResolver.read(ByteArrayInputStream(stringsFile!!.contentsToByteArray(false))) + val components = createStubBuilderComponents(file, packageFqName, nameResolver) + + if (isPackageHeader) { + val packageData = content.toPackageData(nameResolver) + val context = components.createContext(packageData.getNameResolver(), packageFqName) + return createPackageFacadeFileStub(packageData.getPackageProto(), packageFqName, context) + } + else { + val classData = content.toClassData(nameResolver) + val context = components.createContext(classData.getNameResolver(), packageFqName) + val classId = JsMetaFileUtils.getClassId(file) + return createTopLevelClassStub(classId, classData.getClassProto(), context) + } + } + + private fun createStubBuilderComponents(file: VirtualFile, packageFqName: FqName, nameResolver: NameResolver): ClsStubBuilderComponents { + val metaFileFinder = DirectoryBasedKotlinJavaScriptMetaFileFinder(file.getParent()!!, packageFqName, nameResolver) + val classDataFinder = DirectoryBasedKotlinJavaScriptDataFinder(metaFileFinder, LOG) + val annotationLoader = AnnotationLoaderForKotlinJavaScriptStubBuilder() + return ClsStubBuilderComponents(classDataFinder, annotationLoader) + } + + companion object { + val LOG = Logger.getInstance(javaClass()) + } +} + diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt index ca3992b097a..61b9d97868c 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/decompiler/stubBuilder/TypeClsStubBuilder.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.serialization.ProtoBuf.Type import org.jetbrains.kotlin.serialization.ProtoBuf.Type.Argument.Projection import org.jetbrains.kotlin.serialization.ProtoBuf.TypeParameter.Variance import org.jetbrains.kotlin.serialization.deserialization.ProtoContainer +import org.jetbrains.kotlin.types.DynamicTypeCapabilities import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList import java.util.ArrayList @@ -70,6 +71,15 @@ class TypeClsStubBuilder(private val c: ClsStubBuilderContext) { } private fun createClassReferenceTypeStub(parent: StubElement, type: Type) { + if (type.hasFlexibleTypeCapabilitiesId()) { + val id = c.nameResolver.getString(type.getFlexibleTypeCapabilitiesId()) + + if (id == DynamicTypeCapabilities.id) { + KotlinPlaceHolderStubImpl(parent, JetStubElementTypes.DYNAMIC_TYPE) + return + } + } + val classId = c.nameResolver.getClassId(type.getConstructor().getId()) val fqName = classId.asSingleFqName().toUnsafe() val isFunctionType = KotlinBuiltIns.isExactFunctionType(fqName)