Common library-related logic is extracted from UI classes to a util class
This commit is contained in:
@@ -17,6 +17,9 @@
|
|||||||
package org.jetbrains.jet.plugin;
|
package org.jetbrains.jet.plugin;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
||||||
|
import com.intellij.ide.plugins.PluginManager;
|
||||||
|
import com.intellij.openapi.extensions.PluginId;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
@@ -72,4 +75,11 @@ public class JetPluginUtil {
|
|||||||
}
|
}
|
||||||
return libraryScope == ((NamespaceDescriptor) declaration).getMemberScope();
|
return libraryScope == ((NamespaceDescriptor) declaration).getMemberScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static String getPluginVersion() {
|
||||||
|
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.jetbrains.kotlin"));
|
||||||
|
assert plugin != null : "How can it be? Kotlin plugin is available, but its component is running. Complete nonsense.";
|
||||||
|
return plugin.getVersion();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class AbsentJdkAnnotationsNotifications extends EditorNotifications.Provi
|
|||||||
|
|
||||||
GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
|
GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
|
||||||
if (JavaPsiFacade.getInstance(project).findClass("jet.JetObject", scope) == null) return null;
|
if (JavaPsiFacade.getInstance(project).findClass("jet.JetObject", scope) == null) return null;
|
||||||
if (ConfigureKotlinLibraryNotificationProvider.jdkAnnotationsArePresent(module)) return null;
|
if (KotlinRuntimeLibraryUtil.jdkAnnotationsArePresent(module)) return null;
|
||||||
|
|
||||||
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||||
if (sdk == null) return null;
|
if (sdk == null) return null;
|
||||||
@@ -62,7 +62,7 @@ public class AbsentJdkAnnotationsNotifications extends EditorNotifications.Provi
|
|||||||
panel.createActionLabel("Set up Kotlin JDK annotations", new Runnable() {
|
panel.createActionLabel("Set up Kotlin JDK annotations", new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
ConfigureKotlinLibraryNotificationProvider.addJdkAnnotations(module);
|
KotlinRuntimeLibraryUtil.addJdkAnnotations(module);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+37
-141
@@ -28,46 +28,24 @@ import com.intellij.openapi.module.ModuleUtilCore;
|
|||||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||||
import com.intellij.openapi.project.IndexNotReadyException;
|
import com.intellij.openapi.project.IndexNotReadyException;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.projectRoots.Sdk;
|
|
||||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
|
||||||
import com.intellij.openapi.roots.AnnotationOrderRootType;
|
|
||||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
|
||||||
import com.intellij.openapi.roots.ModuleRootManager;
|
|
||||||
import com.intellij.openapi.roots.OrderRootType;
|
|
||||||
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
|
|
||||||
import com.intellij.openapi.roots.libraries.Library;
|
import com.intellij.openapi.roots.libraries.Library;
|
||||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
|
||||||
import com.intellij.openapi.ui.DialogWrapper;
|
import com.intellij.openapi.ui.DialogWrapper;
|
||||||
import com.intellij.openapi.ui.Messages;
|
import com.intellij.openapi.ui.Messages;
|
||||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||||
import com.intellij.openapi.util.Condition;
|
|
||||||
import com.intellij.openapi.util.Key;
|
import com.intellij.openapi.util.Key;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
|
||||||
import com.intellij.openapi.vfs.JarFileSystem;
|
|
||||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
|
||||||
import com.intellij.openapi.vfs.VfsUtil;
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
import com.intellij.psi.JavaPsiFacade;
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
|
||||||
import com.intellij.ui.EditorNotificationPanel;
|
import com.intellij.ui.EditorNotificationPanel;
|
||||||
import com.intellij.ui.EditorNotifications;
|
import com.intellij.ui.EditorNotifications;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
import org.jetbrains.jet.utils.PathUtil;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.jetbrains.jet.plugin.project.JsModuleDetector.isJsModule;
|
|
||||||
|
|
||||||
public class ConfigureKotlinLibraryNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> {
|
public class ConfigureKotlinLibraryNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> {
|
||||||
private static final Key<EditorNotificationPanel> KEY = Key.create("configure.kotlin.library");
|
private static final Key<EditorNotificationPanel> KEY = Key.create("configure.kotlin.library");
|
||||||
public static final String LIBRARY_NAME = "KotlinRuntime";
|
|
||||||
public static final String KOTLIN_RUNTIME_JAR = "kotlin-runtime.jar";
|
|
||||||
private final Project myProject;
|
private final Project myProject;
|
||||||
|
|
||||||
public ConfigureKotlinLibraryNotificationProvider(Project project) {
|
public ConfigureKotlinLibraryNotificationProvider(Project project) {
|
||||||
@@ -90,7 +68,7 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
final Module module = ModuleUtilCore.findModuleForFile(file, myProject);
|
final Module module = ModuleUtilCore.findModuleForFile(file, myProject);
|
||||||
if (module == null) return null;
|
if (module == null) return null;
|
||||||
|
|
||||||
if (!isModuleAlreadyConfigured(module)) {
|
if (!KotlinRuntimeLibraryUtil.isModuleAlreadyConfigured(module)) {
|
||||||
return createNotificationPanel(module);
|
return createNotificationPanel(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,57 +82,6 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Library findOrCreateRuntimeLibrary() {
|
|
||||||
LibraryTable table = ProjectLibraryTable.getInstance(myProject);
|
|
||||||
Library kotlinRuntime = table.getLibraryByName(LIBRARY_NAME);
|
|
||||||
if (kotlinRuntime != null) {
|
|
||||||
for (VirtualFile root : kotlinRuntime.getFiles(OrderRootType.CLASSES)) {
|
|
||||||
if (root.getName().equals(KOTLIN_RUNTIME_JAR)) {
|
|
||||||
return kotlinRuntime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
File runtimePath = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath();
|
|
||||||
if (!runtimePath.exists()) {
|
|
||||||
Messages.showErrorDialog(myProject, "kotlin-runtime.jar is not found. Make sure plugin is properly installed.",
|
|
||||||
"No Runtime Found");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ChoosePathDialog dlg = new ChoosePathDialog(myProject);
|
|
||||||
dlg.show();
|
|
||||||
if (!dlg.isOK()) return null;
|
|
||||||
String path = dlg.getPath();
|
|
||||||
final File targetJar = new File(path, "kotlin-runtime.jar");
|
|
||||||
try {
|
|
||||||
FileUtil.copy(runtimePath, targetJar);
|
|
||||||
VirtualFile jarVfs = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(targetJar);
|
|
||||||
if (jarVfs != null) {
|
|
||||||
jarVfs.refresh(false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
Messages.showErrorDialog(myProject, "Error copying jar: " + e.getLocalizedMessage(), "Error Copying File");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (kotlinRuntime == null) {
|
|
||||||
kotlinRuntime = table.createLibrary("KotlinRuntime");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Library finalKotlinRuntime = kotlinRuntime;
|
|
||||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
Library.ModifiableModel model = finalKotlinRuntime.getModifiableModel();
|
|
||||||
model.addRoot(VfsUtil.getUrlForLibraryRoot(targetJar), OrderRootType.CLASSES);
|
|
||||||
model.addRoot(VfsUtil.getUrlForLibraryRoot(targetJar) + "src", OrderRootType.SOURCES);
|
|
||||||
model.commit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return kotlinRuntime;
|
|
||||||
}
|
|
||||||
|
|
||||||
private EditorNotificationPanel createNotificationPanel(final Module module) {
|
private EditorNotificationPanel createNotificationPanel(final Module module) {
|
||||||
final EditorNotificationPanel answer = new EditorNotificationPanel();
|
final EditorNotificationPanel answer = new EditorNotificationPanel();
|
||||||
@@ -163,7 +90,7 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
answer.createActionLabel("Set up module '" + module.getName() + "' as JVM Kotlin module", new Runnable() {
|
answer.createActionLabel("Set up module '" + module.getName() + "' as JVM Kotlin module", new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
setUpKotlinRuntime(module);
|
setUpJavaModule(module);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -177,6 +104,18 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setUpJavaModule(Module module) {
|
||||||
|
Library library = KotlinRuntimeLibraryUtil.findOrCreateRuntimeLibrary(myProject, new UiFindRuntimeLibraryHandler());
|
||||||
|
if (library == null) return;
|
||||||
|
|
||||||
|
KotlinRuntimeLibraryUtil.setUpKotlinRuntimeLibrary(module, library, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
updateNotifications();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpJSModule(@NotNull Module module) {
|
private void setUpJSModule(@NotNull Module module) {
|
||||||
JsModuleSetUp.doSetUpModule(module, new Runnable() {
|
JsModuleSetUp.doSetUpModule(module, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -186,56 +125,6 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUpKotlinRuntime(@NotNull final Module module) {
|
|
||||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Library library = findOrCreateRuntimeLibrary();
|
|
||||||
if (library != null) {
|
|
||||||
ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
|
|
||||||
if (model.findLibraryOrderEntry(library) == null) {
|
|
||||||
model.addLibraryEntry(library);
|
|
||||||
model.commit();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
model.dispose();
|
|
||||||
}
|
|
||||||
updateNotifications();
|
|
||||||
}
|
|
||||||
if (!jdkAnnotationsArePresent(module)) {
|
|
||||||
addJdkAnnotations(module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package */ static void addJdkAnnotations(Module module) {
|
|
||||||
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
|
||||||
assert sdk != null;
|
|
||||||
File annotationsIoFile = PathUtil.getKotlinPathsForIdeaPlugin().getJdkAnnotationsPath();
|
|
||||||
if (annotationsIoFile.exists()) {
|
|
||||||
VirtualFile jdkAnnotationsJar = LocalFileSystem.getInstance().findFileByIoFile(annotationsIoFile);
|
|
||||||
if (jdkAnnotationsJar != null) {
|
|
||||||
SdkModificator modificator = sdk.getSdkModificator();
|
|
||||||
modificator.addRoot(JarFileSystem.getInstance().getJarRootForLocalFile(jdkAnnotationsJar),
|
|
||||||
AnnotationOrderRootType.getInstance());
|
|
||||||
modificator.commitChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* package */ static boolean jdkAnnotationsArePresent(Module module) {
|
|
||||||
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
|
||||||
if (sdk == null) return false;
|
|
||||||
return ContainerUtil.exists(sdk.getRootProvider().getFiles(AnnotationOrderRootType.getInstance()),
|
|
||||||
new Condition<VirtualFile>() {
|
|
||||||
@Override
|
|
||||||
public boolean value(VirtualFile file) {
|
|
||||||
return PathUtil.JDK_ANNOTATIONS_JAR.equals(file.getName());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateNotifications() {
|
private void updateNotifications() {
|
||||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -245,22 +134,6 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isModuleAlreadyConfigured(Module module) {
|
|
||||||
return isMavenModule(module) || isJsModule(module) || isWithJavaModule(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isWithJavaModule(Module module) {
|
|
||||||
// Can find a reference to kotlin class in module scope
|
|
||||||
GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
|
|
||||||
return (JavaPsiFacade.getInstance(myProject).findClass(JvmStdlibNames.JET_OBJECT.getFqName().getFqName(), scope) != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isMavenModule(@NotNull Module module) {
|
|
||||||
// This constant could be acquired from MavenProjectsManager, but we don't want to depend on the Maven plugin...
|
|
||||||
// See MavenProjectsManager.isMavenizedModule()
|
|
||||||
return "true".equals(module.getOptionValue("org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ChoosePathDialog extends DialogWrapper {
|
private static class ChoosePathDialog extends DialogWrapper {
|
||||||
private final Project myProject;
|
private final Project myProject;
|
||||||
private TextFieldWithBrowseButton myPathField;
|
private TextFieldWithBrowseButton myPathField;
|
||||||
@@ -293,4 +166,27 @@ public class ConfigureKotlinLibraryNotificationProvider extends EditorNotificati
|
|||||||
return myPathField.getText();
|
return myPathField.getText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class UiFindRuntimeLibraryHandler extends KotlinRuntimeLibraryUtil.FindRuntimeLibraryHandler {
|
||||||
|
@Override
|
||||||
|
public void runtimePathDoesNotExist(@NotNull File path) {
|
||||||
|
Messages.showErrorDialog(myProject,
|
||||||
|
"kotlin-runtime.jar is not found at " + path + ". Make sure plugin is properly installed.",
|
||||||
|
"No Runtime Found");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getRuntimeJarPath() {
|
||||||
|
ChoosePathDialog dlg = new ChoosePathDialog(myProject);
|
||||||
|
dlg.show();
|
||||||
|
if (!dlg.isOK()) return null;
|
||||||
|
String path = dlg.getPath();
|
||||||
|
return new File(path, "kotlin-runtime.jar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void ioExceptionOnCopyingJar(@NotNull IOException e) {
|
||||||
|
Messages.showErrorDialog(myProject, "Error copying jar: " + e.getLocalizedMessage(), "Error Copying File");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2013 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.jet.plugin.quickfix;
|
||||||
|
|
||||||
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
|
import com.intellij.openapi.module.Module;
|
||||||
|
import com.intellij.openapi.project.Project;
|
||||||
|
import com.intellij.openapi.projectRoots.Sdk;
|
||||||
|
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||||
|
import com.intellij.openapi.roots.AnnotationOrderRootType;
|
||||||
|
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||||
|
import com.intellij.openapi.roots.ModuleRootManager;
|
||||||
|
import com.intellij.openapi.roots.OrderRootType;
|
||||||
|
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
|
||||||
|
import com.intellij.openapi.roots.libraries.Library;
|
||||||
|
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||||
|
import com.intellij.openapi.util.Condition;
|
||||||
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
|
import com.intellij.openapi.vfs.JarFileSystem;
|
||||||
|
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||||
|
import com.intellij.openapi.vfs.VfsUtil;
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile;
|
||||||
|
import com.intellij.packaging.impl.elements.ManifestFileUtil;
|
||||||
|
import com.intellij.psi.JavaPsiFacade;
|
||||||
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||||
|
import org.jetbrains.jet.utils.PathUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.jar.Attributes;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.plugin.project.JsModuleDetector.isJsModule;
|
||||||
|
|
||||||
|
public class KotlinRuntimeLibraryUtil {
|
||||||
|
public static final String LIBRARY_NAME = "KotlinRuntime";
|
||||||
|
public static final String KOTLIN_RUNTIME_JAR = "kotlin-runtime.jar";
|
||||||
|
public static final String UNKNOWN_VERSION = "UNKNOWN";
|
||||||
|
|
||||||
|
private KotlinRuntimeLibraryUtil() {}
|
||||||
|
|
||||||
|
public static void addJdkAnnotations(@NotNull Module module) {
|
||||||
|
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||||
|
assert sdk != null;
|
||||||
|
File annotationsIoFile = PathUtil.getKotlinPathsForIdeaPlugin().getJdkAnnotationsPath();
|
||||||
|
if (annotationsIoFile.exists()) {
|
||||||
|
VirtualFile jdkAnnotationsJar = LocalFileSystem.getInstance().findFileByIoFile(annotationsIoFile);
|
||||||
|
if (jdkAnnotationsJar != null) {
|
||||||
|
SdkModificator modificator = sdk.getSdkModificator();
|
||||||
|
modificator.addRoot(JarFileSystem.getInstance().getJarRootForLocalFile(jdkAnnotationsJar),
|
||||||
|
AnnotationOrderRootType.getInstance());
|
||||||
|
modificator.commitChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean jdkAnnotationsArePresent(@NotNull Module module) {
|
||||||
|
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
|
||||||
|
if (sdk == null) return false;
|
||||||
|
return ContainerUtil.exists(sdk.getRootProvider().getFiles(AnnotationOrderRootType.getInstance()),
|
||||||
|
new Condition<VirtualFile>() {
|
||||||
|
@Override
|
||||||
|
public boolean value(VirtualFile file) {
|
||||||
|
return PathUtil.JDK_ANNOTATIONS_JAR.equals(file.getName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isModuleAlreadyConfigured(Module module) {
|
||||||
|
return isMavenModule(module) || isJsModule(module) || isWithJavaModule(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isMavenModule(@NotNull Module module) {
|
||||||
|
// This constant could be acquired from MavenProjectsManager, but we don't want to depend on the Maven plugin...
|
||||||
|
// See MavenProjectsManager.isMavenizedModule()
|
||||||
|
return "true".equals(module.getOptionValue("org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isWithJavaModule(Module module) {
|
||||||
|
// Can find a reference to kotlin class in module scope
|
||||||
|
GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
|
||||||
|
return (JavaPsiFacade.getInstance(module.getProject()).findClass(JvmStdlibNames.JET_OBJECT.getFqName().getFqName(), scope) != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setUpKotlinRuntimeLibrary(
|
||||||
|
@NotNull final Module module,
|
||||||
|
@NotNull final Library library,
|
||||||
|
@NotNull final Runnable afterSetUp
|
||||||
|
) {
|
||||||
|
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
|
||||||
|
if (model.findLibraryOrderEntry(library) == null) {
|
||||||
|
model.addLibraryEntry(library);
|
||||||
|
model.commit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
model.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
afterSetUp.run();
|
||||||
|
|
||||||
|
if (!jdkAnnotationsArePresent(module)) {
|
||||||
|
addJdkAnnotations(module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
static Library findOrCreateRuntimeLibrary(@NotNull Project project, @NotNull FindRuntimeLibraryHandler handler) {
|
||||||
|
LibraryTable table = ProjectLibraryTable.getInstance(project);
|
||||||
|
Library kotlinRuntime = table.getLibraryByName(LIBRARY_NAME);
|
||||||
|
if (kotlinRuntime != null) {
|
||||||
|
for (VirtualFile root : kotlinRuntime.getFiles(OrderRootType.CLASSES)) {
|
||||||
|
if (root.getName().equals(KOTLIN_RUNTIME_JAR)) {
|
||||||
|
return kotlinRuntime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File runtimePath = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath();
|
||||||
|
if (!runtimePath.exists()) {
|
||||||
|
handler.runtimePathDoesNotExist(runtimePath);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final File targetJar = handler.getRuntimeJarPath();
|
||||||
|
if (targetJar == null) return null;
|
||||||
|
try {
|
||||||
|
FileUtil.copy(runtimePath, targetJar);
|
||||||
|
VirtualFile jarVfs = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(targetJar);
|
||||||
|
if (jarVfs != null) {
|
||||||
|
jarVfs.refresh(false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
handler.ioExceptionOnCopyingJar(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kotlinRuntime == null) {
|
||||||
|
kotlinRuntime = table.createLibrary("KotlinRuntime");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Library finalKotlinRuntime = kotlinRuntime;
|
||||||
|
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Library.ModifiableModel model = finalKotlinRuntime.getModifiableModel();
|
||||||
|
model.addRoot(VfsUtil.getUrlForLibraryRoot(targetJar), OrderRootType.CLASSES);
|
||||||
|
model.addRoot(VfsUtil.getUrlForLibraryRoot(targetJar) + "src", OrderRootType.SOURCES);
|
||||||
|
model.commit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return kotlinRuntime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateRuntime(
|
||||||
|
@NotNull final Project project,
|
||||||
|
@NotNull final Runnable jarNotFoundHandler
|
||||||
|
) {
|
||||||
|
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
File runtimePath = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath();
|
||||||
|
if (!runtimePath.exists()) {
|
||||||
|
jarNotFoundHandler.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VirtualFile runtimeJar = getKotlinRuntimeJar(project);
|
||||||
|
assert runtimeJar != null;
|
||||||
|
VirtualFile jarFile = JarFileSystem.getInstance().getVirtualFileForJar(runtimeJar);
|
||||||
|
if (jarFile != null) {
|
||||||
|
runtimeJar = jarFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileUtil.copy(runtimePath, new File(runtimeJar.getPath()));
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
throw new AssertionError(e);
|
||||||
|
}
|
||||||
|
runtimeJar.refresh(true, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static String getRuntimeVersion(@NotNull Project project) {
|
||||||
|
VirtualFile kotlinRuntimeJar = getKotlinRuntimeJar(project);
|
||||||
|
if (kotlinRuntimeJar == null) return null;
|
||||||
|
VirtualFile manifestFile = kotlinRuntimeJar.findFileByRelativePath(JarFile.MANIFEST_NAME);
|
||||||
|
if (manifestFile != null) {
|
||||||
|
Attributes attributes = ManifestFileUtil.readManifest(manifestFile).getMainAttributes();
|
||||||
|
if (attributes.containsKey(Attributes.Name.IMPLEMENTATION_VERSION)) {
|
||||||
|
return attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UNKNOWN_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static VirtualFile getKotlinRuntimeJar(@NotNull Project project) {
|
||||||
|
LibraryTable table = ProjectLibraryTable.getInstance(project);
|
||||||
|
Library kotlinRuntime = table.getLibraryByName(LIBRARY_NAME);
|
||||||
|
if (kotlinRuntime != null) {
|
||||||
|
for (VirtualFile root : kotlinRuntime.getFiles(OrderRootType.CLASSES)) {
|
||||||
|
if (root.getName().equals(KOTLIN_RUNTIME_JAR)) {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class FindRuntimeLibraryHandler {
|
||||||
|
@Nullable
|
||||||
|
public abstract File getRuntimeJarPath();
|
||||||
|
|
||||||
|
public void runtimePathDoesNotExist(@NotNull File path) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ioExceptionOnCopyingJar(@NotNull IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,6 @@ package org.jetbrains.jet.plugin.versions;/*
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import com.intellij.ide.plugins.IdeaPluginDescriptor;
|
|
||||||
import com.intellij.ide.plugins.PluginManager;
|
|
||||||
import com.intellij.ide.util.PropertiesComponent;
|
import com.intellij.ide.util.PropertiesComponent;
|
||||||
import com.intellij.notification.Notification;
|
import com.intellij.notification.Notification;
|
||||||
import com.intellij.notification.NotificationListener;
|
import com.intellij.notification.NotificationListener;
|
||||||
@@ -23,31 +21,16 @@ import com.intellij.notification.NotificationType;
|
|||||||
import com.intellij.notification.Notifications;
|
import com.intellij.notification.Notifications;
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager;
|
||||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||||
import com.intellij.openapi.extensions.PluginId;
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.openapi.roots.OrderRootType;
|
|
||||||
import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
|
|
||||||
import com.intellij.openapi.roots.libraries.Library;
|
|
||||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
|
||||||
import com.intellij.openapi.ui.Messages;
|
import com.intellij.openapi.ui.Messages;
|
||||||
import com.intellij.openapi.util.io.FileUtil;
|
|
||||||
import com.intellij.openapi.vfs.JarFileSystem;
|
|
||||||
import com.intellij.openapi.vfs.VirtualFile;
|
|
||||||
import com.intellij.packaging.impl.elements.ManifestFileUtil;
|
|
||||||
import com.intellij.util.text.VersionComparatorUtil;
|
import com.intellij.util.text.VersionComparatorUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.jet.plugin.JetPluginUtil;
|
||||||
import org.jetbrains.jet.plugin.quickfix.ConfigureKotlinLibraryNotificationProvider;
|
import org.jetbrains.jet.plugin.quickfix.KotlinRuntimeLibraryUtil;
|
||||||
import org.jetbrains.jet.utils.PathUtil;
|
|
||||||
|
|
||||||
import javax.swing.event.HyperlinkEvent;
|
import javax.swing.event.HyperlinkEvent;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.jar.Attributes;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
|
|
||||||
public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent {
|
public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent {
|
||||||
private static final String UNKNOWN_VERSION = "UNKNOWN";
|
|
||||||
private static final String SUPPRESSED_PROPERTY_NAME = "oudtdated.runtime.suppressed.plugin.version";
|
private static final String SUPPRESSED_PROPERTY_NAME = "oudtdated.runtime.suppressed.plugin.version";
|
||||||
|
|
||||||
public OutdatedKotlinRuntimeNotification(final Project project) {
|
public OutdatedKotlinRuntimeNotification(final Project project) {
|
||||||
@@ -57,8 +40,8 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
@Override
|
@Override
|
||||||
public void projectOpened() {
|
public void projectOpened() {
|
||||||
if (ApplicationManager.getApplication().isInternal()) return;
|
if (ApplicationManager.getApplication().isInternal()) return;
|
||||||
String runtimeVersion = getRuntimeVersion();
|
String runtimeVersion = KotlinRuntimeLibraryUtil.getRuntimeVersion(myProject);
|
||||||
final String pluginVersion = getPluginVersion();
|
final String pluginVersion = JetPluginUtil.getPluginVersion();
|
||||||
if (runtimeVersion == null) return; // runtime is not present in project
|
if (runtimeVersion == null) return; // runtime is not present in project
|
||||||
if ("@snapshot@".equals(pluginVersion)) return; // plugin is run from sources, can't compare versions
|
if ("@snapshot@".equals(pluginVersion)) return; // plugin is run from sources, can't compare versions
|
||||||
|
|
||||||
@@ -66,7 +49,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
if (pluginVersion.equals(PropertiesComponent.getInstance(myProject).getValue(SUPPRESSED_PROPERTY_NAME))) return;
|
if (pluginVersion.equals(PropertiesComponent.getInstance(myProject).getValue(SUPPRESSED_PROPERTY_NAME))) return;
|
||||||
|
|
||||||
boolean isRuntimeOutdated = "snapshot".equals(runtimeVersion)
|
boolean isRuntimeOutdated = "snapshot".equals(runtimeVersion)
|
||||||
|| UNKNOWN_VERSION.equals(runtimeVersion)
|
|| KotlinRuntimeLibraryUtil.UNKNOWN_VERSION.equals(runtimeVersion)
|
||||||
|| runtimeVersion.startsWith("internal-") != pluginVersion.startsWith("internal-")
|
|| runtimeVersion.startsWith("internal-") != pluginVersion.startsWith("internal-")
|
||||||
|| VersionComparatorUtil.compare(pluginVersion, runtimeVersion) > 0;
|
|| VersionComparatorUtil.compare(pluginVersion, runtimeVersion) > 0;
|
||||||
|
|
||||||
@@ -75,7 +58,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
String message = String.format("<p>Your version of Kotlin runtime library is %s, while plugin version is %s." +
|
String message = String.format("<p>Your version of Kotlin runtime library is %s, while plugin version is %s." +
|
||||||
" Runtime library should be updated to avoid compatibility problems.</p>" +
|
" Runtime library should be updated to avoid compatibility problems.</p>" +
|
||||||
"<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>",
|
"<p><a href=\"update\">Update Runtime</a> <a href=\"ignore\">Ignore</a></p>",
|
||||||
UNKNOWN_VERSION.equals(runtimeVersion) ? "older than 0.1.2296" : runtimeVersion, pluginVersion);
|
KotlinRuntimeLibraryUtil.UNKNOWN_VERSION.equals(runtimeVersion) ? "older than 0.1.2296" : runtimeVersion, pluginVersion);
|
||||||
Notifications.Bus.notify(new Notification("Outdated Kotlin Runtime", "Outdated Kotlin Runtime",
|
Notifications.Bus.notify(new Notification("Outdated Kotlin Runtime", "Outdated Kotlin Runtime",
|
||||||
message,
|
message,
|
||||||
NotificationType.WARNING, new NotificationListener() {
|
NotificationType.WARNING, new NotificationListener() {
|
||||||
@@ -83,7 +66,14 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||||
if ("update".equals(event.getDescription())) {
|
if ("update".equals(event.getDescription())) {
|
||||||
updateRuntime();
|
KotlinRuntimeLibraryUtil.updateRuntime(myProject, new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Messages.showErrorDialog(myProject,
|
||||||
|
"kotlin-runtime.jar is not found. Make sure plugin is properly installed.",
|
||||||
|
"No Runtime Found");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if ("ignore".equals(event.getDescription())) {
|
else if ("ignore".equals(event.getDescription())) {
|
||||||
PropertiesComponent.getInstance(myProject).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion);
|
PropertiesComponent.getInstance(myProject).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion);
|
||||||
@@ -95,68 +85,5 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}), myProject);
|
}), myProject);
|
||||||
}
|
|
||||||
|
|
||||||
private void updateRuntime() {
|
|
||||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
File runtimePath = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath();
|
|
||||||
if (!runtimePath.exists()) {
|
|
||||||
Messages.showErrorDialog(myProject, "kotlin-runtime.jar is not found. Make sure plugin is properly installed.",
|
|
||||||
"No Runtime Found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
VirtualFile runtimeJar = getKotlinRuntimeJar();
|
|
||||||
assert runtimeJar != null;
|
|
||||||
VirtualFile jarFile = JarFileSystem.getInstance().getVirtualFileForJar(runtimeJar);
|
|
||||||
if (jarFile != null) {
|
|
||||||
runtimeJar = jarFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
FileUtil.copy(runtimePath, new File(runtimeJar.getPath()));
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
|
||||||
runtimeJar.refresh(true, true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private String getRuntimeVersion() {
|
|
||||||
VirtualFile kotlinRuntimeJar = getKotlinRuntimeJar();
|
|
||||||
if (kotlinRuntimeJar == null) return null;
|
|
||||||
VirtualFile manifestFile = kotlinRuntimeJar.findFileByRelativePath(JarFile.MANIFEST_NAME);
|
|
||||||
if (manifestFile != null) {
|
|
||||||
Attributes attributes = ManifestFileUtil.readManifest(manifestFile).getMainAttributes();
|
|
||||||
if (attributes.containsKey(Attributes.Name.IMPLEMENTATION_VERSION)) {
|
|
||||||
return attributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return UNKNOWN_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private VirtualFile getKotlinRuntimeJar() {
|
|
||||||
LibraryTable table = ProjectLibraryTable.getInstance(myProject);
|
|
||||||
Library kotlinRuntime = table.getLibraryByName(ConfigureKotlinLibraryNotificationProvider.LIBRARY_NAME);
|
|
||||||
if (kotlinRuntime != null) {
|
|
||||||
for (VirtualFile root : kotlinRuntime.getFiles(OrderRootType.CLASSES)) {
|
|
||||||
if (root.getName().equals(ConfigureKotlinLibraryNotificationProvider.KOTLIN_RUNTIME_JAR)) {
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private static String getPluginVersion() {
|
|
||||||
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId("org.jetbrains.kotlin"));
|
|
||||||
assert plugin != null : "How can it be? Kotlin plugin is available, but its component is running. Complete nonsense.";
|
|
||||||
return plugin.getVersion();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user