use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project ceylon-compiler by ceylon.
the class ClassDefinitionBuilder method addAnnotationTypeMethod.
public ClassDefinitionBuilder addAnnotationTypeMethod(Type type) {
MethodDefinitionBuilder method = MethodDefinitionBuilder.systemMethod(gen, "annotationType");
method.modifiers(PUBLIC);
method.resultType(List.<JCAnnotation>nil(), gen.make().TypeApply(gen.make().QualIdent(gen.syms().classType.tsym), List.<JCTree.JCExpression>of(gen.make().Wildcard(gen.make().TypeBoundKind(BoundKind.EXTENDS), gen.make().Type(gen.syms().annotationType)))));
method.isOverride(true);
List<JCStatement> body = List.<JCStatement>of(gen.make().Return(gen.makeClassLiteral(type, AbstractTransformer.JT_ANNOTATION)));
method.body(body);
JCMethodDecl build = method.build();
defs(build);
return this;
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project ceylon-compiler by ceylon.
the class ExpressionTransformer method transformSpreadOperator.
private JCExpression transformSpreadOperator(final Tree.QualifiedMemberOrTypeExpression expr, TermTransformer transformer) {
at(expr);
boolean spreadMethodReferenceOuter = !expr.equals(this.spreading) && !isWithinInvocation() && isCeylonCallableSubtype(expr.getTypeModel());
boolean spreadMethodReferenceInner = expr.equals(this.spreading) && isWithinInvocation();
Tree.QualifiedMemberOrTypeExpression oldSpreading = spreading;
if (spreadMethodReferenceOuter) {
spreading = expr;
}
try {
Naming.SyntheticName varBaseName = naming.alias("spread");
ListBuffer<JCStatement> letStmts = ListBuffer.<JCStatement>lb();
final Naming.SyntheticName srcIterableName;
if (spreadMethodReferenceInner) {
// use the var we initialized in the outer
srcIterableName = this.memberPrimary;
} else {
srcIterableName = varBaseName.suffixedBy(Suffix.$iterable$);
}
if (spreadMethodReferenceOuter) {
// if we're in the outer, note then name of the var for use in the inner.
this.memberPrimary = srcIterableName;
}
Naming.SyntheticName srcIteratorName = varBaseName.suffixedBy(Suffix.$iterator$);
Type srcElementType = expr.getTarget().getQualifyingType();
JCExpression srcIterableTypeExpr = makeJavaType(typeFact().getIterableType(srcElementType), JT_NO_PRIMITIVES);
JCExpression srcIterableExpr;
boolean isSuperOrSuperOf = false;
if (spreadMethodReferenceInner) {
srcIterableExpr = srcIterableName.makeIdent();
} else {
boolean isSuper = isSuper(expr.getPrimary());
isSuperOrSuperOf = isSuper || isSuperOf(expr.getPrimary());
if (isSuperOrSuperOf) {
// so we just refer to it later
if (isSuper) {
Declaration member = expr.getPrimary().getTypeModel().getDeclaration().getMember("iterator", null, false);
srcIterableExpr = transformSuper(expr, (TypeDeclaration) member.getContainer());
} else
srcIterableExpr = transformSuperOf(expr, expr.getPrimary(), "iterator");
} else {
srcIterableExpr = transformExpression(expr.getPrimary(), BoxingStrategy.BOXED, typeFact().getIterableType(srcElementType));
}
}
// do not capture the iterable for super invocations: see above
if (!spreadMethodReferenceInner && !isSuperOrSuperOf) {
JCVariableDecl srcIterable = null;
srcIterable = makeVar(Flags.FINAL, srcIterableName, srcIterableTypeExpr, srcIterableExpr);
letStmts.prepend(srcIterable);
}
Type resultElementType = expr.getTarget().getType();
Type resultAbsentType = typeFact().getIteratedAbsentType(expr.getPrimary().getTypeModel());
// private Iterator<srcElementType> iterator = srcIterableName.iterator();
JCVariableDecl srcIterator = makeVar(Flags.FINAL, srcIteratorName, makeJavaType(typeFact().getIteratorType(srcElementType)), make().Apply(null, // for super we do not capture it because we can't and it's constant anyways
naming.makeQualIdent(isSuperOrSuperOf ? srcIterableExpr : srcIterableName.makeIdent(), "iterator"), List.<JCExpression>nil()));
Naming.SyntheticName iteratorResultName = varBaseName.suffixedBy(Suffix.$element$);
/* public Object next() {
* Object result;
* if (!((result = iterator.next()) instanceof Finished)) {
* result = transformedMember(result);
* }
* return result;
*/
/* Any arguments in the member of the spread would get re-evaluated on each iteration
* so we need to shift them to the scope of the Let to ensure they're evaluated once.
*/
boolean aliasArguments = (transformer instanceof InvocationTermTransformer) && ((InvocationTermTransformer) transformer).invocation.getNode() instanceof Tree.InvocationExpression && ((Tree.InvocationExpression) ((InvocationTermTransformer) transformer).invocation.getNode()).getPositionalArgumentList() != null;
if (aliasArguments) {
((InvocationTermTransformer) transformer).callBuilder.argumentHandling(CallBuilder.CB_ALIAS_ARGS, varBaseName);
}
JCNewClass iterableClass;
boolean prevSyntheticClassBody = expressionGen().withinSyntheticClassBody(true);
try {
JCExpression transformedElement = applyErasureAndBoxing(iteratorResultName.makeIdent(), typeFact().getAnythingType(), CodegenUtil.hasTypeErased(expr.getPrimary()), true, BoxingStrategy.BOXED, srcElementType, 0);
transformedElement = transformMemberExpression(expr, transformedElement, transformer);
// be handled by the previous recursion
if (spreadMethodReferenceOuter) {
return make().LetExpr(letStmts.toList(), transformedElement);
}
transformedElement = applyErasureAndBoxing(transformedElement, resultElementType, // not necessarily of the applied member
expr.getTarget().getDeclaration() instanceof TypedDeclaration ? CodegenUtil.hasTypeErased((TypedDeclaration) expr.getTarget().getDeclaration()) : false, !CodegenUtil.isUnBoxed(expr), BoxingStrategy.BOXED, resultElementType, 0);
MethodDefinitionBuilder nextMdb = MethodDefinitionBuilder.systemMethod(this, "next");
nextMdb.isOverride(true);
nextMdb.annotationFlags(Annotations.IGNORE);
nextMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
nextMdb.resultType(null, make().Type(syms().objectType));
nextMdb.body(List.of(makeVar(iteratorResultName, make().Type(syms().objectType), null), make().If(make().Unary(JCTree.NOT, make().TypeTest(make().Assign(iteratorResultName.makeIdent(), make().Apply(null, naming.makeQualIdent(srcIteratorName.makeIdent(), "next"), List.<JCExpression>nil())), make().Type(syms().ceylonFinishedType))), make().Block(0, List.<JCStatement>of(make().Exec(make().Assign(iteratorResultName.makeIdent(), transformedElement)))), null), make().Return(iteratorResultName.makeIdent())));
JCMethodDecl nextMethod = nextMdb.build();
// new AbstractIterator()
JCNewClass iteratorClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIteratorType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType)), make().AnonymousClassDef(make().Modifiers(0), List.of(srcIterator, nextMethod)));
MethodDefinitionBuilder iteratorMdb = MethodDefinitionBuilder.systemMethod(this, "iterator");
iteratorMdb.isOverride(true);
iteratorMdb.annotationFlags(Annotations.IGNORE);
iteratorMdb.modifiers(Flags.PUBLIC | Flags.FINAL);
iteratorMdb.resultType(null, makeJavaType(typeFact().getIteratorType(resultElementType)));
iteratorMdb.body(make().Return(iteratorClass));
// new AbstractIterable()
iterableClass = make().NewClass(null, null, make().TypeApply(make().QualIdent(syms().ceylonAbstractIterableType.tsym), List.of(makeJavaType(resultElementType, JT_TYPE_ARGUMENT), makeJavaType(resultAbsentType, JT_TYPE_ARGUMENT))), List.of(makeReifiedTypeArgument(resultElementType), makeReifiedTypeArgument(resultAbsentType)), make().AnonymousClassDef(make().Modifiers(0), List.<JCTree>of(iteratorMdb.build())));
} finally {
expressionGen().withinSyntheticClassBody(prevSyntheticClassBody);
}
if (aliasArguments) {
letStmts = letStmts.appendList(((InvocationTermTransformer) transformer).callBuilder.getStatements());
}
JCMethodInvocation result = make().Apply(null, naming.makeQualIdent(iterableClass, "sequence"), List.<JCExpression>nil());
JCExpression spread = letStmts.isEmpty() ? result : make().LetExpr(letStmts.toList(), result);
// Do we *statically* know the result must be a Sequence
final boolean primaryIsSequence = typeFact().isNonemptyIterableType(expr.getPrimary().getTypeModel());
Type returnElementType = expr.getTarget().getType();
if (primaryIsSequence) {
int flags = EXPR_DOWN_CAST;
spread = applyErasureAndBoxing(spread, typeFact().getSequentialType(returnElementType), false, true, BoxingStrategy.BOXED, primaryIsSequence ? typeFact().getSequenceType(returnElementType) : typeFact().getSequentialType(returnElementType), flags);
}
return spread;
} finally {
spreading = oldSpreading;
}
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project bazel by bazelbuild.
the class InternalUtils method constructor.
/**
* Determines the symbol for a constructor given an invocation via
* {@code new}.
*
* If the tree is a declaration of an anonymous class, then method returns
* constructor that gets invoked in the extended class, rather than the
* anonymous constructor implicitly added by the constructor (JLS 15.9.5.1)
*
* @param tree the constructor invocation
* @return the {@link ExecutableElement} corresponding to the constructor
* call in {@code tree}
*/
public static ExecutableElement constructor(NewClassTree tree) {
if (!(tree instanceof JCTree.JCNewClass)) {
ErrorReporter.errorAbort("InternalUtils.constructor: not a javac internal tree");
// dead code
return null;
}
JCNewClass newClassTree = (JCNewClass) tree;
if (RETURN_INVOKE_CONSTRUCTOR && tree.getClassBody() != null) {
// anonymous constructor bodies should contain exactly one statement
// in the form:
// super(arg1, ...)
// or
// o.super(arg1, ...)
//
// which is a method invocation (!) to the actual constructor
// the method call is guaranteed to return nonnull
JCMethodDecl anonConstructor = (JCMethodDecl) TreeInfo.declarationFor(newClassTree.constructor, newClassTree);
assert anonConstructor != null;
assert anonConstructor.body.stats.size() == 1;
JCExpressionStatement stmt = (JCExpressionStatement) anonConstructor.body.stats.head;
JCTree.JCMethodInvocation superInvok = (JCMethodInvocation) stmt.expr;
return (ExecutableElement) TreeInfo.symbol(superInvok.meth);
}
Element e = newClassTree.constructor;
assert e instanceof ExecutableElement;
return (ExecutableElement) e;
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class JUnit3TestNotRun method matchMethod.
/**
* Matches if:
* 1) Method's name begins with misspelled variation of "test".
* 2) Method is public, returns void, and has no parameters.
* 3) Enclosing class is JUnit3 test (extends TestCase, has no RunWith annotation,
* and is not abstract).
*/
@Override
public Description matchMethod(MethodTree methodTree, VisitorState state) {
Matcher<MethodTree> methodMatcher = allOf(not(methodNameStartsWith("test")), Matchers.<MethodTree>hasModifier(Modifier.PUBLIC), methodReturns(VOID_TYPE), methodHasParameters(), enclosingClass(isJUnit3TestClass));
if (!methodMatcher.matches(methodTree, state)) {
return Description.NO_MATCH;
}
String name = methodTree.getName().toString();
String fixedName;
// regex.Matcher class name collides with errorprone.Matcher
java.util.regex.Matcher matcher = MISSPELLED_NAME.matcher(name);
if (matcher.lookingAt()) {
fixedName = matcher.replaceFirst("test");
} else if (wouldRunInJUnit4.matches(methodTree, state)) {
fixedName = "test" + name.substring(0, 1).toUpperCase() + name.substring(1);
} else {
return Description.NO_MATCH;
}
// We don't have start position for a method symbol, so we replace everything between result
// type and body.
JCMethodDecl decl = (JCMethodDecl) methodTree;
Fix fix = SuggestedFix.replace(decl.restype.getStartPosition() + 4, decl.body.getStartPosition(), " " + fixedName + "() ");
return describeMatch(methodTree, fix);
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class AbstractTestExceptionChecker method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (tree.getBody() == null) {
return NO_MATCH;
}
SuggestedFix.Builder baseFixBuilder = SuggestedFix.builder();
JCExpression expectedException = deleteExpectedException(baseFixBuilder, ((JCMethodDecl) tree).getModifiers().getAnnotations(), state);
SuggestedFix baseFix = baseFixBuilder.build();
if (expectedException == null) {
return NO_MATCH;
}
return handleStatements(tree, state, expectedException, baseFix);
}
Aggregations