diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index af399ab020c..6c04e69c239 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -76,6 +76,8 @@
+
+
diff --git a/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkSupportConfigurable.java b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkSupportConfigurable.java
new file mode 100644
index 00000000000..fb0838c4038
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkSupportConfigurable.java
@@ -0,0 +1,56 @@
+/*
+ * 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.sdk;
+
+import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ModifiableModelsProvider;
+import com.intellij.openapi.roots.ModifiableRootModel;
+import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+/**
+ * @author Maxim.Manuylov
+ * Date: 19.05.12
+ */
+public class KotlinFrameworkSupportConfigurable extends FrameworkSupportInModuleConfigurable {
+ @Nullable
+ @Override
+ public JComponent createComponent() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public CustomLibraryDescription createLibraryDescription() {
+ return new KotlinSdkDescription();
+ }
+
+ @Override
+ public boolean isOnlyLibraryAdded() {
+ return true;
+ }
+
+ @Override
+ public void addSupport(@NotNull final Module module,
+ @NotNull final ModifiableRootModel rootModel,
+ @NotNull final ModifiableModelsProvider modifiableModelsProvider) {
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkSupportProvider.java b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkSupportProvider.java
new file mode 100644
index 00000000000..7a328448a38
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkSupportProvider.java
@@ -0,0 +1,51 @@
+/*
+ * 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.sdk;
+
+import com.intellij.framework.FrameworkTypeEx;
+import com.intellij.framework.addSupport.FrameworkSupportInModuleConfigurable;
+import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
+import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
+import com.intellij.openapi.module.JavaModuleType;
+import com.intellij.openapi.module.ModuleType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Maxim.Manuylov
+ * Date: 19.05.12
+ */
+public class KotlinFrameworkSupportProvider extends FrameworkSupportInModuleProvider {
+ @NotNull private static final String PLUGIN_MODULE_ID = "PLUGIN_MODULE";
+ @NotNull private static final String ANDROID_MODULE_ID = "ANDROID_MODULE";
+
+ @NotNull
+ @Override
+ public FrameworkTypeEx getFrameworkType() {
+ return FrameworkTypeEx.EP_NAME.findExtension(KotlinFrameworkType.class);
+ }
+
+ @NotNull
+ @Override
+ public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull final FrameworkSupportModel model) {
+ return new KotlinFrameworkSupportConfigurable();
+ }
+
+ @Override
+ public boolean isEnabledForModuleType(@NotNull final ModuleType type) {
+ return type instanceof JavaModuleType || PLUGIN_MODULE_ID.equals(type.getId()) || ANDROID_MODULE_ID.equals(type.getId());
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkType.java b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkType.java
new file mode 100644
index 00000000000..379524f9c76
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinFrameworkType.java
@@ -0,0 +1,52 @@
+/*
+ * 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.sdk;
+
+import com.intellij.framework.FrameworkTypeEx;
+import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jet.plugin.JetIcons;
+
+import javax.swing.*;
+
+/**
+ * @author Maxim.Manuylov
+ * Date: 19.05.12
+ */
+public class KotlinFrameworkType extends FrameworkTypeEx {
+ public KotlinFrameworkType() {
+ super("Kotlin");
+ }
+
+ @NotNull
+ @Override
+ public FrameworkSupportInModuleProvider createProvider() {
+ return new KotlinFrameworkSupportProvider();
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Kotlin";
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ return JetIcons.SMALL_LOGO;
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkDescription.java b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkDescription.java
new file mode 100644
index 00000000000..91e078e817a
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkDescription.java
@@ -0,0 +1,129 @@
+/*
+ * 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.sdk;
+
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.roots.libraries.LibraryKind;
+import com.intellij.openapi.roots.libraries.NewLibraryConfiguration;
+import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription;
+import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditor;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Maxim.Manuylov
+ * Date: 19.05.12
+ */
+public class KotlinSdkDescription extends CustomLibraryDescription {
+ @NotNull
+ @Override
+ public Set extends LibraryKind> getSuitableLibraryKinds() {
+ return Collections.singleton(KotlinSdkUtil.getKotlinSdkLibraryKind());
+ }
+
+ @Nullable
+ @Override
+ public NewLibraryConfiguration createNewLibrary(@NotNull final JComponent parentComponent, @Nullable final VirtualFile contextDirectory) {
+ VirtualFile initial = findFile(System.getenv("KOTLIN_HOME"));
+ if (initial == null) {
+ initial = findFile(System.getProperty("kotlinHome"));
+ }
+
+ final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, true, false, false, false, false) {
+ @Override
+ public boolean isFileSelectable(@Nullable final VirtualFile file) {
+ return super.isFileSelectable(file) && KotlinSdkUtil.isSDKHome(file);
+ }
+ };
+ descriptor.setTitle("Kotlin SDK");
+ descriptor.setDescription("Choose a directory containing Kotlin distribution");
+
+ final VirtualFile sdkHome = FileChooser.chooseFile(parentComponent, descriptor, initial);
+ if (sdkHome == null) return null;
+
+ final String sdkHomePath = sdkHome.getPath();
+ final String sdkVersion = KotlinSdkUtil.getSDKVersion(sdkHomePath);
+ if (sdkVersion == null) {
+ Messages.showErrorDialog(parentComponent,
+ "Failed to find Kotlin SDK in the specified path: cannot determine Kotlin version.",
+ "Failed to Find Kotlin SDK");
+ return null;
+ }
+
+ return new NewLibraryConfiguration(KotlinSdkUtil.getSDKName(sdkVersion)) {
+ @Override
+ public void addRoots(@NotNull final LibraryEditor editor) {
+ addSDKRoots(editor, sdkHomePath);
+ }
+ };
+ }
+
+ @Nullable
+ private static VirtualFile findFile(@Nullable final String path) {
+ if (StringUtil.isEmptyOrSpaces(path)) return null;
+ //noinspection ConstantConditions
+ return LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(path));
+ }
+
+ private static void addSDKRoots(@NotNull final LibraryEditor editor, @NotNull final String sdkHomePath) {
+ final File libDir = new File(sdkHomePath, "lib");
+ if (!libDir.isDirectory()) return;
+
+ final List jars = new ArrayList();
+ collectJars(libDir, jars);
+
+ for (final File jar : jars) {
+ editor.addRoot(VfsUtil.getUrlForLibraryRoot(jar), OrderRootType.CLASSES);
+ }
+ }
+
+ private static void collectJars(@NotNull final File dir, @NotNull final List jars) {
+ final File[] children = dir.listFiles();
+ if (children == null) return;
+
+ for (final File child : children) {
+ if (child.isDirectory()) {
+ collectJars(child, jars);
+ }
+ else if (child.isFile() && child.getName().endsWith(".jar")) {
+ jars.add(child);
+ }
+ }
+ }
+
+ @NotNull
+ @Override
+ public LibrariesContainer.LibraryLevel getDefaultLevel() {
+ return LibrariesContainer.LibraryLevel.GLOBAL;
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkProperties.java b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkProperties.java
new file mode 100644
index 00000000000..fcb3633904d
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkProperties.java
@@ -0,0 +1,58 @@
+/*
+ * 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.sdk;
+
+import com.intellij.openapi.roots.libraries.LibraryProperties;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Maxim.Manuylov
+ * Date: 19.05.12
+ */
+public class KotlinSdkProperties extends LibraryProperties {
+ @NotNull private String myVersion;
+
+ public KotlinSdkProperties(@NotNull final String version) {
+ myVersion = version;
+ }
+
+ @NotNull
+ public String getVersion() {
+ return myVersion;
+ }
+
+ @Override
+ public KotlinSdkProperties getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(@NotNull final KotlinSdkProperties state) {
+ myVersion = state.myVersion;
+ }
+
+ @Override
+ public boolean equals(@Nullable final Object that) {
+ return this == that || (that instanceof KotlinSdkProperties && myVersion.equals(((KotlinSdkProperties)that).myVersion));
+ }
+
+ @Override
+ public int hashCode() {
+ return myVersion.hashCode();
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkUtil.java b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkUtil.java
new file mode 100644
index 00000000000..897b016a0fc
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/sdk/KotlinSdkUtil.java
@@ -0,0 +1,89 @@
+/*
+ * 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.sdk;
+
+import com.intellij.openapi.roots.libraries.PersistentLibraryKind;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Maxim.Manuylov
+ * Date: 19.05.12
+ */
+public class KotlinSdkUtil {
+ @NotNull private static final PersistentLibraryKind KOTLIN_SDK_KIND =
+ new PersistentLibraryKind("KotlinSDK", false) {
+ @NotNull
+ @Override
+ public KotlinSdkProperties createDefaultProperties() {
+ return new KotlinSdkProperties("");
+ }
+ };
+ @NotNull private static final String KOTLIN_COMPILER_JAR = "kotlin-compiler.jar";
+
+ private KotlinSdkUtil() {}
+
+ public static boolean isSDKHome(@Nullable final VirtualFile dir) {
+ return dir != null && isSDKHome(new File(dir.getPath()));
+ }
+
+ private static boolean isSDKHome(@NotNull final File dir) {
+ return dir.isDirectory() && new File(new File(dir, "lib"), KOTLIN_COMPILER_JAR).isFile();
+ }
+
+ @Nullable
+ public static String getSDKVersion(@NotNull final String sdkHomePath) {
+ try {
+ return FileUtil.loadFile(new File(sdkHomePath, "build.txt")).trim();
+ }
+ catch (final IOException e) {
+ return null;
+ }
+ }
+
+ @Nullable
+ public static String detectSDKVersion(@NotNull final List jars) {
+ for (final VirtualFile jar : jars) {
+ if (jar.getName().equals(KOTLIN_COMPILER_JAR)) {
+ final VirtualFile libDir = jar.getParent();
+ if (libDir != null) {
+ final VirtualFile sdkHomeDir = libDir.getParent();
+ if (sdkHomeDir != null) {
+ return getSDKVersion(sdkHomeDir.getPath());
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ public static String getSDKName(@NotNull final String version) {
+ return "Kotlin " + version;
+ }
+
+ @NotNull
+ public static PersistentLibraryKind getKotlinSdkLibraryKind() {
+ return KOTLIN_SDK_KIND;
+ }
+}