diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 606443aceae..af399ab020c 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -197,6 +197,7 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/AbsentJdkAnnotationsNotifications.java b/idea/src/org/jetbrains/jet/plugin/quickfix/AbsentJdkAnnotationsNotifications.java new file mode 100644 index 00000000000..56e80d4df8f --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/AbsentJdkAnnotationsNotifications.java @@ -0,0 +1,79 @@ +/* + * Copyright 2010-2012 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.compiler.CompilerManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.util.Key; +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.EditorNotifications; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.JetFileType; + +/** + * @author Evgeny Gerashchenko + * @since 7/22/12 + */ +public class AbsentJdkAnnotationsNotifications implements EditorNotifications.Provider { + private static final Key KEY = Key.create("add.kotlin.jdk.annotations"); + + private final Project project; + + public AbsentJdkAnnotationsNotifications(Project project) { + this.project = project; + } + + @Override + @Nullable + public EditorNotificationPanel createNotificationPanel(VirtualFile file) { + if (file.getFileType() != JetFileType.INSTANCE) return null; + if (CompilerManager.getInstance(project).isExcludedFromCompilation(file)) return null; + + final Module module = ModuleUtil.findModuleForFile(file, project); + if (module == null) return null; + + GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false); + if (JavaPsiFacade.getInstance(project).findClass("jet.JetObject", scope) == null) return null; + if (ConfigureKotlinLibraryNotificationProvider.jdkAnnotationsArePresent(module)) return null; + + Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk == null) return null; + + EditorNotificationPanel panel = new EditorNotificationPanel(); + panel.setText("Kotlin external annotations for JDK are not set for '" + sdk.getName() + "'."); + panel.createActionLabel("Set up Kotlin JDK annotations", new Runnable() { + @Override + public void run() { + ConfigureKotlinLibraryNotificationProvider.addJdkAnnotations(module); + } + }); + + return panel; + } + + @Override + public Key getKey() { + return KEY; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java index a74e005148a..b5b1ab1fe9c 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java @@ -30,6 +30,9 @@ import com.intellij.openapi.module.ModuleUtil; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.project.IndexNotReadyException; 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; @@ -39,8 +42,10 @@ import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; +import com.intellij.openapi.util.Condition; 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; @@ -48,6 +53,7 @@ import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.EditorNotificationPanel; import com.intellij.ui.EditorNotifications; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.utils.PathUtil; @@ -202,10 +208,40 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific } updateNotifications(); } + if (!jdkAnnotationsArePresent(module)) { + addJdkAnnotations(module); + } } }); } + /* package */ static void addJdkAnnotations(Module module) { + Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + assert sdk != null; + File annotationsIoFile = PathUtil.getJdkAnnotationsPath(); + if (annotationsIoFile != null) { + 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() { + @Override + public boolean value(VirtualFile file) { + return PathUtil.JDK_ANNOTATIONS_JAR.equals(file.getName()); + } + }); + } + private void updateNotifications() { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override