mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 09:04:08 +00:00
Captured full/type/name offsets of method declarations
This commit is contained in:
1 parent
9aa23ef49d
commit
b7333bcf6a
2 files changed
+123
-19
No files matched your search
@@ -5,11 +5,20 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Metadata for a method declaration or method call.
|
||||
* Tracks method name, parameters, return type, and containing class.
|
||||
*
|
||||
* <p>This class delegates to helper classes for specific functionality:</p>
|
||||
* <ul>
|
||||
* <li>{@link ControlFlowAnalyzer} - Control flow analysis for missing return detection</li>
|
||||
* <li>{@link CodeParser} - Code parsing utilities (brace matching, comment removal)</li>
|
||||
* <li>{@link TypeChecker} - Type compatibility checking</li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class MethodInfo {
|
||||
|
||||
@@ -17,7 +26,9 @@ public final class MethodInfo {
|
||||
private final TypeInfo returnType;
|
||||
private final TypeInfo containingType; // The class/interface that owns this method
|
||||
private final List<FieldInfo> parameters;
|
||||
private final int declarationOffset; // -1 for external methods (calls to library methods)
|
||||
private final int fullDeclarationOffset; // Start of full declaration (including modifiers), -1 for external
|
||||
private final int typeOffset; // Start of return type
|
||||
private final int nameOffset; // Start of method name
|
||||
private final int bodyStart; // Start of method body (after {)
|
||||
private final int bodyEnd; // End of method body (before })
|
||||
private final boolean resolved;
|
||||
@@ -26,14 +37,16 @@ public final class MethodInfo {
|
||||
private final String documentation; // Javadoc/comment documentation for this method
|
||||
|
||||
private MethodInfo(String name, TypeInfo returnType, TypeInfo containingType,
|
||||
List<FieldInfo> parameters, int declarationOffset,
|
||||
List<FieldInfo> parameters, int fullDeclarationOffset, int typeOffset, int nameOffset,
|
||||
int bodyStart, int bodyEnd, boolean resolved, boolean isDeclaration,
|
||||
int modifiers, String documentation) {
|
||||
this.name = name;
|
||||
this.returnType = returnType;
|
||||
this.containingType = containingType;
|
||||
this.parameters = parameters != null ? new ArrayList<>(parameters) : new ArrayList<>();
|
||||
this.declarationOffset = declarationOffset;
|
||||
this.fullDeclarationOffset = fullDeclarationOffset;
|
||||
this.typeOffset = typeOffset;
|
||||
this.nameOffset = nameOffset;
|
||||
this.bodyStart = bodyStart;
|
||||
this.bodyEnd = bodyEnd;
|
||||
this.resolved = resolved;
|
||||
@@ -44,25 +57,29 @@ public final class MethodInfo {
|
||||
|
||||
// Factory methods
|
||||
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
|
||||
int declOffset, int bodyStart, int bodyEnd) {
|
||||
return new MethodInfo(name, returnType, null, params, declOffset, bodyStart, bodyEnd, true, true, 0, null);
|
||||
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);
|
||||
}
|
||||
|
||||
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
|
||||
int declOffset, int bodyStart, int bodyEnd, boolean isStatic) {
|
||||
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, declOffset, bodyStart, bodyEnd, true, true, modifiers, null);
|
||||
return new MethodInfo(name, returnType, null, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, modifiers, null);
|
||||
}
|
||||
|
||||
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
|
||||
int declOffset, int bodyStart, int bodyEnd, boolean isStatic, String documentation) {
|
||||
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, declOffset, bodyStart, bodyEnd, true, true, modifiers, documentation);
|
||||
return new MethodInfo(name, returnType, null, params, fullDeclOffset, typeOffset, nameOffset, bodyStart, bodyEnd, true, true, modifiers, documentation);
|
||||
}
|
||||
|
||||
public static MethodInfo declaration(String name, TypeInfo returnType, List<FieldInfo> params,
|
||||
int declOffset, int bodyStart, int bodyEnd, int modifiers, String documentation) {
|
||||
return new MethodInfo(name, returnType, null, params, declOffset, bodyStart, bodyEnd, true, true, modifiers, documentation);
|
||||
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);
|
||||
}
|
||||
|
||||
public static MethodInfo call(String name, TypeInfo containingType, int paramCount) {
|
||||
@@ -72,7 +89,7 @@ public final class MethodInfo {
|
||||
for (int i = 0; i < paramCount; i++) {
|
||||
params.add(FieldInfo.unresolved("arg" + i, FieldInfo.Scope.PARAMETER));
|
||||
}
|
||||
return new MethodInfo(name, null, containingType, params, -1, -1, -1, resolved, false, 0, null);
|
||||
return new MethodInfo(name, null, containingType, params, -1, -1, -1, -1, -1, resolved, false, 0, null);
|
||||
}
|
||||
|
||||
public static MethodInfo unresolvedCall(String name, int paramCount) {
|
||||
@@ -80,7 +97,7 @@ public final class MethodInfo {
|
||||
for (int i = 0; i < paramCount; i++) {
|
||||
params.add(FieldInfo.unresolved("arg" + i, FieldInfo.Scope.PARAMETER));
|
||||
}
|
||||
return new MethodInfo(name, null, null, params, -1, -1, -1, false, false, 0, null);
|
||||
return new MethodInfo(name, null, null, params, -1, -1, -1, -1, -1, false, false, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +116,7 @@ public final class MethodInfo {
|
||||
params.add(FieldInfo.reflectionParam("arg" + i, paramType));
|
||||
}
|
||||
|
||||
return new MethodInfo(name, returnType, containingType, params, -1, -1, -1, true, false, modifiers, null);
|
||||
return new MethodInfo(name, returnType, containingType, params, -1, -1, -1, -1, -1, true, false, modifiers, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +135,7 @@ public final class MethodInfo {
|
||||
params.add(FieldInfo.reflectionParam("arg" + i, paramType));
|
||||
}
|
||||
|
||||
return new MethodInfo(name, returnType, containingType, params, -1, -1, -1, true, true, modifiers, null);
|
||||
return new MethodInfo(name, returnType, containingType, params, -1, -1, -1, -1, -1, true, true, modifiers, null);
|
||||
}
|
||||
|
||||
// Getters
|
||||
@@ -127,7 +144,12 @@ public final class MethodInfo {
|
||||
public TypeInfo getContainingType() { return containingType; }
|
||||
public List<FieldInfo> getParameters() { return Collections.unmodifiableList(parameters); }
|
||||
public int getParameterCount() { return parameters.size(); }
|
||||
public int getDeclarationOffset() { return declarationOffset; }
|
||||
/** @deprecated Use getTypeOffset() or getNameOffset() instead */
|
||||
@Deprecated
|
||||
public int getDeclarationOffset() { return typeOffset; }
|
||||
public int getFullDeclarationOffset() { return fullDeclarationOffset; }
|
||||
public int getTypeOffset() { return typeOffset; }
|
||||
public int getNameOffset() { return nameOffset; }
|
||||
public int getBodyStart() { return bodyStart; }
|
||||
public int getBodyEnd() { return bodyEnd; }
|
||||
public boolean isResolved() { return resolved; }
|
||||
|
||||
@@ -455,8 +455,23 @@ public class ScriptDocument {
|
||||
List<FieldInfo> params = parseParametersWithPositions(paramList,
|
||||
bodyStart + 1 + mm.start(3));
|
||||
|
||||
// Calculate the three offsets
|
||||
int typeOffset = bodyStart + 1 + mm.start(1); // Start of return type
|
||||
int nameOffset = bodyStart + 1 + mm.start(2); // Start of method name
|
||||
int fullDeclOffset = findFullDeclarationStart(mm.start(1), bodyText);
|
||||
if (fullDeclOffset >= 0) {
|
||||
fullDeclOffset += bodyStart + 1;
|
||||
} else {
|
||||
fullDeclOffset = typeOffset;
|
||||
}
|
||||
|
||||
MethodInfo methodInfo = MethodInfo.declaration(
|
||||
methodName, returnType, params, absPos, methodBodyStart, methodBodyEnd, modifiers, documentation);
|
||||
methodName, returnType, params, fullDeclOffset, typeOffset, nameOffset, methodBodyStart, methodBodyEnd, modifiers, documentation);
|
||||
|
||||
// Validate the method (including return type checking)
|
||||
String methodBodyText = text.substring(methodBodyStart + 1, methodBodyEnd);
|
||||
methodInfo.validate(methodBodyText, (expr, pos) -> resolveExpressionType(expr, pos));
|
||||
|
||||
scriptType.addMethod(methodInfo);
|
||||
}
|
||||
|
||||
@@ -485,12 +500,25 @@ public class ScriptDocument {
|
||||
// Parse parameters with their actual positions
|
||||
List<FieldInfo> params = parseParametersWithPositions(paramList, bodyStart + 1 + cm.start(1));
|
||||
|
||||
// Calculate the three offsets for constructor
|
||||
// For constructors, type offset and name offset are the same (start of constructor name)
|
||||
int nameOffset = bodyStart + 1 + cm.start();
|
||||
int typeOffset = nameOffset; // No separate type for constructors
|
||||
int fullDeclOffset = findFullDeclarationStart(cm.start(), bodyText);
|
||||
if (fullDeclOffset >= 0) {
|
||||
fullDeclOffset += bodyStart + 1;
|
||||
} else {
|
||||
fullDeclOffset = nameOffset;
|
||||
}
|
||||
|
||||
// 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
|
||||
params,
|
||||
absPos,
|
||||
fullDeclOffset,
|
||||
typeOffset,
|
||||
nameOffset,
|
||||
constructorBodyStart,
|
||||
constructorBodyEnd,
|
||||
modifiers,
|
||||
@@ -547,6 +575,11 @@ public class ScriptDocument {
|
||||
|
||||
// Extract modifiers by scanning backwards from match start
|
||||
int modifiers = extractModifiersBackwards(m.start() - 1, text);
|
||||
|
||||
// Calculate offset positions
|
||||
int typeOffset = m.start(1); // Start of return type
|
||||
int nameOffset = m.start(2); // Start of method name
|
||||
int fullDeclOffset = findFullDeclarationStart(m.start(1), text); // Start including modifiers
|
||||
|
||||
// Parse parameters with their actual positions
|
||||
List<FieldInfo> params = parseParametersWithPositions(paramList, m.start(3));
|
||||
@@ -555,12 +588,19 @@ public class ScriptDocument {
|
||||
methodName,
|
||||
resolveType(returnType),
|
||||
params,
|
||||
m.start(),
|
||||
fullDeclOffset,
|
||||
typeOffset,
|
||||
nameOffset,
|
||||
bodyStart,
|
||||
bodyEnd,
|
||||
modifiers,
|
||||
documentation
|
||||
);
|
||||
|
||||
// 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));
|
||||
|
||||
methods.add(methodInfo);
|
||||
}
|
||||
|
||||
@@ -584,6 +624,48 @@ public class ScriptDocument {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the start of a full method declaration, including any modifiers before the type.
|
||||
*/
|
||||
private int findFullDeclarationStart(int typeStart, String sourceText) {
|
||||
int pos = typeStart - 1;
|
||||
|
||||
// Skip whitespace before type
|
||||
while (pos >= 0 && Character.isWhitespace(sourceText.charAt(pos))) {
|
||||
pos--;
|
||||
}
|
||||
|
||||
// Check for modifiers
|
||||
int earliestPos = typeStart;
|
||||
while (pos >= 0) {
|
||||
// Skip whitespace
|
||||
while (pos >= 0 && Character.isWhitespace(sourceText.charAt(pos))) {
|
||||
pos--;
|
||||
}
|
||||
if (pos < 0) break;
|
||||
|
||||
// Read word backwards
|
||||
int wordEnd = pos + 1;
|
||||
while (pos >= 0 && Character.isJavaIdentifierPart(sourceText.charAt(pos))) {
|
||||
pos--;
|
||||
}
|
||||
int wordStart = pos + 1;
|
||||
|
||||
if (wordStart < wordEnd) {
|
||||
String word = sourceText.substring(wordStart, wordEnd);
|
||||
if (TypeResolver.isModifier(word)) {
|
||||
earliestPos = wordStart;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return earliestPos;
|
||||
}
|
||||
|
||||
private List<FieldInfo> parseParametersWithPositions(String paramList, int paramListStart) {
|
||||
List<FieldInfo> params = new ArrayList<>();
|
||||
if (paramList == null || paramList.trim().isEmpty()) {
|
||||
|
||||
Reference in new issue
Block a user