refactor PathUtil - it is a big difference now, whether we find sdk home from plugin or from compiler

This commit is contained in:
Maxim Manuylov
2012-07-22 17:57:39 +04:00
committed by Evgeny Gerashchenko
parent e5589e1037
commit 843fb8d7a9
13 changed files with 239 additions and 125 deletions
+3 -3
View File
@@ -24,15 +24,15 @@
<component>
<implementation-class>org.jetbrains.jet.plugin.highlighter.DeclarationHintSupport</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.jet.plugin.OutdatedKotlinRuntimeNotification</implementation-class>
</component>
</project-components>
<module-components>
<component>
<implementation-class>org.jetbrains.jet.plugin.project.K2JSModuleComponent</implementation-class>
</component>
<component>
<implementation-class>org.jetbrains.jet.plugin.OutdatedKotlinRuntimeNotification</implementation-class>
</component>
</module-components>
<actions>
@@ -14,19 +14,16 @@ package org.jetbrains.jet.plugin;/*
* 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.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.AbstractProjectComponent;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleComponent;
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.ui.Messages;
@@ -38,6 +35,7 @@ import com.intellij.util.text.VersionComparatorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.quickfix.ConfigureKotlinLibraryNotificationProvider;
import org.jetbrains.jet.plugin.util.PluginPathUtil;
import org.jetbrains.jet.utils.PathUtil;
import javax.swing.event.HyperlinkEvent;
@@ -50,36 +48,40 @@ import java.util.jar.JarFile;
* @author Evgeny Gerashchenko
* @since 5/22/12
*/
public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent {
public class OutdatedKotlinRuntimeNotification implements ModuleComponent {
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_PATTERN = "oudtdated.runtime.suppressed.plugin.version[%s]";
public OutdatedKotlinRuntimeNotification(final Project project) {
super(project);
private final Module myModule;
private final String mySuppressedPropertyName;
public OutdatedKotlinRuntimeNotification(final Module module) {
myModule = module;
mySuppressedPropertyName = String.format(SUPPRESSED_PROPERTY_NAME_PATTERN, module.getName());
}
@Override
public void projectOpened() {
if (ApplicationManager.getApplication().isInternal()) return;
String runtimeVersion = getRuntimeVersion();
final String pluginVersion = getPluginVersion();
String runtimeVersion = getRuntimeVersion(getKotlinRuntimeJar());
if (runtimeVersion == null) return; // runtime is not present in project
if ("@snapshot@".equals(pluginVersion)) return; // plugin is run from sources, can't compare versions
final String sdkVersion = getRuntimeVersion(getRuntimeFromSdk());
if (sdkVersion == null || "snapshot".equals(sdkVersion)) return; // plugin is run from sources, can't compare versions
// user already clicked suppress
if (pluginVersion.equals(PropertiesComponent.getInstance(myProject).getValue(SUPPRESSED_PROPERTY_NAME))) return;
if (sdkVersion.equals(PropertiesComponent.getInstance(myModule.getProject()).getValue(mySuppressedPropertyName))) return;
boolean isRuntimeOutdated = "snapshot".equals(runtimeVersion)
|| UNKNOWN_VERSION.equals(runtimeVersion)
|| runtimeVersion.startsWith("internal-") != pluginVersion.startsWith("internal-")
|| VersionComparatorUtil.compare(pluginVersion, runtimeVersion) > 0;
|| runtimeVersion.startsWith("internal-") != sdkVersion.startsWith("internal-")
|| VersionComparatorUtil.compare(sdkVersion, runtimeVersion) > 0;
if (!isRuntimeOutdated) return;
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 in module \"%s\" is %s, while Kotlin SDK version in this module is %s." +
" Runtime library should be updated to avoid compatibility problems.</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);
myModule.getName(), UNKNOWN_VERSION.equals(runtimeVersion) ? "older than 0.1.2296" : runtimeVersion, sdkVersion);
Notifications.Bus.notify(new Notification("Outdated Kotlin Runtime", "Outdated Kotlin Runtime",
message,
NotificationType.WARNING, new NotificationListener() {
@@ -90,7 +92,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
updateRuntime();
}
else if ("ignore".equals(event.getDescription())) {
PropertiesComponent.getInstance(myProject).setValue(SUPPRESSED_PROPERTY_NAME, pluginVersion);
PropertiesComponent.getInstance(myModule.getProject()).setValue(mySuppressedPropertyName, sdkVersion);
}
else {
throw new AssertionError();
@@ -98,16 +100,17 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
notification.expire();
}
}
}), myProject);
}
}), myModule.getProject());
}
private void updateRuntime() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
File runtimePath = PathUtil.getDefaultRuntimePath();
File runtimePath = PluginPathUtil.getRuntimePath(myModule);
if (runtimePath == null) {
Messages.showErrorDialog(myProject, "kotlin-runtime.jar is not found. Make sure plugin is properly installed.",
Messages.showErrorDialog(myModule.getProject(),
"kotlin-runtime.jar is not found. Make sure plugin is properly installed.",
"No Runtime Found");
return;
}
@@ -130,8 +133,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
}
@Nullable
private String getRuntimeVersion() {
VirtualFile kotlinRuntimeJar = getKotlinRuntimeJar();
private static String getRuntimeVersion(@Nullable final VirtualFile kotlinRuntimeJar) {
if (kotlinRuntimeJar == null) return null;
VirtualFile manifestFile = kotlinRuntimeJar.findFileByRelativePath(JarFile.MANIFEST_NAME);
if (manifestFile != null) {
@@ -145,7 +147,7 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
@Nullable
private VirtualFile getKotlinRuntimeJar() {
LibraryTable table = ProjectLibraryTable.getInstance(myProject);
LibraryTable table = ModuleRootManager.getInstance(myModule).getModifiableModel().getModuleLibraryTable();
Library kotlinRuntime = table.getLibraryByName(ConfigureKotlinLibraryNotificationProvider.LIBRARY_NAME);
if (kotlinRuntime != null) {
for (VirtualFile root : kotlinRuntime.getFiles(OrderRootType.CLASSES)) {
@@ -157,10 +159,27 @@ public class OutdatedKotlinRuntimeNotification extends AbstractProjectComponent
return null;
}
@Nullable
private VirtualFile getRuntimeFromSdk() {
final File runtimePath = PluginPathUtil.getRuntimePath(myModule);
return runtimePath == null ? null : PathUtil.jarFileOrDirectoryToVirtualFile(runtimePath);
}
@Override
public void moduleAdded() {}
@Override
public void projectClosed() {}
@Override
public void initComponent() {}
@Override
public void disposeComponent() {}
@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();
@Override
public String getComponentName() {
return getClass().getName();
}
}
@@ -19,12 +19,11 @@ package org.jetbrains.jet.plugin.compiler;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.VirtualFile;
import jet.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.jet.plugin.sdk.KotlinSdkUtil;
import java.io.*;
import java.io.File;
import static com.intellij.openapi.compiler.CompilerMessageCategory.ERROR;
@@ -37,7 +36,7 @@ public final class CompilerEnvironment {
public static CompilerEnvironment getEnvironmentFor(@NotNull CompileContext compileContext, @NotNull Module module, boolean tests) {
VirtualFile mainOutput = compileContext.getModuleOutputDirectory(module);
final VirtualFile outputDir = tests ? compileContext.getModuleOutputDirectoryForTests(module) : mainOutput;
File kotlinHome = PathUtil.getDefaultCompilerPath();
File kotlinHome = KotlinSdkUtil.getSDKHomeFor(module);
return new CompilerEnvironment(kotlinHome, outputDir);
}
@@ -55,7 +55,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.JetPluginUtil;
import org.jetbrains.jet.plugin.sdk.KotlinSdkUtil;
import org.jetbrains.jet.utils.PathUtil;
import org.jetbrains.jet.plugin.util.PluginPathUtil;
import javax.swing.*;
import java.io.File;
@@ -105,7 +105,7 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific
return null;
}
private Library findOrCreateRuntimeLibrary() {
private Library findOrCreateRuntimeLibrary(@NotNull Module module) {
LibraryTable table = ProjectLibraryTable.getInstance(myProject);
Library kotlinRuntime = table.getLibraryByName(LIBRARY_NAME);
if (kotlinRuntime != null) {
@@ -116,7 +116,7 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific
}
}
File runtimePath = PathUtil.getDefaultRuntimePath();
File runtimePath = PluginPathUtil.getRuntimePath(module);
if (runtimePath == null) {
Messages.showErrorDialog(myProject, "kotlin-runtime.jar is not found. Make sure plugin is properly installed.",
"No Runtime Found");
@@ -192,7 +192,7 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Library library = findOrCreateRuntimeLibrary();
Library library = findOrCreateRuntimeLibrary(module);
if (library != null) {
ModifiableRootModel model = ModuleRootManager.getInstance(module).getModifiableModel();
if (model.findLibraryOrderEntry(library) == null) {
@@ -214,7 +214,7 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific
/* package */ static void addJdkAnnotations(Module module) {
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
assert sdk != null;
File annotationsIoFile = PathUtil.getJdkAnnotationsPath();
File annotationsIoFile = PluginPathUtil.getJdkAnnotationsPath(module);
if (annotationsIoFile != null) {
VirtualFile jdkAnnotationsJar = LocalFileSystem.getInstance().findFileByIoFile(annotationsIoFile);
if (jdkAnnotationsJar != null) {
@@ -36,6 +36,7 @@ import com.intellij.psi.impl.PsiModificationTrackerImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.project.K2JSModuleComponent;
import org.jetbrains.jet.plugin.util.PluginPathUtil;
import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
@@ -65,7 +66,7 @@ public final class JsModuleSetUp {
return;
}
if (!copyJsLibFiles(rootDir)) return;
if (!copyJsLibFiles(module, rootDir)) return;
setUpK2JSModuleComponent(module);
setUpLibraryAsSourceLibrary(module, rootDir);
@@ -108,9 +109,9 @@ public final class JsModuleSetUp {
DaemonCodeAnalyzer.getInstance(module.getProject()).restart();
}
private static boolean copyJsLibFiles(@NotNull File rootDir) {
File jsLibJarPath = PathUtil.getDefaultJsLibJarPath();
File jsLibJsPath = PathUtil.getDefaultJsLibJsPath();
private static boolean copyJsLibFiles(@NotNull Module module, @NotNull File rootDir) {
File jsLibJarPath = PluginPathUtil.getJsLibJarPath(module);
File jsLibJsPath = PluginPathUtil.getJsLibJsPath(module);
if ((jsLibJarPath == null) || (jsLibJsPath == null)) {
notifyFailure("JavaScript library not found. Make sure plugin is installed properly.");
return false;
@@ -24,6 +24,7 @@ import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
import java.io.IOException;
@@ -46,7 +47,6 @@ public class KotlinSdkUtil {
return new KotlinSdkProperties("");
}
};
@NotNull private static final String KOTLIN_COMPILER_JAR = "kotlin-compiler.jar";
@NotNull private static final String[] KOTLIN_COMPILER_JAR_ENTRY_NAMES = {
"org/jetbrains/jet/cli/KotlinCompiler.class",
"org/jetbrains/jet/cli/jvm/K2JVMCompiler.class"
@@ -59,7 +59,7 @@ public class KotlinSdkUtil {
}
private static boolean isSDKHome(@NotNull final File dir) {
return dir.isDirectory() && isKotlinCompilerJar(getKotlinCompilerJar(dir));
return dir.isDirectory() && isKotlinCompilerJar(PathUtil.getCompilerPath(dir));
}
@Nullable
@@ -77,7 +77,8 @@ public class KotlinSdkUtil {
}
catch (final IOException e) {
try {
return getJarImplementationVersion(getKotlinCompilerJar(new File(sdkHomePath)));
final File compilerJar = PathUtil.getCompilerPath(new File(sdkHomePath));
return compilerJar == null ? null : getJarImplementationVersion(compilerJar);
}
catch (final IOException e1) {
return null;
@@ -97,15 +98,10 @@ public class KotlinSdkUtil {
}
}
@NotNull
private static File getKotlinCompilerJar(@NotNull final File sdkHome) {
return new File(new File(sdkHome, "lib"), KOTLIN_COMPILER_JAR);
}
@Nullable
public static String detectSDKVersion(@NotNull final List<VirtualFile> jars) {
for (final VirtualFile jar : jars) {
if (jar.getName().equals(KOTLIN_COMPILER_JAR) && isKotlinCompilerJar(new File(jar.getPath()))) {
if (jar.getName().equals(PathUtil.KOTLIN_COMPILER_JAR) && isKotlinCompilerJar(new File(jar.getPath()))) {
final VirtualFile libDir = jar.getParent();
if (libDir != null) {
final VirtualFile sdkHomeDir = libDir.getParent();
@@ -119,22 +115,29 @@ public class KotlinSdkUtil {
}
public static boolean isSDKConfiguredFor(@NotNull final Module module) {
final GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
return containsKotlinCompilerJar(FilenameIndex.getVirtualFilesByName(module.getProject(), KOTLIN_COMPILER_JAR, scope));
return getSDKHomeFor(module) != null;
}
private static boolean containsKotlinCompilerJar(@NotNull final Collection<VirtualFile> jars) {
@Nullable
public static File getSDKHomeFor(@NotNull final Module module) {
final GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
return findKotlinCompilerJar(FilenameIndex.getVirtualFilesByName(module.getProject(), PathUtil.KOTLIN_COMPILER_JAR, scope));
}
@Nullable
private static File findKotlinCompilerJar(@NotNull final Collection<VirtualFile> jars) {
for (final VirtualFile jar : jars) {
if (isKotlinCompilerJar(new File(jar.getPath()))) {
return true;
final File file = new File(jar.getPath());
if (isKotlinCompilerJar(file)) {
return file;
}
}
return false;
return null;
}
private static boolean isKotlinCompilerJar(@NotNull final File jar) {
private static boolean isKotlinCompilerJar(@Nullable final File jar) {
try {
return doIsKotlinCompilerJar(jar);
return jar != null && doIsKotlinCompilerJar(jar);
}
catch (final IOException e) {
return false;
@@ -0,0 +1,53 @@
/*
* 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.util;
import com.intellij.openapi.module.Module;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.sdk.KotlinSdkUtil;
import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
/**
* @author Maxim.Manuylov
* Date: 20.05.12
*/
public class PluginPathUtil {
private PluginPathUtil() {}
@Nullable
public static File getRuntimePath(@NotNull final Module module) {
return PathUtil.getRuntimePath(KotlinSdkUtil.getSDKHomeFor(module));
}
@Nullable
public static File getJsLibJsPath(@NotNull final Module module) {
return PathUtil.getJsLibJsPath(KotlinSdkUtil.getSDKHomeFor(module));
}
@Nullable
public static File getJsLibJarPath(@NotNull final Module module) {
return PathUtil.getJsLibJarPath(KotlinSdkUtil.getSDKHomeFor(module));
}
@Nullable
public static File getJdkAnnotationsPath(@NotNull final Module module) {
return PathUtil.getJdkAnnotationsPath(KotlinSdkUtil.getSDKHomeFor(module));
}
}