change implementation of 'new file' action to support escaping the package name and creating directory/package hierarchy

#KT-8362 Fixed
 #KT-11328 Fixed
This commit is contained in:
Dmitry Jemerov
2016-06-02 20:23:22 +02:00
parent 5f89274259
commit 8b30e7ef4e
3 changed files with 105 additions and 0 deletions
+2
View File
@@ -666,6 +666,8 @@
<annotationSupport language="kotlin" implementationClass="com.intellij.psi.impl.source.tree.java.JavaAnnotationSupport"/> <annotationSupport language="kotlin" implementationClass="com.intellij.psi.impl.source.tree.java.JavaAnnotationSupport"/>
<createFromTemplateHandler implementation="org.jetbrains.kotlin.idea.actions.KotlinCreateFromTemplateHandler"/>
<intentionAction> <intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.IfNullToElvisIntention</className> <className>org.jetbrains.kotlin.idea.intentions.IfNullToElvisIntention</className>
<category>Kotlin</category> <category>Kotlin</category>
@@ -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<String, Any>) {
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()
}
}
}
@@ -18,18 +18,25 @@ package org.jetbrains.kotlin.idea.actions
import com.intellij.ide.actions.CreateFileFromTemplateAction import com.intellij.ide.actions.CreateFileFromTemplateAction
import com.intellij.ide.actions.CreateFileFromTemplateDialog 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.DataContext
import com.intellij.openapi.actionSystem.LangDataKeys import com.intellij.openapi.actionSystem.LangDataKeys
import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.actionSystem.PlatformDataKeys
import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.DumbAware import com.intellij.openapi.project.DumbAware
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.PsiDirectory import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFile import com.intellij.psi.PsiFile
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinIcons import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.idea.configuration.showConfigureKotlinNotificationIfNeeded import org.jetbrains.kotlin.idea.configuration.showConfigureKotlinNotificationIfNeeded
import java.util.*
class NewKotlinFileAction class NewKotlinFileAction
: CreateFileFromTemplateAction("Kotlin File/Class", : CreateFileFromTemplateAction("Kotlin File/Class",
@@ -74,4 +81,59 @@ class NewKotlinFileAction
override fun equals(obj: Any?): Boolean { override fun equals(obj: Any?): Boolean {
return obj is NewKotlinFileAction 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<Char>): Pair<String, PsiDirectory> {
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
}
} }