From 6dd293f45149acfcefe19dcdd3202b4dd24d031b Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Wed, 18 Nov 2015 22:14:50 +0300 Subject: [PATCH] [groovy] more precise ambiguous block check (IDEA-148160) --- .../groovy/annotator/GroovyAnnotator.java | 26 ++- .../GroovyHighlightingTest.groovy | 160 +++++++++++++++++- 2 files changed, 173 insertions(+), 13 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index 88cedf1b1097..22f42a123588 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -92,6 +92,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.*; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.types.*; +import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.modifiers.GrAnnotationCollector; @@ -393,12 +394,25 @@ public class GroovyAnnotator extends GroovyElementVisitor { @Override public void visitTypeDefinitionBody(GrTypeDefinitionBody typeDefinitionBody) { final PsiElement parent = typeDefinitionBody.getParent(); - if (parent instanceof GrAnonymousClassDefinition) { - final PsiElement prev = typeDefinitionBody.getPrevSibling(); - if (PsiUtil.isLineFeed(prev)) { - myHolder.createErrorAnnotation(typeDefinitionBody, GroovyBundle.message("ambiguous.code.block")); - } + if (!(parent instanceof GrAnonymousClassDefinition)) return; + + final PsiElement prev = typeDefinitionBody.getPrevSibling(); + if (!PsiUtil.isLineFeed(prev)) return; + + final PsiElement newExpression = parent.getParent(); + if (!(newExpression instanceof GrNewExpression)) return; + + final GrStatementOwner statementOwner = PsiTreeUtil.getParentOfType(newExpression, GrStatementOwner.class); + + final GrParenthesizedExpression parenthesizedExpression = PsiTreeUtil.getParentOfType(newExpression, GrParenthesizedExpression.class); + if (parenthesizedExpression != null && PsiTreeUtil.isAncestor(statementOwner, parenthesizedExpression, true)) return; + + final GrArgumentList argumentList = PsiTreeUtil.getParentOfType(newExpression, GrArgumentList.class); + if (argumentList != null && !(argumentList instanceof GrCommandArgumentList)) { + if (PsiTreeUtil.isAncestor(statementOwner, argumentList, true)) return; } + + myHolder.createErrorAnnotation(typeDefinitionBody, GroovyBundle.message("ambiguous.code.block")); } @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy index 8e4c01308f98..4a63e7b93519 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -1002,14 +1002,160 @@ class Sub extends Super { ''') } - void testAnonymousBodyOnNewLine() { - testHighlighting('''\ -class Foo{} -print new Foo() + void 'test anonymous body on new line within parenthesized expression'() { + testHighlighting '''\ +class Foo { + def i +} + +def foo = new Foo() { - String toString() {'abc'} } -''') + +def bar = (new Foo() +{ +}) + +def baz +baz = new Foo() +{ +} + +baz = (new Foo() +{ +}) + +(baz = new Foo() +{ +}) + +new Foo() +{ +} + +(new Foo() +{ +}) + +new Foo() +{ +} + 666 + +(new Foo() +{ +}) + 444 + +1 + (new Foo() +{ +} + 555) + +(1 + new Foo() +{ +} + 112) + +new Foo() +{ +}.getI() + +(new Foo() +{ +}).getI() + +(new Foo() +{ +}.getI()) + +def mm() { + new Foo() + { + } +} + +def mm2() { + (new Foo() + { + }) +} + +def mm3() { + return new Foo() + { + } +} + +def mm4() { + return (new Foo() + { + }) +} + +(new Foo() +{ + def foo() { + // still error + new Foo() + { + } + } +}) +''' + } + + void 'test anonymous body on new line within argument list'() { + testHighlighting '''\ +class Foo {} + +def foo(param) {} + +foo(new Foo() +{ +}) + +def baz +foo(baz = new Foo() +{ +}) + +foo(new Foo() +{ +} + 666) + +foo(1 + new Foo() +{ +}) + +foo(1 + new Foo() +{ +} + 666) + +foo(new Foo() +{ +}.getI()) + +foo(new Foo() +{ + +}.identity { it }) + +foo new Foo() +{ + +} + +foo 1 + (new Foo() +{ +}) + 22 + +foo(new Foo() { + def a() { + // still error + new Foo() + { + + } + } +}) +''' } void testGenerics() {