diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 3fdd12e8d0d..76cd6b1c581 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -666,6 +666,8 @@
+
+
org.jetbrains.kotlin.idea.intentions.IfNullToElvisIntention
Kotlin
diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/KotlinCreateFromTemplateHandler.kt b/idea/src/org/jetbrains/kotlin/idea/actions/KotlinCreateFromTemplateHandler.kt
new file mode 100644
index 00000000000..e2acfe83381
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/actions/KotlinCreateFromTemplateHandler.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.idea.actions
+
+import com.intellij.ide.fileTemplates.DefaultCreateFromTemplateHandler
+import com.intellij.ide.fileTemplates.FileTemplate
+import org.jetbrains.kotlin.idea.KotlinFileType
+import org.jetbrains.kotlin.idea.core.quoteIfNeeded
+
+class KotlinCreateFromTemplateHandler : DefaultCreateFromTemplateHandler() {
+ override fun handlesTemplate(template: FileTemplate) = template.isTemplateOfType(KotlinFileType.INSTANCE)
+
+ override fun prepareProperties(props: MutableMap) {
+ val packageName = props[FileTemplate.ATTRIBUTE_PACKAGE_NAME] as? String
+ if (packageName != null) {
+ props[FileTemplate.ATTRIBUTE_PACKAGE_NAME] = packageName
+ .split('.')
+ .map { it.quoteIfNeeded() }
+ .joinToString(".")
+ }
+
+ val name = props[FileTemplate.ATTRIBUTE_NAME] as? String
+ if (name != null) {
+ props[FileTemplate.ATTRIBUTE_NAME] = name.quoteIfNeeded()
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/kotlin/idea/actions/NewKotlinFileAction.kt b/idea/src/org/jetbrains/kotlin/idea/actions/NewKotlinFileAction.kt
index a7f2a5816e5..039a30fd9bd 100644
--- a/idea/src/org/jetbrains/kotlin/idea/actions/NewKotlinFileAction.kt
+++ b/idea/src/org/jetbrains/kotlin/idea/actions/NewKotlinFileAction.kt
@@ -18,18 +18,25 @@ package org.jetbrains.kotlin.idea.actions
import com.intellij.ide.actions.CreateFileFromTemplateAction
import com.intellij.ide.actions.CreateFileFromTemplateDialog
+import com.intellij.ide.fileTemplates.FileTemplate
+import com.intellij.ide.fileTemplates.FileTemplateManager
+import com.intellij.ide.fileTemplates.actions.AttributesDefaults
+import com.intellij.ide.fileTemplates.ui.CreateFromTemplateDialog
import com.intellij.openapi.actionSystem.DataContext
import com.intellij.openapi.actionSystem.LangDataKeys
import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.DumbAware
+import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFile
+import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.idea.configuration.showConfigureKotlinNotificationIfNeeded
+import java.util.*
class NewKotlinFileAction
: CreateFileFromTemplateAction("Kotlin File/Class",
@@ -74,4 +81,59 @@ class NewKotlinFileAction
override fun equals(obj: Any?): Boolean {
return obj is NewKotlinFileAction
}
+
+ override fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
+ val directorySeparators = if (template.name == "Kotlin File") arrayOf('/', '\\') else arrayOf('/', '\\', '.')
+ val (className, targetDir) = findOrCreateTarget(dir, name, directorySeparators)
+
+ val service = DumbService.getInstance(dir.project)
+ service.isAlternativeResolveEnabled = true
+ try {
+ return createFromTemplate(targetDir, className, template)
+ }
+ finally {
+ service.isAlternativeResolveEnabled = false
+ }
+ }
+
+ private fun findOrCreateTarget(dir: PsiDirectory, name: String, directorySeparators: Array): Pair {
+ var className = name.removeSuffix(".kt")
+ var targetDir = dir
+
+ for (splitChar in directorySeparators) {
+ if (splitChar in className) {
+ val names = className.trim().split(splitChar)
+
+ for (dirName in names.dropLast(1)) {
+ targetDir = targetDir.findSubdirectory(dirName) ?: targetDir.createSubdirectory(dirName)
+ }
+
+ className = names.last()
+ break
+ }
+ }
+ return Pair(className, targetDir)
+ }
+
+ private fun createFromTemplate(dir: PsiDirectory, className: String, template: FileTemplate): PsiFile? {
+ val project = dir.project
+ val defaultProperties = FileTemplateManager.getInstance(project).defaultProperties
+
+ val properties = Properties(defaultProperties)
+
+ val element = try {
+ CreateFromTemplateDialog(project, dir, template,
+ AttributesDefaults(className).withFixedName(true),
+ properties).create()
+ }
+ catch (e: IncorrectOperationException) {
+ throw e
+ }
+ catch (e: Exception) {
+ LOG.error(e)
+ return null
+ }
+
+ return element.containingFile
+ }
}