From b6fa10cf9ebf81cb05e5d91aaea842fc7e9b8323 Mon Sep 17 00:00:00 2001 From: Stanislav Erokhin Date: Mon, 13 Feb 2017 09:48:55 +0300 Subject: [PATCH] Disable some features when LV=1.1 API=1.0. Feature list: - bound callable references - local delegated properties - coroutines. #KT-16017 Fixed --- .../jetbrains/kotlin/diagnostics/Errors.java | 8 +-- .../rendering/DefaultErrorMessages.java | 30 ++------ .../LanguageFeatureMessageRenderer.kt | 69 +++++++++++++++++++ .../kotlin/resolve/DeclarationsChecker.kt | 2 +- .../kotlin/resolve/DescriptorResolver.java | 7 +- .../kotlin/resolve/LocalVariableResolver.kt | 2 +- .../kotlin/resolve/ModifiersChecker.kt | 7 +- .../kotlin/resolve/OperatorModifierChecker.kt | 2 +- .../jetbrains/kotlin/resolve/TypeResolver.kt | 2 +- .../CallableReferenceCompatibilityChecker.kt | 3 +- .../calls/checkers/coroutineCallChecker.kt | 7 +- .../resolve/checkers/UnderscoreChecker.kt | 2 +- .../BasicExpressionTypingVisitor.java | 4 +- .../DoubleColonExpressionResolver.kt | 2 +- compiler/testData/cli/jvm/apiVersion.out | 5 +- compiler/testData/cli/jvm/apiVersion1.0.args | 7 ++ compiler/testData/cli/jvm/apiVersion1.0.kt | 16 +++++ compiler/testData/cli/jvm/apiVersion1.0.out | 13 ++++ .../cli/jvm/apiVersionLessThanLanguage.out | 5 +- compiler/testData/cli/jvm/coroutines.kt | 1 + .../testData/cli/jvm/coroutinesEnable.args | 4 ++ .../testData/cli/jvm/coroutinesEnable.out | 1 + .../testData/cli/jvm/coroutinesError.args | 4 ++ compiler/testData/cli/jvm/coroutinesError.out | 4 ++ .../testData/cli/jvm/coroutinesWarninig.args | 4 ++ .../testData/cli/jvm/coroutinesWarninig.out | 4 ++ compiler/testData/cli/jvm/languageVersion.out | 4 +- .../testData/cli/jvm/unsupportedTypeAlias.out | 2 +- .../noLocalDelegatedProperty.kt | 6 +- .../noLocalDelegatedPropertyInScript.kt | 4 +- .../suspendCoroutineUnavailableWithOldAPI.kt | 4 +- .../kotlin/checkers/BaseDiagnosticsTest.kt | 4 +- .../kotlin/cli/CliTestGenerated.java | 24 +++++++ .../kotlin/config/LanguageVersionSettings.kt | 14 ++-- .../idea/highlighter/IdeErrorMessages.java | 4 ++ .../quickfix/ChangeCoroutineSupportFix.kt | 4 +- .../quickfix/EnableUnsupportedFeatureFix.kt | 2 +- .../unsupportedFeature1.html | 3 + .../diagnosticMessage/unsupportedFeature1.txt | 2 - .../diagnosticMessage/urlMultiproject1.txt | 2 - .../{urlMultiproject.kt => urlRender.kt} | 4 +- .../diagnosticMessage/urlRender1.html | 3 + .../DiagnosticMessageTestGenerated.java | 6 +- 43 files changed, 232 insertions(+), 75 deletions(-) create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/LanguageFeatureMessageRenderer.kt create mode 100644 compiler/testData/cli/jvm/apiVersion1.0.args create mode 100644 compiler/testData/cli/jvm/apiVersion1.0.kt create mode 100644 compiler/testData/cli/jvm/apiVersion1.0.out create mode 100644 compiler/testData/cli/jvm/coroutines.kt create mode 100644 compiler/testData/cli/jvm/coroutinesEnable.args create mode 100644 compiler/testData/cli/jvm/coroutinesEnable.out create mode 100644 compiler/testData/cli/jvm/coroutinesError.args create mode 100644 compiler/testData/cli/jvm/coroutinesError.out create mode 100644 compiler/testData/cli/jvm/coroutinesWarninig.args create mode 100644 compiler/testData/cli/jvm/coroutinesWarninig.out create mode 100644 idea/testData/diagnosticMessage/unsupportedFeature1.html delete mode 100644 idea/testData/diagnosticMessage/unsupportedFeature1.txt delete mode 100644 idea/testData/diagnosticMessage/urlMultiproject1.txt rename idea/testData/diagnosticMessage/{urlMultiproject.kt => urlRender.kt} (58%) create mode 100644 idea/testData/diagnosticMessage/urlRender1.html diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 72b962e0ba9..0f38fa61194 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -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 UNSUPPORTED = DiagnosticFactory1.create(ERROR); - DiagnosticFactory1 UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1> UNSUPPORTED_FEATURE = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 EXCEPTION_FROM_ANALYZER = DiagnosticFactory1.create(ERROR); - DiagnosticFactory1 EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING); - DiagnosticFactory1 EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1> EXPERIMENTAL_FEATURE_WARNING = DiagnosticFactory1.create(WARNING); + DiagnosticFactory1> EXPERIMENTAL_FEATURE_ERROR = DiagnosticFactory1.create(ERROR); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -453,7 +454,6 @@ public interface Errors { DiagnosticFactory0 ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 75296694023..ae9f3d2c8aa 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -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() { - @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() { - @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() { - @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"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/LanguageFeatureMessageRenderer.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/LanguageFeatureMessageRenderer.kt new file mode 100644 index 00000000000..7ea505c7d7d --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/LanguageFeatureMessageRenderer.kt @@ -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> { + + enum class Type { + UNSUPPORTED, + WARNING, + ERROR + } + + override fun render(obj: Pair, 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 here)") + } + else { + sb.append(" (see: ").append(hintUrl).append(")") + } + } + + return sb.toString() + } +} \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt index 3fc14e13de7..2304926f828 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DeclarationsChecker.kt @@ -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)) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 5304354182f..da86d027830 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -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> 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>() { @@ -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()), diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt index 1d735fefe42..0e15470022d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/LocalVariableResolver.kt @@ -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) { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt index 186c1ed9528..fd9441e1740 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/ModifiersChecker.kt @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OperatorModifierChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OperatorModifierChecker.kt index 69cb03406cb..171b9270add 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/OperatorModifierChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/OperatorModifierChecker.kt @@ -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)) } } } \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt index a69ec17cc80..afcd86ac399 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeResolver.kt @@ -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) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallableReferenceCompatibilityChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallableReferenceCompatibilityChecker.kt index 60789b3d1ff..c694d3c3564 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallableReferenceCompatibilityChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/CallableReferenceCompatibilityChecker.kt @@ -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)) } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt index 00b86c91c8c..28a6647163c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/coroutineCallChecker.kt @@ -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)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt index 0fa7fb7416b..b0d3d6f7d79 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/UnderscoreChecker.kt @@ -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)) } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index d1bf78d9aa3..5193df13d51 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -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; } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index 06b5d08dbb3..639a8ed6c4c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -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)) } } diff --git a/compiler/testData/cli/jvm/apiVersion.out b/compiler/testData/cli/jvm/apiVersion.out index 33e62bb3fde..95f1f2de777 100644 --- a/compiler/testData/cli/jvm/apiVersion.out +++ b/compiler/testData/cli/jvm/apiVersion.out @@ -1,4 +1,7 @@ +compiler/testData/cli/jvm/apiVersion.kt:2:5: error: the feature "bound callable references" is only available since API version 1.1 + ""::class.isInstance(42) + ^ compiler/testData/cli/jvm/apiVersion.kt:2:15: error: unresolved reference: isInstance ""::class.isInstance(42) ^ -COMPILATION_ERROR +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/apiVersion1.0.args b/compiler/testData/cli/jvm/apiVersion1.0.args new file mode 100644 index 00000000000..6ef00e03add --- /dev/null +++ b/compiler/testData/cli/jvm/apiVersion1.0.args @@ -0,0 +1,7 @@ +$TESTDATA_DIR$/apiVersion1.0.kt +-d +$TEMP_DIR$ +-language-version +1.1 +-api-version +1.0 diff --git a/compiler/testData/cli/jvm/apiVersion1.0.kt b/compiler/testData/cli/jvm/apiVersion1.0.kt new file mode 100644 index 00000000000..8ff55ac16ed --- /dev/null +++ b/compiler/testData/cli/jvm/apiVersion1.0.kt @@ -0,0 +1,16 @@ +typealias Foo = Int + +sealed class A +data class B(val foo: Int): A() + +inline val f get() = "" + +suspend fun test() { + ""::class + ""::toString + + Foo::class + Foo::toString + + val b by lazy { "" } +} diff --git a/compiler/testData/cli/jvm/apiVersion1.0.out b/compiler/testData/cli/jvm/apiVersion1.0.out new file mode 100644 index 00000000000..191a35e0b83 --- /dev/null +++ b/compiler/testData/cli/jvm/apiVersion1.0.out @@ -0,0 +1,13 @@ +compiler/testData/cli/jvm/apiVersion1.0.kt:8:1: error: the feature "coroutines" is only available since API version 1.1 (see: https://kotlinlang.org/docs/diagnostics/experimental-coroutines) +suspend fun test() { +^ +compiler/testData/cli/jvm/apiVersion1.0.kt:9:5: error: the feature "bound callable references" is only available since API version 1.1 + ""::class + ^ +compiler/testData/cli/jvm/apiVersion1.0.kt:10:5: error: the feature "bound callable references" is only available since API version 1.1 + ""::toString + ^ +compiler/testData/cli/jvm/apiVersion1.0.kt:15:11: error: the feature "local delegated properties" is only available since API version 1.1 + val b by lazy { "" } + ^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out b/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out index 33e62bb3fde..95f1f2de777 100644 --- a/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out +++ b/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out @@ -1,4 +1,7 @@ +compiler/testData/cli/jvm/apiVersion.kt:2:5: error: the feature "bound callable references" is only available since API version 1.1 + ""::class.isInstance(42) + ^ compiler/testData/cli/jvm/apiVersion.kt:2:15: error: unresolved reference: isInstance ""::class.isInstance(42) ^ -COMPILATION_ERROR +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/coroutines.kt b/compiler/testData/cli/jvm/coroutines.kt new file mode 100644 index 00000000000..7a97890f55d --- /dev/null +++ b/compiler/testData/cli/jvm/coroutines.kt @@ -0,0 +1 @@ +suspend fun simple() = 5 \ No newline at end of file diff --git a/compiler/testData/cli/jvm/coroutinesEnable.args b/compiler/testData/cli/jvm/coroutinesEnable.args new file mode 100644 index 00000000000..84ddd5dcce5 --- /dev/null +++ b/compiler/testData/cli/jvm/coroutinesEnable.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/coroutines.kt +-d +$TEMP_DIR$ +-Xcoroutines=enable diff --git a/compiler/testData/cli/jvm/coroutinesEnable.out b/compiler/testData/cli/jvm/coroutinesEnable.out new file mode 100644 index 00000000000..d86bac9de59 --- /dev/null +++ b/compiler/testData/cli/jvm/coroutinesEnable.out @@ -0,0 +1 @@ +OK diff --git a/compiler/testData/cli/jvm/coroutinesError.args b/compiler/testData/cli/jvm/coroutinesError.args new file mode 100644 index 00000000000..f52a3671cf6 --- /dev/null +++ b/compiler/testData/cli/jvm/coroutinesError.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/coroutines.kt +-d +$TEMP_DIR$ +-Xcoroutines=error \ No newline at end of file diff --git a/compiler/testData/cli/jvm/coroutinesError.out b/compiler/testData/cli/jvm/coroutinesError.out new file mode 100644 index 00000000000..2b99464d215 --- /dev/null +++ b/compiler/testData/cli/jvm/coroutinesError.out @@ -0,0 +1,4 @@ +compiler/testData/cli/jvm/coroutines.kt:1:1: error: the feature "coroutines" is experimental and disabled (see: https://kotlinlang.org/docs/diagnostics/experimental-coroutines) +suspend fun simple() = 5 +^ +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/coroutinesWarninig.args b/compiler/testData/cli/jvm/coroutinesWarninig.args new file mode 100644 index 00000000000..9b3bbd9a87e --- /dev/null +++ b/compiler/testData/cli/jvm/coroutinesWarninig.args @@ -0,0 +1,4 @@ +$TESTDATA_DIR$/coroutines.kt +-d +$TEMP_DIR$ +-Xcoroutines=warn diff --git a/compiler/testData/cli/jvm/coroutinesWarninig.out b/compiler/testData/cli/jvm/coroutinesWarninig.out new file mode 100644 index 00000000000..f06a42ab8cb --- /dev/null +++ b/compiler/testData/cli/jvm/coroutinesWarninig.out @@ -0,0 +1,4 @@ +compiler/testData/cli/jvm/coroutines.kt:1:1: warning: the feature "coroutines" is experimental (see: https://kotlinlang.org/docs/diagnostics/experimental-coroutines) +suspend fun simple() = 5 +^ +OK \ No newline at end of file diff --git a/compiler/testData/cli/jvm/languageVersion.out b/compiler/testData/cli/jvm/languageVersion.out index 4bd2f466360..7179b172f54 100644 --- a/compiler/testData/cli/jvm/languageVersion.out +++ b/compiler/testData/cli/jvm/languageVersion.out @@ -1,10 +1,10 @@ compiler/testData/cli/jvm/languageVersion.kt:5:17: error: this type is sealed, so it can be inherited by only its own nested classes or objects class Derived : Base() ^ -compiler/testData/cli/jvm/languageVersion.kt:8:5: error: the feature is only available since Kotlin 1.1: bound callable references +compiler/testData/cli/jvm/languageVersion.kt:8:5: error: the feature "bound callable references" is only available since language version 1.1 ""::class.isInstance(42) ^ compiler/testData/cli/jvm/languageVersion.kt:8:15: error: unresolved reference: isInstance ""::class.isInstance(42) ^ -COMPILATION_ERROR +COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/cli/jvm/unsupportedTypeAlias.out b/compiler/testData/cli/jvm/unsupportedTypeAlias.out index fb5f3e044d2..67a5ca56461 100644 --- a/compiler/testData/cli/jvm/unsupportedTypeAlias.out +++ b/compiler/testData/cli/jvm/unsupportedTypeAlias.out @@ -1,4 +1,4 @@ -compiler/testData/cli/jvm/unsupportedTypeAlias.kt:3:1: error: the feature is only available since Kotlin 1.1: type aliases +compiler/testData/cli/jvm/unsupportedTypeAlias.kt:3:1: error: the feature "type aliases" is only available since language version 1.1 typealias Unused = String ^ COMPILATION_ERROR \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedProperty.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedProperty.kt index b43bded65ab..6b192962382 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedProperty.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedProperty.kt @@ -6,13 +6,13 @@ class Delegate { } fun foo(): Int { - val prop: Int by Delegate() + val prop: Int by Delegate() - val prop2: Int by 123 + val prop2: Int by 123 val obj = object { fun v(): Int { - val prop3: Int by Delegate() + val prop3: Int by Delegate() return prop3 } } diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedPropertyInScript.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedPropertyInScript.kt index 6c445015aa7..3765da85bee 100644 --- a/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedPropertyInScript.kt +++ b/compiler/testData/diagnostics/tests/sourceCompatibility/noLocalDelegatedPropertyInScript.kt @@ -8,9 +8,9 @@ class Delegate { } fun foo(): Int { - val prop: Int by Delegate() + val prop: Int by Delegate() - val prop2: Int by 123 + val prop2: Int by 123 return prop + prop2 } diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineUnavailableWithOldAPI.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineUnavailableWithOldAPI.kt index 29265db81f0..fdae1824309 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineUnavailableWithOldAPI.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendCoroutineUnavailableWithOldAPI.kt @@ -4,11 +4,11 @@ import kotlin.coroutines.experimental.* import kotlin.coroutines.experimental.intrinsics.* -suspend fun foo(): Unit = suspendCoroutine { +suspend fun foo(): Unit = suspendCoroutine { it.resume(Unit) } -suspend fun bar(): Unit = suspendCoroutineOrReturn { +suspend fun bar(): Unit = suspendCoroutineOrReturn { it.resume(Unit) COROUTINE_SUSPENDED } diff --git a/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt b/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt index a169b5ab530..c2356fd6458 100644 --- a/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt +++ b/compiler/tests-common/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.kt @@ -104,8 +104,10 @@ abstract class BaseDiagnosticsTest : KotlinMultiFileTestWithJava= since) || feature in additionalFeatures + return (since != null && languageVersion >= since && apiVersion >= feature.sinceApiVersion) || feature in additionalFeatures } override fun toString() = buildString { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/IdeErrorMessages.java b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/IdeErrorMessages.java index 25f23bfa9c1..c987d3114e6 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/IdeErrorMessages.java +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/highlighter/IdeErrorMessages.java @@ -171,6 +171,10 @@ public class IdeErrorMessages { MAP.put(ErrorsJs.JSCODE_ERROR, "JavaScript: {0}", JsCallDataHtmlRenderer.INSTANCE); MAP.put(ErrorsJs.JSCODE_WARNING, "JavaScript: {0}", JsCallDataHtmlRenderer.INSTANCE); + MAP.put(UNSUPPORTED_FEATURE, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.UNSUPPORTED, true)); + MAP.put(EXPERIMENTAL_FEATURE_WARNING, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.WARNING, true)); + MAP.put(EXPERIMENTAL_FEATURE_ERROR, "{0}", new LanguageFeatureMessageRenderer(LanguageFeatureMessageRenderer.Type.ERROR, true)); + MAP.setImmutable(); } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt index 1d47fe1d4a6..ecf0edab328 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ChangeCoroutineSupportFix.kt @@ -85,11 +85,11 @@ sealed class ChangeCoroutineSupportFix( override fun doCreateActions(diagnostic: Diagnostic): List { val newCoroutineSupports = when (diagnostic.factory) { Errors.EXPERIMENTAL_FEATURE_ERROR -> { - if (Errors.EXPERIMENTAL_FEATURE_ERROR.cast(diagnostic).a != LanguageFeature.Coroutines) return emptyList() + if (Errors.EXPERIMENTAL_FEATURE_ERROR.cast(diagnostic).a.first != LanguageFeature.Coroutines) return emptyList() listOf(CoroutineSupport.ENABLED_WITH_WARNING, CoroutineSupport.ENABLED) } Errors.EXPERIMENTAL_FEATURE_WARNING -> { - if (Errors.EXPERIMENTAL_FEATURE_WARNING.cast(diagnostic).a != LanguageFeature.Coroutines) return emptyList() + if (Errors.EXPERIMENTAL_FEATURE_WARNING.cast(diagnostic).a.first != LanguageFeature.Coroutines) return emptyList() listOf(CoroutineSupport.ENABLED, CoroutineSupport.DISABLED) } else -> return emptyList() diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt index e8f2e4098d8..4bd3f10be25 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/EnableUnsupportedFeatureFix.kt @@ -79,7 +79,7 @@ sealed class EnableUnsupportedFeatureFix( companion object : KotlinSingleIntentionActionFactory() { override fun createAction(diagnostic: Diagnostic): EnableUnsupportedFeatureFix? { - val targetVersion = Errors.UNSUPPORTED_FEATURE.cast(diagnostic).a.sinceVersion ?: return null + val targetVersion = Errors.UNSUPPORTED_FEATURE.cast(diagnostic).a.first.sinceVersion ?: return null val module = ModuleUtilCore.findModuleForPsiElement(diagnostic.psiElement) ?: return null if (KotlinPluginUtil.isMavenModule(module)) return null if (!KotlinPluginUtil.isGradleModule(module)) { diff --git a/idea/testData/diagnosticMessage/unsupportedFeature1.html b/idea/testData/diagnosticMessage/unsupportedFeature1.html new file mode 100644 index 00000000000..a1b0db44f73 --- /dev/null +++ b/idea/testData/diagnosticMessage/unsupportedFeature1.html @@ -0,0 +1,3 @@ + + +The feature "destructuring lambda parameters" is only available since language version 1.1 \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/unsupportedFeature1.txt b/idea/testData/diagnosticMessage/unsupportedFeature1.txt deleted file mode 100644 index 3b1f04418f7..00000000000 --- a/idea/testData/diagnosticMessage/unsupportedFeature1.txt +++ /dev/null @@ -1,2 +0,0 @@ - -The feature is only available since Kotlin 1.1: destructuring lambda parameters \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/urlMultiproject1.txt b/idea/testData/diagnosticMessage/urlMultiproject1.txt deleted file mode 100644 index d80e189518f..00000000000 --- a/idea/testData/diagnosticMessage/urlMultiproject1.txt +++ /dev/null @@ -1,2 +0,0 @@ - -The feature is experimental and should be turned on explicitly via a command line option or in IDE settings: multi platform projects (See: https://kotlinlang.org/docs/diagnostics/experimental-multitraget-projects) \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/urlMultiproject.kt b/idea/testData/diagnosticMessage/urlRender.kt similarity index 58% rename from idea/testData/diagnosticMessage/urlMultiproject.kt rename to idea/testData/diagnosticMessage/urlRender.kt index 23514102532..8a76ed1f242 100644 --- a/idea/testData/diagnosticMessage/urlMultiproject.kt +++ b/idea/testData/diagnosticMessage/urlRender.kt @@ -1,5 +1,5 @@ // !DIAGNOSTICS_NUMBER: 1 // !DIAGNOSTICS: UNSUPPORTED_FEATURE -// !MESSAGE_TYPE: TEXT +// LANGUAGE_VERSION: 1.0 -impl fun test() {} \ No newline at end of file +suspend fun test() {} \ No newline at end of file diff --git a/idea/testData/diagnosticMessage/urlRender1.html b/idea/testData/diagnosticMessage/urlRender1.html new file mode 100644 index 00000000000..dd2ce04912e --- /dev/null +++ b/idea/testData/diagnosticMessage/urlRender1.html @@ -0,0 +1,3 @@ + + +The feature "coroutines" is only available since language version 1.1 (see more here) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java index 03a0ee75d01..39fa5214fe2 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/highlighter/DiagnosticMessageTestGenerated.java @@ -324,9 +324,9 @@ public class DiagnosticMessageTestGenerated extends AbstractDiagnosticMessageTes doTest(fileName); } - @TestMetadata("urlMultiproject.kt") - public void testUrlMultiproject() throws Exception { - String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/urlMultiproject.kt"); + @TestMetadata("urlRender.kt") + public void testUrlRender() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/diagnosticMessage/urlRender.kt"); doTest(fileName); } }