Added INTERFACE_METHOD_BODY error & improved logic

This commit is contained in:
bigguy345 committed 2025-12-31 16:53:38 +02:00
1 parent c97de07ef7
commit 6cdb222b67
3 files changed
+36 -61

No files matched your search

@@ -448,7 +448,9 @@ public class ScriptDocument {
// Constructors don't have a return type, but we'll use the containing type as a marker
MethodInfo constructorInfo = MethodInfo.declaration(
typeName,
scriptType, // Return type is the type itself
scriptType,
// Return type is the type itself
scriptType,
params,
fullDeclOffset,
typeOffset,
@@ -456,8 +458,7 @@ public class ScriptDocument {
constructorBodyStart,
constructorBodyEnd,
modifiers,
documentation
);
documentation);
scriptType.addConstructor(constructorInfo);
}
}
@@ -504,10 +505,10 @@ public class ScriptDocument {
String methodName = m.group(2);
String paramList = m.group(3);
String delimiter = m.group(4);
boolean bodyless = delimiter.equals(";");
boolean hasBody = delimiter.equals("{");
int bodyStart = bodyless ? m.end() : text.indexOf('{', m.end() - 1);
int bodyEnd = bodyless ? m.end() : findMatchingBrace(bodyStart);
int bodyStart = !hasBody ? m.end() : text.indexOf('{', m.end() - 1);
int bodyEnd = !hasBody ? m.end() : findMatchingBrace(bodyStart);
if (bodyEnd < 0)
bodyEnd = text.length();
@@ -523,11 +524,19 @@ public class ScriptDocument {
int nameOffset = m.start(2); // Start of method name
int fullDeclOffset = findFullDeclarationStart(m.start(1), text); // Start including modifiers
ScriptTypeInfo scriptType = null;
for (ScriptTypeInfo type : scriptTypes.values())
if (type.containsPosition(bodyStart)) {
scriptType = type;
break;
}
// Parse parameters with their actual positions
List<FieldInfo> params = parseParametersWithPositions(paramList, m.start(3));
MethodInfo methodInfo = MethodInfo.declaration(
methodName,
scriptType,
resolveType(returnType),
params,
fullDeclOffset,
@@ -539,25 +548,15 @@ public class ScriptDocument {
documentation
);
ScriptTypeInfo scriptType = null;
for (ScriptTypeInfo type : scriptTypes.values())
if (type.containsPosition(bodyStart)) {
scriptType = type;
break;
}
// Validate the method (return statements, parameters) with type resolution
String methodBodyText = bodyEnd > bodyStart + 1 ? text.substring(bodyStart + 1, bodyEnd) : "";
methodInfo.validate(methodBodyText, (expr, pos) -> resolveExpressionType(expr, pos));
if (scriptType != null) {
if (scriptType.getKind() == TypeInfo.Kind.INTERFACE)
methodInfo.setBodyless(bodyless);
scriptType.addMethod(methodInfo);
} else
methods.add(methodInfo);
// Validate the method (return statements, parameters) with type resolution
String methodBodyText = bodyEnd > bodyStart + 1 ? text.substring(bodyStart + 1, bodyEnd) : "";
methodInfo.validate(methodBodyText, hasBody, (expr, pos) -> resolveExpressionType(expr, pos));
}
// Check for duplicate method declarations
@@ -33,7 +33,8 @@ public final class MethodInfo {
*/
public enum ErrorType {
NONE,
MISSING_RETURN, // Non-void method missing return statement
MISSING_RETURN, // Non-void method missing return statement,
INTERFACE_METHOD_BODY, // Interface method has a body
MISSING_BODY, // Non-void method missing return statement
RETURN_TYPE_MISMATCH, // Return statement type doesn't match method return type
VOID_METHOD_RETURNS_VALUE, // Void method returns a value
@@ -57,7 +58,6 @@ public final class MethodInfo {
private final String documentation; // Javadoc/comment documentation for this method
private final java.lang.reflect.Method javaMethod; // The Java reflection Method, if this was created from reflection
private boolean bodyless;
// Error tracking for method declarations
private ErrorType errorType = ErrorType.NONE;
private String errorMessage;
@@ -84,31 +84,10 @@ public final class MethodInfo {
this.javaMethod = javaMethod;
}
// Factory methods
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
int fullDeclOffset, int typeOffset, int nameOffset,
int bodyStart, int bodyEnd) {
return new MethodInfo(name, returnType, null, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, 0, null, null);
}
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
int fullDeclOffset, int typeOffset, int nameOffset,
int bodyStart, int bodyEnd, boolean isStatic) {
int modifiers = isStatic ? Modifier.STATIC : 0;
return new MethodInfo(name, returnType, null, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, modifiers, null, null);
}
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
int fullDeclOffset, int typeOffset, int nameOffset,
int bodyStart, int bodyEnd, boolean isStatic, String documentation) {
int modifiers = isStatic ? Modifier.STATIC : 0;
return new MethodInfo(name, returnType, null, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, modifiers, documentation, null);
}
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
public static MethodInfo declaration(String name, TypeInfo containingType, TypeInfo returnType, List<FieldInfo> params,
int fullDeclOffset, int typeOffset, int nameOffset,
int bodyStart, int bodyEnd, int modifiers, String documentation) {
return new MethodInfo(name, returnType, null, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, modifiers, documentation, null);
return new MethodInfo(name, returnType, containingType, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, modifiers, documentation, null);
}
public static MethodInfo call(String name, TypeInfo containingType, int paramCount) {
@@ -195,8 +174,6 @@ public final class MethodInfo {
public boolean isPrivate() { return Modifier.isPrivate(modifiers); }
public boolean isProtected() { return Modifier.isProtected(modifiers); }
public String getDocumentation() { return documentation; }
public boolean isBodyless() { return bodyless; }
public void setBodyless(boolean bodyless) { this.bodyless = bodyless; }
/**
* Check if a position is inside this method's body.
@@ -407,16 +384,7 @@ public final class MethodInfo {
public interface TypeResolver {
TypeInfo resolveExpression(String expression, int position);
}
/**
* Validate this method declaration.
* Checks for parameter errors and missing return statements.
*
* @param methodBodyText The text content of the method body (between { and })
*/
public void validate(String methodBodyText) {
validate(methodBodyText, null);
}
/**
* Validate this method declaration with type resolution for return statements.
@@ -425,16 +393,22 @@ public final class MethodInfo {
* @param methodBodyText The text content of the method body (between { and })
* @param typeResolver Optional callback to resolve expression types (for return type checking)
*/
public void validate(String methodBodyText, TypeResolver typeResolver) {
public void validate(String methodBodyText, boolean hasBody, TypeResolver typeResolver) {
if (!isDeclaration) return;
// Validate parameters
validateParameters();
boolean interfaceMember = containingType != null && containingType.isInterface();
if (hasBody && (interfaceMember || isAbstract() || isNative())) {
setError(MethodInfo.ErrorType.INTERFACE_METHOD_BODY, "Interface or abstract methods cannot have a body");
return;
}
//No need to check for return types/statements
if(bodyless)
if(interfaceMember)
return;
//If no body and not interface or abstract/native
if (bodyStart == bodyEnd && !isAbstract() && !isNative()) {
setError(ErrorType.MISSING_BODY, "Method must have a body or be declared abstract/native.");
return;
@@ -130,7 +130,9 @@ public class TypeInfo {
public boolean isResolved() { return resolved; }
public TypeInfo getEnclosingType() { return enclosingType; }
public boolean isInnerClass() { return enclosingType != null; }
public boolean isInterface() {return kind == Kind.INTERFACE;}
public boolean isEnum() {return kind == Kind.ENUM;}
/**
* Get the appropriate TokenType for highlighting this type.
*/