From 9418c302fafebd9742ae6d5da0aabe1ff8f74aa7 Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Tue, 19 Sep 2023 09:17:13 -0500 Subject: [PATCH] GROOVY-11168 --- .../search/Groovy21InferencingTests.java | 40 ++++++++++++------- .../core/tests/xform/TypeCheckedTests.java | 19 +++++++++ .../stc/StaticTypeCheckingVisitor.java | 13 +++--- .../stc/StaticTypeCheckingVisitor.java | 13 +++--- .../stc/StaticTypeCheckingVisitor.java | 16 ++++---- .../jdt/groovy/search/SimpleTypeLookup.java | 2 +- .../TypeInferencingVisitorWithRequestor.java | 8 ++-- .../jdt/groovy/search/VariableScope.java | 6 +++ .../groovy/eclipse/astviews/ASTView.groovy | 5 +++ 9 files changed, 82 insertions(+), 40 deletions(-) diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java index 025522ea95..6e756172bc 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/Groovy21InferencingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2020 the original author or authors. + * Copyright 2009-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ public final class Groovy21InferencingTests extends InferencingTestSuite { @Test - public void testDelegatesToValue() { + public void testDelegatesToValue1() { //@formatter:off String contents = "class Other { }\n" + @@ -136,7 +136,7 @@ public void testDelegatesToTarget2() { } @Test // uses constant instead of literal for target - public void testDelegatesToTarget2a() { + public void testDelegatesToTarget3() { createUnit("C", "class C {\n" + " private static final String SELF = 'self'\n" + @@ -164,7 +164,7 @@ public void testDelegatesToTarget2a() { } @Test - public void testDelegatesToTarget3() { + public void testDelegatesToTarget4() { createUnit("C", "class C { static def cat(\n" + "@DelegatesTo.Target('self') Object self, @DelegatesTo(target='self', strategy=Closure.DELEGATE_ONLY) Closure code) {}\n}"); //@formatter:off @@ -187,7 +187,7 @@ public void testDelegatesToTarget3() { } @Test - public void testDelegatesToTarget4() { + public void testDelegatesToTarget5() { createUnit("C", "class C { static def cat(\n" + "@DelegatesTo.Target('self') Object self, @DelegatesTo(target='self', strategy=Closure.OWNER_FIRST) Closure code) {}\n}"); //@formatter:off @@ -211,7 +211,7 @@ public void testDelegatesToTarget4() { } @Test - public void testDelegatesToTarget5() { + public void testDelegatesToTarget6() { createUnit("C", "class C { static def cat(\n" + "@DelegatesTo.Target('self') Object self, @DelegatesTo(target='self', strategy=Closure.OWNER_ONLY) Closure code) {}\n}"); //@formatter:off @@ -233,7 +233,7 @@ public void testDelegatesToTarget5() { } @Test // seemingly invalid combination - public void testDelegatesToTarget6() { + public void testDelegatesToTarget7() { createUnit("C", "class C { static def cat(\n" + "@DelegatesTo.Target('self') Object self, @DelegatesTo(target='self', strategy=Closure.TO_SELF) Closure code) {}\n}"); //@formatter:off @@ -257,7 +257,7 @@ public void testDelegatesToTarget6() { } @Test // https://github.com/groovy/groovy-eclipse/issues/1147 - public void testDelegatesToTarget7() { + public void testDelegatesToTarget8() { //@formatter:off String contents = "abstract class A {\n" + @@ -329,7 +329,7 @@ public void testDelegatesToTypeName3() { } @Test // https://github.com/groovy/groovy-eclipse/issues/966 - public void testDelegatesToTypeName3a() { + public void testDelegatesToTypeName4() { //@formatter:off createUnit("p", "A", "package p\n" + @@ -352,7 +352,7 @@ public void testDelegatesToTypeName3a() { } @Test // https://github.com/groovy/groovy-eclipse/issues/966 - public void testDelegatesToTypeName3b() { + public void testDelegatesToTypeName5() { //@formatter:off createUnit("p", "A", "package p\n" + @@ -378,8 +378,18 @@ public void testDelegatesToTypeName3b() { assertType(contents, "number", "java.lang.Number"); } + @Test // https://issues.apache.org/jira/browse/GROOVY-11168 + public void testDelegatesToTypeName6() { + //@formatter:off + String contents = + "def T m(int i, @DelegatesTo(type='T') Closure block) { }\n" + + "this.m(2) { delegate }"; + //@formatter:on + assertType(contents, "delegate", "java.lang.String"); + } + @Test - public void testDelegatesToResolveStrategy2() { + public void testDelegatesToResolveStrategy1() { //@formatter:off String contents = "class A {}\n" + @@ -399,7 +409,7 @@ public void testDelegatesToResolveStrategy2() { } @Test // https://github.com/groovy/groovy-eclipse/issues/657 - public void testDelegatesToResolveStrategy3() { + public void testDelegatesToResolveStrategy2() { //@formatter:off String contents = "class A {}\n" + @@ -419,7 +429,7 @@ public void testDelegatesToResolveStrategy3() { } @Test - public void testDelegatesToResolveStrategy4() { + public void testDelegatesToResolveStrategy3() { //@formatter:off String contents = "class A {}\n" + @@ -519,7 +529,7 @@ public void testEnumOverrides4() { } @Test // https://github.com/groovy/groovy-eclipse/issues/1100 - public void testEnumOverrides4a() { + public void testEnumOverrides5() { //@formatter:off String contents = "@groovy.transform.CompileStatic\n" + @@ -539,7 +549,7 @@ public void testEnumOverrides4a() { } @Test // https://github.com/groovy/groovy-eclipse/issues/1100 - public void testEnumOverrides4b() { + public void testEnumOverrides6() { //@formatter:off String contents = "@groovy.transform.CompileStatic\n" + diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java index fb4204bd83..cac3834e7f 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java @@ -7122,4 +7122,23 @@ public void testTypeChecked11083() { "Groovy:[Static type checking] - Cannot assign value of type java.util.Date to variable of type java.lang.Number\n" + "----------\n"); } + + @Test + public void testTypeChecked11168() { + //@formatter:off + String[] sources = { + "Main.groovy", + "def T m(@DelegatesTo(type='T',strategy=Closure.DELEGATE_FIRST) Closure c) {\n" + + " 'WORKS'.with(c)\n" + + "}\n" + + "@groovy.transform.TypeChecked\n" + + "void test() {\n" + + " this.m { print toLowerCase() }\n" + + "}\n" + + "test()\n", + }; + //@formatter:on + + runConformTest(sources, "works"); + } } diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 86cfca0b3f..7a78c88b59 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -3461,7 +3461,7 @@ private void processClosureParams(final ClassNode receiver, final Expression arg * of failure. */ private void resolveGenericsFromTypeHint(final ClassNode receiver, final Expression arguments, final MethodNode selectedMethod, final ClassNode[] signature) { - ClassNode returnType = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, OBJECT_TYPE).getPlainNodeReference(); + ClassNode returnType = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, null).getPlainNodeReference(); returnType.setGenericsTypes(Arrays.stream(signature).map(ClassNode::asGenericsType).toArray(GenericsType[]::new)); MethodNode methodNode = selectedMethod instanceof ExtensionMethodNode ? ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode() : selectedMethod; @@ -3483,11 +3483,12 @@ private void resolveGenericsFromTypeHint(final ClassNode receiver, final Express methodNode.setGenericsTypes(selectedMethod.getGenericsTypes()); } - GenericsType[] typeArguments = null; // GROOVY-7789 - Expression emc = typeCheckingContext.getEnclosingMethodCall(); - if (emc instanceof MethodCallExpression) { - MethodCallExpression call = (MethodCallExpression) emc; - if (arguments == call.getArguments()) typeArguments = call.getGenericsTypes(); + GenericsType[] typeArguments = null; + Expression emc = typeCheckingContext.getEnclosingMethodCall(); // GROOVY-7789, GROOVY-11168 + if (emc instanceof MethodCallExpression) { MethodCallExpression call = (MethodCallExpression) emc; + if (arguments == call.getArguments() || InvocationWriter.makeArgumentList(arguments).getExpressions().stream().anyMatch(arg -> + arg instanceof ClosureExpression && DefaultGroovyMethods.contains(InvocationWriter.makeArgumentList(call.getArguments()), arg))) + typeArguments = call.getGenericsTypes(); } returnType = inferReturnTypeGenerics(receiver, methodNode, arguments, typeArguments); diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 96acb49956..4e19126247 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -3159,7 +3159,7 @@ private void processClosureParams(final ClassNode receiver, final Expression arg * of failure. */ private void resolveGenericsFromTypeHint(final ClassNode receiver, final Expression arguments, final MethodNode selectedMethod, final ClassNode[] signature) { - ClassNode returnType = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, OBJECT_TYPE).getPlainNodeReference(); + ClassNode returnType = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, null).getPlainNodeReference(); returnType.setGenericsTypes(Arrays.stream(signature).map(ClassNode::asGenericsType).toArray(GenericsType[]::new)); MethodNode methodNode = selectedMethod instanceof ExtensionMethodNode ? ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode() : selectedMethod; @@ -3181,11 +3181,12 @@ private void resolveGenericsFromTypeHint(final ClassNode receiver, final Express methodNode.setGenericsTypes(selectedMethod.getGenericsTypes()); } - GenericsType[] typeArguments = null; // GROOVY-7789 - Expression emc = typeCheckingContext.getEnclosingMethodCall(); - if (emc instanceof MethodCallExpression) { - MethodCallExpression call = (MethodCallExpression) emc; - if (arguments == call.getArguments()) typeArguments = call.getGenericsTypes(); + GenericsType[] typeArguments = null; + Expression emc = typeCheckingContext.getEnclosingMethodCall(); // GROOVY-7789, GROOVY-11168 + if (emc instanceof MethodCallExpression) { MethodCallExpression call = (MethodCallExpression) emc; + if (arguments == call.getArguments() || InvocationWriter.makeArgumentList(arguments).getExpressions().stream().anyMatch(arg -> + arg instanceof ClosureExpression && DefaultGroovyMethods.contains(InvocationWriter.makeArgumentList(call.getArguments()), arg))) + typeArguments = call.getGenericsTypes(); } returnType = inferReturnTypeGenerics(receiver, methodNode, arguments, typeArguments); diff --git a/base/org.codehaus.groovy50/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy50/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index ed8e885022..53dba612a1 100644 --- a/base/org.codehaus.groovy50/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy50/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -240,7 +240,6 @@ import static org.codehaus.groovy.ast.tools.WideningCategories.lowestUpperBound; import static org.codehaus.groovy.runtime.ArrayGroovyMethods.asBoolean; import static org.codehaus.groovy.runtime.ArrayGroovyMethods.init; -import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last; import static org.codehaus.groovy.syntax.Types.ASSIGN; import static org.codehaus.groovy.syntax.Types.COMPARE_EQUAL; import static org.codehaus.groovy.syntax.Types.COMPARE_NOT_EQUAL; @@ -3305,7 +3304,7 @@ private ClassLoader getTransformLoader() { * of failure. */ private void resolveGenericsFromTypeHint(final ClassNode receiver, final Expression arguments, final MethodNode selectedMethod, final ClassNode[] signature) { - ClassNode returnType = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, OBJECT_TYPE).getPlainNodeReference(); + ClassNode returnType = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, null).getPlainNodeReference(); returnType.setGenericsTypes(Arrays.stream(signature).map(ClassNode::asGenericsType).toArray(GenericsType[]::new)); MethodNode methodNode = selectedMethod instanceof ExtensionMethodNode ? ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode() : selectedMethod; @@ -3327,11 +3326,12 @@ private void resolveGenericsFromTypeHint(final ClassNode receiver, final Express methodNode.setGenericsTypes(selectedMethod.getGenericsTypes()); } - GenericsType[] typeArguments = null; // GROOVY-7789 - Expression emc = typeCheckingContext.getEnclosingMethodCall(); - if (emc instanceof MethodCallExpression) { - MethodCallExpression call = (MethodCallExpression) emc; - if (arguments == call.getArguments()) typeArguments = call.getGenericsTypes(); + GenericsType[] typeArguments = null; + Expression emc = typeCheckingContext.getEnclosingMethodCall(); // GROOVY-7789, GROOVY-11168 + if (emc instanceof MethodCallExpression) { MethodCallExpression call = (MethodCallExpression) emc; + if (arguments == call.getArguments() || InvocationWriter.makeArgumentList(arguments).getExpressions().stream().anyMatch(arg -> + arg instanceof ClosureExpression && DefaultGroovyMethods.contains(InvocationWriter.makeArgumentList(call.getArguments()), arg))) + typeArguments = call.getGenericsTypes(); } returnType = inferReturnTypeGenerics(receiver, methodNode, arguments, typeArguments); @@ -4082,7 +4082,7 @@ public void visitCaseStatement(final CaseStatement statement) { private static boolean maybeFallsThrough(Statement statement) { if (statement.isEmpty()) return true; if (statement instanceof BlockStatement) - statement = last(((BlockStatement) statement).getStatements()); + statement = DefaultGroovyMethods.last(((BlockStatement) statement).getStatements()); // end break, continue, return or throw if (statement instanceof BreakStatement || statement instanceof ContinueStatement diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java index 580402352f..c3633fcfa0 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java @@ -1257,7 +1257,7 @@ protected static Boolean isTypeCompatible(final List arguments, final protected static Boolean isTypeCompatible(final ClassNode source, final ClassNode target) { Boolean result = Boolean.TRUE; if (!target.equals(source) && - !(VariableScope.NULL_TYPE == source && !ClassHelper.isPrimitiveType(target))) { + !(VariableScope.NULL_TYPE == source && !ClassHelper.isPrimitiveType(target))) { // NOTE: Exact match of Closure to SAM Type creates tie for m(Closure) and m(Comparator) result = !GroovyUtils.isAssignable(source, target) && !(VariableScope.CLOSURE_CLASS_NODE.equals(source) && ClassHelper.isSAMType(target)) ? Boolean.FALSE : null; // not an exact match } diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java index 56b8cc2566..e29770332a 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/TypeInferencingVisitorWithRequestor.java @@ -738,7 +738,7 @@ private void visitAnnotationKeys(final AnnotationNode node) { attr = meth; // no Groovy AST node exists for name noLookup = new TypeLookupResult(meth.getReturnType(), meth.getDeclaringClass(), meth, TypeConfidence.EXACT, scope); } else { - attr = new ConstantExpression(name); + attr = GeneralUtils.constX(name); ClassNode type = node.getClassNode(); // this is very rough; it only works for an attribute that directly follows '(' attr.setStart(type.getEnd() + 1); @@ -838,7 +838,7 @@ public void visitBinaryExpression(final BinaryExpression node) { scopes.getLast().setMethodCallArgumentTypes(Arrays.asList(dependentExprType, node.getNodeMetaData("rhsType"))); } // there is an overloadable method associated with this operation; convert to a constant expression and look it up - TypeLookupResult result = lookupExpressionType(new ConstantExpression(associatedMethod), primaryExprType, false, scopes.getLast()); + TypeLookupResult result = lookupExpressionType(GeneralUtils.constX(associatedMethod), primaryExprType, false, scopes.getLast()); if (result.confidence != TypeConfidence.UNKNOWN) completeExprType = result.type; // special case DefaultGroovyMethods.getAt -- the problem is that DGM has too many variants of getAt if ("getAt".equals(associatedMethod) && VariableScope.DGM_CLASS_NODE.equals(result.declaringType)) { @@ -1931,7 +1931,7 @@ private void visitUnaryExpression(final Expression node, final Expression operan String associatedMethod = findUnaryOperatorName(operation); if (associatedMethod != null && !operandType.isDerivedFrom(VariableScope.NUMBER_CLASS_NODE)) { scope.setMethodCallArgumentTypes(Collections.emptyList()); - TypeLookupResult result = lookupExpressionType(new ConstantExpression(associatedMethod), operandType, false, scope); + TypeLookupResult result = lookupExpressionType(GeneralUtils.constX(associatedMethod), operandType, false, scope); exprType = result.confidence.isAtLeast(TypeConfidence.LOOSELY_INFERRED) ? result.type : operandType; } else if (node instanceof BooleanExpression) { @@ -2529,7 +2529,7 @@ private ClassNode[] inferClosureParamTypes(final ClosureExpression node, final V Parameter methodParam = findTargetParameter(node, cat.call, methodNode, !methodNode.getDeclaringClass().equals(cat.getPerceivedDeclaringType())); if (methodParam != null) { if (VariableScope.CLOSURE_CLASS_NODE.equals(methodParam.getType())) { - GroovyUtils.getAnnotations(methodParam, VariableScope.CLOSURE_PARAMS.getName()).findFirst().ifPresent(cp -> { + GroovyUtils.getAnnotations(methodParam, ClosureParams.class.getName()).findFirst().ifPresent(cp -> { SourceUnit sourceUnit = enclosingModule.getContext(); CompilationUnit compilationUnit = resolver.compilationUnit; try { diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java index d1e8ade2a7..624ee98406 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/VariableScope.java @@ -66,6 +66,7 @@ import org.codehaus.groovy.ast.expr.ClosureExpression; import org.codehaus.groovy.ast.expr.Expression; import org.codehaus.groovy.ast.expr.MethodCall; +import org.codehaus.groovy.ast.expr.MethodCallExpression; import org.codehaus.groovy.ast.expr.TupleExpression; import org.codehaus.groovy.ast.stmt.BlockStatement; import org.codehaus.groovy.ast.stmt.ReturnStatement; @@ -1300,6 +1301,11 @@ public CallAndType(final MethodCall call, final ASTNode declaration, final Class compilationUnit = ((org.codehaus.jdt.groovy.control.EclipseSourceUnit) enclosingModule.getContext()).resolver.compilationUnit; } ClassNode[] resolved = parseClassNodesFromString(typeName, enclosingModule.getContext(), compilationUnit, methodNode, delegatesToType); + if (GenericsUtils.hasUnresolvedGenerics(resolved[0])) { // @DelegatesTo(type="T") or @DelegatesTo(type="List") + GenericsMapper mapper = GenericsMapper.gatherGenerics(GroovyUtils.getParameterTypes(methodNode.getParameters()), declaringType, + methodNode.getOriginal(), (call instanceof MethodCallExpression ? ((MethodCallExpression) call).getGenericsTypes() : null)); + resolved[0] = resolveTypeParameterization(mapper, resolved[0]); + } addDelegatesToClosure(closure, resolved[0], strategy); } else if (delegatesToValue == null || (delegatesToValue instanceof ClassExpression && delegatesToValue.getType().getName().equals("groovy.lang.DelegatesTo$Target"))) { diff --git a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy index a51044d0fa..032d815527 100644 --- a/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy +++ b/ide/org.codehaus.groovy.eclipse.astviews/src/org/codehaus/groovy/eclipse/astviews/ASTView.groovy @@ -24,6 +24,7 @@ import static org.eclipse.swt.widgets.Display.getDefault as getDisplay import groovy.transform.* import org.codehaus.groovy.ast.* +import org.codehaus.groovy.ast.expr.MethodCall import org.codehaus.groovy.control.* import org.codehaus.groovy.eclipse.editor.GroovyEditor import org.codehaus.jdt.groovy.model.GroovyCompilationUnit @@ -355,6 +356,10 @@ class ASTView extends ViewPart { if (label ==~ /name|hasInitialExpression|initialValueExpression|is(Enum|Final|Private|Protected|Public|Static|Volatile)/) { return false } + } else if (outer instanceof MethodCall) { // MethodCallExpression, ConstructorCallExpression, etc. + if (label ==~ /methodAsString|receiver/) { + return false + } } else if (outer instanceof MethodNode) { if (label ==~ /firstStatement|is(Abstract|Default|Final|PackageScope|Private|Protected|Public|Static|VoidMethod)|name|typeDescriptor/) { return false