groovy-notifications mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "ASF GitHub Bot (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (GROOVY-7014) A Java compile time error results in a runtime exception in Groovy
Date Sat, 13 Aug 2016 19:28:22 GMT

    [ https://issues.apache.org/jira/browse/GROOVY-7014?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15420043#comment-15420043
] 

ASF GitHub Bot commented on GROOVY-7014:
----------------------------------------

Github user jwagenleitner commented on a diff in the pull request:

    https://github.com/apache/groovy/pull/381#discussion_r74691103
  
    --- Diff: src/main/org/codehaus/groovy/ast/tools/ClassNodeUtils.java ---
    @@ -65,4 +73,122 @@ public static void addDeclaredMethodMapsFromSuperInterfaces(ClassNode
cn, Map<St
                 sn = sn.getSuperClass();
             }
         }
    +
    +    /**
    +     * Returns true if the given method has a possibly matching static method with the
given name and arguments.
    +     *
    +     * @param cNode     the ClassNode of interest
    +     * @param name      the name of the method of interest
    +     * @param arguments the arguments to match against
    +     * @param trySpread whether to try to account for SpreadExpressions within the arguments
    +     * @return true if a matching method was found
    +     */
    +    public static boolean hasPossibleStaticMethod(ClassNode cNode, String name, Expression
arguments, boolean trySpread) {
    +        int count = 0;
    +        boolean foundSpread = false;
    +
    +        if (arguments instanceof TupleExpression) {
    +            TupleExpression tuple = (TupleExpression) arguments;
    +            for (Expression arg : tuple.getExpressions()) {
    +                if (arg instanceof SpreadExpression) {
    +                    foundSpread = true;
    +                } else {
    +                    count++;
    +                }
    +            }
    +        } else if (arguments instanceof MapExpression) {
    +            count = 1;
    +        }
    +
    +        for (MethodNode method : cNode.getMethods(name)) {
    +            if (method.isStatic()) {
    +                Parameter[] parameters = method.getParameters();
    +                // do fuzzy match for spread case: count will be number of non-spread
args
    +                if (trySpread && foundSpread && parameters.length >=
count) return true;
    +
    +                if (parameters.length == count) return true;
    +
    +                // handle varargs case
    +                if (parameters.length > 0 && parameters[parameters.length
- 1].getType().isArray()) {
    +                    if (count >= parameters.length - 1) return true;
    +                    // fuzzy match any spread to a varargs
    +                    if (trySpread && foundSpread) return true;
    +                }
    +
    +                // handle parameters with default values
    +                int nonDefaultParameters = 0;
    +                for (Parameter parameter : parameters) {
    +                    if (!parameter.hasInitialExpression()) {
    +                        nonDefaultParameters++;
    +                    }
    +                }
    +
    +                if (count < parameters.length && nonDefaultParameters <=
count) {
    +                    return true;
    +                }
    +                // TODO handle spread with nonDefaultParams?
    +            }
    +        }
    +        return false;
    +    }
    +
    +    /**
    +     * Return true if we have a static accessor
    +     */
    +    public static boolean hasPossibleStaticProperty(ClassNode candidate, String methodName)
{
    +        // assume explicit static method call checked first so we can assume a simple
check here
    +        if (!methodName.startsWith("get") && !methodName.startsWith("is")) {
    +            return false;
    +        }
    +        String propName = getPropNameForAccessor(methodName);
    +        PropertyNode pNode = getStaticProperty(candidate, propName);
    +        return pNode != null && (methodName.startsWith("get") || boolean_TYPE.equals(pNode.getType()));
    +    }
    +
    +    /**
    +     * Returns the property name, e.g. age, given an accessor name, e.g. getAge.
    +     * Returns the original if a valid prefix cannot be removed.
    +     *
    +     * @param accessorName the accessor name of interest, e.g. getAge
    +     * @return the property name, e.g. age, or original if not a valid property accessor
name
    +     */
    +    public static String getPropNameForAccessor(String accessorName) {
    +        int prefixLength = accessorName.startsWith("is") ? 2 : 3;
    +        if (accessorName.length() < prefixLength + 1) return accessorName;
    +        if (!isValidAccessorName(accessorName)) return accessorName;
    --- End diff --
    
    Would it make sense to move the length check to the `isValidAccessorName` method below?
 That would ensure `isValidAccessorName` would not return true for methods named `get()`/`is()`/`set()`.


> A Java compile time error results in a runtime exception in Groovy
> ------------------------------------------------------------------
>
>                 Key: GROOVY-7014
>                 URL: https://issues.apache.org/jira/browse/GROOVY-7014
>             Project: Groovy
>          Issue Type: Bug
>          Components: Static compilation
>    Affects Versions: 2.3.4, 2.4.0-rc-1
>         Environment: Window 7
>            Reporter: Harminder Singh
>            Priority: Minor
>
> A Groovy class with CompileStatic annotation exhibit a different behavior than Java.
 The following code results in a compile time error in Java, but throws a runtime exception
in Groovy.
> {code}
> @CompileStatic
> class Base
> {
>   String getData() { return "ABCD" }
>   Base() { this(getData()) } // Calling an instance method before the class is constructed
>   Base(String arg) {}
> }
> @CompileStatic
> public class GMain
> {
>   public static void main(String[] args)
>   {
>     Base b = new Base();
>   }
> }
> {code}
> Java produces:
> {noformat}
> Java Compiler error: Error:(11, 11) java: cannot reference this before supertype constructor
has been called
> {noformat}
> Groovy produces:
> {noformat}
> Groovy Runtime Error details:
> Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast
to main.groovy.Base
> 	at main.groovy.Base.<init>(Base.groovy:9)
> 	at main.groovy.Derived.<init>(Derived.groovy)
> 	at main.groovy.GMain.main(Base.groovy:18)
> 	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>         ......
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Mime
View raw message