Introduce keys to control applicability of coroutines

By default now we produce warnings on coroutines
This commit is contained in:
Mikhail Zarechenskiy
2016-12-14 15:22:41 +03:00
committed by Stanislav Erokhin
parent 30710955dc
commit 664485f4bb
25 changed files with 228 additions and 10 deletions
@@ -66,6 +66,9 @@ public interface Errors {
DiagnosticFactory1<PsiElement, LanguageFeature> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, Throwable> EXCEPTION_FROM_ANALYZER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, LanguageFeature> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, LanguageFeature> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Generic errors/warnings: applicable in many contexts
@@ -589,6 +589,20 @@ public class DefaultErrorMessages {
: "experimental and should be turned on explicitly via a command line option or in IDE settings: " + feature.getPresentableText();
}
});
MAP.put(EXPERIMENTAL_FEATURE_WARNING, "The feature is experimental: {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
@NotNull
@Override
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
return feature.getPresentableText();
}
});
MAP.put(EXPERIMENTAL_FEATURE_ERROR, "The experimental feature is disabled: {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
@NotNull
@Override
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
return feature.getPresentableText();
}
});
MAP.put(EXCEPTION_FROM_ANALYZER, "Internal Error occurred while analyzing this expression:\n{0}", THROWABLE);
MAP.put(UNNECESSARY_SAFE_CALL, "Unnecessary safe call on a non-null receiver of type {0}", RENDER_TYPE);
MAP.put(UNEXPECTED_SAFE_CALL, "Safe-call is not allowed here");
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2016 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.
@@ -100,6 +100,14 @@ object ModifierCheckerCore {
IMPL_KEYWORD to LanguageFeature.MultiPlatformProjects
)
val errorOnFeature = mapOf(
LanguageFeature.Coroutines to LanguageFeature.ErrorOnCoroutines
)
val warningOnFeature = mapOf(
LanguageFeature.Coroutines to LanguageFeature.WarnOnCoroutines
)
val featureDependenciesTargets = mapOf(
LanguageFeature.InlineProperties to setOf(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER)
)
@@ -266,15 +274,29 @@ object ModifierCheckerCore {
val dependency = featureDependencies[modifier] ?: return true
if (!languageVersionSettings.supportsFeature(dependency)) {
val errorOnDependencyFeature = errorOnFeature[dependency]?.let { languageVersionSettings.supportsFeature(it) } ?: false
val supportsFeature = languageVersionSettings.supportsFeature(dependency)
if (!supportsFeature || errorOnDependencyFeature) {
val restrictedTargets = featureDependenciesTargets[dependency]
if (restrictedTargets != null && actualTargets.intersect(restrictedTargets).isEmpty()) {
return true
}
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, dependency))
if (!supportsFeature) {
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, dependency))
}
else if (errorOnDependencyFeature) {
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, dependency))
}
return false
}
val pairedWarningFeature = warningOnFeature[dependency]
if (pairedWarningFeature != null && languageVersionSettings.supportsFeature(pairedWarningFeature)) {
trace.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(node.psi, dependency))
}
return true
}
@@ -69,4 +69,4 @@ object OperatorModifierChecker {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature))
}
}
}
}
@@ -18,11 +18,13 @@ package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType
import org.jetbrains.kotlin.coroutines.isSuspendLambda
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
@@ -80,9 +82,20 @@ object CoroutineSuspendCallChecker : CallChecker {
object BuilderFunctionsCallChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val descriptor = resolvedCall.candidateDescriptor as? FunctionDescriptor ?: return
if (descriptor.valueParameters.any { it.hasSuspendFunctionType } &&
!context.languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.Coroutines))
if (descriptor.valueParameters.any { it.hasSuspendFunctionType }) {
checkCoroutinesFeature(context.languageVersionSettings, context.trace, reportOn)
}
}
}
private fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.Coroutines))
}
else if (languageVersionSettings.supportsFeature(LanguageFeature.ErrorOnCoroutines)) {
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(reportOn, LanguageFeature.Coroutines))
}
else if (languageVersionSettings.supportsFeature(LanguageFeature.WarnOnCoroutines)) {
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(reportOn, LanguageFeature.Coroutines))
}
}