From 33ab41249c3b51bcb003517c41f8f7a3b528f1c1 Mon Sep 17 00:00:00 2001 From: Kirill Kirichenko Date: Wed, 6 Feb 2019 16:50:20 +0300 Subject: [PATCH 1/9] LafIconLookup: retrieve non selected icon if selected does not exist --- platform/platform-api/src/com/intellij/util/ui/LafIconLookup.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/util/ui/LafIconLookup.kt b/platform/platform-api/src/com/intellij/util/ui/LafIconLookup.kt index b39a89a6d406..a7e065d37ff1 100644 --- a/platform/platform-api/src/com/intellij/util/ui/LafIconLookup.kt +++ b/platform/platform-api/src/com/intellij/util/ui/LafIconLookup.kt @@ -42,5 +42,5 @@ object LafIconLookup { fun getDisabledIcon(name: String): Icon = getIcon(name, enabled = false) @JvmStatic - fun getSelectedIcon(name: String): Icon = getIcon(name, selected = true) + fun getSelectedIcon(name: String): Icon = findIcon(name, selected = true) ?: getIcon(name) } From 1b875d3162f3eafa4f0d48e9aec0155229cda9c7 Mon Sep 17 00:00:00 2001 From: "alexey.afanasiev" Date: Wed, 6 Feb 2019 17:53:18 +0300 Subject: [PATCH 2/9] [groovy] IDEA-202693 Change lambda psi structure for single expression body form --- .../lang/parser/GroovyGeneratedParser.java | 120 +++++++++++------- .../groovy/lang/psi/GroovyElementTypes.java | 5 +- ... => GrLambdaBlockFormBodyElementType.java} | 8 +- .../groovy/lang/parser/GroovyPsiCreator.java | 1 + .../plugins/groovy/lang/parser/groovy.bnf | 25 ++-- .../groovy/lang/psi/GroovyElementVisitor.java | 12 +- .../groovy/lang/psi/api/GrLambdaBody.java | 10 ++ .../lang/psi/api/GrLambdaExpression.java | 7 +- ...ckImpl.java => GrLambdaBodyBlockImpl.java} | 7 +- .../psi/impl/GrLambdaBodyExpressionImpl.kt | 30 +++++ .../lang/psi/impl/GrLambdaExpressionImpl.kt | 7 +- .../groovy/expressions/lambda/assign4.test | 5 +- .../groovy/expressions/lambda/assign5.test | 5 +- .../groovy/expressions/lambda/command11.test | 10 +- .../groovy/expressions/lambda/command12.test | 10 +- .../groovy/expressions/lambda/command2.test | 5 +- .../groovy/expressions/lambda/command8.test | 13 +- .../expressions/lambda/commandInLambda.test | 13 +- .../expressions/lambda/implicitReturn2.test | 5 +- .../expressions/lambda/methodCall10.test | 5 +- .../expressions/lambda/methodCall11.test | 5 +- .../expressions/lambda/methodCall2.test | 5 +- .../expressions/lambda/methodCall9.test | 5 +- .../expressions/lambda/nestedLambda2.test | 5 +- .../expressions/lambda/nestedLambda3.test | 28 ++-- .../expressions/lambda/nestedLambda4.test | 5 +- .../expressions/lambda/nestedLambda5.test | 29 +++-- .../expressions/lambda/nestedLambda6.test | 23 ++-- .../groovy/expressions/lambda/return2.test | 5 +- .../expressions/lambda/standalone10.test | 5 +- .../expressions/lambda/standalone11.test | 5 +- .../expressions/lambda/standalone7.test | 15 ++- .../expressions/lambda/standalone8.test | 5 +- 33 files changed, 270 insertions(+), 173 deletions(-) rename plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/{GrLambdaBlockElementType.java => GrLambdaBlockFormBodyElementType.java} (61%) create mode 100644 plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaBody.java rename plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/{GrLambdaBlockImpl.java => GrLambdaBodyBlockImpl.java} (72%) create mode 100644 plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyExpressionImpl.kt diff --git a/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/parser/GroovyGeneratedParser.java b/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/parser/GroovyGeneratedParser.java index 5e88c2edad25..65fee3f6f67e 100644 --- a/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/parser/GroovyGeneratedParser.java +++ b/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/parser/GroovyGeneratedParser.java @@ -172,8 +172,11 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { else if (t == LABELED_STATEMENT) { r = labeled_statement(b, 0); } - else if (t == LAMBDA_BLOCK) { - r = lambda_block(b, 0); + else if (t == LAMBDA_BLOCK_FORM_BODY) { + r = lambda_block_form_body(b, 0); + } + else if (t == LAMBDA_EXPRESSION_FORM_BODY) { + r = lambda_expression_form_body(b, 0); } else if (t == LEFT_SHIFT_SIGN) { r = left_shift_sign(b, 0); @@ -4301,8 +4304,8 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { /* ********************************************************** */ // '{' mb_nl block_levels '}' - public static boolean lambda_block(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "lambda_block")) return false; + public static boolean lambda_block_form_body(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "lambda_block_form_body")) return false; if (!nextTokenIsFast(b, T_LBRACE)) return false; boolean r; Marker m = enter_section_(b); @@ -4310,18 +4313,18 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { r = r && mb_nl(b, l + 1); r = r && block_levels(b, l + 1); r = r && consumeToken(b, T_RBRACE); - exit_section_(b, m, LAMBDA_BLOCK, r); + exit_section_(b, m, LAMBDA_BLOCK_FORM_BODY, r); return r; } /* ********************************************************** */ - // (!<> lazy_lambda_block) | expression_or_application + // (!<> lazy_lambda_block) | lambda_expression_form_body static boolean lambda_body(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "lambda_body")) return false; boolean r; Marker m = enter_section_(b); r = lambda_body_0(b, l + 1); - if (!r) r = expression_or_application(b, l + 1); + if (!r) r = lambda_expression_form_body(b, l + 1); exit_section_(b, m, null, r); return r; } @@ -4362,6 +4365,17 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { return r || p; } + /* ********************************************************** */ + // expression_or_application + public static boolean lambda_expression_form_body(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "lambda_expression_form_body")) return false; + boolean r; + Marker m = enter_section_(b, l, _NONE_, LAMBDA_EXPRESSION_FORM_BODY, ""); + r = expression_or_application(b, l + 1); + exit_section_(b, l, m, r, false, null); + return r; + } + /* ********************************************************** */ // lambda_parameter_list mb_nl '->' static boolean lambda_expression_head(PsiBuilder b, int l) { @@ -4435,12 +4449,12 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // <> + // <> public static boolean lazy_lambda_block(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "lazy_lambda_block")) return false; boolean r; - Marker m = enter_section_(b, l, _COLLAPSE_, LAMBDA_BLOCK, ""); - r = parseBlockLazy(b, l + 1, GroovyGeneratedParser::lambda_block, LAMBDA_BLOCK); + Marker m = enter_section_(b, l, _COLLAPSE_, LAMBDA_BLOCK_FORM_BODY, ""); + r = parseBlockLazy(b, l + 1, GroovyGeneratedParser::lambda_block_form_body, LAMBDA_BLOCK_FORM_BODY); exit_section_(b, l, m, r, false, null); return r; } @@ -6038,49 +6052,12 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { } /* ********************************************************** */ - // <> expression_or_application - // | expression_or_application !<> - // | lazy_lambda_block + // single_argument_lambda_expression_form_body | lazy_lambda_block static boolean single_argument_lambda_body(PsiBuilder b, int l) { if (!recursion_guard_(b, l, "single_argument_lambda_body")) return false; boolean r; - Marker m = enter_section_(b); - r = single_argument_lambda_body_0(b, l + 1); - if (!r) r = single_argument_lambda_body_1(b, l + 1); + r = single_argument_lambda_expression_form_body(b, l + 1); if (!r) r = lazy_lambda_block(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - - // <> expression_or_application - private static boolean single_argument_lambda_body_0(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "single_argument_lambda_body_0")) return false; - boolean r; - Marker m = enter_section_(b); - r = isParameterizedClosure(b, l + 1); - r = r && expression_or_application(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - - // expression_or_application !<> - private static boolean single_argument_lambda_body_1(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "single_argument_lambda_body_1")) return false; - boolean r; - Marker m = enter_section_(b); - r = expression_or_application(b, l + 1); - r = r && single_argument_lambda_body_1_1(b, l + 1); - exit_section_(b, m, null, r); - return r; - } - - // !<> - private static boolean single_argument_lambda_body_1_1(PsiBuilder b, int l) { - if (!recursion_guard_(b, l, "single_argument_lambda_body_1_1")) return false; - boolean r; - Marker m = enter_section_(b, l, _NOT_); - r = !isParsedAsClosure(b, l + 1); - exit_section_(b, l, m, r, false, null); return r; } @@ -6098,6 +6075,51 @@ public class GroovyGeneratedParser implements PsiParser, LightPsiParser { return r || p; } + /* ********************************************************** */ + // <> expression_or_application + // | expression_or_application !<> + static boolean single_argument_lambda_expression_form_body(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "single_argument_lambda_expression_form_body")) return false; + boolean r; + Marker m = enter_section_(b); + r = single_argument_lambda_expression_form_body_0(b, l + 1); + if (!r) r = single_argument_lambda_expression_form_body_1(b, l + 1); + exit_section_(b, m, null, r); + return r; + } + + // <> expression_or_application + private static boolean single_argument_lambda_expression_form_body_0(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "single_argument_lambda_expression_form_body_0")) return false; + boolean r; + Marker m = enter_section_(b); + r = isParameterizedClosure(b, l + 1); + r = r && expression_or_application(b, l + 1); + exit_section_(b, m, null, r); + return r; + } + + // expression_or_application !<> + private static boolean single_argument_lambda_expression_form_body_1(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "single_argument_lambda_expression_form_body_1")) return false; + boolean r; + Marker m = enter_section_(b); + r = expression_or_application(b, l + 1); + r = r && single_argument_lambda_expression_form_body_1_1(b, l + 1); + exit_section_(b, m, null, r); + return r; + } + + // !<> + private static boolean single_argument_lambda_expression_form_body_1_1(PsiBuilder b, int l) { + if (!recursion_guard_(b, l, "single_argument_lambda_expression_form_body_1_1")) return false; + boolean r; + Marker m = enter_section_(b, l, _NOT_); + r = !isParsedAsClosure(b, l + 1); + exit_section_(b, l, m, r, false, null); + return r; + } + /* ********************************************************** */ // single_argument_lambda_parameter_list mb_nl '->' static boolean single_argument_lambda_expression_head(PsiBuilder b, int l) { diff --git a/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/psi/GroovyElementTypes.java b/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/psi/GroovyElementTypes.java index be709cf2d4d9..59ba8f2c2ae8 100644 --- a/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/psi/GroovyElementTypes.java +++ b/plugins/groovy/groovy-psi/gen/org/jetbrains/plugins/groovy/lang/psi/GroovyElementTypes.java @@ -24,7 +24,7 @@ import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrFieldElementType; import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrImplementsClauseElementType; import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrImportStatementElementType; import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrInterfaceDefinitionElementType; -import org.jetbrains.plugins.groovy.lang.parser.GrLambdaBlockElementType; +import org.jetbrains.plugins.groovy.lang.parser.GrLambdaBlockFormBodyElementType; import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrMethodElementType; import org.jetbrains.plugins.groovy.lang.psi.stubs.elements.GrModifierListElementType; import org.jetbrains.plugins.groovy.lang.parser.GrBlockElementType; @@ -107,8 +107,9 @@ public interface GroovyElementTypes { GrInterfaceDefinitionElementType INTERFACE_TYPE_DEFINITION = new GrInterfaceDefinitionElementType("INTERFACE_TYPE_DEFINITION"); GroovyElementType IN_EXPRESSION = new GroovyElementType("IN_EXPRESSION"); GroovyElementType LABELED_STATEMENT = new GroovyElementType("LABELED_STATEMENT"); - GrLambdaBlockElementType LAMBDA_BLOCK = new GrLambdaBlockElementType("LAMBDA_BLOCK"); + GrLambdaBlockFormBodyElementType LAMBDA_BLOCK_FORM_BODY = new GrLambdaBlockFormBodyElementType("LAMBDA_BLOCK_FORM_BODY"); GroovyElementType LAMBDA_EXPRESSION = new GroovyElementType("LAMBDA_EXPRESSION"); + GroovyElementType LAMBDA_EXPRESSION_FORM_BODY = new GroovyElementType("LAMBDA_EXPRESSION_FORM_BODY"); GroovyElementType LAND_EXPRESSION = new GroovyElementType("LAND_EXPRESSION"); GroovyElementType LEFT_SHIFT_SIGN = new GroovyElementType("LEFT_SHIFT_SIGN"); GroovyElementType LIST_OR_MAP = new GroovyElementType("LIST_OR_MAP"); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GrLambdaBlockElementType.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GrLambdaBlockFormBodyElementType.java similarity index 61% rename from plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GrLambdaBlockElementType.java rename to plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GrLambdaBlockFormBodyElementType.java index 34a7334cf5b3..23c2b5b53371 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GrLambdaBlockElementType.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GrLambdaBlockFormBodyElementType.java @@ -3,17 +3,17 @@ package org.jetbrains.plugins.groovy.lang.parser; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrBlockImpl; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrLambdaBlockImpl; +import org.jetbrains.plugins.groovy.lang.psi.impl.GrLambdaBodyBlockImpl; -public class GrLambdaBlockElementType extends GrCodeBlockElementType { +public class GrLambdaBlockFormBodyElementType extends GrCodeBlockElementType { - public GrLambdaBlockElementType(String debugName) { + public GrLambdaBlockFormBodyElementType(String debugName) { super(debugName); } @NotNull @Override public GrBlockImpl createNode(CharSequence text) { - return new GrLambdaBlockImpl(this, text); + return new GrLambdaBodyBlockImpl(this, text); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java index 96f61641ceb0..6c70a71c2ece 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyPsiCreator.java @@ -205,6 +205,7 @@ public class GroovyPsiCreator { if (elem == ARRAY_DECLARATION) return new GrArrayDeclarationImpl(node); if (elem == ARRAY_INITIALIZER) return new GrArrayInitializerImpl(node); if (elem == LAMBDA_EXPRESSION) return new GrLambdaExpressionImpl(node); + if (elem == LAMBDA_EXPRESSION_FORM_BODY) return new GrLambdaBodyExpressionImpl(node); //Paths if (elem == REFERENCE_EXPRESSION) return new GrReferenceExpressionImpl(node); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/groovy.bnf b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/groovy.bnf index 9a6bd2a022d3..72b788de2398 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/groovy.bnf +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/groovy.bnf @@ -943,11 +943,14 @@ constructor_call_expression ::= &('this' | 'super') unqualified_reference_expres method_call_expression ::= expression call_tail private call_tail ::= call_argument_list (mb_nl lazy_closure)* | empty_argument_list <> +//region Lambda expression lambda_expression ::= lambda_expression_base | clear_variants_and_fail private lambda_expression_base ::= lambda_expression_head mb_nl lambda_body { pin = 1 } private lambda_expression_head ::= lambda_parameter_list mb_nl '->' { consumeTokenMethod = 'consumeTokenFast' } lambda_parameter_list ::= empty_parens | '(' <> ')' { elementType = parameter_list } -private lambda_body ::= (!<> lazy_lambda_block) | expression_or_application +private lambda_body ::= (!<> lazy_lambda_block) | lambda_expression_form_body + +lambda_expression_form_body ::= expression_or_application single_argument_lambda_expression::= single_argument_lambda_expression_base | clear_variants_and_fail { elementType = lambda_expression } private single_argument_lambda_expression_base ::= single_argument_lambda_expression_head mb_nl single_argument_lambda_body { pin = 1 } @@ -957,18 +960,22 @@ single_argument_lambda_parameter_list ::= !<> single_arg single_argument_lambda_parameter ::= modifier_list IDENTIFIER { elementType = parameter } -private single_argument_lambda_body ::= <> expression_or_application - | expression_or_application !<> - | lazy_lambda_block - -lazy_lambda_block ::= <> { - elementType = lambda_block +private single_argument_lambda_body ::= single_argument_lambda_expression_form_body | lazy_lambda_block +private single_argument_lambda_expression_form_body ::= <> expression_or_application + | expression_or_application !<> +{ + elementType = lambda_expression_form_body } -lambda_block ::= '{' mb_nl block_levels '}' { - elementTypeClass = 'org.jetbrains.plugins.groovy.lang.parser.GrLambdaBlockElementType' +lazy_lambda_block ::= <> { + elementType = lambda_block_form_body +} + +lambda_block_form_body ::= '{' mb_nl block_levels '}' { + elementTypeClass = 'org.jetbrains.plugins.groovy.lang.parser.GrLambdaBlockFormBodyElementType' consumeTokenMethod = 'consumeTokenFast' } +// endregion lazy_closure ::= <> { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java index e7ef3050d149..89d374e3dbc1 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java @@ -58,7 +58,11 @@ public abstract class GroovyElementVisitor { } public void visitClosure(@NotNull GrClosableBlock closure) { - visitStatement(closure); + visitFunctionalExpression(closure); + } + + public void visitFunctionalExpression(@NotNull GrFunctionalExpression expression) { + visitExpression(expression); } public void visitOpenBlock(@NotNull GrOpenBlock block) { @@ -66,11 +70,11 @@ public abstract class GroovyElementVisitor { } public void visitLambdaExpression(@NotNull GrLambdaExpression expression) { - visitExpression(expression); + visitFunctionalExpression(expression); } - public void visitLambdaBlock(@NotNull GrCodeBlock block) { - visitElement(block); + public void visitLambdaBody(@NotNull GrLambdaBody body) { + visitElement(body); } public void visitEnumConstants(@NotNull GrEnumConstantList enumConstantsSection) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaBody.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaBody.java new file mode 100644 index 000000000000..4ccb559b9d88 --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaBody.java @@ -0,0 +1,10 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.groovy.lang.psi.api; + +import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; + +/** + * Represents a Groovy lambda expression body. + */ +public interface GrLambdaBody extends GrControlFlowOwner { +} diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaExpression.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaExpression.java index 09f3dc4f7639..e4c1bd6b5976 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaExpression.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/api/GrLambdaExpression.java @@ -1,20 +1,17 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.plugins.groovy.lang.psi.api; -import com.intellij.psi.*; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; /** * Represents a Groovy lambda expression. */ public interface GrLambdaExpression extends GrFunctionalExpression { /** - * Returns PSI element representing lambda expression body: {@link org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock}, {@link GrExpression}, - * or null if the expression is incomplete. + * Returns PSI element representing lambda expression body or null if the expression is incomplete. * * @return lambda expression body. */ @Nullable - PsiElement getBody(); + GrLambdaBody getBody(); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBlockImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyBlockImpl.java similarity index 72% rename from plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBlockImpl.java rename to plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyBlockImpl.java index f6ab82a000c6..6a46535833d4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBlockImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyBlockImpl.java @@ -4,17 +4,18 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; +import org.jetbrains.plugins.groovy.lang.psi.api.GrLambdaBody; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrBlockImpl; -public class GrLambdaBlockImpl extends GrBlockImpl { +public class GrLambdaBodyBlockImpl extends GrBlockImpl implements GrLambdaBody { - public GrLambdaBlockImpl(@NotNull IElementType type, CharSequence buffer) { + public GrLambdaBodyBlockImpl(@NotNull IElementType type, CharSequence buffer) { super(type, buffer); } @Override public void accept(@NotNull GroovyElementVisitor visitor) { - visitor.visitLambdaBlock(this); + visitor.visitLambdaBody(this); } @Override diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyExpressionImpl.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyExpressionImpl.kt new file mode 100644 index 000000000000..ecbd7bb0e78a --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaBodyExpressionImpl.kt @@ -0,0 +1,30 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.groovy.lang.psi.impl + +import com.intellij.lang.ASTNode +import com.intellij.util.IncorrectOperationException +import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor +import org.jetbrains.plugins.groovy.lang.psi.api.GrLambdaBody +import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction +import org.jetbrains.plugins.groovy.lang.psi.controlFlow.impl.ControlFlowBuilder + +class GrLambdaBodyExpressionImpl(node: ASTNode) : GroovyPsiElementImpl(node), GrLambdaBody { + + fun getExpression() : GrExpression = findNotNullChildByClass(GrExpression::class.java) + + override fun accept(visitor: GroovyElementVisitor) = visitor.visitLambdaBody(this) + + override fun toString(): String = "Lambda body" + + override fun getControlFlow(): Array = ControlFlowBuilder(project).buildControlFlow(this) + + override fun isTopControlFlowOwner(): Boolean = true + + override fun addStatementBefore(statement: GrStatement, anchor: GrStatement?): GrStatement { + throw IncorrectOperationException("Can't add statement in a single expression form of body") + } + + override fun getStatements(): Array = arrayOf(getExpression()) +} diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaExpressionImpl.kt b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaExpressionImpl.kt index 4437047a229f..0b8181ab650c 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaExpressionImpl.kt +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLambdaExpressionImpl.kt @@ -10,8 +10,7 @@ import com.intellij.psi.util.CachedValueProvider.Result.create import com.intellij.psi.util.CachedValuesManager.getCachedValue import com.intellij.psi.util.PsiModificationTracker import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor -import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression +import org.jetbrains.plugins.groovy.lang.psi.api.GrLambdaBody import org.jetbrains.plugins.groovy.lang.psi.api.GrLambdaExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList @@ -31,9 +30,9 @@ class GrLambdaExpressionImpl(node: ASTNode) : GrExpressionImpl(node), GrLambdaEx override fun isVarArgs(): Boolean = false - override fun getBody(): PsiElement? { + override fun getBody(): GrLambdaBody? { val body = lastChild - return if (body is GrExpression || body is GrCodeBlock) body else null + return if (body is GrLambdaBody) body else null } override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean { diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign4.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign4.test index c230e7f4e91a..9c7ae7b3b51c 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign4.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign4.test @@ -21,5 +21,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('a') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign5.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign5.test index e72914d4265f..d2d7c074fd81 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign5.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/assign5.test @@ -23,6 +23,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command11.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command11.test index 0942be24b121..34a4fd9e8e0c 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command11.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command11.test @@ -17,8 +17,9 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement(,)(',') PsiWhiteSpace(' ') Lambda expression @@ -32,5 +33,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('c') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('c') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command12.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command12.test index afa21d879d86..08645f08b5fd 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command12.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command12.test @@ -22,8 +22,9 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement())(')') PsiElement(,)(',') PsiWhiteSpace(' ') @@ -38,5 +39,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('c') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('c') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command2.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command2.test index f1d05c554b12..f5d57ab87412 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command2.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command2.test @@ -17,5 +17,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('a') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command8.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command8.test index 490a6bb66e66..da8e72a61ee7 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command8.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/command8.test @@ -17,10 +17,11 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Call expression - Reference expression - PsiElement(identifier)('a') - PsiWhiteSpace(' ') - Command arguments + Lambda body + Call expression Reference expression - PsiElement(identifier)('b') \ No newline at end of file + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + Command arguments + Reference expression + PsiElement(identifier)('b') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/commandInLambda.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/commandInLambda.test index 832b6af039df..21efffb444c8 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/commandInLambda.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/commandInLambda.test @@ -12,10 +12,11 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Call expression - Reference expression - PsiElement(identifier)('a') - PsiWhiteSpace(' ') - Command arguments + Lambda body + Call expression Reference expression - PsiElement(identifier)('b') \ No newline at end of file + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + Command arguments + Reference expression + PsiElement(identifier)('b') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/implicitReturn2.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/implicitReturn2.test index d48165159a52..d55fc71112cb 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/implicitReturn2.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/implicitReturn2.test @@ -28,7 +28,8 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement(new line)('\n') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall10.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall10.test index 454590343f25..979ece44ef0d 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall10.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall10.test @@ -29,6 +29,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall11.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall11.test index 0892e7a3438b..259b753e0e3c 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall11.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall11.test @@ -13,6 +13,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall2.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall2.test index 3d74291fbfa2..58129c3a0424 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall2.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall2.test @@ -17,6 +17,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall9.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall9.test index da037b540f94..e2eea925b4c7 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall9.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/methodCall9.test @@ -32,6 +32,7 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda2.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda2.test index c02d8f53bf1a..b8d88a59142f 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda2.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda2.test @@ -30,5 +30,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('b') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('b') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda3.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda3.test index f0a94f869732..e422eef61fea 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda3.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda3.test @@ -12,16 +12,18 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Lambda expression - Parameter list - PsiElement(()('(') - Parameter - Modifiers - - PsiElement(identifier)('b') - PsiElement())(')') - PsiWhiteSpace(' ') - PsiElement(->)('->') - PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('b') \ No newline at end of file + Lambda body + Lambda expression + Parameter list + PsiElement(()('(') + Parameter + Modifiers + + PsiElement(identifier)('b') + PsiElement())(')') + PsiWhiteSpace(' ') + PsiElement(->)('->') + PsiWhiteSpace(' ') + Lambda body + Reference expression + PsiElement(identifier)('b') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda4.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda4.test index 05fdc331030c..69ea10793641 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda4.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda4.test @@ -26,7 +26,8 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('b') + Lambda body + Reference expression + PsiElement(identifier)('b') PsiWhiteSpace(' ') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda5.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda5.test index 438f39b3de21..999d820b6dd2 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda5.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda5.test @@ -16,18 +16,19 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Closable block - PsiElement({)('{') - PsiWhiteSpace(' ') - Parameter list - Parameter - Modifiers - + Lambda body + Closable block + PsiElement({)('{') + PsiWhiteSpace(' ') + Parameter list + Parameter + Modifiers + + PsiElement(identifier)('b') + PsiWhiteSpace(' ') + PsiElement(->)('->') + PsiWhiteSpace(' ') + Reference expression PsiElement(identifier)('b') - PsiWhiteSpace(' ') - PsiElement(->)('->') - PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('b') - PsiWhiteSpace(' ') - PsiElement(})('}') \ No newline at end of file + PsiWhiteSpace(' ') + PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda6.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda6.test index 1cd1feb8781c..eb7d77b1a956 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda6.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/nestedLambda6.test @@ -13,14 +13,15 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Closable block - PsiElement({)('{') - PsiWhiteSpace(' ') - Parameter list - - PsiElement(->)('->') - PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') - PsiWhiteSpace(' ') - PsiElement(})('}') \ No newline at end of file + Lambda body + Closable block + PsiElement({)('{') + PsiWhiteSpace(' ') + Parameter list + + PsiElement(->)('->') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/return2.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/return2.test index 62bd78ec16d4..a0395131385b 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/return2.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/return2.test @@ -31,7 +31,8 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') + Lambda body + Reference expression + PsiElement(identifier)('a') PsiElement(new line)('\n') PsiElement(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone10.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone10.test index d2a7a9919f17..49ab79abfd47 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone10.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone10.test @@ -13,5 +13,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('a') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone11.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone11.test index 14fb377c097f..70761f493514 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone11.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone11.test @@ -8,5 +8,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('a') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone7.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone7.test index dc324b56caf8..a9d95749e677 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone7.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone7.test @@ -16,11 +16,12 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Method call - Reference expression - PsiElement(identifier)('print') - Arguments - PsiElement(()('(') + Lambda body + Method call Reference expression - PsiElement(identifier)('a') - PsiElement())(')') \ No newline at end of file + PsiElement(identifier)('print') + Arguments + PsiElement(()('(') + Reference expression + PsiElement(identifier)('a') + PsiElement())(')') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone8.test b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone8.test index 4f3f5785c1fd..3c80d53b7a50 100644 --- a/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone8.test +++ b/plugins/groovy/testdata/parsing/groovy/expressions/lambda/standalone8.test @@ -16,5 +16,6 @@ Groovy script PsiWhiteSpace(' ') PsiElement(->)('->') PsiWhiteSpace(' ') - Reference expression - PsiElement(identifier)('a') \ No newline at end of file + Lambda body + Reference expression + PsiElement(identifier)('a') \ No newline at end of file From 794401e15732487ddbd3aaddaa93cd64170837c0 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 6 Feb 2019 16:00:17 +0100 Subject: [PATCH 3/9] [ui] ensures unsaved password reaches error reporter (IDEA-201018) --- .../com/intellij/diagnostic/ITNReporter.kt | 50 ++++++++--------- .../intellij/diagnostic/IdeErrorsDialog.java | 2 +- .../diagnostic/JetBrainsAccountDialog.kt | 54 ++++++++++++++++++- .../src/messages/DiagnosticBundle.properties | 15 ++++-- 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt index 3222c122475a..a4bd5608d2da 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.kt @@ -1,11 +1,11 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.diagnostic import com.intellij.CommonBundle +import com.intellij.credentialStore.Credentials import com.intellij.credentialStore.hasOnlyUserName import com.intellij.credentialStore.isFulfilled import com.intellij.diagnostic.ITNProxy.ErrorBean -import com.intellij.errorreport.error.InternalEAPException import com.intellij.errorreport.error.NoSuchEAPUserException import com.intellij.errorreport.error.UpdateAvailableException import com.intellij.ide.DataManager @@ -61,7 +61,7 @@ open class ITNReporter : ErrorReportSubmitter() { val project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent)) - return submit(errorBean, parentComponent, consumer, project) + return submit(errorBean, consumer, parentComponent, project) } /** @@ -70,20 +70,20 @@ open class ITNReporter : ErrorReportSubmitter() { open fun showErrorInRelease(event: IdeaLoggingEvent): Boolean = false } -private fun submit(errorBean: ErrorBean, parentComponent: Component, callback: Consumer, project: Project?): Boolean { +private fun submit(errorBean: ErrorBean, callback: Consumer, parentComponent: Component, project: Project?): Boolean { var credentials = ErrorReportConfigurable.getCredentials() if (credentials.hasOnlyUserName()) { - // ask password only if user name was specified - if (!showJetBrainsAccountDialog(parentComponent).showAndGet()) { - return false - } - credentials = ErrorReportConfigurable.getCredentials() + credentials = askJBAccountCredentials(parentComponent, project) + if (credentials == null) return false } + submit(credentials, errorBean, callback, parentComponent, project) + return true +} +private fun submit(credentials: Credentials?, errorBean: ErrorBean, callback: Consumer, parentComponent: Component, project: Project?) { ITNProxy.sendError(project, credentials?.userName, credentials?.getPasswordAsString(), errorBean, { threadId -> onSuccess(threadId, errorBean.event.data, callback, project) }, - { e -> onError(e, errorBean, parentComponent, callback, project) }) - return true + { e -> onError(e, errorBean, callback, parentComponent, project) }) } private fun onSuccess(threadId: Int, eventData: Any?, callback: Consumer, project: Project?) { @@ -104,7 +104,7 @@ private fun onSuccess(threadId: Int, eventData: Any?, callback: Consumer, project: Project?) { +private fun onError(e: Exception, errorBean: ErrorBean, callback: Consumer, parentComponent: Component, project: Project?) { Logger.getInstance(ITNReporter::class.java).info("reporting failed: $e") ApplicationManager.getApplication().invokeLater { if (e is UpdateAvailableException) { @@ -112,24 +112,24 @@ private fun onError(e: Exception, errorBean: ErrorBean, parentComponent: Compone val title = CommonBundle.getWarningTitle() val icon = Messages.getWarningIcon() if (parentComponent.isShowing) Messages.showMessageDialog(parentComponent, message, title, icon) - else Messages.showMessageDialog(project, message, title, icon) + else Messages.showMessageDialog(project, message, title, icon) callback.consume(SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED)) - return@invokeLater } - - val msg = when (e) { - is NoSuchEAPUserException -> DiagnosticBundle.message("error.report.authentication.failed") - is InternalEAPException -> DiagnosticBundle.message("error.report.posting.failed", e.message) - else -> DiagnosticBundle.message("error.report.sending.failure") - } - if (!MessageDialogBuilder.yesNo(ReportMessages.ERROR_REPORT, msg).project(project).isYes) { - callback.consume(SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED)) + else if (e is NoSuchEAPUserException) { + val credentials = askJBAccountCredentials(parentComponent, project, true) + if (credentials != null) { + submit(credentials, errorBean, callback, parentComponent, project) + } + else { + callback.consume(SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED)) + } } else { - if (e is NoSuchEAPUserException) { - showJetBrainsAccountDialog(parentComponent, project).show() + val message = DiagnosticBundle.message("error.report.posting.failed", e.message) + val result = MessageDialogBuilder.yesNo(ReportMessages.ERROR_REPORT, message).project(project).show() + if (result != Messages.YES || !submit(errorBean, callback, parentComponent, project)) { + callback.consume(SubmittedReportInfo(SubmittedReportInfo.SubmissionStatus.FAILED)) } - ApplicationManager.getApplication().invokeLater { submit(errorBean, parentComponent, callback, project) } } } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java index 8c8f7253098b..0cd2b18e6181 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java @@ -287,7 +287,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene myCredentialsLabel = new HyperlinkLabel(); myCredentialsLabel.addHyperlinkListener(e -> { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - JetBrainsAccountDialogKt.showJetBrainsAccountDialog(getRootPane()).show(); + JetBrainsAccountDialogKt.askJBAccountCredentials(getRootPane(), null); updateControls(); } }); diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt index ce77e85394bf..45daf9edb83b 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt +++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.kt @@ -14,10 +14,61 @@ import com.intellij.ui.components.dialog import com.intellij.ui.layout.* import com.intellij.util.io.encodeUrlQueryParameter import com.intellij.util.text.nullize +import org.jetbrains.annotations.ApiStatus import java.awt.Component import javax.swing.JPasswordField import javax.swing.JTextField +@JvmOverloads +fun askJBAccountCredentials(parent: Component, project: Project?, authFailed: Boolean = false): Credentials? { + val credentials = ErrorReportConfigurable.getCredentials() + val remember = if (credentials?.userName == null) PasswordSafe.instance.isRememberPasswordByDefault // EA credentials were never stored + else !credentials.password.isNullOrEmpty() // a password was stored already + + val prompt = if (authFailed) DiagnosticBundle.message("error.report.auth.failed") + else DiagnosticBundle.message("error.report.auth.prompt") + val userField = JTextField(credentials?.userName) + val passwordField = JPasswordField(credentials?.password?.toString()) + val rememberCheckBox = CheckBox(CommonBundle.message("checkbox.remember.password"), remember) + + val panel = panel { + noteRow(prompt) + row(DiagnosticBundle.message("error.report.auth.user")) { userField(growPolicy = GrowPolicy.SHORT_TEXT) } + row(DiagnosticBundle.message("error.report.auth.pass")) { passwordField() } + row { + rememberCheckBox() + right { + link(DiagnosticBundle.message("error.report.auth.restore")) { + val userName = userField.text.trim().encodeUrlQueryParameter() + BrowserUtil.browse("https://account.jetbrains.com/forgot-password?username=$userName") + } + } + } + noteRow(DiagnosticBundle.message("error.report.auth.enlist", "https://account.jetbrains.com/login?signup")) + } + + val dialog = dialog( + title = DiagnosticBundle.message("error.report.title"), + panel = panel, + focusedComponent = if (credentials?.userName == null) userField else passwordField, + project = project, + parent = if (parent.isShowing) parent else null) + + if (!dialog.showAndGet()) { + return null + } + + val userName = userField.text.nullize(true) + val password = passwordField.password + val passwordToRemember = if (rememberCheckBox.isSelected) password else null + RememberCheckBoxState.update(rememberCheckBox) + PasswordSafe.instance.set(CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName), Credentials(userName, passwordToRemember)) + return Credentials(userName, password) +} + +// +@Deprecated("use #askJBAccountCredentials()") +@ApiStatus.ScheduledForRemoval(inVersion = "2020") @JvmOverloads fun showJetBrainsAccountDialog(parent: Component, project: Project? = null): DialogWrapper { val credentials = ErrorReportConfigurable.getCredentials() @@ -64,4 +115,5 @@ fun showJetBrainsAccountDialog(parent: Component, project: Project? = null): Dia passwordSafe.set(CredentialAttributes(ErrorReportConfigurable.SERVICE_NAME, userName), Credentials(userName, password)) return@dialog null } -} \ No newline at end of file +} +// \ No newline at end of file diff --git a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties index 40caee20a0c9..1b86488247ce 100644 --- a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties +++ b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties @@ -57,14 +57,23 @@ error.dialog.notice.named=I agree to my names, email address, username, pa title.submitting.error.report=Submitting Error Report error.report.gratitude=Thank you for your feedback! -error.report.authentication.failed=JetBrains Account authentication failed. Do you want to try again? -error.report.posting.failed=Report posting failed: {0}. Do you want to try again? +error.report.posting.failed=Report sending failed: {0}. Do you want to try again? error.report.new.eap.build.message=New build {0} is available. -error.report.sending.failure=Sending failed. Do you want to try again? error.itn.returns.wrong.data=ITN returns wrong data error.http.result.code=HTTP Result code: {0} error.report.failure.message=Error report sending failed. +error.report.auth.prompt=Use JetBrains Account credentials to be notified\n \ + when reported exceptions are fixed.\n \ + Clear user name to submit reports anonymously. +error.report.auth.failed=JetBrains Account authentication failed.\n \ + Please check your user name and password.\n \ + Clear user name to submit reports anonymously. +error.report.auth.user=&Username: +error.report.auth.pass=&Password: +error.report.auth.restore=Forgot password? +error.report.auth.enlist=Do not have an account yet? Sign Up. + error.dialog.disable.plugin.title=Disable Plugin error.dialog.disable.prompt=Are you sure you want to disable plugin {0}? error.dialog.disable.prompt.lone=Functionality provided by the plugin will no longer be available. From d4f4784bbd779936b914c0689a4af218a3b98c29 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 6 Feb 2019 17:59:14 +0300 Subject: [PATCH 4/9] Fix for ClassCastException (for example PhpClassImpl is not PsiFile) --- .../src/com/intellij/find/impl/FindInProjectTask.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java index ee2d4e8eab4e..9618e72107db 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java +++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectTask.java @@ -29,6 +29,7 @@ import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.TrigramBuilder; import com.intellij.openapi.vfs.*; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.psi.impl.cache.CacheManager; @@ -443,8 +444,8 @@ class FindInProjectTask { private Pair.NonNull findFile(@NotNull final VirtualFile virtualFile) { PsiFile psiFile = myPsiManager.findFile(virtualFile); if (psiFile != null) { - PsiFile sourceFile = (PsiFile)psiFile.getNavigationElement(); - if (sourceFile != null) psiFile = sourceFile; + PsiElement sourceFile = psiFile.getNavigationElement(); + if (sourceFile instanceof PsiFile) psiFile = (PsiFile)sourceFile; if (psiFile.getFileType().isBinary()) { psiFile = null; } From a60c5fb932ef009c3e6b62b1e38a2a1abc929608 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 6 Feb 2019 16:07:45 +0100 Subject: [PATCH 5/9] [platform] temp. fix for incorrect EA response (IDEA-201018) --- .../src/com/intellij/diagnostic/ITNProxy.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNProxy.java b/platform/platform-impl/src/com/intellij/diagnostic/ITNProxy.java index ca5317073f8d..d3cbc3d49ba4 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/ITNProxy.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNProxy.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.diagnostic; import com.intellij.errorreport.error.InternalEAPException; @@ -139,7 +139,7 @@ class ITNProxy { @Nullable String password, @NotNull ErrorBean error, @NotNull IntConsumer onSuccess, - @NotNull Consumer onError) { + @NotNull Consumer onError) { if (StringUtil.isEmptyOrSpaces(login)) { login = DEFAULT_USER; password = DEFAULT_PASS; @@ -175,6 +175,9 @@ class ITNProxy { HttpURLConnection connection = post(new URL(NEW_THREAD_POST_URL), createRequest(login, password, error)); int responseCode = connection.getResponseCode(); + if (responseCode == HttpURLConnection.HTTP_BAD_REQUEST && StringUtil.isEmpty(password)) { + throw new NoSuchEAPUserException(login); + } if (responseCode != HttpURLConnection.HTTP_OK) { throw new InternalEAPException(DiagnosticBundle.message("error.http.result.code", responseCode)); } From bb64599d5c0adbc1cbe62647c5f90cc2e88e2f5d Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 1 Feb 2019 13:12:07 +0100 Subject: [PATCH 6/9] SSR: add class keyword to search plan if part of a class object access expression (IDEA-206479) --- .../impl/matcher/compiler/JavaCompilingVisitor.java | 9 +++++---- .../structuralsearch/OptimizedSearchScanTest.java | 7 ++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java index f15dc527fa24..3cf7471871e1 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/compiler/JavaCompilingVisitor.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.structuralsearch.impl.matcher.compiler; import com.intellij.dupLocator.iterators.NodeIterator; @@ -45,7 +45,7 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { PsiKeyword.THROWS, PsiKeyword.EXTENDS, PsiKeyword.IMPLEMENTS); public JavaCompilingVisitor(GlobalCompilingVisitor compilingVisitor) { - this.myCompilingVisitor = compilingVisitor; + myCompilingVisitor = compilingVisitor; } public void compile(PsiElement[] topLevelElements) { @@ -94,6 +94,7 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { @Override public void visitCatchSection(PsiCatchSection section) { + // check parameter first and skip catch section if count is zero final PsiParameter parameter = section.getParameter(); if (parameter != null && !handleWord(parameter.getName(), CODE, myCompilingVisitor.getContext())) return; super.visitCatchSection(section); @@ -138,7 +139,7 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { } else if (element instanceof PsiKeyword) { final String keyword = element.getText(); - if (!excludedKeywords.contains(keyword)) { + if (!excludedKeywords.contains(keyword) || element.getParent() instanceof PsiExpression) { GlobalCompilingVisitor.addFilesToSearchForGivenWord(keyword, true, CODE, myCompilingVisitor.getContext()); } } @@ -146,7 +147,7 @@ public class JavaCompilingVisitor extends JavaRecursiveElementWalkingVisitor { @Override public List getDescendantsOf(String className, boolean includeSelf, Project project) { - SmartList result = new SmartList<>(); + final SmartList result = new SmartList<>(); // use project and libraries scope, because super class may be outside the scope of the search final GlobalSearchScope projectAndLibraries = ProjectScope.getAllScope(project); diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/OptimizedSearchScanTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/OptimizedSearchScanTest.java index 6c5dc8d67480..baa3f14827f0 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/OptimizedSearchScanTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/OptimizedSearchScanTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.structuralsearch; import com.intellij.openapi.projectRoots.Sdk; @@ -132,4 +132,9 @@ public class OptimizedSearchScanTest extends StructuralSearchTestCase { final String plan = findWordsToBeUsedWhenSearchingFor("assert '_exp != null && true: \"'_exp is null\";"); assertEquals("[in literals:null][in literals:is][in code:assert][in code:null][in code:true]", plan); } + + public void testClassObjectAccessExpression() { + final String plan = findWordsToBeUsedWhenSearchingFor("ArrayUtil.toObjectArray($var$, $class$.class)"); + assertEquals("[in code:toObjectArray][in code:ArrayUtil][in code:class]", plan); + } } From 2261bb4c01d4f05d9c036a296f63503d2d8f6246 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 1 Feb 2019 16:51:20 +0100 Subject: [PATCH 7/9] IG: improve description --- .../IntegerMultiplicationImplicitCastToLong.html | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html b/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html index 03dcb8e740aa..5252bbd9bb59 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/IntegerMultiplicationImplicitCastToLong.html @@ -1,13 +1,16 @@ -Reports integer multiplication or left shift -which are implicitly cast to long. -Such multiplication is often an error, as overflow truncation may occur unexpectedly. +Reports integer multiplications or left shifts which are implicitly cast to long. +For example: +

+  void x(int i) {
+    long val = 65536 * i;
+  }
+
+Such multiplication is often a mistake, as overflow truncation may occur unexpectedly. +Converting the int literal to a long literal (65536L) fixes the problem.

-Use the checkbox below to ignore compile time constant expressions which evaluate to -a non-overflowing value. -

\ No newline at end of file From 0bad8022d58a38b63518a9fd8798bc2186383fef Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 4 Feb 2019 12:18:58 +0100 Subject: [PATCH 8/9] IG: tweak description --- .../src/inspectionDescriptions/TrivialIf.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TrivialIf.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TrivialIf.html index 46fe30403ce4..b9a54dad162d 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/TrivialIf.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TrivialIf.html @@ -1,7 +1,7 @@ -Reports if statements which can be simplified to single assignment, -return or assert statements. +Reports if statements which can be simplified to a single assignment, +return or assert statement.

For example:


From 4e7a841173562c6609db28513c0bcd187eecaee9 Mon Sep 17 00:00:00 2001
From: Bas Leijdekkers 
Date: Wed, 6 Feb 2019 14:12:46 +0100
Subject: [PATCH 9/9] qualify field access in initializer when shadowed by new
 declaration (IDEA-173780)

---
 .../CreateLocalVarFromInstanceofAction.java   | 56 ++++++++++++++-----
 .../afterShadowField.java                     | 12 ++++
 .../beforeShadowField.java                    | 11 ++++
 3 files changed, 64 insertions(+), 15 deletions(-)
 create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/afterShadowField.java
 create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/beforeShadowField.java

diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalVarFromInstanceofAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalVarFromInstanceofAction.java
index 6d362570261a..48c005a84ffe 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalVarFromInstanceofAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalVarFromInstanceofAction.java
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2017 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.
- */
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
 package com.intellij.codeInsight.daemon.impl.quickfix;
 
 import com.intellij.codeInsight.CodeInsightUtilCore;
@@ -22,6 +8,7 @@ import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
 import com.intellij.codeInsight.lookup.LookupElement;
 import com.intellij.codeInsight.lookup.LookupElementBuilder;
 import com.intellij.codeInsight.template.*;
+import com.intellij.codeInsight.template.impl.TemplateState;
 import com.intellij.ide.DataManager;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.diagnostic.Logger;
@@ -39,6 +26,7 @@ import com.intellij.psi.util.PsiUtil;
 import com.intellij.psi.util.TypeConversionUtil;
 import com.intellij.refactoring.JavaRefactoringSettings;
 import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
+import com.intellij.refactoring.util.RefactoringChangeUtil;
 import com.intellij.util.ArrayUtil;
 import com.intellij.util.IncorrectOperationException;
 import com.siyeh.ig.psiutils.EquivalenceChecker;
@@ -221,6 +209,44 @@ public class CreateLocalVarFromInstanceofAction extends BaseIntentionAction {
       newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
 
       CreateFromUsageBaseFix.startTemplate(newEditor, template, project, new TemplateEditingAdapter() {
+
+        @Override
+        public void beforeTemplateFinished(@NotNull TemplateState state, Template template) {
+          final TextResult value = state.getVariableValue("");
+          assert value != null;
+
+          final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
+          final PsiVariable target = resolveHelper.resolveAccessibleReferencedVariable(value.getText(), instanceOfExpression);
+          if (target instanceof PsiField) {
+            final PsiField field = (PsiField)target;
+            final CaretModel caretModel = editor.getCaretModel();
+            final PsiElement elementAt = file.findElementAt(caretModel.getOffset());
+            final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(elementAt, PsiDeclarationStatement.class);
+            if (declarationStatement != null) {
+              final PsiLocalVariable variable = (PsiLocalVariable)declarationStatement.getDeclaredElements()[0];
+              final PsiExpression initializer = variable.getInitializer();
+              assert initializer != null;
+              ApplicationManager.getApplication().runWriteAction(() -> {
+                initializer.accept(new JavaRecursiveElementVisitor() {
+                  @Override
+                  public void visitReferenceExpression(PsiReferenceExpression expression) {
+                    final PsiExpression qualifierExpression = expression.getQualifierExpression();
+                    if (qualifierExpression != null) {
+                      qualifierExpression.accept(this);
+                    }
+                    else if (expression.resolve() == variable) {
+                      RefactoringChangeUtil.qualifyReference(expression, field, field.hasModifierProperty(PsiModifier.STATIC)
+                                                                                ? field.getContainingClass()
+                                                                                : null);
+                    }
+                  }
+                });
+              });
+              PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
+            }
+          }
+        }
+
         @Override
         public void templateFinished(@NotNull Template template, boolean brokenOff) {
           ApplicationManager.getApplication().runWriteAction(() -> {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/afterShadowField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/afterShadowField.java
new file mode 100644
index 000000000000..96aa9eaacb69
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/afterShadowField.java
@@ -0,0 +1,12 @@
+// "Insert '(String)x' declaration" "true"
+
+class C {
+  Object x = new Object();
+
+  void x() {
+    if (x instanceof String) {
+        String x = (String) this.x;
+        
+    }
+  }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/beforeShadowField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/beforeShadowField.java
new file mode 100644
index 000000000000..c20e7f9291ee
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalVarFromInstanceof/beforeShadowField.java
@@ -0,0 +1,11 @@
+// "Insert '(String)x' declaration" "true"
+
+class C {
+  Object x = new Object();
+
+  void x() {
+    if (x instanceof String) {
+
+    }
+  }
+}
\ No newline at end of file