Parses a Java method string regardless of modifier order. Example: "private native static int foo(String s)"
(declaration)
| 51 | return ctypes.CFUNCTYPE(ret_type, ctypes.c_void_p, ctypes.c_void_p, *param_types) |
| 52 | |
| 53 | def parse_method_declaration(declaration): |
| 54 | """ |
| 55 | Parses a Java method string regardless of modifier order. |
| 56 | Example: "private native static int foo(String s)" |
| 57 | """ |
| 58 | # 1. Separate Method Definition (left) from Parameters (right) |
| 59 | if '(' not in declaration or ')' not in declaration: |
| 60 | raise ValueError("Declaration must contain parenthesis '()'") |
| 61 | |
| 62 | def_part, params_part = declaration.split('(', 1) |
| 63 | params_part = params_part.rsplit(')', 1)[0] # remove trailing ')' |
| 64 | |
| 65 | # 2. Tokenize the definition part (handling generics vaguely) |
| 66 | # We replace generic brackets with underscores temporarily to avoid splitting errors |
| 67 | # if users input "List<String>". |
| 68 | # (A real parser is better, but this suffices for single-line inputs) |
| 69 | clean_def = re.sub(r'<[^>]+>', '', def_part) |
| 70 | tokens = clean_def.split() |
| 71 | |
| 72 | if len(tokens) < 2: |
| 73 | raise ValueError("Declaration too short. Needs at least ReturnType and MethodName.") |
| 74 | |
| 75 | # In Java, the last token before '(' is the Method Name |
| 76 | method_name = tokens[-1] |
| 77 | # The second to last is the Return Type |
| 78 | return_type = tokens[-2] |
| 79 | # Everything else are modifiers |
| 80 | modifiers = tokens[:-2] |
| 81 | |
| 82 | # Check for 'native' |
| 83 | if "native" not in modifiers: |
| 84 | print("Warning: 'native' keyword missing. Proceeding anyway...") |
| 85 | |
| 86 | # Check for 'static' |
| 87 | is_static = "static" in modifiers |
| 88 | |
| 89 | # 3. Parse Parameters |
| 90 | params = [] |
| 91 | if params_part.strip(): |
| 92 | # Split by comma |
| 93 | raw_params = params_part.split(',') |
| 94 | for raw_p in raw_params: |
| 95 | raw_p = raw_p.strip() |
| 96 | # Regex to grab type and name: "String arg0" or "int[] numbers" |
| 97 | # We ignore keywords like final or annotations for the signature |
| 98 | parts = raw_p.split() |
| 99 | if not parts: continue |
| 100 | |
| 101 | # Usually the type is the second-to-last word if modifiers exist, |
| 102 | # or first word if simple. |
| 103 | # Heuristic: The Type is the word immediately preceding the Variable Name. |
| 104 | if len(parts) >= 2: |
| 105 | p_type = parts[-2] |
| 106 | else: |
| 107 | p_type = parts[0] # Just a type, no variable name provided |
| 108 | |
| 109 | params.append((p_type, False)) |
| 110 |