Search in sources :

Example 1 with FindTypeVarScanner

use of lombok.javac.FindTypeVarScanner in project lombok by rzwitserloot.

the class HandleDelegate method checkConflictOfTypeVarNames.

/**
	 * There's a rare but problematic case if a delegate method has its own type variables, and the delegated type does too, and the method uses both.
	 * If for example the delegated type has {@code <E>}, and the method has {@code <T>}, but in our class we have a {@code <T>} at the class level, then we have two different
	 * type variables both named {@code T}. We detect this situation and error out asking the programmer to rename their type variable.
	 * 
	 * @throws CantMakeDelegates If there's a conflict. Conflict list is in ex.conflicted.
	 */
public void checkConflictOfTypeVarNames(MethodSig sig, JavacNode annotation) throws CantMakeDelegates {
    if (sig.elem.getTypeParameters().isEmpty())
        return;
    Set<String> usedInOurType = new HashSet<String>();
    JavacNode enclosingType = annotation;
    while (enclosingType != null) {
        if (enclosingType.getKind() == Kind.TYPE) {
            List<JCTypeParameter> typarams = ((JCClassDecl) enclosingType.get()).typarams;
            if (typarams != null)
                for (JCTypeParameter param : typarams) {
                    if (param.name != null)
                        usedInOurType.add(param.name.toString());
                }
        }
        enclosingType = enclosingType.up();
    }
    Set<String> usedInMethodSig = new HashSet<String>();
    for (TypeParameterElement param : sig.elem.getTypeParameters()) {
        usedInMethodSig.add(param.getSimpleName().toString());
    }
    usedInMethodSig.retainAll(usedInOurType);
    if (usedInMethodSig.isEmpty())
        return;
    // We might be delegating a List<T>, and we are making method <T> toArray(). A conflict is possible.
    // But only if the toArray method also uses type vars from its class, otherwise we're only shadowing,
    // which is okay as we'll add a @SuppressWarnings.
    FindTypeVarScanner scanner = new FindTypeVarScanner();
    sig.elem.asType().accept(scanner, null);
    Set<String> names = new HashSet<String>(scanner.getTypeVariables());
    names.removeAll(usedInMethodSig);
    if (!names.isEmpty()) {
        // We have a confirmed conflict. We could dig deeper as this may still be a false alarm, but its already an exceedingly rare case.
        CantMakeDelegates cmd = new CantMakeDelegates();
        cmd.conflicted = usedInMethodSig;
        throw cmd;
    }
}
Also used : JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) FindTypeVarScanner(lombok.javac.FindTypeVarScanner) JavacNode(lombok.javac.JavacNode) HashSet(java.util.HashSet) TypeParameterElement(javax.lang.model.element.TypeParameterElement)

Aggregations

JCClassDecl (com.sun.tools.javac.tree.JCTree.JCClassDecl)1 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)1 HashSet (java.util.HashSet)1 TypeParameterElement (javax.lang.model.element.TypeParameterElement)1 FindTypeVarScanner (lombok.javac.FindTypeVarScanner)1 JavacNode (lombok.javac.JavacNode)1