i18n: add bundle for idea/refactoring/move

This commit is contained in:
Roman Golyshev
2020-02-26 18:27:31 +03:00
committed by Dmitry Gridin
parent 93493bdc09
commit 73de63cefc
24 changed files with 246 additions and 95 deletions
@@ -168,6 +168,12 @@ fix.import.kind.delegate.accessors=Delegate accessors
fix.import.kind.component.functions=Component functions
fix.import.exclude=Exclude ''{0}'' from auto-import
fix.move.file.to.package.family=Move file to package-matching directory
fix.move.file.to.package.text=Move file to {0}
fix.change.package.family=Change file's package to match directory
fix.change.package.text=Change file''s package to {0}
action.add.import.chooser.title=Imports
goto.super.chooser.function.title=Choose super function
@@ -225,6 +231,11 @@ hierarchy.legend.member.is.defined.in.class=Member is defined in the class
hierarchy.legend.member.defined.in.superclass=Member is not defined in the class but defined in superclass
hierarchy.legend.member.should.be.defined=Member should be defined since the class is not abstract
intention.change.package.text=Change package
intention.extract.declarations.from.file.text=Extract declaration from current file
intention.extract.declarations.from.file.text.details=Extract ''{0}'' {1, choice, 0#|1#and subclasses }from current file
intention.suppress.family=Suppress Warnings
intention.suppress.text=Suppress ''{0}'' for {1} {2}
@@ -737,6 +748,8 @@ configuration.warning.text.modules.override.project.settings={0} modules overrid
action.text.append=Append
action.text.cancel=Cancel
action.text.overwrite=Overwrite
button.text.move.nested.class.0.to.upper.level=Move &nested class {0} to upper level
button.text.move.nested.class.0.to.another.class=&Move nested class {0} to another class
cannot.extract.method=Cannot find statements to extract
cannot.extract.super.call=Cannot extract super-call
cannot.inline.property.with.accessor.s.and.backing.field=Cannot inline property with accessor(s) and backing field
@@ -751,10 +764,14 @@ cannot.refactor.package.expression=Cannot introduce package reference
cannot.refactor.syntax.errors=Cannot refactor due to erroneous code
cannot.refactor.synthesized.function=Cannot refactor synthesized function ''{0}''
checkbox.text.declare.with.var=Declare with &var
checkbox.text.delete.empty.source.files=&Delete empty source files
checkbox.text.extension.property=E&xtension property:\u0020
checkbox.text.introduce.default.value=Introduce &default value
checkbox.text.open.moved.files.in.editor=Open moved member in editor
checkbox.text.replace.all.occurrences.0=&Replace all occurrences ({0})
checkbox.text.search.references=Search &references
checkbox.text.specify.type.explicitly=Specify &type explicitly
checkbox.text.update.package.directive=Update package directive (Kotlin files)
column.name.receiver=Receiver:
column.name.val.var=Val/Var
declarations.are.used.outside.of.selected.code.fragment=Following declarations are used outside of selected code fragment:
@@ -798,11 +815,17 @@ introduce.type.parameter.to.declaration=Introduce type parameter to declaration
introduce.type.parameter=Introduce Type Parameter
introduce.variable=Introduce Variable
label.text.default.receiver.value=&Default receiver value:\u0020
label.text.destination.directory=&Destination directory:
label.text.file.name=File &name:
label.text.introduce.as=&Introduce as:\u0020
label.text.name=&Name:\u0020
label.text.package.name=Packa&ge name:
label.text.receiver.type=Receiver &type:\u0020
label.text.target.file.name=Target file name:
label.text.to.file=To &file:
label.text.to.package=To p&ackage:
label.text.type=&Type:\u0020
label.text.update.package.directive=&Update package directive
label.text.visibility=&Visibility:\u0020
member.info.abstract.0=abstract {0}
member.info.companion.0=companion {0}
@@ -830,35 +853,60 @@ selected.code.fragment.has.multiple.exit.points=Selected code fragment has multi
selected.code.fragment.has.multiple.output.values=Selected code fragment has more than 3 output values:
selected.code.fragment.has.output.values.and.exit.points=Selected code fragment has output values as well as alternative exit points
setter.of.0.will.become.invisible.after.extraction = Setter of {0} will become invisible after extraction
text.0.1.must.be.moved.with.sealed.parent.class.and.all.its.subclasses={0} ''{1}'' must be moved with sealed parent class and all its subclasses
text.0.is.invalid.destination.package=''{0}'' is invalid destination package name
text.0.is.not.allowed.in.the.target.context=''{0}'' is not allowed in the target context
text.0.is.not.valid.package.name={0} is not a valid package name
text.0.to.inline={0} to inline
text.0.uses.1.which.will.be.inaccessible.after.move={0} uses {1} which will be inaccessible after move
text.0.uses.internal.1.which.will.be.inaccessible.after.move={0} uses internal {1} which will be inaccessible after move
text.0.will.no.longer.be.accessible.after.signature.change={0} will no longer be accessible after signature change
text.all.declarations.must.belong.to.the.same.directory.or.class=All declarations must belong to the same directory or class
text.all=All
text.anonymous=[Anonymous]
text.at.least.one.file.must.be.selected=At least one member must be selected
text.callee.text.would.be.shown.here=Callee text would be shown here
text.caller.text.with.highlighted.callee.call.would.be.shown.here=Caller text\nwith highlighted callee call would be shown here
text.cannot.create.target.directory.0=Cannot create target directory {0}
text.cannot.determine.source.directory=Can't determine sources directory
text.cannot.find.package.corresponding.to.0=Could not find package corresponding to {0}
text.cannot.find.target.package.name=Cannot find target package name
text.cannot.inline.0.1.usages=Cannot inline {0}/{1} usages
text.cannot.move.for.current.project=Can't move for current project
text.cannot.move.inner.class.0.into.itself=Cannot move nested class {0} to itself
text.cannot.move.to.original.file=Can't move to the original file
text.change.file.package.to.0=Change file''s package to ''{0}''
text.choose.containing.file=Choose Containing File
text.class.0.already.exists.in.package.1=Class {0} already exists in package {1}
text.class.0.already.exists.in.the.target.scope=Class {0} already exists in the target scope
text.constructor=constructor
text.create.destructuring.declaration=Create destructuring declaration
text.create.single.variable=Create single variable
text.declaration=declaration
text.declarations.clash.move.0.destination.1.declared.in.scope.2=Following declarations would clash: to move {0} and destination {1} declared in scope {2}
text.default.value=\ // default value = {0}
text.destination.class.should.be.kotlin.class=Destination class must be a Kotlin class
text.duplicating.local.variable=Duplicating local variable ''{0}''
text.duplicating.parameter=Duplicating parameter ''{0}''
text.duplicating.property=Duplicating property ''{0}''
text.explicit.receiver.is.already.present.in.call.element.0=Explicit receiver is already present in call element: {0}
text.extract.superclass=Extract Superclass
text.file.0.already.exists.in.1=File {0} already exists in {1}
text.file.name.cannot.be.empty=File name may not be empty
text.function.already.exists=Function already exists: ''{0}''
text.function=function
text.implicit.companion.object.will.be.inaccessible.0=Implicit companion object will be inaccessible: {0}
text.incorrect.target.path.directory.0.does.not.belong.to.current.project=Incorrect target path. Directory {0} does not belong to current project.
text.indirect.outer.instances.will.not.be.extracted.0=Indirect outer instances won''t be extracted: {0}
text.inline.0.1.2=Inline {0} ''{1}''? {2}
text.inline.0=Inline {0}
text.inline.all.references.and.0.the.1=Inline all references and {0} the kind {1}
text.inline.recursive.function.is.supported.only.on.references=Inline recursive function is supported only on references
text.inline.this.reference.and.keep.the.0=Inline this reference and keep the {0}
text.inlining.0.1=Inlining {0} {1}
text.inlining.0.1=Inlining {0} {1}
text.introduce.default.value=Intro&duce default value
text.invalid.target.path.0=Invalid target path {0}
text.invalid.target.specified=Invalid target specified
text.keep=keep
text.lambda.parameter=lambda parameter
text.lambda.parameters=Lambda &parameters:\u0020
@@ -866,8 +914,22 @@ text.lambda.return.type=Lambda return &type
text.lazy.property=lazy property
text.local.property=property
text.local.variable=local variable
text.looking.for.usages=Looking for Usages
text.member.extension.call.will.not.be.processed.0=Member extension call won''t be processed: {0}
text.move.declaration.no.support.for.companion.objects=Move declaration is not supported for companion objects
text.move.declaration.no.support.for.enums=Move declaration is not supported for enum entries
text.move.declaration.supports.only.top.levels.and.nested.classes=Move declaration is only supported for top-level declarations and nested classes
text.move.declarations=Move declarations
text.move.file.0=Move {0}
text.move.refactoring.not.available.during.indexing=Move refactoring is not available while indexing is in progress
text.moving.multiple.nested.classes.to.top.level.not.supported=Moving multiple nested classes to top-level is not supported
text.name=Name
text.nested.classes.to.upper.level=Nested Classes to Upper Level
text.no.elements.to.move.are.selected=No elements to move are selected
text.no.files.to.move=There is no given files to move
text.no.name.provided.for.type.alias=No name provided for type alias
text.no.package.corresponds.to.directory=No package corresponds to this directory
text.package.directive.dont.match.file.location=Package directive doesn't match file location
text.parameter.0=parameter ''{0}''
text.parameter.name=Parameter &name:\u0020
text.parameter.reference.can.t.be.safely.replaced.with.0.since.1.is.ambiguous.in.this.context=Parameter reference can''t be safely replaced with {0} since {1} is ambiguous in this context
@@ -877,15 +939,19 @@ text.parameter=parameter ''{0}''
text.parameters=&Parameters
text.proceed.with.extraction=Proceed with extraction
text.process.duplicates=Process Duplicates
text.processing.file.0=Processing {0}
text.property.with.getter=property with getter
text.property.with.initializer=property with initializer
text.property=property
text.qualified.call.will.not.be.processed.0=Qualified call won''t be processed: {0}
text.receiver.can.t.be.safely.transformed.to.value.argument=Receiver can''t be safely transformed to value argument: {0}
text.receiver=receiver
text.refactoring.can.t.be.performed.on.the.selected.code.element=Refactoring can''t be performed on the selected code element
text.refactoring.is.not.applicable.to.this.code.fragment=Refactoring is not applicable to this code fragment
text.references.in.code.to.0.1.and.its.declarations=References in code to {0} {1} and its declarations
text.remove.0.no.longer.used=Remove {0} no longer used
text.remove=remove
text.sealed.class.0.must.be.moved.with.all.its.subclasses=Sealed class ''{0}'' must be moved with all its subclasses
text.select.target.code.block.file=Select target code block / file
text.select.target.code.block=Select target code block
text.select.target.file=Select target file
@@ -899,10 +965,13 @@ text.type.already.exists.in.the.target.scope=Type {0} already exists in the targ
text.type.parameter.names.must.be.distinct=Type parameter names must be distinct
text.type.parameters=Type &Parameters
text.type=Type
text.unexpected.element.type.0=Unexpected element type: {0}
text.update.usages.to.reflect.declaration.0.move=Update usages to reflect {0, choice, 0#declaration|1#declarations} move
text.updating.usages.progress=Updating usages...
text.variable=variable
title.change.signature=Change Signature
title.inline.function=Inline Function
title.introduce.parameter.to.declaration=Introduce parameter to declaration
title.move.nested.classes.to.upper.level=Move Nested Classes to Upper Level
title.select.target.code.block=Select target code block
unsupported.usage.0=Unsupported usage: {0}
title.change.signature=Change Signature
unsupported.usage.0=Unsupported usage: {0}
@@ -23,6 +23,7 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiDocumentManager
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.quoteSegmentsIfNeeded
import org.jetbrains.kotlin.idea.core.util.CodeInsightUtils
import org.jetbrains.kotlin.idea.intentions.SelfTargetingOffsetIndependentIntention
@@ -33,7 +34,10 @@ import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtPackageDirective
class ChangePackageIntention :
SelfTargetingOffsetIndependentIntention<KtPackageDirective>(KtPackageDirective::class.java, "Change package") {
SelfTargetingOffsetIndependentIntention<KtPackageDirective>(
KtPackageDirective::class.java,
KotlinBundle.message("intention.change.package.text")
) {
companion object {
private const val PACKAGE_NAME_VAR = "PACKAGE_NAME"
}
@@ -79,27 +83,35 @@ class ChangePackageIntention :
}
override fun templateFinished(template: Template, brokenOff: Boolean) {
if (brokenOff || enteredName == null || affectedRange == null) return
if (brokenOff) return
val name = enteredName ?: return
val range = affectedRange ?: return
// Restore original name and run refactoring
val document = editor.document
project.executeWriteCommand(text) {
document.replaceString(
affectedRange!!.startOffset,
affectedRange!!.endOffset,
range.startOffset,
range.endOffset,
FqName(currentName).quoteSegmentsIfNeeded()
)
}
PsiDocumentManager.getInstance(project).commitDocument(document)
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document)
if (!FqNameUnsafe(enteredName!!).hasIdentifiersOnly()) {
CodeInsightUtils.showErrorHint(project, editor, "$enteredName is not a valid package name", "Change package", null)
if (!FqNameUnsafe(name).hasIdentifiersOnly()) {
CodeInsightUtils.showErrorHint(
project,
editor,
KotlinBundle.message("text.0.is.not.valid.package.name", name),
KotlinBundle.message("intention.change.package.text"),
null
)
return
}
KotlinChangePackageRefactoring(file).run(FqName(enteredName!!))
KotlinChangePackageRefactoring(file).run(FqName(name))
}
}
)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.idea.refactoring.move.changePackage
import com.intellij.refactoring.RefactoringBundle
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.codeInsight.shorten.runRefactoringAndKeepDelayedRequests
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
import org.jetbrains.kotlin.idea.core.util.runSynchronouslyWithProgress
@@ -54,7 +55,7 @@ class KotlinChangePackageRefactoring(val file: KtFile) {
val changeInfo = ContainerChangeInfo(ContainerInfo.Package(currentFqName), ContainerInfo.Package(newFqName))
val internalUsages = file.getInternalReferencesToUpdateOnPackageNameChange(changeInfo)
project.executeWriteCommand("Change file's package to '${newFqName.asString()}'") {
project.executeWriteCommand(KotlinBundle.message("text.change.file.package.to.0", newFqName)) {
packageDirective.fqName = newFqName.quoteIfNeeded()
postProcessMoveUsages(internalUsages)
project.runRefactoringAndKeepDelayedRequests { declarationProcessor.execute(declarationUsages) }
@@ -18,6 +18,7 @@ import com.intellij.refactoring.move.moveClassesOrPackages.AutocreatingSingleSou
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesUtil
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import com.intellij.refactoring.util.RefactoringMessageUtil
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.getFqNameByDirectory
import org.jetbrains.kotlin.idea.core.getFqNameWithImplicitPrefix
import org.jetbrains.kotlin.idea.core.packageMatchesDirectoryOrImplicit
@@ -59,15 +60,15 @@ class PackageDirectoryMismatchInspection : AbstractKotlinInspection() {
holder.registerProblem(
file,
textRange,
"Package directive doesn't match file location",
KotlinBundle.message("text.package.directive.dont.match.file.location"),
*fixes.toTypedArray()
)
})
private class MoveFileToPackageFix(val dirName: String) : LocalQuickFix {
override fun getFamilyName() = "Move file to package-matching directory"
override fun getFamilyName() = KotlinBundle.message("fix.move.file.to.package.family")
override fun getName() = "Move file to $dirName"
override fun getName() = KotlinBundle.message("fix.move.file.to.package.text", dirName)
override fun startInWriteAction() = false
@@ -103,9 +104,9 @@ class PackageDirectoryMismatchInspection : AbstractKotlinInspection() {
}
private class ChangePackageFix(val packageName: String, val packageFqName: FqName) : LocalQuickFix {
override fun getFamilyName() = "Change file's package to match directory"
override fun getFamilyName() = KotlinBundle.message("fix.change.package.family")
override fun getName() = "Change file's package to $packageName"
override fun getName() = KotlinBundle.message("fix.change.package.text", packageName)
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val file = descriptor.psiElement as? KtFile ?: return
@@ -25,6 +25,7 @@ import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.refactoring.MoveDestination
import com.intellij.usageView.UsageInfo
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.refactoring.move.createMoveUsageInfoIfPossible
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.KotlinDirectoryMoveTarget
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.analyzeConflictsInFile
@@ -78,7 +79,7 @@ class KotlinAwareDelegatingMoveDestination(
val extraUsages = ArrayList<UsageInfo>()
try {
progressIndicator.text = "Looking for Usages"
progressIndicator.text = KotlinBundle.message("text.looking.for.usages")
for ((index, element) in extraElementsForReferenceSearch.withIndex()) {
progressIndicator.fraction = (index + 1) / extraElementsForReferenceSearch.size.toDouble()
ReferencesSearch.search(element, projectScope).mapNotNullTo(extraUsages) { ref ->
@@ -15,11 +15,13 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFile
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.util.CommonRefactoringUtil
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeoutOrNull
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.moveCaret
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
@@ -38,7 +40,10 @@ import org.jetbrains.kotlin.resolve.source.getPsi
private const val TIMEOUT_FOR_IMPORT_OPTIMIZING_MS: Long = 700L
class ExtractDeclarationFromCurrentFileIntention :
SelfTargetingRangeIntention<KtClassOrObject>(KtClassOrObject::class.java, "Extract declaration from current file"),
SelfTargetingRangeIntention<KtClassOrObject>(
KtClassOrObject::class.java,
KotlinBundle.message("intention.extract.declarations.from.file.text")
),
LowPriorityAction {
private fun KtClassOrObject.tryGetExtraClassesToMove(): List<KtNamedDeclaration>? {
@@ -66,8 +71,11 @@ class ExtractDeclarationFromCurrentFileIntention :
val endOffset = element.nameIdentifier?.endOffset ?: return null
text = if (extraClassesToMove.isNotEmpty()) "Extract '${element.name}' and subclasses from current file"
else "Extract '${element.name}' from current file"
text = KotlinBundle.message(
"intention.extract.declarations.from.file.text.details",
element.name.toString(),
extraClassesToMove.size
)
return TextRange(startOffset, endOffset)
}
@@ -86,7 +94,7 @@ class ExtractDeclarationFromCurrentFileIntention :
if (targetFile !== null) {
if (ApplicationManager.getApplication().isUnitTestMode) {
throw CommonRefactoringUtil.RefactoringErrorHintException("File $targetFileName already exists")
throw CommonRefactoringUtil.RefactoringErrorHintException(RefactoringBundle.message("file.already.exist", targetFileName))
}
// If automatic move is not possible, fall back to full-fledged Move Declarations refactoring
runFullFledgedMoveRefactoring(project, element, packageName, directory, targetFile, file)
@@ -13,6 +13,7 @@ import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor
import org.jetbrains.kotlin.idea.codeInsight.shorten.isToBeShortened
import org.jetbrains.kotlin.idea.refactoring.move.*
@@ -101,7 +102,10 @@ sealed class MoveDeclarationsDelegate {
val isConflict = when (usage) {
is ImplicitCompanionAsDispatchReceiverUsageInfo -> {
if (!isValidTargetForImplicitCompanionAsDispatchReceiver(descriptor, usage.companionDescriptor)) {
conflicts.putValue(element, "Implicit companion object will be inaccessible: ${element.text}")
conflicts.putValue(
element,
KotlinBundle.message("text.implicit.companion.object.will.be.inaccessible.0", element.text)
)
}
true
}
@@ -12,6 +12,7 @@ import com.intellij.refactoring.RefactoringBundle
import com.intellij.usageView.UsageViewBundle
import com.intellij.usageView.UsageViewDescriptor
import com.intellij.usageView.UsageViewUtil
import org.jetbrains.kotlin.idea.KotlinBundle
internal class MoveFilesWithDeclarationsViewDescriptor(
private val myElementsToMove: Array<PsiElement>,
@@ -27,8 +28,11 @@ internal class MoveFilesWithDeclarationsViewDescriptor(
UsageViewUtil.getType(myElementsToMove[0]),
newParent.virtualFile.presentableUrl
).capitalize()
myCodeReferencesText =
"References in code to ${UsageViewUtil.getType(myElementsToMove[0])} ${UsageViewUtil.getLongName(myElementsToMove[0])} and its declarations"
myCodeReferencesText = KotlinBundle.message(
"text.references.in.code.to.0.1.and.its.declarations",
UsageViewUtil.getType(myElementsToMove[0]),
UsageViewUtil.getLongName(myElementsToMove[0])
)
} else {
myProcessedElementsHeader =
StringUtil.capitalize(RefactoringBundle.message("move.files.elements.header", newParent.virtualFile.presentableUrl))
@@ -23,14 +23,15 @@ import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.Messages
import com.intellij.psi.*
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesImpl
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import com.intellij.refactoring.util.CommonRefactoringUtil
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.getPackage
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings
import org.jetbrains.kotlin.idea.refactoring.canRefactor
import org.jetbrains.kotlin.idea.refactoring.move.MoveHandlerDelegateCompat
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui.KotlinAwareMoveFilesOrDirectoriesDialog
@@ -142,7 +143,11 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
val container = getUniqueContainer(elements)
if (container == null) {
handlerActions.showErrorHint(
project, editor, "All declarations must belong to the same directory or class", MOVE_DECLARATIONS, null
project,
editor,
KotlinBundle.message("text.all.declarations.must.belong.to.the.same.directory.or.class"),
MOVE_DECLARATIONS,
null
)
return false
}
@@ -157,21 +162,22 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
// todo: allow moving companion object
if (elementsToSearch.any { it is KtObjectDeclaration && it.isCompanion() }) {
val message = RefactoringBundle.getCannotRefactorMessage("Move declaration is not supported for companion objects")
val message = RefactoringBundle.getCannotRefactorMessage(
KotlinBundle.message("text.move.declaration.no.support.for.companion.objects")
)
handlerActions.showErrorHint(project, editor, message, MOVE_DECLARATIONS, null)
return true
}
if (elementsToSearch.any { !it.canMove() }) {
val message =
RefactoringBundle
.getCannotRefactorMessage("Move declaration is only supported for top-level declarations and nested classes")
RefactoringBundle.getCannotRefactorMessage(KotlinBundle.message("text.move.declaration.supports.only.top.levels.and.nested.classes"))
handlerActions.showErrorHint(project, editor, message, MOVE_DECLARATIONS, null)
return true
}
if (elementsToSearch.any { it is KtEnumEntry }) {
val message = RefactoringBundle.getCannotRefactorMessage("Move declaration is not supported for enum entries")
val message = RefactoringBundle.getCannotRefactorMessage(KotlinBundle.message("text.move.declaration.no.support.for.enums"))
handlerActions.showErrorHint(project, editor, message, MOVE_DECLARATIONS, null)
return true
}
@@ -223,7 +229,9 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
// todo: allow moving multiple classes to upper level
if (targetContainer !is KtClassOrObject) {
val message =
RefactoringBundle.getCannotRefactorMessage("Moving multiple nested classes to top-level is not supported")
RefactoringBundle.getCannotRefactorMessage(
KotlinBundle.message("text.moving.multiple.nested.classes.to.top.level.not.supported")
)
handlerActions.showErrorHint(project, editor, message, MOVE_DECLARATIONS, null)
return true
}
@@ -315,4 +323,4 @@ class MoveKotlinDeclarationsHandler internal constructor(private val handlerActi
}
}
private val MOVE_DECLARATIONS = "Move Declarations"
private val MOVE_DECLARATIONS: String get() = KotlinBundle.message("text.move.declarations")
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration
import org.jetbrains.kotlin.asJava.findFacadeClass
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.asJava.toLightElements
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToBeShortenedDescendantsToWaitingSet
import org.jetbrains.kotlin.idea.core.deleteSingle
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
@@ -138,7 +139,6 @@ class MoveKotlinDeclarationsProcessor(
private val throwOnConflicts: Boolean = false
) : BaseRefactoringProcessor(descriptor.project) {
companion object {
private const val REFACTORING_NAME = "Move declarations"
const val REFACTORING_ID = "move.kotlin.declarations"
}
@@ -365,5 +365,5 @@ class MoveKotlinDeclarationsProcessor(
}
}
override fun getCommandName(): String = REFACTORING_NAME
override fun getCommandName(): String = KotlinBundle.message("text.move.declarations")
}
@@ -27,6 +27,7 @@ import com.intellij.usageView.UsageInfo
import com.intellij.usageView.UsageViewDescriptor
import com.intellij.util.containers.MultiMap
import com.intellij.util.text.UniqueNameGenerator
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.psi.KtFile
class MoveToKotlinFileProcessor @JvmOverloads constructor(
@@ -49,7 +50,7 @@ class MoveToKotlinFileProcessor @JvmOverloads constructor(
moveCallback,
prepareSuccessfulCallback
) {
override fun getCommandName() = "Move ${sourceFile.name}"
override fun getCommandName() = KotlinBundle.message("text.move.file.0", sourceFile.name)
override fun createUsageViewDescriptor(usages: Array<out UsageInfo>): UsageViewDescriptor {
return MoveFilesWithDeclarationsViewDescriptor(arrayOf(sourceFile), targetDirectory)
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.MutablePackageFragmentDescriptor
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.caches.project.forcedModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfoByVirtualFile
import org.jetbrains.kotlin.idea.caches.project.implementedModules
@@ -399,7 +400,11 @@ class MoveConflictChecker(
val newDescriptorToCheck = referencedDescriptor.asPredicted(targetContainer, actualVisibility) ?: continue
if (originalDescriptorToCheck.isVisibleIn(referencingDescriptor) && !newDescriptorToCheck.isVisibleIn(referencingDescriptor)) {
val message = "${render(container)} uses ${render(referencedElement)} which will be inaccessible after move"
val message = KotlinBundle.message(
"text.0.uses.1.which.will.be.inaccessible.after.move",
render(container),
render(referencedElement)
)
conflicts.putValue(element, message.capitalize())
}
}
@@ -473,7 +478,11 @@ class MoveConflictChecker(
}
if (!isVisible) {
val message = "${render(declaration)} uses ${render(target)} which will be inaccessible after move"
val message = KotlinBundle.message(
"text.0.uses.1.which.will.be.inaccessible.after.move",
render(declaration),
render(target)
)
conflicts.putValue(refExpr, message.capitalize())
}
}
@@ -502,7 +511,11 @@ class MoveConflictChecker(
val usageModule = ModuleUtilCore.findModuleForPsiElement(element) ?: continue
if (usageModule != targetModule && targetModule !in usageModule.implementedModules && !isToBeMoved(element)) {
val container = element.getUsageContext()
val message = "${render(container)} uses internal ${render(memberToCheck)} which will be inaccessible after move"
val message = KotlinBundle.message(
"text.0.uses.internal.1.which.will.be.inaccessible.after.move",
render(container),
render(memberToCheck)
)
conflicts.putValue(element, message.capitalize())
}
}
@@ -537,10 +550,14 @@ class MoveConflictChecker(
if (isToBeMoved(rootClass) && subclasses.all { isToBeMoved(it) }) continue
val message = if (elementToMove == rootClass) {
"Sealed class '${rootClass.name}' must be moved with all its subclasses"
KotlinBundle.message("text.sealed.class.0.must.be.moved.with.all.its.subclasses", rootClass.name.toString())
} else {
val type = ElementDescriptionUtil.getElementDescription(elementToMove, UsageViewTypeLocation.INSTANCE).capitalize()
"$type '${rootClass.name}' must be moved with sealed parent class and all its subclasses"
KotlinBundle.message(
"text.0.1.must.be.moved.with.sealed.parent.class.and.all.its.subclasses",
type,
rootClass.name.toString()
)
}
conflicts.putValue(elementToMove, message)
}
@@ -624,11 +641,12 @@ class MoveConflictChecker(
moveTarget.getContainerDescriptor()?.let { baseDescriptor ->
walkDeclarations(baseDescriptor, declarationDescriptor) { conflictingDeclaration, conflictingScope ->
val message =
"Following declarations would clash: to move ${render(declarationDescriptor)} " +
"and destination ${render(conflictingDeclaration)} declared in scope " +
render(conflictingScope)
val message = KotlinBundle.message(
"text.declarations.clash.move.0.destination.1.declared.in.scope.2",
render(declarationDescriptor),
render(conflictingDeclaration),
render(conflictingScope)
)
conflicts.putValue(declaration, message)
}
}
@@ -30,6 +30,7 @@ import com.intellij.ui.TextFieldWithHistoryWithBrowseButton
import com.intellij.ui.components.JBLabelDecorator
import com.intellij.util.ui.FormBuilder
import com.intellij.util.ui.UIUtil
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.packageMatchesDirectoryOrImplicit
import org.jetbrains.kotlin.idea.core.util.onTextChange
import org.jetbrains.kotlin.idea.refactoring.isInKotlinAwareSourceRoot
@@ -63,8 +64,10 @@ class KotlinAwareMoveFilesOrDirectoriesDialog(
private val nameLabel = JBLabelDecorator.createJBLabelDecorator().setBold(true)
private val targetDirectoryField = TextFieldWithHistoryWithBrowseButton()
private val searchReferencesCb = NonFocusableCheckBox("Search r${UIUtil.MNEMONIC}eferences").apply { isSelected = true }
private val openInEditorCb = NonFocusableCheckBox("Open moved files in editor")
private val searchReferencesCb = NonFocusableCheckBox(KotlinBundle.message("checkbox.text.search.references")).apply {
isSelected = true
}
private val openInEditorCb = NonFocusableCheckBox(KotlinBundle.message("checkbox.text.open.moved.files.in.editor"))
private val updatePackageDirectiveCb = NonFocusableCheckBox()
override fun getHelpId() = HELP_ID
@@ -144,7 +147,7 @@ class KotlinAwareMoveFilesOrDirectoriesDialog(
val singleFile = jetFiles.singleOrNull()
isSelected = singleFile == null || singleFile.packageMatchesDirectoryOrImplicit()
text = "Update package directive (Kotlin files)"
text = KotlinBundle.message("checkbox.text.update.package.directive")
}
}
@@ -169,7 +172,7 @@ class KotlinAwareMoveFilesOrDirectoriesDialog(
val elementsToMove = directory?.let { existentDirectory ->
val choice = if (psiElements.size > 1 || psiElements[0] is PsiDirectory) intArrayOf(-1) else null
psiElements.filterNot {
it is PsiFile && CopyFilesOrDirectoriesHandler.checkFileExist(existentDirectory, choice, it, it.name, "Move")
it is PsiFile && CopyFilesOrDirectoriesHandler.checkFileExist(existentDirectory, choice, it, it.name, title)
}
} ?: psiElements.toList()
@@ -15,6 +15,7 @@ import com.intellij.psi.PsiFileSystemItem
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.refactoring.isInKotlinAwareSourceRoot
import org.jetbrains.kotlin.idea.refactoring.move.getOrCreateDirectory
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.KotlinAwareMoveFilesOrDirectoriesProcessor
@@ -64,7 +65,7 @@ class KotlinAwareMoveFilesOrDirectoriesModel(
try {
return getOrCreateDirectory(targetDirectoryName, project)
} catch (e: IncorrectOperationException) {
throw ConfigurationException("Cannot create target directory $targetDirectoryName")
throw ConfigurationException(KotlinBundle.message("text.cannot.create.target.directory.0", targetDirectoryName))
}
}
@@ -74,21 +75,21 @@ class KotlinAwareMoveFilesOrDirectoriesModel(
private fun checkModel() {
elementsToMove.firstOrNull { it !is PsiFile && it !is PsiDirectory }?.let {
throw ConfigurationException("Unexpected element type: $it")
throw ConfigurationException(KotlinBundle.message("text.unexpected.element.type.0", it))
}
if (elementsToMove.isEmpty()) {
throw ConfigurationException("There is no given files to move")
throw ConfigurationException(KotlinBundle.message("text.no.files.to.move"))
}
try {
Paths.get(targetDirectoryName)
} catch (e: InvalidPathException) {
throw ConfigurationException("Invalid target path $targetDirectoryName")
throw ConfigurationException(KotlinBundle.message("text.invalid.target.path.0", targetDirectoryName))
}
if (DumbService.isDumb(project)) {
throw ConfigurationException("Move refactoring is not available while indexing is in progress")
throw ConfigurationException(KotlinBundle.message("text.move.refactoring.not.available.during.indexing"))
}
}
@@ -11,6 +11,7 @@ import com.intellij.openapi.ui.DialogWrapper
import com.intellij.psi.PsiElement
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.util.RadioUpDownListener
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtEnumEntry
@@ -40,10 +41,10 @@ internal class KotlinSelectNestedClassRefactoringDialog private constructor(
}
override fun createCenterPanel(): JComponent? {
moveToUpperLevelButton.text = BundleBase.replaceMnemonicAmpersand("Move &nested class ${nestedClass.name} to upper level")
moveToUpperLevelButton.text = KotlinBundle.message("button.text.move.nested.class.0.to.upper.level", nestedClass.name.toString())
moveToUpperLevelButton.isSelected = true
moveMembersButton.text = BundleBase.replaceMnemonicAmpersand("&Move nested class ${nestedClass.name} to another class")
moveMembersButton.text = KotlinBundle.message("button.text.move.nested.class.0.to.another.class", nestedClass.name.toString())
ButtonGroup().apply {
add(moveToUpperLevelButton)
@@ -11,6 +11,7 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.move.MoveCallback
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
@@ -25,10 +26,10 @@ internal class MoveKotlinNestedClassesModel(
) : Model<MoveKotlinDeclarationsProcessor> {
private fun getCheckedTargetClass(): KtElement {
val targetClass = this.targetClass ?: throw ConfigurationException("No destination class specified")
val targetClass = this.targetClass ?: throw ConfigurationException(RefactoringBundle.message("no.destination.class.specified"))
if (targetClass !is KtClassOrObject) {
throw ConfigurationException("Destination class must be a Kotlin class")
throw ConfigurationException(KotlinBundle.message("text.destination.class.should.be.kotlin.class"))
}
if (originalClass === targetClass) {
@@ -37,7 +38,9 @@ internal class MoveKotlinNestedClassesModel(
for (classOrObject in selectedElementsToMove) {
if (PsiTreeUtil.isAncestor(classOrObject, targetClass, false)) {
throw ConfigurationException("Cannot move nested class ${classOrObject.name} to itself")
throw ConfigurationException(
KotlinBundle.message("text.cannot.move.inner.class.0.into.itself", classOrObject.name.toString())
)
}
}
@@ -80,7 +80,7 @@
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Packa&amp;ge name:"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="label.text.package.name"/>
</properties>
</component>
<component id="18010" class="com.intellij.refactoring.ui.PackageNameReferenceEditorCombo" binding="packageNameField" custom-create="true">
@@ -24,6 +24,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils;
import org.jetbrains.kotlin.idea.core.CollectingNameValidator;
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester;
@@ -73,7 +74,7 @@ public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase {
this.innerClass = innerClass;
this.targetContainer = targetContainer;
this.innerClassDescriptor = (ClassDescriptor) ResolutionUtils.unsafeResolveToDescriptor(innerClass, BodyResolveMode.FULL);
setTitle("Move Nested Classes to Upper Level");
setTitle(KotlinBundle.message("title.move.nested.classes.to.upper.level"));
init();
packageNameLabel.setLabelFor(packageNameField.getChildComponent());
classNameLabel.setLabelFor(classNameField);
@@ -89,7 +90,7 @@ public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase {
@Override
protected String getMovePropertySuffix() {
return "Nested Classes to Upper Level";
return KotlinBundle.message("text.nested.classes.to.upper.level");
}
@Override
@@ -99,7 +100,7 @@ public class MoveKotlinNestedClassesToUpperLevelDialog extends MoveDialogBase {
@Override
protected String getCbTitle() {
return "Open moved member in editor";
return KotlinBundle.message("checkbox.text.open.moved.files.in.editor");
}
public String getClassName() {
@@ -20,6 +20,7 @@ import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.util.RefactoringMessageUtil
import com.intellij.refactoring.util.RefactoringUtil
import com.intellij.util.IncorrectOperationException
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
@@ -135,14 +136,16 @@ internal abstract class MoveKotlinNestedClassesToUpperLevelModel(
if (targetContainer is PsiDirectory || targetContainer is KtFile) {
val targetPackageFqName = getTargetPackageFqName(target)
?: throw ConfigurationException("No package corresponds to this directory")
?: throw ConfigurationException(KotlinBundle.message("text.no.package.corresponds.to.directory"))
val existingClass = innerClassDescriptor?.let { DescriptorUtils.getContainingModule(it) }
?.getPackage(targetPackageFqName)
?.memberScope
?.getContributedClassifier(Name.identifier(className), NoLookupLocation.FROM_IDE)
if (existingClass != null) {
throw ConfigurationException("Class $className already exists in package $targetPackageFqName")
throw ConfigurationException(
KotlinBundle.message("text.class.0.already.exists.in.package.1", className, targetPackageFqName)
)
}
val targetDir = targetContainer as? PsiDirectory ?: targetContainer.containingFile.containingDirectory
@@ -150,7 +153,7 @@ internal abstract class MoveKotlinNestedClassesToUpperLevelModel(
if (message != null) throw ConfigurationException(message)
}
return targetContainer ?: throw ConfigurationException("Invalid target specified")
return targetContainer ?: throw ConfigurationException(KotlinBundle.message("text.invalid.target.specified"))
}
@Throws(ConfigurationException::class)
@@ -158,7 +161,7 @@ internal abstract class MoveKotlinNestedClassesToUpperLevelModel(
val target = getTargetContainerWithValidation()
if (target is PsiDirectory) {
val targetPackageFqName = getTargetPackageFqName(target)
?: throw ConfigurationException("Cannot find target package name")
?: throw ConfigurationException(KotlinBundle.message("text.cannot.find.target.package.name"))
val suggestedName = KotlinNameSuggester.suggestNameByName(className) {
target.findFile(it + "." + KotlinFileType.EXTENSION) == null
@@ -45,7 +45,7 @@
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="To p&amp;ackage:"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="label.text.to.package"/>
</properties>
</component>
<component id="9ea97" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="fileChooser">
@@ -59,7 +59,7 @@
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="To &amp;file:"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="label.text.to.file"/>
</properties>
</component>
<component id="67853" class="javax.swing.JTextField" binding="tfFileNameInPackage" default-binding="true">
@@ -79,7 +79,7 @@
<properties>
<horizontalAlignment value="2"/>
<horizontalTextPosition value="11"/>
<text value="File &amp;name:"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="label.text.file.name"/>
</properties>
</component>
<grid id="ce694" binding="targetPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
@@ -96,7 +96,7 @@
</constraints>
<properties>
<labelFor value="36327"/>
<text value="&amp;Destination directory:"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="label.text.destination.directory"/>
</properties>
</component>
<component id="36327" class="com.intellij.ui.ComboboxWithBrowseButton" binding="destinationFolderCB" custom-create="true">
@@ -113,7 +113,7 @@
</constraints>
<properties>
<selected value="true"/>
<text value="&amp;Update package directive"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="label.text.update.package.directive"/>
</properties>
</component>
<grid id="69aba" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
@@ -148,7 +148,7 @@
</constraints>
<properties>
<selected value="true"/>
<text value="Search &amp;references"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="checkbox.text.search.references"/>
</properties>
</component>
<component id="cc60e" class="javax.swing.JCheckBox" binding="cbDeleteEmptySourceFiles">
@@ -157,7 +157,7 @@
</constraints>
<properties>
<selected value="true"/>
<text value="&amp;Delete empty source files"/>
<text resource-bundle="org/jetbrains/kotlin/idea/KotlinBundle" key="checkbox.text.delete.empty.source.files"/>
</properties>
</component>
</children>
@@ -31,6 +31,7 @@ import com.intellij.util.ui.UIUtil;
import kotlin.collections.CollectionsKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.KotlinBundle;
import org.jetbrains.kotlin.idea.core.PackageUtilsKt;
import org.jetbrains.kotlin.idea.core.util.PhysicalFileSystemUtilsKt;
import org.jetbrains.kotlin.idea.refactoring.KotlinRefactoringSettings;
@@ -268,7 +269,10 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
}
fileChooser.addActionListener(e -> {
KotlinFileChooserDialog dialog = new KotlinFileChooserDialog("Choose Containing File", myProject);
KotlinFileChooserDialog dialog = new KotlinFileChooserDialog(
KotlinBundle.message("text.choose.containing.file"),
myProject
);
File targetFile1 = new File(fileChooser.getText());
PsiFile targetPsiFile = PhysicalFileSystemUtilsKt.toPsiFile(targetFile1, myProject);
@@ -387,7 +391,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog {
private List<KtNamedDeclaration> getSelectedElementsToMoveChecked() throws ConfigurationException {
List<KtNamedDeclaration> elementsToMove = getSelectedElementsToMove();
if (elementsToMove.isEmpty()) {
throw new ConfigurationException("No elements to move are selected");
throw new ConfigurationException(KotlinBundle.message("text.no.elements.to.move.are.selected"));
}
return elementsToMove;
}
@@ -6,20 +6,23 @@
package org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.ui
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.options.ConfigurationException
import com.intellij.psi.*
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDirectory
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiNameHelper
import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.MoveDestination
import com.intellij.refactoring.PackageWrapper
import com.intellij.refactoring.move.MoveCallback
import com.intellij.refactoring.move.moveClassesOrPackages.AutocreatingSingleSourceRootMoveDestination
import com.intellij.refactoring.move.moveClassesOrPackages.MultipleRootsMoveDestination
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.core.getPackage
import org.jetbrains.kotlin.idea.core.util.toPsiDirectory
import org.jetbrains.kotlin.idea.core.util.toPsiFile
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.refactoring.getOrCreateKotlinFile
import org.jetbrains.kotlin.idea.refactoring.move.getOrCreateDirectory
import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*
@@ -51,8 +54,8 @@ internal class MoveKotlinTopLevelDeclarationsModel(
private inline fun <T, K> Set<T>.mapToSingleOrNull(transform: (T) -> K?): K? =
mapTo(mutableSetOf(), transform).singleOrNull()
private fun checkedGetSourceDirectory() =
sourceFiles.mapToSingleOrNull { it.parent } ?: throw ConfigurationException("Can't determine sources directory")
private fun checkedGetSourceDirectory() = sourceFiles.mapToSingleOrNull { it.parent }
?: throw ConfigurationException(KotlinBundle.message("text.cannot.determine.source.directory"))
private val sourceFiles: Set<KtFile> = elementsToMove.mapTo(mutableSetOf()) { it.containingKtFile }
@@ -134,7 +137,7 @@ internal class MoveKotlinTopLevelDeclarationsModel(
val targetFile = try {
Paths.get(targetFilePath).toFile()
} catch (e: InvalidPathException) {
throw ConfigurationException("Invalid target path $targetFilePath")
throw ConfigurationException(KotlinBundle.message("text.invalid.target.path.0", targetFilePath))
}
checkTargetFileName(targetFile.name)
@@ -142,7 +145,7 @@ internal class MoveKotlinTopLevelDeclarationsModel(
val jetFile = targetFile.toPsiFile(project) as? KtFile
if (jetFile != null) {
if (sourceFiles.singleOrNull() == jetFile) {
throw ConfigurationException("Can't move to the original file")
throw ConfigurationException(KotlinBundle.message("text.cannot.move.to.original.file"))
}
return KotlinMoveTargetForExistingElement(jetFile)
}
@@ -151,17 +154,21 @@ internal class MoveKotlinTopLevelDeclarationsModel(
?: throw ConfigurationException("Incorrect target path. Directory is not specified.")
val projectBasePath = project.basePath
?: throw ConfigurationException("Can't move for current project")
?: throw ConfigurationException(KotlinBundle.message("text.cannot.move.for.current.project"))
if (!targetDirectoryPath.startsWith(projectBasePath)) {
throw ConfigurationException("Incorrect target path. Directory $targetDirectoryPath does not belong to current project.")
throw ConfigurationException(
KotlinBundle.message("text.incorrect.target.path.directory.0.does.not.belong.to.current.project", targetDirectoryPath)
)
}
val psiDirectory = targetDirectoryPath.toFile().toPsiDirectory(project)
val targetPackageFqName = sourceFiles.singleOrNull()?.packageFqName
?: psiDirectory?.getPackage()?.let { FqName(it.qualifiedName) }
?: throw ConfigurationException("Could not find package corresponding to $targetDirectoryPath")
?: throw ConfigurationException(
KotlinBundle.message("text.cannot.find.package.corresponding.to.0", targetDirectoryPath)
)
val targetDirectoryPathString = targetDirectoryPath.toString()
val finalTargetPackageFqName = targetPackageFqName.asString()
@@ -180,14 +187,13 @@ internal class MoveKotlinTopLevelDeclarationsModel(
if (isMoveToPackage) selectMoveTargetToPackage() else selectMoveTargetToFile()
private fun verifyBeforeRun() {
if (elementsToMove.isEmpty()) throw ConfigurationException("At least one member must be selected")
if (elementsToMove.isEmpty()) throw ConfigurationException(KotlinBundle.message("text.at.least.one.file.must.be.selected"))
if (sourceFiles.isEmpty()) throw ConfigurationException("None elements were selected")
if (singleSourceFileMode && fileNameInPackage.isBlank()) throw ConfigurationException("File name may not be empty")
if (singleSourceFileMode && fileNameInPackage.isBlank()) throw ConfigurationException(KotlinBundle.message("text.file.name.cannot.be.empty"))
if (isMoveToPackage) {
if (targetPackage.isNotEmpty() && !PsiNameHelper.getInstance(project).isQualifiedName(targetPackage)) {
throw ConfigurationException("\'$targetPackage\' is invalid destination package name")
throw ConfigurationException(KotlinBundle.message("text.0.is.invalid.destination.package", targetPackage))
}
} else {
val targetFile = File(targetFilePath).toPsiFile(project)
@@ -16,6 +16,7 @@ import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectori
import com.intellij.usageView.UsageInfo
import com.intellij.util.Function
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.core.getFqNameWithImplicitPrefix
import org.jetbrains.kotlin.idea.core.getPackage
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
@@ -76,7 +77,7 @@ class KotlinMoveDirectoryWithClassesHelper : MoveDirectoryWithClassesHelper() {
for ((index, usageInfo) in infos.withIndex()) {
if (usageInfo !is FileUsagesWrapper) continue
ProgressManager.getInstance().progressIndicator?.text2 = "Processing ${usageInfo.psiFile.name}"
ProgressManager.getInstance().progressIndicator?.text2 = KotlinBundle.message("text.processing.file.0", usageInfo.psiFile.name)
runReadAction {
analyzeConflictsInFile(usageInfo.psiFile, usageInfo.usages, moveTarget, files, conflicts) {
@@ -23,6 +23,7 @@ import com.intellij.util.SmartList
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.asJava.unwrapped
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithAllCompilerChecks
@@ -520,7 +521,7 @@ fun postProcessMoveUsages(
val progressStep = 1.0 / sortedUsages.size
val progressIndicator = ProgressManager.getInstance().progressIndicator
progressIndicator?.text = "Updating usages..."
progressIndicator?.text = KotlinBundle.message("text.updating.usages.progress")
usageLoop@ for ((i, usage) in sortedUsages.withIndex()) {
progressIndicator?.fraction = (i + 1) * progressStep
postProcessMoveUsage(usage, oldToNewElementsMapping, nonCodeUsages, shorteningMode)
@@ -537,7 +538,7 @@ sealed class OuterInstanceReferenceUsageInfo(element: PsiElement, private val is
val element = element ?: return false
if (isIndirectOuter) {
conflicts.putValue(element, "Indirect outer instances won't be extracted: ${element.text}")
conflicts.putValue(element, KotlinBundle.message("text.indirect.outer.instances.will.not.be.extracted.0", element.text))
return true
}
@@ -566,12 +567,12 @@ sealed class OuterInstanceReferenceUsageInfo(element: PsiElement, private val is
val fullCall = callElement?.let { it.getQualifiedExpressionForSelector() ?: it } ?: return false
return when {
fullCall is KtQualifiedExpression -> {
conflicts.putValue(fullCall, "Qualified call won't be processed: ${fullCall.text}")
conflicts.putValue(fullCall, KotlinBundle.message("text.qualified.call.will.not.be.processed.0", fullCall.text))
true
}
isDoubleReceiver -> {
conflicts.putValue(fullCall, "Member extension call won't be processed: ${fullCall.text}")
conflicts.putValue(fullCall, KotlinBundle.message("text.member.extension.call.will.not.be.processed.0", fullCall.text))
true
}
else -> false