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.ModifiableRootModel
|
||||
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.GradleFrameworkSupportProvider
|
||||
import javax.swing.Icon
|
||||
@@ -40,7 +40,7 @@ class GradleKotlinJavaFrameworkSupportProvider() : GradleFrameworkSupportProvide
|
||||
rootModel: ModifiableRootModel,
|
||||
modifiableModelsProvider: ModifiableModelsProvider,
|
||||
buildScriptData: BuildScriptDataBuilder) {
|
||||
var kotlinVersion = KotlinRuntimeLibraryUtil.bundledRuntimeVersion()
|
||||
var kotlinVersion = bundledRuntimeVersion()
|
||||
if (kotlinVersion == "@snapshot@") {
|
||||
kotlinVersion = "0.1-SNAPSHOT"
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.ui.SeparatorWithText;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil;
|
||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -49,7 +49,7 @@ public abstract class CreateLibraryDialogBase extends DialogWrapper {
|
||||
|
||||
init();
|
||||
|
||||
compilerTextLabel.setText(compilerTextLabel.getText() + " - " + KotlinRuntimeLibraryUtil.bundledRuntimeVersion());
|
||||
compilerTextLabel.setText(compilerTextLabel.getText() + " - " + KotlinRuntimeLibraryUtilKt.bundledRuntimeVersion());
|
||||
|
||||
pathPanel = new ChooseLibraryPathPanel(defaultPath);
|
||||
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.KotlinSingleIntentionActionFactory
|
||||
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.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
@@ -155,7 +156,7 @@ abstract class AddKotlinLibQuickFix(element: KtElement) : KotlinQuickFixAction<K
|
||||
val configurator = Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)
|
||||
.firstIsInstanceOrNull<KotlinJavaModuleConfigurator>() ?: return
|
||||
|
||||
for (library in KotlinRuntimeLibraryUtil.findKotlinLibraries(project)) {
|
||||
for (library in findKotlinLibraries(project)) {
|
||||
val runtimeJar = JavaRuntimePresentationProvider.getRuntimeJar(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) {
|
||||
return "0.1-SNAPSHOT"
|
||||
}
|
||||
|
||||
@@ -14,319 +14,247 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.versions;
|
||||
package org.jetbrains.kotlin.idea.versions
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderEntry;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.ProjectScope;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.intellij.util.indexing.ID;
|
||||
import com.intellij.util.indexing.ScalarIndexExtension;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil;
|
||||
import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt;
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator;
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinJsModuleConfigurator;
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider;
|
||||
import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider;
|
||||
import org.jetbrains.kotlin.idea.framework.LibraryPresentationProviderUtil;
|
||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion;
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils;
|
||||
import org.jetbrains.kotlin.utils.KotlinPaths;
|
||||
import org.jetbrains.kotlin.utils.PathUtil;
|
||||
import com.google.common.collect.Sets
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.roots.LibraryOrderEntry
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
import com.intellij.openapi.roots.ProjectFileIndex
|
||||
import com.intellij.openapi.roots.libraries.Library
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.openapi.vfs.JarFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.ProjectScope
|
||||
import com.intellij.util.CommonProcessors
|
||||
import com.intellij.util.PathUtil.getLocalFile
|
||||
import com.intellij.util.PathUtil.getLocalPath
|
||||
import com.intellij.util.indexing.FileBasedIndex
|
||||
import com.intellij.util.indexing.ID
|
||||
import com.intellij.util.indexing.ScalarIndexExtension
|
||||
import org.jetbrains.kotlin.idea.KotlinPluginUtil
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinJavaModuleConfigurator
|
||||
import org.jetbrains.kotlin.idea.configuration.KotlinJsModuleConfigurator
|
||||
import org.jetbrains.kotlin.idea.configuration.getConfiguratorByName
|
||||
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider
|
||||
import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider
|
||||
import org.jetbrains.kotlin.idea.framework.LibraryPresentationProviderUtil
|
||||
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
|
||||
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification.showRuntimeJarNotFoundDialog
|
||||
import org.jetbrains.kotlin.serialization.deserialization.BinaryVersion
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
fun getLibraryRootsWithAbiIncompatibleKotlinClasses(project: Project): Collection<VirtualFile> {
|
||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||
project, KotlinMetadataVersionIndex,
|
||||
{ module -> ProjectStructureUtil.isJavaKotlinModule(module) },
|
||||
{ version -> !version.isCompatible() })
|
||||
}
|
||||
|
||||
import static com.intellij.util.PathUtil.getLocalFile;
|
||||
import static com.intellij.util.PathUtil.getLocalPath;
|
||||
import static org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification.showRuntimeJarNotFoundDialog;
|
||||
|
||||
public class KotlinRuntimeLibraryUtil {
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
fun getLibraryRootsWithAbiIncompatibleForKotlinJs(project: Project): Collection<VirtualFile> {
|
||||
return getLibraryRootsWithAbiIncompatibleVersion(
|
||||
project, KotlinJavaScriptAbiVersionIndex,
|
||||
{ module -> ProjectStructureUtil.isJsKotlinModule(module) },
|
||||
{ version -> !KotlinJavascriptMetadataUtils.isAbiVersionCompatible(version.minor) }) // TODO: support major.minor.patch version in JS metadata
|
||||
}
|
||||
|
||||
|
||||
public static void updateLibraries(
|
||||
@NotNull final Project project,
|
||||
@NotNull final Collection<Library> libraries
|
||||
) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
KotlinJavaModuleConfigurator kJvmConfigurator = (KotlinJavaModuleConfigurator)
|
||||
ConfigureKotlinInProjectUtilsKt.getConfiguratorByName(KotlinJavaModuleConfigurator.NAME);
|
||||
assert kJvmConfigurator != null : "Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME;
|
||||
fun updateLibraries(
|
||||
project: Project,
|
||||
libraries: Collection<Library>) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
val kJvmConfigurator = getConfiguratorByName(KotlinJavaModuleConfigurator.NAME) as KotlinJavaModuleConfigurator?
|
||||
assert(kJvmConfigurator != null) { "Configurator with given name doesn't exists: " + KotlinJavaModuleConfigurator.NAME }
|
||||
|
||||
KotlinJsModuleConfigurator kJsConfigurator = (KotlinJsModuleConfigurator)
|
||||
ConfigureKotlinInProjectUtilsKt.getConfiguratorByName(KotlinJsModuleConfigurator.NAME);
|
||||
assert kJsConfigurator != null : "Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME;
|
||||
val kJsConfigurator = getConfiguratorByName(KotlinJsModuleConfigurator.NAME) as KotlinJsModuleConfigurator?
|
||||
assert(kJsConfigurator != null) { "Configurator with given name doesn't exists: " + KotlinJsModuleConfigurator.NAME }
|
||||
|
||||
for (Library library : libraries) {
|
||||
if (LibraryPresentationProviderUtil.isDetected(JavaRuntimePresentationProvider.getInstance(), library)) {
|
||||
updateJar(project, JavaRuntimePresentationProvider.getRuntimeJar(library), LibraryJarDescriptor.RUNTIME_JAR);
|
||||
updateJar(project, JavaRuntimePresentationProvider.getReflectJar(library), LibraryJarDescriptor.REFLECT_JAR);
|
||||
for (library in libraries) {
|
||||
if (LibraryPresentationProviderUtil.isDetected(JavaRuntimePresentationProvider.getInstance(), library)) {
|
||||
updateJar(project, JavaRuntimePresentationProvider.getRuntimeJar(library), LibraryJarDescriptor.RUNTIME_JAR)
|
||||
updateJar(project, JavaRuntimePresentationProvider.getReflectJar(library), LibraryJarDescriptor.REFLECT_JAR)
|
||||
|
||||
if (kJvmConfigurator.changeOldSourcesPathIfNeeded(project, library)) {
|
||||
kJvmConfigurator.copySourcesToPathFromLibrary(project, library);
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (kJvmConfigurator!!.changeOldSourcesPathIfNeeded(project, library)) {
|
||||
kJvmConfigurator.copySourcesToPathFromLibrary(project, library)
|
||||
}
|
||||
else {
|
||||
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)
|
||||
|
||||
private static void updateJar(
|
||||
@NotNull Project project,
|
||||
@Nullable VirtualFile fileToReplace,
|
||||
@NotNull LibraryJarDescriptor libraryJarDescriptor
|
||||
) {
|
||||
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
|
||||
if (kJsConfigurator!!.changeOldSourcesPathIfNeeded(project, library)) {
|
||||
kJsConfigurator.copySourcesToPathFromLibrary(project, library)
|
||||
}
|
||||
else {
|
||||
updateJar(project, JSLibraryStdPresentationProvider.getJsStdLibSrcJar(library), LibraryJarDescriptor.JS_STDLIB_SRC_JAR)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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())) {
|
||||
Collection<VersionedLibrary> versionedOutdatedLibraries = findOutdatedKotlinLibraries(myProject);
|
||||
Collection<Library> outdatedLibraries = extractLibraries(versionedOutdatedLibraries);
|
||||
KotlinRuntimeLibraryUtil.updateLibraries(myProject, outdatedLibraries);
|
||||
KotlinRuntimeLibraryUtilKt.updateLibraries(myProject, outdatedLibraries);
|
||||
suggestDeleteKotlinJsIfNeeded(outdatedLibraries);
|
||||
}
|
||||
else if ("ignore".equals(event.getDescription())) {
|
||||
@@ -232,7 +232,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
||||
private static Collection<VersionedLibrary> findOutdatedKotlinLibraries(@NotNull Project project) {
|
||||
List<VersionedLibrary> outdatedLibraries = Lists.newArrayList();
|
||||
|
||||
for (Library library : KotlinRuntimeLibraryUtil.findKotlinLibraries(project)) {
|
||||
for (Library library : KotlinRuntimeLibraryUtilKt.findKotlinLibraries(project)) {
|
||||
LibraryVersionProperties libraryVersionProperties =
|
||||
LibraryPresentationProviderUtil.getLibraryProperties(JavaRuntimePresentationProvider.getInstance(), library);
|
||||
if (libraryVersionProperties == null) {
|
||||
@@ -244,7 +244,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
||||
}
|
||||
String libraryVersion = libraryVersionProperties.getVersionString();
|
||||
|
||||
String runtimeVersion = KotlinRuntimeLibraryUtil.bundledRuntimeVersion();
|
||||
String runtimeVersion = KotlinRuntimeLibraryUtilKt.bundledRuntimeVersion();
|
||||
|
||||
boolean isOutdated = isRuntimeOutdated(libraryVersion, runtimeVersion);
|
||||
|
||||
|
||||
+6
-6
@@ -103,13 +103,13 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
||||
private EditorNotificationPanel doCreate(final Collection<VirtualFile> badRoots) {
|
||||
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>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable Library library) {
|
||||
assert library != null : "library should be non null";
|
||||
VirtualFile runtimeJar = KotlinRuntimeLibraryUtil.getLocalJar(JavaRuntimePresentationProvider.getRuntimeJar(library));
|
||||
VirtualFile jsLibJar = KotlinRuntimeLibraryUtil.getLocalJar(JSLibraryStdPresentationProvider.getJsStdLibJar(library));
|
||||
VirtualFile runtimeJar = KotlinRuntimeLibraryUtilKt.getLocalJar(JavaRuntimePresentationProvider.getRuntimeJar(library));
|
||||
VirtualFile jsLibJar = KotlinRuntimeLibraryUtilKt.getLocalJar(JSLibraryStdPresentationProvider.getJsStdLibJar(library));
|
||||
return badRoots.contains(runtimeJar) || badRoots.contains(jsLibJar);
|
||||
}
|
||||
});
|
||||
@@ -130,7 +130,7 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
||||
answer.createActionLabel(actionLabelText, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
KotlinRuntimeLibraryUtil.updateLibraries(project, badRuntimeLibraries);
|
||||
KotlinRuntimeLibraryUtilKt.updateLibraries(project, badRuntimeLibraries);
|
||||
}
|
||||
});
|
||||
if (otherBadRootsCount > 0) {
|
||||
@@ -278,8 +278,8 @@ public class UnsupportedAbiVersionNotificationPanelProvider extends EditorNotifi
|
||||
|
||||
@NotNull
|
||||
private static Collection<VirtualFile> collectBadRoots(@NotNull Project project) {
|
||||
Collection<VirtualFile> badJVMRoots = KotlinRuntimeLibraryUtil.getLibraryRootsWithAbiIncompatibleKotlinClasses(project);
|
||||
Collection<VirtualFile> badJSRoots = KotlinRuntimeLibraryUtil.getLibraryRootsWithAbiIncompatibleForKotlinJs(project);
|
||||
Collection<VirtualFile> badJVMRoots = KotlinRuntimeLibraryUtilKt.getLibraryRootsWithAbiIncompatibleKotlinClasses(project);
|
||||
Collection<VirtualFile> badJSRoots = KotlinRuntimeLibraryUtilKt.getLibraryRootsWithAbiIncompatibleForKotlinJs(project);
|
||||
|
||||
if (badJVMRoots.isEmpty() && badJSRoots.isEmpty()) return Collections.emptyList();
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.jetbrains.kotlin.idea
|
||||
|
||||
import junit.framework.TestCase
|
||||
import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.versions.OutdatedKotlinRuntimeNotification
|
||||
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
|
||||
import org.junit.Assert
|
||||
|
||||
|
||||
@@ -87,15 +87,15 @@ class KotlinRuntimeLibraryUtilTest : TestCase() {
|
||||
|
||||
private fun outdated(plugin: String, library: String) {
|
||||
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) {
|
||||
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) {
|
||||
Assert.assertEquals(expected, KotlinRuntimeLibraryUtil.bundledRuntimeVersion(version))
|
||||
Assert.assertEquals(expected, bundledRuntimeVersion(version))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user