use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project error-prone by google.
the class ArrayEquals method matchMethodInvocation.
/**
* Suggests replacing with Arrays.equals(a, b). Also adds the necessary import statement for
* java.util.Arrays.
*/
@Override
public Description matchMethodInvocation(MethodInvocationTree t, VisitorState state) {
String arg1;
String arg2;
if (instanceEqualsMatcher.matches(t, state)) {
arg1 = ((JCFieldAccess) t.getMethodSelect()).getExpression().toString();
arg2 = t.getArguments().get(0).toString();
} else if (staticEqualsMatcher.matches(t, state)) {
arg1 = t.getArguments().get(0).toString();
arg2 = t.getArguments().get(1).toString();
} else {
return NO_MATCH;
}
Fix fix = SuggestedFix.builder().replace(t, "Arrays.equals(" + arg1 + ", " + arg2 + ")").addImport("java.util.Arrays").build();
return describeMatch(t, fix);
}
use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project error-prone by google.
the class ArrayHashCode method matchMethodInvocation.
/**
* Wraps identity hashcode computations in calls to {@link java.util.Arrays#hashCode} if the
* array is single dimensional or {@link java.util.Arrays#deepHashCode} if the array is
* multidimensional.
*
* <p>If there is only one argument to the hashcode method or the instance hashcode method is
* used, replaces the whole method invocation. If there are multiple arguments, wraps any that
* are of array type with the appropriate {@link java.util.Arrays} hashcode method.
*/
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
SuggestedFix.Builder fix = null;
Types types = state.getTypes();
if (jdk7HashCodeMethodMatcher.matches(tree, state)) {
// java.util.Objects#hashCode takes a single argument, so rewrite the whole method call
// to use Arrays.hashCode/deepHashCode instead.
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(tree.getArguments().get(0), types));
} else if (instanceHashCodeMethodMatcher.matches(tree, state)) {
// Rewrite call to instance hashCode method to use Arrays.hashCode/deepHashCode instead.
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(((JCFieldAccess) tree.getMethodSelect()).getExpression(), types));
} else if (varargsHashCodeMethodMatcher.matches(tree, state)) {
// com.google.common.base.Objects#hashCode
if (tree.getArguments().size() == 1) {
// If only one argument, type must be either primitive array or multidimensional array.
// Types like Object[], String[], etc. are not an error because they don't get boxed
// in this single-argument varargs call.
ExpressionTree arg = tree.getArguments().get(0);
Type elemType = types.elemtype(ASTHelpers.getType(arg));
if (elemType.isPrimitive() || types.isArray(elemType)) {
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(arg, types));
}
} else {
// If more than one argument, wrap each argument in a call to Arrays#hashCode/deepHashCode.
fix = SuggestedFix.builder();
for (ExpressionTree arg : tree.getArguments()) {
if (types.isArray(ASTHelpers.getType(arg))) {
fix.replace(arg, rewriteArrayArgument(arg, types));
}
}
}
}
if (fix != null) {
fix.addImport("java.util.Arrays");
return describeMatch(tree, fix.build());
}
return Description.NO_MATCH;
}
use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project error-prone by google.
the class Matchers method selectedIsInstance.
/**
* Returns true if the expression is a member access on an instance, rather than a static type.
* Supports member method invocations and field accesses.
*/
public static Matcher<ExpressionTree> selectedIsInstance() {
return new Matcher<ExpressionTree>() {
@Override
public boolean matches(ExpressionTree expr, VisitorState state) {
if (!(expr instanceof JCFieldAccess)) {
// TODO(cushon): throw IllegalArgumentException?
return false;
}
JCExpression selected = ((JCFieldAccess) expr).getExpression();
if (selected instanceof JCNewClass) {
return true;
}
Symbol sym = ASTHelpers.getSymbol(selected);
return sym instanceof VarSymbol;
}
};
}
use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project ceylon-compiler by ceylon.
the class Attr method visitApply.
/** Visitor method for method invocations.
* NOTE: The method part of an application will have in its type field
* the return type of the method, not the method's type itself!
*/
public void visitApply(JCMethodInvocation tree) {
// The local environment of a method application is
// a new environment nested in the current one.
Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
// The types of the actual method arguments.
List<Type> argtypes;
// The types of the actual method type arguments.
List<Type> typeargtypes = null;
Name methName = TreeInfo.name(tree.meth);
boolean isConstructorCall = methName == names._this || methName == names._super;
if (isConstructorCall) {
// Check that this is the first statement in a constructor.
if (checkFirstConstructorStat(tree, env)) {
// Record the fact
// that this is a constructor call (using isSelfCall).
localEnv.info.isSelfCall = true;
// Attribute arguments, yielding list of argument types.
argtypes = attribArgs(tree.args, localEnv);
typeargtypes = attribTypes(tree.typeargs, localEnv);
// Variable `site' points to the class in which the called
// constructor is defined.
Type site = env.enclClass.sym.type;
if (methName == names._super) {
if (site == syms.objectType) {
log.error(tree.meth.pos(), "no.superclass", site);
site = types.createErrorType(syms.objectType);
} else {
site = types.supertype(site);
}
}
if (site.tag == CLASS) {
Type encl = site.getEnclosingType();
while (encl != null && encl.tag == TYPEVAR) encl = encl.getUpperBound();
if (encl.tag == CLASS) {
if (tree.meth.getTag() == JCTree.SELECT) {
JCTree qualifier = ((JCFieldAccess) tree.meth).selected;
// We are seeing a prefixed call, of the form
// <expr>.super(...).
// Check that the prefix expression conforms
// to the outer instance type of the class.
chk.checkRefType(qualifier.pos(), attribExpr(qualifier, localEnv, encl));
} else if (methName == names._super) {
// qualifier omitted; check for existence
// of an appropriate implicit qualifier.
rs.resolveImplicitThis(tree.meth.pos(), localEnv, site, true);
}
} else if (tree.meth.getTag() == JCTree.SELECT) {
log.error(tree.meth.pos(), "illegal.qual.not.icls", site.tsym);
}
// prefix the implicit String and int parameters
if (site.tsym == syms.enumSym && allowEnums)
argtypes = argtypes.prepend(syms.intType).prepend(syms.stringType);
// Resolve the called constructor under the assumption
// that we are referring to a superclass instance of the
// current instance (JLS ???).
boolean selectSuperPrev = localEnv.info.selectSuper;
localEnv.info.selectSuper = true;
localEnv.info.varArgs = false;
Symbol sym = rs.resolveConstructor(tree.meth.pos(), localEnv, site, argtypes, typeargtypes);
localEnv.info.selectSuper = selectSuperPrev;
// Set method symbol to resolved constructor...
TreeInfo.setSymbol(tree.meth, sym);
// ...and check that it is legal in the current context.
// (this will also set the tree's type)
Type mpt = newMethTemplate(argtypes, typeargtypes);
checkId(tree.meth, site, sym, localEnv, MTH, mpt, tree.varargsElement != null);
}
// Otherwise, `site' is an error type and we do nothing
}
result = tree.type = syms.voidType;
} else {
// Otherwise, we are seeing a regular method call.
// Attribute the arguments, yielding list of argument types, ...
argtypes = attribArgs(tree.args, localEnv);
typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
// ... and attribute the method using as a prototype a methodtype
// whose formal argument types is exactly the list of actual
// arguments (this will also set the method symbol).
Type mpt = newMethTemplate(argtypes, typeargtypes);
localEnv.info.varArgs = false;
Type mtype = attribExpr(tree.meth, localEnv, mpt);
if (localEnv.info.varArgs)
Assert.check(mtype.isErroneous() || tree.varargsElement != null);
// Compute the result type.
Type restype = mtype.getReturnType();
if (restype.tag == WILDCARD)
throw new AssertionError(mtype);
// the same as static type of the array being cloned
if (tree.meth.getTag() == JCTree.SELECT && allowCovariantReturns && methName == names.clone && types.isArray(((JCFieldAccess) tree.meth).selected.type))
restype = ((JCFieldAccess) tree.meth).selected.type;
// as a special case, x.getClass() has type Class<? extends |X|>
if (allowGenerics && methName == names.getClass && tree.args.isEmpty()) {
Type qualifier = (tree.meth.getTag() == JCTree.SELECT) ? ((JCFieldAccess) tree.meth).selected.type : env.enclClass.sym.type;
restype = new ClassType(restype.getEnclosingType(), List.<Type>of(new WildcardType(types.erasure(qualifier), BoundKind.EXTENDS, syms.boundClass)), restype.tsym);
}
chk.checkRefTypes(tree.typeargs, typeargtypes);
// Check that value of resulting type is admissible in the
// current context. Also, capture the return type
result = check(tree, capture(restype), VAL, pkind, pt);
}
chk.validate(tree.typeargs, localEnv);
}
use of com.sun.tools.javac.tree.JCTree.JCFieldAccess in project ceylon-compiler by ceylon.
the class ClassDocImpl method importedPackages.
/**
* Get the list of packages declared as imported.
* These are called "type-import-on-demand declarations" in the JLS.
* This method is deprecated in the ClassDoc interface.
*
* @return an array of PackageDocImpl representing the imported packages.
*
* ###NOTE: the syntax supports importing all inner classes from a class as well.
* @deprecated Import declarations are implementation details that
* should not be exposed here. In addition, this method's
* return type does not allow for all type-import-on-demand
* declarations to be returned.
*/
@Deprecated
public PackageDoc[] importedPackages() {
// information is not available for binary classfiles
if (tsym.sourcefile == null)
return new PackageDoc[0];
ListBuffer<PackageDocImpl> importedPackages = new ListBuffer<PackageDocImpl>();
//### Add the implicit "import java.lang.*" to the result
Names names = tsym.name.table.names;
importedPackages.append(env.getPackageDoc(env.reader.enterPackage(names.java_lang)));
Env<AttrContext> compenv = env.enter.getEnv(tsym);
if (compenv == null)
return new PackageDocImpl[0];
for (JCTree t : compenv.toplevel.defs) {
if (t.getTag() == JCTree.IMPORT) {
JCTree imp = ((JCImport) t).qualid;
if (TreeInfo.name(imp) == names.asterisk) {
JCFieldAccess sel = (JCFieldAccess) imp;
Symbol s = sel.selected.type.tsym;
PackageDocImpl pdoc = env.getPackageDoc(s.packge());
if (!importedPackages.contains(pdoc))
importedPackages.append(pdoc);
}
}
}
return importedPackages.toArray(new PackageDocImpl[importedPackages.length()]);
}
Aggregations