|
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