Disable some features when LV=1.1 API=1.0.

Feature list:
 - bound callable references
 - local delegated properties
 - coroutines.

#KT-16017 Fixed
This commit is contained in:
Stanislav Erokhin
2017-02-13 09:48:55 +03:00
parent be0211cd49
commit b6fa10cf9e
43 changed files with 232 additions and 75 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.cfg.WhenMissingCase;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersion;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.lexer.KtKeywordToken;
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
@@ -63,11 +64,11 @@ public interface Errors {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DiagnosticFactory1<PsiElement, String> UNSUPPORTED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, LanguageFeature> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> 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);
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING);
DiagnosticFactory1<PsiElement, Pair<LanguageFeature, LanguageVersionSettings>> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -453,7 +454,6 @@ public interface Errors {
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyAccessor> ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyDelegate> DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtPropertyDelegate> LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
@@ -237,7 +237,6 @@ public class DefaultErrorMessages {
MAP.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract");
MAP.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations");
MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces");
MAP.put(LOCAL_VARIABLE_WITH_DELEGATE, "Local variables are not allowed to have delegates");
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
@@ -600,30 +599,11 @@ public class DefaultErrorMessages {
MAP.put(UNSAFE_IMPLICIT_INVOKE_CALL, "Reference has a nullable type ''{0}'', use explicit ''?.invoke()'' to make a function-like call instead", RENDER_TYPE);
MAP.put(AMBIGUOUS_LABEL, "Ambiguous label");
MAP.put(UNSUPPORTED, "Unsupported [{0}]", STRING);
MAP.put(UNSUPPORTED_FEATURE, "The feature is {0}", new DiagnosticParameterRenderer<LanguageFeature>() {
@NotNull
@Override
public String render(LanguageFeature feature, @NotNull RenderingContext renderingContext) {
LanguageVersion version = feature.getSinceVersion();
return version != null
? "only available since Kotlin " + version.getVersionString() + ": " + feature.getPresentableText()
: "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(UNSUPPORTED_FEATURE, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.UNSUPPORTED));
MAP.put(EXPERIMENTAL_FEATURE_WARNING, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.WARNING));
MAP.put(EXPERIMENTAL_FEATURE_ERROR, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.ERROR));
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");
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2017 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.diagnostics.rendering
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
class LanguageFeatureMessageRenderer @JvmOverloads constructor(
private val type: Type,
private val useHtml: Boolean = false
): DiagnosticParameterRenderer<Pair<LanguageFeature, LanguageVersionSettings>> {
enum class Type {
UNSUPPORTED,
WARNING,
ERROR
}
override fun render(obj: Pair<LanguageFeature, LanguageVersionSettings>, renderingContext: RenderingContext): String {
val (feature, settings) = obj
val since = feature.sinceVersion
val sb = StringBuilder()
sb.append("The feature \"").append(feature.presentableName).append("\" is ")
when (type) {
Type.UNSUPPORTED ->
when {
since == null ->
sb.append("experimental and should be enabled explicitly")
since > settings.languageVersion ->
sb.append("only available since language version ").append(since.versionString)
feature.sinceApiVersion > settings.apiVersion ->
sb.append("only available since API version ").append(feature.sinceApiVersion.versionString)
else ->
sb.append("disabled")
}
Type.WARNING -> sb.append("experimental")
Type.ERROR -> sb.append("experimental and disabled")
}
val hintUrl = feature.hintUrl
if (hintUrl != null) {
if (useHtml) {
sb.append(" (").append("see more <a href=\"").append(hintUrl).append("\">here</a>)")
}
else {
sb.append(" (see: ").append(hintUrl).append(")")
}
}
return sb.toString()
}
}
@@ -711,7 +711,7 @@ class DeclarationsChecker(
}
}
else if (property.typeReference == null && !languageVersionSettings.supportsFeature(LanguageFeature.ShortSyntaxForPropertyGetters)) {
trace.report(Errors.UNSUPPORTED_FEATURE.on(property, LanguageFeature.ShortSyntaxForPropertyGetters))
trace.report(Errors.UNSUPPORTED_FEATURE.on(property, LanguageFeature.ShortSyntaxForPropertyGetters to languageVersionSettings))
}
else if (noExplicitTypeOrGetterType(property)) {
trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property))
@@ -22,6 +22,7 @@ import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import kotlin.Pair;
import kotlin.TuplesKt;
import kotlin.collections.CollectionsKt;
import kotlin.collections.SetsKt;
import kotlin.jvm.functions.Function0;
@@ -324,7 +325,8 @@ public class DescriptorResolver {
Function0<List<VariableDescriptor>> destructuringVariables;
if (destructuringDeclaration != null) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.DestructuringLambdaParameters)) {
trace.report(Errors.UNSUPPORTED_FEATURE.on(valueParameter, LanguageFeature.DestructuringLambdaParameters));
trace.report(Errors.UNSUPPORTED_FEATURE.on(valueParameter,
TuplesKt.to(LanguageFeature.DestructuringLambdaParameters, languageVersionSettings)));
}
destructuringVariables = new Function0<List<VariableDescriptor>>() {
@@ -742,7 +744,8 @@ public class DescriptorResolver {
else if (!languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)) {
typeResolver.resolveAbbreviatedType(scopeWithTypeParameters, typeReference, trace);
PsiElement typeAliasKeyword = typeAlias.getTypeAliasKeyword();
trace.report(UNSUPPORTED_FEATURE.on(typeAliasKeyword != null ? typeAliasKeyword : typeAlias, LanguageFeature.TypeAliases));
trace.report(UNSUPPORTED_FEATURE.on(typeAliasKeyword != null ? typeAliasKeyword : typeAlias,
TuplesKt.to(LanguageFeature.TypeAliases, languageVersionSettings)));
typeAliasDescriptor.initialize(
typeParameterDescriptors,
ErrorUtils.createErrorType(name.asString()),
@@ -77,7 +77,7 @@ class LocalVariableResolver(
val delegateExpression = property.delegateExpression
if (delegateExpression != null) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.LocalDelegatedProperties)) {
context.trace.report(LOCAL_VARIABLE_WITH_DELEGATE.on(property.delegate!!))
context.trace.report(UNSUPPORTED_FEATURE.on(property.delegate!!, LanguageFeature.LocalDelegatedProperties to languageVersionSettings))
}
if (propertyDescriptor is VariableDescriptorWithAccessors) {
@@ -277,6 +277,7 @@ object ModifierCheckerCore {
val errorOnDependencyFeature = errorOnFeature[dependency]?.let { languageVersionSettings.supportsFeature(it) } ?: false
val supportsFeature = languageVersionSettings.supportsFeature(dependency)
val diagnosticData = dependency to languageVersionSettings
if (!supportsFeature || errorOnDependencyFeature) {
val restrictedTargets = featureDependenciesTargets[dependency]
if (restrictedTargets != null && actualTargets.intersect(restrictedTargets).isEmpty()) {
@@ -284,17 +285,17 @@ object ModifierCheckerCore {
}
if (!supportsFeature) {
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, dependency))
trace.report(Errors.UNSUPPORTED_FEATURE.on(node.psi, diagnosticData))
}
else if (errorOnDependencyFeature) {
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, dependency))
trace.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(node.psi, diagnosticData))
}
return false
}
val pairedWarningFeature = warningOnFeature[dependency]
if (pairedWarningFeature != null && languageVersionSettings.supportsFeature(pairedWarningFeature)) {
trace.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(node.psi, dependency))
trace.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(node.psi, diagnosticData))
}
return true
@@ -66,7 +66,7 @@ object OperatorModifierChecker {
private fun checkSupportsFeature(feature: LanguageFeature, languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, modifier: PsiElement) {
if (!languageVersionSettings.supportsFeature(feature)) {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature))
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(modifier, feature to languageVersionSettings))
}
}
}
@@ -512,7 +512,7 @@ class TypeResolver(
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
}
if (!languageVersionSettings.supportsFeature(LanguageFeature.TypeAliases)) {
c.trace.report(UNSUPPORTED_FEATURE.on(type, LanguageFeature.TypeAliases))
c.trace.report(UNSUPPORTED_FEATURE.on(type, LanguageFeature.TypeAliases to languageVersionSettings))
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
}
@@ -35,7 +35,8 @@ class CallableReferenceCompatibilityChecker : CallChecker {
val callableReferenceResolvedCall = argumentExpression.callableReference.getResolvedCall(context.trace.bindingContext) ?: continue@inner
if (callableReferenceResolvedCall.call.isCallableReference() &&
callableReferenceResolvedCall.candidateDescriptor.typeParameters.isNotEmpty()) {
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(argumentExpression, typeInferenceForCallableReferencesFeature))
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(argumentExpression,
typeInferenceForCallableReferencesFeature to context.languageVersionSettings))
}
}
}
@@ -89,14 +89,15 @@ object BuilderFunctionsCallChecker : CallChecker {
}
fun checkCoroutinesFeature(languageVersionSettings: LanguageVersionSettings, diagnosticHolder: DiagnosticSink, reportOn: PsiElement) {
val diagnosticData = LanguageFeature.Coroutines to languageVersionSettings
if (!languageVersionSettings.supportsFeature(LanguageFeature.Coroutines)) {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, LanguageFeature.Coroutines))
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(reportOn, diagnosticData))
}
else if (languageVersionSettings.supportsFeature(LanguageFeature.ErrorOnCoroutines)) {
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(reportOn, LanguageFeature.Coroutines))
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_ERROR.on(reportOn, diagnosticData))
}
else if (languageVersionSettings.supportsFeature(LanguageFeature.WarnOnCoroutines)) {
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(reportOn, LanguageFeature.Coroutines))
diagnosticHolder.report(Errors.EXPERIMENTAL_FEATURE_WARNING.on(reportOn, diagnosticData))
}
}
@@ -42,7 +42,7 @@ object UnderscoreChecker : DeclarationChecker {
diagnosticHolder.report(Errors.UNDERSCORE_IS_RESERVED.on(identifier))
}
else if (isValidSingleUnderscore && !languageVersionSettings.supportsFeature(LanguageFeature.SingleUnderscoreForParameterName)) {
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(identifier, LanguageFeature.SingleUnderscoreForParameterName))
diagnosticHolder.report(Errors.UNSUPPORTED_FEATURE.on(identifier, LanguageFeature.SingleUnderscoreForParameterName to languageVersionSettings))
}
}
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import kotlin.TuplesKt;
import kotlin.jvm.functions.Function0;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
@@ -238,7 +239,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (!text.contains("_")) return;
if (!components.languageVersionSettings.supportsFeature(LanguageFeature.UnderscoresInNumericLiterals)) {
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(expression, LanguageFeature.UnderscoresInNumericLiterals));
context.trace.report(Errors.UNSUPPORTED_FEATURE.on(expression,
TuplesKt.to(LanguageFeature.UnderscoresInNumericLiterals, components.languageVersionSettings)));
return;
}
@@ -198,7 +198,7 @@ class DoubleColonExpressionResolver(
private fun reportUnsupportedIfNeeded(expression: KtDoubleColonExpression, c: ExpressionTypingContext) {
if (!languageVersionSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) {
c.trace.report(UNSUPPORTED_FEATURE.on(expression.receiverExpression!!, LanguageFeature.BoundCallableReferences))
c.trace.report(UNSUPPORTED_FEATURE.on(expression.receiverExpression!!, LanguageFeature.BoundCallableReferences to languageVersionSettings))
}
}