From 2fc16045c9822cee78a39330bd42f8adc56f0c26 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Thu, 26 Jan 2012 20:27:45 +0400 Subject: [PATCH] Quick fix to add kotlin runtime to modules classpath. --- .idea/dictionaries/max.xml | 1 + idea/src/META-INF/plugin.xml | 2 + .../jet/plugin/compiler/CompilerUtil.java | 32 +++ ...gureKotlinLibraryNotificationProvider.java | 198 ++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 idea/src/org/jetbrains/jet/plugin/compiler/CompilerUtil.java create mode 100644 idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java diff --git a/.idea/dictionaries/max.xml b/.idea/dictionaries/max.xml index d8e764b26e2..064d7e3b1c4 100644 --- a/.idea/dictionaries/max.xml +++ b/.idea/dictionaries/max.xml @@ -3,6 +3,7 @@ classfiles codegen + kotlin \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index d4db336e0f4..8dc6a3e3536 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -79,6 +79,8 @@ + + { + private static final Key KEY = Key.create("configure.kotlin.library"); + private final Project myProject; + + @Override + public Key getKey() { + return KEY; + } + + public ConfigureKotlinLibraryNotificationProvider(Project project, final EditorNotifications notifications) { + myProject = project; + project.getMessageBus().connect(project).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootListener() { + @Override + public void beforeRootsChange(ModuleRootEvent event) { + } + + @Override + public void rootsChanged(ModuleRootEvent event) { + notifications.updateAllNotifications(); + } + }); + } + + + @Override + public EditorNotificationPanel createNotificationPanel(VirtualFile file) { + try { + if (file.getFileType() != JetFileType.INSTANCE) return null; + + if (CompilerManager.getInstance(myProject).isExcludedFromCompilation(file)) return null; + + final Module module = ModuleUtil.findModuleForFile(file, myProject); + if (module == null) return null; + + if (isMavenModule(module)) return null; + + GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false); + if (JavaPsiFacade.getInstance(myProject).findClass("jet.JetObject", scope) == null) { + return createNotificationPanel(module); + } + + } catch (ProcessCanceledException e) { + // Ignore + } catch (IndexNotReadyException e) { + // Ignore + } + + + return null; + } + + private Library findOrCreateRuntimeLibrary(final Module module) { + LibraryTable table = ProjectLibraryTable.getInstance(myProject); + final Library kotlinRuntime = table.getLibraryByName("KotlinRuntime"); + if (kotlinRuntime != null) return null; + + File runtimePath = CompilerUtil.getDefaultRuntimePath(); + if (runtimePath == null) { + 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; + } + + final Library answer = table.createLibrary("KotlinRuntime"); + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + public void run() { + Library.ModifiableModel model = answer.getModifiableModel(); + model.addRoot(VfsUtil.getUrlForLibraryRoot(targetJar), OrderRootType.CLASSES); + model.commit(); + } + }); + + return answer; + } + + private EditorNotificationPanel createNotificationPanel(final Module module) { + final EditorNotificationPanel answer = new EditorNotificationPanel(); + + answer.setText("Kotlin runtime library is not configured for module '" + module.getName() + "'"); + answer.createActionLabel("Setup Kotlin Runtime", new Runnable() { + @Override + public void run() { + + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + Library library = findOrCreateRuntimeLibrary(module); + if (library != null) { + ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel(); + model.addLibraryEntry(library); + model.commit(); + } + } + }); + } + }); + + return answer; + } + + private static boolean isMavenModule(@NotNull Module module) { + for (VirtualFile root : ModuleRootManager.getInstance(module).getContentRoots()) { + if (root.findChild("pom.xml") != null) return true; + } + + return false; + } + + private static class ChoosePathDialog extends DialogWrapper { + private final Project myProject; + private TextFieldWithBrowseButton myPathField; + + protected ChoosePathDialog(Project project) { + super(project); + myProject = project; + + setTitle("Local Kotlin Runtime Path"); + init(); + } + + @Override + protected JComponent createCenterPanel() { + FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); + FileTextField field = FileChooserFactory.getInstance().createFileTextField(descriptor, myDisposable); + field.getField().setColumns(25); + myPathField = new TextFieldWithBrowseButton(field.getField()); + myPathField.addBrowseFolderListener("Choose Destination Folder", "Choose folder for file", myProject, descriptor); + + VirtualFile baseDir = myProject.getBaseDir(); + if (baseDir != null) { + myPathField.setText(baseDir.getPath() + File.separatorChar + "lib"); + } + + return myPathField; + } + + public String getPath() { + return myPathField.getText(); + } + } +}