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"/>
<createFromTemplateHandler implementation="org.jetbrains.kotlin.idea.actions.KotlinCreateFromTemplateHandler"/>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.IfNullToElvisIntention</className>
<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.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<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
}
}