diff --git a/idea/kotlin-android-plugin/kotlin-android-plugin.iml b/idea/kotlin-android-plugin/kotlin-android-plugin.iml index 894dae4c845..212437c1f39 100644 --- a/idea/kotlin-android-plugin/kotlin-android-plugin.iml +++ b/idea/kotlin-android-plugin/kotlin-android-plugin.iml @@ -12,5 +12,6 @@ + \ No newline at end of file diff --git a/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/actions/NewKotlinActivityAction.kt b/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/actions/NewKotlinActivityAction.kt new file mode 100644 index 00000000000..4676344b9fe --- /dev/null +++ b/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/actions/NewKotlinActivityAction.kt @@ -0,0 +1,157 @@ +/* + * Copyright 2010-2016 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.kotlin.android.actions + +import com.intellij.history.core.RevisionsCollector +import com.intellij.history.core.revisions.Revision +import com.intellij.history.integration.LocalHistoryImpl +import com.intellij.openapi.actionSystem.* +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.module.Module +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.psi.PsiJavaFile +import org.jetbrains.android.facet.AndroidFacet +import org.jetbrains.kotlin.idea.KotlinIcons +import org.jetbrains.kotlin.idea.actions.JavaToKotlinAction +import org.jetbrains.kotlin.idea.refactoring.toPsiFile +import java.io.File +import kotlin.reflect.functions +import kotlin.reflect.memberFunctions + +private val NEW_KOTLIN_ACTIVITY_START_LABEL = "Start New Kotlin Activity Action" +private val NEW_KOTLIN_ACTIVITY_END_LABEL = "Finish New Kotlin Activity Action" + +class NewKotlinActivityAction: AnAction(KotlinIcons.FILE) { + + companion object { + private val LOG = Logger.getInstance(NewKotlinActivityAction::class.java) + } + + override fun actionPerformed(e: AnActionEvent) { + val project = e.project ?: return + + LocalHistoryImpl.getInstanceImpl().putSystemLabel(project, NEW_KOTLIN_ACTIVITY_START_LABEL) + val isSuccess = showWizard(e.dataContext) + LocalHistoryImpl.getInstanceImpl().putSystemLabel(project, NEW_KOTLIN_ACTIVITY_END_LABEL) + + if (!isSuccess) return + + val localHistory = LocalHistoryImpl.getInstanceImpl() + val gateway = localHistory.gateway!! + val localHistoryFacade = localHistory.facade + + val revisionsCollector = RevisionsCollector( + localHistoryFacade, gateway.createTransientRootEntry(), + project.baseDir.path, project.locationHash, null) + + val revisions = revisionsCollector.result + var endRevision: Revision? = null + for (rev in revisions) { + val label = rev.label ?: continue + if (label == NEW_KOTLIN_ACTIVITY_END_LABEL) { + endRevision = rev + } + + if (label == NEW_KOTLIN_ACTIVITY_START_LABEL && endRevision != null) { + val javaFiles = arrayListOf() + val differences = endRevision.getDifferencesWith(rev) + for (difference in differences) { + if (difference.right == null && difference.isFile) { + val file = File(difference.left.path) + if (file.extension == "java") { + val psiFile = file.toPsiFile(project) as? PsiJavaFile + if (psiFile != null) { + javaFiles.add(psiFile) + } + } + } + } + if (javaFiles.isNotEmpty()) { + JavaToKotlinAction.convertFiles(javaFiles, project, false) + } + break + } + } + } + + private fun showWizard(dataContext: DataContext): Boolean { + try { + val wizardClass = try { + // AS 1.5 + Class.forName("com.android.tools.idea.wizard.NewAndroidActivityWizard") + } + catch(e: ClassNotFoundException) { + // AS 2.0 + Class.forName("com.android.tools.idea.npw.NewAndroidActivityWizard") + } + + val constructor = wizardClass.getConstructor(Module::class.java, VirtualFile::class.java, File::class.java) + val wizard = constructor.newInstance( + LangDataKeys.MODULE.getData(dataContext), + CommonDataKeys.VIRTUAL_FILE.getData(dataContext), + null) + + wizardClass.kotlin.functions.firstOrNull { it.name == "init" }?.call(wizard) + return (wizardClass.kotlin.functions.firstOrNull { it.name == "showAndGet" }?.call(wizard) as? Boolean) ?: false + } + catch(e: Throwable) { + LOG.error(e) + return false + } + } + + override fun update(e: AnActionEvent) { + val view = LangDataKeys.IDE_VIEW.getData(e.dataContext) + val module = LangDataKeys.MODULE.getData(e.dataContext) + val facet = if (module != null) AndroidFacet.getInstance(module) else null + val presentation = e.presentation + val isProjectReady = facet != null && isProjectReady(facet) + presentation.text = "Kotlin Activity" + if (isProjectReady) "" else " (Project not ready)" + presentation.isVisible = view != null && facet != null && isVisible(facet) + } + + private fun isVisible(facet: AndroidFacet): Boolean { + try { + val shouldSetVisible = AndroidFacet::class.memberFunctions.singleOrNull { + it.name == "isGradleProject" || it.name == "requiresAndroidModel" + } + + return shouldSetVisible?.call(facet) != null + } + catch(e: Throwable) { + LOG.error(e) + return false + } + } + + private fun isProjectReady(facet: AndroidFacet): Boolean { + try { + val getAndroidProjectInfoFun = AndroidFacet::class.memberFunctions.singleOrNull { + it.name == "getIdeaAndroidProject" || it.name == "getAndroidModel" + } + + return getAndroidProjectInfoFun?.call(facet) != null + } + catch(e: Throwable) { + LOG.error(e) + return false + } + } + + override fun hashCode() = 0 + override fun equals(other: Any?) = other is NewKotlinActivityAction +} \ No newline at end of file diff --git a/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/facet/KotlinAndroidStartupManager.kt b/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/facet/KotlinAndroidStartupManager.kt new file mode 100644 index 00000000000..63b52cee05f --- /dev/null +++ b/idea/kotlin-android-plugin/src/org/jetbrains/kotlin/android/facet/KotlinAndroidStartupManager.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2016 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.kotlin.android.facet + +import com.intellij.openapi.project.Project + +class KotlinAndroidStartupManager(private val project: Project) { + init { + + } +} \ No newline at end of file diff --git a/idea/src/META-INF/android.xml b/idea/src/META-INF/android.xml index 98485f2cf97..98b7dd0f913 100644 --- a/idea/src/META-INF/android.xml +++ b/idea/src/META-INF/android.xml @@ -24,4 +24,17 @@ + + + + org.jetbrains.kotlin.android.facet.KotlinAndroidStartupManager + org.jetbrains.kotlin.android.facet.KotlinAndroidStartupManager + + + + + + + +