From aa5056db55f627edc4c21d684aaf105f2415d74b Mon Sep 17 00:00:00 2001 From: Eric Milles Date: Sun, 10 Nov 2019 21:20:26 -0600 Subject: [PATCH] Fix for NPE #990 --- .../stc/StaticTypeCheckingVisitor.java | 12 +++ .../stc/StaticTypeCheckingVisitor.java | 12 +++ .../stc/StaticTypeCheckingVisitor.java | 74 ++++++++++--------- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/base/org.codehaus.groovy24/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy24/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index af578ad1f9..df52c06839 100644 --- a/base/org.codehaus.groovy24/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy24/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -3802,6 +3802,7 @@ public void visitTryCatchFinally(final TryCatchStatement statement) { } protected void storeType(Expression exp, ClassNode cn) { + /* GRECLIPSE edit if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable() && isPrimitiveType(cn)) { cn = getWrapper(cn); } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe() && isPrimitiveType(cn)) { @@ -3809,6 +3810,17 @@ protected void storeType(Expression exp, ClassNode cn) { } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe() && isPrimitiveType(cn)) { cn = getWrapper(cn); } + */ + if (cn != null && isPrimitiveType(cn)) { + if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable()) { + cn = getWrapper(cn); + } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe()) { + cn = getWrapper(cn); + } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe()) { + cn = getWrapper(cn); + } + } + // GRECLIPSE end if (cn == UNKNOWN_PARAMETER_TYPE) { // this can happen for example when "null" is used in an assignment or a method parameter. // In that case, instead of storing the virtual type, we must "reset" type information diff --git a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index bafcdb5f5e..36ca8a6c53 100644 --- a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -4043,6 +4043,7 @@ public void visitTryCatchFinally(final TryCatchStatement statement) { } protected void storeType(Expression exp, ClassNode cn) { + /* GRECLIPSE edit if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable() && isPrimitiveType(cn)) { cn = getWrapper(cn); } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe() && isPrimitiveType(cn)) { @@ -4050,6 +4051,17 @@ protected void storeType(Expression exp, ClassNode cn) { } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe() && isPrimitiveType(cn)) { cn = getWrapper(cn); } + */ + if (cn != null && isPrimitiveType(cn)) { + if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable()) { + cn = getWrapper(cn); + } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe()) { + cn = getWrapper(cn); + } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe()) { + cn = getWrapper(cn); + } + } + // GRECLIPSE end if (cn == UNKNOWN_PARAMETER_TYPE) { // this can happen for example when "null" is used in an assignment or a method parameter. // In that case, instead of storing the virtual type, we must "reset" type information 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 17667134a2..73772c7526 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 @@ -569,18 +569,15 @@ private void checkOrMarkPrivateAccess(Expression source, MethodNode mn) { private void checkSuperCallFromClosure(Expression call, MethodNode directCallTarget) { if (call instanceof MethodCallExpression && typeCheckingContext.getEnclosingClosure() != null) { Expression objectExpression = ((MethodCallExpression) call).getObjectExpression(); - if (objectExpression instanceof VariableExpression) { - VariableExpression var = (VariableExpression) objectExpression; - if (var.isSuperExpression()) { - ClassNode current = typeCheckingContext.getEnclosingClassNode(); - LinkedList list = current.getNodeMetaData(SUPER_MOP_METHOD_REQUIRED); - if (list == null) { - list = new LinkedList(); - current.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, list); - } - list.add(directCallTarget); - call.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, current); + if (isSuperExpression(objectExpression)) { + ClassNode current = typeCheckingContext.getEnclosingClassNode(); + LinkedList list = current.getNodeMetaData(SUPER_MOP_METHOD_REQUIRED); + if (list == null) { + list = new LinkedList(); + current.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, list); } + list.add(directCallTarget); + call.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, current); } } } @@ -2266,15 +2263,12 @@ public void visitConstructorCallExpression(ConstructorCallExpression call) { ClassNode[] args = getArgumentTypes(argumentList); if (args.length > 0 && typeCheckingContext.getEnclosingClosure() != null && - argumentList.getExpression(0) instanceof VariableExpression && - ((VariableExpression) argumentList.getExpression(0)).isThisExpression() && - call.getType() instanceof InnerClassNode && - call.getType().getOuterClass().equals(args[0]) && + isThisExpression(argumentList.getExpression(0)) && + args[0].equals(call.getType().getOuterClass()) && !call.getType().isStaticClass()) { args[0] = CLOSURE_TYPE; } - MethodNode node; if (looksLikeNamedArgConstructor(receiver, args) && findMethod(receiver, "", DefaultGroovyMethods.init(args)).size() == 1 @@ -3360,7 +3354,7 @@ public void visitMethodCallExpression(MethodCallExpression call) { boolean callArgsVisited = false; if (isCallOnClosure) { // this is a closure.call() call - if (objectExpression == VariableExpression.THIS_EXPRESSION) { + if (isThisExpression(objectExpression)) { // isClosureCall() check verified earlier that a field exists FieldNode field = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name); GenericsType[] genericsTypes = field.getType().getGenericsTypes(); @@ -3436,8 +3430,8 @@ public void visitMethodCallExpression(MethodCallExpression call) { // if we are not in a static context but the current receiver is a static class, we must // ensure that all methods are either static or declared by the current receiver or a superclass if (!mn.isEmpty() - && (typeCheckingContext.isInStaticContext || (receiverType.getModifiers() & Opcodes.ACC_STATIC) != 0) - && (call.isImplicitThis() || (objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression()))) { + && (call.isImplicitThis() || isThisExpression(objectExpression)) + && (typeCheckingContext.isInStaticContext || (receiverType.getModifiers() & Opcodes.ACC_STATIC) != 0)) { // we create separate method lists just to be able to print out // a nice error message to the user // a method is accessible if it is static, or if we are not in a static context and it is @@ -3500,15 +3494,10 @@ public void visitMethodCallExpression(MethodCallExpression call) { } ClassNode returnType = getType(directMethodCallCandidate); - if (isUsingGenericsOrIsArrayUsingGenerics(returnType)) { visitMethodCallArguments(chosenReceiver.getType(), argumentList, true, directMethodCallCandidate); - ClassNode irtg = inferReturnTypeGenerics( - chosenReceiver.getType(), - directMethodCallCandidate, - callArguments, - call.getGenericsTypes()); - returnType = irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType; + ClassNode irtg = inferReturnTypeGenerics(chosenReceiver.getType(), directMethodCallCandidate, callArguments, call.getGenericsTypes()); + returnType = (irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType); callArgsVisited = true; } if (directMethodCallCandidate == GET_DELEGATE && typeCheckingContext.getEnclosingClosure() != null) { @@ -3568,7 +3557,7 @@ && isNumberType(getType(argumentList.getExpression(0)))) { if (mn != null) { List argExpressions = argumentList.getExpressions(); Parameter[] parameters = mn.getParameters(); - for (int i = 0; i < argExpressions.size() && i < parameters.length; i++) { + for (int i = 0; i < argExpressions.size() && i < parameters.length; i += 1) { Expression arg = argExpressions.get(i); ClassNode pType = parameters[i].getType(); ClassNode aType = getType(arg); @@ -3813,7 +3802,7 @@ protected void storeTargetMethod(final Expression call, final MethodNode directM protected boolean isClosureCall(final String name, final Expression objectExpression, final Expression arguments) { if (objectExpression instanceof ClosureExpression && ("call".equals(name) || "doCall".equals(name))) return true; - if (objectExpression == VariableExpression.THIS_EXPRESSION) { + if (isThisExpression(objectExpression)) { FieldNode fieldNode = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name); if (fieldNode != null) { ClassNode type = fieldNode.getType(); @@ -4212,6 +4201,7 @@ public void visitTryCatchFinally(final TryCatchStatement statement) { } protected void storeType(Expression exp, ClassNode cn) { + /* GRECLIPSE edit if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable() && isPrimitiveType(cn)) { cn = getWrapper(cn); } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe() && isPrimitiveType(cn)) { @@ -4219,6 +4209,17 @@ protected void storeType(Expression exp, ClassNode cn) { } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe() && isPrimitiveType(cn)) { cn = getWrapper(cn); } + */ + if (cn != null && isPrimitiveType(cn)) { + if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable()) { + cn = getWrapper(cn); + } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe()) { + cn = getWrapper(cn); + } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe()) { + cn = getWrapper(cn); + } + } + // GRECLIPSE end if (cn == UNKNOWN_PARAMETER_TYPE) { // this can happen for example when "null" is used in an assignment or a method parameter. // In that case, instead of storing the virtual type, we must "reset" type information @@ -4847,15 +4848,14 @@ protected ClassNode getType(final ASTNode exp) { return node; } if (exp instanceof VariableExpression) { - final VariableExpression vexp = (VariableExpression) exp; + VariableExpression vexp = (VariableExpression) exp; ClassNode selfTrait = isTraitSelf(vexp); if (selfTrait != null) return makeSelf(selfTrait); - if (vexp == VariableExpression.THIS_EXPRESSION) return makeThis(); - if (vexp == VariableExpression.SUPER_EXPRESSION) return makeSuper(); - final Variable variable = vexp.getAccessedVariable(); + if (vexp.isThisExpression()) return makeThis(); + if (vexp.isSuperExpression()) return makeSuper(); + Variable variable = vexp.getAccessedVariable(); if (variable instanceof FieldNode) { FieldNode fieldNode = (FieldNode) variable; - checkOrMarkPrivateAccess(vexp, fieldNode, isLHSOfEnclosingAssignment(vexp)); return getType(fieldNode); } @@ -5089,6 +5089,14 @@ protected static boolean isNullConstant(final Expression expression) { return expression instanceof ConstantExpression && ((ConstantExpression) expression).isNullExpression(); } + protected static boolean isThisExpression(final Expression expression) { + return expression instanceof VariableExpression && ((VariableExpression) expression).isThisExpression(); + } + + protected static boolean isSuperExpression(final Expression expression) { + return expression instanceof VariableExpression && ((VariableExpression) expression).isSuperExpression(); + } + protected ClassNode inferMapExpressionType(final MapExpression map) { ClassNode mapType = LINKEDHASHMAP_CLASSNODE.getPlainNodeReference(); List entryExpressions = map.getMapEntryExpressions();