Skip to content

Commit

Permalink
Add null checks for tree.getParameters(), unit test for eclipse-archi…
Browse files Browse the repository at this point in the history
…ved#7441

Signed-off-by: Voitech <[email protected]>
  • Loading branch information
Voiteh committed Sep 19, 2019
1 parent 7e653a1 commit f408a8b
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -222,29 +222,32 @@ private List<JCTree> makeClassBody(Declaration decl, WantedDeclaration wantedDec
// only do it for Bootstrap where we control the annotations, because it's so dodgy ATM
if(wantedDeclaration == WantedDeclaration.Annotation){
ListBuffer<JCTree> body = new ListBuffer<JCTree>();
for(Tree.Parameter param : ((Tree.ClassDefinition)decl).getParameterList().getParameters()){
String name;

JCExpression type = make().TypeArray(make().Type(syms().stringType));
if(param instanceof Tree.InitializerParameter)
name = ((Tree.InitializerParameter)param).getIdentifier().getText();
else if(param instanceof Tree.ParameterDeclaration){
Tree.TypedDeclaration typedDeclaration = ((Tree.ParameterDeclaration)param).getTypedDeclaration();
name = typedDeclaration.getIdentifier().getText();
type = getAnnotationTypeFor(typedDeclaration.getType());
}else
name = "ERROR";
JCMethodDecl method
= make().MethodDef(make().Modifiers(Flags.PUBLIC), names().fromString(name),
type,
List.<JCTypeParameter>nil(),
List.<JCVariableDecl>nil(),
List.<JCExpression>nil(),
null,
null);
body.append(method);
}
return body.toList();
Tree.ClassDefinition classDefiniton=(Tree.ClassDefinition)decl;
if(classDefiniton.getParameterList()!=null) {
for(Tree.Parameter param : classDefiniton.getParameterList().getParameters()){
String name;

JCExpression type = make().TypeArray(make().Type(syms().stringType));
if(param instanceof Tree.InitializerParameter)
name = ((Tree.InitializerParameter)param).getIdentifier().getText();
else if(param instanceof Tree.ParameterDeclaration){
Tree.TypedDeclaration typedDeclaration = ((Tree.ParameterDeclaration)param).getTypedDeclaration();
name = typedDeclaration.getIdentifier().getText();
type = getAnnotationTypeFor(typedDeclaration.getType());
}else
name = "ERROR";
JCMethodDecl method
= make().MethodDef(make().Modifiers(Flags.PUBLIC), names().fromString(name),
type,
List.<JCTypeParameter>nil(),
List.<JCVariableDecl>nil(),
List.<JCExpression>nil(),
null,
null);
body.append(method);
}
return body.toList();
}
}
if(wantedDeclaration == WantedDeclaration.AnnotationSequence){
String name = Naming.toplevelClassName("", decl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -841,96 +841,99 @@ private void transformAnnotationClassConstructor(
// annotation

ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
if (!klass.getUnit().getPackage().isLanguagePackage()
|| !classBuilder.getClassName().equals("RestrictedAnnotation")) { //ignore argument to restricted()
for (Tree.Parameter parameter : def.getParameterList().getParameters()) {
at(parameter);
Parameter parameterModel = parameter.getParameterModel();
JCExpression annoAttr = make().Apply(null, naming.makeQuotedQualIdent(naming.makeUnquotedIdent("anno"),
parameter.getParameterModel().getName()),
List.<JCExpression>nil());
Type parameterType = parameterModel.getType();
JCExpression argExpr;
if (typeFact().isIterableType(parameterType)
&& !isCeylonString(parameterType)) {
// Convert from array to Sequential
Type iteratedType = typeFact().getIteratedType(parameterType);
boolean nonEmpty = typeFact().isNonemptyIterableType(parameterType);
if (isCeylonBasicType(iteratedType)) {
argExpr = utilInvocation().sequentialWrapperBoxed(annoAttr);
} else if (Decl.isAnnotationClass(iteratedType.getDeclaration())) {
// Can't use Util.sequentialAnnotation becase we need to 'box'
// the Java annotations in their Ceylon annotation class
argExpr = make().Apply(null, naming.makeUnquotedIdent(naming.getAnnotationSequenceMethodName()), List.of(annoAttr));
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
SyntheticName array = naming.synthetic(Unfix.$array$);
SyntheticName sb = naming.synthetic(Unfix.$sb$);
SyntheticName index = naming.synthetic(Unfix.$index$);
SyntheticName element = naming.synthetic(Unfix.$element$);
stmts.append(makeVar(FINAL, sb,
make().TypeArray(make().Type(syms().objectType)),
make().NewArray(make().Type(syms().objectType), List.of(naming.makeQualIdent(array.makeIdent(), "length")), null)));
stmts.append(makeVar(index,
make().Type(syms().intType),
make().Literal(0)));
stmts.append(make().ForeachLoop(
makeVar(element, makeJavaType(iteratedType, JT_ANNOTATION), null),
array.makeIdent(),
make().Exec(make().Assign(
make().Indexed(sb.makeIdent(),
make().Unary(JCTree.Tag.POSTINC, index.makeIdent())),
instantiateAnnotationClass(iteratedType, element.makeIdent())))));
stmts.append(make().Return(
make().NewClass(null,
null,
make().QualIdent(syms().ceylonTupleType.tsym),
List.of(makeReifiedTypeArgument(iteratedType),
sb.makeIdent(),
makeEmpty(),
make().Literal(false)),
null)));
classBuilder.method(
systemMethod(this, naming.getAnnotationSequenceMethodName())
.ignoreModelAnnotations()
.modifiers(PRIVATE | STATIC)
.resultType(new TransformedType(makeJavaType(typeFact().getSequentialType(iteratedType)), null, makeAtNonNull()))
.parameter(systemParameter(this, array.getName())
.type(new TransformedType(make().TypeArray(makeJavaType(iteratedType, JT_ANNOTATION)))))
.body(stmts.toList()));
} else if (isCeylonMetamodelDeclaration(iteratedType)) {
argExpr = makeMetamodelInvocation("parseMetamodelReferences",
List.<JCExpression>of(makeReifiedTypeArgument(iteratedType), annoAttr),
List.<JCExpression>of(makeJavaType(iteratedType, JT_TYPE_ARGUMENT)));
} else if (Decl.isEnumeratedTypeWithAnonCases(iteratedType)) {
argExpr = makeMetamodelInvocation("parseEnumerationReferences",
List.<JCExpression>of(makeReifiedTypeArgument(iteratedType), annoAttr),
List.<JCExpression>of(makeJavaType(iteratedType, JT_TYPE_ARGUMENT)));
} else {
argExpr = makeErroneous(parameter, "compiler bug");
}
if (nonEmpty) {
argExpr = make().TypeCast(makeJavaType(parameterType), argExpr);
}
} else if (Decl.isAnnotationClass(parameterType.getDeclaration())) {
argExpr = instantiateAnnotationClass(parameterType, annoAttr);
} else if (isCeylonMetamodelDeclaration(parameterType)) {
argExpr = makeMetamodelInvocation("parseMetamodelReference",
List.<JCExpression>of(annoAttr),
List.<JCExpression>of(makeJavaType(parameterType, JT_TYPE_ARGUMENT)));
} else if (Decl.isEnumeratedTypeWithAnonCases(parameterType)) {
argExpr = makeMetamodelInvocation("parseEnumerationReference",
List.<JCExpression>of(annoAttr),
null);
} else {
argExpr = annoAttr;
argExpr = expressionGen().applyErasureAndBoxing(annoAttr, parameterType.withoutUnderlyingType(), false, BoxingStrategy.UNBOXED, parameterType);
}

args.add(argExpr);
}
if(def.getParameterList()!=null) {
if (!klass.getUnit().getPackage().isLanguagePackage()
|| !classBuilder.getClassName().equals("RestrictedAnnotation")) { //ignore argument to restricted()
for (Tree.Parameter parameter : def.getParameterList().getParameters()) {
at(parameter);
Parameter parameterModel = parameter.getParameterModel();
JCExpression annoAttr = make().Apply(null, naming.makeQuotedQualIdent(naming.makeUnquotedIdent("anno"),
parameter.getParameterModel().getName()),
List.<JCExpression>nil());
Type parameterType = parameterModel.getType();
JCExpression argExpr;
if (typeFact().isIterableType(parameterType)
&& !isCeylonString(parameterType)) {
// Convert from array to Sequential
Type iteratedType = typeFact().getIteratedType(parameterType);
boolean nonEmpty = typeFact().isNonemptyIterableType(parameterType);
if (isCeylonBasicType(iteratedType)) {
argExpr = utilInvocation().sequentialWrapperBoxed(annoAttr);
} else if (Decl.isAnnotationClass(iteratedType.getDeclaration())) {
// Can't use Util.sequentialAnnotation becase we need to 'box'
// the Java annotations in their Ceylon annotation class
argExpr = make().Apply(null, naming.makeUnquotedIdent(naming.getAnnotationSequenceMethodName()), List.of(annoAttr));
ListBuffer<JCStatement> stmts = new ListBuffer<JCStatement>();
SyntheticName array = naming.synthetic(Unfix.$array$);
SyntheticName sb = naming.synthetic(Unfix.$sb$);
SyntheticName index = naming.synthetic(Unfix.$index$);
SyntheticName element = naming.synthetic(Unfix.$element$);
stmts.append(makeVar(FINAL, sb,
make().TypeArray(make().Type(syms().objectType)),
make().NewArray(make().Type(syms().objectType), List.of(naming.makeQualIdent(array.makeIdent(), "length")), null)));
stmts.append(makeVar(index,
make().Type(syms().intType),
make().Literal(0)));
stmts.append(make().ForeachLoop(
makeVar(element, makeJavaType(iteratedType, JT_ANNOTATION), null),
array.makeIdent(),
make().Exec(make().Assign(
make().Indexed(sb.makeIdent(),
make().Unary(JCTree.Tag.POSTINC, index.makeIdent())),
instantiateAnnotationClass(iteratedType, element.makeIdent())))));
stmts.append(make().Return(
make().NewClass(null,
null,
make().QualIdent(syms().ceylonTupleType.tsym),
List.of(makeReifiedTypeArgument(iteratedType),
sb.makeIdent(),
makeEmpty(),
make().Literal(false)),
null)));
classBuilder.method(
systemMethod(this, naming.getAnnotationSequenceMethodName())
.ignoreModelAnnotations()
.modifiers(PRIVATE | STATIC)
.resultType(new TransformedType(makeJavaType(typeFact().getSequentialType(iteratedType)), null, makeAtNonNull()))
.parameter(systemParameter(this, array.getName())
.type(new TransformedType(make().TypeArray(makeJavaType(iteratedType, JT_ANNOTATION)))))
.body(stmts.toList()));
} else if (isCeylonMetamodelDeclaration(iteratedType)) {
argExpr = makeMetamodelInvocation("parseMetamodelReferences",
List.<JCExpression>of(makeReifiedTypeArgument(iteratedType), annoAttr),
List.<JCExpression>of(makeJavaType(iteratedType, JT_TYPE_ARGUMENT)));
} else if (Decl.isEnumeratedTypeWithAnonCases(iteratedType)) {
argExpr = makeMetamodelInvocation("parseEnumerationReferences",
List.<JCExpression>of(makeReifiedTypeArgument(iteratedType), annoAttr),
List.<JCExpression>of(makeJavaType(iteratedType, JT_TYPE_ARGUMENT)));
} else {
argExpr = makeErroneous(parameter, "compiler bug");
}
if (nonEmpty) {
argExpr = make().TypeCast(makeJavaType(parameterType), argExpr);
}
} else if (Decl.isAnnotationClass(parameterType.getDeclaration())) {
argExpr = instantiateAnnotationClass(parameterType, annoAttr);
} else if (isCeylonMetamodelDeclaration(parameterType)) {
argExpr = makeMetamodelInvocation("parseMetamodelReference",
List.<JCExpression>of(annoAttr),
List.<JCExpression>of(makeJavaType(parameterType, JT_TYPE_ARGUMENT)));
} else if (Decl.isEnumeratedTypeWithAnonCases(parameterType)) {
argExpr = makeMetamodelInvocation("parseEnumerationReference",
List.<JCExpression>of(annoAttr),
null);
} else {
argExpr = annoAttr;
argExpr = expressionGen().applyErasureAndBoxing(annoAttr, parameterType.withoutUnderlyingType(), false, BoxingStrategy.UNBOXED, parameterType);
}

args.add(argExpr);
}
}
}
annoCtor.body(at(def).Exec(
make().Apply(null, naming.makeThis(), args.toList())));

}

private JCNewClass instantiateAnnotationClass(
Expand Down Expand Up @@ -983,9 +986,10 @@ private List<JCTree> transformAnnotationClass(Tree.AnyClass def) {
} else {
annoBuilder.annotations(transformAnnotationConstraints(klass));
}

for (Tree.Parameter p : def.getParameterList().getParameters()) {
annoBuilder.method(makeAnnotationMethod(p));
if(def.getParameterList()!=null) {
for (Tree.Parameter p : def.getParameterList().getParameters()) {
annoBuilder.method(makeAnnotationMethod(p));
}
}
List<JCTree> result;
if (isSequencedAnnotation(klass)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,8 @@ public void bug7263() throws Throwable{
compile("bug72xx/bug7263/run.ceylon");
runInJBossModules("run", "org.eclipse.ceylon.compiler.java.test.issues.bug72xx.bug7263/1", Collections.<String>emptyList());
}
@Test
public void bug7441() {
assertErrors("bug74xx/bug7441",Collections.emptyList(), null,new CompilerError(8, "illegal annotation parameter type: 'Anything'") );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import ceylon.language.meta.declaration {
ValueDeclaration
}

shared final annotation class TestAnnotation satisfies OptionalAnnotation<TestAnnotation,ValueDeclaration> {
shared new (Anything args) {}
}
shared annotation TestAnnotation testAnnotation(Anything args) => TestAnnotation(args);
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ private void checkAnnotationType(Tree.AnyClass that, Class c) {
that.addError("annotation class must directly extend 'Basic'");
}
}
if(that.getParameterList()!=null)
for (Tree.Parameter pn:
that.getParameterList().getParameters()) {
checkAnnotationParameter(c, pn);
Expand Down

0 comments on commit f408a8b

Please sign in to comment.