|
35 | 35 |
|
36 | 36 | java_parsing = True |
37 | 37 |
|
38 | | -default_java_version = '1.4' |
| 38 | +default_java_version = '25.0' |
39 | 39 |
|
40 | | -# a switch for which jdk versions to use the Scope state for smarter |
41 | | -# anonymous inner class parsing. |
42 | | -scopeStateVersions = ('1.8',) |
| 40 | +# Ancient Java versions that require special handling for anonymous inner classes. |
| 41 | +# Versions from 1.5 onwards use the modern stack-based behavior. |
| 42 | +ANCIENT_JAVA_VERSIONS = ('1.1', '1.2', '1.3', '1.4') |
| 43 | + |
| 44 | + |
| 45 | +def _version_uses_scope_state(version: str) -> bool: |
| 46 | + """Determine if a Java version uses ScopeState for anonymous inner classes. |
| 47 | +
|
| 48 | + Only Java 1.8 and newer versions benefit from ScopeState tracking. |
| 49 | +
|
| 50 | + Args: |
| 51 | + version: Java version string (e.g., '1.8', '11.0', '21', '26.0') |
| 52 | +
|
| 53 | + Returns: |
| 54 | + True if the version should use ScopeState, False otherwise. |
| 55 | + """ |
| 56 | + # Ancient versions never use ScopeState |
| 57 | + if version in ANCIENT_JAVA_VERSIONS: |
| 58 | + return False |
| 59 | + |
| 60 | + try: |
| 61 | + # Handle "1.X" format (e.g., "1.5", "1.6", "1.7", "1.8") |
| 62 | + if version.startswith('1.'): |
| 63 | + minor = int(version[2:].split('.')[0]) |
| 64 | + return minor >= 8 # 1.8 and later |
| 65 | + else: |
| 66 | + # Handle "X" or "X.Y" format (e.g., "9", "11.0", "21") |
| 67 | + major = int(version.split('.')[0]) |
| 68 | + return major >= 9 # Java 9 and later (which is Java 1.9, so >= 1.8) |
| 69 | + except (ValueError, IndexError): |
| 70 | + # If we can't parse it, assume it's a modern version |
| 71 | + return True |
43 | 72 |
|
44 | 73 | # Glob patterns for use in finding where the JDK is. |
45 | 74 | # |
@@ -105,33 +134,18 @@ class OuterState: |
105 | 134 | interfaces, and anonymous inner classes.""" |
106 | 135 |
|
107 | 136 | def __init__(self, version=default_java_version) -> None: |
108 | | - if version not in ( |
109 | | - '1.1', |
110 | | - '1.2', |
111 | | - '1.3', |
112 | | - '1.4', |
113 | | - '1.5', |
114 | | - '1.6', |
115 | | - '1.7', |
116 | | - '1.8', |
117 | | - '5', |
118 | | - '6', |
119 | | - '9.0', |
120 | | - '10.0', |
121 | | - '11.0', |
122 | | - '12.0', |
123 | | - '13.0', |
124 | | - '14.0', |
125 | | - '15.0', |
126 | | - '16.0', |
127 | | - '17.0', |
128 | | - '18.0', |
129 | | - '19.0', |
130 | | - '20.0', |
131 | | - '21.0', |
132 | | - ): |
133 | | - msg = "Java version %s not supported" % version |
134 | | - raise NotImplementedError(msg) |
| 137 | + # Validate that this is a recognized Java version format. |
| 138 | + # We accept any reasonable version string; only ancient versions (1.1-1.4) |
| 139 | + # require special handling. Assume future Java versions are fine until |
| 140 | + # proven otherwise (this replaces earlier explicit lists of "good" versions). |
| 141 | + try: |
| 142 | + if version not in ANCIENT_JAVA_VERSIONS: |
| 143 | + # For modern versions, do basic validation of format |
| 144 | + parts = version.split('.') |
| 145 | + if not parts[0].isdigit(): |
| 146 | + raise ValueError(f"Invalid Java version format: {version}") |
| 147 | + except (AttributeError, ValueError): |
| 148 | + raise ValueError(f"Invalid Java version format: {version}") |
135 | 149 |
|
136 | 150 | self.version = version |
137 | 151 | self.listClasses = [] |
@@ -197,7 +211,7 @@ def closeBracket(self) -> None: |
197 | 211 | self.stackBrackets.pop() |
198 | 212 | if len(self.stackAnonClassBrackets) and \ |
199 | 213 | self.brackets == self.stackAnonClassBrackets[-1] and \ |
200 | | - self.version not in scopeStateVersions: |
| 214 | + not _version_uses_scope_state(self.version): |
201 | 215 | self._getAnonStack().pop() |
202 | 216 | self.stackAnonClassBrackets.pop() |
203 | 217 |
|
@@ -232,32 +246,16 @@ def parseToken(self, token): |
232 | 246 | return self |
233 | 247 |
|
234 | 248 | def addAnonClass(self) -> None: |
235 | | - """Add an anonymous inner class""" |
236 | | - if self.version in ('1.1', '1.2', '1.3', '1.4'): |
| 249 | + """Add an anonymous inner class. |
| 250 | +
|
| 251 | + Modern versions (1.5+) use scope-based parsing for more accurate handling. |
| 252 | + Ancient versions (1.1-1.4) use simple sequential numbering. |
| 253 | + """ |
| 254 | + if self.version in ANCIENT_JAVA_VERSIONS: |
| 255 | + # Ancient Java versions: simple sequential numbering |
237 | 256 | clazz = self.listClasses[0] |
238 | 257 | self.listOutputs.append('%s$%d' % (clazz, self.nextAnon)) |
239 | | - # TODO: shouldn't need to repeat versions here and in OuterState |
240 | | - elif self.version in ( |
241 | | - '1.5', |
242 | | - '1.6', |
243 | | - '1.7', |
244 | | - '1.8', |
245 | | - '5', |
246 | | - '6', |
247 | | - '9.0', |
248 | | - '10.0', |
249 | | - '11.0', |
250 | | - '12.0', |
251 | | - '13.0', |
252 | | - '14.0', |
253 | | - '15.0', |
254 | | - '16.0', |
255 | | - '17.0', |
256 | | - '18.0', |
257 | | - '19.0', |
258 | | - '20.0', |
259 | | - '21.0', |
260 | | - ): |
| 258 | + else: |
261 | 259 | self.stackAnonClassBrackets.append(self.brackets) |
262 | 260 | className = [] |
263 | 261 | className.extend(self.listClasses) |
@@ -376,7 +374,7 @@ def parseToken(self, token): |
376 | 374 | return self |
377 | 375 | if token == '{': |
378 | 376 | self.outer_state.addAnonClass() |
379 | | - if self.outer_state.version in scopeStateVersions: |
| 377 | + if _version_uses_scope_state(self.outer_state.version): |
380 | 378 | return ScopeState(old_state=self.old_state).parseToken(token) |
381 | 379 | return self.old_state.parseToken(token) |
382 | 380 |
|
|
0 commit comments