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 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/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; } 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) } 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)); } 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. 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); + } } 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 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:

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