add KotlinJavaScriptStubBuilder

This commit is contained in:
Michael Nedzelsky
2015-04-06 11:43:03 +03:00
parent ea9d7ed49a
commit a0579ebedd
5 changed files with 170 additions and 14 deletions
@@ -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<ClassId, Unit> {
override fun loadClassAnnotations(
classProto: ProtoBuf.Class, nameResolver: NameResolver
): List<ClassId> =
classProto.getExtension(JsProtoBuf.classAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) }
override fun loadCallableAnnotations(
container: ProtoContainer,
proto: ProtoBuf.Callable,
nameResolver: NameResolver,
kind: AnnotatedCallableKind
): List<ClassId> =
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<ClassId> =
proto.getExtension(JsProtoBuf.parameterAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) }
override fun loadTypeAnnotations(
proto: ProtoBuf.Type,
nameResolver: NameResolver
): List<ClassId> =
proto.getExtension(JsProtoBuf.typeAnnotation).orEmpty().map { nameResolver.getClassId(it.getId()) }
override fun loadPropertyConstant(
container: ProtoContainer,
proto: ProtoBuf.Callable,
nameResolver: NameResolver,
expectedType: JetType
): Unit {}
}
@@ -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));
}
}
@@ -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<ClassId, Unit>
) {
fun createContext(
nameResolver: NameResolver,
@@ -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<JetFile>? {
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<KotlinJavaScriptStubBuilder>())
}
}
@@ -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<out PsiElement>, type: Type) {
if (type.hasFlexibleTypeCapabilitiesId()) {
val id = c.nameResolver.getString(type.getFlexibleTypeCapabilitiesId())
if (id == DynamicTypeCapabilities.id) {
KotlinPlaceHolderStubImpl<JetDynamicType>(parent, JetStubElementTypes.DYNAMIC_TYPE)
return
}
}
val classId = c.nameResolver.getClassId(type.getConstructor().getId())
val fqName = classId.asSingleFqName().toUnsafe()
val isFunctionType = KotlinBuiltIns.isExactFunctionType(fqName)