KotlinRuntimeLibraryUtil: J2K
This commit is contained in:
+2
-2
@@ -22,7 +22,7 @@ import com.intellij.openapi.module.Module
|
|||||||
import com.intellij.openapi.roots.ModifiableModelsProvider
|
import com.intellij.openapi.roots.ModifiableModelsProvider
|
||||||
import com.intellij.openapi.roots.ModifiableRootModel
|
import com.intellij.openapi.roots.ModifiableRootModel
|
||||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil
|
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||||
import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder
|
import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder
|
||||||
import org.jetbrains.plugins.gradle.frameworkSupport.GradleFrameworkSupportProvider
|
import org.jetbrains.plugins.gradle.frameworkSupport.GradleFrameworkSupportProvider
|
||||||
import javax.swing.Icon
|
import javax.swing.Icon
|
||||||
@@ -40,7 +40,7 @@ class GradleKotlinJavaFrameworkSupportProvider() : GradleFrameworkSupportProvide
|
|||||||
rootModel: ModifiableRootModel,
|
rootModel: ModifiableRootModel,
|
||||||
modifiableModelsProvider: ModifiableModelsProvider,
|
modifiableModelsProvider: ModifiableModelsProvider,
|
||||||
buildScriptData: BuildScriptDataBuilder) {
|
buildScriptData: BuildScriptDataBuilder) {
|
||||||
var kotlinVersion = KotlinRuntimeLibraryUtil.bundledRuntimeVersion()
|
var kotlinVersion = bundledRuntimeVersion()
|
||||||
if (kotlinVersion == "@snapshot@") {
|
if (kotlinVersion == "@snapshot@") {
|
||||||
kotlinVersion = "0.1-SNAPSHOT"
|
kotlinVersion = "0.1-SNAPSHOT"
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.ui.DialogWrapper;
|
|||||||
import com.intellij.ui.SeparatorWithText;
|
import com.intellij.ui.SeparatorWithText;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil;
|
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
@@ -49,7 +49,7 @@ public abstract class CreateLibraryDialogBase extends DialogWrapper {
|
|||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
compilerTextLabel.setText(compilerTextLabel.getText() + " - " + KotlinRuntimeLibraryUtil.bundledRuntimeVersion());
|
compilerTextLabel.setText(compilerTextLabel.getText() + " - " + KotlinRuntimeLibraryUtilKt.bundledRuntimeVersion());
|
||||||
|
|
||||||
pathPanel = new ChooseLibraryPathPanel(defaultPath);
|
pathPanel = new ChooseLibraryPathPanel(defaultPath);
|
||||||
pathPanel.addValidityListener(new ValidityListener() {
|
pathPanel.addValidityListener(new ValidityListener() {
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider
|
|||||||
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
import org.jetbrains.kotlin.idea.quickfix.KotlinQuickFixAction
|
||||||
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
import org.jetbrains.kotlin.idea.quickfix.KotlinSingleIntentionActionFactory
|
||||||
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType
|
import org.jetbrains.kotlin.idea.quickfix.quickfixUtil.createIntentionForFirstParentOfType
|
||||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil
|
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||||
|
import org.jetbrains.kotlin.idea.versions.findKotlinLibraries
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
@@ -155,7 +156,7 @@ abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixAction<K
|
|||||||
val configurator = Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)
|
val configurator = Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)
|
||||||
.firstIsInstanceOrNull<KotlinJavaModuleConfigurator>() ?: return
|
.firstIsInstanceOrNull<KotlinJavaModuleConfigurator>() ?: return
|
||||||
|
|
||||||
for (library in KotlinRuntimeLibraryUtil.findKotlinLibraries(project)) {
|
for (library in findKotlinLibraries(project)) {
|
||||||
val runtimeJar = JavaRuntimePresentationProvider.getRuntimeJar(library) ?: continue
|
val runtimeJar = JavaRuntimePresentationProvider.getRuntimeJar(library) ?: continue
|
||||||
if (hasLibJarInLibrary(library)) continue
|
if (hasLibJarInLibrary(library)) continue
|
||||||
|
|
||||||
@@ -194,7 +195,7 @@ abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixAction<K
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val pluginVersion = KotlinRuntimeLibraryUtil.bundledRuntimeVersion()
|
val pluginVersion = bundledRuntimeVersion()
|
||||||
if ("@snapshot@" == pluginVersion) {
|
if ("@snapshot@" == pluginVersion) {
|
||||||
return "0.1-SNAPSHOT"
|
return "0.1-SNAPSHOT"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,319 +14,247 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.versions;
|
package org.jetbrains.kotlin.idea.versions
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.module.Module;
|
import com.intellij.openapi.module.Module
|
||||||
import com.intellij.openapi.module.ModuleManager;
|
import com.intellij.openapi.module.ModuleManager
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.roots.LibraryOrderEntry;
|
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||||
import com.intellij.openapi.roots.ModuleRootManager;
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
import com.intellij.openapi.roots.OrderEntry;
|
import com.intellij.openapi.roots.ProjectFileIndex
|
||||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
import com.intellij.openapi.roots.libraries.Library
|
||||||
import com.intellij.openapi.roots.libraries.Library;
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.openapi.util.text.StringUtil;
|
import com.intellij.openapi.vfs.JarFileSystem
|
||||||
import com.intellij.openapi.vfs.JarFileSystem;
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.ProjectScope
|
||||||
import com.intellij.psi.search.ProjectScope;
|
import com.intellij.util.CommonProcessors
|
||||||
import com.intellij.util.CommonProcessors;
|
import com.intellij.util.PathUtil.getLocalFile
|
||||||
import com.intellij.util.indexing.FileBasedIndex;
|
import com.intellij.util.PathUtil.getLocalPath
|
||||||
import com.intellij.util.indexing.ID;
|
import com.intellij.util.indexing.FileBasedIndex
|
||||||
import com.intellij.util.indexing.ScalarIndexExtension;
|
import com.intellij.util.indexing.ID
|
||||||
import kotlin.collections.ArraysKt;
|
import com.intellij.util.indexing.ScalarIndexExtension
|
||||||
import kotlin.collections.CollectionsKt;
|
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||||
import kotlin.jvm.functions.Function1;
|
import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.kotlin.idea.configuration.KotlinJsModuleConfigurator
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.kotlin.idea.configuration.getConfiguratorByName
|
||||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil;
|
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider
|
||||||
import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt;
|
import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider
|
||||||
import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator;
|
import org.jetbrains.kotlin.idea.framework.LibraryPresentationProviderUtil
|
||||||
import org.jetbrains.kotlin.idea.configuration.KotlinJsModuleConfigurator;
|
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||||
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider;
|
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification.showRuntimeJarNotFoundDialog
|
||||||
import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider;
|
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||||
import org.jetbrains.kotlin.idea.framework.LibraryPresentationProviderUtil;
|
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil;
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
import java.io.File
|
||||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils;
|
import java.io.IOException
|
||||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
import java.util.*
|
||||||
import org.jetbrains.kotlin.utils.PathUtil;
|
|
||||||
|
|
||||||
import java.io.File;
|
fun getLibraryRootsWithAbiIncompatibleKotlinClasses(project: Project): Collection<VirtualFile> {
|
||||||
import java.io.IOException;
|
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||||
import java.util.*;
|
project, KotlinMetadataVersionIndex,
|
||||||
|
{ module -> ProjectStructureUtil.isJavaKotlinModule(module) },
|
||||||
|
{ version -> !version.isCompatible() })
|
||||||
|
}
|
||||||
|
|
||||||
import static com.intellij.util.PathUtil.getLocalFile;
|
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(project: Project): Collection<VirtualFile> {
|
||||||
import static com.intellij.util.PathUtil.getLocalPath;
|
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||||
import static org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification.showRuntimeJarNotFoundDialog;
|
project, KotlinJavaScriptAbiVersionIndex,
|
||||||
|
{ module -> ProjectStructureUtil.isJsKotlinModule(module) },
|
||||||
public class KotlinRuntimeLibraryUtil {
|
{ version -> !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.minor) }) // TODO: support major.minor.patch version in JS metadata
|
||||||
private KotlinRuntimeLibraryUtil() {
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Collection<VirtualFile> getLibraryRootsWithAbiIncompatibleKotlinClasses(@NotNull Project project) {
|
|
||||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
|
||||||
project, KotlinMetadataVersionIndex.INSTANCE,
|
|
||||||
new Function1<Module, Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean invoke(@Nullable Module module) {
|
|
||||||
return module != null && ProjectStructureUtil.isJavaKotlinModule(module);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<BinaryVersion, Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean invoke(@NotNull BinaryVersion version) {
|
|
||||||
return !version.isCompatible();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Collection<VirtualFile> getLibraryRootsWithAbiIncompatibleForKotlinJs(@NotNull Project project) {
|
|
||||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
|
||||||
project, KotlinJavaScriptAbiVersionIndex.INSTANCE,
|
|
||||||
new Function1<Module, Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean invoke(@Nullable Module module) {
|
|
||||||
return module != null && ProjectStructureUtil.isJsKotlinModule(module);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new Function1<BinaryVersion, Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean invoke(@NotNull BinaryVersion version) {
|
|
||||||
// TODO: support major.minor.patch version in JS metadata
|
|
||||||
return !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.getMinor());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void updateLibraries(
|
fun updateLibraries(
|
||||||
@NotNull final Project project,
|
project: Project,
|
||||||
@NotNull final Collection<Library> libraries
|
libraries: Collection<Library>) {
|
||||||
) {
|
ApplicationManager.getApplication().invokeLater {
|
||||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator?
|
||||||
@Override
|
assert(kJvmConfigurator != null) { "Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME }
|
||||||
public void run() {
|
|
||||||
KotlinJavaModuleConfigurator kJvmConfigurator = (KotlinJavaModuleConfigurator)
|
|
||||||
ConfigureKotlinInProjectUtilsKt.getConfiguratorByName(KotlinJavaModuleConfigurator.NAME);
|
|
||||||
assert kJvmConfigurator != null : "Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME;
|
|
||||||
|
|
||||||
KotlinJsModuleConfigurator kJsConfigurator = (KotlinJsModuleConfigurator)
|
val kJsConfigurator = getConfiguratorByName(KotlinJsModuleConfigurator.NAME) as KotlinJsModuleConfigurator?
|
||||||
ConfigureKotlinInProjectUtilsKt.getConfiguratorByName(KotlinJsModuleConfigurator.NAME);
|
assert(kJsConfigurator != null) { "Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME }
|
||||||
assert kJsConfigurator != null : "Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME;
|
|
||||||
|
|
||||||
for (Library library : libraries) {
|
for (library in libraries) {
|
||||||
if (LibraryPresentationProviderUtil.isDetected(JavaRuntimePresentationProvider.getInstance(), library)) {
|
if (LibraryPresentationProviderUtil.isDetected(JavaRuntimePresentationProvider.getInstance(), library)) {
|
||||||
updateJar(project, JavaRuntimePresentationProvider.getRuntimeJar(library), LibraryJarDescriptor.RUNTIME_JAR);
|
updateJar(project, JavaRuntimePresentationProvider.getRuntimeJar(library), LibraryJarDescriptor.RUNTIME_JAR)
|
||||||
updateJar(project, JavaRuntimePresentationProvider.getReflectJar(library), LibraryJarDescriptor.REFLECT_JAR);
|
updateJar(project, JavaRuntimePresentationProvider.getReflectJar(library), LibraryJarDescriptor.REFLECT_JAR)
|
||||||
|
|
||||||
if (kJvmConfigurator.changeOldSourcesPathIfNeeded(project, library)) {
|
if (kJvmConfigurator!!.changeOldSourcesPathIfNeeded(project, library)) {
|
||||||
kJvmConfigurator.copySourcesToPathFromLibrary(project, library);
|
kJvmConfigurator.copySourcesToPathFromLibrary(project, library)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
updateJar(project, JavaRuntimePresentationProvider.getRuntimeSrcJar(library), LibraryJarDescriptor.RUNTIME_SRC_JAR);
|
updateJar(project, JavaRuntimePresentationProvider.getRuntimeSrcJar(library), LibraryJarDescriptor.RUNTIME_SRC_JAR)
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (LibraryPresentationProviderUtil.isDetected(JSLibraryStdPresentationProvider.getInstance(), library)) {
|
|
||||||
updateJar(project, JSLibraryStdPresentationProvider.getJsStdLibJar(library), LibraryJarDescriptor.JS_STDLIB_JAR);
|
|
||||||
|
|
||||||
if (kJsConfigurator.changeOldSourcesPathIfNeeded(project, library)) {
|
|
||||||
kJsConfigurator.copySourcesToPathFromLibrary(project, library);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
updateJar(project, JSLibraryStdPresentationProvider.getJsStdLibSrcJar(library), LibraryJarDescriptor.JS_STDLIB_SRC_JAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
else if (LibraryPresentationProviderUtil.isDetected(JSLibraryStdPresentationProvider.getInstance(), library)) {
|
||||||
}
|
updateJar(project, JSLibraryStdPresentationProvider.getJsStdLibJar(library), LibraryJarDescriptor.JS_STDLIB_JAR)
|
||||||
|
|
||||||
private static void updateJar(
|
if (kJsConfigurator!!.changeOldSourcesPathIfNeeded(project, library)) {
|
||||||
@NotNull Project project,
|
kJsConfigurator.copySourcesToPathFromLibrary(project, library)
|
||||||
@Nullable VirtualFile fileToReplace,
|
}
|
||||||
@NotNull LibraryJarDescriptor libraryJarDescriptor
|
else {
|
||||||
) {
|
updateJar(project, JSLibraryStdPresentationProvider.getJsStdLibSrcJar(library), LibraryJarDescriptor.JS_STDLIB_SRC_JAR)
|
||||||
if (fileToReplace == null && !libraryJarDescriptor.shouldExist) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
KotlinPaths paths = PathUtil.getKotlinPathsForIdeaPlugin();
|
|
||||||
File jarPath;
|
|
||||||
switch (libraryJarDescriptor) {
|
|
||||||
case RUNTIME_JAR: jarPath = paths.getRuntimePath(); break;
|
|
||||||
case REFLECT_JAR: jarPath = paths.getReflectPath(); break;
|
|
||||||
case RUNTIME_SRC_JAR: jarPath = paths.getRuntimeSourcesPath(); break;
|
|
||||||
case JS_STDLIB_JAR: jarPath = paths.getJsStdLibJarPath(); break;
|
|
||||||
case JS_STDLIB_SRC_JAR: jarPath = paths.getJsStdLibSrcJarPath(); break;
|
|
||||||
default: jarPath = null; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!jarPath.exists()) {
|
|
||||||
showRuntimeJarNotFoundDialog(project, libraryJarDescriptor.jarName).run();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
VirtualFile localJar = getLocalJar(fileToReplace);
|
|
||||||
assert localJar != null;
|
|
||||||
|
|
||||||
replaceFile(jarPath, localJar);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Collection<Library> findKotlinLibraries(@NotNull Project project) {
|
|
||||||
Set<Library> libraries = Sets.newHashSet();
|
|
||||||
|
|
||||||
for (Module module : ModuleManager.getInstance(project).getModules()) {
|
|
||||||
ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
|
|
||||||
|
|
||||||
for (OrderEntry entry : moduleRootManager.getOrderEntries()) {
|
|
||||||
if (entry instanceof LibraryOrderEntry) {
|
|
||||||
LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry) entry;
|
|
||||||
Library library = libraryOrderEntry.getLibrary();
|
|
||||||
|
|
||||||
if (library == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
libraries.add(library);
|
|
||||||
|
|
||||||
// TODO: search js libraries as well
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return libraries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum LibraryJarDescriptor {
|
|
||||||
RUNTIME_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_JAR, true),
|
|
||||||
REFLECT_JAR(PathUtil.KOTLIN_JAVA_REFLECT_JAR, false),
|
|
||||||
RUNTIME_SRC_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_SRC_JAR, false),
|
|
||||||
JS_STDLIB_JAR(PathUtil.JS_LIB_JAR_NAME, true),
|
|
||||||
JS_STDLIB_SRC_JAR(PathUtil.JS_LIB_SRC_JAR_NAME, false);
|
|
||||||
|
|
||||||
public final String jarName;
|
|
||||||
private final boolean shouldExist;
|
|
||||||
|
|
||||||
LibraryJarDescriptor(@NotNull String jarName, boolean shouldExist) {
|
|
||||||
this.jarName = jarName;
|
|
||||||
this.shouldExist = shouldExist;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String bundledRuntimeVersion() {
|
|
||||||
return bundledRuntimeVersion(KotlinPluginUtil.getPluginVersion());
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static String bundledRuntimeVersion(@NotNull String pluginVersion) {
|
|
||||||
int placeToSplit = -1;
|
|
||||||
|
|
||||||
int ideaPatternIndex = StringUtil.indexOf(pluginVersion, "Idea");
|
|
||||||
if (ideaPatternIndex >= 2 && Character.isDigit(pluginVersion.charAt(ideaPatternIndex - 2))) {
|
|
||||||
placeToSplit = ideaPatternIndex - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ijPatternIndex = StringUtil.indexOf(pluginVersion, "IJ");
|
|
||||||
if (ijPatternIndex >= 2 && Character.isDigit(pluginVersion.charAt(ijPatternIndex - 2))) {
|
|
||||||
placeToSplit = ijPatternIndex - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (placeToSplit == -1) {
|
|
||||||
for (int i = 1; i < pluginVersion.length(); i++) {
|
|
||||||
char ch = pluginVersion.charAt(i);
|
|
||||||
if (Character.isLetter(ch) && pluginVersion.charAt(i - 1) == '.') {
|
|
||||||
placeToSplit = i - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return placeToSplit != - 1 ? pluginVersion.substring(0, placeToSplit) : pluginVersion;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static VirtualFile getLocalJar(@Nullable VirtualFile kotlinRuntimeJar) {
|
|
||||||
if (kotlinRuntimeJar == null) return null;
|
|
||||||
|
|
||||||
VirtualFile localJarFile = JarFileSystem.getInstance().getVirtualFileForJar(kotlinRuntimeJar);
|
|
||||||
if (localJarFile != null) {
|
|
||||||
return localJarFile;
|
|
||||||
}
|
|
||||||
return kotlinRuntimeJar;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void replaceFile(File updatedFile, VirtualFile replacedJarFile) {
|
|
||||||
try {
|
|
||||||
VirtualFile replacedFile = getLocalFile(replacedJarFile);
|
|
||||||
|
|
||||||
String localPath = getLocalPath(replacedFile);
|
|
||||||
assert localPath != null : "Should be called for replacing valid root file: " + replacedJarFile;
|
|
||||||
|
|
||||||
File libraryJarPath = new File(localPath);
|
|
||||||
|
|
||||||
if (FileUtil.filesEqual(updatedFile, libraryJarPath)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileUtil.copy(updatedFile, libraryJarPath);
|
|
||||||
replacedFile.refresh(false, true);
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static Collection<VirtualFile> getLibraryRootsWithAbiIncompatibleVersion(
|
|
||||||
@NotNull Project project,
|
|
||||||
@NotNull ScalarIndexExtension<BinaryVersion> index,
|
|
||||||
@NotNull Function1<Module, Boolean> checkModule,
|
|
||||||
@NotNull Function1<BinaryVersion, Boolean> checkVersion
|
|
||||||
) {
|
|
||||||
ID<BinaryVersion, Void> id = index.getName();
|
|
||||||
|
|
||||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
|
||||||
|
|
||||||
List<Module> modulesToCheck = ArraysKt.filter(modules, checkModule);
|
|
||||||
if (modulesToCheck.isEmpty()) return Collections.emptyList();
|
|
||||||
|
|
||||||
Collection<BinaryVersion> versions = collectAllKeys(id, modulesToCheck);
|
|
||||||
Set<BinaryVersion> badVersions = Sets.newHashSet(CollectionsKt.filter(versions, checkVersion));
|
|
||||||
Set<VirtualFile> badRoots = Sets.newHashSet();
|
|
||||||
ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(project);
|
|
||||||
|
|
||||||
for (BinaryVersion version : badVersions) {
|
|
||||||
Collection<VirtualFile> indexedFiles = FileBasedIndex.getInstance().getContainingFiles(
|
|
||||||
id, version, ProjectScope.getLibrariesScope(project));
|
|
||||||
|
|
||||||
for (VirtualFile indexedFile : indexedFiles) {
|
|
||||||
VirtualFile libraryRoot = fileIndex.getClassRootForFile(indexedFile);
|
|
||||||
assert libraryRoot != null : "Only library roots were requested, " +
|
|
||||||
"and only class files should be indexed with KotlinAbiVersionIndex key. " +
|
|
||||||
"File: " + indexedFile.getPath();
|
|
||||||
badRoots.add(getLocalFile(libraryRoot));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return badRoots;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static <T> Collection<T> collectAllKeys(@NotNull ID<T, Void> id, @NotNull List<Module> modules) {
|
|
||||||
Set<T> allKeys = new HashSet<T>();
|
|
||||||
|
|
||||||
for (Module module : modules) {
|
|
||||||
GlobalSearchScope scope = GlobalSearchScope.moduleWithLibrariesScope(module);
|
|
||||||
FileBasedIndex.getInstance().processAllKeys(id, new CommonProcessors.CollectProcessor<T>(allKeys), scope, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
return allKeys;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateJar(
|
||||||
|
project: Project,
|
||||||
|
fileToReplace: VirtualFile?,
|
||||||
|
libraryJarDescriptor: LibraryJarDescriptor) {
|
||||||
|
if (fileToReplace == null && !libraryJarDescriptor.shouldExist) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val paths = PathUtil.getKotlinPathsForIdeaPlugin()
|
||||||
|
val jarPath: File = when (libraryJarDescriptor) {
|
||||||
|
LibraryJarDescriptor.RUNTIME_JAR -> paths.runtimePath
|
||||||
|
LibraryJarDescriptor.REFLECT_JAR -> paths.reflectPath
|
||||||
|
LibraryJarDescriptor.RUNTIME_SRC_JAR -> paths.runtimeSourcesPath
|
||||||
|
LibraryJarDescriptor.JS_STDLIB_JAR -> paths.jsStdLibJarPath
|
||||||
|
LibraryJarDescriptor.JS_STDLIB_SRC_JAR -> paths.jsStdLibSrcJarPath
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!jarPath.exists()) {
|
||||||
|
showRuntimeJarNotFoundDialog(project, libraryJarDescriptor.jarName).run()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val localJar = getLocalJar(fileToReplace)
|
||||||
|
assert(localJar != null)
|
||||||
|
|
||||||
|
replaceFile(jarPath, localJar!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findKotlinLibraries(project: Project): Collection<Library> {
|
||||||
|
val libraries = Sets.newHashSet<Library>()
|
||||||
|
|
||||||
|
for (module in ModuleManager.getInstance(project).modules) {
|
||||||
|
val moduleRootManager = ModuleRootManager.getInstance(module)
|
||||||
|
|
||||||
|
for (entry in moduleRootManager.orderEntries) {
|
||||||
|
if (entry is LibraryOrderEntry) {
|
||||||
|
val library = entry.library ?: continue
|
||||||
|
|
||||||
|
libraries.add(library)
|
||||||
|
|
||||||
|
// TODO: search js libraries as well
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return libraries
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum class LibraryJarDescriptor private constructor(val jarName: String, val shouldExist: Boolean) {
|
||||||
|
RUNTIME_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_JAR, true),
|
||||||
|
REFLECT_JAR(PathUtil.KOTLIN_JAVA_REFLECT_JAR, false),
|
||||||
|
RUNTIME_SRC_JAR(PathUtil.KOTLIN_JAVA_RUNTIME_SRC_JAR, false),
|
||||||
|
JS_STDLIB_JAR(PathUtil.JS_LIB_JAR_NAME, true),
|
||||||
|
JS_STDLIB_SRC_JAR(PathUtil.JS_LIB_SRC_JAR_NAME, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmOverloads fun bundledRuntimeVersion(pluginVersion: String = KotlinPluginUtil.getPluginVersion()): String {
|
||||||
|
var placeToSplit = -1
|
||||||
|
|
||||||
|
val ideaPatternIndex = StringUtil.indexOf(pluginVersion, "Idea")
|
||||||
|
if (ideaPatternIndex >= 2 && Character.isDigit(pluginVersion[ideaPatternIndex - 2])) {
|
||||||
|
placeToSplit = ideaPatternIndex - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
val ijPatternIndex = StringUtil.indexOf(pluginVersion, "IJ")
|
||||||
|
if (ijPatternIndex >= 2 && Character.isDigit(pluginVersion[ijPatternIndex - 2])) {
|
||||||
|
placeToSplit = ijPatternIndex - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (placeToSplit == -1) {
|
||||||
|
for (i in 1..pluginVersion.length - 1) {
|
||||||
|
val ch = pluginVersion[i]
|
||||||
|
if (Character.isLetter(ch) && pluginVersion[i - 1] == '.') {
|
||||||
|
placeToSplit = i - 1
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (placeToSplit != -1) pluginVersion.substring(0, placeToSplit) else pluginVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getLocalJar(kotlinRuntimeJar: VirtualFile?): VirtualFile? {
|
||||||
|
if (kotlinRuntimeJar == null) return null
|
||||||
|
|
||||||
|
val localJarFile = JarFileSystem.getInstance().getVirtualFileForJar(kotlinRuntimeJar)
|
||||||
|
if (localJarFile != null) {
|
||||||
|
return localJarFile
|
||||||
|
}
|
||||||
|
return kotlinRuntimeJar
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun replaceFile(updatedFile: File, replacedJarFile: VirtualFile) {
|
||||||
|
try {
|
||||||
|
val replacedFile = getLocalFile(replacedJarFile)
|
||||||
|
|
||||||
|
val localPath = getLocalPath(replacedFile)
|
||||||
|
assert(localPath != null) { "Should be called for replacing valid root file: " + replacedJarFile }
|
||||||
|
|
||||||
|
val libraryJarPath = File(localPath)
|
||||||
|
|
||||||
|
if (FileUtil.filesEqual(updatedFile, libraryJarPath)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
FileUtil.copy(updatedFile, libraryJarPath)
|
||||||
|
replacedFile.refresh(false, true)
|
||||||
|
}
|
||||||
|
catch (e: IOException) {
|
||||||
|
throw AssertionError(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getLibraryRootsWithAbiIncompatibleVersion(
|
||||||
|
project: Project,
|
||||||
|
index: ScalarIndexExtension<BinaryVersion>,
|
||||||
|
checkModule: (Module) -> Boolean,
|
||||||
|
checkVersion: (BinaryVersion) -> Boolean): Collection<VirtualFile> {
|
||||||
|
val id = index.name
|
||||||
|
|
||||||
|
val modules = ModuleManager.getInstance(project).modules
|
||||||
|
|
||||||
|
val modulesToCheck = modules.filter(checkModule)
|
||||||
|
if (modulesToCheck.isEmpty()) return emptyList()
|
||||||
|
|
||||||
|
val versions = collectAllKeys(id, modulesToCheck)
|
||||||
|
val badVersions = versions.filter(checkVersion).toHashSet()
|
||||||
|
val badRoots = Sets.newHashSet<VirtualFile>()
|
||||||
|
val fileIndex = ProjectFileIndex.SERVICE.getInstance(project)
|
||||||
|
|
||||||
|
for (version in badVersions) {
|
||||||
|
val indexedFiles = FileBasedIndex.getInstance().getContainingFiles(
|
||||||
|
id, version, ProjectScope.getLibrariesScope(project))
|
||||||
|
|
||||||
|
for (indexedFile in indexedFiles) {
|
||||||
|
val libraryRoot = fileIndex.getClassRootForFile(indexedFile)
|
||||||
|
assert(libraryRoot != null) { "Only library roots were requested, " + "and only class files should be indexed with KotlinAbiVersionIndex key. " + "File: " + indexedFile.path }
|
||||||
|
badRoots.add(getLocalFile(libraryRoot!!))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return badRoots
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> collectAllKeys(id: ID<T, Void>, modules: List<Module>): Collection<T> {
|
||||||
|
val allKeys = HashSet<T>()
|
||||||
|
|
||||||
|
for (module in modules) {
|
||||||
|
val scope = GlobalSearchScope.moduleWithLibrariesScope(module)
|
||||||
|
FileBasedIndex.getInstance().processAllKeys(id, CommonProcessors.CollectProcessor(allKeys), scope, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
return allKeys
|
||||||
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
if ("update".equals(event.getDescription())) {
|
if ("update".equals(event.getDescription())) {
|
||||||
Collection<VersionedLibrary> versionedOutdatedLibraries = findOutdatedKotlinLibraries(myProject);
|
Collection<VersionedLibrary> versionedOutdatedLibraries = findOutdatedKotlinLibraries(myProject);
|
||||||
Collection<Library> outdatedLibraries = extractLibraries(versionedOutdatedLibraries);
|
Collection<Library> outdatedLibraries = extractLibraries(versionedOutdatedLibraries);
|
||||||
KotlinRuntimeLibraryUtil.updateLibraries(myProject, outdatedLibraries);
|
KotlinRuntimeLibraryUtilKt.updateLibraries(myProject, outdatedLibraries);
|
||||||
suggestDeleteKotlinJsIfNeeded(outdatedLibraries);
|
suggestDeleteKotlinJsIfNeeded(outdatedLibraries);
|
||||||
}
|
}
|
||||||
else if ("ignore".equals(event.getDescription())) {
|
else if ("ignore".equals(event.getDescription())) {
|
||||||
@@ -232,7 +232,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
private static Collection<VersionedLibrary> findOutdatedKotlinLibraries(@NotNull Project project) {
|
private static Collection<VersionedLibrary> findOutdatedKotlinLibraries(@NotNull Project project) {
|
||||||
List<VersionedLibrary> outdatedLibraries = Lists.newArrayList();
|
List<VersionedLibrary> outdatedLibraries = Lists.newArrayList();
|
||||||
|
|
||||||
for (Library library : KotlinRuntimeLibraryUtil.findKotlinLibraries(project)) {
|
for (Library library : KotlinRuntimeLibraryUtilKt.findKotlinLibraries(project)) {
|
||||||
LibraryVersionProperties libraryVersionProperties =
|
LibraryVersionProperties libraryVersionProperties =
|
||||||
LibraryPresentationProviderUtil.getLibraryProperties(JavaRuntimePresentationProvider.getInstance(), library);
|
LibraryPresentationProviderUtil.getLibraryProperties(JavaRuntimePresentationProvider.getInstance(), library);
|
||||||
if (libraryVersionProperties == null) {
|
if (libraryVersionProperties == null) {
|
||||||
@@ -244,7 +244,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
}
|
}
|
||||||
String libraryVersion = libraryVersionProperties.getVersionString();
|
String libraryVersion = libraryVersionProperties.getVersionString();
|
||||||
|
|
||||||
String runtimeVersion = KotlinRuntimeLibraryUtil.bundledRuntimeVersion();
|
String runtimeVersion = KotlinRuntimeLibraryUtilKt.bundledRuntimeVersion();
|
||||||
|
|
||||||
boolean isOutdated = isRuntimeOutdated(libraryVersion, runtimeVersion);
|
boolean isOutdated = isRuntimeOutdated(libraryVersion, runtimeVersion);
|
||||||
|
|
||||||
|
|||||||
+6
-6
@@ -103,13 +103,13 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
|||||||
private EditorNotificationPanel doCreate(final Collection<VirtualFile> badRoots) {
|
private EditorNotificationPanel doCreate(final Collection<VirtualFile> badRoots) {
|
||||||
EditorNotificationPanel answer = new ErrorNotificationPanel();
|
EditorNotificationPanel answer = new ErrorNotificationPanel();
|
||||||
|
|
||||||
Collection<Library> kotlinLibraries = KotlinRuntimeLibraryUtil.findKotlinLibraries(project);
|
Collection<Library> kotlinLibraries = KotlinRuntimeLibraryUtilKt.findKotlinLibraries(project);
|
||||||
final Collection<Library> badRuntimeLibraries = Collections2.filter(kotlinLibraries, new Predicate<Library>() {
|
final Collection<Library> badRuntimeLibraries = Collections2.filter(kotlinLibraries, new Predicate<Library>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(@Nullable Library library) {
|
public boolean apply(@Nullable Library library) {
|
||||||
assert library != null : "library should be non null";
|
assert library != null : "library should be non null";
|
||||||
VirtualFile runtimeJar = KotlinRuntimeLibraryUtil.getLocalJar(JavaRuntimePresentationProvider.getRuntimeJar(library));
|
VirtualFile runtimeJar = KotlinRuntimeLibraryUtilKt.getLocalJar(JavaRuntimePresentationProvider.getRuntimeJar(library));
|
||||||
VirtualFile jsLibJar = KotlinRuntimeLibraryUtil.getLocalJar(JSLibraryStdPresentationProvider.getJsStdLibJar(library));
|
VirtualFile jsLibJar = KotlinRuntimeLibraryUtilKt.getLocalJar(JSLibraryStdPresentationProvider.getJsStdLibJar(library));
|
||||||
return badRoots.contains(runtimeJar) || badRoots.contains(jsLibJar);
|
return badRoots.contains(runtimeJar) || badRoots.contains(jsLibJar);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -130,7 +130,7 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
|||||||
answer.createActionLabel(actionLabelText, new Runnable() {
|
answer.createActionLabel(actionLabelText, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
KotlinRuntimeLibraryUtil.updateLibraries(project, badRuntimeLibraries);
|
KotlinRuntimeLibraryUtilKt.updateLibraries(project, badRuntimeLibraries);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (otherBadRootsCount > 0) {
|
if (otherBadRootsCount > 0) {
|
||||||
@@ -278,8 +278,8 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static Collection<VirtualFile> collectBadRoots(@NotNull Project project) {
|
private static Collection<VirtualFile> collectBadRoots(@NotNull Project project) {
|
||||||
Collection<VirtualFile> badJVMRoots = KotlinRuntimeLibraryUtil.getLibraryRootsWithAbiIncompatibleKotlinClasses(project);
|
Collection<VirtualFile> badJVMRoots = KotlinRuntimeLibraryUtilKt.getLibraryRootsWithAbiIncompatibleKotlinClasses(project);
|
||||||
Collection<VirtualFile> badJSRoots = KotlinRuntimeLibraryUtil.getLibraryRootsWithAbiIncompatibleForKotlinJs(project);
|
Collection<VirtualFile> badJSRoots = KotlinRuntimeLibraryUtilKt.getLibraryRootsWithAbiIncompatibleForKotlinJs(project);
|
||||||
|
|
||||||
if (badJVMRoots.isEmpty() && badJSRoots.isEmpty()) return Collections.emptyList();
|
if (badJVMRoots.isEmpty() && badJSRoots.isEmpty()) return Collections.emptyList();
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
package org.jetbrains.kotlin.idea
|
package org.jetbrains.kotlin.idea
|
||||||
|
|
||||||
import junit.framework.TestCase
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil
|
|
||||||
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification
|
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification
|
||||||
|
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
|
|
||||||
|
|
||||||
@@ -87,15 +87,15 @@ class KotlinRuntimeLibraryUtilTest : TestCase() {
|
|||||||
|
|
||||||
private fun outdated(plugin: String, library: String) {
|
private fun outdated(plugin: String, library: String) {
|
||||||
Assert.assertTrue("Should be outdated: plugin=$plugin, library=$library",
|
Assert.assertTrue("Should be outdated: plugin=$plugin, library=$library",
|
||||||
OutdatedKotlinRuntimeNotification.isRuntimeOutdated(library, KotlinRuntimeLibraryUtil.bundledRuntimeVersion(plugin)))
|
OutdatedKotlinRuntimeNotification.isRuntimeOutdated(library, bundledRuntimeVersion(plugin)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun notOutdated(plugin: String, library: String) {
|
private fun notOutdated(plugin: String, library: String) {
|
||||||
Assert.assertFalse("Should NOT be outdated: plugin=$plugin, library=$library",
|
Assert.assertFalse("Should NOT be outdated: plugin=$plugin, library=$library",
|
||||||
OutdatedKotlinRuntimeNotification.isRuntimeOutdated(library, KotlinRuntimeLibraryUtil.bundledRuntimeVersion(plugin)))
|
OutdatedKotlinRuntimeNotification.isRuntimeOutdated(library, bundledRuntimeVersion(plugin)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun test(version: String, expected: String) {
|
private fun test(version: String, expected: String) {
|
||||||
Assert.assertEquals(expected, KotlinRuntimeLibraryUtil.bundledRuntimeVersion(version))
|
Assert.assertEquals(expected, bundledRuntimeVersion(version))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user