in src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java [1770:1826]
private void validateMethodDeclaration(final MethodDeclarationContext ctx, final MethodNode methodNode, final ModifierManager modifierManager, final ClassNode classNode) {
if (1 == ctx.t || 2 == ctx.t || 3 == ctx.t) { // 1: normal method declaration; 2: abstract method declaration; 3: normal method declaration OR abstract method declaration
if (!(asBoolean(ctx.modifiersOpt().modifiers()) || asBoolean(ctx.returnType()))) {
throw createParsingFailedException("Modifiers or return type is required", ctx);
}
}
if (1 == ctx.t) {
if (!asBoolean(ctx.methodBody())) {
throw createParsingFailedException("Method body is required", ctx);
}
}
if (2 == ctx.t) {
if (asBoolean(ctx.methodBody())) {
throw createParsingFailedException("Abstract method should not have method body", ctx);
}
}
boolean isAbstractMethod = methodNode.isAbstract();
boolean hasMethodBody =
asBoolean(methodNode.getCode())
&& !(methodNode.getCode() instanceof ExpressionStatement);
if (9 == ctx.ct) { // script
if (isAbstractMethod || !hasMethodBody) { // method should not be declared abstract in the script
throw createParsingFailedException("You cannot define " + (isAbstractMethod ? "an abstract" : "a") + " method[" + methodNode.getName() + "] " + (!hasMethodBody ? "without method body " : "") + "in the script. Try " + (isAbstractMethod ? "removing the 'abstract'" : "") + (isAbstractMethod && !hasMethodBody ? " and" : "") + (!hasMethodBody ? " adding a method body" : ""), methodNode);
}
} else {
if (4 == ctx.ct) { // trait
if (isAbstractMethod && hasMethodBody) {
throw createParsingFailedException("Abstract method should not have method body", ctx);
}
}
if (3 == ctx.ct) { // annotation
if (hasMethodBody) {
throw createParsingFailedException("Annotation type element should not have body", ctx);
}
}
if (!isAbstractMethod && !hasMethodBody) { // non-abstract method without body in the non-script(e.g. class, enum, trait) is not allowed!
throw createParsingFailedException("You defined a method[" + methodNode.getName() + "] without a body. Try adding a method body, or declare it abstract", methodNode);
}
boolean isInterfaceOrAbstractClass = asBoolean(classNode) && classNode.isAbstract() && !classNode.isAnnotationDefinition();
if (isInterfaceOrAbstractClass && !modifierManager.containsAny(DEFAULT, PRIVATE) && isAbstractMethod && hasMethodBody) {
throw createParsingFailedException("You defined an abstract method[" + methodNode.getName() + "] with a body. Try removing the method body" + (classNode.isInterface() ? ", or declare it default or private" : ""), methodNode);
}
}
modifierManager.validate(methodNode);
if (methodNode instanceof ConstructorNode) {
modifierManager.validate((ConstructorNode) methodNode);
}
}