Merge branch master into pr/269
This commit is contained in:
-11
@@ -1,11 +0,0 @@
|
||||
public class MyClass {
|
||||
public fun f(a: Int): String {
|
||||
var res: String
|
||||
|
||||
if (a == 1) res = "one";
|
||||
else if (a == 2) res = "two";
|
||||
else res = "too many";
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
public class MyClass {
|
||||
public fun f(a: Int): String {
|
||||
var res: String
|
||||
|
||||
res = if (a == 1) "one";
|
||||
else if (a == 2) "two";
|
||||
else "too many";
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts assignment with 'if' expression as right-hand side
|
||||
into 'if' statement where each branch is terminated with assignment to the original variable
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
when {
|
||||
n == 1 -> {
|
||||
res = "one"
|
||||
}
|
||||
n == 2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention eliminates argument of 'when' expression transforming its pattern-matching conditions into boolean expressions
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,17 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
3 -> {
|
||||
res = "three"
|
||||
}
|
||||
4 -> {
|
||||
res = "four"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> when (n) {
|
||||
3 -> {
|
||||
res = "thress"
|
||||
}
|
||||
4 -> {
|
||||
res = "four"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention merges branches of nested 'when' expression into enclosing one
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
res = if (ok) {
|
||||
"ok"
|
||||
} else {
|
||||
"failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
if (ok) {
|
||||
res = "ok"
|
||||
} else {
|
||||
res = "failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'if' expression where each branch is terminated with assignment into a single assignment with 'if' expression as a right-hand side
|
||||
</body>
|
||||
</html>
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
return if (ok) {
|
||||
"ok"
|
||||
} else "failed"
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
if (ok) {
|
||||
return "ok"
|
||||
}
|
||||
return "failed"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts single-branch 'if' expression immediately followed by 'return' into a single 'return' with 'if' expression as an argument
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
return if (ok) {
|
||||
"ok"
|
||||
} else {
|
||||
"failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
if (ok) {
|
||||
return "ok"
|
||||
} else {
|
||||
return "failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'if' expression where each branch is terminated with 'return' into a single 'return' with 'if' expression as a right-hand side
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
res = when (n) {
|
||||
1 -> "one"
|
||||
2 -> "two"
|
||||
else -> "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
when (n) {
|
||||
1 -> res = "one"
|
||||
2 -> res = "two"
|
||||
else -> res = "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'when' expression where each branch is terminated with assignment into a single assignment with 'when' expression as right-hand side
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
return when (n) {
|
||||
1 -> "one"
|
||||
2 -> "two"
|
||||
else -> "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
when (n) {
|
||||
1 -> return "one"
|
||||
2 -> return "two"
|
||||
else -> return "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'when' expression where each branch is terminated with 'return' into a single 'return' with 'when' expression as a right-hand side
|
||||
</body>
|
||||
</html>
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
public class MyClass {
|
||||
public fun f(a: Int): String {
|
||||
var res: String
|
||||
|
||||
res = if (a == 1) "one";
|
||||
else if (a == 2) "two";
|
||||
else "too many";
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
public class MyClass {
|
||||
public fun f(a: Int): String {
|
||||
var res: String
|
||||
|
||||
if (a == 1) res = "one";
|
||||
else if (a == 2) res = "two";
|
||||
else res = "too many";
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'if' statement where each branch is terminated with assignment to the same variable
|
||||
into single assignment with 'if' expression
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
if (n == 1) {
|
||||
res = "one"
|
||||
} else if (n == 2) {
|
||||
res = "two"
|
||||
} else {
|
||||
res = "???"
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'if' expression to equivalent 'when' expression
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,11 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
when {
|
||||
n == 1 -> {
|
||||
res = "one"
|
||||
}
|
||||
n == 2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention introduces argument into 'when' expression simplifying conditions of its branches
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
if (ok) {
|
||||
res = "ok"
|
||||
} else {
|
||||
res = "failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
res = if (ok) {
|
||||
"ok"
|
||||
} else {
|
||||
"failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts assignment with 'if' right-hand side to 'if' expression where each branch is terminated with assignment
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
when (n) {
|
||||
1 -> res = "one"
|
||||
2 -> res = "two"
|
||||
else -> res = "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
res = when (n) {
|
||||
1 -> "one"
|
||||
2 -> "two"
|
||||
else -> "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts assignment with 'when' right-hand side to 'when' expression where each branch is terminated with assignment
|
||||
</body>
|
||||
</html>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
val res: String
|
||||
if (ok) {
|
||||
res = "ok"
|
||||
} else {
|
||||
res = "failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val res = if (ok) {
|
||||
"ok"
|
||||
} else {
|
||||
"failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts property with 'if' initializer to uninitialized property followed by 'if' expression where each branch is terminated with assignment
|
||||
</body>
|
||||
</html>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
val res: String
|
||||
when (n) {
|
||||
1 -> res = "one"
|
||||
2 -> res = "two"
|
||||
else -> res = "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
val res = when (n) {
|
||||
1 -> "one"
|
||||
2 -> "two"
|
||||
else -> "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts property with 'when' initializer to uninitialized property followed by 'when' expression where each branch is terminated with assignment
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
if (ok) {
|
||||
return "ok"
|
||||
} else {
|
||||
return "failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
return if (ok) {
|
||||
"ok"
|
||||
} else {
|
||||
"failed"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'return' with 'if' expression as a result to 'if' expression where each branch is terminated with 'return'
|
||||
</body>
|
||||
</html>
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
when (n) {
|
||||
1 -> return "one"
|
||||
2 -> return "two"
|
||||
else -> return "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
return when (n) {
|
||||
1 -> "one"
|
||||
2 -> "two"
|
||||
else -> "many"
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'return' with 'when' expression as a result to 'when' expression where each branch is terminated with 'return'
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
if (n == 1) {
|
||||
res = "one"
|
||||
} else if (n == 2) {
|
||||
res = "two"
|
||||
} else {
|
||||
res = "???"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
when (n) {
|
||||
1 -> {
|
||||
res = "one"
|
||||
}
|
||||
2 -> {
|
||||
res = "two"
|
||||
}
|
||||
else -> {
|
||||
res = "???"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention converts 'when' expression to one or more 'if' expressions
|
||||
</body>
|
||||
</html>
|
||||
@@ -219,6 +219,8 @@
|
||||
forClass="org.jetbrains.jet.lang.psi.JetClass"/>
|
||||
<itemPresentationProvider implementationClass="org.jetbrains.jet.plugin.presentation.JetPropertyPresenter"
|
||||
forClass="org.jetbrains.jet.lang.psi.JetProperty"/>
|
||||
<itemPresentationProvider implementationClass="org.jetbrains.jet.plugin.presentation.JetParameterPresenter"
|
||||
forClass="org.jetbrains.jet.lang.psi.JetParameter"/>
|
||||
<gotoTargetRendererProvider id="JetGotoTargetRenderProvider" implementation="org.jetbrains.jet.plugin.JetGotoTargetRenderProvider"
|
||||
order="first"/>
|
||||
<elementDescriptionProvider implementation="org.jetbrains.jet.plugin.findUsages.JetElementDescriptionProvider"/>
|
||||
@@ -281,6 +283,14 @@
|
||||
serviceImplementation="org.jetbrains.jet.plugin.editor.JetEditorOptions"/>
|
||||
<editorAppearanceConfigurable instance="org.jetbrains.jet.plugin.editor.JetSettingEditorConfigurable"/>
|
||||
|
||||
<statementUpDownMover id="jetExpression"
|
||||
implementation="org.jetbrains.jet.plugin.codeInsight.upDownMover.JetExpressionMover"
|
||||
order="before declaration" />
|
||||
|
||||
<statementUpDownMover id="jetDeclaration"
|
||||
implementation="org.jetbrains.jet.plugin.codeInsight.upDownMover.JetDeclarationMover"
|
||||
order="before jetExpression" />
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.intentions.SpecifyTypeExplicitlyAction</className>
|
||||
<category>Kotlin</category>
|
||||
@@ -292,12 +302,82 @@
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.IfStatementWithAssignmentsToExpressionIntention</className>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.FoldBranchedExpressionIntention$FoldIfToAssignmentIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.AssignmentWithIfExpressionToStatementIntention</className>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.FoldBranchedExpressionIntention$FoldIfToReturnAsymmetricallyIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.FoldBranchedExpressionIntention$FoldIfToReturnIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.FoldBranchedExpressionIntention$FoldWhenToAssignmentIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.FoldBranchedExpressionIntention$FoldWhenToReturnIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.UnfoldBranchedExpressionIntention$UnfoldAssignmentToIfIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.UnfoldBranchedExpressionIntention$UnfoldPropertyToIfIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.UnfoldBranchedExpressionIntention$UnfoldAssignmentToWhenIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.UnfoldBranchedExpressionIntention$UnfoldPropertyToWhenIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.UnfoldBranchedExpressionIntention$UnfoldReturnToIfIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.UnfoldBranchedExpressionIntention$UnfoldReturnToWhenIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.IfToWhenIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.WhenToIfIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.FlattenWhenIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.IntroduceWhenSubjectIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
<intentionAction>
|
||||
<className>org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions.EliminateWhenSubjectIntention</className>
|
||||
<category>Kotlin</category>
|
||||
</intentionAction>
|
||||
|
||||
|
||||
@@ -59,9 +59,12 @@ add.semicolon.after.invocation=Add semicolon after invocation of ''{0}''
|
||||
add.semicolon.family=Add Semicolon
|
||||
change.function.return.type=Change ''{0}'' function return type to ''{1}''
|
||||
change.no.name.function.return.type=Change function return type to ''{0}''
|
||||
change.function.literal.return.type=Change function literal return type to ''{0}''
|
||||
remove.function.return.type=Remove explicitly specified return type in ''{0}'' function
|
||||
remove.no.name.function.return.type=Remove explicitly specified function return type
|
||||
change.element.type=Change ''{0}'' type to ''{1}''
|
||||
change.function.parameter.type=Change parameter ''{0}'' type of function ''{1}'' to ''{2}''
|
||||
change.primary.constructor.parameter.type=Change parameter ''{0}'' type of primary constructor of class ''{1}'' to ''{2}''
|
||||
change.type=Change type from ''{0}'' to ''{1}''
|
||||
change.type.family=Change Type
|
||||
add.parameters.to.function=Add parameter{0} to function ''{1}''
|
||||
@@ -110,6 +113,8 @@ options.jet.attribute.descriptor.closure.braces=Function literal braces and arro
|
||||
options.jet.attribute.descriptor.safe.access=Safe access dot
|
||||
options.jet.attribute.descriptor.arrow=Arrow
|
||||
options.jet.attribute.descriptor.kdoc.comment=KDoc comment
|
||||
options.jet.attribute.descriptor.kdoc.tag=KDoc tag
|
||||
options.jet.attribute.descriptor.kdoc.value=KDoc tag value
|
||||
options.jet.attribute.descriptor.trait=Trait
|
||||
options.jet.attribute.descriptor.annotation=Annotation
|
||||
options.jet.attribute.descriptor.var=Var (mutable variable, parameter or property)
|
||||
@@ -154,6 +159,44 @@ surround.with.cannot.perform.action=Cannot perform Surround With action to the c
|
||||
remove.variable.family.name=Remove variable
|
||||
remove.variable.action=Remove variable ''{0}''
|
||||
kotlin.code.transformations=Kotlin Code Transformations
|
||||
fold.if.to.assignment=Replace 'if' expression with assignment
|
||||
fold.if.to.assignment.family=Replace 'if' Expression with Assignment
|
||||
fold.if.to.return=Replace 'if' expression with return
|
||||
fold.if.to.return.family=Replace 'if' Expression with Return
|
||||
fold.if.to.call=Replace 'if' expression with method call
|
||||
fold.if.to.call.family=Replace 'if' Expression with Method Call
|
||||
fold.when.to.assignment=Replace 'when' expression with assignment
|
||||
fold.when.to.assignment.family=Replace 'when' Expression with Assignment
|
||||
fold.when.to.return=Replace 'when' expression with return
|
||||
fold.when.to.return.family=Replace 'when' Expression with Return
|
||||
fold.when.to.call=Replace 'when' expression with method call
|
||||
fold.when.to.call.family=Replace 'when' Expression with Method Call
|
||||
unfold.assignment.to.if=Replace assignment with 'if' expression
|
||||
unfold.assignment.to.if.family=Replace Assignment with 'if' Expression
|
||||
unfold.property.to.if=Replace property initializer with 'if' expression
|
||||
unfold.property.to.if.family=Replace Property Initializer with 'if' Expression
|
||||
unfold.return.to.if=Replace return with 'if' expression
|
||||
unfold.return.to.if.family=Replace Return with 'if' Expression
|
||||
unfold.call.to.if=Replace method call with 'if' expression
|
||||
unfold.call.to.if.family=Replace Method Call with 'if' Expression
|
||||
unfold.assignment.to.when=Replace assignment with 'when' expression
|
||||
unfold.assignment.to.when.family=Replace Assignment with 'when' Expression
|
||||
unfold.property.to.when=Replace property initializer with 'when' expression
|
||||
unfold.property.to.when.family=Replace Property Initializer with 'when' Expression
|
||||
unfold.return.to.when=Replace return with 'when' expression
|
||||
unfold.return.to.when.family=Replace Return with 'when' Expression
|
||||
unfold.call.to.when=Replace method call with 'when' expression
|
||||
unfold.call.to.when.family=Replace Method Call with 'when' Expression
|
||||
if.to.when=Replace 'if' with 'when'
|
||||
if.to.when.family=Replace 'if' with 'when'
|
||||
when.to.if=Replace 'when' with 'if'
|
||||
when.to.if.family=Replace 'when' with 'if'
|
||||
flatten.when=Flatten 'when' expression
|
||||
flatten.when.family=Flatten 'when' Expression
|
||||
introduce.when.subject=Introduce argument to 'when'
|
||||
introduce.when.subject.family=Introduce Argument to 'when'
|
||||
eliminate.when.subject=Eliminate argument of 'when'
|
||||
eliminate.when.subject.family=Eliminate Argument of 'when'
|
||||
transform.if.statement.with.assignments.to.expression=Transform 'if' statement with assignments to expression
|
||||
transform.assignment.with.if.expression.to.statement=Transform assignment with 'if' expression to statement
|
||||
transform.if.statement.with.assignments.to.expression.family=Transform 'if' Statement with Assignments to Expression
|
||||
@@ -164,4 +207,22 @@ change.function.signature.family=Change function signature
|
||||
change.function.signature.chooser.title=Choose signature
|
||||
change.function.signature.action=Change function signature
|
||||
remove.unnecessary.parentheses=Remove unnecessary parentheses
|
||||
remove.unnecessary.parentheses.family=Remove Unnecessary Parentheses
|
||||
remove.unnecessary.parentheses.family=Remove Unnecessary Parentheses
|
||||
add.name.to.argument.family=Add Name to Argument
|
||||
add.name.to.argument.single=Add name to argument\: ''{0}''
|
||||
add.name.to.argument.multiple=Add name to argument...
|
||||
add.name.to.argument.action=Add name to argument...
|
||||
add.name.to.parameter.name.chooser.title=Choose parameter name
|
||||
|
||||
property.is.implemented.too.many=Has implementations
|
||||
property.is.overridden.too.many=Is overridden in subclasses
|
||||
property.is.implemented.header=Is implemented in <br/>
|
||||
property.is.overridden.header=Is overridden in <br/>
|
||||
|
||||
navigation.title.overriding.property=Choose Implementation of {0}
|
||||
navigation.findUsages.title.overriding.property=Overriding properties of {0}
|
||||
add.function.to.supertype.family=Add Function to Supertype
|
||||
add.function.to.supertype.action.multiple=Add function to supertype...
|
||||
add.function.to.type.action.single=Add ''{0}'' to ''{1}''
|
||||
add.function.to.type.action=Add function to type
|
||||
add.function.to.type.action.type.chooser=Choose type...
|
||||
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
package org.jetbrains.jet.plugin;
|
||||
|
||||
import com.intellij.lang.Commenter;
|
||||
import com.intellij.lang.CodeDocumentationAwareCommenter;
|
||||
import com.intellij.psi.PsiComment;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.jet.kdoc.psi.api.KDoc;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetCommenter implements Commenter {
|
||||
public class JetCommenter implements CodeDocumentationAwareCommenter {
|
||||
@Override
|
||||
public String getLineCommentPrefix() {
|
||||
return "//";
|
||||
@@ -43,4 +47,39 @@ public class JetCommenter implements Commenter {
|
||||
public String getCommentedBlockCommentSuffix() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IElementType getLineCommentTokenType() {
|
||||
return JetTokens.EOL_COMMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IElementType getBlockCommentTokenType() {
|
||||
return JetTokens.BLOCK_COMMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IElementType getDocumentationCommentTokenType() {
|
||||
return JetTokens.DOC_COMMENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDocumentationCommentPrefix() {
|
||||
return "/**";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDocumentationCommentLinePrefix() {
|
||||
return "*";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDocumentationCommentSuffix() {
|
||||
return "*/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDocumentationComment(PsiComment element) {
|
||||
return element instanceof KDoc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,12 +143,10 @@ public class JetIconProvider extends IconProvider {
|
||||
}
|
||||
if (psiElement instanceof JetParameter) {
|
||||
JetParameter parameter = (JetParameter) psiElement;
|
||||
if (parameter.getValOrVarNode() != null) {
|
||||
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
|
||||
if (parameterList != null && parameterList.getParent() instanceof JetClass) {
|
||||
return parameter.isMutable() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL;
|
||||
}
|
||||
if (JetPsiUtil.getClassIfParameterIsProperty(parameter) != null) {
|
||||
return parameter.isMutable() ? JetIcons.FIELD_VAR : JetIcons.FIELD_VAL;
|
||||
}
|
||||
|
||||
return JetIcons.PARAMETER;
|
||||
}
|
||||
if (psiElement instanceof JetProperty) {
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.kdoc.lexer.KDocTokens;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetPairMatcher implements PairedBraceMatcher {
|
||||
@@ -29,7 +30,8 @@ public class JetPairMatcher implements PairedBraceMatcher {
|
||||
new BracePair(JetTokens.LPAR, JetTokens.RPAR, false),
|
||||
new BracePair(JetTokens.LONG_TEMPLATE_ENTRY_START, JetTokens.LONG_TEMPLATE_ENTRY_END, false),
|
||||
new BracePair(JetTokens.LBRACE, JetTokens.RBRACE, true),
|
||||
new BracePair(JetTokens.LBRACKET, JetTokens.RBRACKET, false)
|
||||
new BracePair(JetTokens.LBRACKET, JetTokens.RBRACKET, false),
|
||||
new BracePair(KDocTokens.WIKI_LINK_OPEN, KDocTokens.WIKI_LINK_CLOSE, false)
|
||||
};
|
||||
|
||||
@Override
|
||||
@@ -39,7 +41,14 @@ public class JetPairMatcher implements PairedBraceMatcher {
|
||||
|
||||
@Override
|
||||
public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType lbraceType, @Nullable IElementType contextType) {
|
||||
return JetTokens.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(contextType)
|
||||
if (lbraceType.equals(JetTokens.LONG_TEMPLATE_ENTRY_START)) {
|
||||
// KotlinTypedHandler insert paired brace in this case
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lbraceType == KDocTokens.WIKI_LINK_OPEN) return false;
|
||||
|
||||
return JetTokens.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(contextType)
|
||||
|| contextType == JetTokens.SEMICOLON
|
||||
|| contextType == JetTokens.COMMA
|
||||
|| contextType == JetTokens.RPAR
|
||||
|
||||
@@ -44,11 +44,11 @@ public class JetPluginUtil {
|
||||
|
||||
LinkedList<String> fullName = Lists.newLinkedList();
|
||||
while (declarationDescriptor != null && !(declarationDescriptor instanceof ModuleDescriptor)) {
|
||||
fullName.addFirst(declarationDescriptor.getName().getName());
|
||||
fullName.addFirst(declarationDescriptor.getName().asString());
|
||||
declarationDescriptor = declarationDescriptor.getContainingDeclaration();
|
||||
}
|
||||
assert fullName.size() > 0;
|
||||
if (JavaDescriptorResolver.JAVA_ROOT.getName().equals(fullName.getFirst())) {
|
||||
if (JavaDescriptorResolver.JAVA_ROOT.asString().equals(fullName.getFirst())) {
|
||||
fullName.removeFirst();
|
||||
}
|
||||
return fullName;
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.actions;
|
||||
|
||||
import com.intellij.codeInsight.hint.QuestionAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.ListPopupStep;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassKind;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.Modality;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetClassBody;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.DescriptorToDeclarationUtil;
|
||||
import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Changes method signature to one of provided signatures.
|
||||
* Based on {@link JetAddImportAction}
|
||||
*/
|
||||
public class JetAddFunctionToClassifierAction implements QuestionAction {
|
||||
private final List<FunctionDescriptor> functionsToAdd;
|
||||
private final Project project;
|
||||
private final Editor editor;
|
||||
private final BindingContext bindingContext;
|
||||
|
||||
/**
|
||||
* @param project Project where action takes place.
|
||||
* @param editor Editor where modification should be done.
|
||||
* @param bindingContext BindingContext to be used for finding type declarations.
|
||||
* @param functionsToAdd List of possible functions to add.
|
||||
*/
|
||||
public JetAddFunctionToClassifierAction(
|
||||
@NotNull Project project,
|
||||
@NotNull Editor editor,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull List<FunctionDescriptor> functionsToAdd
|
||||
) {
|
||||
this.project = project;
|
||||
this.editor = editor;
|
||||
this.bindingContext = bindingContext;
|
||||
this.functionsToAdd = new ArrayList<FunctionDescriptor>(functionsToAdd);
|
||||
}
|
||||
|
||||
private static void addFunction(
|
||||
@NotNull final Project project,
|
||||
@NotNull final ClassDescriptor typeDescriptor,
|
||||
@NotNull final FunctionDescriptor functionDescriptor,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
final String signatureString = CodeInsightUtils.createFunctionSignatureStringFromDescriptor(
|
||||
functionDescriptor,
|
||||
/* shortTypeNames = */ false);
|
||||
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
|
||||
final JetClass classifierDeclaration = (JetClass) DescriptorToDeclarationUtil.getDeclaration(project, typeDescriptor, bindingContext);
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
JetClassBody body = classifierDeclaration.getBody();
|
||||
if (body == null) {
|
||||
PsiElement whitespaceBefore = classifierDeclaration.add(JetPsiFactory.createWhiteSpace(project));
|
||||
body = (JetClassBody) classifierDeclaration.addAfter(JetPsiFactory.createEmptyClassBody(project), whitespaceBefore);
|
||||
classifierDeclaration.addAfter(JetPsiFactory.createNewLine(project), body);
|
||||
}
|
||||
|
||||
String functionBody = "";
|
||||
if (typeDescriptor.getKind() != ClassKind.TRAIT && functionDescriptor.getModality() != Modality.ABSTRACT) {
|
||||
functionBody = "{}";
|
||||
JetType returnType = functionDescriptor.getReturnType();
|
||||
if (returnType == null || !KotlinBuiltIns.getInstance().isUnit(returnType)) {
|
||||
functionBody = "{ throw UnsupportedOperationException() }";
|
||||
}
|
||||
}
|
||||
JetNamedFunction functionElement = JetPsiFactory.createFunction(project, signatureString + functionBody);
|
||||
PsiElement anchor = body.getRBrace();
|
||||
JetNamedFunction insertedFunctionElement = (JetNamedFunction) body.addBefore(functionElement, anchor);
|
||||
|
||||
ReferenceToClassesShortening.compactReferenceToClasses(Collections.singletonList(insertedFunctionElement));
|
||||
}
|
||||
});
|
||||
}
|
||||
}, JetBundle.message("add.function.to.type.action"), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
if (functionsToAdd.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (functionsToAdd.size() == 1 || !editor.getComponent().isShowing()) {
|
||||
addFunction(functionsToAdd.get(0));
|
||||
}
|
||||
else {
|
||||
chooseFunctionAndAdd();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void chooseFunctionAndAdd() {
|
||||
JBPopupFactory.getInstance().createListPopup(getFunctionPopup()).showInBestPositionFor(editor);
|
||||
}
|
||||
|
||||
private ListPopupStep getFunctionPopup() {
|
||||
return new BaseListPopupStep<FunctionDescriptor>(
|
||||
JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) {
|
||||
@Override
|
||||
public boolean isAutoSelectionEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(FunctionDescriptor selectedValue, boolean finalChoice) {
|
||||
if (finalChoice) {
|
||||
addFunction(selectedValue);
|
||||
}
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIconFor(FunctionDescriptor aValue) {
|
||||
return PlatformIcons.FUNCTION_ICON;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(FunctionDescriptor functionDescriptor) {
|
||||
ClassDescriptor type = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
||||
return JetBundle.message("add.function.to.type.action.single",
|
||||
CodeInsightUtils.createFunctionSignatureStringFromDescriptor(
|
||||
functionDescriptor,
|
||||
/* shortTypeNames = */ true),
|
||||
type.getName().toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void addFunction(FunctionDescriptor functionToAdd) {
|
||||
addFunction(project, (ClassDescriptor) functionToAdd.getContainingDeclaration(),
|
||||
functionToAdd, bindingContext);
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ public class JetAddImportAction implements QuestionAction {
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
List<String> toExclude = AddImportAction.getAllExcludableStrings(selectedValue.getFqName());
|
||||
List<String> toExclude = AddImportAction.getAllExcludableStrings(selectedValue.asString());
|
||||
|
||||
return new BaseListPopupStep<String>(null, toExclude) {
|
||||
@NotNull
|
||||
@@ -135,7 +135,7 @@ public class JetAddImportAction implements QuestionAction {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(FqName value) {
|
||||
return value.getFqName();
|
||||
return value.asString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,7 +39,7 @@ public class JetGotoClassContributor implements GotoClassContributor {
|
||||
JetNamedDeclaration jetClass = (JetNamedDeclaration) item;
|
||||
FqName name = JetPsiUtil.getFQName(jetClass);
|
||||
if (name != null) {
|
||||
return name.getFqName();
|
||||
return name.asString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
Collection<FqName> fqNames = packageClasses.get(name);
|
||||
if (!fqNames.isEmpty()) {
|
||||
for (FqName fqName : fqNames) {
|
||||
PsiClass psiClass = JavaElementFinder.getInstance(project).findClass(fqName.getFqName(), scope);
|
||||
PsiClass psiClass = JavaElementFinder.getInstance(project).findClass(fqName.asString(), scope);
|
||||
if (psiClass != null) {
|
||||
result.add(psiClass);
|
||||
}
|
||||
@@ -123,10 +123,10 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
for (JetClassOrObject classOrObject : classOrObjects) {
|
||||
FqName fqName = JetPsiUtil.getFQName(classOrObject);
|
||||
if (fqName != null) {
|
||||
assert fqName.shortName().getName().equals(name) : "A declaration obtained from index has non-matching name:\n" +
|
||||
assert fqName.shortName().asString().equals(name) : "A declaration obtained from index has non-matching name:\n" +
|
||||
"in index: " + name + "\n" +
|
||||
"declared: " + fqName.shortName() + "(" + fqName + ")";
|
||||
PsiClass psiClass = JavaElementFinder.getInstance(project).findClass(fqName.getFqName(), scope);
|
||||
PsiClass psiClass = JavaElementFinder.getInstance(project).findClass(fqName.asString(), scope);
|
||||
if (psiClass != null) {
|
||||
result.add(psiClass);
|
||||
}
|
||||
@@ -230,7 +230,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
Set<FunctionDescriptor> result = Sets.newHashSet();
|
||||
|
||||
Collection<PsiMethod> topLevelFunctionPrototypes = JetFromJavaDescriptorHelper.getTopLevelFunctionPrototypesByName(
|
||||
referenceName.getName(), project, scope);
|
||||
referenceName.asString(), project, scope);
|
||||
for (PsiMethod method : topLevelFunctionPrototypes) {
|
||||
FqName functionFQN = JetFromJavaDescriptorHelper.getJetTopLevelDeclarationFQN(method);
|
||||
if (functionFQN != null) {
|
||||
@@ -246,7 +246,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
}
|
||||
|
||||
Set<FqName> affectedPackages = Sets.newHashSet();
|
||||
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(referenceName.getName(), project, scope);
|
||||
Collection<JetNamedFunction> jetNamedFunctions = JetShortFunctionNameIndex.getInstance().get(referenceName.asString(), project, scope);
|
||||
for (JetNamedFunction jetNamedFunction : jetNamedFunctions) {
|
||||
PsiFile containingFile = jetNamedFunction.getContainingFile();
|
||||
if (containingFile instanceof JetFile) {
|
||||
@@ -354,7 +354,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
|
||||
for (String fqName : JetFullClassNameIndex.getInstance().getAllKeys(project)) {
|
||||
FqName classFQName = new FqName(fqName);
|
||||
if (acceptedShortNameCondition.value(classFQName.shortName().getName())) {
|
||||
if (acceptedShortNameCondition.value(classFQName.shortName().asString())) {
|
||||
classDescriptors.addAll(getJetClassesDescriptorsByFQName(analyzer, classFQName));
|
||||
}
|
||||
}
|
||||
@@ -364,7 +364,7 @@ public class JetShortNamesCache extends PsiShortNamesCache {
|
||||
|
||||
private Collection<ClassDescriptor> getJetClassesDescriptorsByFQName(@NotNull KotlinCodeAnalyzer analyzer, @NotNull FqName classFQName) {
|
||||
Collection<JetClassOrObject> jetClassOrObjects = JetFullClassNameIndex.getInstance().get(
|
||||
classFQName.getFqName(), project, GlobalSearchScope.allScope(project));
|
||||
classFQName.asString(), project, GlobalSearchScope.allScope(project));
|
||||
|
||||
if (jetClassOrObjects.isEmpty()) {
|
||||
// This fqn is absent in caches, dead or not in scope
|
||||
|
||||
+6
-8
@@ -31,11 +31,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.asJava.KotlinLightClassForExplicitDeclaration;
|
||||
import org.jetbrains.jet.asJava.LightClassConstructionContext;
|
||||
import org.jetbrains.jet.asJava.LightClassGenerationSupport;
|
||||
import org.jetbrains.jet.codegen.binding.PsiCodegenPredictor;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.plugin.libraries.JetSourceNavigationHelper;
|
||||
@@ -70,13 +68,13 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetClassOrObject> findClassOrObjectDeclarations(@NotNull FqName fqName, @NotNull GlobalSearchScope searchScope) {
|
||||
return JetFullClassNameIndex.getInstance().get(fqName.getFqName(), project, kotlinSources(searchScope));
|
||||
return JetFullClassNameIndex.getInstance().get(fqName.asString(), project, kotlinSources(searchScope));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<JetFile> findFilesForPackage(@NotNull final FqName fqName, @NotNull GlobalSearchScope searchScope) {
|
||||
Collection<JetFile> files = JetAllPackagesIndex.getInstance().get(fqName.getFqName(), project, kotlinSources(searchScope));
|
||||
Collection<JetFile> files = JetAllPackagesIndex.getInstance().get(fqName.asString(), project, kotlinSources(searchScope));
|
||||
return ContainerUtil.filter(files, new Condition<JetFile>() {
|
||||
@Override
|
||||
public boolean value(JetFile file) {
|
||||
@@ -90,20 +88,20 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
public Collection<JetClassOrObject> findClassOrObjectDeclarationsInPackage(
|
||||
@NotNull FqName packageFqName, @NotNull GlobalSearchScope searchScope
|
||||
) {
|
||||
return JetClassByPackageIndex.getInstance().get(packageFqName.getFqName(), project, kotlinSources(searchScope));
|
||||
return JetClassByPackageIndex.getInstance().get(packageFqName.asString(), project, kotlinSources(searchScope));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean packageExists(
|
||||
@NotNull FqName fqName, @NotNull GlobalSearchScope scope
|
||||
) {
|
||||
return !JetAllPackagesIndex.getInstance().get(fqName.getFqName(), project, kotlinSources(scope)).isEmpty();
|
||||
return !JetAllPackagesIndex.getInstance().get(fqName.asString(), project, kotlinSources(scope)).isEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<FqName> getSubPackages(@NotNull FqName fqn, @NotNull GlobalSearchScope scope) {
|
||||
Collection<JetFile> files = JetAllPackagesIndex.getInstance().get(fqn.getFqName(), project, kotlinSources(scope));
|
||||
Collection<JetFile> files = JetAllPackagesIndex.getInstance().get(fqn.asString(), project, kotlinSources(scope));
|
||||
|
||||
Set<FqName> result = Sets.newHashSet();
|
||||
for (JetFile file : files) {
|
||||
@@ -141,7 +139,7 @@ public class IDELightClassGenerationSupport extends LightClassGenerationSupport
|
||||
Collection<JetFile> files = findFilesForPackage(new FqName(packageFqName), scope);
|
||||
if (!files.isEmpty()) {
|
||||
FqName packageClassFqName = PackageClassUtils.getPackageClassFqName(new FqName(packageFqName));
|
||||
result.putValue(packageClassFqName.shortName().getName(), packageClassFqName);
|
||||
result.putValue(packageClassFqName.shortName().asString(), packageClassFqName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.plugin.codeInsight;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
@@ -30,11 +31,15 @@ public final class DescriptorToDeclarationUtil {
|
||||
}
|
||||
|
||||
public static PsiElement getDeclaration(JetFile file, DeclarationDescriptor descriptor, BindingContext bindingContext) {
|
||||
return getDeclaration(file.getProject(), descriptor, bindingContext);
|
||||
}
|
||||
|
||||
public static PsiElement getDeclaration(Project project, DeclarationDescriptor descriptor, BindingContext bindingContext) {
|
||||
Collection<PsiElement> elements = BindingContextUtils.descriptorToDeclarations(bindingContext, descriptor);
|
||||
|
||||
if (elements.isEmpty()) {
|
||||
BuiltInsReferenceResolver libraryReferenceResolver =
|
||||
file.getProject().getComponent(BuiltInsReferenceResolver.class);
|
||||
project.getComponent(BuiltInsReferenceResolver.class);
|
||||
elements = libraryReferenceResolver.resolveStandardLibrarySymbol(descriptor);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,14 +51,17 @@ public class GotoSuperActionHandler implements CodeInsightActionHandler {
|
||||
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
if (element == null) return;
|
||||
@SuppressWarnings("unchecked") JetNamedDeclaration funOrClass =
|
||||
PsiTreeUtil.getParentOfType(element, JetNamedFunction.class, JetClass.class, JetProperty.class);
|
||||
if (funOrClass == null) return;
|
||||
@SuppressWarnings("unchecked") JetDeclaration declaration =
|
||||
PsiTreeUtil.getParentOfType(element,
|
||||
JetNamedFunction.class,
|
||||
JetClass.class,
|
||||
JetProperty.class,
|
||||
JetObjectDeclaration.class);
|
||||
if (declaration == null) return;
|
||||
|
||||
final BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) file).getBindingContext();
|
||||
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, funOrClass);
|
||||
|
||||
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, declaration);
|
||||
|
||||
Collection<? extends DeclarationDescriptor> superDescriptors;
|
||||
String message;
|
||||
|
||||
@@ -81,7 +81,7 @@ public class ReferenceToClassesShortening {
|
||||
}
|
||||
|
||||
private void compactReferenceToClass(JetUserType userType, ClassDescriptor targetClass) {
|
||||
String name = targetClass.getName().getName();
|
||||
String name = targetClass.getName().asString();
|
||||
DeclarationDescriptor parent = targetClass.getContainingDeclaration();
|
||||
while (parent instanceof ClassDescriptor) {
|
||||
name = parent.getName() + "." + name;
|
||||
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations;
|
||||
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
|
||||
public class AssignmentWithIfExpressionToStatementIntention extends BaseIntentionAction {
|
||||
public AssignmentWithIfExpressionToStatementIntention() {
|
||||
setText(JetBundle.message("transform.assignment.with.if.expression.to.statement"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return JetBundle.message("transform.assignment.with.if.expression.to.statement.family");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetBinaryExpression getAssignment(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiElement element = file.findElementAt(offset);
|
||||
|
||||
while (element != null) {
|
||||
if (CodeTransformationUtils.checkAssignmentWithIfExpression(element)) return (JetBinaryExpression)element;
|
||||
PsiElement parent = PsiTreeUtil.getParentOfType(element, JetBinaryExpression.class, false);
|
||||
element = (element != parent) ? parent : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
return getAssignment(editor, file) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(
|
||||
@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file
|
||||
) throws IncorrectOperationException {
|
||||
JetBinaryExpression assignment = getAssignment(editor, file);
|
||||
assert assignment != null;
|
||||
CodeTransformationUtils.transformAssignmentWithIfExpressionToStatement(assignment);
|
||||
}
|
||||
}
|
||||
-166
@@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CodeTransformationUtils {
|
||||
private static List<JetExpression> getIfExpressionOutcomes(@NotNull JetElement root) {
|
||||
return root.accept(
|
||||
new JetVisitor<List<JetExpression>, List<JetExpression>>() {
|
||||
@Override
|
||||
public List<JetExpression> visitExpression(JetExpression expression, List<JetExpression> data) {
|
||||
data.add(expression);
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JetExpression> visitBlockExpression(
|
||||
JetBlockExpression expression, List<JetExpression> data) {
|
||||
int n = expression.getStatements().size();
|
||||
if (n > 0) {
|
||||
expression.getStatements().get(n - 1).accept(this, data);
|
||||
} else {
|
||||
data.add(expression);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public List<JetExpression> visitIfExpression(
|
||||
JetIfExpression expression, List<JetExpression> data) {
|
||||
if (expression.getThen() != null) {
|
||||
expression.getThen().accept(this, data);
|
||||
}
|
||||
if (expression.getElse() != null) {
|
||||
expression.getElse().accept(this, data);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
},
|
||||
new ArrayList<JetExpression>()
|
||||
);
|
||||
}
|
||||
|
||||
private static Boolean checkAllIfExpressionsAreComplete(@NotNull JetElement root) {
|
||||
return root.accept(
|
||||
new JetVisitor<Boolean, Boolean>() {
|
||||
@Override
|
||||
public Boolean visitJetElement(JetElement element, Boolean data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public Boolean visitIfExpression(JetIfExpression expression, Boolean data) {
|
||||
if (data && expression.getThen() != null) {
|
||||
data = expression.getThen().accept(this, data);
|
||||
} else {
|
||||
data = false;
|
||||
}
|
||||
if (data && expression.getElse() != null) {
|
||||
data = expression.getElse().accept(this, data);
|
||||
} else {
|
||||
data = false;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public static boolean isAssignment(@NotNull PsiElement element) {
|
||||
if (!(element instanceof JetBinaryExpression)) return false;
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression)element;
|
||||
if (binaryExpression.getOperationReference().getReferencedNameElementType() != JetTokens.EQ) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkAllOutcomesAreCompatibleAssignments(@NotNull List<JetExpression> outcomes) {
|
||||
JetExpression lastLhs = null;
|
||||
for (JetExpression outcome : outcomes) {
|
||||
if (!isAssignment(outcome)) return false;
|
||||
|
||||
JetExpression currLhs = ((JetBinaryExpression)outcome).getLeft();
|
||||
if (!(currLhs instanceof JetSimpleNameExpression)) return false;
|
||||
|
||||
if (lastLhs == null) {
|
||||
lastLhs = currLhs;
|
||||
} else if (!lastLhs.getText().equals(currLhs.getText())) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean checkIfStatementWithAssignments(@NotNull JetIfExpression ifExpression) {
|
||||
if (ifExpression.getParent() == null) return false;
|
||||
List<JetExpression> outcomes = getIfExpressionOutcomes(ifExpression);
|
||||
|
||||
return !outcomes.isEmpty() && checkAllIfExpressionsAreComplete(ifExpression) && checkAllOutcomesAreCompatibleAssignments(outcomes);
|
||||
}
|
||||
|
||||
static boolean checkAssignmentWithIfExpression(@NotNull PsiElement element) {
|
||||
if (!isAssignment(element)) return false;
|
||||
JetBinaryExpression assignment = (JetBinaryExpression)element;
|
||||
return (assignment.getLeft() instanceof JetSimpleNameExpression) &&
|
||||
(assignment.getRight() instanceof JetIfExpression);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
static void transformIfStatementWithAssignmentsToExpression(@NotNull JetIfExpression ifExpression) {
|
||||
Project project = ifExpression.getProject();
|
||||
List<JetExpression> outcomes = getIfExpressionOutcomes(ifExpression);
|
||||
JetExpression lhs = ((JetBinaryExpression)outcomes.get(0)).getLeft();
|
||||
|
||||
JetBinaryExpression assignment = JetPsiFactory.createAssignment(project, lhs, ifExpression);
|
||||
|
||||
assignment = (JetBinaryExpression)ifExpression.replace(assignment);
|
||||
ifExpression = (JetIfExpression)assignment.getRight();
|
||||
|
||||
for (JetExpression outcome : getIfExpressionOutcomes(ifExpression)) {
|
||||
outcome.replace(((JetBinaryExpression)outcome).getRight());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
static void transformAssignmentWithIfExpressionToStatement(@NotNull JetBinaryExpression assignment) {
|
||||
Project project = assignment.getProject();
|
||||
String varName = assignment.getLeft().getText();
|
||||
JetIfExpression ifExpression = (JetIfExpression)assignment.getRight();
|
||||
|
||||
ifExpression = (JetIfExpression)assignment.replace(ifExpression);
|
||||
|
||||
for (JetExpression outcome : getIfExpressionOutcomes(ifExpression)) {
|
||||
JetBinaryExpression localAssignment = JetPsiFactory.createAssignment(project, JetPsiFactory.createExpression(project, varName), outcome);
|
||||
outcome.replace(localAssignment);
|
||||
}
|
||||
}
|
||||
|
||||
private CodeTransformationUtils() {
|
||||
}
|
||||
}
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations;
|
||||
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetIfExpression;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
|
||||
public class IfStatementWithAssignmentsToExpressionIntention extends BaseIntentionAction {
|
||||
public IfStatementWithAssignmentsToExpressionIntention() {
|
||||
setText(JetBundle.message("transform.if.statement.with.assignments.to.expression"));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return JetBundle.message("transform.if.statement.with.assignments.to.expression.family");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetIfExpression getOriginalExpression(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiElement element = file.findElementAt(offset);
|
||||
return PsiTreeUtil.getParentOfType(element, JetIfExpression.class, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(
|
||||
@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
JetIfExpression ifExpression = getOriginalExpression(editor, file);
|
||||
return (ifExpression != null) && CodeTransformationUtils.checkIfStatementWithAssignments(ifExpression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(
|
||||
@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file
|
||||
) throws IncorrectOperationException {
|
||||
JetIfExpression ifExpression = getOriginalExpression(editor, file);
|
||||
assert ifExpression != null;
|
||||
CodeTransformationUtils.transformIfStatementWithAssignmentsToExpression(ifExpression);
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetElement;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetPsiUtil;
|
||||
import org.jetbrains.jet.plugin.JetBundle;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public abstract class AbstractCodeTransformationIntention<T extends Transformer> extends BaseIntentionAction {
|
||||
private final T transformer;
|
||||
private final Predicate<PsiElement> isApplicable;
|
||||
|
||||
protected AbstractCodeTransformationIntention(@NotNull T transformer, @NotNull Predicate<PsiElement> isApplicable) {
|
||||
this.transformer = transformer;
|
||||
this.isApplicable = isApplicable;
|
||||
setText(JetBundle.message(transformer.getKey()));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiElement getTarget(@NotNull Editor editor, @NotNull PsiFile file) {
|
||||
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
|
||||
return JetPsiUtil.getParentByTypeAndPredicate(element, JetElement.class, isApplicable, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return JetBundle.message(transformer.getKey() + ".family");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
return getTarget(editor, file) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) throws IncorrectOperationException {
|
||||
PsiElement target = getTarget(editor, file);
|
||||
|
||||
assert target != null : "Intention is not applicable";
|
||||
|
||||
transformer.transform(target, editor, (JetFile) file);
|
||||
}
|
||||
}
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class BranchedFoldingUtils {
|
||||
private BranchedFoldingUtils() {
|
||||
}
|
||||
|
||||
private static boolean checkEquivalence(JetExpression e1, JetExpression e2) {
|
||||
return e1.getText().equals(e2.getText());
|
||||
}
|
||||
|
||||
private static final Predicate<JetElement> CHECK_ASSIGNMENT = new Predicate<JetElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable JetElement input) {
|
||||
if (input == null || !JetPsiUtil.isAssignment(input)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JetBinaryExpression assignment = (JetBinaryExpression)input;
|
||||
|
||||
if (assignment.getRight() == null || !(assignment.getLeft() instanceof JetSimpleNameExpression)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (assignment.getParent() instanceof JetBlockExpression) {
|
||||
//noinspection ConstantConditions
|
||||
return !JetPsiUtil.checkVariableDeclarationInBlock((JetBlockExpression) assignment.getParent(), assignment.getLeft().getText());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<JetElement> CHECK_RETURN = new Predicate<JetElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable JetElement input) {
|
||||
return (input instanceof JetReturnExpression) && ((JetReturnExpression)input).getReturnedExpression() != null;
|
||||
}
|
||||
};
|
||||
|
||||
private static JetBinaryExpression getFoldableBranchedAssignment(JetExpression branch) {
|
||||
return (JetBinaryExpression)JetPsiUtil.getOutermostLastBlockElement(branch, CHECK_ASSIGNMENT);
|
||||
}
|
||||
|
||||
private static JetReturnExpression getFoldableBranchedReturn(JetExpression branch) {
|
||||
return (JetReturnExpression)JetPsiUtil.getOutermostLastBlockElement(branch, CHECK_RETURN);
|
||||
}
|
||||
|
||||
private static boolean checkAssignmentsMatch(JetBinaryExpression a1, JetBinaryExpression a2) {
|
||||
return checkEquivalence(a1.getLeft(), a2.getLeft()) && a1.getOperationToken().equals(a2.getOperationToken());
|
||||
}
|
||||
|
||||
private static boolean checkFoldableIfExpressionWithAssignments(JetIfExpression ifExpression) {
|
||||
JetExpression thenBranch = ifExpression.getThen();
|
||||
JetExpression elseBranch = ifExpression.getElse();
|
||||
|
||||
JetBinaryExpression thenAssignment = getFoldableBranchedAssignment(thenBranch);
|
||||
JetBinaryExpression elseAssignment = getFoldableBranchedAssignment(elseBranch);
|
||||
|
||||
if (thenAssignment == null || elseAssignment == null) return false;
|
||||
|
||||
return checkAssignmentsMatch(thenAssignment, elseAssignment);
|
||||
}
|
||||
|
||||
private static boolean checkFoldableWhenExpressionWithAssignments(JetWhenExpression whenExpression) {
|
||||
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;
|
||||
|
||||
List<JetWhenEntry> entries = whenExpression.getEntries();
|
||||
|
||||
if (entries.isEmpty()) return false;
|
||||
|
||||
List<JetBinaryExpression> assignments = new ArrayList<JetBinaryExpression>();
|
||||
for (JetWhenEntry entry : entries) {
|
||||
JetBinaryExpression assignment = getFoldableBranchedAssignment(entry.getExpression());
|
||||
if (assignment == null) return false;
|
||||
assignments.add(assignment);
|
||||
}
|
||||
|
||||
assert !assignments.isEmpty();
|
||||
|
||||
JetBinaryExpression firstAssignment = assignments.get(0);
|
||||
for (JetBinaryExpression assignment : assignments) {
|
||||
if (!checkAssignmentsMatch(assignment, firstAssignment)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkFoldableIfExpressionWithReturns(JetIfExpression ifExpression) {
|
||||
return getFoldableBranchedReturn(ifExpression.getThen()) != null &&
|
||||
getFoldableBranchedReturn(ifExpression.getElse()) != null;
|
||||
}
|
||||
|
||||
private static boolean checkFoldableWhenExpressionWithReturns(JetWhenExpression whenExpression) {
|
||||
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;
|
||||
|
||||
List<JetWhenEntry> entries = whenExpression.getEntries();
|
||||
|
||||
if (entries.isEmpty()) return false;
|
||||
|
||||
for (JetWhenEntry entry : entries) {
|
||||
if (getFoldableBranchedReturn(entry.getExpression()) == null) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkFoldableIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) {
|
||||
if (getFoldableBranchedReturn(ifExpression.getThen()) == null ||
|
||||
ifExpression.getElse() != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PsiElement nextElement = JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression);
|
||||
return (nextElement instanceof JetExpression) && getFoldableBranchedReturn((JetExpression) nextElement) != null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static FoldableKind getFoldableExpressionKind(@Nullable JetExpression root) {
|
||||
if (root instanceof JetIfExpression) {
|
||||
JetIfExpression ifExpression = (JetIfExpression)root;
|
||||
|
||||
if (checkFoldableIfExpressionWithAssignments(ifExpression)) return FoldableKind.IF_TO_ASSIGNMENT;
|
||||
if (checkFoldableIfExpressionWithReturns(ifExpression)) return FoldableKind.IF_TO_RETURN;
|
||||
if (checkFoldableIfExpressionWithAsymmetricReturns(ifExpression)) return FoldableKind.IF_TO_RETURN_ASYMMETRICALLY;
|
||||
} else if (root instanceof JetWhenExpression) {
|
||||
JetWhenExpression whenExpression = (JetWhenExpression)root;
|
||||
|
||||
if (checkFoldableWhenExpressionWithAssignments(whenExpression)) return FoldableKind.WHEN_TO_ASSIGNMENT;
|
||||
if (checkFoldableWhenExpressionWithReturns(whenExpression)) return FoldableKind.WHEN_TO_RETURN;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final String FOLD_WITHOUT_CHECK = "Expression must be checked before folding";
|
||||
|
||||
private static void assertNotNull(JetExpression expression) {
|
||||
assert expression != null : FOLD_WITHOUT_CHECK;
|
||||
}
|
||||
|
||||
public static void foldIfExpressionWithAssignments(JetIfExpression ifExpression) {
|
||||
Project project = ifExpression.getProject();
|
||||
|
||||
JetBinaryExpression thenAssignment = getFoldableBranchedAssignment(ifExpression.getThen());
|
||||
|
||||
assertNotNull(thenAssignment);
|
||||
|
||||
String op = thenAssignment.getOperationReference().getText();
|
||||
JetSimpleNameExpression lhs = (JetSimpleNameExpression) thenAssignment.getLeft();
|
||||
|
||||
JetBinaryExpression assignment = JetPsiFactory.createBinaryExpression(project, lhs, op, ifExpression);
|
||||
JetIfExpression newIfExpression = (JetIfExpression)assignment.getRight();
|
||||
|
||||
assertNotNull(newIfExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
thenAssignment = getFoldableBranchedAssignment(newIfExpression.getThen());
|
||||
JetBinaryExpression elseAssignment = getFoldableBranchedAssignment(newIfExpression.getElse());
|
||||
|
||||
assertNotNull(thenAssignment);
|
||||
assertNotNull(elseAssignment);
|
||||
|
||||
JetExpression thenRhs = thenAssignment.getRight();
|
||||
JetExpression elseRhs = elseAssignment.getRight();
|
||||
|
||||
assertNotNull(thenRhs);
|
||||
assertNotNull(elseRhs);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
thenAssignment.replace(thenRhs);
|
||||
//noinspection ConstantConditions
|
||||
elseAssignment.replace(elseRhs);
|
||||
|
||||
ifExpression.replace(assignment);
|
||||
}
|
||||
|
||||
public static void foldIfExpressionWithReturns(JetIfExpression ifExpression) {
|
||||
Project project = ifExpression.getProject();
|
||||
|
||||
JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, ifExpression);
|
||||
JetIfExpression newIfExpression = (JetIfExpression)newReturnExpression.getReturnedExpression();
|
||||
|
||||
assertNotNull(newIfExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetReturnExpression thenReturn = getFoldableBranchedReturn(newIfExpression.getThen());
|
||||
JetReturnExpression elseReturn = getFoldableBranchedReturn(newIfExpression.getElse());
|
||||
|
||||
assertNotNull(thenReturn);
|
||||
assertNotNull(elseReturn);
|
||||
|
||||
JetExpression thenExpr = thenReturn.getReturnedExpression();
|
||||
JetExpression elseExpr = elseReturn.getReturnedExpression();
|
||||
|
||||
assertNotNull(thenExpr);
|
||||
assertNotNull(elseExpr);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
thenReturn.replace(thenExpr);
|
||||
//noinspection ConstantConditions
|
||||
elseReturn.replace(elseExpr);
|
||||
|
||||
ifExpression.replace(newReturnExpression);
|
||||
}
|
||||
|
||||
public static void foldIfExpressionWithAsymmetricReturns(JetIfExpression ifExpression) {
|
||||
Project project = ifExpression.getProject();
|
||||
|
||||
JetExpression condition = ifExpression.getCondition();
|
||||
JetExpression thenRoot = ifExpression.getThen();
|
||||
JetExpression elseRoot = (JetExpression)JetPsiUtil.skipTrailingWhitespacesAndComments(ifExpression);
|
||||
|
||||
assertNotNull(condition);
|
||||
assertNotNull(thenRoot);
|
||||
assertNotNull(elseRoot);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetIfExpression newIfExpression = JetPsiFactory.createIf(project, condition, thenRoot, elseRoot);
|
||||
JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, newIfExpression);
|
||||
|
||||
newIfExpression = (JetIfExpression)newReturnExpression.getReturnedExpression();
|
||||
|
||||
assertNotNull(newIfExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetReturnExpression thenReturn = getFoldableBranchedReturn(newIfExpression.getThen());
|
||||
JetReturnExpression elseReturn = getFoldableBranchedReturn(newIfExpression.getElse());
|
||||
|
||||
assertNotNull(thenReturn);
|
||||
assertNotNull(elseReturn);
|
||||
|
||||
JetExpression thenExpr = thenReturn.getReturnedExpression();
|
||||
JetExpression elseExpr = elseReturn.getReturnedExpression();
|
||||
|
||||
assertNotNull(thenExpr);
|
||||
assertNotNull(elseExpr);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
thenReturn.replace(thenExpr);
|
||||
//noinspection ConstantConditions
|
||||
elseReturn.replace(elseExpr);
|
||||
|
||||
elseRoot.delete();
|
||||
ifExpression.replace(newReturnExpression);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static void foldWhenExpressionWithAssignments(JetWhenExpression whenExpression) {
|
||||
Project project = whenExpression.getProject();
|
||||
|
||||
assert !whenExpression.getEntries().isEmpty() : FOLD_WITHOUT_CHECK;
|
||||
|
||||
JetBinaryExpression firstAssignment = getFoldableBranchedAssignment(whenExpression.getEntries().get(0).getExpression());
|
||||
|
||||
assertNotNull(firstAssignment);
|
||||
|
||||
String op = firstAssignment.getOperationReference().getText();
|
||||
JetSimpleNameExpression lhs = (JetSimpleNameExpression) firstAssignment.getLeft();
|
||||
|
||||
JetBinaryExpression assignment = JetPsiFactory.createBinaryExpression(project, lhs, op, whenExpression);
|
||||
JetWhenExpression newWhenExpression = (JetWhenExpression)assignment.getRight();
|
||||
|
||||
assertNotNull(newWhenExpression);
|
||||
|
||||
for (JetWhenEntry entry : newWhenExpression.getEntries()) {
|
||||
JetBinaryExpression currAssignment = getFoldableBranchedAssignment(entry.getExpression());
|
||||
|
||||
assertNotNull(currAssignment);
|
||||
|
||||
JetExpression currRhs = currAssignment.getRight();
|
||||
|
||||
assertNotNull(currRhs);
|
||||
|
||||
currAssignment.replace(currRhs);
|
||||
}
|
||||
|
||||
whenExpression.replace(assignment);
|
||||
}
|
||||
|
||||
public static void foldWhenExpressionWithReturns(JetWhenExpression whenExpression) {
|
||||
Project project = whenExpression.getProject();
|
||||
|
||||
assert !whenExpression.getEntries().isEmpty() : FOLD_WITHOUT_CHECK;
|
||||
|
||||
JetReturnExpression newReturnExpression = JetPsiFactory.createReturn(project, whenExpression);
|
||||
JetWhenExpression newWhenExpression = (JetWhenExpression)newReturnExpression.getReturnedExpression();
|
||||
|
||||
assertNotNull(newWhenExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
for (JetWhenEntry entry : newWhenExpression.getEntries()) {
|
||||
JetReturnExpression currReturn = getFoldableBranchedReturn(entry.getExpression());
|
||||
|
||||
assertNotNull(currReturn);
|
||||
|
||||
JetExpression currExpr = currReturn.getReturnedExpression();
|
||||
|
||||
assertNotNull(currExpr);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
currReturn.replace(currExpr);
|
||||
}
|
||||
|
||||
whenExpression.replace(newReturnExpression);
|
||||
}
|
||||
}
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening;
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class BranchedUnfoldingUtils {
|
||||
private BranchedUnfoldingUtils() {
|
||||
}
|
||||
|
||||
private static JetExpression getOutermostLastBlockElement(@Nullable JetExpression expression) {
|
||||
return (JetExpression) JetPsiUtil.getOutermostLastBlockElement(expression, JetPsiUtil.ANY_JET_ELEMENT);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static UnfoldableKind getUnfoldableExpressionKind(@Nullable JetExpression root) {
|
||||
if (root == null) return null;
|
||||
|
||||
if (JetPsiUtil.isAssignment(root)) {
|
||||
JetBinaryExpression assignment = (JetBinaryExpression) root;
|
||||
|
||||
assertNotNull(assignment.getLeft());
|
||||
|
||||
JetExpression rhs = assignment.getRight();
|
||||
if (rhs instanceof JetIfExpression) return UnfoldableKind.ASSIGNMENT_TO_IF;
|
||||
if (rhs instanceof JetWhenExpression && JetPsiUtil.checkWhenExpressionHasSingleElse((JetWhenExpression) rhs)) {
|
||||
return UnfoldableKind.ASSIGNMENT_TO_WHEN;
|
||||
}
|
||||
}
|
||||
else if (root instanceof JetReturnExpression) {
|
||||
JetExpression resultExpr = ((JetReturnExpression) root).getReturnedExpression();
|
||||
|
||||
if (resultExpr instanceof JetIfExpression) return UnfoldableKind.RETURN_TO_IF;
|
||||
if (resultExpr instanceof JetWhenExpression && JetPsiUtil.checkWhenExpressionHasSingleElse((JetWhenExpression) resultExpr)) {
|
||||
return UnfoldableKind.RETURN_TO_WHEN;
|
||||
}
|
||||
}
|
||||
else if (root instanceof JetProperty) {
|
||||
JetProperty property = (JetProperty) root;
|
||||
if (!property.isLocal()) return null;
|
||||
|
||||
JetExpression initializer = property.getInitializer();
|
||||
|
||||
if (initializer instanceof JetIfExpression) return UnfoldableKind.PROPERTY_TO_IF;
|
||||
if (initializer instanceof JetWhenExpression && JetPsiUtil.checkWhenExpressionHasSingleElse((JetWhenExpression) initializer)) {
|
||||
return UnfoldableKind.PROPERTY_TO_WHEN;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final String UNFOLD_WITHOUT_CHECK = "Expression must be checked before unfolding";
|
||||
|
||||
private static void assertNotNull(Object value) {
|
||||
assert value != null : UNFOLD_WITHOUT_CHECK;
|
||||
}
|
||||
|
||||
public static void unfoldAssignmentToIf(@NotNull JetBinaryExpression assignment, @NotNull Editor editor) {
|
||||
Project project = assignment.getProject();
|
||||
String op = assignment.getOperationReference().getText();
|
||||
JetExpression lhs = assignment.getLeft();
|
||||
JetIfExpression ifExpression = (JetIfExpression) assignment.getRight();
|
||||
|
||||
assertNotNull(ifExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetIfExpression newIfExpression = (JetIfExpression) ifExpression.copy();
|
||||
|
||||
JetExpression thenExpr = getOutermostLastBlockElement(newIfExpression.getThen());
|
||||
JetExpression elseExpr = getOutermostLastBlockElement(newIfExpression.getElse());
|
||||
|
||||
assertNotNull(thenExpr);
|
||||
assertNotNull(elseExpr);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
thenExpr.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, thenExpr));
|
||||
elseExpr.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, elseExpr));
|
||||
|
||||
PsiElement resultElement = assignment.replace(newIfExpression);
|
||||
|
||||
editor.getCaretModel().moveToOffset(resultElement.getTextOffset());
|
||||
}
|
||||
|
||||
public static void unfoldAssignmentToWhen(@NotNull JetBinaryExpression assignment, @NotNull Editor editor) {
|
||||
Project project = assignment.getProject();
|
||||
String op = assignment.getOperationReference().getText();
|
||||
JetExpression lhs = assignment.getLeft();
|
||||
JetWhenExpression whenExpression = (JetWhenExpression) assignment.getRight();
|
||||
|
||||
assertNotNull(whenExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetWhenExpression newWhenExpression = (JetWhenExpression) whenExpression.copy();
|
||||
|
||||
for (JetWhenEntry entry : newWhenExpression.getEntries()) {
|
||||
JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression());
|
||||
|
||||
assertNotNull(currExpr);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
currExpr.replace(JetPsiFactory.createBinaryExpression(project, lhs, op, currExpr));
|
||||
}
|
||||
|
||||
PsiElement resultElement = assignment.replace(newWhenExpression);
|
||||
|
||||
editor.getCaretModel().moveToOffset(resultElement.getTextOffset());
|
||||
}
|
||||
|
||||
private static JetType getPropertyTypeIfNeeded(@NotNull JetProperty property, @NotNull JetFile file) {
|
||||
if (property.getTypeRef() != null) return null;
|
||||
return AnalyzerFacadeWithCache.analyzeFileWithCache(file).getBindingContext().get(BindingContext.EXPRESSION_TYPE, property.getInitializer());
|
||||
}
|
||||
|
||||
protected interface PropertyUnfolder<T extends JetExpression> {
|
||||
void processInitializer(@NotNull T newInitializer, @NotNull JetExpression propertyRef, @NotNull Project project);
|
||||
}
|
||||
|
||||
protected static final PropertyUnfolder<JetIfExpression> IF_EXPRESSION_PROPERTY_UNFOLDER = new PropertyUnfolder<JetIfExpression>() {
|
||||
@Override
|
||||
public void processInitializer(
|
||||
@NotNull JetIfExpression newInitializer, @NotNull JetExpression propertyRef, @NotNull Project project
|
||||
) {
|
||||
JetExpression thenExpr = getOutermostLastBlockElement(newInitializer.getThen());
|
||||
JetExpression elseExpr = getOutermostLastBlockElement(newInitializer.getElse());
|
||||
|
||||
assertNotNull(thenExpr);
|
||||
assertNotNull(elseExpr);
|
||||
|
||||
thenExpr.replace(JetPsiFactory.createBinaryExpression(project, propertyRef, "=", thenExpr));
|
||||
elseExpr.replace(JetPsiFactory.createBinaryExpression(project, propertyRef, "=", elseExpr));
|
||||
}
|
||||
};
|
||||
|
||||
protected static final PropertyUnfolder<JetWhenExpression> WHEN_EXPRESSION_PROPERTY_UNFOLDER = new PropertyUnfolder<JetWhenExpression>() {
|
||||
@Override
|
||||
public void processInitializer(
|
||||
@NotNull JetWhenExpression newInitializer, @NotNull JetExpression propertyRef, @NotNull Project project
|
||||
) {
|
||||
for (JetWhenEntry entry : newInitializer.getEntries()) {
|
||||
JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression());
|
||||
|
||||
assertNotNull(currExpr);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
currExpr.replace(JetPsiFactory.createBinaryExpression(project, propertyRef, "=", currExpr));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private static <T extends JetExpression> void unfoldProperty(
|
||||
@NotNull JetProperty property, @NotNull JetFile file, PropertyUnfolder<T> unfolder
|
||||
) {
|
||||
Project project = property.getProject();
|
||||
|
||||
PsiElement parent = property.getParent();
|
||||
assertNotNull(parent);
|
||||
|
||||
//noinspection unchecked
|
||||
T initializer = (T) property.getInitializer();
|
||||
assertNotNull(initializer);
|
||||
|
||||
JetSimpleNameExpression propertyName = JetPsiFactory.createSimpleName(project, property.getName());
|
||||
|
||||
//noinspection ConstantConditions, unchecked
|
||||
T newInitializer = (T) initializer.copy();
|
||||
|
||||
unfolder.processInitializer(newInitializer, propertyName, project);
|
||||
|
||||
parent.addAfter(newInitializer, property);
|
||||
parent.addAfter(JetPsiFactory.createNewLine(project), property);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetType inferredType = getPropertyTypeIfNeeded(property, file);
|
||||
|
||||
String typeStr = inferredType != null
|
||||
? DescriptorRenderer.TEXT.renderType(inferredType)
|
||||
: JetPsiUtil.getNullableText(property.getTypeRef());
|
||||
|
||||
property = (JetProperty) property.replace(
|
||||
JetPsiFactory.createProperty(project, property.getName(), typeStr, property.isVar())
|
||||
);
|
||||
|
||||
if (inferredType != null) {
|
||||
ReferenceToClassesShortening.compactReferenceToClasses(Collections.singletonList(property.getTypeRef()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void unfoldPropertyToIf(@NotNull JetProperty property, @NotNull JetFile file) {
|
||||
unfoldProperty(property, file, IF_EXPRESSION_PROPERTY_UNFOLDER);
|
||||
}
|
||||
|
||||
public static void unfoldPropertyToWhen(@NotNull JetProperty property, @NotNull JetFile file) {
|
||||
unfoldProperty(property, file, WHEN_EXPRESSION_PROPERTY_UNFOLDER);
|
||||
}
|
||||
|
||||
public static void unfoldReturnToIf(@NotNull JetReturnExpression returnExpression) {
|
||||
Project project = returnExpression.getProject();
|
||||
JetIfExpression ifExpression = (JetIfExpression) returnExpression.getReturnedExpression();
|
||||
|
||||
assertNotNull(ifExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetIfExpression newIfExpression = (JetIfExpression) ifExpression.copy();
|
||||
|
||||
JetExpression thenExpr = getOutermostLastBlockElement(newIfExpression.getThen());
|
||||
JetExpression elseExpr = getOutermostLastBlockElement(newIfExpression.getElse());
|
||||
|
||||
assertNotNull(thenExpr);
|
||||
assertNotNull(elseExpr);
|
||||
|
||||
thenExpr.replace(JetPsiFactory.createReturn(project, thenExpr));
|
||||
elseExpr.replace(JetPsiFactory.createReturn(project, elseExpr));
|
||||
|
||||
returnExpression.replace(newIfExpression);
|
||||
}
|
||||
|
||||
public static void unfoldReturnToWhen(@NotNull JetReturnExpression returnExpression) {
|
||||
Project project = returnExpression.getProject();
|
||||
JetWhenExpression whenExpression = (JetWhenExpression) returnExpression.getReturnedExpression();
|
||||
|
||||
assertNotNull(whenExpression);
|
||||
|
||||
//noinspection ConstantConditions
|
||||
JetWhenExpression newWhenExpression = (JetWhenExpression) whenExpression.copy();
|
||||
|
||||
for (JetWhenEntry entry : newWhenExpression.getEntries()) {
|
||||
JetExpression currExpr = getOutermostLastBlockElement(entry.getExpression());
|
||||
|
||||
assertNotNull(currExpr);
|
||||
|
||||
currExpr.replace(JetPsiFactory.createReturn(project, currExpr));
|
||||
}
|
||||
|
||||
returnExpression.replace(newWhenExpression);
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance TO 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,
|
||||
* TOOUT 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetIfExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public enum FoldableKind implements Transformer {
|
||||
IF_TO_ASSIGNMENT("fold.if.to.assignment") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
BranchedFoldingUtils.foldIfExpressionWithAssignments((JetIfExpression) element);
|
||||
}
|
||||
},
|
||||
IF_TO_RETURN("fold.if.to.return") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
BranchedFoldingUtils.foldIfExpressionWithReturns((JetIfExpression) element);
|
||||
}
|
||||
},
|
||||
IF_TO_RETURN_ASYMMETRICALLY("fold.if.to.return") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
BranchedFoldingUtils.foldIfExpressionWithAsymmetricReturns((JetIfExpression) element);
|
||||
}
|
||||
},
|
||||
WHEN_TO_ASSIGNMENT("fold.when.to.assignment") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
BranchedFoldingUtils.foldWhenExpressionWithAssignments((JetWhenExpression) element);
|
||||
}
|
||||
},
|
||||
WHEN_TO_RETURN("fold.when.to.return") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
BranchedFoldingUtils.foldWhenExpressionWithReturns((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private final String key;
|
||||
|
||||
private FoldableKind(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils.*;
|
||||
|
||||
public class IfWhenUtils {
|
||||
|
||||
public static final String TRANSFORM_WITHOUT_CHECK =
|
||||
"Expression must be checked before applying transformation";
|
||||
|
||||
private IfWhenUtils() {
|
||||
}
|
||||
|
||||
public static boolean checkIfToWhen(@NotNull JetIfExpression ifExpression) {
|
||||
return ifExpression.getThen() != null && ifExpression.getElse() != null;
|
||||
}
|
||||
|
||||
public static boolean checkWhenToIf(@NotNull JetWhenExpression whenExpression) {
|
||||
return !whenExpression.getEntries().isEmpty() && JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression);
|
||||
}
|
||||
|
||||
private static void assertNotNull(JetExpression expression) {
|
||||
assert expression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
|
||||
private static List<JetExpression> splitExpressionToOrBranches(@Nullable JetExpression expression) {
|
||||
if (expression == null) return Collections.emptyList();
|
||||
|
||||
final List<JetExpression> branches = new ArrayList<JetExpression>();
|
||||
|
||||
expression.accept(
|
||||
new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitBinaryExpression(JetBinaryExpression expression) {
|
||||
if (expression.getOperationToken() == JetTokens.OROR) {
|
||||
JetExpression left = expression.getLeft();
|
||||
JetExpression right = expression.getRight();
|
||||
|
||||
if (left != null) {
|
||||
left.accept(this);
|
||||
}
|
||||
|
||||
if (right != null) {
|
||||
right.accept(this);
|
||||
}
|
||||
} else {
|
||||
visitExpression(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
|
||||
JetExpression baseExpression = expression.getExpression();
|
||||
|
||||
if (baseExpression != null) {
|
||||
baseExpression.accept(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitExpression(JetExpression expression) {
|
||||
branches.add(expression);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return branches;
|
||||
}
|
||||
|
||||
public static void transformIfToWhen(@NotNull JetIfExpression ifExpression) {
|
||||
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder();
|
||||
|
||||
JetIfExpression currIfExpression = ifExpression;
|
||||
do {
|
||||
JetExpression condition = currIfExpression.getCondition();
|
||||
JetExpression thenBranch = currIfExpression.getThen();
|
||||
JetExpression elseBranch = currIfExpression.getElse();
|
||||
|
||||
assertNotNull(thenBranch);
|
||||
assertNotNull(elseBranch);
|
||||
|
||||
List<JetExpression> orBranches = splitExpressionToOrBranches(condition);
|
||||
|
||||
if (orBranches.isEmpty()) {
|
||||
builder.condition("");
|
||||
} else {
|
||||
for (JetExpression orBranch : orBranches) {
|
||||
builder.condition(orBranch);
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection ConstantConditions
|
||||
builder.branchExpression(thenBranch);
|
||||
|
||||
if (elseBranch instanceof JetIfExpression) {
|
||||
currIfExpression = (JetIfExpression) elseBranch;
|
||||
}
|
||||
else {
|
||||
currIfExpression = null;
|
||||
//noinspection ConstantConditions
|
||||
builder.elseEntry(elseBranch);
|
||||
}
|
||||
} while (currIfExpression != null);
|
||||
|
||||
JetWhenExpression whenExpression = builder.toExpression(ifExpression.getProject());
|
||||
if (WhenUtils.checkIntroduceWhenSubject(whenExpression)) {
|
||||
whenExpression = WhenUtils.introduceWhenSubject(whenExpression);
|
||||
}
|
||||
|
||||
ifExpression.replace(whenExpression);
|
||||
}
|
||||
|
||||
private static String combineWhenConditions(JetWhenCondition[] conditions, JetExpression subject) {
|
||||
int n = conditions.length;
|
||||
if (n == 0) return "";
|
||||
|
||||
JetWhenCondition condition = conditions[0];
|
||||
assert condition != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
String text = WhenUtils.whenConditionToExpressionText(condition, subject);
|
||||
if (n > 1) {
|
||||
text = parenthesizeTextIfNeeded(text);
|
||||
}
|
||||
sb.append(text);
|
||||
|
||||
for (int i = 1; i < n; i++) {
|
||||
JetWhenCondition currCondition = conditions[i];
|
||||
assert currCondition != null : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
sb.append(" || ").append(parenthesizeTextIfNeeded(WhenUtils.whenConditionToExpressionText(currCondition, subject)));
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static void transformWhenToIf(@NotNull JetWhenExpression whenExpression) {
|
||||
JetPsiFactory.IfChainBuilder builder = new JetPsiFactory.IfChainBuilder();
|
||||
|
||||
List<JetWhenEntry> entries = whenExpression.getEntries();
|
||||
for (JetWhenEntry entry : entries) {
|
||||
JetExpression branch = entry.getExpression();
|
||||
|
||||
if (entry.isElse()) {
|
||||
builder.elseBranch(branch);
|
||||
} else {
|
||||
String branchConditionText = combineWhenConditions(entry.getConditions(), whenExpression.getSubjectExpression());
|
||||
builder.ifBranch(branchConditionText, JetPsiUtil.getText(branch));
|
||||
}
|
||||
}
|
||||
|
||||
whenExpression.replace(builder.toExpression(whenExpression.getProject()));
|
||||
}
|
||||
}
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetProperty;
|
||||
import org.jetbrains.jet.lang.psi.JetReturnExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public enum UnfoldableKind implements Transformer {
|
||||
ASSIGNMENT_TO_IF("unfold.assignment.to.if") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, JetFile file) {
|
||||
BranchedUnfoldingUtils.unfoldAssignmentToIf((JetBinaryExpression) element, editor);
|
||||
}
|
||||
},
|
||||
PROPERTY_TO_IF("unfold.property.to.if") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, JetFile file) {
|
||||
BranchedUnfoldingUtils.unfoldPropertyToIf((JetProperty) element, file);
|
||||
}
|
||||
},
|
||||
RETURN_TO_IF("unfold.return.to.if") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, JetFile file) {
|
||||
BranchedUnfoldingUtils.unfoldReturnToIf((JetReturnExpression) element);
|
||||
}
|
||||
},
|
||||
ASSIGNMENT_TO_WHEN("unfold.assignment.to.when") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, JetFile file) {
|
||||
BranchedUnfoldingUtils.unfoldAssignmentToWhen((JetBinaryExpression) element, editor);
|
||||
}
|
||||
},
|
||||
PROPERTY_TO_WHEN("unfold.property.to.when") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, JetFile file) {
|
||||
BranchedUnfoldingUtils.unfoldPropertyToWhen((JetProperty) element, file);
|
||||
}
|
||||
},
|
||||
RETURN_TO_WHEN("unfold.return.to.when") {
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, JetFile file) {
|
||||
BranchedUnfoldingUtils.unfoldReturnToWhen((JetReturnExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private final String key;
|
||||
|
||||
private UnfoldableKind(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations;
|
||||
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.util.JetPsiMatcher;
|
||||
|
||||
import static org.jetbrains.jet.lang.psi.JetPsiUnparsingUtils.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WhenUtils {
|
||||
private WhenUtils() {
|
||||
}
|
||||
|
||||
public static final String TRANSFORM_WITHOUT_CHECK =
|
||||
"Expression must be checked before applying transformation";
|
||||
|
||||
private static void assertNotNull(Object expression) {
|
||||
assert expression != null : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
|
||||
private static JetExpression getWhenConditionSubjectCandidate(JetExpression condition) {
|
||||
if (condition instanceof JetIsExpression) {
|
||||
return ((JetIsExpression) condition).getLeftHandSide();
|
||||
}
|
||||
|
||||
if (condition instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) condition;
|
||||
IElementType op = binaryExpression.getOperationToken();
|
||||
if (op == JetTokens.EQEQ || op == JetTokens.IN_KEYWORD || op == JetTokens.NOT_IN) {
|
||||
return ((JetBinaryExpression) condition).getLeft();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JetExpression getWhenSubjectCandidate(@NotNull JetWhenExpression whenExpression) {
|
||||
if (whenExpression.getSubjectExpression() != null) return null;
|
||||
|
||||
JetExpression lastCandidate = null;
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
JetWhenCondition[] conditions = entry.getConditions();
|
||||
|
||||
if (!entry.isElse() && conditions.length == 0) return null;
|
||||
|
||||
for (JetWhenCondition condition : conditions) {
|
||||
if (!(condition instanceof JetWhenConditionWithExpression)) return null;
|
||||
|
||||
JetExpression currCandidate = getWhenConditionSubjectCandidate(((JetWhenConditionWithExpression) condition).getExpression());
|
||||
|
||||
if (!(currCandidate instanceof JetSimpleNameExpression)) return null;
|
||||
|
||||
if (lastCandidate == null) {
|
||||
lastCandidate = currCandidate;
|
||||
}
|
||||
else if (!JetPsiMatcher.checkElementMatch(lastCandidate, currCandidate)) return null;
|
||||
}
|
||||
}
|
||||
|
||||
return lastCandidate;
|
||||
}
|
||||
|
||||
public static boolean checkFlattenWhen(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subject = whenExpression.getSubjectExpression();
|
||||
|
||||
if (subject != null && !(subject instanceof JetSimpleNameExpression)) return false;
|
||||
|
||||
if (!JetPsiUtil.checkWhenExpressionHasSingleElse(whenExpression)) return false;
|
||||
|
||||
JetExpression elseBranch = whenExpression.getElseExpression();
|
||||
if (!(elseBranch instanceof JetWhenExpression)) return false;
|
||||
|
||||
JetWhenExpression nestedWhenExpression = (JetWhenExpression) elseBranch;
|
||||
|
||||
return JetPsiUtil.checkWhenExpressionHasSingleElse(nestedWhenExpression) &&
|
||||
JetPsiMatcher.checkElementMatch(subject, nestedWhenExpression.getSubjectExpression());
|
||||
}
|
||||
|
||||
public static boolean checkIntroduceWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
return getWhenSubjectCandidate(whenExpression) != null;
|
||||
}
|
||||
|
||||
public static boolean checkEliminateWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
return whenExpression.getSubjectExpression() instanceof JetSimpleNameExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetWhenExpression flattenWhen(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subjectExpression = whenExpression.getSubjectExpression();
|
||||
|
||||
JetExpression elseBranch = whenExpression.getElseExpression();
|
||||
assert elseBranch instanceof JetWhenExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetWhenExpression nestedWhenExpression = (JetWhenExpression) elseBranch;
|
||||
|
||||
List<JetWhenEntry> outerEntries = whenExpression.getEntries();
|
||||
List<JetWhenEntry> innerEntries = nestedWhenExpression.getEntries();
|
||||
|
||||
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder(subjectExpression);
|
||||
|
||||
for (JetWhenEntry entry : outerEntries) {
|
||||
if (entry.isElse()) continue;
|
||||
|
||||
builder.entry(entry);
|
||||
}
|
||||
|
||||
for (JetWhenEntry entry : innerEntries) {
|
||||
builder.entry(entry);
|
||||
}
|
||||
|
||||
JetWhenExpression newWhenExpression = builder.toExpression(whenExpression.getProject());
|
||||
whenExpression.replace(newWhenExpression);
|
||||
|
||||
return newWhenExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetWhenExpression introduceWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subject = getWhenSubjectCandidate(whenExpression);
|
||||
assertNotNull(subject);
|
||||
|
||||
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder(subject);
|
||||
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
JetExpression branchExpression = entry.getExpression();
|
||||
|
||||
if (entry.isElse()) {
|
||||
builder.elseEntry(branchExpression);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (JetWhenCondition condition : entry.getConditions()) {
|
||||
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
|
||||
|
||||
if (conditionExpression instanceof JetIsExpression) {
|
||||
JetIsExpression isExpression = (JetIsExpression) conditionExpression;
|
||||
builder.pattern(isExpression.getTypeRef(), isExpression.isNegated());
|
||||
}
|
||||
else if (conditionExpression instanceof JetBinaryExpression) {
|
||||
JetBinaryExpression binaryExpression = (JetBinaryExpression) conditionExpression;
|
||||
|
||||
JetExpression rhs = binaryExpression.getRight();
|
||||
|
||||
IElementType op = binaryExpression.getOperationToken();
|
||||
if (op == JetTokens.IN_KEYWORD) {
|
||||
builder.range(rhs, false);
|
||||
}
|
||||
else if (op == JetTokens.NOT_IN) {
|
||||
builder.range(rhs, true);
|
||||
}
|
||||
else if (op == JetTokens.EQEQ) {
|
||||
builder.condition(rhs);
|
||||
}
|
||||
else assert false : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
else assert false : TRANSFORM_WITHOUT_CHECK;
|
||||
}
|
||||
|
||||
builder.branchExpression(branchExpression);
|
||||
}
|
||||
|
||||
JetWhenExpression newWhenExpression = builder.toExpression(whenExpression.getProject());
|
||||
whenExpression.replace(newWhenExpression);
|
||||
|
||||
return newWhenExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static String whenConditionToExpressionText(@NotNull JetWhenCondition condition, JetExpression subject) {
|
||||
if (condition instanceof JetWhenConditionIsPattern) {
|
||||
JetWhenConditionIsPattern patternCondition = (JetWhenConditionIsPattern) condition;
|
||||
return toBinaryExpression(subject, (patternCondition.isNegated() ? "!is" : "is"), patternCondition.getTypeRef());
|
||||
}
|
||||
|
||||
if (condition instanceof JetWhenConditionInRange) {
|
||||
JetWhenConditionInRange rangeCondition = (JetWhenConditionInRange) condition;
|
||||
return toBinaryExpression(subject, rangeCondition.getOperationReference().getText(), rangeCondition.getRangeExpression());
|
||||
}
|
||||
|
||||
assert condition instanceof JetWhenConditionWithExpression : TRANSFORM_WITHOUT_CHECK;
|
||||
|
||||
JetExpression conditionExpression = ((JetWhenConditionWithExpression) condition).getExpression();
|
||||
|
||||
if (subject != null) {
|
||||
return toBinaryExpression(parenthesizeIfNeeded(subject), "==", parenthesizeIfNeeded(conditionExpression));
|
||||
}
|
||||
return JetPsiUtil.getText(conditionExpression);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetWhenExpression eliminateWhenSubject(@NotNull JetWhenExpression whenExpression) {
|
||||
JetExpression subject = whenExpression.getSubjectExpression();
|
||||
assertNotNull(subject);
|
||||
|
||||
JetPsiFactory.WhenBuilder builder = new JetPsiFactory.WhenBuilder();
|
||||
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
JetExpression branchExpression = entry.getExpression();
|
||||
|
||||
if (entry.isElse()) {
|
||||
builder.elseEntry(branchExpression);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (JetWhenCondition condition : entry.getConditions()) {
|
||||
builder.condition(whenConditionToExpressionText(condition, subject));
|
||||
}
|
||||
|
||||
builder.branchExpression(branchExpression);
|
||||
}
|
||||
|
||||
JetWhenExpression newWhenExpression = builder.toExpression(whenExpression.getProject());
|
||||
whenExpression.replace(newWhenExpression);
|
||||
|
||||
return newWhenExpression;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core;
|
||||
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
public interface Transformer {
|
||||
@NotNull
|
||||
String getKey();
|
||||
void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file);
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.WhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class EliminateWhenSubjectIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "eliminate.when.subject";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
WhenUtils.eliminateWhenSubject((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return input instanceof JetWhenExpression && WhenUtils.checkEliminateWhenSubject((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public EliminateWhenSubjectIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.WhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class FlattenWhenIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "flatten.when";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
WhenUtils.flattenWhen((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return input instanceof JetWhenExpression && WhenUtils.checkFlattenWhen((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public FlattenWhenIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.BranchedFoldingUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.FoldableKind;
|
||||
|
||||
public abstract class FoldBranchedExpressionIntention extends AbstractCodeTransformationIntention<FoldableKind> {
|
||||
protected FoldBranchedExpressionIntention(@NotNull final FoldableKind foldableKind) {
|
||||
super(
|
||||
foldableKind,
|
||||
new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return (input instanceof JetExpression) && BranchedFoldingUtils.getFoldableExpressionKind((JetExpression) input) == foldableKind;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static class FoldIfToAssignmentIntention extends FoldBranchedExpressionIntention {
|
||||
public FoldIfToAssignmentIntention() {
|
||||
super(FoldableKind.IF_TO_ASSIGNMENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FoldIfToReturnAsymmetricallyIntention extends FoldBranchedExpressionIntention {
|
||||
public FoldIfToReturnAsymmetricallyIntention() {
|
||||
super(FoldableKind.IF_TO_RETURN_ASYMMETRICALLY);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FoldIfToReturnIntention extends FoldBranchedExpressionIntention {
|
||||
public FoldIfToReturnIntention() {
|
||||
super(FoldableKind.IF_TO_RETURN);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FoldWhenToAssignmentIntention extends FoldBranchedExpressionIntention {
|
||||
public FoldWhenToAssignmentIntention() {
|
||||
super(FoldableKind.WHEN_TO_ASSIGNMENT);
|
||||
}
|
||||
}
|
||||
|
||||
public static class FoldWhenToReturnIntention extends FoldBranchedExpressionIntention {
|
||||
public FoldWhenToReturnIntention() {
|
||||
super(FoldableKind.WHEN_TO_RETURN);
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetIfExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.IfWhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class IfToWhenIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "if.to.when";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
IfWhenUtils.transformIfToWhen((JetIfExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return (input instanceof JetIfExpression) && IfWhenUtils.checkIfToWhen((JetIfExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public IfToWhenIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.WhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class IntroduceWhenSubjectIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "introduce.when.subject";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
WhenUtils.introduceWhenSubject((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return input instanceof JetWhenExpression && WhenUtils.checkIntroduceWhenSubject((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public IntroduceWhenSubjectIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.*;
|
||||
|
||||
public abstract class UnfoldBranchedExpressionIntention extends AbstractCodeTransformationIntention<UnfoldableKind> {
|
||||
protected UnfoldBranchedExpressionIntention(@NotNull final UnfoldableKind unfoldableKind) {
|
||||
super(
|
||||
unfoldableKind,
|
||||
new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return (input instanceof JetExpression) && BranchedUnfoldingUtils.getUnfoldableExpressionKind((JetExpression) input) == unfoldableKind;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public static class UnfoldAssignmentToIfIntention extends UnfoldBranchedExpressionIntention {
|
||||
public UnfoldAssignmentToIfIntention() {
|
||||
super(UnfoldableKind.ASSIGNMENT_TO_IF);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnfoldPropertyToIfIntention extends UnfoldBranchedExpressionIntention {
|
||||
public UnfoldPropertyToIfIntention() {
|
||||
super(UnfoldableKind.PROPERTY_TO_IF);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnfoldAssignmentToWhenIntention extends UnfoldBranchedExpressionIntention {
|
||||
public UnfoldAssignmentToWhenIntention() {
|
||||
super(UnfoldableKind.ASSIGNMENT_TO_WHEN);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnfoldPropertyToWhenIntention extends UnfoldBranchedExpressionIntention {
|
||||
public UnfoldPropertyToWhenIntention() {
|
||||
super(UnfoldableKind.PROPERTY_TO_WHEN);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnfoldReturnToIfIntention extends UnfoldBranchedExpressionIntention {
|
||||
public UnfoldReturnToIfIntention() {
|
||||
super(UnfoldableKind.RETURN_TO_IF);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnfoldReturnToWhenIntention extends UnfoldBranchedExpressionIntention {
|
||||
public UnfoldReturnToWhenIntention() {
|
||||
super(UnfoldableKind.RETURN_TO_WHEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.plugin.codeInsight.codeTransformations.branchedTransformations.intentions;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.psi.JetWhenExpression;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.AbstractCodeTransformationIntention;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.IfWhenUtils;
|
||||
import org.jetbrains.jet.plugin.codeInsight.codeTransformations.branchedTransformations.core.Transformer;
|
||||
|
||||
public class WhenToIfIntention extends AbstractCodeTransformationIntention<Transformer> {
|
||||
private static final Transformer TRANSFORMER = new Transformer() {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getKey() {
|
||||
return "when.to.if";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull PsiElement element, @NotNull Editor editor, @NotNull JetFile file) {
|
||||
IfWhenUtils.transformWhenToIf((JetWhenExpression) element);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate<PsiElement> IS_APPLICABLE = new Predicate<PsiElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable PsiElement input) {
|
||||
return (input instanceof JetWhenExpression) && IfWhenUtils.checkWhenToIf((JetWhenExpression) input);
|
||||
}
|
||||
};
|
||||
|
||||
public WhenToIfIntention() {
|
||||
super(TRANSFORMER, IS_APPLICABLE);
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver;
|
||||
|
||||
class KotlinSignatureUtil {
|
||||
static final String KOTLIN_SIGNATURE_ANNOTATION = JvmStdlibNames.KOTLIN_SIGNATURE.getFqName().getFqName();
|
||||
static final String KOTLIN_SIGNATURE_ANNOTATION = JvmStdlibNames.KOTLIN_SIGNATURE.getFqName().asString();
|
||||
|
||||
private KotlinSignatureUtil() {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.upDownMover;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineMover;
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineRange;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
|
||||
public abstract class AbstractJetUpDownMover extends LineMover {
|
||||
protected AbstractJetUpDownMover() {
|
||||
}
|
||||
|
||||
protected abstract boolean checkSourceElement(@NotNull PsiElement element);
|
||||
protected abstract LineRange getElementSourceLineRange(@NotNull PsiElement element, @NotNull Editor editor, @NotNull LineRange oldRange);
|
||||
|
||||
@Nullable
|
||||
protected LineRange getSourceRange(@NotNull PsiElement firstElement, @NotNull PsiElement lastElement, @NotNull Editor editor, LineRange oldRange) {
|
||||
if (firstElement == lastElement) {
|
||||
LineRange sourceRange = getElementSourceLineRange(firstElement, editor, oldRange);
|
||||
|
||||
if (sourceRange != null) {
|
||||
sourceRange.firstElement = sourceRange.lastElement = firstElement;
|
||||
}
|
||||
|
||||
return sourceRange;
|
||||
}
|
||||
|
||||
PsiElement parent = PsiTreeUtil.findCommonParent(firstElement, lastElement);
|
||||
if (parent == null) return null;
|
||||
|
||||
Pair<PsiElement, PsiElement> combinedRange = getElementRange(parent, firstElement, lastElement);
|
||||
|
||||
if (combinedRange == null
|
||||
|| !checkSourceElement(combinedRange.first)
|
||||
|| !checkSourceElement(combinedRange.second)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
LineRange lineRange1 = getElementSourceLineRange(combinedRange.first, editor, oldRange);
|
||||
if (lineRange1 == null) return null;
|
||||
|
||||
LineRange lineRange2 = getElementSourceLineRange(combinedRange.second, editor, oldRange);
|
||||
if (lineRange2 == null) return null;
|
||||
|
||||
LineRange sourceRange = new LineRange(lineRange1.startLine, lineRange2.endLine);
|
||||
sourceRange.firstElement = combinedRange.first;
|
||||
sourceRange.lastElement = combinedRange.second;
|
||||
|
||||
return sourceRange;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement getSiblingOfType(@NotNull PsiElement element, boolean down, @NotNull Class<? extends PsiElement> type) {
|
||||
return down ? PsiTreeUtil.getNextSiblingOfType(element, type) : PsiTreeUtil.getPrevSiblingOfType(element, type);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement firstNonWhiteSibling(@NotNull LineRange lineRange, boolean down) {
|
||||
return firstNonWhiteElement(down ? lineRange.lastElement.getNextSibling() : lineRange.firstElement.getPrevSibling(), down);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static PsiElement firstNonWhiteSibling(@NotNull PsiElement element, boolean down) {
|
||||
return firstNonWhiteElement(down ? element.getNextSibling() : element.getPrevSibling(), down);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
||||
return (file instanceof JetFile) && super.checkAvailable(editor, file, info, down);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.upDownMover;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineRange;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class JetDeclarationMover extends AbstractJetUpDownMover {
|
||||
public JetDeclarationMover() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<PsiElement> getDeclarationAnchors(@NotNull JetDeclaration declaration) {
|
||||
final List<PsiElement> memberSuspects = new ArrayList<PsiElement>();
|
||||
|
||||
JetModifierList modifierList = declaration.getModifierList();
|
||||
if (modifierList != null) memberSuspects.add(modifierList);
|
||||
|
||||
if (declaration instanceof JetNamedDeclaration) {
|
||||
PsiElement nameIdentifier = ((JetNamedDeclaration) declaration).getNameIdentifier();
|
||||
if (nameIdentifier != null) memberSuspects.add(nameIdentifier);
|
||||
}
|
||||
|
||||
declaration.accept(
|
||||
new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitAnonymousInitializer(JetClassInitializer initializer) {
|
||||
PsiElement brace = initializer.getOpenBraceNode();
|
||||
if (brace != null) {
|
||||
memberSuspects.add(brace);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitClassObject(JetClassObject classObject) {
|
||||
PsiElement classKeyword = classObject.getClassKeywordNode();
|
||||
if (classKeyword != null) memberSuspects.add(classKeyword);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(JetNamedFunction function) {
|
||||
PsiElement equalsToken = function.getEqualsToken();
|
||||
if (equalsToken != null) memberSuspects.add(equalsToken);
|
||||
|
||||
JetTypeParameterList typeParameterList = function.getTypeParameterList();
|
||||
if (typeParameterList != null) memberSuspects.add(typeParameterList);
|
||||
|
||||
JetTypeReference receiverTypeRef = function.getReceiverTypeRef();
|
||||
if (receiverTypeRef != null) memberSuspects.add(receiverTypeRef);
|
||||
|
||||
JetTypeReference returnTypeRef = function.getReturnTypeRef();
|
||||
if (returnTypeRef != null) memberSuspects.add(returnTypeRef);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProperty(JetProperty property) {
|
||||
PsiElement valOrVarNode = property.getValOrVarNode().getPsi();
|
||||
if (valOrVarNode != null) memberSuspects.add(valOrVarNode);
|
||||
|
||||
JetTypeParameterList typeParameterList = property.getTypeParameterList();
|
||||
if (typeParameterList != null) memberSuspects.add(typeParameterList);
|
||||
|
||||
JetTypeReference receiverTypeRef = property.getReceiverTypeRef();
|
||||
if (receiverTypeRef != null) memberSuspects.add(receiverTypeRef);
|
||||
|
||||
JetTypeReference returnTypeRef = property.getTypeRef();
|
||||
if (returnTypeRef != null) memberSuspects.add(returnTypeRef);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return memberSuspects;
|
||||
}
|
||||
|
||||
private static final Class[] DECLARATION_CONTAINER_CLASSES =
|
||||
{JetClassBody.class, JetClassInitializer.class, JetFunction.class, JetPropertyAccessor.class, JetFile.class};
|
||||
|
||||
private static final Class[] CLASSBODYLIKE_DECLARATION_CONTAINER_CLASSES = {JetClassBody.class, JetFile.class};
|
||||
|
||||
@Nullable
|
||||
private static JetDeclaration getMovableDeclaration(@Nullable PsiElement element) {
|
||||
if (element == null) return null;
|
||||
|
||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetDeclaration.class, false);
|
||||
if (declaration instanceof JetTypeParameter) {
|
||||
return getMovableDeclaration(declaration.getParent());
|
||||
}
|
||||
|
||||
return PsiTreeUtil.instanceOf(PsiTreeUtil.getParentOfType(declaration,
|
||||
DECLARATION_CONTAINER_CLASSES),
|
||||
CLASSBODYLIKE_DECLARATION_CONTAINER_CLASSES) ? declaration : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkSourceElement(@NotNull PsiElement element) {
|
||||
return element instanceof JetDeclaration;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LineRange getElementSourceLineRange(@NotNull PsiElement element, @NotNull Editor editor, @NotNull LineRange oldRange) {
|
||||
JetDeclaration declaration = (JetDeclaration) element;
|
||||
|
||||
Document doc = editor.getDocument();
|
||||
TextRange textRange = declaration.getTextRange();
|
||||
if (doc.getTextLength() < textRange.getEndOffset()) return null;
|
||||
|
||||
int startLine = editor.offsetToLogicalPosition(textRange.getStartOffset()).line;
|
||||
int endLine = editor.offsetToLogicalPosition(textRange.getEndOffset()).line + 1;
|
||||
|
||||
if (startLine == oldRange.startLine || startLine == oldRange.endLine
|
||||
|| endLine == oldRange.startLine || endLine == oldRange.endLine) {
|
||||
return new LineRange(startLine, endLine);
|
||||
}
|
||||
|
||||
TextRange lineTextRange = new TextRange(doc.getLineStartOffset(oldRange.startLine),
|
||||
doc.getLineEndOffset(oldRange.endLine));
|
||||
for (PsiElement anchor : getDeclarationAnchors(declaration)) {
|
||||
TextRange suspectTextRange = anchor.getTextRange();
|
||||
if (suspectTextRange != null && lineTextRange.intersects(suspectTextRange)) return new LineRange(startLine, endLine);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LineRange getTargetRange(
|
||||
@NotNull Editor editor,
|
||||
@NotNull PsiElement sibling,
|
||||
boolean down,
|
||||
@NotNull PsiElement target
|
||||
) {
|
||||
PsiElement start = sibling;
|
||||
PsiElement end = sibling;
|
||||
|
||||
PsiElement nextParent = null;
|
||||
|
||||
// moving out of code block
|
||||
if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)) {
|
||||
// elements which aren't immediately placed in class body can't leave the block
|
||||
PsiElement parent = sibling.getParent();
|
||||
if (!(parent instanceof JetClassBody)) return null;
|
||||
|
||||
JetClassOrObject jetClassOrObject = (JetClassOrObject) parent.getParent();
|
||||
assert jetClassOrObject != null;
|
||||
|
||||
nextParent = jetClassOrObject.getParent();
|
||||
|
||||
if (!down) {
|
||||
start = jetClassOrObject;
|
||||
}
|
||||
}
|
||||
// moving into code block
|
||||
// element may move only into class body
|
||||
else if (sibling instanceof JetClassOrObject) {
|
||||
JetClassOrObject jetClassOrObject = (JetClassOrObject) sibling;
|
||||
JetClassBody classBody = jetClassOrObject.getBody();
|
||||
|
||||
// confined elements can't leave their block
|
||||
if (classBody != null) {
|
||||
nextParent = classBody;
|
||||
start = down ? jetClassOrObject : classBody.getRBrace();
|
||||
end = down ? classBody.getLBrace() : classBody.getRBrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (nextParent != null) {
|
||||
if (target instanceof JetClassInitializer && !(nextParent instanceof JetClassBody)) return null;
|
||||
|
||||
if (target instanceof JetEnumEntry) {
|
||||
if (!(nextParent instanceof JetClassBody)) return null;
|
||||
|
||||
JetClassOrObject nextClassOrObject = (JetClassOrObject) nextParent.getParent();
|
||||
assert nextClassOrObject != null;
|
||||
|
||||
if (!nextClassOrObject.hasModifier(JetTokens.ENUM_KEYWORD)) return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (target instanceof JetPropertyAccessor && !(sibling instanceof JetPropertyAccessor)) return null;
|
||||
|
||||
return start != null && end != null ? new LineRange(start, end, editor.getDocument()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
||||
if (!super.checkAvailable(editor, file, info, down)) return false;
|
||||
|
||||
LineRange oldRange = info.toMove;
|
||||
|
||||
Pair<PsiElement, PsiElement> psiRange = getElementRange(editor, file, oldRange);
|
||||
if (psiRange == null) return false;
|
||||
|
||||
JetDeclaration firstDecl = getMovableDeclaration(psiRange.getFirst());
|
||||
if (firstDecl == null) return false;
|
||||
|
||||
JetDeclaration lastDecl = getMovableDeclaration(psiRange.getSecond());
|
||||
if (lastDecl == null) return false;
|
||||
|
||||
//noinspection ConstantConditions
|
||||
LineRange sourceRange = getSourceRange(firstDecl, lastDecl, editor, oldRange);
|
||||
if (sourceRange == null) return false;
|
||||
|
||||
PsiElement sibling = firstNonWhiteSibling(sourceRange, down);
|
||||
|
||||
// Either reached last sibling, or jumped over multi-line whitespace
|
||||
if (sibling == null) {
|
||||
info.toMove2 = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
info.toMove = sourceRange;
|
||||
info.toMove2 = getTargetRange(editor, sibling, down, sourceRange.firstElement);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
package org.jetbrains.jet.plugin.codeInsight.upDownMover;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.moveUpDown.LineRange;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetExpressionMover extends AbstractJetUpDownMover {
|
||||
public JetExpressionMover() {
|
||||
}
|
||||
|
||||
private final static Class[] MOVABLE_ELEMENT_CLASSES = {JetExpression.class, JetWhenEntry.class, JetValueArgument.class, PsiComment.class};
|
||||
|
||||
private final static Class[] BLOCKLIKE_ELEMENT_CLASSES =
|
||||
{JetBlockExpression.class, JetWhenExpression.class, JetClassBody.class, JetFile.class};
|
||||
|
||||
private final static Class[] FUNCTIONLIKE_ELEMENT_CLASSES =
|
||||
{JetFunction.class, JetPropertyAccessor.class, JetClassInitializer.class};
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getStandaloneClosingBrace(@NotNull PsiFile file, @NotNull Editor editor) {
|
||||
LineRange range = getLineRangeFromSelection(editor);
|
||||
if (range.endLine - range.startLine != 1) return null;
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
Document document = editor.getDocument();
|
||||
int line = document.getLineNumber(offset);
|
||||
int lineStartOffset = document.getLineStartOffset(line);
|
||||
String lineText = document.getText().substring(lineStartOffset, document.getLineEndOffset(line));
|
||||
if (!lineText.trim().equals("}")) return null;
|
||||
|
||||
return file.findElementAt(lineStartOffset + lineText.indexOf('}'));
|
||||
}
|
||||
|
||||
private static BraceStatus checkForMovableDownClosingBrace(
|
||||
@NotNull PsiElement closingBrace,
|
||||
@NotNull PsiElement block,
|
||||
@NotNull Editor editor,
|
||||
@NotNull MoveInfo info
|
||||
) {
|
||||
PsiElement current = block;
|
||||
PsiElement nextElement = null;
|
||||
PsiElement nextExpression = null;
|
||||
do {
|
||||
PsiElement sibling = firstNonWhiteElement(current.getNextSibling(), true);
|
||||
if (sibling != null && nextElement == null) {
|
||||
nextElement = sibling;
|
||||
}
|
||||
|
||||
if (sibling instanceof JetExpression) {
|
||||
nextExpression = sibling;
|
||||
break;
|
||||
}
|
||||
|
||||
current = current.getParent();
|
||||
}
|
||||
while (current != null && !(PsiTreeUtil.instanceOf(current, BLOCKLIKE_ELEMENT_CLASSES)));
|
||||
|
||||
if (nextExpression == null) return BraceStatus.NOT_MOVABLE;
|
||||
|
||||
Document doc = editor.getDocument();
|
||||
|
||||
info.toMove = new LineRange(closingBrace, closingBrace, doc);
|
||||
info.toMove2 = new LineRange(nextElement, nextExpression);
|
||||
info.indentSource = true;
|
||||
|
||||
return BraceStatus.MOVABLE;
|
||||
}
|
||||
|
||||
private static BraceStatus checkForMovableUpClosingBrace(
|
||||
@NotNull PsiElement closingBrace,
|
||||
PsiElement block,
|
||||
@NotNull Editor editor,
|
||||
@NotNull MoveInfo info
|
||||
) {
|
||||
//noinspection unchecked
|
||||
PsiElement prev = JetPsiUtil.getLastChildByType(block, JetExpression.class);
|
||||
if (prev == null) return BraceStatus.NOT_MOVABLE;
|
||||
|
||||
Document doc = editor.getDocument();
|
||||
|
||||
info.toMove = new LineRange(closingBrace, closingBrace, doc);
|
||||
info.toMove2 = new LineRange(prev, prev, doc);
|
||||
info.indentSource = true;
|
||||
|
||||
return BraceStatus.MOVABLE;
|
||||
}
|
||||
|
||||
private static enum BraceStatus {
|
||||
NOT_FOUND,
|
||||
MOVABLE,
|
||||
NOT_MOVABLE
|
||||
}
|
||||
|
||||
// Returns null if standalone closing brace is not found
|
||||
private static BraceStatus checkForMovableClosingBrace(
|
||||
@NotNull Editor editor,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull MoveInfo info,
|
||||
boolean down
|
||||
) {
|
||||
PsiElement closingBrace = getStandaloneClosingBrace(file, editor);
|
||||
if (closingBrace == null) return BraceStatus.NOT_FOUND;
|
||||
|
||||
PsiElement blockLikeElement = closingBrace.getParent();
|
||||
if (!(blockLikeElement instanceof JetBlockExpression)) return BraceStatus.NOT_MOVABLE;
|
||||
|
||||
PsiElement blockParent = blockLikeElement.getParent();
|
||||
if (blockParent instanceof JetWhenEntry) return BraceStatus.NOT_FOUND;
|
||||
if (PsiTreeUtil.instanceOf(blockParent, FUNCTIONLIKE_ELEMENT_CLASSES)) return BraceStatus.NOT_FOUND;
|
||||
|
||||
PsiElement enclosingExpression = PsiTreeUtil.getParentOfType(blockLikeElement, JetExpression.class);
|
||||
|
||||
if (enclosingExpression instanceof JetDoWhileExpression) return BraceStatus.NOT_MOVABLE;
|
||||
|
||||
if (enclosingExpression instanceof JetIfExpression) {
|
||||
JetIfExpression ifExpression = (JetIfExpression) enclosingExpression;
|
||||
|
||||
if (blockLikeElement == ifExpression.getThen() && ifExpression.getElse() != null) return BraceStatus.NOT_MOVABLE;
|
||||
}
|
||||
|
||||
return down
|
||||
? checkForMovableDownClosingBrace(closingBrace, blockLikeElement, editor, info)
|
||||
: checkForMovableUpClosingBrace(closingBrace, blockLikeElement, editor, info);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JetBlockExpression findClosestBlock(@NotNull PsiElement anchor, boolean down) {
|
||||
PsiElement current = PsiTreeUtil.getParentOfType(anchor, JetBlockExpression.class);
|
||||
while (current != null) {
|
||||
PsiElement parent = current.getParent();
|
||||
if (parent instanceof JetClassBody ||
|
||||
parent instanceof JetClassInitializer ||
|
||||
parent instanceof JetFunction ||
|
||||
parent instanceof JetProperty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (parent instanceof JetBlockExpression) return (JetBlockExpression) parent;
|
||||
|
||||
PsiElement sibling = down ? current.getNextSibling() : current.getPrevSibling();
|
||||
if (sibling != null) {
|
||||
//noinspection unchecked
|
||||
JetBlockExpression block = JetPsiUtil.getOutermostJetElement(sibling, down, JetBlockExpression.class);
|
||||
if (block != null) return block;
|
||||
|
||||
current = sibling;
|
||||
}
|
||||
else {
|
||||
current = parent;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LineRange getExpressionTargetRange(@NotNull Editor editor, @NotNull PsiElement sibling, boolean down) {
|
||||
PsiElement start = sibling;
|
||||
PsiElement end = sibling;
|
||||
|
||||
// moving out of code block
|
||||
if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE)) {
|
||||
PsiElement parent = sibling.getParent();
|
||||
if (!(parent instanceof JetBlockExpression || parent instanceof JetFunctionLiteral)) return null;
|
||||
|
||||
JetBlockExpression newBlock = findClosestBlock(sibling, down);
|
||||
if (newBlock == null) return null;
|
||||
|
||||
if (PsiTreeUtil.isAncestor(newBlock, parent, true)) {
|
||||
PsiElement outermostParent = JetPsiUtil.getOutermostParent(parent, newBlock, true);
|
||||
|
||||
if (down) {
|
||||
end = outermostParent;
|
||||
}
|
||||
else {
|
||||
start = outermostParent;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (down) {
|
||||
end = newBlock.getLBrace();
|
||||
}
|
||||
else {
|
||||
start = newBlock.getRBrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// moving into code block
|
||||
//noinspection unchecked
|
||||
JetElement blockLikeElement = JetPsiUtil.getOutermostJetElement(sibling, down, JetBlockExpression.class, JetWhenExpression.class, JetClassBody.class);
|
||||
if (blockLikeElement != null &&
|
||||
!(PsiTreeUtil.instanceOf(blockLikeElement.getParent(), FUNCTIONLIKE_ELEMENT_CLASSES))) {
|
||||
if (blockLikeElement instanceof JetWhenExpression) {
|
||||
//noinspection unchecked
|
||||
blockLikeElement = JetPsiUtil.getOutermostJetElement(blockLikeElement, down, JetBlockExpression.class);
|
||||
}
|
||||
|
||||
if (blockLikeElement != null) {
|
||||
if (down) {
|
||||
end = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.LBRACE);
|
||||
}
|
||||
else {
|
||||
start = JetPsiUtil.findChildByType(blockLikeElement, JetTokens.RBRACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return start != null && end != null ? new LineRange(start, end, editor.getDocument()) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static LineRange getWhenEntryTargetRange(@NotNull Editor editor, @NotNull PsiElement sibling, boolean down) {
|
||||
if (sibling.getNode().getElementType() == (down ? JetTokens.RBRACE : JetTokens.LBRACE) &&
|
||||
PsiTreeUtil.getParentOfType(sibling, JetWhenEntry.class) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new LineRange(sibling, sibling, editor.getDocument());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LineRange getValueParamOrArgTargetRange(@NotNull Editor editor, @NotNull PsiElement elementToCheck, @NotNull PsiElement sibling, boolean down) {
|
||||
PsiElement next = sibling;
|
||||
|
||||
if (next.getNode().getElementType() == JetTokens.COMMA) {
|
||||
next = firstNonWhiteSibling(next, down);
|
||||
}
|
||||
|
||||
LineRange range = (next instanceof JetParameter || next instanceof JetValueArgument)
|
||||
? new LineRange(next, next, editor.getDocument())
|
||||
: null;
|
||||
|
||||
if (range != null) {
|
||||
parametersOrArgsToMove = new Pair<PsiElement, PsiElement>(elementToCheck, next);
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private LineRange getTargetRange(
|
||||
@NotNull Editor editor,
|
||||
@Nullable PsiElement elementToCheck,
|
||||
@NotNull PsiElement sibling,
|
||||
boolean down
|
||||
) {
|
||||
if (elementToCheck instanceof JetParameter || elementToCheck instanceof JetValueArgument) {
|
||||
return getValueParamOrArgTargetRange(editor, elementToCheck, sibling, down);
|
||||
}
|
||||
|
||||
if (elementToCheck instanceof JetExpression || elementToCheck instanceof PsiComment) {
|
||||
return getExpressionTargetRange(editor, sibling, down);
|
||||
}
|
||||
|
||||
if (elementToCheck instanceof JetWhenEntry) {
|
||||
return getWhenEntryTargetRange(editor, sibling, down);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkSourceElement(@NotNull PsiElement element) {
|
||||
return PsiTreeUtil.instanceOf(element, MOVABLE_ELEMENT_CLASSES);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LineRange getElementSourceLineRange(@NotNull PsiElement element, @NotNull Editor editor, @NotNull LineRange oldRange) {
|
||||
TextRange textRange = element.getTextRange();
|
||||
if (editor.getDocument().getTextLength() < textRange.getEndOffset()) return null;
|
||||
|
||||
int startLine = editor.offsetToLogicalPosition(textRange.getStartOffset()).line;
|
||||
int endLine = editor.offsetToLogicalPosition(textRange.getEndOffset()).line + 1;
|
||||
|
||||
return new LineRange(startLine, endLine);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getMovableElement(@NotNull PsiElement element, boolean lookRight) {
|
||||
PsiElement movableElement = PsiTreeUtil.getNonStrictParentOfType(element, MOVABLE_ELEMENT_CLASSES);
|
||||
if (movableElement == null) return null;
|
||||
|
||||
if (isBracelessBlock(movableElement)) {
|
||||
movableElement = firstNonWhiteElement(lookRight ? movableElement.getLastChild() : movableElement.getFirstChild(), !lookRight);
|
||||
}
|
||||
|
||||
return movableElement;
|
||||
}
|
||||
|
||||
private static boolean isLastOfItsKind(@NotNull PsiElement element, boolean down) {
|
||||
return getSiblingOfType(element, down, element.getClass()) == null;
|
||||
}
|
||||
|
||||
private static boolean isForbiddenMove(@NotNull PsiElement element, boolean down) {
|
||||
if (element instanceof JetParameter || element instanceof JetValueArgument) {
|
||||
return isLastOfItsKind(element, down);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isBracelessBlock(@NotNull PsiElement element) {
|
||||
if (!(element instanceof JetBlockExpression)) return false;
|
||||
|
||||
JetBlockExpression block = (JetBlockExpression) element;
|
||||
|
||||
return block.getLBrace() == null && block.getRBrace() == null;
|
||||
}
|
||||
|
||||
protected static PsiElement adjustWhiteSpaceSibling(
|
||||
@NotNull Editor editor,
|
||||
@NotNull LineRange sourceRange,
|
||||
@NotNull MoveInfo info,
|
||||
boolean down
|
||||
) {
|
||||
PsiElement element = down ? sourceRange.lastElement : sourceRange.firstElement;
|
||||
PsiElement sibling = down ? element.getNextSibling() : element.getPrevSibling();
|
||||
|
||||
PsiElement whiteSpaceTestSubject = sibling;
|
||||
if (sibling == null) {
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent != null && isBracelessBlock(parent)) {
|
||||
whiteSpaceTestSubject = down ? parent.getNextSibling() : parent.getPrevSibling();
|
||||
}
|
||||
}
|
||||
|
||||
if (whiteSpaceTestSubject instanceof PsiWhiteSpace) {
|
||||
Document doc = editor.getDocument();
|
||||
TextRange spaceRange = whiteSpaceTestSubject.getTextRange();
|
||||
|
||||
int startLine = doc.getLineNumber(spaceRange.getStartOffset());
|
||||
int endLine = doc.getLineNumber(spaceRange.getEndOffset());
|
||||
|
||||
if (endLine - startLine > 1) {
|
||||
int nearLine = down ? sourceRange.endLine : sourceRange.startLine - 1;
|
||||
|
||||
info.toMove = sourceRange;
|
||||
info.toMove2 = new LineRange(nearLine, nearLine + 1);
|
||||
info.indentTarget = false;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
if (sibling != null) {
|
||||
sibling = firstNonWhiteElement(sibling, down);
|
||||
}
|
||||
}
|
||||
|
||||
if (sibling == null) {
|
||||
info.toMove2 = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return sibling;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) {
|
||||
parametersOrArgsToMove = null;
|
||||
|
||||
if (!super.checkAvailable(editor, file, info, down)) return false;
|
||||
|
||||
switch (checkForMovableClosingBrace(editor, file, info, down)) {
|
||||
case NOT_MOVABLE: {
|
||||
info.toMove2 = null;
|
||||
return true;
|
||||
}
|
||||
case MOVABLE: return true;
|
||||
default: break;
|
||||
}
|
||||
|
||||
LineRange oldRange = info.toMove;
|
||||
|
||||
Pair<PsiElement, PsiElement> psiRange = getElementRange(editor, file, oldRange);
|
||||
if (psiRange == null) return false;
|
||||
|
||||
//noinspection unchecked
|
||||
PsiElement firstElement = getMovableElement(psiRange.getFirst(), false);
|
||||
PsiElement lastElement = getMovableElement(psiRange.getSecond(), true);
|
||||
|
||||
if (firstElement == null || lastElement == null) return false;
|
||||
|
||||
if (isForbiddenMove(firstElement, down) || isForbiddenMove(lastElement, down)) {
|
||||
info.toMove2 = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((firstElement instanceof JetParameter || firstElement instanceof JetValueArgument) && PsiTreeUtil.isAncestor(lastElement, firstElement, false)) {
|
||||
lastElement = firstElement;
|
||||
}
|
||||
|
||||
LineRange sourceRange = getSourceRange(firstElement, lastElement, editor, oldRange);
|
||||
if (sourceRange == null) return false;
|
||||
|
||||
PsiElement sibling = adjustWhiteSpaceSibling(editor, sourceRange, info, down);
|
||||
|
||||
// Either reached last sibling, or jumped over multi-line whitespace
|
||||
if (sibling == null) return true;
|
||||
|
||||
info.toMove = sourceRange;
|
||||
info.toMove2 = getTargetRange(editor, sourceRange.firstElement, sibling, down);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Pair<PsiElement, PsiElement> parametersOrArgsToMove;
|
||||
|
||||
private static PsiElement getComma(@NotNull PsiElement element) {
|
||||
PsiElement sibling = firstNonWhiteSibling(element, true);
|
||||
return sibling != null && (sibling.getNode().getElementType() == JetTokens.COMMA) ? sibling : null;
|
||||
}
|
||||
|
||||
private static void fixCommaIfNeeded(@NotNull PsiElement element, boolean willBeLast) {
|
||||
PsiElement comma = getComma(element);
|
||||
if (willBeLast && comma != null) {
|
||||
comma.delete();
|
||||
}
|
||||
else if (!willBeLast && comma == null) {
|
||||
PsiElement parent = element.getParent();
|
||||
assert parent != null;
|
||||
|
||||
parent.addAfter(JetPsiFactory.createComma(parent.getProject()), element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeMove(@NotNull Editor editor, @NotNull MoveInfo info, boolean down) {
|
||||
if (parametersOrArgsToMove != null) {
|
||||
PsiElement element1 = parametersOrArgsToMove.first;
|
||||
PsiElement element2 = parametersOrArgsToMove.second;
|
||||
|
||||
fixCommaIfNeeded(element1, down && isLastOfItsKind(element2, true));
|
||||
fixCommaIfNeeded(element2, !down && isLastOfItsKind(element1, true));
|
||||
|
||||
//noinspection ConstantConditions
|
||||
PsiDocumentManager.getInstance(editor.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,9 +68,9 @@ public final class DescriptorLookupConverter {
|
||||
}
|
||||
|
||||
LookupElementBuilder element = LookupElementBuilder.create(
|
||||
new JetLookupObject(descriptor, analyzer, declaration), descriptor.getName().getName());
|
||||
new JetLookupObject(descriptor, analyzer, declaration), descriptor.getName().asString());
|
||||
|
||||
String presentableText = descriptor.getName().getName();
|
||||
String presentableText = descriptor.getName().asString();
|
||||
String typeText = "";
|
||||
String tailText = "";
|
||||
boolean tailTextGrayed = true;
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.codeInsight.CommentUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lexer.JetToken;
|
||||
@@ -103,7 +102,7 @@ public class JetKeywordCompletionContributor extends CompletionContributor {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CommentUtilCore.isComment((PsiElement) element);
|
||||
return JetPsiUtil.isInComment((PsiElement) element);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,12 +43,12 @@ class ConvertedCode implements TextBlockTransferableData {
|
||||
|
||||
@Override
|
||||
public int getOffsets(int[] offsets, int index) {
|
||||
return 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setOffsets(int[] offsets, int index) {
|
||||
return 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
|
||||
@@ -227,7 +227,7 @@ public class JetImportOptimizer implements ImportOptimizer {
|
||||
for (JetSimpleNameExpression nameExpression : simpleNameExpressions) {
|
||||
Name referencedName = nameExpression.getReferencedNameAsName();
|
||||
if (fqName == null) {
|
||||
fqName = new FqName(referencedName.getName());
|
||||
fqName = new FqName(referencedName.asString());
|
||||
} else {
|
||||
fqName = QualifiedNamesUtil.combine(fqName, referencedName);
|
||||
}
|
||||
|
||||
@@ -27,9 +27,13 @@ import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.kdoc.lexer.KDocTokens;
|
||||
import org.jetbrains.jet.plugin.JetLanguage;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.JetNodeTypes.*;
|
||||
import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
@@ -38,6 +42,7 @@ import static org.jetbrains.jet.lexer.JetTokens.*;
|
||||
* @see Block for good JavaDoc documentation
|
||||
*/
|
||||
public class JetBlock extends AbstractBlock {
|
||||
private static final int KDOC_COMMENT_INDENT = 1;
|
||||
private final ASTAlignmentStrategy myAlignmentStrategy;
|
||||
private final Indent myIndent;
|
||||
private final CodeStyleSettings mySettings;
|
||||
@@ -208,6 +213,9 @@ public class JetBlock extends AbstractBlock {
|
||||
}
|
||||
return new ChildAttributes(Indent.getContinuationIndent(), null);
|
||||
}
|
||||
else if (type == DOC_COMMENT) {
|
||||
return new ChildAttributes(Indent.getSpaceIndent(KDOC_COMMENT_INDENT), null);
|
||||
}
|
||||
|
||||
if (isIncomplete()) {
|
||||
return super.getChildAttributes(newChildIndex);
|
||||
@@ -321,6 +329,11 @@ public class JetBlock extends AbstractBlock {
|
||||
.in(PROPERTY, FUN)
|
||||
.notForType(BLOCK)
|
||||
.set(Indent.getContinuationWithoutFirstIndent()),
|
||||
|
||||
ASTIndentStrategy.forNode("KDoc comment indent")
|
||||
.in(DOC_COMMENT)
|
||||
.forType(KDocTokens.LEADING_ASTERISK, KDocTokens.END)
|
||||
.set(Indent.getSpaceIndent(KDOC_COMMENT_INDENT)),
|
||||
};
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -34,8 +34,9 @@ public class JetFormattingModelBuilder implements FormattingModelBuilder {
|
||||
@NotNull
|
||||
@Override
|
||||
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
|
||||
PsiFile containingFile = element.getContainingFile().getViewProvider().getPsi(JetLanguage.INSTANCE);
|
||||
JetBlock block = new JetBlock(
|
||||
element.getNode(), ASTAlignmentStrategy.getNullStrategy(), Indent.getNoneIndent(), null, settings,
|
||||
containingFile.getNode(), ASTAlignmentStrategy.getNullStrategy(), Indent.getNoneIndent(), null, settings,
|
||||
createSpacingBuilder(settings));
|
||||
|
||||
return FormattingModelProvider.createFormattingModelForPsiFile(
|
||||
@@ -53,6 +54,7 @@ public class JetFormattingModelBuilder implements FormattingModelBuilder {
|
||||
.between(IMPORT_DIRECTIVE, IMPORT_DIRECTIVE).lineBreakInCode()
|
||||
.after(IMPORT_DIRECTIVE).blankLines(1)
|
||||
|
||||
.before(DOC_COMMENT).lineBreakInCode()
|
||||
.before(FUN).lineBreakInCode()
|
||||
.before(PROPERTY).lineBreakInCode()
|
||||
.between(FUN, FUN).blankLines(1)
|
||||
|
||||
@@ -247,7 +247,7 @@ public class DeprecatedAnnotationVisitor extends AfterAnalysisHighlightingVisito
|
||||
|
||||
private static String getDescriptorString(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
return DescriptorUtils.getFQName(descriptor).getFqName();
|
||||
return DescriptorUtils.getFQName(descriptor).asString();
|
||||
}
|
||||
else if (descriptor instanceof ConstructorDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||
|
||||
@@ -166,7 +166,7 @@ public class IdeRenderers {
|
||||
DeclarationDescriptor containingDeclaration = funDescriptor.getContainingDeclaration();
|
||||
if (containingDeclaration != null) {
|
||||
FqNameUnsafe fqName = DescriptorUtils.getFQName(containingDeclaration);
|
||||
stringBuilder.append(FqName.ROOT.equalsTo(fqName) ? "root package" : fqName.getFqName());
|
||||
stringBuilder.append(FqName.ROOT.equalsTo(fqName) ? "root package" : fqName.asString());
|
||||
}
|
||||
stringBuilder.append("</li>");
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class JetColorSettingsPage implements ColorSettingsPage {
|
||||
"\n" +
|
||||
"/**\n" +
|
||||
" * Doc comment here for `SomeClass`\n" +
|
||||
" * @see Iterator#next()\n" +
|
||||
" * <KDOC_TAG>@see</KDOC_TAG> Iterator#next()\n" +
|
||||
" */\n" +
|
||||
"[<ANNOTATION>Deprecated</ANNOTATION>]\n" +
|
||||
"<BUILTIN_ANNOTATION>public</BUILTIN_ANNOTATION> class <CLASS>MyClass</CLASS><<BUILTIN_ANNOTATION>out</BUILTIN_ANNOTATION> <TYPE_PARAMETER>T</TYPE_PARAMETER> : <TRAIT>Iterable</TRAIT><<TYPE_PARAMETER>T</TYPE_PARAMETER>>>(var <INSTANCE_PROPERTY><MUTABLE_VARIABLE>prop1</MUTABLE_VARIABLE></INSTANCE_PROPERTY> : Int) {\n" +
|
||||
@@ -126,6 +126,8 @@ public class JetColorSettingsPage implements ColorSettingsPage {
|
||||
new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.block.comment"), JetHighlightingColors.BLOCK_COMMENT),
|
||||
|
||||
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.kdoc.comment"), JetHighlightingColors.DOC_COMMENT),
|
||||
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.kdoc.tag"), JetHighlightingColors.KDOC_TAG),
|
||||
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.kdoc.value"), JetHighlightingColors.KDOC_TAG_VALUE),
|
||||
|
||||
new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.class"), JetHighlightingColors.CLASS),
|
||||
new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.type.parameter"), JetHighlightingColors.TYPE_PARAMETER),
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lexer.JetLexer;
|
||||
import org.jetbrains.jet.kdoc.lexer.KDocTokens;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -34,7 +34,7 @@ public class JetHighlighter extends SyntaxHighlighterBase {
|
||||
|
||||
@NotNull
|
||||
public Lexer getHighlightingLexer() {
|
||||
return new JetLexer();
|
||||
return new JetHighlightingLexer();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -83,6 +83,9 @@ public class JetHighlighter extends SyntaxHighlighterBase {
|
||||
keys.put(JetTokens.BLOCK_COMMENT, JetHighlightingColors.BLOCK_COMMENT);
|
||||
keys.put(JetTokens.DOC_COMMENT, JetHighlightingColors.DOC_COMMENT);
|
||||
|
||||
fillMap(keys, KDocTokens.CONTENT_TOKENS, JetHighlightingColors.DOC_COMMENT);
|
||||
keys.put(KDocTokens.TAG_NAME, JetHighlightingColors.KDOC_TAG);
|
||||
|
||||
keys.put(TokenType.BAD_CHARACTER, JetHighlightingColors.BAD_CHARACTER);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user