Search in sources :

Example 1 with Enter

use of com.sun.tools.javac.comp.Enter in project error-prone by google.

the class Template method infer.

/**
 * Returns the inferred method type of the template based on the given actual argument types.
 *
 * @throws InferException if no instances of the specified type variables would allow the {@code
 *     actualArgTypes} to match the {@code expectedArgTypes}
 */
private Type infer(Warner warner, Inliner inliner, List<Type> freeTypeVariables, List<Type> expectedArgTypes, Type returnType, List<Type> actualArgTypes) throws InferException {
    Symtab symtab = inliner.symtab();
    Type methodType = new MethodType(expectedArgTypes, returnType, List.<Type>nil(), symtab.methodClass);
    if (!freeTypeVariables.isEmpty()) {
        methodType = new ForAll(freeTypeVariables, methodType);
    }
    Enter enter = inliner.enter();
    MethodSymbol methodSymbol = new MethodSymbol(0, inliner.asName("__m__"), methodType, symtab.unknownSymbol);
    Type site = symtab.methodClass.type;
    Env<AttrContext> env = enter.getTopLevelEnv(TreeMaker.instance(inliner.getContext()).TopLevel(List.<JCTree>nil()));
    // Set up the resolution phase:
    try {
        Field field = AttrContext.class.getDeclaredField("pendingResolutionPhase");
        field.setAccessible(true);
        field.set(env.info, newMethodResolutionPhase(autoboxing()));
    } catch (ReflectiveOperationException e) {
        throw new LinkageError(e.getMessage(), e);
    }
    Object resultInfo;
    try {
        Class<?> resultInfoClass = Class.forName("com.sun.tools.javac.comp.Attr$ResultInfo");
        Constructor<?> resultInfoCtor = resultInfoClass.getDeclaredConstructor(Attr.class, KindSelector.class, Type.class);
        resultInfoCtor.setAccessible(true);
        resultInfo = resultInfoCtor.newInstance(Attr.instance(inliner.getContext()), KindSelector.PCK, Type.noType);
    } catch (ReflectiveOperationException e) {
        throw new LinkageError(e.getMessage(), e);
    }
    // Type inference sometimes produces diagnostics, so we need to catch them to avoid interfering
    // with the enclosing compilation.
    Log.DeferredDiagnosticHandler handler = new Log.DeferredDiagnosticHandler(Log.instance(inliner.getContext()));
    try {
        MethodType result = callCheckMethod(warner, inliner, resultInfo, actualArgTypes, methodSymbol, site, env);
        if (!handler.getDiagnostics().isEmpty()) {
            throw new InferException(handler.getDiagnostics());
        }
        return result;
    } finally {
        Log.instance(inliner.getContext()).popDiagnosticHandler(handler);
    }
}
Also used : MethodType(com.sun.tools.javac.code.Type.MethodType) Log(com.sun.tools.javac.util.Log) JCTree(com.sun.tools.javac.tree.JCTree) AttrContext(com.sun.tools.javac.comp.AttrContext) Symtab(com.sun.tools.javac.code.Symtab) Field(java.lang.reflect.Field) MethodType(com.sun.tools.javac.code.Type.MethodType) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Enter(com.sun.tools.javac.comp.Enter) ForAll(com.sun.tools.javac.code.Type.ForAll)

Example 2 with Enter

use of com.sun.tools.javac.comp.Enter in project error-prone by google.

the class LiteralClassName method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    if (!CLASS_NAME.matches(tree, state)) {
        return NO_MATCH;
    }
    String className = constValue(getOnlyElement(tree.getArguments()), String.class);
    if (className == null) {
        return NO_MATCH;
    }
    if (className.startsWith("[")) {
        // TODO(cushon): consider handling arrays
        return NO_MATCH;
    }
    Type type = state.getTypeFromString(className);
    if (type == null) {
        return NO_MATCH;
    }
    ClassSymbol owner = getSymbol(state.findEnclosing(ClassTree.class));
    Enter enter = Enter.instance(state.context);
    if (!Resolve.instance(state.context).isAccessible(enter.getEnv(owner), type.tsym)) {
        return NO_MATCH;
    }
    SuggestedFix.Builder fix = SuggestedFix.builder();
    String replaceWith = String.format("%s.class", qualifyType(state, fix, state.getTypes().erasure(type)));
    if (state.getPath().getParentPath().getLeaf().getKind() == Tree.Kind.EXPRESSION_STATEMENT) {
        fix.addStaticImport("java.util.Objects.requireNonNull");
        replaceWith = String.format("requireNonNull(%s)", replaceWith);
    }
    fix.replace(tree, replaceWith);
    return describeMatch(tree, fix.build());
}
Also used : SuggestedFixes.qualifyType(com.google.errorprone.fixes.SuggestedFixes.qualifyType) Type(com.sun.tools.javac.code.Type) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ClassTree(com.sun.source.tree.ClassTree) Enter(com.sun.tools.javac.comp.Enter)

Example 3 with Enter

use of com.sun.tools.javac.comp.Enter in project error-prone by google.

the class ASTHelpers method resolveExistingMethod.

/**
 * Given a Type ({@code base}), find the method named {@code name}, with the appropriate {@code
 * argTypes} and {@code tyargTypes} and return its MethodSymbol.
 *
 * <p>Ex:
 *
 * <pre>{@code
 * .....
 * class A {}
 * class B {
 *   public int hashCode() { return 42; }
 * }
 * .....
 *
 * MethodSymbol meth =  ASTHelpers.resolveExistingMethod(
 *    state,
 *    symbol,
 *    state.getName("hashCode"),
 *    ImmutableList.<Type>of(),
 *    ImmutableList.<Type>of());
 * }</pre>
 *
 * {@code meth} could be different MethodSymbol's depending on whether {@code symbol} represented
 * {@code B} or {@code A}. (B's hashCode method or Object#hashCode).
 *
 * <p>Do NOT call this method unless the method you're looking for is guaranteed to exist. A fatal
 * error will result otherwise. Note: a method can fail to exist if it was added in a newer
 * version of a library (you may be depending on version N of a library which added a method to a
 * class, but someone else could depend on version N-1 which didn't have that method).
 *
 * @return a MethodSymbol representing the method symbol resolved from the context of this type
 */
public static MethodSymbol resolveExistingMethod(VisitorState state, TypeSymbol base, Name name, Iterable<Type> argTypes, Iterable<Type> tyargTypes) {
    Resolve resolve = Resolve.instance(state.context);
    Enter enter = Enter.instance(state.context);
    Log log = Log.instance(state.context);
    DeferredDiagnosticHandler handler = new DeferredDiagnosticHandler(log);
    try {
        return resolve.resolveInternalMethod(/*pos*/
        null, enter.getEnv(base), base.type, name, com.sun.tools.javac.util.List.from(argTypes), com.sun.tools.javac.util.List.from(tyargTypes));
    } finally {
        log.popDiagnosticHandler(handler);
    }
}
Also used : Log(com.sun.tools.javac.util.Log) Enter(com.sun.tools.javac.comp.Enter) DeferredDiagnosticHandler(com.sun.tools.javac.util.Log.DeferredDiagnosticHandler) Resolve(com.sun.tools.javac.comp.Resolve)

Aggregations

Enter (com.sun.tools.javac.comp.Enter)3 Type (com.sun.tools.javac.code.Type)2 Log (com.sun.tools.javac.util.Log)2 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)1 SuggestedFixes.qualifyType (com.google.errorprone.fixes.SuggestedFixes.qualifyType)1 ClassTree (com.sun.source.tree.ClassTree)1 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)1 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)1 Symtab (com.sun.tools.javac.code.Symtab)1 ForAll (com.sun.tools.javac.code.Type.ForAll)1 MethodType (com.sun.tools.javac.code.Type.MethodType)1 AttrContext (com.sun.tools.javac.comp.AttrContext)1 Resolve (com.sun.tools.javac.comp.Resolve)1 JCTree (com.sun.tools.javac.tree.JCTree)1 DeferredDiagnosticHandler (com.sun.tools.javac.util.Log.DeferredDiagnosticHandler)1 Field (java.lang.reflect.Field)1