use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.
the class ClassTransformer method makeParamDefaultValueMethod.
/**
* Creates a (possibly abstract) method for retrieving the value for a
* defaulted parameter
* @param typeParameterList
*/
MethodDefinitionBuilder makeParamDefaultValueMethod(boolean noBody, Declaration container, Tree.ParameterList params, Tree.Parameter currentParam) {
at(currentParam);
Parameter parameter = currentParam.getParameterModel();
if (!Strategy.hasDefaultParameterValueMethod(parameter)) {
throw new BugException();
}
MethodDefinitionBuilder methodBuilder = MethodDefinitionBuilder.systemMethod(this, Naming.getDefaultedParamMethodName(container, parameter));
methodBuilder.ignoreModelAnnotations();
if (container != null && Decl.isAnnotationConstructor(container)) {
AnnotationInvocation ac = (AnnotationInvocation) ((Function) container).getAnnotationConstructor();
for (AnnotationConstructorParameter acp : ac.getConstructorParameters()) {
if (acp.getParameter().equals(parameter) && acp.getDefaultArgument() != null) {
methodBuilder.userAnnotations(acp.getDefaultArgument().makeDpmAnnotations(expressionGen()));
}
}
}
int modifiers = 0;
if (noBody) {
modifiers |= PUBLIC | ABSTRACT;
} else if (container == null || !(container instanceof Class && Strategy.defaultParameterMethodStatic(container))) {
// initializers can override parameter defaults
modifiers |= FINAL;
}
if (container != null && container.isShared()) {
modifiers |= PUBLIC;
} else if (container == null || (!container.isToplevel() && !noBody)) {
modifiers |= PRIVATE;
}
boolean staticMethod = Strategy.defaultParameterMethodStatic(container);
if (staticMethod) {
// static default parameter methods should be consistently public so that if non-shared class Top and
// shared class Bottom which extends Top both have the same default param name, we don't get an error
// if the Bottom class tries to "hide" a static public method with a private one
modifiers &= ~PRIVATE;
modifiers |= STATIC | PUBLIC;
}
methodBuilder.modifiers(modifiers);
if (container instanceof Constructor) {
copyTypeParameters((Class) container.getContainer(), methodBuilder);
methodBuilder.reifiedTypeParameters(((Class) container.getContainer()).getTypeParameters());
} else if (container instanceof Generic) {
// make sure reified type parameters are accepted
copyTypeParameters((Generic) container, methodBuilder);
methodBuilder.reifiedTypeParameters(((Generic) container).getTypeParameters());
}
WideningRules wideningRules = !staticMethod && container instanceof Class ? WideningRules.CAN_WIDEN : WideningRules.NONE;
// Add any of the preceding parameters as parameters to the method
for (Tree.Parameter p : params.getParameters()) {
if (p.equals(currentParam)) {
break;
}
at(p);
methodBuilder.parameter(p.getParameterModel(), null, 0, wideningRules);
}
// The method's return type is the same as the parameter's type
NonWideningParam nonWideningParam = methodBuilder.getNonWideningParam(currentParam.getParameterModel().getModel(), wideningRules);
methodBuilder.resultType(nonWideningParam.nonWideningDecl, nonWideningParam.nonWideningType, nonWideningParam.flags);
// The implementation of the method
if (noBody) {
methodBuilder.noBody();
} else {
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(Decl.getDefaultArgument(currentParam).getExpression());
if (error != null) {
methodBuilder.body(this.makeThrowUnresolvedCompilationError(error));
} else {
java.util.List<TypeParameter> copiedTypeParameters = null;
if (container instanceof Generic) {
copiedTypeParameters = ((Generic) container).getTypeParameters();
if (copiedTypeParameters != null)
addTypeParameterSubstitution(copiedTypeParameters);
}
try {
JCExpression expr = expressionGen().transform(currentParam);
JCBlock body = at(currentParam).Block(0, List.<JCStatement>of(at(currentParam).Return(expr)));
methodBuilder.block(body);
} finally {
if (copiedTypeParameters != null)
popTypeParameterSubstitution();
}
}
}
return methodBuilder;
}
use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.
the class ClassTransformer method transform.
public AttributeDefinitionBuilder transform(AttributeSetterDefinition decl, boolean forCompanion) {
if (Strategy.onlyOnCompanion(decl.getDeclarationModel()) && !forCompanion) {
return null;
}
String name = decl.getIdentifier().getText();
final AttributeDefinitionBuilder builder = AttributeDefinitionBuilder.setter(this, name, decl.getDeclarationModel().getGetter()).modifiers(transformAttributeGetSetDeclFlags(decl.getDeclarationModel(), forCompanion));
// companion class members are never actual no matter what the Declaration says
if (forCompanion)
builder.notActual();
if (Decl.withinClass(decl) || forCompanion) {
JCBlock setterBlock = makeSetterBlock(decl.getDeclarationModel(), decl.getBlock(), decl.getSpecifierExpression());
builder.setterBlock(setterBlock);
} else {
builder.isFormal(true);
}
builder.userAnnotationsSetter(expressionGen().transformAnnotations(OutputElement.SETTER, decl));
return builder;
}
use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeSetterBlock.
JCBlock makeSetterBlock(TypedDeclaration declarationModel, final Tree.Block block, final Tree.SpecifierOrInitializerExpression expression) {
List<JCStatement> stats;
if (block != null) {
stats = statementGen().transformBlock(block);
} else {
Type type = declarationModel.getType();
JCStatement transStmt;
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getExpression());
if (error != null) {
transStmt = this.makeThrowUnresolvedCompilationError(error);
} else {
transStmt = make().Exec(expressionGen().transformExpression(expression.getExpression(), BoxingStrategy.INDIFFERENT, type));
}
stats = List.<JCStatement>of(transStmt);
}
JCBlock setterBlock = make().Block(0, stats);
return setterBlock;
}
use of com.sun.tools.javac.tree.JCTree.JCBlock in project ceylon-compiler by ceylon.
the class AbstractTransformer method makeGetterBlock.
JCBlock makeGetterBlock(TypedDeclaration declarationModel, final Tree.Block block, final Tree.SpecifierOrInitializerExpression expression) {
List<JCStatement> stats;
if (block != null) {
stats = statementGen().transformBlock(block);
} else {
BoxingStrategy boxing = CodegenUtil.getBoxingStrategy(declarationModel);
Type type = declarationModel.getType();
JCStatement transStat;
HasErrorException error = errors().getFirstExpressionErrorAndMarkBrokenness(expression.getExpression());
if (error != null) {
transStat = this.makeThrowUnresolvedCompilationError(error);
} else {
transStat = make().Return(expressionGen().transformExpression(expression.getExpression(), boxing, type));
}
stats = List.<JCStatement>of(transStat);
}
JCBlock getterBlock = make().Block(0, stats);
return getterBlock;
}
use of com.sun.tools.javac.tree.JCTree.JCBlock in project lombok by rzwitserloot.
the class HandleEqualsAndHashCode method createEquals.
public JCMethodDecl createEquals(JavacNode typeNode, java.util.List<Included<JavacNode, EqualsAndHashCode.Include>> members, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JavacNode source, List<JCAnnotation> onParam) {
JavacTreeMaker maker = typeNode.getTreeMaker();
Name oName = typeNode.toName("o");
Name otherName = typeNode.toName("other");
Name thisName = typeNode.toName("this");
List<JCAnnotation> annsOnParamOnMethod = List.nil();
JCAnnotation overrideAnnotation = maker.Annotation(genJavaLangTypeRef(typeNode, "Override"), List.<JCExpression>nil());
List<JCAnnotation> annsOnMethod = List.of(overrideAnnotation);
CheckerFrameworkVersion checkerFramework = getCheckerFrameworkVersion(typeNode);
if (checkerFramework.generateSideEffectFree()) {
annsOnMethod = annsOnMethod.prepend(maker.Annotation(genTypeRef(typeNode, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE), List.<JCExpression>nil()));
}
JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annsOnMethod);
JCExpression objectType;
if (annsOnParamOnMethod.isEmpty()) {
objectType = genJavaLangTypeRef(typeNode, "Object");
} else {
objectType = chainDots(typeNode, "java", "lang", "Object");
objectType = maker.AnnotatedType(annsOnParamOnMethod, objectType);
}
JCExpression returnType = maker.TypeIdent(CTC_BOOLEAN);
long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
JCVariableDecl param = maker.VarDef(maker.Modifiers(finalFlag | Flags.PARAMETER, onParam), oName, objectType, null);
JavacHandlerUtil.createRelevantNullableAnnotation(typeNode, param);
final List<JCVariableDecl> params = List.of(param);
/* if (o == this) return true; */
{
statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName), maker.Ident(thisName)), returnBool(maker, true), null));
}
/* if (!(o instanceof Outer.Inner.MyType)) return false; */
{
JCUnary notInstanceOf = maker.Unary(CTC_NOT, maker.Parens(maker.TypeTest(maker.Ident(oName), createTypeReference(typeNode, false))));
statements.append(maker.If(notInstanceOf, returnBool(maker, false), null));
}
/* Outer.Inner.MyType<?> other = (Outer.Inner.MyType<?>) o; */
{
if (!members.isEmpty() || needsCanEqual) {
final JCExpression selfType1 = createTypeReference(typeNode, true), selfType2 = createTypeReference(typeNode, true);
statements.append(maker.VarDef(maker.Modifiers(finalFlag), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName))));
}
}
/* if (!other.canEqual((java.lang.Object) this)) return false; */
{
if (needsCanEqual) {
List<JCExpression> exprNil = List.nil();
JCExpression thisRef = maker.Ident(thisName);
JCExpression castThisRef = maker.TypeCast(genJavaLangTypeRef(typeNode, "Object"), thisRef);
JCExpression equalityCheck = maker.Apply(exprNil, maker.Select(maker.Ident(otherName), typeNode.toName("canEqual")), List.of(castThisRef));
statements.append(maker.If(maker.Unary(CTC_NOT, equalityCheck), returnBool(maker, false), null));
}
}
/* if (!super.equals(o)) return false; */
if (callSuper) {
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")), List.<JCExpression>of(maker.Ident(oName)));
JCUnary superNotEqual = maker.Unary(CTC_NOT, callToSuper);
statements.append(maker.If(superNotEqual, returnBool(maker, false), null));
}
for (Included<JavacNode, EqualsAndHashCode.Include> member : members) {
JavacNode memberNode = member.getNode();
boolean isMethod = memberNode.getKind() == Kind.METHOD;
JCExpression fType = unnotate(getFieldType(memberNode, fieldAccess));
JCExpression thisFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode) : createFieldAccessor(maker, memberNode, fieldAccess);
JCExpression otherFieldAccessor = isMethod ? createMethodAccessor(maker, memberNode, maker.Ident(otherName)) : createFieldAccessor(maker, memberNode, fieldAccess, maker.Ident(otherName));
if (fType instanceof JCPrimitiveTypeTree) {
switch(((JCPrimitiveTypeTree) fType).getPrimitiveTypeKind()) {
case FLOAT:
/* if (Float.compare(this.fieldName, other.fieldName) != 0) return false; */
statements.append(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, maker, typeNode, false));
break;
case DOUBLE:
/* if (Double.compare(this.fieldName, other.fieldName) != 0) return false; */
statements.append(generateCompareFloatOrDouble(thisFieldAccessor, otherFieldAccessor, maker, typeNode, true));
break;
default:
/* if (this.fieldName != other.fieldName) return false; */
statements.append(maker.If(maker.Binary(CTC_NOT_EQUAL, thisFieldAccessor, otherFieldAccessor), returnBool(maker, false), null));
break;
}
} else if (fType instanceof JCArrayTypeTree) {
JCArrayTypeTree array = (JCArrayTypeTree) fType;
/* if (!java.util.Arrays.deepEquals(this.fieldName, other.fieldName)) return false; //use equals for primitive arrays. */
boolean multiDim = unnotate(array.elemtype) instanceof JCArrayTypeTree;
boolean primitiveArray = unnotate(array.elemtype) instanceof JCPrimitiveTypeTree;
boolean useDeepEquals = multiDim || !primitiveArray;
JCExpression eqMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepEquals ? "deepEquals" : "equals");
List<JCExpression> args = List.of(thisFieldAccessor, otherFieldAccessor);
statements.append(maker.If(maker.Unary(CTC_NOT, maker.Apply(List.<JCExpression>nil(), eqMethod, args)), returnBool(maker, false), null));
} else /* objects */
{
/* final java.lang.Object this$fieldName = this.fieldName; */
/* final java.lang.Object other$fieldName = other.fieldName; */
/* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
Name thisDollarFieldName = memberNode.toName("this" + (isMethod ? "$$" : "$") + memberNode.getName());
Name otherDollarFieldName = memberNode.toName("other" + (isMethod ? "$$" : "$") + memberNode.getName());
statements.append(maker.VarDef(maker.Modifiers(finalFlag), thisDollarFieldName, genJavaLangTypeRef(typeNode, "Object"), thisFieldAccessor));
statements.append(maker.VarDef(maker.Modifiers(finalFlag), otherDollarFieldName, genJavaLangTypeRef(typeNode, "Object"), otherFieldAccessor));
JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(thisDollarFieldName), maker.Literal(CTC_BOT, null));
JCExpression otherNotEqualsNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(otherDollarFieldName), maker.Literal(CTC_BOT, null));
JCExpression thisEqualsThat = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(thisDollarFieldName), typeNode.toName("equals")), List.<JCExpression>of(maker.Ident(otherDollarFieldName)));
JCExpression fieldsAreNotEqual = maker.Conditional(thisEqualsNull, otherNotEqualsNull, maker.Unary(CTC_NOT, thisEqualsThat));
statements.append(maker.If(fieldsAreNotEqual, returnBool(maker, false), null));
}
}
/* return true; */
{
statements.append(returnBool(maker, true));
}
JCBlock body = maker.Block(0, statements.toList());
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("equals"), returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source);
}
Aggregations