Search in sources :

Example 11 with ImportNode

use of org.codehaus.groovy.ast.ImportNode in project groovy by apache.

the class AntlrParserPlugin method importDef.

protected void importDef(AST importNode) {
    try {
        // GROOVY-6094
        output.putNodeMetaData(ImportNode.class, ImportNode.class);
        boolean isStatic = importNode.getType() == STATIC_IMPORT;
        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
        AST node = importNode.getFirstChild();
        if (isType(ANNOTATIONS, node)) {
            processAnnotations(annotations, node);
            node = node.getNextSibling();
        }
        String alias = null;
        if (isType(LITERAL_as, node)) {
            //import is like "import Foo as Bar"
            node = node.getFirstChild();
            AST aliasNode = node.getNextSibling();
            alias = identifier(aliasNode);
        }
        if (node.getNumberOfChildren() == 0) {
            String name = identifier(node);
            // import is like  "import Foo"
            ClassNode type = ClassHelper.make(name);
            configureAST(type, importNode);
            addImport(type, name, alias, annotations);
            return;
        }
        AST packageNode = node.getFirstChild();
        String packageName = qualifiedName(packageNode);
        AST nameNode = packageNode.getNextSibling();
        if (isType(STAR, nameNode)) {
            if (isStatic) {
                // import is like "import static foo.Bar.*"
                // packageName is actually a className in this case
                ClassNode type = ClassHelper.make(packageName);
                configureAST(type, importNode);
                addStaticStarImport(type, packageName, annotations);
            } else {
                // import is like "import foo.*"
                addStarImport(packageName, annotations);
            }
            if (alias != null)
                throw new GroovyBugError("imports like 'import foo.* as Bar' are not " + "supported and should be caught by the grammar");
        } else {
            String name = identifier(nameNode);
            if (isStatic) {
                // import is like "import static foo.Bar.method"
                // packageName is really class name in this case
                ClassNode type = ClassHelper.make(packageName);
                configureAST(type, importNode);
                addStaticImport(type, name, alias, annotations);
            } else {
                // import is like "import foo.Bar"
                ClassNode type = ClassHelper.make(packageName + "." + name);
                configureAST(type, importNode);
                addImport(type, name, alias, annotations);
            }
        }
    } finally {
        // we're using node metadata here in order to fix GROOVY-6094
        // without breaking external APIs
        Object node = output.getNodeMetaData(ImportNode.class);
        if (node != null && node != ImportNode.class) {
            configureAST((ImportNode) node, importNode);
        }
        output.removeNodeMetaData(ImportNode.class);
    }
}
Also used : EnumConstantClassNode(org.codehaus.groovy.ast.EnumConstantClassNode) InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) AST(antlr.collections.AST) AnnotationNode(org.codehaus.groovy.ast.AnnotationNode) ArrayList(java.util.ArrayList) GroovyBugError(org.codehaus.groovy.GroovyBugError) ImportNode(org.codehaus.groovy.ast.ImportNode)

Example 12 with ImportNode

use of org.codehaus.groovy.ast.ImportNode in project groovy by apache.

the class StaticImportVisitor method findStaticFieldOrPropAccessorImportFromModule.

private Expression findStaticFieldOrPropAccessorImportFromModule(String name) {
    ModuleNode module = currentClass.getModule();
    if (module == null)
        return null;
    Map<String, ImportNode> importNodes = module.getStaticImports();
    Expression expression;
    String accessorName = getAccessorName(name);
    // when resolving prop reference
    if (importNodes.containsKey(accessorName)) {
        expression = findStaticProperty(importNodes, accessorName);
        if (expression != null)
            return expression;
    }
    if (accessorName.startsWith("get")) {
        accessorName = "is" + accessorName.substring(3);
        if (importNodes.containsKey(accessorName)) {
            expression = findStaticProperty(importNodes, accessorName);
            if (expression != null)
                return expression;
        }
    }
    // when resolving prop or field reference
    if (importNodes.containsKey(name)) {
        ImportNode importNode = importNodes.get(name);
        expression = findStaticPropertyAccessor(importNode.getType(), importNode.getFieldName());
        if (expression != null)
            return expression;
        expression = findStaticField(importNode.getType(), importNode.getFieldName());
        if (expression != null)
            return expression;
    }
    // when resolving prop or field reference
    for (ImportNode importNode : module.getStaticStarImports().values()) {
        ClassNode node = importNode.getType();
        expression = findStaticPropertyAccessor(node, name);
        if (expression != null)
            return expression;
        expression = findStaticField(node, name);
        if (expression != null)
            return expression;
    }
    return null;
}
Also used : ClassNode(org.codehaus.groovy.ast.ClassNode) ListExpression(org.codehaus.groovy.ast.expr.ListExpression) PropertyExpression(org.codehaus.groovy.ast.expr.PropertyExpression) StaticMethodCallExpression(org.codehaus.groovy.ast.expr.StaticMethodCallExpression) ConstantExpression(org.codehaus.groovy.ast.expr.ConstantExpression) NamedArgumentListExpression(org.codehaus.groovy.ast.expr.NamedArgumentListExpression) MethodCallExpression(org.codehaus.groovy.ast.expr.MethodCallExpression) EmptyExpression(org.codehaus.groovy.ast.expr.EmptyExpression) Expression(org.codehaus.groovy.ast.expr.Expression) ConstructorCallExpression(org.codehaus.groovy.ast.expr.ConstructorCallExpression) VariableExpression(org.codehaus.groovy.ast.expr.VariableExpression) ArgumentListExpression(org.codehaus.groovy.ast.expr.ArgumentListExpression) AnnotationConstantExpression(org.codehaus.groovy.ast.expr.AnnotationConstantExpression) ClosureExpression(org.codehaus.groovy.ast.expr.ClosureExpression) ClassExpression(org.codehaus.groovy.ast.expr.ClassExpression) TupleExpression(org.codehaus.groovy.ast.expr.TupleExpression) BinaryExpression(org.codehaus.groovy.ast.expr.BinaryExpression) MapEntryExpression(org.codehaus.groovy.ast.expr.MapEntryExpression) ImportNode(org.codehaus.groovy.ast.ImportNode) ModuleNode(org.codehaus.groovy.ast.ModuleNode)

Example 13 with ImportNode

use of org.codehaus.groovy.ast.ImportNode in project gradle by gradle.

the class GradleResolveVisitor method resolveAliasFromModule.

private boolean resolveAliasFromModule(ClassNode type) {
    // node and any subclass resolving will then take place elsewhere
    if (type instanceof ConstructedClassWithPackage) {
        return false;
    }
    ModuleNode module = currentClass.getModule();
    if (module == null) {
        return false;
    }
    String name = type.getName();
    // check module node imports aliases
    // the while loop enables a check for inner classes which are not fully imported,
    // but visible as the surrounding class is imported and the inner class is public/protected static
    String pname = name;
    int index = name.length();
    /*
     * we have a name foo.bar and an import foo.foo. This means foo.bar is possibly
     * foo.foo.bar rather than foo.bar. This means to cut at the dot in foo.bar and
     * foo for import
     */
    while (true) {
        pname = name.substring(0, index);
        ClassNode aliasedNode = null;
        ImportNode importNode = module.getImport(pname);
        if (importNode != null && importNode != currImportNode) {
            aliasedNode = importNode.getType();
        }
        if (aliasedNode == null) {
            importNode = module.getStaticImports().get(pname);
            if (importNode != null && importNode != currImportNode) {
                // static alias only for inner classes and must be at end of chain
                ClassNode tmp = new ConstructedNestedClass(importNode.getType(), importNode.getFieldName());
                if (resolve(tmp, false, false, true)) {
                    if ((tmp.getModifiers() & Opcodes.ACC_STATIC) != 0) {
                        type.setRedirect(tmp.redirect());
                        return true;
                    }
                }
            }
        }
        if (aliasedNode != null) {
            if (pname.length() == name.length()) {
                // full match
                // We can compare here by length, because pname is always
                // a substring of name, so same length means they are equal.
                type.setRedirect(aliasedNode);
                return true;
            } else {
                // partial match
                // At this point we know that we have a match for pname. This may
                // mean, that name[pname.length()..<-1] is a static inner class.
                // For this the rest of the name does not need any dots in its name.
                // It is either completely a inner static class or it is not.
                // Since we do not want to have useless lookups we create the name
                // completely and use a ConstructedClassWithPackage to prevent lookups against the package.
                String className = aliasedNode.getNameWithoutPackage() + '$' + name.substring(pname.length() + 1).replace('.', '$');
                ConstructedClassWithPackage tmp = new ConstructedClassWithPackage(aliasedNode.getPackageName() + ".", className);
                if (resolve(tmp, true, true, false)) {
                    type.setRedirect(tmp.redirect());
                    return true;
                }
            }
        }
        index = pname.lastIndexOf('.');
        if (index == -1) {
            break;
        }
    }
    return false;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ImportNode(org.codehaus.groovy.ast.ImportNode) ModuleNode(org.codehaus.groovy.ast.ModuleNode)

Example 14 with ImportNode

use of org.codehaus.groovy.ast.ImportNode in project gradle by gradle.

the class GradleResolveVisitor method resolveFromModule.

private boolean resolveFromModule(ClassNode type, boolean testModuleImports) {
    if (type instanceof ConstructedNestedClass) {
        return false;
    }
    // with a lower case letter anymore
    if (type instanceof LowerCaseClass) {
        return resolveAliasFromModule(type);
    }
    String name = type.getName();
    ModuleNode module = currentClass.getModule();
    if (module == null) {
        return false;
    }
    boolean newNameUsed = false;
    // fact. We check here for ConstructedClassWithPackage.
    if (!type.hasPackageName() && module.hasPackageName() && !(type instanceof ConstructedClassWithPackage)) {
        type.setName(module.getPackageName() + name);
        newNameUsed = true;
    }
    // look into the module node if there is a class with that name
    List<ClassNode> moduleClasses = module.getClasses();
    for (ClassNode mClass : moduleClasses) {
        if (mClass.getName().equals(type.getName())) {
            if (mClass != type) {
                type.setRedirect(mClass);
            }
            return true;
        }
    }
    if (newNameUsed) {
        type.setName(name);
    }
    if (testModuleImports) {
        if (resolveAliasFromModule(type)) {
            return true;
        }
        if (module.hasPackageName()) {
            // check package this class is defined in. The usage of ConstructedClassWithPackage here
            // means, that the module package will not be involved when the
            // compiler tries to find an inner class.
            ConstructedClassWithPackage tmp = new ConstructedClassWithPackage(module.getPackageName(), name);
            if (resolve(tmp, false, false, false)) {
                ambiguousClass(type, tmp, name);
                type.setRedirect(tmp.redirect());
                return true;
            }
        }
        if (!name.contains(".")) {
            // check module static imports (for static inner classes)
            for (ImportNode importNode : module.getStaticImports().values()) {
                if (importNode.getFieldName().equals(name)) {
                    ClassNode tmp = new ConstructedNestedClass(importNode.getType(), name);
                    if (resolve(tmp, false, false, true)) {
                        if ((tmp.getModifiers() & Opcodes.ACC_STATIC) != 0) {
                            type.setRedirect(tmp.redirect());
                            return true;
                        }
                    }
                }
            }
            // check module node import packages
            for (ImportNode importNode : module.getStarImports()) {
                String packagePrefix = importNode.getPackageName();
                // We limit the inner class lookups here by using ConstructedClassWithPackage.
                // This way only the name will change, the packagePrefix will
                // not be included in the lookup. The case where the
                // packagePrefix is really a class is handled elsewhere.
                ConstructedClassWithPackage tmp = new ConstructedClassWithPackage(packagePrefix, name);
                if (resolve(tmp, false, false, true)) {
                    ambiguousClass(type, tmp, name);
                    type.setRedirect(tmp.redirect());
                    return true;
                }
            }
            // check for star imports (import static pkg.Outer.*) matching static inner classes
            for (ImportNode importNode : module.getStaticStarImports().values()) {
                ClassNode tmp = new ConstructedNestedClass(importNode.getType(), name);
                if (resolve(tmp, false, false, true)) {
                    if ((tmp.getModifiers() & Opcodes.ACC_STATIC) != 0) {
                        ambiguousClass(type, tmp, name);
                        type.setRedirect(tmp.redirect());
                        return true;
                    }
                }
            }
        }
    }
    return false;
}
Also used : InnerClassNode(org.codehaus.groovy.ast.InnerClassNode) ClassNode(org.codehaus.groovy.ast.ClassNode) ImportNode(org.codehaus.groovy.ast.ImportNode) ModuleNode(org.codehaus.groovy.ast.ModuleNode)

Aggregations

ImportNode (org.codehaus.groovy.ast.ImportNode)14 ClassNode (org.codehaus.groovy.ast.ClassNode)13 ModuleNode (org.codehaus.groovy.ast.ModuleNode)9 AnnotationNode (org.codehaus.groovy.ast.AnnotationNode)6 ConstantExpression (org.codehaus.groovy.ast.expr.ConstantExpression)6 Expression (org.codehaus.groovy.ast.expr.Expression)6 ListExpression (org.codehaus.groovy.ast.expr.ListExpression)6 StaticMethodCallExpression (org.codehaus.groovy.ast.expr.StaticMethodCallExpression)6 ArgumentListExpression (org.codehaus.groovy.ast.expr.ArgumentListExpression)5 MethodCallExpression (org.codehaus.groovy.ast.expr.MethodCallExpression)5 VariableExpression (org.codehaus.groovy.ast.expr.VariableExpression)5 ArrayList (java.util.ArrayList)4 InnerClassNode (org.codehaus.groovy.ast.InnerClassNode)4 AnnotationConstantExpression (org.codehaus.groovy.ast.expr.AnnotationConstantExpression)4 BinaryExpression (org.codehaus.groovy.ast.expr.BinaryExpression)4 ClassExpression (org.codehaus.groovy.ast.expr.ClassExpression)4 ClosureExpression (org.codehaus.groovy.ast.expr.ClosureExpression)4 ConstructorCallExpression (org.codehaus.groovy.ast.expr.ConstructorCallExpression)4 EmptyExpression (org.codehaus.groovy.ast.expr.EmptyExpression)4 MapEntryExpression (org.codehaus.groovy.ast.expr.MapEntryExpression)4