Build: fix API differences between 201 and 202 in NewKotlinFileAction
This commit is contained in:
+3
-2
@@ -25,6 +25,7 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
@WithMutedInDatabaseRunTest
|
||||
@@ -46,7 +47,7 @@ public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCod
|
||||
return super.getFile();
|
||||
}
|
||||
|
||||
protected final Collection<File> myFilesToDelete = new THashSet<>();
|
||||
protected final Collection<Path> myFilesToDelete = new THashSet<>();
|
||||
private final TempFiles myTempFiles = new TempFiles(myFilesToDelete);
|
||||
|
||||
@Override
|
||||
@@ -65,7 +66,7 @@ public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCod
|
||||
File temp = FileUtil.createTempFile("copy", "." + ext);
|
||||
setContentOnDisk(temp, bom, content, charset);
|
||||
|
||||
myFilesToDelete.add(temp);
|
||||
myFilesToDelete.add(temp.toPath());
|
||||
final VirtualFile file = getVirtualFile(temp);
|
||||
assert file != null : temp;
|
||||
return file;
|
||||
|
||||
+2
-3
@@ -25,7 +25,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
@WithMutedInDatabaseRunTest
|
||||
@@ -47,7 +46,7 @@ public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCod
|
||||
return super.getFile();
|
||||
}
|
||||
|
||||
protected final Collection<Path> myFilesToDelete = new THashSet<>();
|
||||
protected final Collection<File> myFilesToDelete = new THashSet<>();
|
||||
private final TempFiles myTempFiles = new TempFiles(myFilesToDelete);
|
||||
|
||||
@Override
|
||||
@@ -66,7 +65,7 @@ public abstract class KotlinLightCodeInsightFixtureTestCaseBase extends LightCod
|
||||
File temp = FileUtil.createTempFile("copy", "." + ext);
|
||||
setContentOnDisk(temp, bom, content, charset);
|
||||
|
||||
myFilesToDelete.add(temp.toPath());
|
||||
myFilesToDelete.add(temp);
|
||||
final VirtualFile file = getVirtualFile(temp);
|
||||
assert file != null : temp;
|
||||
return file;
|
||||
@@ -47,10 +47,10 @@ class NewKotlinFileAction : CreateFileFromTemplateAction(
|
||||
KotlinBundle.message("action.new.file.description"),
|
||||
KotlinFileType.INSTANCE.icon
|
||||
), DumbAware {
|
||||
override fun postProcess(createdElement: PsiFile?, templateName: String?, customProperties: Map<String, String>?) {
|
||||
override fun postProcess(createdElement: PsiFile, templateName: String?, customProperties: Map<String, String>?) {
|
||||
super.postProcess(createdElement, templateName, customProperties)
|
||||
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(createdElement!!)
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(createdElement)
|
||||
|
||||
if (createdElement is KtFile) {
|
||||
if (module != null) {
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.idea.actions
|
||||
|
||||
import com.intellij.ide.actions.CreateFileFromTemplateAction
|
||||
import com.intellij.ide.actions.CreateFileFromTemplateDialog
|
||||
import com.intellij.ide.actions.CreateFromTemplateAction
|
||||
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.editor.LogicalPosition
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.module.Module
|
||||
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.openapi.ui.InputValidatorEx
|
||||
import com.intellij.psi.PsiDirectory
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.kotlin.idea.KotlinBundle
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.KotlinIcons
|
||||
import org.jetbrains.kotlin.idea.statistics.FUSEventGroups
|
||||
import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.parsing.KotlinParserDefinition.Companion.STD_SCRIPT_SUFFIX
|
||||
import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import java.util.*
|
||||
|
||||
class NewKotlinFileAction : CreateFileFromTemplateAction(
|
||||
KotlinBundle.message("action.new.file.text"),
|
||||
KotlinBundle.message("action.new.file.description"),
|
||||
KotlinFileType.INSTANCE.icon
|
||||
), DumbAware {
|
||||
override fun postProcess(createdElement: PsiFile?, templateName: String?, customProperties: Map<String, String>?) {
|
||||
super.postProcess(createdElement, templateName, customProperties)
|
||||
|
||||
val module = ModuleUtilCore.findModuleForPsiElement(createdElement!!)
|
||||
|
||||
if (createdElement is KtFile) {
|
||||
if (module != null) {
|
||||
for (hook in NewKotlinFileHook.EP_NAME.extensions) {
|
||||
hook.postProcess(createdElement, module)
|
||||
}
|
||||
}
|
||||
|
||||
val ktClass = createdElement.declarations.singleOrNull() as? KtNamedDeclaration
|
||||
if (ktClass != null) {
|
||||
CreateFromTemplateAction.moveCaretAfterNameIdentifier(ktClass)
|
||||
} else {
|
||||
val editor = FileEditorManager.getInstance(createdElement.project).selectedTextEditor ?: return
|
||||
if (editor.document == createdElement.viewProvider.document) {
|
||||
val lineCount = editor.document.lineCount
|
||||
if (lineCount > 0) {
|
||||
editor.caretModel.moveToLogicalPosition(LogicalPosition(lineCount - 1, 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun buildDialog(project: Project, directory: PsiDirectory, builder: CreateFileFromTemplateDialog.Builder) {
|
||||
builder.setTitle(KotlinBundle.message("action.new.file.dialog.title"))
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.class.title"),
|
||||
KotlinIcons.CLASS,
|
||||
"Kotlin Class"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.file.title"),
|
||||
KotlinFileType.INSTANCE.icon,
|
||||
"Kotlin File"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.interface.title"),
|
||||
KotlinIcons.INTERFACE,
|
||||
"Kotlin Interface"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.data.class.title"),
|
||||
KotlinIcons.CLASS,
|
||||
"Kotlin Data Class"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.enum.title"),
|
||||
KotlinIcons.ENUM,
|
||||
"Kotlin Enum"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.sealed.class.title"),
|
||||
KotlinIcons.CLASS,
|
||||
"Kotlin Sealed Class"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.annotation.title"),
|
||||
KotlinIcons.ANNOTATION,
|
||||
"Kotlin Annotation"
|
||||
)
|
||||
.addKind(
|
||||
KotlinBundle.message("action.new.file.dialog.object.title"),
|
||||
KotlinIcons.OBJECT,
|
||||
"Kotlin Object"
|
||||
)
|
||||
|
||||
builder.setValidator(NameValidator)
|
||||
}
|
||||
|
||||
override fun getActionName(directory: PsiDirectory, newName: String, templateName: String): String =
|
||||
KotlinBundle.message("action.new.file.text")
|
||||
|
||||
override fun isAvailable(dataContext: DataContext): Boolean {
|
||||
if (super.isAvailable(dataContext)) {
|
||||
val ideView = LangDataKeys.IDE_VIEW.getData(dataContext)!!
|
||||
val project = PlatformDataKeys.PROJECT.getData(dataContext)!!
|
||||
val projectFileIndex = ProjectRootManager.getInstance(project).fileIndex
|
||||
return ideView.directories.any { projectFileIndex.isInSourceContent(it.virtualFile) }
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = 0
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is NewKotlinFileAction
|
||||
|
||||
override fun startInWriteAction() = false
|
||||
|
||||
override fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory) =
|
||||
createFileFromTemplateWithStat(name, template, dir)
|
||||
|
||||
companion object {
|
||||
private object NameValidator : InputValidatorEx {
|
||||
override fun getErrorText(inputString: String): String? {
|
||||
if (inputString.trim().isEmpty()) {
|
||||
return KotlinBundle.message("action.new.file.error.empty.name")
|
||||
}
|
||||
|
||||
val parts: List<String> = inputString.split(*FQNAME_SEPARATORS)
|
||||
if (parts.any { it.trim().isEmpty() }) {
|
||||
return KotlinBundle.message("action.new.file.error.empty.name.part")
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
override fun checkInput(inputString: String): Boolean = true
|
||||
|
||||
override fun canClose(inputString: String): Boolean = getErrorText(inputString) == null
|
||||
}
|
||||
|
||||
@get:TestOnly
|
||||
val nameValidator: InputValidatorEx
|
||||
get() = NameValidator
|
||||
|
||||
private fun findOrCreateTarget(dir: PsiDirectory, name: String, directorySeparators: CharArray): Pair<String, PsiDirectory> {
|
||||
var className = removeKotlinExtensionIfPresent(name)
|
||||
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) ?: runWriteAction {
|
||||
targetDir.createSubdirectory(dirName)
|
||||
}
|
||||
}
|
||||
|
||||
className = names.last()
|
||||
break
|
||||
}
|
||||
}
|
||||
return Pair(className, targetDir)
|
||||
}
|
||||
|
||||
private fun removeKotlinExtensionIfPresent(name: String): String = when {
|
||||
name.endsWith(".$KOTLIN_WORKSHEET_EXTENSION") -> name.removeSuffix(".$KOTLIN_WORKSHEET_EXTENSION")
|
||||
name.endsWith(".$STD_SCRIPT_SUFFIX") -> name.removeSuffix(".$STD_SCRIPT_SUFFIX")
|
||||
name.endsWith(".${KotlinFileType.EXTENSION}") -> name.removeSuffix(".${KotlinFileType.EXTENSION}")
|
||||
else -> name
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
private val FILE_SEPARATORS = charArrayOf('/', '\\')
|
||||
private val FQNAME_SEPARATORS = charArrayOf('/', '\\', '.')
|
||||
|
||||
fun createFileFromTemplateWithStat(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
|
||||
KotlinFUSLogger.log(FUSEventGroups.NewFileTemplate, template.name)
|
||||
return createFileFromTemplate(name, template, dir)
|
||||
}
|
||||
|
||||
|
||||
fun createFileFromTemplate(name: String, template: FileTemplate, dir: PsiDirectory): PsiFile? {
|
||||
val directorySeparators = when (template.name) {
|
||||
"Kotlin File" -> FILE_SEPARATORS
|
||||
else -> FQNAME_SEPARATORS
|
||||
}
|
||||
val (className, targetDir) = findOrCreateTarget(dir, name, directorySeparators)
|
||||
|
||||
val service = DumbService.getInstance(dir.project)
|
||||
service.isAlternativeResolveEnabled = true
|
||||
try {
|
||||
val psiFile = createFromTemplate(targetDir, className, template)
|
||||
if (psiFile is KtFile) {
|
||||
val singleClass = psiFile.declarations.singleOrNull() as? KtClass
|
||||
if (singleClass != null && !singleClass.isEnum() && !singleClass.isInterface() && name.contains("Abstract")) {
|
||||
runWriteAction {
|
||||
singleClass.addModifier(KtTokens.ABSTRACT_KEYWORD)
|
||||
}
|
||||
}
|
||||
}
|
||||
return psiFile
|
||||
} finally {
|
||||
service.isAlternativeResolveEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class NewKotlinFileHook {
|
||||
companion object {
|
||||
val EP_NAME: ExtensionPointName<NewKotlinFileHook> =
|
||||
ExtensionPointName.create<NewKotlinFileHook>("org.jetbrains.kotlin.newFileHook")
|
||||
}
|
||||
|
||||
abstract fun postProcess(createdElement: KtFile, module: Module)
|
||||
}
|
||||
+2
-2
@@ -15,7 +15,7 @@ abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTes
|
||||
override fun getProjectDirOrFile(): Path {
|
||||
val tempDir = FileUtil.generateRandomTemporaryPath()
|
||||
FileUtil.createTempDirectory("temp", null)
|
||||
myFilesToDelete.add(tempDir)
|
||||
myFilesToDelete.add(tempDir.toPath())
|
||||
|
||||
FileUtil.copyDir(File(projectRoot), tempDir)
|
||||
|
||||
@@ -35,4 +35,4 @@ abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTes
|
||||
|
||||
return File(projectFilePath).toPath()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ abstract class AbstractConfigureKotlinInTempDirTest : AbstractConfigureKotlinTes
|
||||
override fun getProjectDirOrFile(): Path {
|
||||
val tempDir = FileUtil.generateRandomTemporaryPath()
|
||||
FileUtil.createTempDirectory("temp", null)
|
||||
myFilesToDelete.add(tempDir.toPath())
|
||||
myFilesToDelete.add(tempDir)
|
||||
|
||||
FileUtil.copyDir(File(projectRoot), tempDir)
|
||||
|
||||
@@ -237,14 +237,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
|
||||
private val pathToNonexistentRuntimeJar: String
|
||||
get() {
|
||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar).toPath())
|
||||
return pathToTempKotlinRuntimeJar
|
||||
}
|
||||
|
||||
private val pathToNonexistentJsJar: String
|
||||
get() {
|
||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar).toPath())
|
||||
return pathToTempKotlinRuntimeJar
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -237,14 +237,14 @@ abstract class AbstractConfigureKotlinTest : PlatformTestCase() {
|
||||
private val pathToNonexistentRuntimeJar: String
|
||||
get() {
|
||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_STDLIB_JAR
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar).toPath())
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
|
||||
return pathToTempKotlinRuntimeJar
|
||||
}
|
||||
|
||||
private val pathToNonexistentJsJar: String
|
||||
get() {
|
||||
val pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar).toPath())
|
||||
myFilesToDelete.add(File(pathToTempKotlinRuntimeJar))
|
||||
return pathToTempKotlinRuntimeJar
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ class QuickDocInHierarchyTest() : CodeInsightTestCase() {
|
||||
val provider = BrowseHierarchyActionBase.findProvider(LanguageTypeHierarchy.INSTANCE, file, file, context)!!
|
||||
val hierarchyTreeStructure = TypeHierarchyTreeStructure(
|
||||
project,
|
||||
provider.getTarget(context) as PsiClass?,
|
||||
provider.getTarget(context) as PsiClass,
|
||||
HierarchyBrowserBaseEx.SCOPE_PROJECT
|
||||
)
|
||||
val hierarchyNodeDescriptor = hierarchyTreeStructure.baseDescriptor as TypeHierarchyNodeDescriptor
|
||||
@@ -47,4 +47,4 @@ class QuickDocInHierarchyTest() : CodeInsightTestCase() {
|
||||
|
||||
TestCase.assertTrue("Invalid doc\n: $doc", doc.contains("Very special class"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ class QuickDocInHierarchyTest() : CodeInsightTestCase() {
|
||||
val provider = BrowseHierarchyActionBase.findProvider(LanguageTypeHierarchy.INSTANCE, file, file, context)!!
|
||||
val hierarchyTreeStructure = TypeHierarchyTreeStructure(
|
||||
project,
|
||||
provider.getTarget(context) as PsiClass,
|
||||
provider.getTarget(context) as PsiClass?,
|
||||
HierarchyBrowserBaseEx.SCOPE_PROJECT
|
||||
)
|
||||
val hierarchyNodeDescriptor = hierarchyTreeStructure.baseDescriptor as TypeHierarchyNodeDescriptor
|
||||
@@ -5,7 +5,7 @@ import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.test.common.UElementToParentMap
|
||||
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
|
||||
import org.jetbrains.uast.test.common.visitUFileAndGetResult
|
||||
import org.jetbrains.uast.test.env.assertEqualsToFile
|
||||
import org.jetbrains.uast.test.env.kotlin.assertEqualsToFile
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
@@ -34,4 +34,4 @@ private fun refNameRetriever(psiElement: PsiElement): UElement? =
|
||||
|
||||
fun UFile.asRefNames() = object : UElementToParentMap(::refNameRetriever) {
|
||||
override fun renderSource(element: PsiElement): String = element.javaClass.simpleName
|
||||
}.visitUFileAndGetResult(this)
|
||||
}.visitUFileAndGetResult(this)
|
||||
|
||||
+1
-1
@@ -1,11 +1,11 @@
|
||||
package org.jetbrains.uast.test.kotlin
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.testFramework.assertEqualsToFile
|
||||
import org.jetbrains.uast.*
|
||||
import org.jetbrains.uast.test.common.UElementToParentMap
|
||||
import org.jetbrains.uast.test.common.kotlin.IdentifiersTestBase
|
||||
import org.jetbrains.uast.test.common.visitUFileAndGetResult
|
||||
import org.jetbrains.uast.test.env.assertEqualsToFile
|
||||
import java.io.File
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
Reference in New Issue
Block a user