Merge branch 'master' into idea13
Adding move statement/move expression
This commit is contained in:
@@ -53,7 +53,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD,
|
||||
CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD, TRY_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD,
|
||||
WHEN_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS, EXCLEXCL,
|
||||
// MUL,
|
||||
// MUL,
|
||||
PLUS, MINUS, EXCL, DIV, PERC, LTEQ,
|
||||
// TODO GTEQ, foo<bar, baz>=x
|
||||
EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, SAFE_ACCESS, ELVIS,
|
||||
@@ -111,17 +111,17 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
);
|
||||
|
||||
private static final TokenSet STATEMENT_FIRST = TokenSet.orSet(
|
||||
EXPRESSION_FIRST,
|
||||
TokenSet.create(
|
||||
// declaration
|
||||
LBRACKET, // attribute
|
||||
FUN_KEYWORD,
|
||||
VAL_KEYWORD, VAR_KEYWORD,
|
||||
TRAIT_KEYWORD,
|
||||
CLASS_KEYWORD,
|
||||
TYPE_KEYWORD
|
||||
),
|
||||
MODIFIER_KEYWORDS
|
||||
EXPRESSION_FIRST,
|
||||
TokenSet.create(
|
||||
// declaration
|
||||
LBRACKET, // attribute
|
||||
FUN_KEYWORD,
|
||||
VAL_KEYWORD, VAR_KEYWORD,
|
||||
TRAIT_KEYWORD,
|
||||
CLASS_KEYWORD,
|
||||
TYPE_KEYWORD
|
||||
),
|
||||
MODIFIER_KEYWORDS
|
||||
);
|
||||
|
||||
/*package*/ static final TokenSet EXPRESSION_FOLLOW = TokenSet.create(
|
||||
@@ -174,7 +174,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
EQUALITY(EQEQ, EXCLEQ, EQEQEQ, EXCLEQEQEQ),
|
||||
CONJUNCTION(ANDAND),
|
||||
DISJUNCTION(OROR),
|
||||
// ARROW(JetTokens.ARROW),
|
||||
// ARROW(JetTokens.ARROW),
|
||||
ASSIGNMENT(EQ, PLUSEQ, MINUSEQ, MULTEQ, DIVEQ, PERCEQ),
|
||||
;
|
||||
|
||||
@@ -287,7 +287,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
* see the precedence table
|
||||
*/
|
||||
private void parseBinaryExpression(Precedence precedence) {
|
||||
// System.out.println(precedence.name() + " at " + myBuilder.getTokenText());
|
||||
// System.out.println(precedence.name() + " at " + myBuilder.getTokenText());
|
||||
|
||||
PsiBuilder.Marker expression = mark();
|
||||
|
||||
@@ -300,7 +300,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
|
||||
JetNodeType resultType = precedence.parseRightHandSide(operation, this);
|
||||
expression.done(resultType);
|
||||
expression = expression.precede();
|
||||
expression = expression.precede();
|
||||
}
|
||||
|
||||
expression.drop();
|
||||
@@ -310,7 +310,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
* operation? prefixExpression
|
||||
*/
|
||||
private void parsePrefixExpression() {
|
||||
// System.out.println("pre at " + myBuilder.getTokenText());
|
||||
// System.out.println("pre at " + myBuilder.getTokenText());
|
||||
|
||||
if (at(LBRACKET)) {
|
||||
if (!parseLocalDeclaration()) {
|
||||
@@ -485,10 +485,10 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
*/
|
||||
protected boolean parseCallWithClosure() {
|
||||
boolean success = false;
|
||||
// while (!myBuilder.newlineBeforeCurrentToken()
|
||||
// && (at(LBRACE)
|
||||
// while (!myBuilder.newlineBeforeCurrentToken()
|
||||
// && (at(LBRACE)
|
||||
while ((at(LBRACE)
|
||||
|| atSet(LABELS) && lookahead(1) == LBRACE)) {
|
||||
|| atSet(LABELS) && lookahead(1) == LBRACE)) {
|
||||
if (!at(LBRACE)) {
|
||||
assert _atSet(LABELS);
|
||||
parsePrefixExpression();
|
||||
@@ -520,7 +520,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
* ;
|
||||
*/
|
||||
private void parseAtomicExpression() {
|
||||
// System.out.println("atom at " + myBuilder.getTokenText());
|
||||
// System.out.println("atom at " + myBuilder.getTokenText());
|
||||
|
||||
if (at(LPAR)) {
|
||||
parseParenthesizedExpression();
|
||||
@@ -574,7 +574,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
parseDoWhile();
|
||||
}
|
||||
else if (atSet(CLASS_KEYWORD, FUN_KEYWORD, VAL_KEYWORD,
|
||||
VAR_KEYWORD, TYPE_KEYWORD)) {
|
||||
VAR_KEYWORD, TYPE_KEYWORD)) {
|
||||
parseLocalDeclaration();
|
||||
}
|
||||
else if (at(FIELD_IDENTIFIER)) {
|
||||
@@ -784,7 +784,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
|
||||
if (!at(ARROW)) {
|
||||
errorUntil("Expecting '->'", TokenSet.create(ARROW,
|
||||
RBRACE, EOL_OR_SEMICOLON));
|
||||
RBRACE, EOL_OR_SEMICOLON));
|
||||
}
|
||||
|
||||
if (at(ARROW)) {
|
||||
@@ -798,7 +798,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
}
|
||||
}
|
||||
else if (!atSet(WHEN_CONDITION_RECOVERY_SET)) {
|
||||
errorAndAdvance("Expecting '->'");
|
||||
errorAndAdvance("Expecting '->'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -982,8 +982,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
parseFunctionLiteralParametersAndType();
|
||||
|
||||
paramsFound = preferParamsToExpressions ?
|
||||
rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
|
||||
rollbackOrDropAt(rollbackMarker, ARROW);
|
||||
rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
|
||||
rollbackOrDropAt(rollbackMarker, ARROW);
|
||||
}
|
||||
|
||||
if (!paramsFound) {
|
||||
@@ -1047,8 +1047,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
}
|
||||
|
||||
private boolean rollbackOrDrop(PsiBuilder.Marker rollbackMarker,
|
||||
JetToken expected, String expectMessage,
|
||||
IElementType validForDrop) {
|
||||
JetToken expected, String expectMessage,
|
||||
IElementType validForDrop) {
|
||||
if (at(expected)) {
|
||||
advance(); // dropAt
|
||||
rollbackMarker.drop();
|
||||
@@ -1074,8 +1074,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
while (!eof()) {
|
||||
PsiBuilder.Marker parameter = mark();
|
||||
|
||||
// int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
|
||||
// createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
|
||||
// int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos)));
|
||||
// createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST, false);
|
||||
|
||||
expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW));
|
||||
|
||||
@@ -1135,8 +1135,8 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
}
|
||||
|
||||
return preferParamsToExpressions ?
|
||||
rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
|
||||
rollbackOrDropAt(rollbackMarker, ARROW);
|
||||
rollbackOrDrop(rollbackMarker, ARROW, "An -> is expected", RBRACE) :
|
||||
rollbackOrDropAt(rollbackMarker, ARROW);
|
||||
}
|
||||
|
||||
private void parseFunctionLiteralParametersAndType() {
|
||||
@@ -1252,38 +1252,38 @@ public class JetExpressionParsing extends AbstractJetParsing {
|
||||
* ;
|
||||
*/
|
||||
private IElementType parseLocalDeclarationRest(boolean isEnum) {
|
||||
IElementType keywordToken = tt();
|
||||
IElementType declType = null;
|
||||
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) {
|
||||
declType = myJetParsing.parseClass(isEnum);
|
||||
}
|
||||
else if (keywordToken == FUN_KEYWORD) {
|
||||
declType = myJetParsing.parseFunction();
|
||||
}
|
||||
else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
|
||||
declType = myJetParsing.parseProperty(true);
|
||||
}
|
||||
else if (keywordToken == TYPE_KEYWORD) {
|
||||
declType = myJetParsing.parseTypeDef();
|
||||
}
|
||||
else if (keywordToken == OBJECT_KEYWORD) {
|
||||
// Object expression may appear at the statement position: should parse it
|
||||
// as expression instead of object declaration
|
||||
// sample:
|
||||
// {
|
||||
// object : Thread() {
|
||||
// }
|
||||
// }
|
||||
IElementType lookahead = lookahead(1);
|
||||
if (lookahead == COLON || lookahead == LBRACE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
myJetParsing.parseObject(true, true);
|
||||
declType = OBJECT_DECLARATION;
|
||||
}
|
||||
return declType;
|
||||
}
|
||||
IElementType keywordToken = tt();
|
||||
IElementType declType = null;
|
||||
if (keywordToken == CLASS_KEYWORD || keywordToken == TRAIT_KEYWORD) {
|
||||
declType = myJetParsing.parseClass(isEnum);
|
||||
}
|
||||
else if (keywordToken == FUN_KEYWORD) {
|
||||
declType = myJetParsing.parseFunction();
|
||||
}
|
||||
else if (keywordToken == VAL_KEYWORD || keywordToken == VAR_KEYWORD) {
|
||||
declType = myJetParsing.parseProperty(true);
|
||||
}
|
||||
else if (keywordToken == TYPE_KEYWORD) {
|
||||
declType = myJetParsing.parseTypeDef();
|
||||
}
|
||||
else if (keywordToken == OBJECT_KEYWORD) {
|
||||
// Object expression may appear at the statement position: should parse it
|
||||
// as expression instead of object declaration
|
||||
// sample:
|
||||
// {
|
||||
// object : Thread() {
|
||||
// }
|
||||
// }
|
||||
IElementType lookahead = lookahead(1);
|
||||
if (lookahead == COLON || lookahead == LBRACE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
myJetParsing.parseObject(true, true);
|
||||
declType = OBJECT_DECLARATION;
|
||||
}
|
||||
return declType;
|
||||
}
|
||||
|
||||
/*
|
||||
* doWhile
|
||||
|
||||
@@ -50,6 +50,7 @@ public class JetParsing extends AbstractJetParsing {
|
||||
private static final TokenSet IMPORT_RECOVERY_SET = TokenSet.create(AS_KEYWORD, DOT, EOL_OR_SEMICOLON);
|
||||
/*package*/ static final TokenSet TYPE_REF_FIRST = TokenSet.create(LBRACKET, IDENTIFIER, FUN_KEYWORD, LPAR, CAPITALIZED_THIS_KEYWORD, HASH);
|
||||
private static final TokenSet RECEIVER_TYPE_TERMINATORS = TokenSet.create(DOT, SAFE_ACCESS);
|
||||
private static final TokenSet VALUE_PARAMETER_FIRST = TokenSet.orSet(TokenSet.create(IDENTIFIER, LBRACKET), MODIFIER_KEYWORDS);
|
||||
|
||||
static JetParsing createForTopLevel(SemanticWhitespaceAwarePsiBuilder builder) {
|
||||
JetParsing jetParsing = new JetParsing(builder);
|
||||
@@ -1722,8 +1723,10 @@ public class JetParsing extends AbstractJetParsing {
|
||||
else {
|
||||
parseValueParameter();
|
||||
}
|
||||
if (!at(COMMA)) break;
|
||||
advance(); // COMMA
|
||||
if (at(COMMA)) {
|
||||
advance(); // COMMA
|
||||
}
|
||||
else if (!atSet(VALUE_PARAMETER_FIRST)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,17 @@ public class JetBlockExpression extends JetExpressionImpl implements JetStatemen
|
||||
|
||||
@Nullable
|
||||
public TextRange getLastBracketRange() {
|
||||
PsiElement rBrace = findChildByType(JetTokens.RBRACE);
|
||||
PsiElement rBrace = getRBrace();
|
||||
return rBrace != null ? rBrace.getTextRange() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getRBrace() {
|
||||
return findChildByType(JetTokens.RBRACE);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getLBrace() {
|
||||
return findChildByType(JetTokens.LBRACE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetClassInitializer extends JetDeclarationImpl implements JetStatementExpression {
|
||||
public JetClassInitializer(@NotNull ASTNode node) {
|
||||
@@ -40,4 +43,10 @@ public class JetClassInitializer extends JetDeclarationImpl implements JetStatem
|
||||
assert body != null;
|
||||
return body;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getOpenBraceNode() {
|
||||
JetExpression body = getBody();
|
||||
return (body instanceof JetBlockExpression) ? ((JetBlockExpression) body).getLBrace() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
public class JetClassObject extends JetDeclarationImpl implements JetStatementExpression {
|
||||
public JetClassObject(@NotNull ASTNode node) {
|
||||
@@ -41,4 +43,9 @@ public class JetClassObject extends JetDeclarationImpl implements JetStatementEx
|
||||
return (JetObjectDeclaration) findChildByType(JetNodeTypes.OBJECT_DECLARATION);
|
||||
}
|
||||
|
||||
@Nullable @IfNotParsed
|
||||
public PsiElement getClassKeywordNode() {
|
||||
ASTNode keywordNode = getNode().findChildByType(JetTokens.CLASS_KEYWORD);
|
||||
return keywordNode != null ? keywordNode.getPsi() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,13 @@ public class JetPsiFactory {
|
||||
return star;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiElement createComma(Project project) {
|
||||
PsiElement comma = createType(project, "T<X, Y>").findElementAt(3);
|
||||
assert comma != null;
|
||||
return comma;
|
||||
}
|
||||
|
||||
//the pair contains the first and the last elements of a range
|
||||
public static Pair<PsiElement, PsiElement> createColonAndWhiteSpaces(Project project) {
|
||||
JetProperty property = createProperty(project, "val x : Int");
|
||||
|
||||
@@ -756,6 +756,65 @@ public class JetPsiUtil {
|
||||
return CommentUtilCore.isComment(element) || element instanceof KDocElement;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getOutermostParent(@NotNull PsiElement element, @NotNull PsiElement upperBound, boolean strict) {
|
||||
PsiElement parent = strict ? element.getParent() : element;
|
||||
while (parent != null && parent.getParent() != upperBound) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
public static <T extends PsiElement> T getLastChildByType(@NotNull PsiElement root, @NotNull Class<? extends T>... elementTypes) {
|
||||
PsiElement[] children = root.getChildren();
|
||||
|
||||
for (int i = children.length - 1; i >= 0; i--) {
|
||||
if (PsiTreeUtil.instanceOf(children[i], elementTypes)) {
|
||||
//noinspection unchecked
|
||||
return (T) children[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T extends JetElement> T getOutermostJetElement(
|
||||
@Nullable PsiElement root,
|
||||
boolean first,
|
||||
@NotNull final Class<? extends T>... elementTypes
|
||||
) {
|
||||
if (!(root instanceof JetElement)) return null;
|
||||
|
||||
final List<T> results = Lists.newArrayList();
|
||||
|
||||
((JetElement) root).accept(
|
||||
new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
if (PsiTreeUtil.instanceOf(element, elementTypes)) {
|
||||
//noinspection unchecked
|
||||
results.add((T) element);
|
||||
}
|
||||
else {
|
||||
element.acceptChildren(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
if (results.isEmpty()) return null;
|
||||
|
||||
return first ? results.get(0) : results.get(results.size() - 1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement findChildByType(@NotNull PsiElement element, @NotNull IElementType type) {
|
||||
ASTNode node = element.getNode().findChildByType(type);
|
||||
return node == null ? null : node.getPsi();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static JetExpression getCalleeExpressionIfAny(@NotNull JetExpression expression) {
|
||||
if (expression instanceof JetCallElement) {
|
||||
|
||||
@@ -114,7 +114,7 @@ public interface JetTokens {
|
||||
JetToken SAFE_ACCESS = new JetToken("SAFE_ACCESS");
|
||||
JetToken ELVIS = new JetToken("ELVIS");
|
||||
// JetToken MAP = new JetToken("MAP");
|
||||
// JetToken FILTER = new JetToken("FILTER");
|
||||
// JetToken FILTER = new JetToken("FILTER");
|
||||
JetToken QUEST = new JetToken("QUEST");
|
||||
JetToken COLONCOLON = new JetToken("COLONCOLON");
|
||||
JetToken COLON = new JetToken("COLON");
|
||||
@@ -131,7 +131,7 @@ public interface JetTokens {
|
||||
JetToken HASH = new JetToken("HASH");
|
||||
JetToken AT = new JetToken("AT");
|
||||
JetToken ATAT = new JetToken("ATAT");
|
||||
|
||||
|
||||
JetToken IDE_TEMPLATE_START = new JetToken("IDE_TEMPLATE_START");
|
||||
JetToken IDE_TEMPLATE_END = new JetToken("IDE_TEMPLATE_END");
|
||||
|
||||
@@ -165,23 +165,23 @@ public interface JetTokens {
|
||||
JetKeywordToken FINAL_KEYWORD = JetKeywordToken.softKeyword("final");
|
||||
|
||||
TokenSet KEYWORDS = TokenSet.create(PACKAGE_KEYWORD, AS_KEYWORD, TYPE_KEYWORD, CLASS_KEYWORD, TRAIT_KEYWORD,
|
||||
THIS_KEYWORD, SUPER_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, FOR_KEYWORD,
|
||||
NULL_KEYWORD,
|
||||
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD,
|
||||
IN_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD,
|
||||
ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD, TRY_KEYWORD, WHEN_KEYWORD,
|
||||
NOT_IN, NOT_IS, CAPITALIZED_THIS_KEYWORD, AS_SAFE
|
||||
THIS_KEYWORD, SUPER_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, FOR_KEYWORD,
|
||||
NULL_KEYWORD,
|
||||
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD,
|
||||
IN_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD, CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD,
|
||||
ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD, TRY_KEYWORD, WHEN_KEYWORD,
|
||||
NOT_IN, NOT_IS, CAPITALIZED_THIS_KEYWORD, AS_SAFE
|
||||
);
|
||||
|
||||
TokenSet SOFT_KEYWORDS = TokenSet.create(IMPORT_KEYWORD, WHERE_KEYWORD, BY_KEYWORD, GET_KEYWORD,
|
||||
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD,
|
||||
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
|
||||
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD
|
||||
SET_KEYWORD, ABSTRACT_KEYWORD, ENUM_KEYWORD, OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD,
|
||||
OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD,
|
||||
CATCH_KEYWORD, FINALLY_KEYWORD, OUT_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD
|
||||
);
|
||||
|
||||
TokenSet MODIFIER_KEYWORDS = TokenSet.create(ABSTRACT_KEYWORD, ENUM_KEYWORD,
|
||||
OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD,
|
||||
PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD
|
||||
OPEN_KEYWORD, INNER_KEYWORD, ANNOTATION_KEYWORD, OVERRIDE_KEYWORD, PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD,
|
||||
PROTECTED_KEYWORD, OUT_KEYWORD, IN_KEYWORD, FINAL_KEYWORD, VARARG_KEYWORD, INLINE_KEYWORD, REIFIED_KEYWORD
|
||||
);
|
||||
TokenSet WHITESPACES = TokenSet.create(TokenType.WHITE_SPACE);
|
||||
|
||||
@@ -196,13 +196,13 @@ public interface JetTokens {
|
||||
|
||||
TokenSet STRINGS = TokenSet.create(CHARACTER_LITERAL, REGULAR_STRING_PART);
|
||||
TokenSet OPERATIONS = TokenSet.create(AS_KEYWORD, AS_SAFE, IS_KEYWORD, IN_KEYWORD, DOT, PLUSPLUS, MINUSMINUS, EXCLEXCL, MUL, PLUS,
|
||||
MINUS, EXCL, DIV, PERC, LT, GT, LTEQ, GTEQ, EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR,
|
||||
SAFE_ACCESS, ELVIS,
|
||||
// MAP, FILTER,
|
||||
COLON,
|
||||
RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ,
|
||||
NOT_IN, NOT_IS,
|
||||
IDENTIFIER, LABEL_IDENTIFIER, ATAT, AT);
|
||||
MINUS, EXCL, DIV, PERC, LT, GT, LTEQ, GTEQ, EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR,
|
||||
SAFE_ACCESS, ELVIS,
|
||||
// MAP, FILTER,
|
||||
COLON,
|
||||
RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ,
|
||||
NOT_IN, NOT_IS,
|
||||
IDENTIFIER, LABEL_IDENTIFIER, ATAT, AT);
|
||||
|
||||
TokenSet AUGMENTED_ASSIGNMENTS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, DIVEQ);
|
||||
TokenSet ALL_ASSIGNMENTS = TokenSet.create(EQ, PLUSEQ, MINUSEQ, MULTEQ, PERCEQ, DIVEQ);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
val x = foo(
|
||||
a,
|
||||
b
|
||||
c
|
||||
)
|
||||
@@ -0,0 +1,32 @@
|
||||
JetFile: MissingCommaInValueArgumentList.kt
|
||||
NAMESPACE_HEADER
|
||||
<empty list>
|
||||
PROPERTY
|
||||
PsiElement(val)('val')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
CALL_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('foo')
|
||||
VALUE_ARGUMENT_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
PsiWhiteSpace('\n ')
|
||||
VALUE_ARGUMENT
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
VALUE_ARGUMENT
|
||||
BINARY_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('b')
|
||||
PsiWhiteSpace('\n ')
|
||||
OPERATION_REFERENCE
|
||||
PsiElement(IDENTIFIER)('c')
|
||||
PsiErrorElement:Expecting an element
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(RPAR)(')')
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo(
|
||||
a: Any,
|
||||
b: Int
|
||||
c: String
|
||||
) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
JetFile: MissingCommaInValueParameterList.kt
|
||||
NAMESPACE_HEADER
|
||||
<empty list>
|
||||
FUN
|
||||
PsiElement(fun)('fun')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(IDENTIFIER)('foo')
|
||||
VALUE_PARAMETER_LIST
|
||||
PsiElement(LPAR)('(')
|
||||
PsiWhiteSpace('\n ')
|
||||
VALUE_PARAMETER
|
||||
PsiElement(IDENTIFIER)('a')
|
||||
PsiElement(COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('Any')
|
||||
PsiElement(COMMA)(',')
|
||||
PsiWhiteSpace('\n ')
|
||||
VALUE_PARAMETER
|
||||
PsiElement(IDENTIFIER)('b')
|
||||
PsiElement(COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('Int')
|
||||
PsiWhiteSpace('\n ')
|
||||
VALUE_PARAMETER
|
||||
PsiElement(IDENTIFIER)('c')
|
||||
PsiElement(COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
TYPE_REFERENCE
|
||||
USER_TYPE
|
||||
REFERENCE_EXPRESSION
|
||||
PsiElement(IDENTIFIER)('String')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(RPAR)(')')
|
||||
PsiWhiteSpace(' ')
|
||||
BLOCK
|
||||
PsiElement(LBRACE)('{')
|
||||
PsiWhiteSpace('\n\n')
|
||||
PsiElement(RBRACE)('}')
|
||||
@@ -32,7 +32,8 @@ import org.jetbrains.jet.completion.AbstractJavaWithLibCompletionTest;
|
||||
import org.jetbrains.jet.completion.AbstractJetJSCompletionTest;
|
||||
import org.jetbrains.jet.completion.AbstractKeywordCompletionTest;
|
||||
import org.jetbrains.jet.jvm.compiler.*;
|
||||
import org.jetbrains.jet.lang.psi.AbstractJetPsiMatcherTest;
|
||||
import org.jetbrains.jet.plugin.codeInsight.moveUpDown.AbstractCodeMoverTest;
|
||||
import org.jetbrains.jet.psi.AbstractJetPsiMatcherTest;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.AbstractLazyResolveDescriptorRendererTest;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.AbstractLazyResolveNamespaceComparingTest;
|
||||
import org.jetbrains.jet.lang.resolve.lazy.AbstractLazyResolveTest;
|
||||
@@ -213,10 +214,11 @@ public class GenerateTests {
|
||||
);
|
||||
|
||||
generateTest(
|
||||
"compiler/tests/",
|
||||
"idea/tests/",
|
||||
"JetPsiMatcherTest",
|
||||
AbstractJetPsiMatcherTest.class,
|
||||
testModel("compiler/testData/psi/jetPsiMatcher", "doTestExpressions")
|
||||
testModel("idea/testData/jetPsiMatcher/expressions", "doTestExpressions"),
|
||||
testModel("idea/testData/jetPsiMatcher/types", "doTestTypes")
|
||||
);
|
||||
|
||||
generateTest(
|
||||
@@ -337,6 +339,15 @@ public class GenerateTests {
|
||||
testModelWithDirectories("idea/testData/hierarchy/class/super", "doSuperClassHierarchyTest"),
|
||||
testModelWithDirectories("idea/testData/hierarchy/class/sub", "doSubClassHierarchyTest")
|
||||
);
|
||||
|
||||
generateTest(
|
||||
"idea/tests/",
|
||||
"CodeMoverTestGenerated",
|
||||
AbstractCodeMoverTest.class,
|
||||
testModel("idea/testData/codeInsight/moveUpDown/classBodyDeclarations", "doTestClassBodyDeclaration"),
|
||||
testModel("idea/testData/codeInsight/moveUpDown/closingBraces", "doTestExpression"),
|
||||
testModel("idea/testData/codeInsight/moveUpDown/expressions", "doTestExpression")
|
||||
);
|
||||
}
|
||||
|
||||
private static SimpleTestClassModel testModel(@NotNull String rootPath) {
|
||||
|
||||
@@ -283,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>
|
||||
|
||||
+1
@@ -4,6 +4,7 @@ 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.*;
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-3
@@ -14,10 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
package org.jetbrains.jet.plugin.util;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -61,6 +61,13 @@ public class JetPsiMatcher {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Predicate2<JetParameter, JetParameter> PARAMETER_TYPE_CHECKER = new Predicate2<JetParameter, JetParameter>() {
|
||||
@Override
|
||||
public boolean apply(JetParameter param1, JetParameter param2) {
|
||||
return checkElementMatch(param1.getTypeReference(), param2.getTypeReference());
|
||||
}
|
||||
};
|
||||
|
||||
private static <T> boolean checkListMatch(List<? extends T> list1, List<? extends T> list2, Predicate2<T, T> checker) {
|
||||
int n = list1.size();
|
||||
if (list2.size() != n) return false;
|
||||
@@ -204,7 +211,9 @@ public class JetPsiMatcher {
|
||||
public Boolean visitFunctionType(JetFunctionType type1, JetElement data) {
|
||||
JetFunctionType type2 = (JetFunctionType) data;
|
||||
|
||||
return checkListMatch(type1.getTypeArgumentsAsTypes(), type2.getTypeArgumentsAsTypes());
|
||||
return checkElementMatch(type1.getReceiverTypeRef(), type2.getReceiverTypeRef()) &&
|
||||
checkElementMatch(type1.getReturnTypeRef(), type2.getReturnTypeRef()) &&
|
||||
checkListMatch(type1.getParameters(), type2.getParameters(), PARAMETER_TYPE_CHECKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -0,0 +1,6 @@
|
||||
// MOVE: down
|
||||
// IS_APPLICABLE: false
|
||||
val x: String
|
||||
<caret>get() {
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// MOVE: up
|
||||
// IS_APPLICABLE: false
|
||||
val x: String
|
||||
<caret>get() {
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
var x: String
|
||||
<caret>get() {
|
||||
return ""
|
||||
}
|
||||
set(v: String) {
|
||||
// test
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
var x: String
|
||||
set(v: String) {
|
||||
// test
|
||||
}
|
||||
<caret>get() {
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
var x: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
<caret>set(v: String) {
|
||||
// test
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
var x: String
|
||||
<caret>set(v: String) {
|
||||
// test
|
||||
}
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val x = ""
|
||||
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val x = ""
|
||||
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
|
||||
val y = ""
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
class A {
|
||||
|
||||
val y = ""
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
class B {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
class B {
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
class B {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
class B {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
fun foo() {
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
fun foo() {
|
||||
class A {
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
fun foo() {
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
fun foo() {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
class A {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
class B {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
class B {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
class B {
|
||||
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
class B {
|
||||
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
{
|
||||
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
{
|
||||
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
|
||||
val y = ""
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val y = ""
|
||||
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
val x = ""
|
||||
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
|
||||
val x = ""
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
val y = ""
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val y = ""
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
val y = ""
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>class B {
|
||||
|
||||
}
|
||||
val y = ""
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
// IS_APPLICABLE: false
|
||||
class B {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
// IS_APPLICABLE: false
|
||||
class B {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
class B {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
class B {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
class B {
|
||||
|
||||
}
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
class B {
|
||||
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
{
|
||||
|
||||
}
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
{
|
||||
|
||||
}
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
|
||||
val y = ""
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val y = ""
|
||||
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
val x = ""
|
||||
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
|
||||
val x = ""
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
val y = ""
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val y = ""
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
val y = ""
|
||||
<caret>{
|
||||
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>{
|
||||
|
||||
}
|
||||
val y = ""
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
enum class B {
|
||||
<caret>X
|
||||
Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
enum class B {
|
||||
Y
|
||||
<caret>X
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
// IS_APPLICABLE: false
|
||||
class A {
|
||||
enum class B {
|
||||
<caret>X
|
||||
Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
// IS_APPLICABLE: false
|
||||
class A {
|
||||
enum class B {
|
||||
X
|
||||
<caret>Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
enum class B {
|
||||
X
|
||||
<caret>Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
enum class B {
|
||||
<caret>Y
|
||||
X
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: up
|
||||
enum class A {
|
||||
U
|
||||
V
|
||||
|
||||
enum class B {
|
||||
<caret>X
|
||||
Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: up
|
||||
enum class A {
|
||||
U
|
||||
V
|
||||
|
||||
<caret>X
|
||||
enum class B {
|
||||
Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: down
|
||||
enum class A {
|
||||
U
|
||||
V
|
||||
|
||||
enum class B {
|
||||
X
|
||||
<caret>Y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// MOVE: down
|
||||
enum class A {
|
||||
U
|
||||
V
|
||||
|
||||
enum class B {
|
||||
X
|
||||
}
|
||||
<caret>Y
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val x = ""
|
||||
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
val x = ""
|
||||
|
||||
}
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
|
||||
val y = ""
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
class A {
|
||||
|
||||
val y = ""
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
class B {
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
class A {
|
||||
class B {
|
||||
}
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
class B {
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
class A {
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
class B {
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
fun foo() {
|
||||
class B {
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: down
|
||||
fun foo() {
|
||||
class B {
|
||||
}
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// MOVE: up
|
||||
fun foo() {
|
||||
class B {
|
||||
<caret>fun foo() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user