From 167ab1f860fc8a3541feb3d3b1c895ef26b5abae Mon Sep 17 00:00:00 2001
From: Alexander Udalov
Date: Mon, 26 Sep 2016 19:56:22 +0300
Subject: [PATCH] Introduce "-api-version" CLI option
The `@SinceKotlin("X.Y.Z")` annotation now hides a particular declaration from
resolution when the API version specified by the `-api-version` option is
_less_ than X.Y.Z. The comparison is performed as for versions in Maven:
MavenComparableVersion is in fact a copy of
org.apache.maven.artifact.versioning.ComparableVersion.
Also support "!API_VERSION" directive in diagnostic tests
#KT-14298 Fixed
---
.../arguments/CommonCompilerArguments.java | 5 +
.../kotlin/cli/common/CLICompiler.java | 59 +-
.../jetbrains/kotlin/diagnostics/Errors.java | 8 +-
.../rendering/DefaultErrorMessages.java | 2 +
.../kotlin/resolve/TargetPlatform.kt | 4 +-
.../calls/checkers/ApiVersionCallChecker.kt | 47 ++
.../calls/checkers/DeprecatedCallChecker.kt | 2 +-
.../ApiVersionClassifierUsageChecker.kt | 37 ++
.../kotlin/resolve/deprecationUtil.kt | 3 +
.../kotlin/resolve/sinceKotlinUtil.kt | 48 ++
compiler/testData/cli/js/jsHelp.out | 1 +
compiler/testData/cli/jvm/apiVersion.args | 5 +
compiler/testData/cli/jvm/apiVersion.kt | 3 +
compiler/testData/cli/jvm/apiVersion.out | 4 +
.../jvm/apiVersionGreaterThanLanguage.args | 7 +
.../cli/jvm/apiVersionGreaterThanLanguage.out | 2 +
.../testData/cli/jvm/apiVersionInvalid.args | 5 +
.../testData/cli/jvm/apiVersionInvalid.out | 3 +
.../cli/jvm/apiVersionLessThanLanguage.args | 7 +
.../cli/jvm/apiVersionLessThanLanguage.out | 4 +
compiler/testData/cli/jvm/help.out | 1 +
compiler/testData/cli/jvm/languageVersion.kt | 4 +
compiler/testData/cli/jvm/languageVersion.out | 6 +
compiler/testData/cli/jvm/wrongArgument.out | 1 +
compiler/testData/diagnostics/ReadMe.md | 8 +
.../duplicateMethod/sinceKotlin.kt | 34 ++
.../duplicateMethod/sinceKotlin.txt | 29 +
.../hiddenClass/sinceKotlinImportPriority.kt | 38 ++
.../hiddenClass/sinceKotlinImportPriority.txt | 49 ++
.../hiddenClass/sinceKotlinMultipleClasses.kt | 47 ++
.../sinceKotlinMultipleClasses.txt | 71 +++
.../apiVersion/annotations.kt | 11 +
.../apiVersion/annotations.txt | 18 +
.../apiVersion/classesAndConstructors.kt | 19 +
.../apiVersion/classesAndConstructors.txt | 27 +
.../apiVersion/overriddenMembers.kt | 34 ++
.../apiVersion/overriddenMembers.txt | 59 ++
.../apiVersion/propertyAccessors.kt | 48 ++
.../apiVersion/propertyAccessors.txt | 10 +
.../apiVersion/simpleMembers.kt | 19 +
.../apiVersion/simpleMembers.txt | 9 +
.../apiVersion/sinceOldVersionIsOK.kt | 18 +
.../apiVersion/sinceOldVersionIsOK.txt | 10 +
.../checkers/AbstractDiagnosticsTest.java | 14 +-
.../kotlin/checkers/BaseDiagnosticsTest.java | 69 ++-
.../checkers/DiagnosticsTestGenerated.java | 63 +++
.../kotlin/cli/CliTestGenerated.java | 24 +
.../kotlin/code/CodeConformanceTest.kt | 5 +-
.../org/jetbrains/kotlin/config/ApiVersion.kt | 48 ++
.../kotlin/config/LanguageVersionSettings.kt | 15 +-
.../kotlin/config/MavenComparableVersion.java | 504 ++++++++++++++++++
core/builtins/src/kotlin/reflect/KClass.kt | 1 +
.../AbstractDiagnosticMessageJsTest.java | 8 +-
.../AbstractDiagnosticMessageTest.java | 8 +-
.../kotlin/gradle/dsl/KotlinJsOptions.kt | 7 +
.../kotlin/gradle/dsl/KotlinJsOptionsBase.kt | 7 +
.../kotlin/gradle/dsl/KotlinJvmOptions.kt | 7 +
.../kotlin/gradle/dsl/KotlinJvmOptionsBase.kt | 7 +
license/third_party/maven_LICENSE.txt | 202 +++++++
59 files changed, 1758 insertions(+), 57 deletions(-)
create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ApiVersionCallChecker.kt
create mode 100644 compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ApiVersionClassifierUsageChecker.kt
create mode 100644 compiler/testData/cli/jvm/apiVersion.args
create mode 100644 compiler/testData/cli/jvm/apiVersion.kt
create mode 100644 compiler/testData/cli/jvm/apiVersion.out
create mode 100644 compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args
create mode 100644 compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.out
create mode 100644 compiler/testData/cli/jvm/apiVersionInvalid.args
create mode 100644 compiler/testData/cli/jvm/apiVersionInvalid.out
create mode 100644 compiler/testData/cli/jvm/apiVersionLessThanLanguage.args
create mode 100644 compiler/testData/cli/jvm/apiVersionLessThanLanguage.out
create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt
create mode 100644 compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.txt
create mode 100644 compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.kt
create mode 100644 compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.txt
create mode 100644 compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.kt
create mode 100644 compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.txt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.kt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.txt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.kt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.txt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.kt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.txt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.kt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.txt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.txt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.kt
create mode 100644 compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.txt
create mode 100644 compiler/util/src/org/jetbrains/kotlin/config/ApiVersion.kt
create mode 100644 compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java
create mode 100644 license/third_party/maven_LICENSE.txt
diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java
index 906a7412cbe..ce6bf7889a5 100644
--- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java
+++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/CommonCompilerArguments.java
@@ -30,6 +30,11 @@ public abstract class CommonCompilerArguments {
@ValueDescription("")
public String languageVersion;
+ @GradleOption(DefaultValues.LanguageVersions.class)
+ @Argument(value = "api-version", description = "Allow to use declarations only from the specified version of bundled libraries")
+ @ValueDescription("")
+ public String apiVersion;
+
@GradleOption(DefaultValues.BooleanFalseDefault.class)
@Argument(value = "nowarn", description = "Generate no warnings")
public boolean suppressWarnings;
diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java
index 7e0b3541245..0b6f5b24803 100644
--- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java
+++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java
@@ -248,27 +248,58 @@ public abstract class CLICompiler {
configuration.put(CLIConfigurationKeys.COMPILER_JAR_LOCATOR, locator);
}
- if (arguments.languageVersion != null) {
- LanguageVersion languageVersion = LanguageVersion.fromVersionString(arguments.languageVersion);
- if (languageVersion != null) {
- configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, new LanguageVersionSettingsImpl(languageVersion));
+ LanguageVersion languageVersion = parseVersion(configuration, arguments.languageVersion, "language");
+ LanguageVersion apiVersion = parseVersion(configuration, arguments.apiVersion, "API");
+ if (languageVersion != null || apiVersion != null) {
+ if (languageVersion == null) {
+ // If only "-api-version" is specified, language version is assumed to be the latest
+ languageVersion = LanguageVersion.LATEST;
}
- else {
- List versionStrings = ArraysKt.map(LanguageVersion.values(), new Function1() {
- @Override
- public String invoke(LanguageVersion version) {
- return version.getVersionString();
- }
- });
- String message = "Unknown language version: " + arguments.languageVersion + "\n" +
- "Supported language versions: " + StringsKt.join(versionStrings, ", ");
+ if (apiVersion == null) {
+ // If only "-language-version" is specified, API version is assumed to be equal to the language version
+ // (API version cannot be greater than the language version)
+ apiVersion = languageVersion;
+ }
+
+ if (apiVersion.compareTo(languageVersion) > 0) {
configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
- CompilerMessageSeverity.ERROR, message, CompilerMessageLocation.NO_LOCATION
+ CompilerMessageSeverity.ERROR,
+ "-api-version (" + apiVersion.getVersionString() + ") cannot be greater than " +
+ "-language-version (" + languageVersion.getVersionString() + ")",
+ CompilerMessageLocation.NO_LOCATION
);
}
+
+ configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
+ new LanguageVersionSettingsImpl(languageVersion, ApiVersion.createByLanguageVersion(apiVersion)));
}
}
+ private static LanguageVersion parseVersion(
+ @NotNull CompilerConfiguration configuration, @Nullable String value, @NotNull String versionOf
+ ) {
+ if (value == null) return null;
+
+ LanguageVersion version = LanguageVersion.fromVersionString(value);
+ if (version != null) {
+ return version;
+ }
+
+ List versionStrings = ArraysKt.map(LanguageVersion.values(), new Function1() {
+ @Override
+ public String invoke(LanguageVersion version) {
+ return version.getVersionString();
+ }
+ });
+ String message = "Unknown " + versionOf + " version: " + value + "\n" +
+ "Supported " + versionOf + " versions: " + StringsKt.join(versionStrings, ", ");
+ configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY).report(
+ CompilerMessageSeverity.ERROR, message, CompilerMessageLocation.NO_LOCATION
+ );
+
+ return null;
+ }
+
protected abstract void setupPlatformSpecificArgumentsAndServices(
@NotNull CompilerConfiguration configuration, @NotNull A arguments, @NotNull Services services
);
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
index 06b990407ab..73646f21242 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java
@@ -73,6 +73,11 @@ public interface Errors {
DiagnosticFactory1 UNRESOLVED_REFERENCE =
DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE);
+ DiagnosticFactory2 DEPRECATION = DiagnosticFactory2.create(WARNING);
+ DiagnosticFactory2 DEPRECATION_ERROR = DiagnosticFactory2.create(ERROR);
+
+ DiagnosticFactory2 API_NOT_AVAILABLE = DiagnosticFactory2.create(ERROR);
+
//Elements with "INVISIBLE_REFERENCE" error are marked as unresolved, unlike elements with "INVISIBLE_MEMBER" error
//"INVISIBLE_REFERENCE" is used for invisible classes references and references in import
DiagnosticFactory3 INVISIBLE_REFERENCE =
@@ -278,9 +283,6 @@ public interface Errors {
DiagnosticFactory0 MANY_COMPANION_OBJECTS = DiagnosticFactory0.create(ERROR, COMPANION_OBJECT);
- DiagnosticFactory2 DEPRECATION = DiagnosticFactory2.create(WARNING);
- DiagnosticFactory2 DEPRECATION_ERROR = DiagnosticFactory2.create(ERROR);
-
// Objects
DiagnosticFactory1 LOCAL_OBJECT_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, DECLARATION_NAME);
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 8a7e24a5edf..b7ff3119e07 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java
+++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java
@@ -300,6 +300,8 @@ public class DefaultErrorMessages {
MAP.put(DEPRECATION, "''{0}'' is deprecated. {1}", DEPRECATION_RENDERER, STRING);
MAP.put(DEPRECATION_ERROR, "Using ''{0}'' is an error. {1}", DEPRECATION_RENDERER, STRING);
+ MAP.put(API_NOT_AVAILABLE, "This declaration is only available since Kotlin {0} and cannot be used with the specified API version {1}", STRING, STRING);
+
MAP.put(LOCAL_OBJECT_NOT_ALLOWED, "Named object ''{0}'' is a singleton and cannot be local. Try to use anonymous object instead", NAME);
MAP.put(LOCAL_INTERFACE_NOT_ALLOWED, "''{0}'' is an interface so it cannot be local. Try to use anonymous object or abstract class instead", NAME);
MAP.put(ENUM_CLASS_CONSTRUCTOR_CALL, "Enum types cannot be instantiated");
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt
index e45eea384b1..b892437ac48 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TargetPlatform.kt
@@ -71,11 +71,11 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
private val DEFAULT_CALL_CHECKERS = listOf(
CapturingInClosureChecker(), InlineCheckerWrapper(), ReifiedTypeParameterSubstitutionChecker(), SafeCallChecker(),
DeprecatedCallChecker, CallReturnsArrayOfNothingChecker(), InfixCallChecker(), OperatorCallChecker(),
- ConstructorHeaderCallChecker, ProtectedConstructorCallChecker,
+ ConstructorHeaderCallChecker, ProtectedConstructorCallChecker, ApiVersionCallChecker,
CoroutineSuspendCallChecker, BuilderFunctionsCallChecker
)
private val DEFAULT_TYPE_CHECKERS = emptyList()
-private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(DeprecatedClassifierUsageChecker())
+private val DEFAULT_CLASSIFIER_USAGE_CHECKERS = listOf(DeprecatedClassifierUsageChecker(), ApiVersionClassifierUsageChecker)
abstract class PlatformConfigurator(
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ApiVersionCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ApiVersionCallChecker.kt
new file mode 100644
index 00000000000..20d9000c340
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/ApiVersionCallChecker.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ * 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.resolve.calls.checkers
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.diagnostics.Errors.API_NOT_AVAILABLE
+import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
+import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
+import org.jetbrains.kotlin.resolve.checkSinceKotlinVersionAccessibility
+
+// TODO: consider combining with DeprecatedCallChecker somehow
+object ApiVersionCallChecker : CallChecker {
+ override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
+ check(resolvedCall.resultingDescriptor, context, reportOn)
+ }
+
+ private fun check(targetDescriptor: CallableDescriptor, context: CallCheckerContext, element: PsiElement) {
+ // Objects will be checked by ApiVersionClassifierUsageChecker
+ if (targetDescriptor is FakeCallableDescriptorForObject) return
+
+ val accessible = targetDescriptor.checkSinceKotlinVersionAccessibility(context.languageVersionSettings) { version ->
+ context.trace.report(
+ API_NOT_AVAILABLE.on(element, version.versionString, context.languageVersionSettings.apiVersion.versionString)
+ )
+ }
+
+ if (accessible && targetDescriptor is PropertyDescriptor && DeprecatedCallChecker.shouldCheckPropertyGetter(element)) {
+ targetDescriptor.getter?.let { check(it, context, element) }
+ }
+ }
+}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt
index 862cb7ec569..2be15fe9c5f 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/DeprecatedCallChecker.kt
@@ -57,7 +57,7 @@ object DeprecatedCallChecker : CallChecker {
private val PROPERTY_SET_OPERATIONS = TokenSet.create(*KtTokens.ALL_ASSIGNMENTS.types, KtTokens.PLUSPLUS, KtTokens.MINUSMINUS)
- private fun shouldCheckPropertyGetter(expression: PsiElement): Boolean {
+ internal fun shouldCheckPropertyGetter(expression: PsiElement): Boolean {
// property getters do not come as callable yet, so we analyse surroundings to check for deprecation annotation on getter
val binaryExpression = PsiTreeUtil.getParentOfType(expression, KtBinaryExpression::class.java)
if (binaryExpression != null) {
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ApiVersionClassifierUsageChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ApiVersionClassifierUsageChecker.kt
new file mode 100644
index 00000000000..3e03593ac65
--- /dev/null
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ApiVersionClassifierUsageChecker.kt
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ * 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.resolve.checkers
+
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
+import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.checkSinceKotlinVersionAccessibility
+
+object ApiVersionClassifierUsageChecker : ClassifierUsageChecker {
+ override fun check(
+ targetDescriptor: ClassifierDescriptor,
+ trace: BindingTrace,
+ element: PsiElement,
+ languageVersionSettings: LanguageVersionSettings
+ ) {
+ targetDescriptor.checkSinceKotlinVersionAccessibility(languageVersionSettings) { version ->
+ trace.report(Errors.API_NOT_AVAILABLE.on(element, version.versionString, languageVersionSettings.apiVersion.versionString))
+ }
+ }
+}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt
index d9b8d265d53..352aac4fe52 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/deprecationUtil.kt
@@ -196,5 +196,8 @@ fun DeclarationDescriptor.isHiddenInResolution(languageVersionSettings: Language
if (isHiddenToOvercomeSignatureClash) return true
if (isHiddenForResolutionEverywhereBesideSupercalls && !isSuperCall) return true
}
+
+ if (!checkSinceKotlinVersionAccessibility(languageVersionSettings)) return true
+
return isDeprecatedHidden()
}
diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/sinceKotlinUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/sinceKotlinUtil.kt
index 9254c5c1700..36ad1c1be0e 100644
--- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/sinceKotlinUtil.kt
+++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/sinceKotlinUtil.kt
@@ -16,11 +16,59 @@
package org.jetbrains.kotlin.resolve
+import org.jetbrains.kotlin.config.ApiVersion
+import org.jetbrains.kotlin.config.LanguageVersionSettings
+import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.name.FqName
private val SINCE_KOTLIN_FQ_NAME = FqName("kotlin.SinceKotlin")
+// TODO: use-site targeted annotations
internal fun DeclarationDescriptor.getSinceKotlinAnnotation(): AnnotationDescriptor? =
annotations.findAnnotation(SINCE_KOTLIN_FQ_NAME)
+
+/**
+ * @return true if the descriptor is accessible according to [languageVersionSettings], or false otherwise. The [actionIfInaccessible]
+ * callback is called with the version specified in the [SinceKotlin] annotation if the descriptor is inaccessible.
+ */
+internal fun DeclarationDescriptor.checkSinceKotlinVersionAccessibility(
+ languageVersionSettings: LanguageVersionSettings,
+ actionIfInaccessible: ((ApiVersion) -> Unit)? = null
+): Boolean {
+ val version =
+ if (this is CallableMemberDescriptor && !kind.isReal) getSinceKotlinVersionByOverridden(this)
+ else getOwnSinceKotlinVersion()
+
+ // Allow access in the following cases:
+ // 1) There's no @SinceKotlin annotation for this descriptor
+ // 2) There's a @SinceKotlin annotation but its value is some unrecognizable nonsense
+ // 3) The value as a version is not greater than our API version
+ if (version == null || version <= languageVersionSettings.apiVersion) return true
+
+ actionIfInaccessible?.invoke(version)
+
+ return false
+}
+
+/**
+ * @return null if there are no overridden members or if there's at least one declaration in the hierarchy not annotated with [SinceKotlin],
+ * or the minimal value of the version from all declarations annotated with [SinceKotlin] otherwise.
+ */
+private fun getSinceKotlinVersionByOverridden(descriptor: CallableMemberDescriptor): ApiVersion? {
+ return DescriptorUtils.getAllOverriddenDeclarations(descriptor).map { it.getOwnSinceKotlinVersion() ?: return null }.min()
+}
+
+private fun DeclarationDescriptor.getOwnSinceKotlinVersion(): ApiVersion? {
+ fun DeclarationDescriptor.loadAnnotationValue(): ApiVersion? =
+ (getSinceKotlinAnnotation()?.allValueArguments?.values?.singleOrNull()?.value as? String)?.let(ApiVersion.Companion::parse)
+
+ val ownVersion = loadAnnotationValue()
+ val ctorClass = (this as? ConstructorDescriptor)?.containingDeclaration?.loadAnnotationValue()
+ val property = (this as? PropertyAccessorDescriptor)?.correspondingProperty?.loadAnnotationValue()
+
+ return listOfNotNull(ownVersion, ctorClass, property).max()
+}
diff --git a/compiler/testData/cli/js/jsHelp.out b/compiler/testData/cli/js/jsHelp.out
index 101a52bfe90..0b08b09ad61 100644
--- a/compiler/testData/cli/js/jsHelp.out
+++ b/compiler/testData/cli/js/jsHelp.out
@@ -13,6 +13,7 @@ where possible options include:
-output-prefix Path to file which will be added to the beginning of output file
-output-postfix Path to file which will be added to the end of output file
-language-version Provide source compatibility with specified language version
+ -api-version Allow to use declarations only from the specified version of bundled libraries
-nowarn Generate no warnings
-verbose Enable verbose logging output
-version Display compiler version
diff --git a/compiler/testData/cli/jvm/apiVersion.args b/compiler/testData/cli/jvm/apiVersion.args
new file mode 100644
index 00000000000..e6a17467052
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersion.args
@@ -0,0 +1,5 @@
+$TESTDATA_DIR$/apiVersion.kt
+-d
+$TEMP_DIR$
+-api-version
+1.0
diff --git a/compiler/testData/cli/jvm/apiVersion.kt b/compiler/testData/cli/jvm/apiVersion.kt
new file mode 100644
index 00000000000..8d4661d72c0
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersion.kt
@@ -0,0 +1,3 @@
+fun test() {
+ ""::class.isInstance(42)
+}
diff --git a/compiler/testData/cli/jvm/apiVersion.out b/compiler/testData/cli/jvm/apiVersion.out
new file mode 100644
index 00000000000..33e62bb3fde
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersion.out
@@ -0,0 +1,4 @@
+compiler/testData/cli/jvm/apiVersion.kt:2:15: error: unresolved reference: isInstance
+ ""::class.isInstance(42)
+ ^
+COMPILATION_ERROR
diff --git a/compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args b/compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args
new file mode 100644
index 00000000000..70d1ba13868
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args
@@ -0,0 +1,7 @@
+$TESTDATA_DIR$/apiVersion.kt
+-d
+$TEMP_DIR$
+-api-version
+1.1
+-language-version
+1.0
diff --git a/compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.out b/compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.out
new file mode 100644
index 00000000000..47a8f88e3a8
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.out
@@ -0,0 +1,2 @@
+error: -api-version (1.1) cannot be greater than -language-version (1.0)
+COMPILATION_ERROR
diff --git a/compiler/testData/cli/jvm/apiVersionInvalid.args b/compiler/testData/cli/jvm/apiVersionInvalid.args
new file mode 100644
index 00000000000..5139d064397
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersionInvalid.args
@@ -0,0 +1,5 @@
+$TESTDATA_DIR$/simple.kt
+-d
+$TEMP_DIR$
+-api-version
+239.42
diff --git a/compiler/testData/cli/jvm/apiVersionInvalid.out b/compiler/testData/cli/jvm/apiVersionInvalid.out
new file mode 100644
index 00000000000..e0ff180c445
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersionInvalid.out
@@ -0,0 +1,3 @@
+error: unknown API version: 239.42
+Supported API versions: 1.0, 1.1
+COMPILATION_ERROR
diff --git a/compiler/testData/cli/jvm/apiVersionLessThanLanguage.args b/compiler/testData/cli/jvm/apiVersionLessThanLanguage.args
new file mode 100644
index 00000000000..6ac842f7e60
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersionLessThanLanguage.args
@@ -0,0 +1,7 @@
+$TESTDATA_DIR$/apiVersion.kt
+-d
+$TEMP_DIR$
+-api-version
+1.0
+-language-version
+1.1
diff --git a/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out b/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out
new file mode 100644
index 00000000000..33e62bb3fde
--- /dev/null
+++ b/compiler/testData/cli/jvm/apiVersionLessThanLanguage.out
@@ -0,0 +1,4 @@
+compiler/testData/cli/jvm/apiVersion.kt:2:15: error: unresolved reference: isInstance
+ ""::class.isInstance(42)
+ ^
+COMPILATION_ERROR
diff --git a/compiler/testData/cli/jvm/help.out b/compiler/testData/cli/jvm/help.out
index d5dcc9e50de..66e5cd9ff39 100644
--- a/compiler/testData/cli/jvm/help.out
+++ b/compiler/testData/cli/jvm/help.out
@@ -15,6 +15,7 @@ where possible options include:
-module-name Module name
-jvm-target Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6
-language-version Provide source compatibility with specified language version
+ -api-version Allow to use declarations only from the specified version of bundled libraries
-nowarn Generate no warnings
-verbose Enable verbose logging output
-version Display compiler version
diff --git a/compiler/testData/cli/jvm/languageVersion.kt b/compiler/testData/cli/jvm/languageVersion.kt
index 73d94ad88be..1eb94bd3466 100644
--- a/compiler/testData/cli/jvm/languageVersion.kt
+++ b/compiler/testData/cli/jvm/languageVersion.kt
@@ -3,3 +3,7 @@ package test
sealed class Base
class Derived : Base()
+
+fun test() {
+ ""::class.isInstance(42)
+}
diff --git a/compiler/testData/cli/jvm/languageVersion.out b/compiler/testData/cli/jvm/languageVersion.out
index cdd464da409..4bd2f466360 100644
--- a/compiler/testData/cli/jvm/languageVersion.out
+++ b/compiler/testData/cli/jvm/languageVersion.out
@@ -1,4 +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
+ ""::class.isInstance(42)
+ ^
+compiler/testData/cli/jvm/languageVersion.kt:8:15: error: unresolved reference: isInstance
+ ""::class.isInstance(42)
+ ^
COMPILATION_ERROR
diff --git a/compiler/testData/cli/jvm/wrongArgument.out b/compiler/testData/cli/jvm/wrongArgument.out
index 6d4131ddd1b..35d77484a70 100644
--- a/compiler/testData/cli/jvm/wrongArgument.out
+++ b/compiler/testData/cli/jvm/wrongArgument.out
@@ -16,6 +16,7 @@ where possible options include:
-module-name Module name
-jvm-target Target version of the generated JVM bytecode (1.6 or 1.8), default is 1.6
-language-version Provide source compatibility with specified language version
+ -api-version Allow to use declarations only from the specified version of bundled libraries
-nowarn Generate no warnings
-verbose Enable verbose logging output
-version Display compiler version
diff --git a/compiler/testData/diagnostics/ReadMe.md b/compiler/testData/diagnostics/ReadMe.md
index cec9ce67785..121e0a17765 100644
--- a/compiler/testData/diagnostics/ReadMe.md
+++ b/compiler/testData/diagnostics/ReadMe.md
@@ -83,3 +83,11 @@ This directive lets you enable or disable certain language features. Language fe
// !LANGUAGE: -TopLevelSealedInheritance
// !LANGUAGE: +TypeAliases -LocalDelegatedProperties
+
+### 5. API_VERSION
+
+This directive emulates the behavior of the `-api-version` command line option, disallowing to use declarations annotated with `@SinceKotlin(X)` where X is greater than the specified API version.
+
+#### Usage:
+
+ // !API_VERSION: 1.0
diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt
new file mode 100644
index 00000000000..87c398e27f8
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt
@@ -0,0 +1,34 @@
+// !API_VERSION: 1.0
+// MODULE: m1
+// FILE: a.kt
+
+package p1
+
+@SinceKotlin("1.1")
+fun foo(s: Int): String = s.toString()
+
+// MODULE: m2
+// FILE: b.kt
+
+package p2
+
+fun foo(s: Int): Int = s
+
+// MODULE: m3(m1, m2)
+// FILE: severalStarImports.kt
+import p1.*
+import p2.*
+
+fun test1(): Int {
+ val r = foo(42)
+ return r
+}
+
+// FILE: explicitlyImportP1.kt
+import p1.foo // TODO: consider reporting API_NOT_AVAILABLE here
+import p2.*
+
+fun test2(): Int {
+ val r = foo(42)
+ return r
+}
diff --git a/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.txt b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.txt
new file mode 100644
index 00000000000..702076ed83b
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.txt
@@ -0,0 +1,29 @@
+// -- Module: --
+package
+
+package p1 {
+ @kotlin.SinceKotlin(version = "1.1") public fun foo(/*0*/ s: kotlin.Int): kotlin.String
+}
+
+
+// -- Module: --
+package
+
+package p2 {
+ public fun foo(/*0*/ s: kotlin.Int): kotlin.Int
+}
+
+
+// -- Module: --
+package
+
+public fun test1(): kotlin.Int
+public fun test2(): kotlin.Int
+
+package p1 {
+ @kotlin.SinceKotlin(version = "1.1") public fun foo(/*0*/ s: kotlin.Int): kotlin.String
+}
+
+package p2 {
+ public fun foo(/*0*/ s: kotlin.Int): kotlin.Int
+}
diff --git a/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.kt b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.kt
new file mode 100644
index 00000000000..f1e897f2cc2
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.kt
@@ -0,0 +1,38 @@
+// !API_VERSION: 1.0
+// MODULE: m1
+// FILE: a.kt
+
+package p1
+
+@SinceKotlin("1.1")
+class A {
+ fun m1() {}
+}
+
+// MODULE: m2
+// FILE: b.kt
+
+package p2
+
+class A {
+ fun m2() {}
+}
+
+// MODULE: m3(m1, m2)
+// FILE: severalStarImports.kt
+import p1.*
+import p2.*
+
+fun test(a: A) {
+ a.m1()
+ a.m2()
+}
+
+// FILE: explicitlyImportP1.kt
+import p1.A
+import p2.*
+
+fun test(a: A) {
+ a.m1()
+ a.m2()
+}
diff --git a/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.txt b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.txt
new file mode 100644
index 00000000000..eaf4e477f92
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.txt
@@ -0,0 +1,49 @@
+// -- Module: --
+package
+
+package p1 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ public constructor A()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public final fun m1(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+ }
+}
+
+
+// -- Module: --
+package
+
+package p2 {
+
+ public final class A {
+ public constructor A()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public final fun m2(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+ }
+}
+
+
+// -- Module: --
+package
+
+public fun test(/*0*/ a: p1.A): kotlin.Unit
+public fun test(/*0*/ a: p2.A): kotlin.Unit
+
+package p1 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ // -- Module: --
+ }
+}
+
+package p2 {
+
+ public final class A {
+ // -- Module: --
+ }
+}
diff --git a/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.kt b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.kt
new file mode 100644
index 00000000000..ea81d365db7
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.kt
@@ -0,0 +1,47 @@
+// !API_VERSION: 1.0
+// MODULE: m1
+// FILE: a.kt
+
+package p1
+
+@SinceKotlin("1.1")
+class A(val v1: Unit)
+
+// MODULE: m2
+// FILE: b.kt
+
+package p2
+
+@SinceKotlin("1.1")
+class A(val v2: Unit)
+
+// MODULE: m3
+// FILE: c.kt
+
+package p3
+
+@SinceKotlin("1.1")
+class A(val v3: Unit)
+
+// MODULE: m4(m1, m2, m3)
+// FILE: oneExplicitImportOtherStars.kt
+import p1.*
+import p2.A
+import p3.*
+
+fun test(a: A) {
+ a.v1
+ a.v2
+ a.v3
+}
+
+// FILE: severalStarImports.kt
+import p1.*
+import p2.*
+import p3.*
+
+fun test(a: A) {
+ a.v1
+ a.v2
+ a.v3
+}
diff --git a/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.txt b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.txt
new file mode 100644
index 00000000000..b6e4eba395a
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.txt
@@ -0,0 +1,71 @@
+// -- Module: --
+package
+
+package p1 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ public constructor A(/*0*/ v1: kotlin.Unit)
+ public final val v1: kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+ }
+}
+
+
+// -- Module: --
+package
+
+package p2 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ public constructor A(/*0*/ v2: kotlin.Unit)
+ public final val v2: kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+ }
+}
+
+
+// -- Module: --
+package
+
+package p3 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ public constructor A(/*0*/ v3: kotlin.Unit)
+ public final val v3: kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+ }
+}
+
+
+// -- Module: --
+package
+
+public fun test(/*0*/ a: [ERROR : A]): kotlin.Unit
+public fun test(/*0*/ a: p2.A): kotlin.Unit
+
+package p1 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ // -- Module: --
+ }
+}
+
+package p2 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ // -- Module: --
+ }
+}
+
+package p3 {
+
+ @kotlin.SinceKotlin(version = "1.1") public final class A {
+ // -- Module: --
+ }
+}
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.kt
new file mode 100644
index 00000000000..42042412e0f
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.kt
@@ -0,0 +1,11 @@
+// !API_VERSION: 1.0
+
+@SinceKotlin("1.1")
+annotation class Anno1(val s: String)
+
+annotation class Anno2 @SinceKotlin("1.1") constructor()
+
+
+@Anno1("")
+@Anno2
+fun t1() {}
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.txt
new file mode 100644
index 00000000000..f3a28488d38
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.txt
@@ -0,0 +1,18 @@
+package
+
+@Anno1() @Anno2() public fun t1(): kotlin.Unit
+
+@kotlin.SinceKotlin(version = "1.1") public final annotation class Anno1 : kotlin.Annotation {
+ public constructor Anno1(/*0*/ s: kotlin.String)
+ public final val s: kotlin.String
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public final annotation class Anno2 : kotlin.Annotation {
+ @kotlin.SinceKotlin(version = "1.1") public constructor Anno2()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.kt
new file mode 100644
index 00000000000..aa0e96dc4f5
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.kt
@@ -0,0 +1,19 @@
+// !API_VERSION: 1.0
+
+@SinceKotlin("1.1")
+open class Foo
+
+class Bar @SinceKotlin("1.1") constructor()
+
+@SinceKotlin("1.0")
+class Baz @SinceKotlin("1.1") constructor()
+
+
+fun t1(): Foo = Foo()
+
+// TODO: do not report API_NOT_AVAILABLE twice
+fun t2() = object : Foo() {}
+
+fun t3(): Bar? = Bar()
+
+fun t4(): Baz = Baz()
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.txt
new file mode 100644
index 00000000000..9c89074b1a2
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.txt
@@ -0,0 +1,27 @@
+package
+
+public fun t1(): Foo
+public fun t2(): Foo
+public fun t3(): Bar?
+public fun t4(): Baz
+
+public final class Bar {
+ @kotlin.SinceKotlin(version = "1.1") public constructor Bar()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+@kotlin.SinceKotlin(version = "1.0") public final class Baz {
+ @kotlin.SinceKotlin(version = "1.1") public constructor Baz()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+@kotlin.SinceKotlin(version = "1.1") public open class Foo {
+ public constructor Foo()
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.kt
new file mode 100644
index 00000000000..5a6836588bc
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.kt
@@ -0,0 +1,34 @@
+// !API_VERSION: 1.0
+// FILE: J.java
+
+public interface J {
+ void foo();
+}
+
+// FILE: test.kt
+
+interface I10 {
+ @SinceKotlin("1.0")
+ fun foo()
+}
+
+interface I11 {
+ @SinceKotlin("1.1")
+ fun foo()
+}
+
+fun f1(x: I10) = x.foo()
+fun f2(x: I11) = x.foo()
+fun f3(x: J) = x.foo()
+
+interface BothI1 : I10, I11
+fun f4(x: BothI1) = x.foo()
+
+interface BothI2 : I11, I10
+fun f5(x: BothI2) = x.foo()
+
+interface JAndI10 : J, I10
+fun f6(x: JAndI10) = x.foo()
+
+interface JAndI11 : J, I11
+fun f7(x: JAndI11) = x.foo()
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.txt
new file mode 100644
index 00000000000..461f76d6e5c
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.txt
@@ -0,0 +1,59 @@
+package
+
+public /*synthesized*/ fun J(/*0*/ function: () -> kotlin.Unit): J
+public fun f1(/*0*/ x: I10): kotlin.Unit
+public fun f2(/*0*/ x: I11): [ERROR : Error function type]
+public fun f3(/*0*/ x: J): kotlin.Unit
+public fun f4(/*0*/ x: BothI1): kotlin.Unit
+public fun f5(/*0*/ x: BothI2): kotlin.Unit
+public fun f6(/*0*/ x: JAndI10): kotlin.Unit
+public fun f7(/*0*/ x: JAndI11): kotlin.Unit
+
+public interface BothI1 : I10, I11 {
+ public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @kotlin.SinceKotlin(version = "1.0") public abstract override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit
+ public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface BothI2 : I11, I10 {
+ public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @kotlin.SinceKotlin(version = "1.1") public abstract override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit
+ public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface I10 {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @kotlin.SinceKotlin(version = "1.0") public abstract fun foo(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface I11 {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ @kotlin.SinceKotlin(version = "1.1") public abstract fun foo(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface J {
+ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract fun foo(): kotlin.Unit
+ public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface JAndI10 : J, I10 {
+ public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit
+ public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
+}
+
+public interface JAndI11 : J, I11 {
+ public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
+ public abstract override /*2*/ /*fake_override*/ fun foo(): kotlin.Unit
+ public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
+ public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
+}
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.kt
new file mode 100644
index 00000000000..28bfadf4c27
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.kt
@@ -0,0 +1,48 @@
+// !API_VERSION: 1.0
+
+val v1: String
+ @SinceKotlin("1.1")
+ get() = ""
+
+@SinceKotlin("1.1")
+val v2 = ""
+
+var v3: String
+ @SinceKotlin("1.1")
+ get() = ""
+ set(value) {}
+
+var v4: String
+ get() = ""
+ @SinceKotlin("1.1")
+ set(value) {}
+
+var v5: String
+ @SinceKotlin("1.1")
+ get() = ""
+ @SinceKotlin("1.1")
+ set(value) {}
+
+@SinceKotlin("1.1")
+var v6: String
+ get() = ""
+ set(value) {}
+
+@SinceKotlin("1.0")
+val v7: String
+ @SinceKotlin("1.1")
+ get() = ""
+
+fun test() {
+ v1
+ v2
+ v3
+ v3 = ""
+ v4
+ v4 = ""
+ v5
+ v5 = ""
+ v6
+ v6 = ""
+ v7
+}
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.txt
new file mode 100644
index 00000000000..e6481973f12
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.txt
@@ -0,0 +1,10 @@
+package
+
+public val v1: kotlin.String
+@kotlin.SinceKotlin(version = "1.1") public val v2: kotlin.String = ""
+public var v3: kotlin.String
+public var v4: kotlin.String
+public var v5: kotlin.String
+@kotlin.SinceKotlin(version = "1.1") public var v6: kotlin.String
+@kotlin.SinceKotlin(version = "1.0") public val v7: kotlin.String
+public fun test(): kotlin.Unit
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt
new file mode 100644
index 00000000000..2fb3a53d971
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt
@@ -0,0 +1,19 @@
+// !API_VERSION: 1.0
+
+@SinceKotlin("1.1")
+fun f() {}
+
+@SinceKotlin("1.1")
+var p = Unit
+
+@SinceKotlin("1.1.2")
+fun z() {}
+
+
+fun t1() = f()
+
+fun t2() = p
+
+fun t3() { p = Unit }
+
+fun t4() { z() }
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.txt
new file mode 100644
index 00000000000..2f406ad6fc6
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.txt
@@ -0,0 +1,9 @@
+package
+
+@kotlin.SinceKotlin(version = "1.1") public var p: kotlin.Unit
+@kotlin.SinceKotlin(version = "1.1") public fun f(): kotlin.Unit
+public fun t1(): [ERROR : Error function type]
+public fun t2(): [ERROR : Error function type]
+public fun t3(): kotlin.Unit
+public fun t4(): kotlin.Unit
+@kotlin.SinceKotlin(version = "1.1.2") public fun z(): kotlin.Unit
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.kt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.kt
new file mode 100644
index 00000000000..6d35fbdbbb6
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.kt
@@ -0,0 +1,18 @@
+// !API_VERSION: 1.1
+
+@SinceKotlin("0.9")
+fun ok1() {}
+
+@SinceKotlin("1.0")
+fun ok2() {}
+
+@SinceKotlin("1.1")
+fun ok3() {}
+
+@SinceKotlin("0.9.9")
+fun ok4() {}
+
+fun t1() = ok1()
+fun t2() = ok2()
+fun t3() = ok3()
+fun t4() = ok4()
diff --git a/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.txt b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.txt
new file mode 100644
index 00000000000..e1fff254c64
--- /dev/null
+++ b/compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.txt
@@ -0,0 +1,10 @@
+package
+
+@kotlin.SinceKotlin(version = "0.9") public fun ok1(): kotlin.Unit
+@kotlin.SinceKotlin(version = "1.0") public fun ok2(): kotlin.Unit
+@kotlin.SinceKotlin(version = "1.1") public fun ok3(): kotlin.Unit
+@kotlin.SinceKotlin(version = "0.9.9") public fun ok4(): kotlin.Unit
+public fun t1(): kotlin.Unit
+public fun t2(): kotlin.Unit
+public fun t3(): kotlin.Unit
+public fun t4(): kotlin.Unit
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java
index 2465d516bd2..61fddd4fc44 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsTest.java
@@ -143,7 +143,7 @@ public abstract class AbstractDiagnosticsTest extends BaseDiagnosticsTest {
moduleBindings.put(testModule, moduleTrace.getBindingContext());
- LanguageVersionSettings languageVersionSettings = loadCustomLanguageVersionSettings(testFilesInModule);
+ LanguageVersionSettings languageVersionSettings = loadLanguageVersionSettings(testFilesInModule);
ModuleContext moduleContext = ContextKt.withModule(ContextKt.withProject(context, getProject()), module);
boolean separateModules = groupedByModule.size() == 1;
@@ -210,17 +210,19 @@ public abstract class AbstractDiagnosticsTest extends BaseDiagnosticsTest {
}
@Nullable
- private LanguageVersionSettings loadCustomLanguageVersionSettings(List extends TestFile> module) {
+ private LanguageVersionSettings loadLanguageVersionSettings(List extends TestFile> module) {
LanguageVersionSettings result = null;
for (TestFile file : module) {
- if (file.customLanguageVersionSettings != null) {
- if (result != null) {
+ LanguageVersionSettings current = file.customLanguageVersionSettings;
+ if (current != null) {
+ if (result != null && !result.equals(current)) {
Assert.fail(
- "More than one file in the module has " + BaseDiagnosticsTest.LANGUAGE_DIRECTIVE + " directive specified. " +
+ "More than one file in the module has " + BaseDiagnosticsTest.LANGUAGE_DIRECTIVE + " or " +
+ BaseDiagnosticsTest.API_VERSION_DIRECTIVE + " directive specified. " +
"This is not supported. Please move all directives into one file"
);
}
- result = file.customLanguageVersionSettings;
+ result = current;
}
}
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java b/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java
index 83fb516e2c0..c7711f81fd4 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/BaseDiagnosticsTest.java
@@ -34,6 +34,7 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.asJava.DuplicateJvmSignatureUtilKt;
+import org.jetbrains.kotlin.config.ApiVersion;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
@@ -71,6 +72,8 @@ public abstract class BaseDiagnosticsTest
public static final String LANGUAGE_DIRECTIVE = "LANGUAGE";
private static final Pattern LANGUAGE_PATTERN = Pattern.compile("([\\+\\-])(\\w+)\\s*");
+ public static final String API_VERSION_DIRECTIVE = "API_VERSION";
+
public static final String CHECK_TYPE_DIRECTIVE = "CHECK_TYPE";
public static final String CHECK_TYPE_PACKAGE = "tests._checkType";
private static final String CHECK_TYPE_DECLARATIONS = "\npackage " + CHECK_TYPE_PACKAGE +
@@ -155,14 +158,26 @@ public abstract class BaseDiagnosticsTest
}
@Nullable
- private static LanguageVersionSettings parseLanguageDirective(Map directiveMap) {
+ private static LanguageVersionSettings parseLanguageVersionSettings(Map directiveMap) {
+ String apiVersionString = directiveMap.get(API_VERSION_DIRECTIVE);
String directives = directiveMap.get(LANGUAGE_DIRECTIVE);
- if (directives == null) return null;
+ if (apiVersionString == null && directives == null) return null;
+ ApiVersion apiVersion = apiVersionString != null ? ApiVersion.Companion.parse(apiVersionString) : ApiVersion.LATEST;
+ assert apiVersion != null : "Unknown API version: " + apiVersionString;
+
+ Map languageFeatures =
+ directives == null ? Collections.emptyMap() : collectLanguageFeatureMap(directives);
+
+ return new DiagnosticTestLanguageVersionSettings(languageFeatures, apiVersion);
+ }
+
+ @NotNull
+ private static Map collectLanguageFeatureMap(@NotNull String directives) {
Matcher matcher = LANGUAGE_PATTERN.matcher(directives);
if (!matcher.find()) {
Assert.fail(
- "Wrong syntax in the '// !LANGUAGE: ...' directive:\n" +
+ "Wrong syntax in the '// !" + LANGUAGE_DIRECTIVE + ": ...' directive:\n" +
"found: '" + directives + "'\n" +
"Must be '([+-]LanguageFeatureName)+'\n" +
"where '+' means 'enable' and '-' means 'disable'\n" +
@@ -170,7 +185,7 @@ public abstract class BaseDiagnosticsTest
);
}
- final Map values = new HashMap();
+ Map values = new HashMap();
do {
boolean enable = matcher.group(1).equals("+");
String name = matcher.group(2);
@@ -187,16 +202,7 @@ public abstract class BaseDiagnosticsTest
}
while (matcher.find());
- return new LanguageVersionSettings() {
- @Override
- public boolean supportsFeature(@NotNull LanguageFeature feature) {
- Boolean enabled = values.get(feature);
- if (enabled != null) {
- return enabled;
- }
- return LanguageVersionSettingsImpl.DEFAULT.supportsFeature(feature);
- }
- };
+ return values;
}
public static Condition parseDiagnosticFilterDirective(Map directiveMap) {
@@ -207,7 +213,7 @@ public abstract class BaseDiagnosticsTest
Condition condition = Conditions.alwaysTrue();
Matcher matcher = DIAGNOSTICS_PATTERN.matcher(directives);
if (!matcher.find()) {
- Assert.fail("Wrong syntax in the '// !DIAGNOSTICS: ...' directive:\n" +
+ Assert.fail("Wrong syntax in the '// !" + DIAGNOSTICS_DIRECTIVE + ": ...' directive:\n" +
"found: '" + directives + "'\n" +
"Must be '([+-!]DIAGNOSTIC_FACTORY_NAME|ERROR|WARNING|INFO)+'\n" +
"where '+' means 'include'\n" +
@@ -289,6 +295,37 @@ public abstract class BaseDiagnosticsTest
}
}
+ public static class DiagnosticTestLanguageVersionSettings implements LanguageVersionSettings {
+ private final Map languageFeatures;
+ private final ApiVersion apiVersion;
+
+ public DiagnosticTestLanguageVersionSettings(
+ @NotNull Map languageFeatures, @NotNull ApiVersion apiVersion
+ ) {
+ this.languageFeatures = languageFeatures;
+ this.apiVersion = apiVersion;
+ }
+
+ @Override
+ public boolean supportsFeature(@NotNull LanguageFeature feature) {
+ Boolean enabled = languageFeatures.get(feature);
+ return enabled != null ? enabled : LanguageVersionSettingsImpl.DEFAULT.supportsFeature(feature);
+ }
+
+ @NotNull
+ @Override
+ public ApiVersion getApiVersion() {
+ return apiVersion;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof DiagnosticTestLanguageVersionSettings &&
+ ((DiagnosticTestLanguageVersionSettings) obj).languageFeatures.equals(languageFeatures) &&
+ ((DiagnosticTestLanguageVersionSettings) obj).apiVersion.equals(apiVersion);
+ }
+ }
+
protected class TestFile {
private final List diagnosedRanges = Lists.newArrayList();
public final String expectedText;
@@ -311,7 +348,7 @@ public abstract class BaseDiagnosticsTest
) {
this.module = module;
this.whatDiagnosticsToConsider = parseDiagnosticFilterDirective(directives);
- this.customLanguageVersionSettings = parseLanguageDirective(directives);
+ this.customLanguageVersionSettings = parseLanguageVersionSettings(directives);
this.checkLazyLog = directives.containsKey(CHECK_LAZY_LOG_DIRECTIVE) || CHECK_LAZY_LOG_DEFAULT;
this.declareCheckType = directives.containsKey(CHECK_TYPE_DIRECTIVE);
this.declareFlexibleType = directives.containsKey(EXPLICIT_FLEXIBLE_TYPES_DIRECTIVE);
diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
index 9a6c5479779..637abe57621 100644
--- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java
@@ -12383,6 +12383,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
+ @TestMetadata("sinceKotlin.kt")
+ public void testSinceKotlin() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/duplicateMethod/sinceKotlin.kt");
+ doTest(fileName);
+ }
+
@TestMetadata("substitutedGenericInParams.kt")
public void testSubstitutedGenericInParams() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/duplicateMethod/substitutedGenericInParams.kt");
@@ -12442,6 +12448,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/hiddenClass/deprecatedHiddenMultipleClasses.kt");
doTest(fileName);
}
+
+ @TestMetadata("sinceKotlinImportPriority.kt")
+ public void testSinceKotlinImportPriority() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinImportPriority.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("sinceKotlinMultipleClasses.kt")
+ public void testSinceKotlinMultipleClasses() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multimodule/hiddenClass/sinceKotlinMultipleClasses.kt");
+ doTest(fileName);
+ }
}
}
@@ -19488,6 +19506,51 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
+ @TestMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion")
+ @TestDataPath("$PROJECT_ROOT")
+ @RunWith(JUnit3RunnerWithInners.class)
+ public static class ApiVersion extends AbstractDiagnosticsTest {
+ public void testAllFilesPresentInApiVersion() throws Exception {
+ KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion"), Pattern.compile("^(.+)\\.kt$"), true);
+ }
+
+ @TestMetadata("annotations.kt")
+ public void testAnnotations() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/annotations.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("classesAndConstructors.kt")
+ public void testClassesAndConstructors() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/classesAndConstructors.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("overriddenMembers.kt")
+ public void testOverriddenMembers() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/overriddenMembers.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("propertyAccessors.kt")
+ public void testPropertyAccessors() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/propertyAccessors.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("simpleMembers.kt")
+ public void testSimpleMembers() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/simpleMembers.kt");
+ doTest(fileName);
+ }
+
+ @TestMetadata("sinceOldVersionIsOK.kt")
+ public void testSinceOldVersionIsOK() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/apiVersion/sinceOldVersionIsOK.kt");
+ doTest(fileName);
+ }
+ }
+
@TestMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
diff --git a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java
index 1b3f881f333..c03a0fdc07e 100644
--- a/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/cli/CliTestGenerated.java
@@ -37,6 +37,30 @@ public class CliTestGenerated extends AbstractCliTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/cli/jvm"), Pattern.compile("^(.+)\\.args$"), false);
}
+ @TestMetadata("apiVersion.args")
+ public void testApiVersion() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersion.args");
+ doJvmTest(fileName);
+ }
+
+ @TestMetadata("apiVersionGreaterThanLanguage.args")
+ public void testApiVersionGreaterThanLanguage() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionGreaterThanLanguage.args");
+ doJvmTest(fileName);
+ }
+
+ @TestMetadata("apiVersionInvalid.args")
+ public void testApiVersionInvalid() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionInvalid.args");
+ doJvmTest(fileName);
+ }
+
+ @TestMetadata("apiVersionLessThanLanguage.args")
+ public void testApiVersionLessThanLanguage() throws Exception {
+ String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/apiVersionLessThanLanguage.args");
+ doJvmTest(fileName);
+ }
+
@TestMetadata("classAndFileClassClash.args")
public void testClassAndFileClassClash() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/cli/jvm/classAndFileClassClash.args");
diff --git a/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt b/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt
index cf5d8bf6007..3ed4d109537 100644
--- a/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt
+++ b/compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt
@@ -40,8 +40,9 @@ class CodeConformanceTest : TestCase() {
"libraries/tools/kotlin-gradle-plugin-core/gradle_api_jar/build/tmp",
"libraries/tools/kotlin-maven-plugin/target",
"compiler/testData/psi/kdoc",
- "compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt"
- ).map { File(it) }
+ "compiler/tests/org/jetbrains/kotlin/code/CodeConformanceTest.kt",
+ "compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java"
+ ).map(::File)
}
fun testParserCode() {
diff --git a/compiler/util/src/org/jetbrains/kotlin/config/ApiVersion.kt b/compiler/util/src/org/jetbrains/kotlin/config/ApiVersion.kt
new file mode 100644
index 00000000000..af29b8528eb
--- /dev/null
+++ b/compiler/util/src/org/jetbrains/kotlin/config/ApiVersion.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ * 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.config
+
+class ApiVersion private constructor(
+ private val version: MavenComparableVersion,
+ val versionString: String
+) : Comparable {
+ override fun compareTo(other: ApiVersion): Int =
+ version.compareTo(other.version)
+
+ override fun equals(other: Any?) =
+ (other as? ApiVersion)?.version == version
+
+ override fun hashCode() =
+ version.hashCode()
+
+ override fun toString() = versionString
+
+ companion object {
+ @JvmField
+ val LATEST: ApiVersion = createByLanguageVersion(LanguageVersion.Companion.LATEST)
+
+ @JvmStatic
+ fun createByLanguageVersion(version: LanguageVersion): ApiVersion = parse(version.versionString)!!
+
+ fun parse(versionString: String): ApiVersion? = try {
+ ApiVersion(MavenComparableVersion(versionString), versionString)
+ }
+ catch (e: Exception) {
+ null
+ }
+ }
+}
diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
index 286f5cf330a..2c25fcccefd 100644
--- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
+++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt
@@ -45,6 +45,8 @@ enum class LanguageVersion(val versionString: String) {
KOTLIN_1_0("1.0"),
KOTLIN_1_1("1.1");
+ override fun toString() = versionString
+
companion object {
@JvmStatic
fun fromVersionString(str: String) = values().find { it.versionString == str }
@@ -56,15 +58,22 @@ enum class LanguageVersion(val versionString: String) {
interface LanguageVersionSettings {
fun supportsFeature(feature: LanguageFeature): Boolean
+
+ val apiVersion: ApiVersion
}
-class LanguageVersionSettingsImpl(private val languageVersion: LanguageVersion) : LanguageVersionSettings {
+class LanguageVersionSettingsImpl(
+ private val languageVersion: LanguageVersion,
+ override val apiVersion: ApiVersion
+) : LanguageVersionSettings {
override fun supportsFeature(feature: LanguageFeature): Boolean {
- return languageVersion.ordinal >= feature.sinceVersion.ordinal
+ return languageVersion >= feature.sinceVersion
}
+ override fun toString() = "Language = $languageVersion, API = $apiVersion"
+
companion object {
@JvmField
- val DEFAULT = LanguageVersionSettingsImpl(LanguageVersion.LATEST)
+ val DEFAULT = LanguageVersionSettingsImpl(LanguageVersion.LATEST, ApiVersion.LATEST)
}
}
diff --git a/compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java b/compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java
new file mode 100644
index 00000000000..e970f8f88d6
--- /dev/null
+++ b/compiler/util/src/org/jetbrains/kotlin/config/MavenComparableVersion.java
@@ -0,0 +1,504 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.config;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.Stack;
+
+/**
+ * Generic implementation of version comparison.
+ *
+ * Features:
+ *
+ * - mixing of '
-' (dash) and '.' (dot) separators,
+ * - transition between characters and digits also constitutes a separator:
+ *
1.0alpha1 => [1, 0, alpha, 1]
+ * - unlimited number of version components,
+ * - version components in the text can be digits or strings,
+ * - strings are checked for well-known qualifiers and the qualifier ordering is used for version ordering.
+ * Well-known qualifiers (case insensitive) are:
+ * alpha or a
+ * beta or b
+ * milestone or m
+ * rc or cr
+ * snapshot
+ * (the empty string) or ga or final
+ * sp
+ *
+ * Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive),
+ *
+ * - a dash usually precedes a qualifier, and is always less important than something preceded with a dot.
+ *
+ *
+ * @see "Versioning" on Maven Wiki
+ * @author Kenney Westerhof
+ * @author Hervé Boutemy
+ */
+@SuppressWarnings("ALL")
+public class MavenComparableVersion
+ implements Comparable
+{
+ private String value;
+
+ private String canonical;
+
+ private ListItem items;
+
+ private interface Item
+ {
+ int INTEGER_ITEM = 0;
+ int STRING_ITEM = 1;
+ int LIST_ITEM = 2;
+
+ int compareTo( Item item );
+
+ int getType();
+
+ boolean isNull();
+ }
+
+ /**
+ * Represents a numeric item in the version item list.
+ */
+ private static class IntegerItem
+ implements Item
+ {
+ private static final BigInteger BIG_INTEGER_ZERO = new BigInteger( "0" );
+
+ private final BigInteger value;
+
+ public static final IntegerItem ZERO = new IntegerItem();
+
+ private IntegerItem()
+ {
+ this.value = BIG_INTEGER_ZERO;
+ }
+
+ public IntegerItem( String str )
+ {
+ this.value = new BigInteger( str );
+ }
+
+ public int getType()
+ {
+ return INTEGER_ITEM;
+ }
+
+ public boolean isNull()
+ {
+ return BIG_INTEGER_ZERO.equals( value );
+ }
+
+ public int compareTo( Item item )
+ {
+ if ( item == null )
+ {
+ return BIG_INTEGER_ZERO.equals( value ) ? 0 : 1; // 1.0 == 1, 1.1 > 1
+ }
+
+ switch ( item.getType() )
+ {
+ case INTEGER_ITEM:
+ return value.compareTo( ( (IntegerItem) item ).value );
+
+ case STRING_ITEM:
+ return 1; // 1.1 > 1-sp
+
+ case LIST_ITEM:
+ return 1; // 1.1 > 1-1
+
+ default:
+ throw new RuntimeException( "invalid item: " + item.getClass() );
+ }
+ }
+
+ public String toString()
+ {
+ return value.toString();
+ }
+ }
+
+ /**
+ * Represents a string in the version item list, usually a qualifier.
+ */
+ private static class StringItem
+ implements Item
+ {
+ private static final String[] QUALIFIERS = { "alpha", "beta", "milestone", "rc", "snapshot", "", "sp" };
+
+ @SuppressWarnings( "checkstyle:constantname" )
+ private static final List _QUALIFIERS = Arrays.asList( QUALIFIERS );
+
+ private static final Properties ALIASES = new Properties();
+ static
+ {
+ ALIASES.put( "ga", "" );
+ ALIASES.put( "final", "" );
+ ALIASES.put( "cr", "rc" );
+ }
+
+ /**
+ * A comparable value for the empty-string qualifier. This one is used to determine if a given qualifier makes
+ * the version older than one without a qualifier, or more recent.
+ */
+ private static final String RELEASE_VERSION_INDEX = String.valueOf( _QUALIFIERS.indexOf( "" ) );
+
+ private String value;
+
+ public StringItem( String value, boolean followedByDigit )
+ {
+ if ( followedByDigit && value.length() == 1 )
+ {
+ // a1 = alpha-1, b1 = beta-1, m1 = milestone-1
+ switch ( value.charAt( 0 ) )
+ {
+ case 'a':
+ value = "alpha";
+ break;
+ case 'b':
+ value = "beta";
+ break;
+ case 'm':
+ value = "milestone";
+ break;
+ default:
+ }
+ }
+ this.value = ALIASES.getProperty( value , value );
+ }
+
+ public int getType()
+ {
+ return STRING_ITEM;
+ }
+
+ public boolean isNull()
+ {
+ return ( comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX ) == 0 );
+ }
+
+ /**
+ * Returns a comparable value for a qualifier.
+ *
+ * This method takes into account the ordering of known qualifiers then unknown qualifiers with lexical
+ * ordering.
+ *
+ * just returning an Integer with the index here is faster, but requires a lot of if/then/else to check for -1
+ * or QUALIFIERS.size and then resort to lexical ordering. Most comparisons are decided by the first character,
+ * so this is still fast. If more characters are needed then it requires a lexical sort anyway.
+ *
+ * @param qualifier
+ * @return an equivalent value that can be used with lexical comparison
+ */
+ public static String comparableQualifier( String qualifier )
+ {
+ int i = _QUALIFIERS.indexOf( qualifier );
+
+ return i == -1 ? ( _QUALIFIERS.size() + "-" + qualifier ) : String.valueOf( i );
+ }
+
+ public int compareTo( Item item )
+ {
+ if ( item == null )
+ {
+ // 1-rc < 1, 1-ga > 1
+ return comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX );
+ }
+ switch ( item.getType() )
+ {
+ case INTEGER_ITEM:
+ return -1; // 1.any < 1.1 ?
+
+ case STRING_ITEM:
+ return comparableQualifier( value ).compareTo( comparableQualifier( ( (StringItem) item ).value ) );
+
+ case LIST_ITEM:
+ return -1; // 1.any < 1-1
+
+ default:
+ throw new RuntimeException( "invalid item: " + item.getClass() );
+ }
+ }
+
+ public String toString()
+ {
+ return value;
+ }
+ }
+
+ /**
+ * Represents a version list item. This class is used both for the global item list and for sub-lists (which start
+ * with '-(number)' in the version specification).
+ */
+ private static class ListItem
+ extends ArrayList-
+ implements Item
+ {
+ public int getType()
+ {
+ return LIST_ITEM;
+ }
+
+ public boolean isNull()
+ {
+ return ( size() == 0 );
+ }
+
+ void normalize()
+ {
+ for ( int i = size() - 1; i >= 0; i-- )
+ {
+ Item lastItem = get( i );
+
+ if ( lastItem.isNull() )
+ {
+ // remove null trailing items: 0, "", empty list
+ remove( i );
+ }
+ else if ( !( lastItem instanceof ListItem ) )
+ {
+ break;
+ }
+ }
+ }
+
+ public int compareTo( Item item )
+ {
+ if ( item == null )
+ {
+ if ( size() == 0 )
+ {
+ return 0; // 1-0 = 1- (normalize) = 1
+ }
+ Item first = get( 0 );
+ return first.compareTo( null );
+ }
+ switch ( item.getType() )
+ {
+ case INTEGER_ITEM:
+ return -1; // 1-1 < 1.0.x
+
+ case STRING_ITEM:
+ return 1; // 1-1 > 1-sp
+
+ case LIST_ITEM:
+ Iterator
- left = iterator();
+ Iterator
- right = ( (ListItem) item ).iterator();
+
+ while ( left.hasNext() || right.hasNext() )
+ {
+ Item l = left.hasNext() ? left.next() : null;
+ Item r = right.hasNext() ? right.next() : null;
+
+ // if this is shorter, then invert the compare and mul with -1
+ int result = l == null ? ( r == null ? 0 : -1 * r.compareTo( l ) ) : l.compareTo( r );
+
+ if ( result != 0 )
+ {
+ return result;
+ }
+ }
+
+ return 0;
+
+ default:
+ throw new RuntimeException( "invalid item: " + item.getClass() );
+ }
+ }
+
+ public String toString()
+ {
+ StringBuilder buffer = new StringBuilder();
+ for ( Iterator
- iter = iterator(); iter.hasNext(); )
+ {
+ Item item = iter.next();
+ if ( buffer.length() > 0 )
+ {
+ buffer.append( ( item instanceof ListItem ) ? '-' : '.' );
+ }
+ buffer.append( item );
+ }
+ return buffer.toString();
+ }
+ }
+
+ public MavenComparableVersion( String version )
+ {
+ parseVersion( version );
+ }
+
+ public final void parseVersion( String version )
+ {
+ this.value = version;
+
+ items = new ListItem();
+
+ version = version.toLowerCase( Locale.ENGLISH );
+
+ ListItem list = items;
+
+ Stack
- stack = new Stack
- ();
+ stack.push( list );
+
+ boolean isDigit = false;
+
+ int startIndex = 0;
+
+ for ( int i = 0; i < version.length(); i++ )
+ {
+ char c = version.charAt( i );
+
+ if ( c == '.' )
+ {
+ if ( i == startIndex )
+ {
+ list.add( IntegerItem.ZERO );
+ }
+ else
+ {
+ list.add( parseItem( isDigit, version.substring( startIndex, i ) ) );
+ }
+ startIndex = i + 1;
+ }
+ else if ( c == '-' )
+ {
+ if ( i == startIndex )
+ {
+ list.add( IntegerItem.ZERO );
+ }
+ else
+ {
+ list.add( parseItem( isDigit, version.substring( startIndex, i ) ) );
+ }
+ startIndex = i + 1;
+
+ list.add( list = new ListItem() );
+ stack.push( list );
+ }
+ else if ( Character.isDigit( c ) )
+ {
+ if ( !isDigit && i > startIndex )
+ {
+ list.add( new StringItem( version.substring( startIndex, i ), true ) );
+ startIndex = i;
+
+ list.add( list = new ListItem() );
+ stack.push( list );
+ }
+
+ isDigit = true;
+ }
+ else
+ {
+ if ( isDigit && i > startIndex )
+ {
+ list.add( parseItem( true, version.substring( startIndex, i ) ) );
+ startIndex = i;
+
+ list.add( list = new ListItem() );
+ stack.push( list );
+ }
+
+ isDigit = false;
+ }
+ }
+
+ if ( version.length() > startIndex )
+ {
+ list.add( parseItem( isDigit, version.substring( startIndex ) ) );
+ }
+
+ while ( !stack.isEmpty() )
+ {
+ list = (ListItem) stack.pop();
+ list.normalize();
+ }
+
+ canonical = items.toString();
+ }
+
+ private static Item parseItem( boolean isDigit, String buf )
+ {
+ return isDigit ? new IntegerItem( buf ) : new StringItem( buf, false );
+ }
+
+ public int compareTo( MavenComparableVersion o )
+ {
+ return items.compareTo( o.items );
+ }
+
+ public String toString()
+ {
+ return value;
+ }
+
+ public String getCanonical()
+ {
+ return canonical;
+ }
+
+ public boolean equals( Object o )
+ {
+ return ( o instanceof MavenComparableVersion) && canonical.equals(((MavenComparableVersion) o ).canonical );
+ }
+
+ public int hashCode()
+ {
+ return canonical.hashCode();
+ }
+
+ /**
+ * Main to test version parsing and comparison.
+ *
+ * @param args the version strings to parse and compare
+ */
+ public static void main( String... args )
+ {
+ System.out.println( "Display parameters as parsed by Maven (in canonical form) and comparison result:" );
+ if ( args.length == 0 )
+ {
+ return;
+ }
+
+ MavenComparableVersion prev = null;
+ int i = 1;
+ for ( String version : args )
+ {
+ MavenComparableVersion c = new MavenComparableVersion(version );
+
+ if ( prev != null )
+ {
+ int compare = prev.compareTo( c );
+ System.out.println( " " + prev.toString() + ' '
+ + ( ( compare == 0 ) ? "==" : ( ( compare < 0 ) ? "<" : ">" ) ) + ' ' + version );
+ }
+
+ System.out.println( String.valueOf( i++ ) + ". " + version + " == " + c.getCanonical() );
+
+ prev = c;
+ }
+ }
+}
diff --git a/core/builtins/src/kotlin/reflect/KClass.kt b/core/builtins/src/kotlin/reflect/KClass.kt
index e4bb27d11c1..c7dd12cb519 100644
--- a/core/builtins/src/kotlin/reflect/KClass.kt
+++ b/core/builtins/src/kotlin/reflect/KClass.kt
@@ -61,6 +61,7 @@ public interface KClass : KDeclarationContainer, KAnnotatedElement, KCl
/**
* Returns `true` if [value] is an instance of this class on a given platform.
*/
+ @SinceKotlin("1.1")
public fun isInstance(value: Any?): Boolean
/**
diff --git a/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageJsTest.java b/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageJsTest.java
index 7dbc57641ba..d749be05a76 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageJsTest.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageJsTest.java
@@ -21,10 +21,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
-import org.jetbrains.kotlin.config.CommonConfigurationKeys;
-import org.jetbrains.kotlin.config.CompilerConfiguration;
-import org.jetbrains.kotlin.config.LanguageVersion;
-import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
+import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase;
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
@@ -71,7 +68,8 @@ public abstract class AbstractDiagnosticMessageJsTest extends AbstractDiagnostic
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, true);
configuration.put(JSConfigurationKeys.UNIT_TEST_CONFIG, true);
if (explicitLanguageVersion != null) {
- configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, new LanguageVersionSettingsImpl(explicitLanguageVersion));
+ configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
+ new LanguageVersionSettingsImpl(explicitLanguageVersion, ApiVersion.LATEST));
}
return new LibrarySourcesConfig(getProject(), configuration);
}
diff --git a/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageTest.java b/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageTest.java
index c2c543c1b8f..eb2f4b5bd99 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageTest.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/highlighter/AbstractDiagnosticMessageTest.java
@@ -24,10 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment;
-import org.jetbrains.kotlin.config.CommonConfigurationKeys;
-import org.jetbrains.kotlin.config.CompilerConfiguration;
-import org.jetbrains.kotlin.config.LanguageVersion;
-import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
+import org.jetbrains.kotlin.config.*;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory;
import org.jetbrains.kotlin.diagnostics.Errors;
@@ -82,7 +79,8 @@ public abstract class AbstractDiagnosticMessageTest extends KotlinTestWithEnviro
protected AnalysisResult analyze(@NotNull KtFile file, @Nullable LanguageVersion explicitLanguageVersion) {
CompilerConfiguration configuration = getEnvironment().getConfiguration();
if (explicitLanguageVersion != null) {
- configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, new LanguageVersionSettingsImpl(explicitLanguageVersion));
+ configuration.put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS,
+ new LanguageVersionSettingsImpl(explicitLanguageVersion, ApiVersion.LATEST));
}
return JvmResolveUtil.analyze(Collections.singleton(file), getEnvironment(), configuration);
}
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt
index 7b7a6859731..a47f9644caf 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptions.kt
@@ -4,6 +4,13 @@ package org.jetbrains.kotlin.gradle.dsl
interface KotlinJsOptions {
+ /**
+ * Allow to use declarations only from the specified version of bundled libraries
+ * Possible values: "1.0", "1.1"
+ * Default value: "1.1"
+ */
+ var apiVersion: kotlin.String
+
/**
* Generate kjsm-files (for creating libraries)
* Default value: true
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt
index 2cb98f71fa7..3ae48f2afbe 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJsOptionsBase.kt
@@ -4,6 +4,11 @@ package org.jetbrains.kotlin.gradle.dsl
internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.KotlinJsOptions {
+ private var apiVersionField: kotlin.String? = null
+ override var apiVersion: kotlin.String
+ get() = apiVersionField ?: "1.1"
+ set(value) { apiVersionField = value }
+
private var kjsmField: kotlin.Boolean? = null
override var kjsm: kotlin.Boolean
get() = kjsmField ?: true
@@ -60,6 +65,7 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko
set(value) { verboseField = value }
open fun updateArguments(args: org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments) {
+ apiVersionField?.let { args.apiVersion = it }
kjsmField?.let { args.kjsm = it }
languageVersionField?.let { args.languageVersion = it }
mainField?.let { args.main = it }
@@ -75,6 +81,7 @@ internal abstract class KotlinJsOptionsBase : org.jetbrains.kotlin.gradle.dsl.Ko
}
internal fun org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments.fillDefaultValues() {
+ apiVersion = "1.1"
kjsm = true
languageVersion = "1.1"
main = "noCall"
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt
index 81bc55cea5b..f6ff56cd41c 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptions.kt
@@ -4,6 +4,13 @@ package org.jetbrains.kotlin.gradle.dsl
interface KotlinJvmOptions {
+ /**
+ * Allow to use declarations only from the specified version of bundled libraries
+ * Possible values: "1.0", "1.1"
+ * Default value: "1.1"
+ */
+ var apiVersion: kotlin.String
+
/**
* Include Kotlin runtime in to resulting .jar
* Default value: false
diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt
index 0f17864db23..683c9707694 100644
--- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt
+++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinJvmOptionsBase.kt
@@ -4,6 +4,11 @@ package org.jetbrains.kotlin.gradle.dsl
internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions {
+ private var apiVersionField: kotlin.String? = null
+ override var apiVersion: kotlin.String
+ get() = apiVersionField ?: "1.1"
+ set(value) { apiVersionField = value }
+
private var includeRuntimeField: kotlin.Boolean? = null
override var includeRuntime: kotlin.Boolean
get() = includeRuntimeField ?: false
@@ -50,6 +55,7 @@ internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.K
set(value) { verboseField = value }
open fun updateArguments(args: org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments) {
+ apiVersionField?.let { args.apiVersion = it }
includeRuntimeField?.let { args.includeRuntime = it }
jdkHomeField?.let { args.jdkHome = it }
jvmTargetField?.let { args.jvmTarget = it }
@@ -63,6 +69,7 @@ internal abstract class KotlinJvmOptionsBase : org.jetbrains.kotlin.gradle.dsl.K
}
internal fun org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments.fillDefaultValues() {
+ apiVersion = "1.1"
includeRuntime = false
jdkHome = null
jvmTarget = "1.6"
diff --git a/license/third_party/maven_LICENSE.txt b/license/third_party/maven_LICENSE.txt
new file mode 100644
index 00000000000..d6456956733
--- /dev/null
+++ b/license/third_party/maven_LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.