Remove redundant locals

Do not transform already transformed suspend lambdas
Ignore duplicates of continuation in local variable table during redundant locals elimination.
This commit is contained in:
Ilmir Usmanov
2018-02-27 19:08:37 +03:00
parent 81f3e39f29
commit 826d667398
28 changed files with 785 additions and 113 deletions
@@ -201,7 +201,7 @@ public interface Errors {
DiagnosticFactory2<PsiElement, KtModifierKeywordToken, String> DEPRECATED_MODIFIER_CONTAINING_DECLARATION = DiagnosticFactory2.create(WARNING);
DiagnosticFactory1<PsiElement, KtModifierKeywordToken> ILLEGAL_INLINE_PARAMETER_MODIFIER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<KtParameter> INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtParameter> REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET = DiagnosticFactory1.create(ERROR);
DiagnosticFactory2<KtAnnotationEntry, String, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET = DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<KtAnnotationEntry, String> WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE = DiagnosticFactory1.create(WARNING);
@@ -122,8 +122,8 @@ public class DefaultErrorMessages {
MAP.put(WRONG_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is not applicable inside ''{1}''", TO_STRING, TO_STRING);
MAP.put(DEPRECATED_MODIFIER_CONTAINING_DECLARATION, "Modifier ''{0}'' is deprecated inside ''{1}''", TO_STRING, TO_STRING);
MAP.put(ILLEGAL_INLINE_PARAMETER_MODIFIER, "Modifier ''{0}'' is allowed only for function parameters of an inline function", TO_STRING);
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Inline lambda parameters of suspend function type are not supported. Add 'noinline' or 'crossinline' modifier.");
MAP.put(REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE, "Redundant suspend modifier of inline lambda parameters of suspend function type.");
MAP.put(INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED, "Suspend inline lambda parameters of non-suspend function type are not supported. Add 'noinline' or 'crossinline' modifier.");
MAP.put(REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE, "Redundant 'suspend' modifier: lambda parameters of suspend function type uses existing continuation.");
MAP.put(WRONG_ANNOTATION_TARGET, "This annotation is not applicable to target ''{0}''", TO_STRING);
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET, "This annotation is not applicable to target ''{0}'' and use site target ''@{1}''", TO_STRING, TO_STRING);
MAP.put(WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET_ON_TYPE,
@@ -17,13 +17,12 @@
package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionType
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.contracts.parsing.isFromContractDsl
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.contracts.parsing.isFromContractDsl
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -239,8 +238,7 @@ internal class InlineChecker(private val descriptor: FunctionDescriptor) : CallC
val containingDeclaration = descriptor.getContainingDeclaration()
val isInvoke = descriptor.getName() == OperatorNameConventions.INVOKE &&
containingDeclaration is ClassDescriptor &&
(containingDeclaration.defaultType.isFunctionType || containingDeclaration.defaultType.isSuspendFunctionType)
containingDeclaration is ClassDescriptor && containingDeclaration.defaultType.isBuiltinFunctionalType
return isInvoke || InlineUtil.isInline(descriptor)
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFunction
@@ -32,7 +33,6 @@ object InlineParameterChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration is KtFunction) {
val inline = declaration.hasModifier(KtTokens.INLINE_KEYWORD)
val suspend = declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)
for (parameter in declaration.valueParameters) {
val parameterDescriptor = context.trace.get(BindingContext.VALUE_PARAMETER, parameter)
if (!inline || (parameterDescriptor != null && !parameterDescriptor.type.isBuiltinFunctionalType)) {
@@ -43,8 +43,11 @@ object InlineParameterChecker : DeclarationChecker {
!parameter.hasModifier(KtTokens.CROSSINLINE_KEYWORD) &&
parameterDescriptor?.type?.isSuspendFunctionType == true
) {
if (suspend) {
context.trace.report(Errors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.on(parameter))
if (declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)) {
val typeReference = parameter.typeReference!!
val modifierList = typeReference.modifierList!!
val modifier = modifierList.getModifier(KtTokens.SUSPEND_KEYWORD)!!
context.trace.report(Errors.REDUNDANT_INLINE_SUSPEND_FUNCTION_TYPE.on(modifier))
} else {
context.trace.report(Errors.INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED.on(parameter))
}
@@ -36,8 +36,7 @@ public class InlineUtil {
public static boolean isInlineParameterExceptNullability(@NotNull ParameterDescriptor valueParameterOrReceiver) {
return !(valueParameterOrReceiver instanceof ValueParameterDescriptor
&& ((ValueParameterDescriptor) valueParameterOrReceiver).isNoinline()) &&
(FunctionTypesKt.isFunctionType(valueParameterOrReceiver.getOriginal().getType()) ||
FunctionTypesKt.isSuspendFunctionType(valueParameterOrReceiver.getOriginal().getType()));
FunctionTypesKt.isBuiltinFunctionalType(valueParameterOrReceiver.getOriginal().getType());
}
public static boolean isInlineParameter(@NotNull ParameterDescriptor valueParameterOrReceiver) {