convert JetPositionManager to Kotlin

This commit is contained in:
Dmitry Jemerov
2014-12-05 20:17:32 +01:00
parent 6d7b4ad721
commit 16481a4144
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2013 JetBrains s.r.o. * Copyright 2010-2014 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -14,428 +14,383 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.jet.plugin.debugger; package org.jetbrains.jet.plugin.debugger
import com.intellij.debugger.NoDataException; import com.intellij.debugger.NoDataException
import com.intellij.debugger.PositionManager; import com.intellij.debugger.PositionManager
import com.intellij.debugger.SourcePosition; import com.intellij.debugger.SourcePosition
import com.intellij.debugger.engine.DebugProcess; import com.intellij.debugger.engine.DebugProcess
import com.intellij.debugger.requests.ClassPrepareRequestor; import com.intellij.debugger.requests.ClassPrepareRequestor
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.LibraryUtil; import com.intellij.openapi.roots.libraries.LibraryUtil
import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Pair
import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Ref
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.*; import com.intellij.psi.util.*
import com.sun.jdi.AbsentInformationException; import com.sun.jdi.AbsentInformationException
import com.sun.jdi.Location; import com.sun.jdi.Location
import com.sun.jdi.ReferenceType; import com.sun.jdi.ReferenceType
import com.sun.jdi.request.ClassPrepareRequest; import com.sun.jdi.request.ClassPrepareRequest
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly
import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.analyzer.AnalysisResult
import org.jetbrains.annotations.TestOnly; import org.jetbrains.jet.codegen.AsmUtil
import org.jetbrains.jet.analyzer.AnalysisResult; import org.jetbrains.jet.codegen.ClassBuilderFactories
import org.jetbrains.jet.codegen.AsmUtil; import org.jetbrains.jet.codegen.state.GenerationState
import org.jetbrains.jet.codegen.ClassBuilderFactories; import org.jetbrains.jet.codegen.state.JetTypeMapper
import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.callUtil.*
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.extension.InlineAnalyzerExtension
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.jet.lang.resolve.java.JvmClassName
import org.jetbrains.jet.lang.resolve.extension.InlineAnalyzerExtension; import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils
import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils; import org.jetbrains.jet.lang.types.lang.InlineStrategy
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.lang.InlineUtil
import org.jetbrains.jet.lang.types.lang.InlineStrategy; import org.jetbrains.jet.plugin.caches.resolve.IdeaModuleInfo
import org.jetbrains.jet.lang.types.lang.InlineUtil; import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService
import org.jetbrains.jet.plugin.caches.resolve.IdeaModuleInfo; import org.jetbrains.jet.plugin.caches.resolve.*
import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService; import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage; import org.jetbrains.jet.plugin.util.DebuggerUtils
import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.jet.plugin.util.DebuggerUtils;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.*; import java.util.*
import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass; import org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass
import static org.jetbrains.jet.plugin.stubindex.PackageIndexUtil.findFilesWithExactPackage; import org.jetbrains.jet.plugin.stubindex.PackageIndexUtil
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
import com.intellij.psi.stubs.StubElement
public class JetPositionManager implements PositionManager { public class JetPositionManager(private val myDebugProcess: DebugProcess) : PositionManager {
private final DebugProcess myDebugProcess; private val myTypeMappers = WeakHashMap<Pair<FqName, IdeaModuleInfo>, CachedValue<JetTypeMapper>>()
private final WeakHashMap<Pair<FqName, IdeaModuleInfo>, CachedValue<JetTypeMapper>> myTypeMappers = new WeakHashMap<Pair<FqName, IdeaModuleInfo>, CachedValue<JetTypeMapper>>();
public JetPositionManager(DebugProcess debugProcess) { override fun getSourcePosition(location: Location?): SourcePosition? {
myDebugProcess = debugProcess;
}
@Override
@Nullable
public SourcePosition getSourcePosition(@Nullable Location location) throws NoDataException {
if (location == null) { if (location == null) {
throw new NoDataException(); throw NoDataException()
} }
PsiFile psiFile = getPsiFileByLocation(location); val psiFile = getPsiFileByLocation(location)
if (psiFile == null) { if (psiFile == null) {
throw new NoDataException(); throw NoDataException()
} }
int lineNumber; val lineNumber: Int
try { try {
lineNumber = location.lineNumber() - 1; lineNumber = location.lineNumber() - 1
} }
catch (InternalError e) { catch (e: InternalError) {
lineNumber = -1; lineNumber = -1
} }
if (lineNumber >= 0) { if (lineNumber >= 0) {
JetFunctionLiteral lambdaIfInside = getLambdaIfInside(location, (JetFile) psiFile, lineNumber); val lambdaIfInside = getLambdaIfInside(location, psiFile as JetFile, lineNumber)
if (lambdaIfInside != null) { if (lambdaIfInside != null) {
return SourcePosition.createFromElement(lambdaIfInside.getBodyExpression().getStatements().get(0)); return SourcePosition.createFromElement(lambdaIfInside.getBodyExpression().getStatements().get(0))
} }
return SourcePosition.createFromLine(psiFile, lineNumber); return SourcePosition.createFromLine(psiFile, lineNumber)
} }
throw new NoDataException(); throw NoDataException()
} }
private JetFunctionLiteral getLambdaIfInside(@NotNull Location location, @NotNull JetFile file, int lineNumber) { private fun getLambdaIfInside(location: Location, file: JetFile, lineNumber: Int): JetFunctionLiteral? {
String currentLocationFqName = location.declaringType().name(); val currentLocationFqName = location.declaringType().name()
if (currentLocationFqName == null) return null; if (currentLocationFqName == null) return null
Integer start = CodeInsightUtils.getStartLineOffset(file, lineNumber); val start = CodeInsightUtils.getStartLineOffset(file, lineNumber)
Integer end = CodeInsightUtils.getEndLineOffset(file, lineNumber); val end = CodeInsightUtils.getEndLineOffset(file, lineNumber)
if (start == null || end == null) return null; if (start == null || end == null) return null
PsiElement[] literals = CodeInsightUtils.findElementsOfClassInRange(file, start, end, JetFunctionLiteral.class); val literals = CodeInsightUtils.findElementsOfClassInRange(file, start, end, javaClass<JetFunctionLiteral>())
if (literals == null || literals.length == 0) return null; if (literals == null || literals.size() == 0) return null
boolean isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null; val isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null
JetTypeMapper typeMapper = !isInLibrary val typeMapper = if (!isInLibrary)
? prepareTypeMapper(file) prepareTypeMapper(file)
: createTypeMapperForLibraryFile(file.findElementAt(start), file); else
createTypeMapperForLibraryFile(file.findElementAt(start), file)
String currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(new FqName(currentLocationFqName)).getInternalName(); val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).getInternalName()
for (PsiElement literal : literals) { for (literal in literals) {
JetFunctionLiteral functionLiteral = (JetFunctionLiteral) literal; val functionLiteral = literal as JetFunctionLiteral
if (isInlinedLambda(functionLiteral, typeMapper.getBindingContext())) { if (isInlinedLambda(functionLiteral, typeMapper.getBindingContext())) {
continue; continue
} }
String internalClassName = getClassNameForElement(literal.getFirstChild(), typeMapper, file, isInLibrary); val internalClassName = getClassNameForElement(literal.getFirstChild(), typeMapper, file, isInLibrary)
if (internalClassName.equals(currentLocationClassName)) { if (internalClassName == currentLocationClassName) {
return functionLiteral; return functionLiteral
} }
} }
return null; return null
} }
@Nullable private fun getPsiFileByLocation(location: Location): PsiFile? {
private PsiFile getPsiFileByLocation(@NotNull Location location) { val sourceName: String
String sourceName;
try { try {
sourceName = location.sourceName(); sourceName = location.sourceName()
} }
catch (AbsentInformationException e) { catch (e: AbsentInformationException) {
return null; return null
} }
// JDI names are of form "package.Class$InnerClass" // JDI names are of form "package.Class$InnerClass"
String referenceFqName = location.declaringType().name(); val referenceFqName = location.declaringType().name()
String referenceInternalName = referenceFqName.replace('.', '/'); val referenceInternalName = referenceFqName.replace('.', '/')
JvmClassName className = JvmClassName.byInternalName(referenceInternalName); val className = JvmClassName.byInternalName(referenceInternalName)
Project project = myDebugProcess.getProject(); val project = myDebugProcess.getProject()
if (DumbService.getInstance(project).isDumb()) return null; if (DumbService.getInstance(project).isDumb()) return null
return DebuggerUtils.findSourceFileForClass(project, GlobalSearchScope.allScope(project), className, sourceName, location.lineNumber() - 1); return DebuggerUtils.findSourceFileForClass(project, GlobalSearchScope.allScope(project), className, sourceName, location.lineNumber() - 1)
} }
@NotNull override fun getAllClasses(sourcePosition: SourcePosition): List<ReferenceType> {
@Override if (sourcePosition.getFile() !is JetFile) {
public List<ReferenceType> getAllClasses(SourcePosition sourcePosition) throws NoDataException { throw NoDataException()
if (!(sourcePosition.getFile() instanceof JetFile)) {
throw new NoDataException();
} }
String name = classNameForPosition(sourcePosition); val name = classNameForPosition(sourcePosition)
List<ReferenceType> result = new ArrayList<ReferenceType>(); val result = ArrayList<ReferenceType>()
if (name != null) { if (name != null) {
result.addAll(myDebugProcess.getVirtualMachineProxy().classesByName(name)); result.addAll(myDebugProcess.getVirtualMachineProxy().classesByName(name))
} }
return result; return result
} }
@Nullable private fun classNameForPosition(sourcePosition: SourcePosition): String? {
private String classNameForPosition(final SourcePosition sourcePosition) { val result = Ref.create<String>()
final Ref<String> result = Ref.create();
ApplicationManager.getApplication().runReadAction(new Runnable() { ApplicationManager.getApplication().runReadAction {
@Override val file = sourcePosition.getFile() as JetFile
@SuppressWarnings("unchecked") val isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null
public void run() { val typeMapper = if (!isInLibrary) prepareTypeMapper(file) else createTypeMapperForLibraryFile(sourcePosition.getElementAt(), file)
JetFile file = (JetFile) sourcePosition.getFile(); result.set(getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file, isInLibrary))
boolean isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null;
JetTypeMapper typeMapper = !isInLibrary ? prepareTypeMapper(file) : createTypeMapperForLibraryFile(sourcePosition.getElementAt(), file);
result.set(getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file, isInLibrary));
} }
}); return result.get()
return result.get();
} }
@SuppressWarnings("unchecked") private fun prepareTypeMapper(file: JetFile): JetTypeMapper {
public static String getClassNameForElement( val key = createKeyForTypeMapper(file)
@Nullable PsiElement notPositionedElement,
@NotNull JetTypeMapper typeMapper,
@NotNull JetFile file,
boolean isInLibrary
) {
PsiElement element = getElementToCalculateClassName(notPositionedElement);
if (element instanceof JetClassOrObject) { var value: CachedValue<JetTypeMapper>? = myTypeMappers.get(key)
return getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) element); if (value == null) {
value = CachedValuesManager.getManager(file.getProject()).createCachedValue<JetTypeMapper>(object : CachedValueProvider<JetTypeMapper> {
override fun compute(): CachedValueProvider.Result<JetTypeMapper>? {
val project = file.getProject()
val packageFacadeScope = key.second.contentScope()
val packageFiles = PackageIndexUtil.findFilesWithExactPackage(key.first, packageFacadeScope, project)
val analysisResult = KotlinCacheService.getInstance(project).getAnalysisResults(packageFiles)
analysisResult.throwIfError()
val state = GenerationState(project, ClassBuilderFactories.THROW_EXCEPTION, analysisResult.moduleDescriptor,
analysisResult.bindingContext, ArrayList(packageFiles))
state.beforeCompile()
return CachedValueProvider.Result<JetTypeMapper>(state.getTypeMapper(), PsiModificationTracker.MODIFICATION_COUNT)
} }
else if (element instanceof JetFunctionLiteral) { }, false)
if (isInlinedLambda((JetFunctionLiteral) element, typeMapper.getBindingContext())) {
return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary); myTypeMappers.put(key, value)
} else { }
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), ((JetFunctionLiteral) element));
return asmType.getInternalName(); return value!!.getValue()
}
override fun locationsOfLine(type: ReferenceType, position: SourcePosition): List<Location> {
if (position.getFile() !is JetFile) {
throw NoDataException()
}
try {
val line = position.getLine() + 1
val locations = if (myDebugProcess.getVirtualMachineProxy().versionHigher("1.4"))
type.locationsOfLine(DebugProcess.JAVA_STRATUM, null, line)
else
type.locationsOfLine(line)
if (locations == null || locations.isEmpty()) throw NoDataException()
return locations
}
catch (e: AbsentInformationException) {
throw NoDataException()
} }
} }
else if (element instanceof JetClassInitializer) {
PsiElement parent = getElementToCalculateClassName(element.getParent()); override fun createPrepareRequest(classPrepareRequestor: ClassPrepareRequestor, sourcePosition: SourcePosition): ClassPrepareRequest? {
if (sourcePosition.getFile() !is JetFile) {
throw NoDataException()
}
val className = classNameForPosition(sourcePosition)
if (className == null) {
return null
}
return myDebugProcess.getRequestsManager().createClassPrepareRequest(classPrepareRequestor, className.replace('/', '.'))
}
TestOnly
public fun addTypeMapper(file: JetFile, typeMapper: JetTypeMapper) {
val value = CachedValuesManager.getManager(file.getProject()).createCachedValue<JetTypeMapper>(object : CachedValueProvider<JetTypeMapper> {
override fun compute() = CachedValueProvider.Result<JetTypeMapper>(typeMapper, PsiModificationTracker.MODIFICATION_COUNT)
}, false)
val key = createKeyForTypeMapper(file)
myTypeMappers.put(key, value)
}
class object {
public fun getClassNameForElement(notPositionedElement: PsiElement?, typeMapper: JetTypeMapper, file: JetFile, isInLibrary: Boolean): String? {
val element = getElementToCalculateClassName(notPositionedElement)
when {
element is JetClassOrObject -> return getJvmInternalNameForImpl(typeMapper, element)
element is JetFunctionLiteral -> {
if (isInlinedLambda(element, typeMapper.getBindingContext())) {
return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary)
}
else {
val asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), element)
return asmType.getInternalName()
}
}
element is JetClassInitializer -> {
val parent = getElementToCalculateClassName(element.getParent())
// Class-object initializer // Class-object initializer
if (parent instanceof JetObjectDeclaration && ((JetObjectDeclaration) parent).isClassObject()) { if (parent is JetObjectDeclaration && parent.isClassObject()) {
return getClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary); return getClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary)
} }
return getClassNameForElement(element, typeMapper, file, isInLibrary); return getClassNameForElement(element, typeMapper, file, isInLibrary)
} }
else if (element instanceof JetProperty && (!((JetProperty) element).isTopLevel() || !isInLibrary)) { element is JetProperty && (!element.isTopLevel() || !isInLibrary) -> {
if (isInPropertyAccessor(notPositionedElement)) { if (isInPropertyAccessor(notPositionedElement)) {
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class); val classOrObject = PsiTreeUtil.getParentOfType(element, javaClass<JetClassOrObject>())
if (classOrObject != null) { if (classOrObject != null) {
return getJvmInternalNameForImpl(typeMapper, classOrObject); return getJvmInternalNameForImpl(typeMapper, classOrObject)
} }
} }
VariableDescriptor descriptor = (VariableDescriptor) typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element); val descriptor = typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
if (!(descriptor instanceof PropertyDescriptor)) { if (descriptor !is PropertyDescriptor) {
return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary); return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary)
} }
return getJvmInternalNameForPropertyOwner(typeMapper, (PropertyDescriptor) descriptor); return getJvmInternalNameForPropertyOwner(typeMapper, descriptor)
} }
else if (element instanceof JetNamedFunction) { element is JetNamedFunction -> {
PsiElement parent = getElementToCalculateClassName(element); val parent = getElementToCalculateClassName(element)
if (parent instanceof JetClassOrObject) { if (parent is JetClassOrObject) {
return getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) parent); return getJvmInternalNameForImpl(typeMapper, parent)
} }
else if (parent != null) { else if (parent != null) {
Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), (JetElement) element); val asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), element)
return asmType.getInternalName(); return asmType.getInternalName()
}
} }
} }
if (isInLibrary) { if (isInLibrary) {
JetElement elementAtForLibraryFile = getElementToCreateTypeMapperForLibraryFile(notPositionedElement); val elementAtForLibraryFile = getElementToCreateTypeMapperForLibraryFile(notPositionedElement)
assert elementAtForLibraryFile != null : "Couldn't find element at breakpoint for library file " + file.getName() assert(elementAtForLibraryFile != null) {
+ (notPositionedElement == null ? "" : ", notPositionedElement = " + JetPsiUtil.getElementTextWithContext( (JetElement) notPositionedElement)); "Couldn't find element at breakpoint for library file " + file.getName() +
return DebuggerPackage.findPackagePartInternalNameForLibraryFile(elementAtForLibraryFile); (if (notPositionedElement == null) "" else ", notPositionedElement = " + JetPsiUtil.getElementTextWithContext(notPositionedElement))
}
return findPackagePartInternalNameForLibraryFile(elementAtForLibraryFile!!)
} }
return PackagePartClassUtils.getPackagePartInternalName(file); return PackagePartClassUtils.getPackagePartInternalName(file)
} }
@Nullable private fun getElementToCalculateClassName(notPositionedElement: PsiElement?) =
private static JetDeclaration getElementToCalculateClassName(@Nullable PsiElement notPositionedElement) { PsiTreeUtil.getParentOfType(notPositionedElement,
//noinspection unchecked javaClass<JetClassOrObject>(),
return PsiTreeUtil.getParentOfType(notPositionedElement, javaClass<JetFunctionLiteral>(),
JetClassOrObject.class, javaClass<JetNamedFunction>(),
JetFunctionLiteral.class, JetNamedFunction.class, javaClass<JetProperty>(),
JetProperty.class, javaClass<JetClassInitializer>())
JetClassInitializer.class);
}
@NotNull public fun getJvmInternalNameForPropertyOwner(typeMapper: JetTypeMapper, descriptor: PropertyDescriptor): String {
public static String getJvmInternalNameForPropertyOwner(@NotNull JetTypeMapper typeMapper, @NotNull PropertyDescriptor descriptor) {
return typeMapper.mapOwner( return typeMapper.mapOwner(
AsmUtil.isPropertyWithBackingFieldInOuterClass(descriptor) ? descriptor.getContainingDeclaration() : descriptor, if (AsmUtil.isPropertyWithBackingFieldInOuterClass(descriptor)) descriptor.getContainingDeclaration() else descriptor,
true) true).getInternalName()
.getInternalName();
} }
private static boolean isInPropertyAccessor(@Nullable PsiElement element) { private fun isInPropertyAccessor(element: PsiElement?) =
//noinspection unchecked element is JetPropertyAccessor ||
return element instanceof JetPropertyAccessor || ((JetElement) PsiTreeUtil.getParentOfType(element, JetProperty.class, JetPropertyAccessor.class)) instanceof JetPropertyAccessor; PsiTreeUtil.getParentOfType(element, javaClass<JetProperty>(), javaClass<JetPropertyAccessor>()) is JetPropertyAccessor
}
@Nullable private fun getElementToCreateTypeMapperForLibraryFile(element: PsiElement?) =
private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement element) { if (element is JetElement) element else PsiTreeUtil.getParentOfType(element, javaClass<JetElement>())
return element instanceof JetElement ? (JetElement) element : PsiTreeUtil.getParentOfType(element, JetElement.class);
}
@Nullable private fun getJvmInternalNameForImpl(typeMapper: JetTypeMapper, jetClass: JetClassOrObject): String? {
private static String getJvmInternalNameForImpl(JetTypeMapper typeMapper, JetClassOrObject jetClass) { val classDescriptor = typeMapper.getBindingContext().get<PsiElement, ClassDescriptor>(BindingContext.CLASS, jetClass)
ClassDescriptor classDescriptor = typeMapper.getBindingContext().get(BindingContext.CLASS, jetClass);
if (classDescriptor == null) { if (classDescriptor == null) {
return null; return null
} }
if (jetClass instanceof JetClass && ((JetClass) jetClass).isTrait()) { if (jetClass is JetClass && jetClass.isTrait()) {
return typeMapper.mapTraitImpl(classDescriptor).getInternalName(); return typeMapper.mapTraitImpl(classDescriptor).getInternalName()
} }
return typeMapper.mapClass(classDescriptor).getInternalName(); return typeMapper.mapClass(classDescriptor).getInternalName()
} }
private static JetTypeMapper createTypeMapperForLibraryFile(@Nullable PsiElement notPositionedElement, @NotNull JetFile file) { private fun createTypeMapperForLibraryFile(notPositionedElement: PsiElement?, file: JetFile): JetTypeMapper {
JetElement element = getElementToCreateTypeMapperForLibraryFile(notPositionedElement); val element = getElementToCreateTypeMapperForLibraryFile(notPositionedElement)
AnalysisResult analysisResult = ResolvePackage.analyzeAndGetResult(element); val analysisResult = element!!.analyzeAndGetResult()
GenerationState state = new GenerationState(file.getProject(), ClassBuilderFactories.THROW_EXCEPTION, val state = GenerationState(file.getProject(), ClassBuilderFactories.THROW_EXCEPTION,
analysisResult.getModuleDescriptor(), analysisResult.moduleDescriptor, analysisResult.bindingContext, listOf(file))
analysisResult.getBindingContext(), state.beforeCompile()
Collections.singletonList(file) return state.getTypeMapper()
);
state.beforeCompile();
return state.getTypeMapper();
} }
private JetTypeMapper prepareTypeMapper(final JetFile file) { public fun isInlinedLambda(functionLiteral: JetFunctionLiteral, context: BindingContext): Boolean {
final Pair<FqName, IdeaModuleInfo> key = createKeyForTypeMapper(file); val functionLiteralExpression = functionLiteral.getParent()
if (functionLiteralExpression == null) return false
CachedValue<JetTypeMapper> value = myTypeMappers.get(key); var parent = functionLiteralExpression.getParent()
if(value == null) {
value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<JetTypeMapper>() {
@Override
public Result<JetTypeMapper> compute() {
Project project = file.getProject();
GlobalSearchScope packageFacadeScope = key.second.contentScope();
Collection<JetFile> packageFiles = findFilesWithExactPackage(key.first, packageFacadeScope, project);
AnalysisResult analysisResult = KotlinCacheService.OBJECT$.getInstance(project).getAnalysisResults(packageFiles); var valueArgument: PsiElement = functionLiteralExpression
analysisResult.throwIfError(); while (parent is JetParenthesizedExpression || parent is JetBinaryExpressionWithTypeRHS || parent is JetLabeledExpression) {
valueArgument = parent
GenerationState state = new GenerationState(project, ClassBuilderFactories.THROW_EXCEPTION, parent = parent.getParent()
analysisResult.getModuleDescriptor(), analysisResult.getBindingContext(),
new ArrayList<JetFile>(packageFiles)
);
state.beforeCompile();
return new Result<JetTypeMapper>(state.getTypeMapper(), PsiModificationTracker.MODIFICATION_COUNT);
}
}, false);
myTypeMappers.put(key, value);
} }
return value.getValue(); while (parent is ValueArgument || parent is JetValueArgumentList) {
parent = parent.getParent()
} }
@NotNull if (parent !is JetElement) return false
@Override
public List<Location> locationsOfLine(ReferenceType type, SourcePosition position) throws NoDataException {
if (!(position.getFile() instanceof JetFile)) {
throw new NoDataException();
}
try {
int line = position.getLine() + 1;
List<Location> locations = myDebugProcess.getVirtualMachineProxy().versionHigher("1.4")
? type.locationsOfLine(DebugProcess.JAVA_STRATUM, null, line)
: type.locationsOfLine(line);
if (locations == null || locations.isEmpty()) throw new NoDataException();
return locations;
}
catch (AbsentInformationException e) {
throw new NoDataException();
}
}
@Override val call = (parent as JetElement).getResolvedCall(context)
public ClassPrepareRequest createPrepareRequest(ClassPrepareRequestor classPrepareRequestor, if (call == null) return false
SourcePosition sourcePosition) throws NoDataException {
if (!(sourcePosition.getFile() instanceof JetFile)) {
throw new NoDataException();
}
String className = classNameForPosition(sourcePosition);
if (className == null) {
return null;
}
return myDebugProcess.getRequestsManager().createClassPrepareRequest(classPrepareRequestor, className.replace('/', '.'));
}
@TestOnly val inlineType = InlineUtil.getInlineType(call.getResultingDescriptor())
public void addTypeMapper(JetFile file, final JetTypeMapper typeMapper) { if (!inlineType.isInline()) return false
CachedValue<JetTypeMapper> value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<JetTypeMapper>() {
@Override
public Result<JetTypeMapper> compute() {
return new Result<JetTypeMapper>(typeMapper, PsiModificationTracker.MODIFICATION_COUNT);
}
}, false);
Pair<FqName, IdeaModuleInfo> key = createKeyForTypeMapper(file); for (entry in call.getValueArguments().entrySet()) {
myTypeMappers.put(key, value); val valueParameterDescriptor = entry.getKey()
} val resolvedValueArgument = entry.getValue()
for (next in resolvedValueArgument.getArguments()) {
public static boolean isInlinedLambda(@NotNull JetFunctionLiteral functionLiteral, @NotNull BindingContext context) { val expression = next.getArgumentExpression()
PsiElement functionLiteralExpression = functionLiteral.getParent();
if (functionLiteralExpression == null) return false;
PsiElement parent = functionLiteralExpression.getParent();
PsiElement valueArgument = functionLiteralExpression;
while (parent instanceof JetParenthesizedExpression ||
parent instanceof JetBinaryExpressionWithTypeRHS ||
parent instanceof JetLabeledExpression) {
valueArgument = parent;
parent = parent.getParent();
}
while (parent instanceof ValueArgument ||
parent instanceof JetValueArgumentList) {
parent = parent.getParent();
}
if (!(parent instanceof JetElement)) return false;
ResolvedCall<?> call = CallUtilPackage.getResolvedCall((JetElement) parent, context);
if (call == null) return false;
InlineStrategy inlineType = InlineUtil.getInlineType(call.getResultingDescriptor());
if (!inlineType.isInline()) return false;
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : call.getValueArguments().entrySet()) {
ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
ResolvedValueArgument resolvedValueArgument = entry.getValue();
for (ValueArgument next : resolvedValueArgument.getArguments()) {
JetExpression expression = next.getArgumentExpression();
if (valueArgument == expression) { if (valueArgument == expression) {
return InlineAnalyzerExtension.checkInlinableParameter( return InlineAnalyzerExtension.checkInlinableParameter(valueParameterDescriptor, expression, call.getResultingDescriptor(), null)
valueParameterDescriptor, expression,
call.getResultingDescriptor(), null
);
} }
} }
} }
return false; return false
} }
private static Pair<FqName, IdeaModuleInfo> createKeyForTypeMapper(@NotNull JetFile file) { private fun createKeyForTypeMapper(file: JetFile) = Pair(file.getPackageFqName(), file.getModuleInfo())
return new Pair<FqName, IdeaModuleInfo>(file.getPackageFqName(), ResolvePackage.getModuleInfo(file));
} }
} }