|
27 | 27 | import java.util.Map;
|
28 | 28 | import java.util.Optional;
|
29 | 29 | import java.util.concurrent.CancellationException;
|
| 30 | +import java.util.function.BiConsumer; |
30 | 31 | import java.util.function.Consumer;
|
31 | 32 | import java.util.stream.Collectors;
|
32 | 33 | import java.util.stream.Stream;
|
@@ -947,41 +948,36 @@ public void visitClosureExpression(final ClosureExpression node) {
|
947 | 948 | VariableScope scope = new VariableScope(parent, node, false);
|
948 | 949 | scopes.add(scope);
|
949 | 950 | try {
|
950 |
| - // if enclosing closure, owner type is 'Closure', otherwise it's 'typeof(this)' |
| 951 | + // GRECLIPSE-1348 and GROOVY-11313: don't override variable named "owner" |
| 952 | + BiConsumer<String, ClassNode> impliedVariableDeclarator = (name, type) -> { |
| 953 | + VariableScope.VariableInfo info = scope.lookupName(name); |
| 954 | + if (info == null || info.type == null || info.declaringType.equals(VariableScope.CLOSURE_CLASS_NODE)) { |
| 955 | + scope.addVariable(name, type, VariableScope.CLOSURE_CLASS_NODE); |
| 956 | + } |
| 957 | + scope.addVariable("get" + org.apache.groovy.util.BeanUtils.capitalize(name), type, VariableScope.CLOSURE_CLASS_NODE); |
| 958 | + }; |
| 959 | + |
| 960 | + // if enclosing closure, owner type is 'Closure', otherwise it is 'typeof(this)' |
951 | 961 | if (parent.getEnclosingClosure() != null) {
|
952 | 962 | ClassNode closureType = VariableScope.CLOSURE_CLASS_NODE.getPlainNodeReference();
|
953 | 963 | closureType.putNodeMetaData("outer.scope", parent.getEnclosingClosureScope());
|
954 | 964 |
|
955 |
| - scope.addVariable("owner", closureType, VariableScope.CLOSURE_CLASS_NODE); |
956 |
| - scope.addVariable("getOwner", closureType, VariableScope.CLOSURE_CLASS_NODE); |
| 965 | + impliedVariableDeclarator.accept("owner", closureType); |
957 | 966 | } else {
|
958 | 967 | ClassNode ownerType = parent.getThis();
|
959 |
| - // GRECLIPSE-1348: if someone is silly enough to have a variable named "owner"; don't override it |
960 |
| - VariableScope.VariableInfo info = scope.lookupName("owner"); |
961 |
| - if (info == null || info.type == null || info.scopeNode instanceof ClosureExpression) { |
962 |
| - scope.addVariable("owner", ownerType, VariableScope.CLOSURE_CLASS_NODE); |
963 |
| - } |
964 |
| - scope.addVariable("getOwner", ownerType, VariableScope.CLOSURE_CLASS_NODE); |
965 |
| - |
966 |
| - // only set this if not already in a closure; type doesn't vary with nesting |
967 |
| - scope.addVariable("thisObject", ownerType, VariableScope.CLOSURE_CLASS_NODE); |
968 |
| - scope.addVariable("getThisObject", ownerType, VariableScope.CLOSURE_CLASS_NODE); |
| 968 | + impliedVariableDeclarator.accept("owner", ownerType); |
| 969 | + // only set this for first closure; its type doesn't vary |
| 970 | + impliedVariableDeclarator.accept("thisObject", ownerType); |
969 | 971 | }
|
970 | 972 |
|
971 |
| - // if enclosing method call, delegate type can be specified by the method, otherwise it's 'typeof(owner)' |
| 973 | + // if enclosing method call, delegate type can be specified by the method, otherwise it is 'typeof(owner)' |
972 | 974 | VariableScope.CallAndType cat = scope.getEnclosingMethodCallExpression();
|
973 | 975 | if (cat != null && cat.getDelegateType(node) != null) {
|
974 | 976 | ClassNode delegateType = cat.getDelegateType(node);
|
975 |
| - scope.addVariable("delegate", delegateType, VariableScope.CLOSURE_CLASS_NODE); |
976 |
| - scope.addVariable("getDelegate", delegateType, VariableScope.CLOSURE_CLASS_NODE); |
| 977 | + impliedVariableDeclarator.accept("delegate", delegateType); |
977 | 978 | } else {
|
978 | 979 | ClassNode delegateType = scope.getOwner();
|
979 |
| - // GRECLIPSE-1348: if someone is silly enough to have a variable named "delegate"; don't override it |
980 |
| - VariableScope.VariableInfo info = scope.lookupName("delegate"); |
981 |
| - if (info == null || info.type == null || info.scopeNode instanceof ClosureExpression) { |
982 |
| - scope.addVariable("delegate", delegateType, VariableScope.CLOSURE_CLASS_NODE); |
983 |
| - } |
984 |
| - scope.addVariable("getDelegate", delegateType, VariableScope.CLOSURE_CLASS_NODE); |
| 980 | + impliedVariableDeclarator.accept("delegate", delegateType); |
985 | 981 | }
|
986 | 982 |
|
987 | 983 | ClassNode[] inferredParamTypes = inferClosureParamTypes(node, scope);
|
|
0 commit comments