@tracecode/harness 0.6.6 → 0.7.0-beta7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (494) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +134 -15
  3. package/THIRD_PARTY_NOTICES.md +170 -0
  4. package/dist/browser.cjs +2361 -1033
  5. package/dist/browser.cjs.map +1 -1
  6. package/dist/browser.d.cts +33 -3
  7. package/dist/browser.d.ts +33 -3
  8. package/dist/browser.js +2357 -1033
  9. package/dist/browser.js.map +1 -1
  10. package/dist/cli.cjs +160 -23
  11. package/dist/cli.cjs.map +1 -1
  12. package/dist/cli.js +161 -24
  13. package/dist/cli.js.map +1 -1
  14. package/dist/core.cjs +748 -867
  15. package/dist/core.cjs.map +1 -1
  16. package/dist/core.d.cts +21 -85
  17. package/dist/core.d.ts +21 -85
  18. package/dist/core.js +734 -855
  19. package/dist/core.js.map +1 -1
  20. package/dist/cpp-worker-client-Bn7kC0_L.d.ts +84 -0
  21. package/dist/cpp-worker-client-BzdJLuZa.d.cts +84 -0
  22. package/dist/cpp.cjs +1063 -0
  23. package/dist/cpp.cjs.map +1 -0
  24. package/dist/cpp.d.cts +7 -0
  25. package/dist/cpp.d.ts +7 -0
  26. package/dist/cpp.js +1035 -0
  27. package/dist/cpp.js.map +1 -0
  28. package/dist/csharp-worker-client-DMHIa2YG.d.cts +69 -0
  29. package/dist/csharp-worker-client-JwqS6LiX.d.ts +69 -0
  30. package/dist/csharp.cjs +1012 -0
  31. package/dist/csharp.cjs.map +1 -0
  32. package/dist/csharp.d.cts +7 -0
  33. package/dist/csharp.d.ts +7 -0
  34. package/dist/csharp.js +984 -0
  35. package/dist/csharp.js.map +1 -0
  36. package/dist/index.cjs +3142 -1160
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +13 -5
  39. package/dist/index.d.ts +13 -5
  40. package/dist/index.js +3117 -1148
  41. package/dist/index.js.map +1 -1
  42. package/dist/internal/browser.cjs +1639 -30
  43. package/dist/internal/browser.cjs.map +1 -1
  44. package/dist/internal/browser.d.cts +6 -199
  45. package/dist/internal/browser.d.ts +6 -199
  46. package/dist/internal/browser.js +1636 -30
  47. package/dist/internal/browser.js.map +1 -1
  48. package/dist/java-worker-client-BOwKW-11.d.cts +72 -0
  49. package/dist/java-worker-client-C97DDnCp.d.ts +72 -0
  50. package/dist/java.cjs +1225 -0
  51. package/dist/java.cjs.map +1 -0
  52. package/dist/java.d.cts +7 -0
  53. package/dist/java.d.ts +7 -0
  54. package/dist/java.js +1197 -0
  55. package/dist/java.js.map +1 -0
  56. package/dist/javascript-worker-client-CYBGEEvc.d.cts +51 -0
  57. package/dist/javascript-worker-client-DIX1Mp21.d.ts +51 -0
  58. package/dist/javascript.cjs +1063 -19
  59. package/dist/javascript.cjs.map +1 -1
  60. package/dist/javascript.d.cts +7 -4
  61. package/dist/javascript.d.ts +7 -4
  62. package/dist/javascript.js +1061 -19
  63. package/dist/javascript.js.map +1 -1
  64. package/dist/pyodide-worker-client-C-2rfHj9.d.ts +111 -0
  65. package/dist/pyodide-worker-client-Cn0a8Uv3.d.cts +111 -0
  66. package/dist/python.cjs +1282 -74
  67. package/dist/python.cjs.map +1 -1
  68. package/dist/python.d.cts +20 -14
  69. package/dist/python.d.ts +20 -14
  70. package/dist/python.js +1279 -74
  71. package/dist/python.js.map +1 -1
  72. package/dist/runtime-language-info-BFUSti3-.d.ts +43 -0
  73. package/dist/runtime-language-info-Bxza1cI2.d.cts +43 -0
  74. package/dist/runtime-types-2qM0MukN.d.cts +244 -0
  75. package/dist/runtime-types-2qM0MukN.d.ts +244 -0
  76. package/package.json +73 -8
  77. package/workers/cpp/cpp-compiler-frame.html +82 -0
  78. package/workers/cpp/cpp-compiler-worker.js +131 -0
  79. package/workers/cpp/cpp-worker.js +5790 -0
  80. package/workers/cpp/tracecode_runtime.hpp +6147 -0
  81. package/workers/csharp/csharp-worker.js +301 -0
  82. package/workers/java/.build/classes/harness/browser/JavaRewriteLibrary.class +0 -0
  83. package/workers/java/java-source-augmentations.js +880 -0
  84. package/workers/java/java-worker.js +2149 -178
  85. package/workers/java/src/harness/browser/JavaRewriteLibrary.java +1645 -32
  86. package/workers/java/src/javafx/util/Pair.java +42 -0
  87. package/workers/java/src/tracecode/browser/BrowserCompileAndTraceLibrary.java +714 -0
  88. package/workers/java/src/tracecode/browser/BrowserCompileAndTraceMain.java +76 -0
  89. package/workers/java/src/tracecode/browser/RuntimeProbeMain.java +14 -0
  90. package/workers/java/src/tracecode/user/TraceHooks.java +1406 -0
  91. package/workers/javascript/javascript-libraries-entry.js +71 -0
  92. package/workers/javascript/javascript-worker.js +2054 -424
  93. package/workers/python/generated-python-harness-snippets.js +4 -4
  94. package/workers/python/pyodide-worker.js +222 -61
  95. package/workers/python/runtime-core.js +1387 -301
  96. package/workers/vendor/csharp/.stamp +0 -0
  97. package/workers/vendor/csharp/TraceCode.CSharpHost.runtimeconfig.json +32 -0
  98. package/workers/vendor/csharp/_framework/Microsoft.CSharp.wasm +0 -0
  99. package/workers/vendor/csharp/_framework/Microsoft.CodeAnalysis.CSharp.wasm +0 -0
  100. package/workers/vendor/csharp/_framework/Microsoft.CodeAnalysis.wasm +0 -0
  101. package/workers/vendor/csharp/_framework/Microsoft.VisualBasic.Core.wasm +0 -0
  102. package/workers/vendor/csharp/_framework/Microsoft.VisualBasic.wasm +0 -0
  103. package/workers/vendor/csharp/_framework/Microsoft.Win32.Primitives.wasm +0 -0
  104. package/workers/vendor/csharp/_framework/Microsoft.Win32.Registry.wasm +0 -0
  105. package/workers/vendor/csharp/_framework/System.AppContext.wasm +0 -0
  106. package/workers/vendor/csharp/_framework/System.Buffers.wasm +0 -0
  107. package/workers/vendor/csharp/_framework/System.Collections.Concurrent.wasm +0 -0
  108. package/workers/vendor/csharp/_framework/System.Collections.Immutable.wasm +0 -0
  109. package/workers/vendor/csharp/_framework/System.Collections.NonGeneric.wasm +0 -0
  110. package/workers/vendor/csharp/_framework/System.Collections.Specialized.wasm +0 -0
  111. package/workers/vendor/csharp/_framework/System.Collections.wasm +0 -0
  112. package/workers/vendor/csharp/_framework/System.ComponentModel.Annotations.wasm +0 -0
  113. package/workers/vendor/csharp/_framework/System.ComponentModel.DataAnnotations.wasm +0 -0
  114. package/workers/vendor/csharp/_framework/System.ComponentModel.EventBasedAsync.wasm +0 -0
  115. package/workers/vendor/csharp/_framework/System.ComponentModel.Primitives.wasm +0 -0
  116. package/workers/vendor/csharp/_framework/System.ComponentModel.TypeConverter.wasm +0 -0
  117. package/workers/vendor/csharp/_framework/System.ComponentModel.wasm +0 -0
  118. package/workers/vendor/csharp/_framework/System.Configuration.wasm +0 -0
  119. package/workers/vendor/csharp/_framework/System.Console.wasm +0 -0
  120. package/workers/vendor/csharp/_framework/System.Core.wasm +0 -0
  121. package/workers/vendor/csharp/_framework/System.Data.Common.wasm +0 -0
  122. package/workers/vendor/csharp/_framework/System.Data.DataSetExtensions.wasm +0 -0
  123. package/workers/vendor/csharp/_framework/System.Data.wasm +0 -0
  124. package/workers/vendor/csharp/_framework/System.Diagnostics.Contracts.wasm +0 -0
  125. package/workers/vendor/csharp/_framework/System.Diagnostics.Debug.wasm +0 -0
  126. package/workers/vendor/csharp/_framework/System.Diagnostics.DiagnosticSource.wasm +0 -0
  127. package/workers/vendor/csharp/_framework/System.Diagnostics.FileVersionInfo.wasm +0 -0
  128. package/workers/vendor/csharp/_framework/System.Diagnostics.Process.wasm +0 -0
  129. package/workers/vendor/csharp/_framework/System.Diagnostics.StackTrace.wasm +0 -0
  130. package/workers/vendor/csharp/_framework/System.Diagnostics.TextWriterTraceListener.wasm +0 -0
  131. package/workers/vendor/csharp/_framework/System.Diagnostics.Tools.wasm +0 -0
  132. package/workers/vendor/csharp/_framework/System.Diagnostics.TraceSource.wasm +0 -0
  133. package/workers/vendor/csharp/_framework/System.Diagnostics.Tracing.wasm +0 -0
  134. package/workers/vendor/csharp/_framework/System.Drawing.Primitives.wasm +0 -0
  135. package/workers/vendor/csharp/_framework/System.Drawing.wasm +0 -0
  136. package/workers/vendor/csharp/_framework/System.Dynamic.Runtime.wasm +0 -0
  137. package/workers/vendor/csharp/_framework/System.Formats.Asn1.wasm +0 -0
  138. package/workers/vendor/csharp/_framework/System.Formats.Tar.wasm +0 -0
  139. package/workers/vendor/csharp/_framework/System.Globalization.Calendars.wasm +0 -0
  140. package/workers/vendor/csharp/_framework/System.Globalization.Extensions.wasm +0 -0
  141. package/workers/vendor/csharp/_framework/System.Globalization.wasm +0 -0
  142. package/workers/vendor/csharp/_framework/System.IO.Compression.Brotli.wasm +0 -0
  143. package/workers/vendor/csharp/_framework/System.IO.Compression.FileSystem.wasm +0 -0
  144. package/workers/vendor/csharp/_framework/System.IO.Compression.ZipFile.wasm +0 -0
  145. package/workers/vendor/csharp/_framework/System.IO.Compression.wasm +0 -0
  146. package/workers/vendor/csharp/_framework/System.IO.FileSystem.AccessControl.wasm +0 -0
  147. package/workers/vendor/csharp/_framework/System.IO.FileSystem.DriveInfo.wasm +0 -0
  148. package/workers/vendor/csharp/_framework/System.IO.FileSystem.Primitives.wasm +0 -0
  149. package/workers/vendor/csharp/_framework/System.IO.FileSystem.Watcher.wasm +0 -0
  150. package/workers/vendor/csharp/_framework/System.IO.FileSystem.wasm +0 -0
  151. package/workers/vendor/csharp/_framework/System.IO.IsolatedStorage.wasm +0 -0
  152. package/workers/vendor/csharp/_framework/System.IO.MemoryMappedFiles.wasm +0 -0
  153. package/workers/vendor/csharp/_framework/System.IO.Pipelines.wasm +0 -0
  154. package/workers/vendor/csharp/_framework/System.IO.Pipes.AccessControl.wasm +0 -0
  155. package/workers/vendor/csharp/_framework/System.IO.Pipes.wasm +0 -0
  156. package/workers/vendor/csharp/_framework/System.IO.UnmanagedMemoryStream.wasm +0 -0
  157. package/workers/vendor/csharp/_framework/System.IO.wasm +0 -0
  158. package/workers/vendor/csharp/_framework/System.Linq.AsyncEnumerable.wasm +0 -0
  159. package/workers/vendor/csharp/_framework/System.Linq.Expressions.wasm +0 -0
  160. package/workers/vendor/csharp/_framework/System.Linq.Parallel.wasm +0 -0
  161. package/workers/vendor/csharp/_framework/System.Linq.Queryable.wasm +0 -0
  162. package/workers/vendor/csharp/_framework/System.Linq.wasm +0 -0
  163. package/workers/vendor/csharp/_framework/System.Memory.wasm +0 -0
  164. package/workers/vendor/csharp/_framework/System.Net.Http.Json.wasm +0 -0
  165. package/workers/vendor/csharp/_framework/System.Net.Http.wasm +0 -0
  166. package/workers/vendor/csharp/_framework/System.Net.HttpListener.wasm +0 -0
  167. package/workers/vendor/csharp/_framework/System.Net.Mail.wasm +0 -0
  168. package/workers/vendor/csharp/_framework/System.Net.NameResolution.wasm +0 -0
  169. package/workers/vendor/csharp/_framework/System.Net.NetworkInformation.wasm +0 -0
  170. package/workers/vendor/csharp/_framework/System.Net.Ping.wasm +0 -0
  171. package/workers/vendor/csharp/_framework/System.Net.Primitives.wasm +0 -0
  172. package/workers/vendor/csharp/_framework/System.Net.Quic.wasm +0 -0
  173. package/workers/vendor/csharp/_framework/System.Net.Requests.wasm +0 -0
  174. package/workers/vendor/csharp/_framework/System.Net.Security.wasm +0 -0
  175. package/workers/vendor/csharp/_framework/System.Net.ServerSentEvents.wasm +0 -0
  176. package/workers/vendor/csharp/_framework/System.Net.ServicePoint.wasm +0 -0
  177. package/workers/vendor/csharp/_framework/System.Net.Sockets.wasm +0 -0
  178. package/workers/vendor/csharp/_framework/System.Net.WebClient.wasm +0 -0
  179. package/workers/vendor/csharp/_framework/System.Net.WebHeaderCollection.wasm +0 -0
  180. package/workers/vendor/csharp/_framework/System.Net.WebProxy.wasm +0 -0
  181. package/workers/vendor/csharp/_framework/System.Net.WebSockets.Client.wasm +0 -0
  182. package/workers/vendor/csharp/_framework/System.Net.WebSockets.wasm +0 -0
  183. package/workers/vendor/csharp/_framework/System.Net.wasm +0 -0
  184. package/workers/vendor/csharp/_framework/System.Numerics.Vectors.wasm +0 -0
  185. package/workers/vendor/csharp/_framework/System.Numerics.wasm +0 -0
  186. package/workers/vendor/csharp/_framework/System.ObjectModel.wasm +0 -0
  187. package/workers/vendor/csharp/_framework/System.Private.CoreLib.wasm +0 -0
  188. package/workers/vendor/csharp/_framework/System.Private.DataContractSerialization.wasm +0 -0
  189. package/workers/vendor/csharp/_framework/System.Private.Uri.wasm +0 -0
  190. package/workers/vendor/csharp/_framework/System.Private.Xml.Linq.wasm +0 -0
  191. package/workers/vendor/csharp/_framework/System.Private.Xml.wasm +0 -0
  192. package/workers/vendor/csharp/_framework/System.Reflection.DispatchProxy.wasm +0 -0
  193. package/workers/vendor/csharp/_framework/System.Reflection.Emit.ILGeneration.wasm +0 -0
  194. package/workers/vendor/csharp/_framework/System.Reflection.Emit.Lightweight.wasm +0 -0
  195. package/workers/vendor/csharp/_framework/System.Reflection.Emit.wasm +0 -0
  196. package/workers/vendor/csharp/_framework/System.Reflection.Extensions.wasm +0 -0
  197. package/workers/vendor/csharp/_framework/System.Reflection.Metadata.wasm +0 -0
  198. package/workers/vendor/csharp/_framework/System.Reflection.Primitives.wasm +0 -0
  199. package/workers/vendor/csharp/_framework/System.Reflection.TypeExtensions.wasm +0 -0
  200. package/workers/vendor/csharp/_framework/System.Reflection.wasm +0 -0
  201. package/workers/vendor/csharp/_framework/System.Resources.Reader.wasm +0 -0
  202. package/workers/vendor/csharp/_framework/System.Resources.ResourceManager.wasm +0 -0
  203. package/workers/vendor/csharp/_framework/System.Resources.Writer.wasm +0 -0
  204. package/workers/vendor/csharp/_framework/System.Runtime.CompilerServices.Unsafe.wasm +0 -0
  205. package/workers/vendor/csharp/_framework/System.Runtime.CompilerServices.VisualC.wasm +0 -0
  206. package/workers/vendor/csharp/_framework/System.Runtime.Extensions.wasm +0 -0
  207. package/workers/vendor/csharp/_framework/System.Runtime.Handles.wasm +0 -0
  208. package/workers/vendor/csharp/_framework/System.Runtime.InteropServices.JavaScript.wasm +0 -0
  209. package/workers/vendor/csharp/_framework/System.Runtime.InteropServices.RuntimeInformation.wasm +0 -0
  210. package/workers/vendor/csharp/_framework/System.Runtime.InteropServices.wasm +0 -0
  211. package/workers/vendor/csharp/_framework/System.Runtime.Intrinsics.wasm +0 -0
  212. package/workers/vendor/csharp/_framework/System.Runtime.Loader.wasm +0 -0
  213. package/workers/vendor/csharp/_framework/System.Runtime.Numerics.wasm +0 -0
  214. package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Formatters.wasm +0 -0
  215. package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Json.wasm +0 -0
  216. package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Primitives.wasm +0 -0
  217. package/workers/vendor/csharp/_framework/System.Runtime.Serialization.Xml.wasm +0 -0
  218. package/workers/vendor/csharp/_framework/System.Runtime.Serialization.wasm +0 -0
  219. package/workers/vendor/csharp/_framework/System.Runtime.wasm +0 -0
  220. package/workers/vendor/csharp/_framework/System.Security.AccessControl.wasm +0 -0
  221. package/workers/vendor/csharp/_framework/System.Security.Claims.wasm +0 -0
  222. package/workers/vendor/csharp/_framework/System.Security.Cryptography.Algorithms.wasm +0 -0
  223. package/workers/vendor/csharp/_framework/System.Security.Cryptography.Cng.wasm +0 -0
  224. package/workers/vendor/csharp/_framework/System.Security.Cryptography.Csp.wasm +0 -0
  225. package/workers/vendor/csharp/_framework/System.Security.Cryptography.Encoding.wasm +0 -0
  226. package/workers/vendor/csharp/_framework/System.Security.Cryptography.OpenSsl.wasm +0 -0
  227. package/workers/vendor/csharp/_framework/System.Security.Cryptography.Primitives.wasm +0 -0
  228. package/workers/vendor/csharp/_framework/System.Security.Cryptography.X509Certificates.wasm +0 -0
  229. package/workers/vendor/csharp/_framework/System.Security.Cryptography.wasm +0 -0
  230. package/workers/vendor/csharp/_framework/System.Security.Principal.Windows.wasm +0 -0
  231. package/workers/vendor/csharp/_framework/System.Security.Principal.wasm +0 -0
  232. package/workers/vendor/csharp/_framework/System.Security.SecureString.wasm +0 -0
  233. package/workers/vendor/csharp/_framework/System.Security.wasm +0 -0
  234. package/workers/vendor/csharp/_framework/System.ServiceModel.Web.wasm +0 -0
  235. package/workers/vendor/csharp/_framework/System.ServiceProcess.wasm +0 -0
  236. package/workers/vendor/csharp/_framework/System.Text.Encoding.CodePages.wasm +0 -0
  237. package/workers/vendor/csharp/_framework/System.Text.Encoding.Extensions.wasm +0 -0
  238. package/workers/vendor/csharp/_framework/System.Text.Encoding.wasm +0 -0
  239. package/workers/vendor/csharp/_framework/System.Text.Encodings.Web.wasm +0 -0
  240. package/workers/vendor/csharp/_framework/System.Text.Json.wasm +0 -0
  241. package/workers/vendor/csharp/_framework/System.Text.RegularExpressions.wasm +0 -0
  242. package/workers/vendor/csharp/_framework/System.Threading.AccessControl.wasm +0 -0
  243. package/workers/vendor/csharp/_framework/System.Threading.Channels.wasm +0 -0
  244. package/workers/vendor/csharp/_framework/System.Threading.Overlapped.wasm +0 -0
  245. package/workers/vendor/csharp/_framework/System.Threading.Tasks.Dataflow.wasm +0 -0
  246. package/workers/vendor/csharp/_framework/System.Threading.Tasks.Extensions.wasm +0 -0
  247. package/workers/vendor/csharp/_framework/System.Threading.Tasks.Parallel.wasm +0 -0
  248. package/workers/vendor/csharp/_framework/System.Threading.Tasks.wasm +0 -0
  249. package/workers/vendor/csharp/_framework/System.Threading.Thread.wasm +0 -0
  250. package/workers/vendor/csharp/_framework/System.Threading.ThreadPool.wasm +0 -0
  251. package/workers/vendor/csharp/_framework/System.Threading.Timer.wasm +0 -0
  252. package/workers/vendor/csharp/_framework/System.Threading.wasm +0 -0
  253. package/workers/vendor/csharp/_framework/System.Transactions.Local.wasm +0 -0
  254. package/workers/vendor/csharp/_framework/System.Transactions.wasm +0 -0
  255. package/workers/vendor/csharp/_framework/System.ValueTuple.wasm +0 -0
  256. package/workers/vendor/csharp/_framework/System.Web.HttpUtility.wasm +0 -0
  257. package/workers/vendor/csharp/_framework/System.Web.wasm +0 -0
  258. package/workers/vendor/csharp/_framework/System.Windows.wasm +0 -0
  259. package/workers/vendor/csharp/_framework/System.Xml.Linq.wasm +0 -0
  260. package/workers/vendor/csharp/_framework/System.Xml.ReaderWriter.wasm +0 -0
  261. package/workers/vendor/csharp/_framework/System.Xml.Serialization.wasm +0 -0
  262. package/workers/vendor/csharp/_framework/System.Xml.XDocument.wasm +0 -0
  263. package/workers/vendor/csharp/_framework/System.Xml.XPath.XDocument.wasm +0 -0
  264. package/workers/vendor/csharp/_framework/System.Xml.XPath.wasm +0 -0
  265. package/workers/vendor/csharp/_framework/System.Xml.XmlDocument.wasm +0 -0
  266. package/workers/vendor/csharp/_framework/System.Xml.XmlSerializer.wasm +0 -0
  267. package/workers/vendor/csharp/_framework/System.Xml.wasm +0 -0
  268. package/workers/vendor/csharp/_framework/System.wasm +0 -0
  269. package/workers/vendor/csharp/_framework/TraceCode.CSharpHost.wasm +0 -0
  270. package/workers/vendor/csharp/_framework/WindowsBase.wasm +0 -0
  271. package/workers/vendor/csharp/_framework/cs/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  272. package/workers/vendor/csharp/_framework/cs/Microsoft.CodeAnalysis.resources.wasm +0 -0
  273. package/workers/vendor/csharp/_framework/de/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  274. package/workers/vendor/csharp/_framework/de/Microsoft.CodeAnalysis.resources.wasm +0 -0
  275. package/workers/vendor/csharp/_framework/dotnet.boot.js +1958 -0
  276. package/workers/vendor/csharp/_framework/dotnet.js +4 -0
  277. package/workers/vendor/csharp/_framework/dotnet.js.map +1 -0
  278. package/workers/vendor/csharp/_framework/dotnet.native.js +6687 -0
  279. package/workers/vendor/csharp/_framework/dotnet.native.wasm +0 -0
  280. package/workers/vendor/csharp/_framework/dotnet.runtime.js +4 -0
  281. package/workers/vendor/csharp/_framework/dotnet.runtime.js.map +1 -0
  282. package/workers/vendor/csharp/_framework/es/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  283. package/workers/vendor/csharp/_framework/es/Microsoft.CodeAnalysis.resources.wasm +0 -0
  284. package/workers/vendor/csharp/_framework/fr/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  285. package/workers/vendor/csharp/_framework/fr/Microsoft.CodeAnalysis.resources.wasm +0 -0
  286. package/workers/vendor/csharp/_framework/it/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  287. package/workers/vendor/csharp/_framework/it/Microsoft.CodeAnalysis.resources.wasm +0 -0
  288. package/workers/vendor/csharp/_framework/ja/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  289. package/workers/vendor/csharp/_framework/ja/Microsoft.CodeAnalysis.resources.wasm +0 -0
  290. package/workers/vendor/csharp/_framework/ko/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  291. package/workers/vendor/csharp/_framework/ko/Microsoft.CodeAnalysis.resources.wasm +0 -0
  292. package/workers/vendor/csharp/_framework/mscorlib.wasm +0 -0
  293. package/workers/vendor/csharp/_framework/netstandard.wasm +0 -0
  294. package/workers/vendor/csharp/_framework/pl/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  295. package/workers/vendor/csharp/_framework/pl/Microsoft.CodeAnalysis.resources.wasm +0 -0
  296. package/workers/vendor/csharp/_framework/pt-BR/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  297. package/workers/vendor/csharp/_framework/pt-BR/Microsoft.CodeAnalysis.resources.wasm +0 -0
  298. package/workers/vendor/csharp/_framework/ru/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  299. package/workers/vendor/csharp/_framework/ru/Microsoft.CodeAnalysis.resources.wasm +0 -0
  300. package/workers/vendor/csharp/_framework/supportFiles/0_Microsoft.CodeAnalysis.CSharp.dll +0 -0
  301. package/workers/vendor/csharp/_framework/supportFiles/100_System.Reflection.Emit.ILGeneration.dll +0 -0
  302. package/workers/vendor/csharp/_framework/supportFiles/101_System.Reflection.Emit.Lightweight.dll +0 -0
  303. package/workers/vendor/csharp/_framework/supportFiles/102_System.Reflection.Extensions.dll +0 -0
  304. package/workers/vendor/csharp/_framework/supportFiles/103_System.Reflection.Metadata.dll +0 -0
  305. package/workers/vendor/csharp/_framework/supportFiles/104_System.Reflection.Primitives.dll +0 -0
  306. package/workers/vendor/csharp/_framework/supportFiles/105_System.Reflection.TypeExtensions.dll +0 -0
  307. package/workers/vendor/csharp/_framework/supportFiles/106_System.Resources.Reader.dll +0 -0
  308. package/workers/vendor/csharp/_framework/supportFiles/107_System.Resources.ResourceManager.dll +0 -0
  309. package/workers/vendor/csharp/_framework/supportFiles/108_System.Resources.Writer.dll +0 -0
  310. package/workers/vendor/csharp/_framework/supportFiles/109_System.Runtime.CompilerServices.Unsafe.dll +0 -0
  311. package/workers/vendor/csharp/_framework/supportFiles/10_System.Buffers.dll +0 -0
  312. package/workers/vendor/csharp/_framework/supportFiles/110_System.Runtime.CompilerServices.VisualC.dll +0 -0
  313. package/workers/vendor/csharp/_framework/supportFiles/111_System.Runtime.dll +0 -0
  314. package/workers/vendor/csharp/_framework/supportFiles/112_System.Runtime.Extensions.dll +0 -0
  315. package/workers/vendor/csharp/_framework/supportFiles/113_System.Runtime.Handles.dll +0 -0
  316. package/workers/vendor/csharp/_framework/supportFiles/114_System.Runtime.InteropServices.dll +0 -0
  317. package/workers/vendor/csharp/_framework/supportFiles/115_System.Runtime.InteropServices.JavaScript.dll +0 -0
  318. package/workers/vendor/csharp/_framework/supportFiles/116_System.Runtime.InteropServices.RuntimeInformation.dll +0 -0
  319. package/workers/vendor/csharp/_framework/supportFiles/117_System.Runtime.Intrinsics.dll +0 -0
  320. package/workers/vendor/csharp/_framework/supportFiles/118_System.Runtime.Loader.dll +0 -0
  321. package/workers/vendor/csharp/_framework/supportFiles/119_System.Runtime.Numerics.dll +0 -0
  322. package/workers/vendor/csharp/_framework/supportFiles/11_System.Collections.Concurrent.dll +0 -0
  323. package/workers/vendor/csharp/_framework/supportFiles/120_System.Runtime.Serialization.dll +0 -0
  324. package/workers/vendor/csharp/_framework/supportFiles/121_System.Runtime.Serialization.Formatters.dll +0 -0
  325. package/workers/vendor/csharp/_framework/supportFiles/122_System.Runtime.Serialization.Json.dll +0 -0
  326. package/workers/vendor/csharp/_framework/supportFiles/123_System.Runtime.Serialization.Primitives.dll +0 -0
  327. package/workers/vendor/csharp/_framework/supportFiles/124_System.Runtime.Serialization.Xml.dll +0 -0
  328. package/workers/vendor/csharp/_framework/supportFiles/125_System.Security.AccessControl.dll +0 -0
  329. package/workers/vendor/csharp/_framework/supportFiles/126_System.Security.Claims.dll +0 -0
  330. package/workers/vendor/csharp/_framework/supportFiles/127_System.Security.Cryptography.Algorithms.dll +0 -0
  331. package/workers/vendor/csharp/_framework/supportFiles/128_System.Security.Cryptography.Cng.dll +0 -0
  332. package/workers/vendor/csharp/_framework/supportFiles/129_System.Security.Cryptography.Csp.dll +0 -0
  333. package/workers/vendor/csharp/_framework/supportFiles/12_System.Collections.dll +0 -0
  334. package/workers/vendor/csharp/_framework/supportFiles/130_System.Security.Cryptography.dll +0 -0
  335. package/workers/vendor/csharp/_framework/supportFiles/131_System.Security.Cryptography.Encoding.dll +0 -0
  336. package/workers/vendor/csharp/_framework/supportFiles/132_System.Security.Cryptography.OpenSsl.dll +0 -0
  337. package/workers/vendor/csharp/_framework/supportFiles/133_System.Security.Cryptography.Primitives.dll +0 -0
  338. package/workers/vendor/csharp/_framework/supportFiles/134_System.Security.Cryptography.X509Certificates.dll +0 -0
  339. package/workers/vendor/csharp/_framework/supportFiles/135_System.Security.dll +0 -0
  340. package/workers/vendor/csharp/_framework/supportFiles/136_System.Security.Principal.dll +0 -0
  341. package/workers/vendor/csharp/_framework/supportFiles/137_System.Security.Principal.Windows.dll +0 -0
  342. package/workers/vendor/csharp/_framework/supportFiles/138_System.Security.SecureString.dll +0 -0
  343. package/workers/vendor/csharp/_framework/supportFiles/139_System.ServiceModel.Web.dll +0 -0
  344. package/workers/vendor/csharp/_framework/supportFiles/13_System.Collections.Immutable.dll +0 -0
  345. package/workers/vendor/csharp/_framework/supportFiles/140_System.ServiceProcess.dll +0 -0
  346. package/workers/vendor/csharp/_framework/supportFiles/141_System.Text.Encoding.CodePages.dll +0 -0
  347. package/workers/vendor/csharp/_framework/supportFiles/142_System.Text.Encoding.dll +0 -0
  348. package/workers/vendor/csharp/_framework/supportFiles/143_System.Text.Encoding.Extensions.dll +0 -0
  349. package/workers/vendor/csharp/_framework/supportFiles/144_System.Text.Encodings.Web.dll +0 -0
  350. package/workers/vendor/csharp/_framework/supportFiles/145_System.Text.Json.dll +0 -0
  351. package/workers/vendor/csharp/_framework/supportFiles/146_System.Text.RegularExpressions.dll +0 -0
  352. package/workers/vendor/csharp/_framework/supportFiles/147_System.Threading.AccessControl.dll +0 -0
  353. package/workers/vendor/csharp/_framework/supportFiles/148_System.Threading.Channels.dll +0 -0
  354. package/workers/vendor/csharp/_framework/supportFiles/149_System.Threading.dll +0 -0
  355. package/workers/vendor/csharp/_framework/supportFiles/14_System.Collections.NonGeneric.dll +0 -0
  356. package/workers/vendor/csharp/_framework/supportFiles/150_System.Threading.Overlapped.dll +0 -0
  357. package/workers/vendor/csharp/_framework/supportFiles/151_System.Threading.Tasks.Dataflow.dll +0 -0
  358. package/workers/vendor/csharp/_framework/supportFiles/152_System.Threading.Tasks.dll +0 -0
  359. package/workers/vendor/csharp/_framework/supportFiles/153_System.Threading.Tasks.Extensions.dll +0 -0
  360. package/workers/vendor/csharp/_framework/supportFiles/154_System.Threading.Tasks.Parallel.dll +0 -0
  361. package/workers/vendor/csharp/_framework/supportFiles/155_System.Threading.Thread.dll +0 -0
  362. package/workers/vendor/csharp/_framework/supportFiles/156_System.Threading.ThreadPool.dll +0 -0
  363. package/workers/vendor/csharp/_framework/supportFiles/157_System.Threading.Timer.dll +0 -0
  364. package/workers/vendor/csharp/_framework/supportFiles/158_System.Transactions.dll +0 -0
  365. package/workers/vendor/csharp/_framework/supportFiles/159_System.Transactions.Local.dll +0 -0
  366. package/workers/vendor/csharp/_framework/supportFiles/15_System.Collections.Specialized.dll +0 -0
  367. package/workers/vendor/csharp/_framework/supportFiles/160_System.ValueTuple.dll +0 -0
  368. package/workers/vendor/csharp/_framework/supportFiles/161_System.Web.dll +0 -0
  369. package/workers/vendor/csharp/_framework/supportFiles/162_System.Web.HttpUtility.dll +0 -0
  370. package/workers/vendor/csharp/_framework/supportFiles/163_System.Windows.dll +0 -0
  371. package/workers/vendor/csharp/_framework/supportFiles/164_System.Xml.dll +0 -0
  372. package/workers/vendor/csharp/_framework/supportFiles/165_System.Xml.Linq.dll +0 -0
  373. package/workers/vendor/csharp/_framework/supportFiles/166_System.Xml.ReaderWriter.dll +0 -0
  374. package/workers/vendor/csharp/_framework/supportFiles/167_System.Xml.Serialization.dll +0 -0
  375. package/workers/vendor/csharp/_framework/supportFiles/168_System.Xml.XDocument.dll +0 -0
  376. package/workers/vendor/csharp/_framework/supportFiles/169_System.Xml.XmlDocument.dll +0 -0
  377. package/workers/vendor/csharp/_framework/supportFiles/16_System.ComponentModel.Annotations.dll +0 -0
  378. package/workers/vendor/csharp/_framework/supportFiles/170_System.Xml.XmlSerializer.dll +0 -0
  379. package/workers/vendor/csharp/_framework/supportFiles/171_System.Xml.XPath.dll +0 -0
  380. package/workers/vendor/csharp/_framework/supportFiles/172_System.Xml.XPath.XDocument.dll +0 -0
  381. package/workers/vendor/csharp/_framework/supportFiles/173_TraceCode.CSharpHost.dll +0 -0
  382. package/workers/vendor/csharp/_framework/supportFiles/174_WindowsBase.dll +0 -0
  383. package/workers/vendor/csharp/_framework/supportFiles/17_System.ComponentModel.DataAnnotations.dll +0 -0
  384. package/workers/vendor/csharp/_framework/supportFiles/18_System.ComponentModel.dll +0 -0
  385. package/workers/vendor/csharp/_framework/supportFiles/19_System.ComponentModel.EventBasedAsync.dll +0 -0
  386. package/workers/vendor/csharp/_framework/supportFiles/1_Microsoft.CodeAnalysis.dll +0 -0
  387. package/workers/vendor/csharp/_framework/supportFiles/20_System.ComponentModel.Primitives.dll +0 -0
  388. package/workers/vendor/csharp/_framework/supportFiles/21_System.ComponentModel.TypeConverter.dll +0 -0
  389. package/workers/vendor/csharp/_framework/supportFiles/22_System.Configuration.dll +0 -0
  390. package/workers/vendor/csharp/_framework/supportFiles/23_System.Console.dll +0 -0
  391. package/workers/vendor/csharp/_framework/supportFiles/24_System.Core.dll +0 -0
  392. package/workers/vendor/csharp/_framework/supportFiles/25_System.Data.Common.dll +0 -0
  393. package/workers/vendor/csharp/_framework/supportFiles/26_System.Data.DataSetExtensions.dll +0 -0
  394. package/workers/vendor/csharp/_framework/supportFiles/27_System.Data.dll +0 -0
  395. package/workers/vendor/csharp/_framework/supportFiles/28_System.Diagnostics.Contracts.dll +0 -0
  396. package/workers/vendor/csharp/_framework/supportFiles/29_System.Diagnostics.Debug.dll +0 -0
  397. package/workers/vendor/csharp/_framework/supportFiles/2_Microsoft.CSharp.dll +0 -0
  398. package/workers/vendor/csharp/_framework/supportFiles/30_System.Diagnostics.DiagnosticSource.dll +0 -0
  399. package/workers/vendor/csharp/_framework/supportFiles/31_System.Diagnostics.FileVersionInfo.dll +0 -0
  400. package/workers/vendor/csharp/_framework/supportFiles/32_System.Diagnostics.Process.dll +0 -0
  401. package/workers/vendor/csharp/_framework/supportFiles/33_System.Diagnostics.StackTrace.dll +0 -0
  402. package/workers/vendor/csharp/_framework/supportFiles/34_System.Diagnostics.TextWriterTraceListener.dll +0 -0
  403. package/workers/vendor/csharp/_framework/supportFiles/35_System.Diagnostics.Tools.dll +0 -0
  404. package/workers/vendor/csharp/_framework/supportFiles/36_System.Diagnostics.TraceSource.dll +0 -0
  405. package/workers/vendor/csharp/_framework/supportFiles/37_System.Diagnostics.Tracing.dll +0 -0
  406. package/workers/vendor/csharp/_framework/supportFiles/38_System.dll +0 -0
  407. package/workers/vendor/csharp/_framework/supportFiles/39_System.Drawing.dll +0 -0
  408. package/workers/vendor/csharp/_framework/supportFiles/3_Microsoft.VisualBasic.Core.dll +0 -0
  409. package/workers/vendor/csharp/_framework/supportFiles/40_System.Drawing.Primitives.dll +0 -0
  410. package/workers/vendor/csharp/_framework/supportFiles/41_System.Dynamic.Runtime.dll +0 -0
  411. package/workers/vendor/csharp/_framework/supportFiles/42_System.Formats.Asn1.dll +0 -0
  412. package/workers/vendor/csharp/_framework/supportFiles/43_System.Formats.Tar.dll +0 -0
  413. package/workers/vendor/csharp/_framework/supportFiles/44_System.Globalization.Calendars.dll +0 -0
  414. package/workers/vendor/csharp/_framework/supportFiles/45_System.Globalization.dll +0 -0
  415. package/workers/vendor/csharp/_framework/supportFiles/46_System.Globalization.Extensions.dll +0 -0
  416. package/workers/vendor/csharp/_framework/supportFiles/47_System.IO.Compression.Brotli.dll +0 -0
  417. package/workers/vendor/csharp/_framework/supportFiles/48_System.IO.Compression.dll +0 -0
  418. package/workers/vendor/csharp/_framework/supportFiles/49_System.IO.Compression.FileSystem.dll +0 -0
  419. package/workers/vendor/csharp/_framework/supportFiles/4_Microsoft.VisualBasic.dll +0 -0
  420. package/workers/vendor/csharp/_framework/supportFiles/50_System.IO.Compression.ZipFile.dll +0 -0
  421. package/workers/vendor/csharp/_framework/supportFiles/51_System.IO.dll +0 -0
  422. package/workers/vendor/csharp/_framework/supportFiles/52_System.IO.FileSystem.AccessControl.dll +0 -0
  423. package/workers/vendor/csharp/_framework/supportFiles/53_System.IO.FileSystem.dll +0 -0
  424. package/workers/vendor/csharp/_framework/supportFiles/54_System.IO.FileSystem.DriveInfo.dll +0 -0
  425. package/workers/vendor/csharp/_framework/supportFiles/55_System.IO.FileSystem.Primitives.dll +0 -0
  426. package/workers/vendor/csharp/_framework/supportFiles/56_System.IO.FileSystem.Watcher.dll +0 -0
  427. package/workers/vendor/csharp/_framework/supportFiles/57_System.IO.IsolatedStorage.dll +0 -0
  428. package/workers/vendor/csharp/_framework/supportFiles/58_System.IO.MemoryMappedFiles.dll +0 -0
  429. package/workers/vendor/csharp/_framework/supportFiles/59_System.IO.Pipelines.dll +0 -0
  430. package/workers/vendor/csharp/_framework/supportFiles/5_Microsoft.Win32.Primitives.dll +0 -0
  431. package/workers/vendor/csharp/_framework/supportFiles/60_System.IO.Pipes.AccessControl.dll +0 -0
  432. package/workers/vendor/csharp/_framework/supportFiles/61_System.IO.Pipes.dll +0 -0
  433. package/workers/vendor/csharp/_framework/supportFiles/62_System.IO.UnmanagedMemoryStream.dll +0 -0
  434. package/workers/vendor/csharp/_framework/supportFiles/63_System.Linq.AsyncEnumerable.dll +0 -0
  435. package/workers/vendor/csharp/_framework/supportFiles/64_System.Linq.dll +0 -0
  436. package/workers/vendor/csharp/_framework/supportFiles/65_System.Linq.Expressions.dll +0 -0
  437. package/workers/vendor/csharp/_framework/supportFiles/66_System.Linq.Parallel.dll +0 -0
  438. package/workers/vendor/csharp/_framework/supportFiles/67_System.Linq.Queryable.dll +0 -0
  439. package/workers/vendor/csharp/_framework/supportFiles/68_System.Memory.dll +0 -0
  440. package/workers/vendor/csharp/_framework/supportFiles/69_System.Net.dll +0 -0
  441. package/workers/vendor/csharp/_framework/supportFiles/6_Microsoft.Win32.Registry.dll +0 -0
  442. package/workers/vendor/csharp/_framework/supportFiles/70_System.Net.Http.dll +0 -0
  443. package/workers/vendor/csharp/_framework/supportFiles/71_System.Net.Http.Json.dll +0 -0
  444. package/workers/vendor/csharp/_framework/supportFiles/72_System.Net.HttpListener.dll +0 -0
  445. package/workers/vendor/csharp/_framework/supportFiles/73_System.Net.Mail.dll +0 -0
  446. package/workers/vendor/csharp/_framework/supportFiles/74_System.Net.NameResolution.dll +0 -0
  447. package/workers/vendor/csharp/_framework/supportFiles/75_System.Net.NetworkInformation.dll +0 -0
  448. package/workers/vendor/csharp/_framework/supportFiles/76_System.Net.Ping.dll +0 -0
  449. package/workers/vendor/csharp/_framework/supportFiles/77_System.Net.Primitives.dll +0 -0
  450. package/workers/vendor/csharp/_framework/supportFiles/78_System.Net.Quic.dll +0 -0
  451. package/workers/vendor/csharp/_framework/supportFiles/79_System.Net.Requests.dll +0 -0
  452. package/workers/vendor/csharp/_framework/supportFiles/7_mscorlib.dll +0 -0
  453. package/workers/vendor/csharp/_framework/supportFiles/80_System.Net.Security.dll +0 -0
  454. package/workers/vendor/csharp/_framework/supportFiles/81_System.Net.ServerSentEvents.dll +0 -0
  455. package/workers/vendor/csharp/_framework/supportFiles/82_System.Net.ServicePoint.dll +0 -0
  456. package/workers/vendor/csharp/_framework/supportFiles/83_System.Net.Sockets.dll +0 -0
  457. package/workers/vendor/csharp/_framework/supportFiles/84_System.Net.WebClient.dll +0 -0
  458. package/workers/vendor/csharp/_framework/supportFiles/85_System.Net.WebHeaderCollection.dll +0 -0
  459. package/workers/vendor/csharp/_framework/supportFiles/86_System.Net.WebProxy.dll +0 -0
  460. package/workers/vendor/csharp/_framework/supportFiles/87_System.Net.WebSockets.Client.dll +0 -0
  461. package/workers/vendor/csharp/_framework/supportFiles/88_System.Net.WebSockets.dll +0 -0
  462. package/workers/vendor/csharp/_framework/supportFiles/89_System.Numerics.dll +0 -0
  463. package/workers/vendor/csharp/_framework/supportFiles/8_netstandard.dll +0 -0
  464. package/workers/vendor/csharp/_framework/supportFiles/90_System.Numerics.Vectors.dll +0 -0
  465. package/workers/vendor/csharp/_framework/supportFiles/91_System.ObjectModel.dll +0 -0
  466. package/workers/vendor/csharp/_framework/supportFiles/92_System.Private.CoreLib.dll +0 -0
  467. package/workers/vendor/csharp/_framework/supportFiles/93_System.Private.DataContractSerialization.dll +0 -0
  468. package/workers/vendor/csharp/_framework/supportFiles/94_System.Private.Uri.dll +0 -0
  469. package/workers/vendor/csharp/_framework/supportFiles/95_System.Private.Xml.dll +0 -0
  470. package/workers/vendor/csharp/_framework/supportFiles/96_System.Private.Xml.Linq.dll +0 -0
  471. package/workers/vendor/csharp/_framework/supportFiles/97_System.Reflection.DispatchProxy.dll +0 -0
  472. package/workers/vendor/csharp/_framework/supportFiles/98_System.Reflection.dll +0 -0
  473. package/workers/vendor/csharp/_framework/supportFiles/99_System.Reflection.Emit.dll +0 -0
  474. package/workers/vendor/csharp/_framework/supportFiles/9_System.AppContext.dll +0 -0
  475. package/workers/vendor/csharp/_framework/tr/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  476. package/workers/vendor/csharp/_framework/tr/Microsoft.CodeAnalysis.resources.wasm +0 -0
  477. package/workers/vendor/csharp/_framework/zh-Hans/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  478. package/workers/vendor/csharp/_framework/zh-Hans/Microsoft.CodeAnalysis.resources.wasm +0 -0
  479. package/workers/vendor/csharp/_framework/zh-Hant/Microsoft.CodeAnalysis.CSharp.resources.wasm +0 -0
  480. package/workers/vendor/csharp/_framework/zh-Hant/Microsoft.CodeAnalysis.resources.wasm +0 -0
  481. package/workers/vendor/csharp/main.mjs +5 -0
  482. package/workers/vendor/csharp/package.json +1 -0
  483. package/workers/vendor/java-browser-helper.jar +0 -0
  484. package/workers/vendor/java-rewriter.jar +0 -0
  485. package/workers/vendor/javascript-libraries.js +10106 -0
  486. package/dist/runtime-types-89nchXlY.d.cts +0 -89
  487. package/dist/runtime-types-CCQ-ZLc9.d.ts +0 -89
  488. package/dist/types-zyvpJKCi.d.cts +0 -100
  489. package/dist/types-zyvpJKCi.d.ts +0 -100
  490. package/workers/java/java-source-augmentations.cjs +0 -242
  491. package/workers/java/src/spike/user/TraceHooks.java +0 -619
  492. package/workers/vendor/java-browser-spike-helper.jar +0 -0
  493. package/workers/vendor/java-practice-rewriter.jar +0 -0
  494. package/workers/vendor/java-rewrite-bridge.jar +0 -0
@@ -3,11 +3,94 @@ package harness.browser;
3
3
  import java.nio.charset.StandardCharsets;
4
4
  import java.nio.file.Files;
5
5
  import java.nio.file.Path;
6
- import spike.rewriter.GenericPracticeRewriter;
6
+ import java.util.ArrayDeque;
7
+ import java.util.Deque;
8
+ import java.util.HashMap;
9
+ import java.util.Map;
10
+ import java.util.regex.Matcher;
11
+ import java.util.regex.Pattern;
7
12
 
8
13
  public final class JavaRewriteLibrary {
14
+ private static final Pattern METHOD_START = Pattern.compile(
15
+ "^(\\s*)(?:(?:public|private|protected|static|final|synchronized)\\s+)*(?:[A-Za-z_][A-Za-z0-9_<>, ?]*(?:\\s*\\[\\])*\\s+)+([A-Za-z_][A-Za-z0-9_]*)\\s*\\(([^)]*)\\)\\s*\\{\\s*$");
16
+ private static final Pattern RETURN_STMT = Pattern.compile("^(\\s*)return(?:\\s+(.+?))?;\\s*$");
17
+ private static final Pattern ARRAY_WRITE_2D = Pattern.compile(
18
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]]+)\\]\\s*\\[([^;\\]]+)\\]\\s*=(?!=)\\s*(.+);\\s*$");
19
+ private static final Pattern ARRAY_WRITE_1D = Pattern.compile(
20
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]]+)\\]\\s*=(?!=)\\s*(.+);\\s*$");
21
+ private static final Pattern ARRAY_COMPOUND_WRITE_2D = Pattern.compile(
22
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]]+)\\]\\s*\\[([^;\\]]+)\\]\\s*([+\\-*/%&|^]|<<|>>|>>>)=\\s*(.+);\\s*$");
23
+ private static final Pattern ARRAY_COMPOUND_WRITE_1D = Pattern.compile(
24
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]]+)\\]\\s*([+\\-*/%&|^]|<<|>>|>>>)=\\s*(.+);\\s*$");
25
+ private static final Pattern ARRAY_UPDATE_2D = Pattern.compile(
26
+ "^(\\s*)(?:(\\+\\+|--))?\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]]+)\\]\\s*\\[([^;\\]]+)\\]\\s*(?:(\\+\\+|--))?;\\s*$");
27
+ private static final Pattern ARRAY_UPDATE_1D = Pattern.compile(
28
+ "^(\\s*)(?:(\\+\\+|--))?\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]]+)\\]\\s*(?:(\\+\\+|--))?;\\s*$");
29
+ private static final Pattern STRING_CHAR_AT = Pattern.compile("\\b([A-Za-z_][A-Za-z0-9_]*)\\.charAt\\(([^()]+)\\)");
30
+ private static final Pattern STRING_ARRAY_CHAR_AT = Pattern.compile("\\b([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]\\[]+)\\]\\.charAt\\(([^()]+)\\)");
31
+ private static final Pattern STRING_ARRAY_LENGTH_CALL = Pattern.compile("\\b([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]\\[]+)\\]\\.length\\(\\)");
32
+ private static final Pattern LIST_ARRAY_READ = Pattern.compile("\\b([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)\\s*\\[([^;\\]\\[]+)\\]");
33
+ private static final Pattern FIELD_WRITE = Pattern.compile("^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.+);\\s*$");
34
+ private static final Pattern FIELD_READ = Pattern.compile("(?<!\\.)\\b(?!System\\b|TraceHooks\\b)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\b(?!\\s*\\()");
35
+ private static final Pattern FIELD_DECLARATION = Pattern.compile(
36
+ "^\\s*(?:public|private|protected|static|final|transient|volatile|\\s)*([A-Za-z_][A-Za-z0-9_<>?, \\[\\]]*(?:\\s*\\[\\])*)\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*(?:=\\s*.+)?;\\s*$");
37
+ private static final Pattern LOCAL_DECLARATION = Pattern.compile(
38
+ "^(\\s*)(?:final\\s+)?([A-Za-z_][A-Za-z0-9_<>?, \\[\\]]*(?:\\s*\\[\\])*)\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*=\\s*(.+);\\s*$");
39
+ private static final Pattern LOCAL_ASSIGNMENT = Pattern.compile(
40
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*=(?!=)\\s*(.+);\\s*$");
41
+ private static final Pattern LOCAL_COMPOUND_ASSIGNMENT = Pattern.compile(
42
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*([+\\-*/%&|^]|<<|>>|>>>)=\\s*(.+);\\s*$");
43
+ private static final Pattern LOCAL_UPDATE = Pattern.compile(
44
+ "^(\\s*)(?:(\\+\\+|--))?\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*(?:(\\+\\+|--))?;\\s*$");
45
+ private static final Pattern MUTATING_CALL_STATEMENT = Pattern.compile(
46
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
47
+ private static final Pattern FIELD_INDEXED_MUTATING_CALL_STATEMENT = Pattern.compile(
48
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
49
+ private static final Pattern FIELD_MUTATING_CALL_STATEMENT = Pattern.compile(
50
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
51
+ private static final Pattern FRONT_FIELD_MUTATING_CALL_STATEMENT = Pattern.compile(
52
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.peek\\(\\)\\.([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
53
+ private static final Pattern COMPUTE_IF_ABSENT_MUTATING_CALL_STATEMENT = Pattern.compile(
54
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.computeIfAbsent\\((.+),\\s*([^;]+)\\)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
55
+ private static final Pattern INDEXED_MUTATING_CALL_STATEMENT = Pattern.compile(
56
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
57
+ private static final Pattern ARRAY_INDEXED_MUTATING_CALL_STATEMENT = Pattern.compile(
58
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]\\[]+)\\]\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\);\\s*$");
59
+ private static final Pattern ARRAY_INDEXED_MAP_WRITE_STATEMENT = Pattern.compile(
60
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]\\[]+)\\]\\.(put|merge)\\((.*)\\);\\s*$");
61
+ private static final Pattern LIST_ARRAY_WRITE = Pattern.compile(
62
+ "^(\\s*)([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)\\s*\\[([^;\\]\\[]+)\\]\\s*=(?!=)\\s*(.+);\\s*$");
63
+ private static final Pattern MUTATING_CALL_EXPRESSION = Pattern.compile(
64
+ "^([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\((.*)\\)$");
65
+ private static final Pattern MAP_GET_CALL = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)");
66
+ private static final Pattern MAP_GET_OR_DEFAULT_CALL = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\.getOrDefault\\(([^()\\n;]+)\\)");
67
+ private static final Pattern MAP_CONTAINS_KEY_CALL = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\.containsKey\\(([^()\\n;]+)\\)");
68
+ private static final Pattern QUEUE_PEEK_CALL = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\.peek\\(\\)");
69
+ private static final Pattern QUEUE_REMOVE_CALL = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\.(remove|poll)\\(\\)");
70
+ private static final Pattern COLLECTION_CONTAINS_CALL = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\.contains\\(([^()\\n;]+)\\)");
71
+ private static final Pattern THIS_FIELD_MAP_GET_CALL = Pattern.compile("\\bthis\\.([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)");
72
+ private static final Pattern THIS_FIELD_MAP_GET_OR_DEFAULT_CALL = Pattern.compile("\\bthis\\.([A-Za-z_][A-Za-z0-9_]*)\\.getOrDefault\\(([^()\\n;]+)\\)");
73
+ private static final Pattern THIS_FIELD_MAP_CONTAINS_KEY_CALL = Pattern.compile("\\bthis\\.([A-Za-z_][A-Za-z0-9_]*)\\.containsKey\\(([^()\\n;]+)\\)");
74
+ private static final Pattern OBJECT_FIELD_MAP_GET_CALL = Pattern.compile("(?<!\\.)\\b(?!this\\b)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\.get\\(([^()\\n;]+)\\)");
75
+ private static final Pattern OBJECT_FIELD_MAP_GET_OR_DEFAULT_CALL = Pattern.compile("(?<!\\.)\\b(?!this\\b)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\.getOrDefault\\(([^()\\n;]+)\\)");
76
+ private static final Pattern OBJECT_FIELD_MAP_CONTAINS_KEY_CALL = Pattern.compile("(?<!\\.)\\b(?!this\\b)([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\.containsKey\\(([^()\\n;]+)\\)");
77
+ private static final Pattern MATRIX_READ = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]\\[]+)\\]\\s*\\[([^;\\]\\[]+)\\]");
78
+ private static final Pattern ARRAY_READ = Pattern.compile("(?<!\\.)\\b([A-Za-z_][A-Za-z0-9_]*)\\s*\\[([^;\\]\\[]+)\\]");
79
+
9
80
  private JavaRewriteLibrary() {}
10
81
 
82
+ public static void main(String[] args) throws Exception {
83
+ if (args.length < 7) {
84
+ throw new IllegalArgumentException(
85
+ "Usage: <source> <output> <executionStyle> <entryName> <exportsSource> <exportsClassName> <packageName>");
86
+ }
87
+ String source = Files.readString(Path.of(args[0]), StandardCharsets.UTF_8);
88
+ String exportsSource = Files.readString(Path.of(args[4]), StandardCharsets.UTF_8);
89
+ String rewritten = rewriteSource(source, args[2], args[3], exportsSource, args[5], args[6]);
90
+ Files.createDirectories(Path.of(args[1]).getParent());
91
+ Files.writeString(Path.of(args[1]), rewritten, StandardCharsets.UTF_8);
92
+ }
93
+
11
94
  public static String rewriteSource(
12
95
  String source,
13
96
  String executionStyle,
@@ -15,40 +98,1570 @@ public final class JavaRewriteLibrary {
15
98
  String exportsSource,
16
99
  String exportsClassName,
17
100
  String packageName
18
- ) throws Exception {
19
- Path workDir = Files.createTempDirectory("tracecode-java-rewrite-");
20
- Path inputPath = workDir.resolve("Input.java");
21
- Path outputPath = workDir.resolve("Output.java");
22
-
23
- try {
24
- Files.writeString(inputPath, normalizeTopLevelPublicClasses(source), StandardCharsets.UTF_8);
25
- GenericPracticeRewriter.main(
26
- new String[] {
27
- inputPath.toString(),
28
- outputPath.toString(),
29
- executionStyle,
30
- entryName,
31
- });
32
- String rewrittenSource = Files.readString(outputPath, StandardCharsets.UTF_8);
33
- String renamedExports =
34
- exportsSource.replaceAll("\\bpublic class Exports\\b", "public class " + exportsClassName);
35
- return "package " + packageName + ";\n\n" + rewrittenSource.trim() + "\n\n" + renamedExports.trim() + "\n";
36
- } finally {
37
- try (var paths = Files.walk(workDir)) {
38
- paths
39
- .sorted((left, right) -> right.getNameCount() - left.getNameCount())
40
- .forEach(
41
- path -> {
42
- try {
43
- Files.deleteIfExists(path);
44
- } catch (Exception ignored) {
45
- }
46
- });
101
+ ) {
102
+ String rewrittenSource = rewriteJava(normalizeTopLevelPublicClasses(source));
103
+ String renamedExports = exportsSource.replaceAll("\\bpublic class Exports\\b", "public class " + exportsClassName);
104
+ return "package " + packageName + ";\n\n" + rewrittenSource.trim() + "\n\n" + renamedExports.trim() + "\n";
105
+ }
106
+
107
+ private static String normalizeTopLevelPublicClasses(String source) {
108
+ return source.replaceAll("(?m)^([ \\t]*)public\\s+class\\s+", "$1class ");
109
+ }
110
+
111
+ private static String extractReturnType(String methodLine, String methodName) {
112
+ int nameIndex = methodLine.indexOf(methodName);
113
+ if (nameIndex <= 0) return "var";
114
+ String beforeName = methodLine.substring(0, nameIndex).trim();
115
+ if (beforeName.isEmpty()) return "var";
116
+ String[] parts = beforeName.split("\\s+");
117
+ return parts.length == 0 ? "var" : parts[parts.length - 1];
118
+ }
119
+
120
+ private static String rewriteJava(String source) {
121
+ StringBuilder out = new StringBuilder();
122
+ out.append("import tracecode.user.TraceHooks;\n");
123
+ String[] lines = source.split("\\r?\\n", -1);
124
+ Deque<MethodFrame> methods = new ArrayDeque<>();
125
+ Map<String, String> fields = new HashMap<>();
126
+
127
+ for (int index = 0; index < lines.length; index++) {
128
+ String line = lines[index];
129
+ int sourceLine = index + 1;
130
+ Matcher method = METHOD_START.matcher(line);
131
+ if (method.matches()) {
132
+ out.append(line).append('\n');
133
+ String name = method.group(2);
134
+ methods.push(new MethodFrame(name, extractReturnType(line, name), braceDelta(line), fields, method.group(3)));
135
+ out.append(method.group(1)).append(" TraceHooks.emitCallAtLine(")
136
+ .append(sourceLine).append(", ").append(quote(name)).append(", \"\");\n");
137
+ continue;
138
+ }
139
+
140
+ MethodFrame current = methods.peek();
141
+ if (current == null) {
142
+ registerFieldDeclaration(fields, line);
143
+ out.append(line).append('\n');
144
+ continue;
145
+ }
146
+
147
+ String trimmed = line.trim();
148
+ if (trimmed.startsWith("@")) {
149
+ out.append(line).append('\n');
150
+ current.depth += braceDelta(line);
151
+ current.pendingAnnotation = true;
152
+ continue;
153
+ }
154
+
155
+ if (current.initializerDepth > 0 || startsMultilineInitializer(trimmed)) {
156
+ if (
157
+ current.initializerDepth <= 0 &&
158
+ !current.pendingAnnotation &&
159
+ shouldEmitLine(trimmed)
160
+ ) {
161
+ out.append(indentOf(line)).append("TraceHooks.emitLineAtLine(").append(sourceLine).append(");\n");
162
+ }
163
+ registerMultilineLocalDeclaration(current, trimmed);
164
+ out.append(line).append('\n');
165
+ current.initializerDepth = Math.max(0, current.initializerDepth + braceDelta(line));
166
+ current.depth += braceDelta(line);
167
+ while (!methods.isEmpty() && methods.peek().depth <= 0) {
168
+ methods.pop();
169
+ }
170
+ continue;
171
+ }
172
+
173
+ if (current.headerParenDepth > 0) {
174
+ String rewrittenLine = rewriteStatement(line, sourceLine, current);
175
+ out.append(rewrittenLine).append('\n');
176
+ current.headerParenDepth = Math.max(0, current.headerParenDepth + parenDelta(line));
177
+ current.depth += braceDelta(rewrittenLine);
178
+ while (!methods.isEmpty() && methods.peek().depth <= 0) {
179
+ methods.pop();
180
+ }
181
+ continue;
182
+ }
183
+
184
+ boolean continuingExpression = current.expressionParenDepth > 0 || current.statementContinuation;
185
+ boolean postLineStateStatement = emitsPostLineState(trimmed, current);
186
+ boolean suppressLineHook = current.suppressNextLineHook || continuingExpression || postLineStateStatement;
187
+ current.suppressNextLineHook = false;
188
+ if (!current.pendingAnnotation && !suppressLineHook && shouldEmitLine(trimmed)) {
189
+ out.append(indentOf(line)).append("TraceHooks.emitLineAtLine(").append(sourceLine).append(");\n");
190
+ }
191
+
192
+ String rewrittenLine = rewriteStatement(line, sourceLine, current);
193
+ out.append(rewrittenLine).append('\n');
194
+ current.pendingAnnotation = false;
195
+ if (startsMultilineControlHeader(trimmed)) {
196
+ current.headerParenDepth = Math.max(0, parenDelta(line));
197
+ }
198
+ if (startsUnbracedControlHeader(trimmed)) {
199
+ current.suppressNextLineHook = true;
200
+ }
201
+ if (endsWithExpressionContinuation(trimmed)) {
202
+ current.suppressNextLineHook = true;
203
+ }
204
+ updateExpressionContinuation(current, trimmed);
205
+
206
+ current.depth += braceDelta(rewrittenLine);
207
+ while (!methods.isEmpty() && methods.peek().depth <= 0) {
208
+ methods.pop();
209
+ if (!methods.isEmpty()) {
210
+ methods.peek().depth += current.depth;
211
+ }
47
212
  }
48
213
  }
214
+ return out.toString();
49
215
  }
50
216
 
51
- private static String normalizeTopLevelPublicClasses(String source) {
52
- return source.replaceAll("(^|\\n)\\s*public\\s+class\\s+", "$1class ");
217
+ private static String rewriteStatement(String line, int sourceLine, MethodFrame frame) {
218
+ String inlineControl = rewriteInlineControlStatement(line, sourceLine, frame);
219
+ if (inlineControl != null) {
220
+ return inlineControl;
221
+ }
222
+
223
+ Matcher returnMatch = RETURN_STMT.matcher(line);
224
+ if (returnMatch.matches()) {
225
+ String indent = returnMatch.group(1);
226
+ String expression = returnMatch.group(2);
227
+ StringBuilder out = new StringBuilder();
228
+ if (expression == null || expression.trim().isEmpty()) {
229
+ out.append(indent).append("TraceHooks.emitReturnAtLine(").append(sourceLine).append(", ").append(quote(frame.name)).append(");\n");
230
+ out.append(indent).append("return;");
231
+ } else {
232
+ String rewrittenExpression = rewriteReads(expression.trim(), sourceLine, frame);
233
+ String tempName = "__tracecodeReturnValue" + sourceLine;
234
+ out.append(indent).append(frame.returnTypeOrVar()).append(" ").append(tempName).append(" = ").append(rewrittenExpression).append(";\n");
235
+ out.append(indent).append("TraceHooks.emitSerializedReturnAtLine(").append(sourceLine).append(", ").append(quote(frame.name)).append(", TraceHooks.serializeResult(").append(tempName).append("));\n");
236
+ out.append(indent).append("return ").append(tempName).append(';');
237
+ }
238
+ return out.toString();
239
+ }
240
+
241
+ Matcher declaration = LOCAL_DECLARATION.matcher(line);
242
+ if (declaration.matches() && !line.trim().startsWith("for ") && !isControlKeyword(declaration.group(2).trim())) {
243
+ String indent = declaration.group(1);
244
+ String type = declaration.group(2).trim();
245
+ String name = declaration.group(3);
246
+ java.util.List<String> declaredNames = registerLocalDeclarators(frame, type, name + " = " + declaration.group(4).trim());
247
+ String value = rewriteReads(declaration.group(4).trim(), sourceLine, frame);
248
+ String prefix = line.substring(0, declaration.start(3));
249
+ String rewritten = frame.pendingAnnotation
250
+ ? prefix + name + " = " + value + ";\n" + indent + "TraceHooks.emitLineAtLine(" + sourceLine + ");"
251
+ : indent + "TraceHooks.emitLineAtLine(" + sourceLine + ");\n" + prefix + name + " = " + value + ";";
252
+ Matcher mutatingExpression = MUTATING_CALL_EXPRESSION.matcher(declaration.group(4).trim());
253
+ if (mutatingExpression.matches() && isTrackedMutationMethod(mutatingExpression.group(2))) {
254
+ String receiver = mutatingExpression.group(1);
255
+ if (!value.contains("TraceHooks.") || !value.contains(receiver)) {
256
+ rewritten += " TraceHooks.emitMutatingCallAtLine(" + sourceLine + ", " +
257
+ quote(receiver) + ", " + quote(mutatingExpression.group(2)) + ");";
258
+ rewritten += " TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " +
259
+ quote(receiver) + ", " + receiver + ");";
260
+ }
261
+ }
262
+ for (String declaredName : declaredNames) {
263
+ rewritten += "\n" + indent + "TraceHooks.emitScalarWriteAtLine(" + sourceLine + ", " + quote(declaredName) + ", " + declaredName + ");";
264
+ rewritten += "\n" + indent + "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(declaredName) + ", " + declaredName + ");";
265
+ }
266
+ return rewritten;
267
+ }
268
+
269
+ Matcher forDeclaration = Pattern.compile("^(\\s*)for\\s*\\(\\s*(?:final\\s+)?([A-Za-z_][A-Za-z0-9_<>.?\\[\\] ]*)\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*=([^;]+);(.*)\\)\\s*\\{\\s*$").matcher(line);
270
+ if (forDeclaration.matches()) {
271
+ String indent = forDeclaration.group(1);
272
+ String type = forDeclaration.group(2).trim();
273
+ String name = forDeclaration.group(3);
274
+ registerLocalDeclarators(frame, type, name + " = " + forDeclaration.group(4).trim());
275
+ String bodyIndent = indent + " ";
276
+ return line + "\n" +
277
+ bodyIndent + "TraceHooks.emitScalarWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");\n" +
278
+ bodyIndent + "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
279
+ }
280
+
281
+ Matcher enhancedForDeclaration = Pattern.compile("^(\\s*)for\\s*\\(\\s*(?:final\\s+)?([A-Za-z_][A-Za-z0-9_<>.?\\[\\] ]*)\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*:\\s*([^\\)]+)\\)\\s*\\{\\s*$").matcher(line);
282
+ if (enhancedForDeclaration.matches()) {
283
+ String type = enhancedForDeclaration.group(2).trim();
284
+ String name = enhancedForDeclaration.group(3);
285
+ registerLocalDeclarators(frame, type, name);
286
+ return line;
287
+ }
288
+
289
+ Matcher assignment = LOCAL_ASSIGNMENT.matcher(line);
290
+ if (assignment.matches() && frame.variables.containsKey(assignment.group(2))) {
291
+ String indent = assignment.group(1);
292
+ String name = assignment.group(2);
293
+ String rawValue = assignment.group(3).trim();
294
+ String value = rewriteReads(rawValue, sourceLine, frame);
295
+ String rewritten = indent + "TraceHooks.emitLineAtLine(" + sourceLine + ");\n" +
296
+ indent + name + " = " + value + ";\n" +
297
+ indent + "TraceHooks.emitScalarWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");\n" +
298
+ indent + "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
299
+ Matcher mutatingExpression = MUTATING_CALL_EXPRESSION.matcher(rawValue);
300
+ if (mutatingExpression.matches() && isTrackedMutationMethod(mutatingExpression.group(2))) {
301
+ String receiver = mutatingExpression.group(1);
302
+ if (!value.contains("TraceHooks.") || !value.contains(receiver)) {
303
+ rewritten += "\n" + indent + "TraceHooks.emitMutatingCallAtLine(" + sourceLine + ", " +
304
+ quote(receiver) + ", " + quote(mutatingExpression.group(2)) + ");";
305
+ rewritten += " TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " +
306
+ quote(receiver) + ", " + receiver + ");";
307
+ }
308
+ }
309
+ return rewritten;
310
+ }
311
+
312
+ Matcher compoundAssignment = LOCAL_COMPOUND_ASSIGNMENT.matcher(line);
313
+ if (compoundAssignment.matches() && frame.variables.containsKey(compoundAssignment.group(2))) {
314
+ String indent = compoundAssignment.group(1);
315
+ String name = compoundAssignment.group(2);
316
+ String operator = compoundAssignment.group(3);
317
+ String value = rewriteReads(compoundAssignment.group(4).trim(), sourceLine, frame);
318
+ return indent + "TraceHooks.emitLineAtLine(" + sourceLine + ");\n" +
319
+ indent + name + " " + operator + "= " + value + ";\n" +
320
+ indent + "TraceHooks.emitScalarWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");\n" +
321
+ indent + "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
322
+ }
323
+
324
+ Matcher localUpdate = LOCAL_UPDATE.matcher(line);
325
+ if (localUpdate.matches() && (localUpdate.group(2) != null || localUpdate.group(4) != null) && frame.variables.containsKey(localUpdate.group(3))) {
326
+ String indent = localUpdate.group(1);
327
+ String prefix = localUpdate.group(2);
328
+ String name = localUpdate.group(3);
329
+ String suffix = localUpdate.group(4);
330
+ String operator = prefix != null ? prefix : suffix;
331
+ return indent + "TraceHooks.emitLineAtLine(" + sourceLine + ");\n" +
332
+ indent + name + ("++".equals(operator) ? " += 1;" : " -= 1;") + "\n" +
333
+ indent + "TraceHooks.emitScalarWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");\n" +
334
+ indent + "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
335
+ }
336
+
337
+ Matcher fieldWrite = FIELD_WRITE.matcher(line);
338
+ if (fieldWrite.matches()) {
339
+ String indent = fieldWrite.group(1);
340
+ String name = fieldWrite.group(2);
341
+ String field = fieldWrite.group(3);
342
+ String value = rewriteReads(fieldWrite.group(4).trim(), sourceLine, frame);
343
+ return indent + name + "." + field + " = " + value + "; TraceHooks.emitFieldWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + quote(field) + ", " + name + "." + field + ");";
344
+ }
345
+
346
+ Matcher fieldIndexedMutatingCall = FIELD_INDEXED_MUTATING_CALL_STATEMENT.matcher(line);
347
+ if (fieldIndexedMutatingCall.matches() && isTrackedMutationMethod(fieldIndexedMutatingCall.group(5))) {
348
+ String indent = fieldIndexedMutatingCall.group(1);
349
+ String name = fieldIndexedMutatingCall.group(2);
350
+ String field = fieldIndexedMutatingCall.group(3);
351
+ String index = rewriteReads(fieldIndexedMutatingCall.group(4).trim(), sourceLine, frame);
352
+ String method = fieldIndexedMutatingCall.group(5);
353
+ MutatingArgs rewrittenArgs = mutatingArgs(fieldIndexedMutatingCall.group(6).trim(), sourceLine, frame);
354
+ String target = name + "." + field + ".get(" + index + ")";
355
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\\\"" + field + "\\\",";
356
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + "," +
357
+ pathPrefix + "\" + (" + index + ") + \"]},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
358
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
359
+ pathPrefix + "\" + (" + index + ") + \"]},\\\"method\\\":\\\"" + method + "\\\"}\");";
360
+ String snapshotEvent = "this".equals(name) && frame.isField(field)
361
+ ? "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(field) + ", " + field + ");"
362
+ : "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
363
+ return indent + "{ " + readEvent + " " + rewrittenArgs.prefix + target + "." + method + "(" + rewrittenArgs.callArgs + "); " + mutateEvent + " " + snapshotEvent + " }";
364
+ }
365
+
366
+ Matcher frontFieldMutatingCall = FRONT_FIELD_MUTATING_CALL_STATEMENT.matcher(line);
367
+ if (frontFieldMutatingCall.matches() && isTrackedMutationMethod(frontFieldMutatingCall.group(4))) {
368
+ String indent = frontFieldMutatingCall.group(1);
369
+ String name = frontFieldMutatingCall.group(2);
370
+ String field = frontFieldMutatingCall.group(3);
371
+ String method = frontFieldMutatingCall.group(4);
372
+ MutatingArgs rewrittenArgs = mutatingArgs(frontFieldMutatingCall.group(5).trim(), sourceLine, frame);
373
+ String target = name + ".peek()." + field;
374
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[0,\\\"" + field + "\\\"]}";
375
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + "," +
376
+ pathPrefix + ",\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
377
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
378
+ pathPrefix + ",\\\"method\\\":\\\"" + method + "\\\"}\");";
379
+ String snapshotEvent = "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
380
+ return indent + "{ " + readEvent + " " + rewrittenArgs.prefix + target + "." + method + "(" + rewrittenArgs.callArgs + "); " + mutateEvent + " " + snapshotEvent + " }";
381
+ }
382
+
383
+ Matcher fieldMutatingCall = FIELD_MUTATING_CALL_STATEMENT.matcher(line);
384
+ if (fieldMutatingCall.matches() && isTrackedMutationMethod(fieldMutatingCall.group(4))) {
385
+ String indent = fieldMutatingCall.group(1);
386
+ String name = fieldMutatingCall.group(2);
387
+ String field = fieldMutatingCall.group(3);
388
+ String method = fieldMutatingCall.group(4);
389
+ String rawArgs = fieldMutatingCall.group(5).trim();
390
+ String target = name + "." + field;
391
+ if ("this".equals(name) && "put".equals(method) && isMapType(frame.typeOf(field))) {
392
+ java.util.List<String> parts = splitTopLevel(rawArgs);
393
+ if (parts.size() >= 2) {
394
+ String key = rewriteReads(parts.get(0), sourceLine, frame);
395
+ String value = rewriteReads(parts.get(1), sourceLine, frame);
396
+ return indent + "TraceHooks.putFieldMapAtLine(" + sourceLine + ", \"this\", " + quote(field) + ", " + target + ", " + key + ", " + value + ", " + indexSourceArgument(parts.get(0)) + ");";
397
+ }
398
+ }
399
+ if (!"this".equals(name) && ("put".equals(method) || "putIfAbsent".equals(method)) && isMapType(frame.typeOf(field))) {
400
+ java.util.List<String> parts = splitTopLevel(rawArgs);
401
+ if (parts.size() >= 2) {
402
+ String key = rewriteReads(parts.get(0), sourceLine, frame);
403
+ String value = rewriteReads(parts.get(1), sourceLine, frame);
404
+ String hook = "putIfAbsent".equals(method) ? "putFieldMapIfAbsentAtLine" : "putFieldMapAtLine";
405
+ return indent + "TraceHooks." + hook + "(" + sourceLine + ", " + quote(name) + ", " + quote(field) + ", " + target + ", " + key + ", " + value + ", " + indexSourceArgument(parts.get(0)) + ");";
406
+ }
407
+ }
408
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\\\"" + field + "\\\"]}";
409
+ MutatingArgs rewrittenArgs = mutatingArgs(rawArgs, sourceLine, frame);
410
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
411
+ pathPrefix + ",\\\"method\\\":\\\"" + method + "\\\"" + rewrittenArgs.eventSegment + "}\");";
412
+ String snapshotEvent = "this".equals(name) && frame.isField(field)
413
+ ? "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(field) + ", " + field + ");"
414
+ : "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
415
+ return indent + "{ " + rewrittenArgs.prefix + target + "." + method + "(" + rewrittenArgs.callArgs + "); " + mutateEvent + " " + snapshotEvent + " }";
416
+ }
417
+
418
+ Matcher computeMutatingCall = COMPUTE_IF_ABSENT_MUTATING_CALL_STATEMENT.matcher(line);
419
+ if (computeMutatingCall.matches() && isTrackedMutationMethod(computeMutatingCall.group(5))) {
420
+ String indent = computeMutatingCall.group(1);
421
+ String name = computeMutatingCall.group(2);
422
+ String rawKey = computeMutatingCall.group(3).trim();
423
+ String key = rewriteReads(rawKey, sourceLine, frame);
424
+ String fallback = computeMutatingCall.group(4).trim();
425
+ String method = computeMutatingCall.group(5);
426
+ MutatingArgs rewrittenArgs = mutatingArgs(computeMutatingCall.group(6).trim(), sourceLine, frame);
427
+ String target = name + ".computeIfAbsent(" + key + ", " + fallback + ")";
428
+ String temp = "__tracecodeComputedTarget" + sourceLine;
429
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[";
430
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + "," +
431
+ pathPrefix + "\" + TraceHooks.serializeResult(" + key + ") + \"]" + escapedIndexSourcesTargetSegment(rawKey) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + temp + ") + \"}\");";
432
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
433
+ pathPrefix + "\" + TraceHooks.serializeResult(" + key + ") + \"]" + escapedIndexSourcesTargetSegment(rawKey) + "},\\\"method\\\":\\\"" + method + "\\\"" + rewrittenArgs.eventSegment + "}\");";
434
+ String snapshotEvent = "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
435
+ return indent + "{ var " + temp + " = " + target + "; " + readEvent + " " + rewrittenArgs.prefix + temp + "." + method + "(" + rewrittenArgs.callArgs + "); " + mutateEvent + " " + snapshotEvent + " }";
436
+ }
437
+
438
+ Matcher indexedMutatingCall = INDEXED_MUTATING_CALL_STATEMENT.matcher(line);
439
+ if (indexedMutatingCall.matches() && isTrackedMutationMethod(indexedMutatingCall.group(4))) {
440
+ String indent = indexedMutatingCall.group(1);
441
+ String name = indexedMutatingCall.group(2);
442
+ String rawIndex = indexedMutatingCall.group(3).trim();
443
+ String index = rewriteReads(rawIndex, sourceLine, frame);
444
+ String method = indexedMutatingCall.group(4);
445
+ MutatingArgs rewrittenArgs = mutatingArgs(indexedMutatingCall.group(5).trim(), sourceLine, frame);
446
+ String temp = "__tracecodeIndexedTarget" + sourceLine;
447
+ String target = indexedAccessExpression(name, frame.typeOf(name), index);
448
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[";
449
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + "," +
450
+ pathPrefix + "\" + TraceHooks.serializeResult(" + index + ") + \"]" + escapedIndexSourcesTargetSegment(rawIndex) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + temp + ") + \"}\");";
451
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
452
+ pathPrefix + "\" + TraceHooks.serializeResult(" + index + ") + \"]" + escapedIndexSourcesTargetSegment(rawIndex) + "},\\\"method\\\":\\\"" + method + "\\\"" + rewrittenArgs.eventSegment + "}\");";
453
+ String snapshotEvent = "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
454
+ return indent + "{ var " + temp + " = " + target + "; " + readEvent + " " + rewrittenArgs.prefix + temp + "." + method + "(" + rewrittenArgs.callArgs + "); " + mutateEvent + " " + snapshotEvent + " }";
455
+ }
456
+
457
+ Matcher arrayIndexedMapWrite = ARRAY_INDEXED_MAP_WRITE_STATEMENT.matcher(line);
458
+ if (arrayIndexedMapWrite.matches() && isArrayOfMapType(frame.typeOf(arrayIndexedMapWrite.group(2)))) {
459
+ String indent = arrayIndexedMapWrite.group(1);
460
+ String name = arrayIndexedMapWrite.group(2);
461
+ String rawIndex = arrayIndexedMapWrite.group(3).trim();
462
+ String index = rewriteReads(rawIndex, sourceLine, frame);
463
+ String method = arrayIndexedMapWrite.group(4);
464
+ java.util.List<String> args = splitTopLevel(arrayIndexedMapWrite.group(5).trim());
465
+ if (args.size() < 2) {
466
+ return rewriteReads(line, sourceLine, frame);
467
+ }
468
+ String rawKey = args.get(0);
469
+ String key = rewriteReads(rawKey, sourceLine, frame);
470
+ java.util.List<String> rewrittenArgs = new java.util.ArrayList<>();
471
+ rewrittenArgs.add(key);
472
+ for (int i = 1; i < args.size(); i++) {
473
+ rewrittenArgs.add(rewriteReads(args.get(i), sourceLine, frame));
474
+ }
475
+ String target = name + "[" + index + "]";
476
+ String joinedArgs = String.join(", ", rewrittenArgs);
477
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[";
478
+ String writeEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"write\\\",\\\"line\\\":" + sourceLine + "," +
479
+ pathPrefix + "\" + TraceHooks.serializeResult(" + index + ") + \",\" + TraceHooks.serializeResult(" + key + ") + \"]" + escapedIndexSourcesTargetSegment(rawIndex, rawKey) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ".get(" + key + ")) + \"}\");";
480
+ String snapshotEvent = "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
481
+ return indent + target + "." + method + "(" + joinedArgs + "); " + writeEvent + " " + snapshotEvent;
482
+ }
483
+
484
+ Matcher listArrayWrite = LIST_ARRAY_WRITE.matcher(line);
485
+ if (listArrayWrite.matches()) {
486
+ String indent = listArrayWrite.group(1);
487
+ String name = listArrayWrite.group(2);
488
+ String rawRow = listArrayWrite.group(3).trim();
489
+ String rawCol = listArrayWrite.group(4).trim();
490
+ String row = rewriteReads(rawRow, sourceLine, frame);
491
+ String col = rewriteReads(rawCol, sourceLine, frame);
492
+ String value = rewriteReads(listArrayWrite.group(5).trim(), sourceLine, frame);
493
+ String temp = "__tracecodeArrayListTarget" + sourceLine;
494
+ String target = "((int[])((java.util.List)" + name + ").get(" + row + "))";
495
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + ",\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\" + TraceHooks.serializeResult(" + row + ") + \",\" + TraceHooks.serializeResult(" + col + ") + \"]" + escapedIndexSourcesTargetSegment(rawRow, rawCol) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + temp + "[" + col + "]) + \"}\");";
496
+ String writeEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"write\\\",\\\"line\\\":" + sourceLine + ",\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\" + TraceHooks.serializeResult(" + row + ") + \",\" + TraceHooks.serializeResult(" + col + ") + \"]" + escapedIndexSourcesTargetSegment(rawRow, rawCol) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + value + ") + \"}\");";
497
+ return indent + "{ int[] " + temp + " = " + target + "; " + readEvent + " " + temp + "[" + col + "] = " + value + "; " + writeEvent + " }";
498
+ }
499
+
500
+ Matcher arrayIndexedMutatingCall = ARRAY_INDEXED_MUTATING_CALL_STATEMENT.matcher(line);
501
+ if (arrayIndexedMutatingCall.matches() && isTrackedMutationMethod(arrayIndexedMutatingCall.group(4))) {
502
+ String indent = arrayIndexedMutatingCall.group(1);
503
+ String name = arrayIndexedMutatingCall.group(2);
504
+ String rawIndex = arrayIndexedMutatingCall.group(3).trim();
505
+ String index = rewriteReads(rawIndex, sourceLine, frame);
506
+ String method = arrayIndexedMutatingCall.group(4);
507
+ String args = rewriteReads(arrayIndexedMutatingCall.group(5).trim(), sourceLine, frame);
508
+ String target = name + "[" + index + "]";
509
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[";
510
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + "," +
511
+ pathPrefix + "\" + TraceHooks.serializeResult(" + index + ") + \"]" + escapedIndexSourcesTargetSegment(rawIndex) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
512
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
513
+ pathPrefix + "\" + TraceHooks.serializeResult(" + index + ") + \"]" + escapedIndexSourcesTargetSegment(rawIndex) + "},\\\"method\\\":\\\"" + method + "\\\"}\");";
514
+ String snapshotEvent = "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
515
+ return indent + "{ " + readEvent + " " + target + "." + method + "(" + args + "); " + mutateEvent + " " + snapshotEvent + " }";
516
+ }
517
+
518
+ Matcher update2d = ARRAY_UPDATE_2D.matcher(line);
519
+ if (update2d.matches() && (update2d.group(2) != null || update2d.group(6) != null)) {
520
+ String indent = update2d.group(1);
521
+ String operator = update2d.group(2) != null ? update2d.group(2) : update2d.group(6);
522
+ String name = update2d.group(3);
523
+ String row = update2d.group(4).trim();
524
+ String col = update2d.group(5).trim();
525
+ if (hasIndexSideEffect(row) || hasIndexSideEffect(col)) {
526
+ return rewriteReads(line, sourceLine, frame);
527
+ }
528
+ String target = name + "[" + row + "][" + col + "]";
529
+ String delta = "++".equals(operator) ? "1" : "-1";
530
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + ",\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\" + TraceHooks.serializeResult(" + row + ") + \",\" + TraceHooks.serializeResult(" + col + ") + \"]" + escapedIndexSourcesTargetSegment(row, col) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
531
+ return indent + readEvent + " " + target + " += " + delta + "; TraceHooks.emitArrayWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + row + ", " + col + ", " + target + ", " + indexSourceArgument(row) + ", " + indexSourceArgument(col) + ");";
532
+ }
533
+
534
+ Matcher update1d = ARRAY_UPDATE_1D.matcher(line);
535
+ if (update1d.matches() && (update1d.group(2) != null || update1d.group(5) != null)) {
536
+ String indent = update1d.group(1);
537
+ String operator = update1d.group(2) != null ? update1d.group(2) : update1d.group(5);
538
+ String name = update1d.group(3);
539
+ String idx = update1d.group(4).trim();
540
+ if (hasIndexSideEffect(idx)) {
541
+ return rewriteReads(line, sourceLine, frame);
542
+ }
543
+ String target = name + "[" + idx + "]";
544
+ String delta = "++".equals(operator) ? "1" : "-1";
545
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + ",\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\" + TraceHooks.serializeResult(" + idx + ") + \"]" + escapedIndexSourcesTargetSegment(idx) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
546
+ return indent + readEvent + " " + target + " += " + delta + "; TraceHooks.emitArrayWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + idx + ", (Object) " + target + ", " + indexSourceArgument(idx) + ");";
547
+ }
548
+
549
+ Matcher compoundWrite2d = ARRAY_COMPOUND_WRITE_2D.matcher(line);
550
+ if (compoundWrite2d.matches()) {
551
+ String indent = compoundWrite2d.group(1);
552
+ String name = compoundWrite2d.group(2);
553
+ String row = compoundWrite2d.group(3).trim();
554
+ String col = compoundWrite2d.group(4).trim();
555
+ if (hasIndexSideEffect(row) || hasIndexSideEffect(col)) {
556
+ return rewriteReads(line, sourceLine, frame);
557
+ }
558
+ String operator = compoundWrite2d.group(5);
559
+ String value = rewriteReads(compoundWrite2d.group(6).trim(), sourceLine, frame);
560
+ String target = name + "[" + row + "][" + col + "]";
561
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + ",\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\" + TraceHooks.serializeResult(" + row + ") + \",\" + TraceHooks.serializeResult(" + col + ") + \"]" + escapedIndexSourcesTargetSegment(row, col) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
562
+ return indent + readEvent + " " + target + " " + operator + "= " + value + "; TraceHooks.emitArrayWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + row + ", " + col + ", " + target + ", " + indexSourceArgument(row) + ", " + indexSourceArgument(col) + ");";
563
+ }
564
+
565
+ Matcher compoundWrite1d = ARRAY_COMPOUND_WRITE_1D.matcher(line);
566
+ if (compoundWrite1d.matches()) {
567
+ String indent = compoundWrite1d.group(1);
568
+ String name = compoundWrite1d.group(2);
569
+ String idx = compoundWrite1d.group(3).trim();
570
+ if (hasIndexSideEffect(idx)) {
571
+ return rewriteReads(line, sourceLine, frame);
572
+ }
573
+ String operator = compoundWrite1d.group(4);
574
+ String value = rewriteReads(compoundWrite1d.group(5).trim(), sourceLine, frame);
575
+ String target = name + "[" + idx + "]";
576
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + ",\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\",\\\"path\\\":[\" + TraceHooks.serializeResult(" + idx + ") + \"]" + escapedIndexSourcesTargetSegment(idx) + "},\\\"value\\\":\" + TraceHooks.serializeResult(" + target + ") + \"}\");";
577
+ return indent + readEvent + " " + target + " " + operator + "= " + value + "; TraceHooks.emitArrayWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + idx + ", (Object) " + target + ", " + indexSourceArgument(idx) + ");";
578
+ }
579
+
580
+ Matcher write2d = ARRAY_WRITE_2D.matcher(line);
581
+ if (write2d.matches()) {
582
+ String indent = write2d.group(1);
583
+ String name = write2d.group(2);
584
+ String row = write2d.group(3).trim();
585
+ String col = write2d.group(4).trim();
586
+ String value = rewriteReads(write2d.group(5).trim(), sourceLine, frame);
587
+ String rowTemp = "__tracecodeRow" + sourceLine;
588
+ String colTemp = "__tracecodeCol" + sourceLine;
589
+ return indent + "{ int " + rowTemp + " = " + row + "; int " + colTemp + " = " + col + "; " +
590
+ name + "[" + rowTemp + "][" + colTemp + "] = " + value + "; TraceHooks.emitArrayWriteAtLine(" +
591
+ sourceLine + ", " + quote(name) + ", " + rowTemp + ", " + colTemp + ", " +
592
+ name + "[" + rowTemp + "][" + colTemp + "], " + indexSourceArgument(row) + ", " + indexSourceArgument(col) + "); }";
593
+ }
594
+
595
+ Matcher write1d = ARRAY_WRITE_1D.matcher(line);
596
+ if (write1d.matches()) {
597
+ String indent = write1d.group(1);
598
+ String name = write1d.group(2);
599
+ String idx = write1d.group(3).trim();
600
+ String value = rewriteReads(write1d.group(4).trim(), sourceLine, frame);
601
+ String indexTemp = "__tracecodeIndex" + sourceLine;
602
+ return indent + "{ int " + indexTemp + " = " + idx + "; " + name + "[" + indexTemp + "] = " + value +
603
+ "; TraceHooks.emitArrayWriteAtLine(" + sourceLine + ", " + quote(name) + ", " + indexTemp + ", " +
604
+ "(Object) " + name + "[" + indexTemp + "], " + indexSourceArgument(idx) + "); }";
605
+ }
606
+
607
+ Matcher mutatingCall = MUTATING_CALL_STATEMENT.matcher(line);
608
+ if (mutatingCall.matches() && isTrackedMutationMethod(mutatingCall.group(3))) {
609
+ String indent = mutatingCall.group(1);
610
+ String name = mutatingCall.group(2);
611
+ String method = mutatingCall.group(3);
612
+ String rawArgs = mutatingCall.group(4).trim();
613
+ String args = rewriteReads(rawArgs, sourceLine, frame);
614
+ if (("put".equals(method) || "putIfAbsent".equals(method)) && frame.isField(name) && isMapType(frame.typeOf(name))) {
615
+ java.util.List<String> parts = splitTopLevel(rawArgs);
616
+ if (parts.size() >= 2) {
617
+ String key = rewriteReads(parts.get(0), sourceLine, frame);
618
+ String value = rewriteReads(parts.get(1), sourceLine, frame);
619
+ String keySource = indexSourceArgument(parts.get(0));
620
+ String hook = "putIfAbsent".equals(method) ? "putMapIfAbsentAtLine" : "putMapAtLine";
621
+ return indent + "TraceHooks." + hook + "(" + sourceLine + ", " + quote(name) + ", " + name + ", " + key + ", " + value + ", " + keySource + ");";
622
+ }
623
+ }
624
+ if (("put".equals(method) || "putIfAbsent".equals(method)) && isMapType(frame.typeOf(name))) {
625
+ java.util.List<String> parts = splitTopLevel(mutatingCall.group(4).trim());
626
+ if (parts.size() >= 2) {
627
+ String key = rewriteReads(parts.get(0), sourceLine, frame);
628
+ String value = rewriteReads(parts.get(1), sourceLine, frame);
629
+ String keySource = indexSourceArgument(parts.get(0));
630
+ String hook = "putIfAbsent".equals(method) ? "putMapIfAbsentAtLine" : "putMapAtLine";
631
+ return indent + "TraceHooks." + hook + "(" + sourceLine + ", " + quote(name) + ", " + name + ", " + key + ", " + value + ", " + keySource + ");";
632
+ }
633
+ }
634
+ if ("set".equals(method) && isListType(frame.typeOf(name))) {
635
+ java.util.List<String> parts = splitTopLevel(mutatingCall.group(4).trim());
636
+ if (parts.size() >= 2) {
637
+ String index = rewriteReads(parts.get(0), sourceLine, frame);
638
+ String value = rewriteReads(parts.get(1), sourceLine, frame);
639
+ return indent + "TraceHooks.writeListAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ", " + index + ", " + value + ", " + indexSourceArgument(parts.get(0)) + ");";
640
+ }
641
+ }
642
+ if (frame.isField(name)) {
643
+ String pathPrefix = "\\\"target\\\":{\\\"variable\\\":\\\"" + name + "\\\"}";
644
+ String readEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"read\\\",\\\"line\\\":" + sourceLine + "," +
645
+ pathPrefix + ",\\\"value\\\":\" + TraceHooks.serializeResult(" + name + ") + \"}\");";
646
+ MutatingArgs rewrittenArgs = mutatingArgs(rawArgs, sourceLine, frame);
647
+ String mutateEvent = "TraceHooks.emit(\"trace:{\\\"kind\\\":\\\"mutate\\\",\\\"line\\\":" + sourceLine + "," +
648
+ pathPrefix + ",\\\"method\\\":\\\"" + method + "\\\"" + rewrittenArgs.eventSegment + "}\");";
649
+ String snapshotEvent = "TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
650
+ return indent + "{ " + readEvent + " " + rewrittenArgs.prefix + name + "." + method + "(" + rewrittenArgs.callArgs + "); " + mutateEvent + " " + snapshotEvent + " }";
651
+ }
652
+ String mutateHook = rawArgs.isEmpty()
653
+ ? "TraceHooks.emitNoArgMutatingCallAtLine(" + sourceLine + ", " + quote(name) + ", " + quote(method) + ")"
654
+ : "TraceHooks.emitMutatingCallAtLine(" + sourceLine + ", " + quote(name) + ", " + quote(method) + ", " + args + ")";
655
+ return indent + name + "." + method + "(" + args + "); " + mutateHook + "; TraceHooks.emitRuntimeSnapshotAtLine(" + sourceLine + ", " + quote(name) + ", " + name + ");";
656
+ }
657
+
658
+ return rewriteReads(line, sourceLine, frame);
659
+ }
660
+
661
+ private static boolean emitsPostLineState(String trimmed, MethodFrame frame) {
662
+ if (trimmed.startsWith("for ")) return false;
663
+ Matcher declaration = LOCAL_DECLARATION.matcher(trimmed);
664
+ if (declaration.matches() && !isControlKeyword(declaration.group(2).trim())) return true;
665
+ Matcher assignment = LOCAL_ASSIGNMENT.matcher(trimmed);
666
+ if (assignment.matches() && frame.variables.containsKey(assignment.group(2))) return true;
667
+ Matcher compoundAssignment = LOCAL_COMPOUND_ASSIGNMENT.matcher(trimmed);
668
+ if (compoundAssignment.matches() && frame.variables.containsKey(compoundAssignment.group(2))) return true;
669
+ Matcher localUpdate = LOCAL_UPDATE.matcher(trimmed);
670
+ return localUpdate.matches() && (localUpdate.group(2) != null || localUpdate.group(4) != null) && frame.variables.containsKey(localUpdate.group(3));
671
+ }
672
+
673
+ private static String rewriteInlineControlStatement(String line, int sourceLine, MethodFrame frame) {
674
+ String trimmed = line.trim();
675
+ if (trimmed.startsWith("if ") || trimmed.startsWith("if(")) {
676
+ return rewriteInlineIfStatement(line, sourceLine, frame);
677
+ }
678
+ if (trimmed.startsWith("else ") && !trimmed.startsWith("else if ") && !trimmed.startsWith("else if(")) {
679
+ String indent = indentOf(line);
680
+ String body = stripTrailingLineComment(trimmed.substring("else".length()).trim()).trim();
681
+ if (body.isEmpty() || body.startsWith("{") || !body.endsWith(";")) {
682
+ return null;
683
+ }
684
+ return indent + "else {\n" +
685
+ indent + " TraceHooks.emitLineAtLine(" + sourceLine + ");\n" +
686
+ rewriteBranchStatement(indent + " ", body, sourceLine, frame) + "\n" +
687
+ indent + "}";
688
+ }
689
+ return null;
690
+ }
691
+
692
+ private static String rewriteInlineIfStatement(String line, int sourceLine, MethodFrame frame) {
693
+ String indent = indentOf(line);
694
+ int keyword = firstNonWhitespace(line);
695
+ int openParen = line.indexOf('(', keyword + 2);
696
+ if (openParen < 0) return null;
697
+ int closeParen = findMatchingParen(line, openParen);
698
+ if (closeParen < 0) return null;
699
+ String rest = stripTrailingLineComment(line.substring(closeParen + 1)).trim();
700
+ if (rest.isEmpty() || rest.startsWith("{") || !rest.endsWith(";")) {
701
+ return null;
702
+ }
703
+ int elseIndex = findTopLevelElse(rest);
704
+ String thenBody = elseIndex >= 0 ? rest.substring(0, elseIndex).trim() : rest;
705
+ if (thenBody.isEmpty() || !thenBody.endsWith(";")) {
706
+ return null;
707
+ }
708
+ String condition = rewriteReads(line.substring(openParen + 1, closeParen).trim(), sourceLine, frame);
709
+ StringBuilder out = new StringBuilder();
710
+ out.append(indent).append("if (").append(condition).append(") {\n")
711
+ .append(rewriteBranchStatement(indent + " ", thenBody, sourceLine, frame)).append('\n')
712
+ .append(indent).append("}");
713
+ if (elseIndex >= 0) {
714
+ String elseBody = rest.substring(elseIndex + "else".length()).trim();
715
+ if (elseBody.isEmpty() || elseBody.startsWith("{") || !elseBody.endsWith(";")) {
716
+ return null;
717
+ }
718
+ out.append(" else {\n")
719
+ .append(rewriteBranchStatement(indent + " ", elseBody, sourceLine, frame)).append('\n')
720
+ .append(indent).append("}");
721
+ }
722
+ return out.toString();
723
+ }
724
+
725
+ private static String rewriteBranchStatement(String indent, String statement, int sourceLine, MethodFrame frame) {
726
+ String rewritten = rewriteStatement(indent + stripTrailingLineComment(statement).trim(), sourceLine, frame);
727
+ return stripLeadingLineHook(rewritten, indent, sourceLine);
728
+ }
729
+
730
+ private static String stripLeadingLineHook(String rewritten, String indent, int sourceLine) {
731
+ String hook = indent + "TraceHooks.emitLineAtLine(" + sourceLine + ");\n";
732
+ if (rewritten.startsWith(hook)) {
733
+ return rewritten.substring(hook.length());
734
+ }
735
+ return rewritten;
736
+ }
737
+
738
+ private static String rewriteReads(String source, int line, MethodFrame frame) {
739
+ String next = replaceAll(STRING_ARRAY_CHAR_AT, source, match -> {
740
+ String name = match.group(1);
741
+ if (!isStringArrayType(frame.typeOf(name))) return match.group(0);
742
+ String row = match.group(2).trim();
743
+ String col = match.group(3).trim();
744
+ return "TraceHooks.readStringMatrixCharAtLine(" + line + ", " + quote(name) + ", " + name + ", " + row + ", " + col + ", " + indexSourceArgument(row) + ", " + indexSourceArgument(col) + ")";
745
+ });
746
+ next = replaceAll(STRING_ARRAY_LENGTH_CALL, next, match -> {
747
+ String name = match.group(1);
748
+ if (!isStringArrayType(frame.typeOf(name))) return match.group(0);
749
+ String index = match.group(2).trim();
750
+ return "TraceHooks.readIndexedStringLengthAtLine(" + line + ", " + quote(name) + ", " + name + ", " + index + ", " + indexSourceArgument(index) + ")";
751
+ });
752
+ next = replaceAll(STRING_CHAR_AT, next, match -> {
753
+ String index = match.group(2).trim();
754
+ return "TraceHooks.readStringCharAtLine(" + line + ", " + quote(match.group(1)) + ", " + match.group(1) + ", " + index + ", " + indexSourceArgument(index) + ")";
755
+ });
756
+ next = replaceAll(QUEUE_REMOVE_CALL, next, match -> {
757
+ String name = match.group(1);
758
+ if (!isQueueLikeType(frame.typeOf(name))) return match.group(0);
759
+ String method = match.group(2);
760
+ String hook = "poll".equals(method) ? "pollQueueAtLine" : "removeQueueAtLine";
761
+ return "TraceHooks." + hook + "(" + line + ", " + quote(name) + ", " + name + ")";
762
+ });
763
+ next = replaceAll(QUEUE_PEEK_CALL, next, match -> {
764
+ String name = match.group(1);
765
+ if (!isQueueLikeType(frame.typeOf(name))) return match.group(0);
766
+ return "TraceHooks.readQueuePeekAtLine(" + line + ", " + quote(name) + ", " + name + ")";
767
+ });
768
+ next = replaceAll(LIST_ARRAY_READ, next, match -> {
769
+ String name = match.group(1);
770
+ String helper = listArrayReadHelper(frame.typeOf(name));
771
+ if (helper == null) return match.group(0);
772
+ String row = match.group(2).trim();
773
+ String col = match.group(3).trim();
774
+ return "TraceHooks." + helper + "(" + line + ", " + quote(name) + ", " + name + ", " + row + ", " + col + ", " + indexSourceArgument(row) + ", " + indexSourceArgument(col) + ")";
775
+ });
776
+ next = replaceAll(THIS_FIELD_MAP_CONTAINS_KEY_CALL, next, match -> {
777
+ String field = match.group(1);
778
+ if (!isMapType(frame.typeOf(field))) return match.group(0);
779
+ String key = match.group(2).trim();
780
+ return "TraceHooks.containsFieldMapKeyAtLine(" + line + ", \"this\", " + quote(field) + ", this." + field + ", " + key + ", " + indexSourceArgument(key) + ")";
781
+ });
782
+ next = replaceAll(THIS_FIELD_MAP_GET_OR_DEFAULT_CALL, next, match -> {
783
+ String field = match.group(1);
784
+ if (!isMapType(frame.typeOf(field))) return match.group(0);
785
+ java.util.List<String> args = splitTopLevel(match.group(2).trim());
786
+ if (args.size() != 2) return match.group(0);
787
+ return "TraceHooks.readFieldMapOrDefaultAtLine(" + line + ", \"this\", " + quote(field) + ", this." + field + ", " + args.get(0) + ", " + args.get(1) + ", " + indexSourceArgument(args.get(0)) + ")";
788
+ });
789
+ next = replaceAll(THIS_FIELD_MAP_GET_CALL, next, match -> {
790
+ String field = match.group(1);
791
+ if (!isMapType(frame.typeOf(field))) return match.group(0);
792
+ String key = match.group(2).trim();
793
+ return "TraceHooks.readFieldMapAtLine(" + line + ", \"this\", " + quote(field) + ", this." + field + ", " + key + ", " + indexSourceArgument(key) + ")";
794
+ });
795
+ next = replaceAll(OBJECT_FIELD_MAP_CONTAINS_KEY_CALL, next, match -> {
796
+ String name = match.group(1);
797
+ String field = match.group(2);
798
+ if (!isMapType(frame.typeOf(field))) return match.group(0);
799
+ String key = match.group(3).trim();
800
+ return "TraceHooks.containsFieldMapKeyAtLine(" + line + ", " + quote(name) + ", " + quote(field) + ", " + name + "." + field + ", " + key + ", " + indexSourceArgument(key) + ")";
801
+ });
802
+ next = replaceAll(OBJECT_FIELD_MAP_GET_OR_DEFAULT_CALL, next, match -> {
803
+ String name = match.group(1);
804
+ String field = match.group(2);
805
+ if (!isMapType(frame.typeOf(field))) return match.group(0);
806
+ java.util.List<String> args = splitTopLevel(match.group(3).trim());
807
+ if (args.size() != 2) return match.group(0);
808
+ return "TraceHooks.readFieldMapOrDefaultAtLine(" + line + ", " + quote(name) + ", " + quote(field) + ", " + name + "." + field + ", " + args.get(0) + ", " + args.get(1) + ", " + indexSourceArgument(args.get(0)) + ")";
809
+ });
810
+ next = replaceAll(OBJECT_FIELD_MAP_GET_CALL, next, match -> {
811
+ String name = match.group(1);
812
+ String field = match.group(2);
813
+ if (!isMapType(frame.typeOf(field))) return match.group(0);
814
+ String key = match.group(3).trim();
815
+ return "TraceHooks.readFieldMapAtLine(" + line + ", " + quote(name) + ", " + quote(field) + ", " + name + "." + field + ", " + key + ", " + indexSourceArgument(key) + ")";
816
+ });
817
+ next = replaceAll(MAP_CONTAINS_KEY_CALL, next, match -> {
818
+ String name = match.group(1);
819
+ if (!isMapType(frame.typeOf(name))) return match.group(0);
820
+ if (frame.isField(name)) {
821
+ String key = match.group(2).trim();
822
+ return "TraceHooks.containsFieldMapKeyAtLine(" + line + ", \"this\", " + quote(name) + ", " + name + ", " + key + ", " + indexSourceArgument(key) + ")";
823
+ }
824
+ String key = match.group(2).trim();
825
+ return "TraceHooks.containsMapKeyAtLine(" + line + ", " + quote(name) + ", " + name + ", " + key + ", " + indexSourceArgument(key) + ")";
826
+ });
827
+ next = replaceAll(COLLECTION_CONTAINS_CALL, next, match -> {
828
+ String name = match.group(1);
829
+ if (!isSetType(frame.typeOf(name))) return match.group(0);
830
+ String key = match.group(2).trim();
831
+ return "TraceHooks.readSetAtLine(" + line + ", " + quote(name) + ", " + name + ", " + key + ", " + indexSourceArgument(key) + ")";
832
+ });
833
+ next = replaceAll(MAP_GET_OR_DEFAULT_CALL, next, match -> {
834
+ String name = match.group(1);
835
+ if (!isMapType(frame.typeOf(name))) return match.group(0);
836
+ java.util.List<String> args = splitTopLevel(match.group(2).trim());
837
+ if (args.size() != 2) return match.group(0);
838
+ if (frame.isField(name)) {
839
+ return "TraceHooks.readFieldMapOrDefaultAtLine(" + line + ", \"this\", " + quote(name) + ", " + name + ", " + args.get(0) + ", " + args.get(1) + ", " + indexSourceArgument(args.get(0)) + ")";
840
+ }
841
+ return "TraceHooks.readMapOrDefaultAtLine(" + line + ", " + quote(name) + ", " + name + ", " + args.get(0) + ", " + args.get(1) + ", " + indexSourceArgument(args.get(0)) + ")";
842
+ });
843
+ next = replaceAll(MAP_GET_CALL, next, match -> {
844
+ String name = match.group(1);
845
+ String receiverType = frame.typeOf(name);
846
+ if (isMapType(receiverType)) {
847
+ if (frame.isField(name)) {
848
+ String key = match.group(2).trim();
849
+ return "TraceHooks.readFieldMapAtLine(" + line + ", \"this\", " + quote(name) + ", " + name + ", " + key + ", " + indexSourceArgument(key) + ")";
850
+ }
851
+ String key = match.group(2).trim();
852
+ return "TraceHooks.readMapAtLine(" + line + ", " + quote(name) + ", " + name + ", " + key + ", " + indexSourceArgument(key) + ")";
853
+ }
854
+ if (isListType(receiverType)) {
855
+ String index = match.group(2).trim();
856
+ return "TraceHooks.readListAtLine(" + line + ", " + quote(name) + ", " + name + ", " + index + ", " + indexSourceArgument(index) + ")";
857
+ }
858
+ return match.group(0);
859
+ });
860
+ final String matrixReadSource = next;
861
+ next = replaceAll(MATRIX_READ, matrixReadSource, match -> {
862
+ String full = match.group(0);
863
+ if (full.contains("TraceHooks.")) return full;
864
+ String name = match.group(1);
865
+ if (isArrayAllocationTypeMatch(matrixReadSource, match.start())) return full;
866
+ if (isArrayWriteTarget(matrixReadSource, match.start(), match.end())) return full;
867
+ if (nextNonWhitespace(matrixReadSource, match.end()) == '[') return full;
868
+ String helper = matrixReadHelper(frame.typeOf(name));
869
+ if (helper == null) return full;
870
+ String row = match.group(2).trim();
871
+ String col = match.group(3).trim();
872
+ return "TraceHooks." + helper + "(" + line + ", " + quote(name) + ", " + name + ", " + row + ", " + col + ", " + indexSourceArgument(row) + ", " + indexSourceArgument(col) + ")";
873
+ });
874
+ final String arrayReadSource = next;
875
+ next = replaceAll(ARRAY_READ, next, match -> {
876
+ String full = match.group(0);
877
+ if (full.contains("TraceHooks.")) return full;
878
+ if (isArrayAllocationTypeMatch(arrayReadSource, match.start())) return full;
879
+ if (isArrayWriteTarget(arrayReadSource, match.start(), match.end())) return full;
880
+ if (nextNonWhitespace(arrayReadSource, match.end()) == '[') return full;
881
+ String name = match.group(1);
882
+ String helper = arrayReadHelper(frame.typeOf(name));
883
+ if (helper == null) return full;
884
+ String index = match.group(2).trim();
885
+ return "TraceHooks." + helper + "(" + line + ", " + quote(name) + ", " + name + ", " + index + ", " + indexSourceArgument(index) + ")";
886
+ });
887
+ final String fieldReadSource = next;
888
+ next = replaceAll(FIELD_READ, fieldReadSource, match -> {
889
+ String full = match.group(0);
890
+ if (full.contains("TraceHooks.")) return full;
891
+ if (isInsideTraceHooksCall(fieldReadSource, match.start())) return full;
892
+ if (isArrayWriteTarget(fieldReadSource, match.start(), match.end())) return full;
893
+ String name = match.group(1);
894
+ String field = match.group(2);
895
+ if ("java".equals(name) || Character.isUpperCase(name.charAt(0)) || "out".equals(field) || "err".equals(field) || "length".equals(field)) return full;
896
+ return "TraceHooks.readObjectFieldAtLine(" + line + ", " + quote(name) + ", " + quote(field) + ", " + name + "." + field + ")";
897
+ });
898
+ return next;
899
+ }
900
+
901
+ private static void registerFieldDeclaration(Map<String, String> fields, String line) {
902
+ Matcher field = FIELD_DECLARATION.matcher(stripTrailingLineComment(line));
903
+ if (field.matches()) {
904
+ fields.put(field.group(2), normalizeJavaType(field.group(1)));
905
+ }
906
+ }
907
+
908
+ private static String stripTrailingLineComment(String line) {
909
+ boolean inString = false;
910
+ boolean inChar = false;
911
+ boolean escaped = false;
912
+ for (int index = 0; index < line.length() - 1; index++) {
913
+ char ch = line.charAt(index);
914
+ if (escaped) {
915
+ escaped = false;
916
+ continue;
917
+ }
918
+ if (ch == '\\') {
919
+ escaped = inString || inChar;
920
+ continue;
921
+ }
922
+ if (inString) {
923
+ if (ch == '"') inString = false;
924
+ continue;
925
+ }
926
+ if (inChar) {
927
+ if (ch == '\'') inChar = false;
928
+ continue;
929
+ }
930
+ if (ch == '"') {
931
+ inString = true;
932
+ continue;
933
+ }
934
+ if (ch == '\'') {
935
+ inChar = true;
936
+ continue;
937
+ }
938
+ if (ch == '/' && line.charAt(index + 1) == '/') {
939
+ return line.substring(0, index).replaceAll("\\s+$", "");
940
+ }
941
+ }
942
+ return line;
943
+ }
944
+
945
+ private static boolean startsMultilineInitializer(String trimmed) {
946
+ return trimmed.contains("{") && !trimmed.contains(";") &&
947
+ !trimmed.startsWith("if ") && !trimmed.startsWith("for ") && !trimmed.startsWith("while ") &&
948
+ !trimmed.startsWith("switch ") && !trimmed.startsWith("try") && !trimmed.startsWith("catch") &&
949
+ !trimmed.startsWith("finally") && !trimmed.startsWith("else") && !trimmed.startsWith("do ");
950
+ }
951
+
952
+ private static void registerMultilineLocalDeclaration(MethodFrame frame, String trimmed) {
953
+ int equalsIndex = trimmed.indexOf('=');
954
+ if (equalsIndex <= 0) return;
955
+ String beforeEquals = trimmed.substring(0, equalsIndex).trim();
956
+ String[] parts = beforeEquals.split("\\s+");
957
+ if (parts.length < 2) return;
958
+ String name = parts[parts.length - 1];
959
+ if (!name.matches("[A-Za-z_][A-Za-z0-9_]*")) return;
960
+ String type = beforeEquals.substring(0, beforeEquals.length() - name.length()).trim();
961
+ if (type.startsWith("final ")) type = type.substring("final ".length()).trim();
962
+ if (type.isEmpty() || isControlKeyword(type)) return;
963
+ registerLocalDeclarators(frame, type, name);
964
+ }
965
+
966
+ private static boolean startsMultilineControlHeader(String trimmed) {
967
+ if (!(trimmed.startsWith("if ") || trimmed.startsWith("if(") ||
968
+ trimmed.startsWith("while ") || trimmed.startsWith("while(") ||
969
+ trimmed.startsWith("for ") || trimmed.startsWith("for(") ||
970
+ trimmed.startsWith("switch ") || trimmed.startsWith("switch("))) {
971
+ return false;
972
+ }
973
+ return parenDelta(trimmed) > 0;
974
+ }
975
+
976
+ private static boolean startsUnbracedControlHeader(String trimmed) {
977
+ if (trimmed.contains("{") || trimmed.endsWith(";")) return false;
978
+ if (startsMultilineControlHeader(trimmed)) return false;
979
+ return trimmed.startsWith("if ") || trimmed.startsWith("if(") ||
980
+ trimmed.startsWith("while ") || trimmed.startsWith("while(") ||
981
+ trimmed.startsWith("for ") || trimmed.startsWith("for(") ||
982
+ trimmed.startsWith("else if ") || trimmed.startsWith("else if(") ||
983
+ trimmed.equals("else") ||
984
+ trimmed.startsWith("else ");
985
+ }
986
+
987
+ private static boolean endsWithExpressionContinuation(String trimmed) {
988
+ if (trimmed.isEmpty()) return false;
989
+ return trimmed.endsWith("||") || trimmed.endsWith("&&") ||
990
+ trimmed.endsWith("+") || trimmed.endsWith("-") || trimmed.endsWith("*") ||
991
+ trimmed.endsWith("/") || trimmed.endsWith("%") || trimmed.endsWith("?") ||
992
+ trimmed.endsWith(":") || trimmed.endsWith(",") ||
993
+ trimmed.endsWith("(") || trimmed.endsWith("[");
994
+ }
995
+
996
+ private static void updateExpressionContinuation(MethodFrame frame, String trimmed) {
997
+ if (trimmed.isEmpty() || trimmed.startsWith("//") || trimmed.startsWith("@")) {
998
+ return;
999
+ }
1000
+ int nextParenDepth = Math.max(0, frame.expressionParenDepth + parenDelta(trimmed));
1001
+ boolean startsStatementContinuation = !trimmed.endsWith(";") &&
1002
+ !trimmed.endsWith("{") &&
1003
+ !trimmed.endsWith("}") &&
1004
+ !startsMultilineControlHeader(trimmed) &&
1005
+ !trimmed.startsWith("if ") && !trimmed.startsWith("if(") &&
1006
+ !trimmed.startsWith("while ") && !trimmed.startsWith("while(") &&
1007
+ !trimmed.startsWith("for ") && !trimmed.startsWith("for(") &&
1008
+ !trimmed.startsWith("switch ") && !trimmed.startsWith("switch(") &&
1009
+ !trimmed.startsWith("else") &&
1010
+ !trimmed.startsWith("catch") &&
1011
+ !trimmed.startsWith("finally");
1012
+ frame.expressionParenDepth = nextParenDepth;
1013
+ frame.statementContinuation = nextParenDepth > 0 || (startsStatementContinuation && frame.depth > 0);
1014
+ }
1015
+
1016
+ private static boolean isArrayAllocationTypeMatch(String source, int matchStart) {
1017
+ String prefix = source.substring(0, matchStart).replaceAll("\\s+$", "");
1018
+ return prefix.matches("(?s).*\\bnew$");
1019
+ }
1020
+
1021
+ private static boolean isArrayWriteTarget(String source, int start, int end) {
1022
+ String before = source.substring(0, start).replaceAll("\\s+$", "");
1023
+ if (before.endsWith("++") || before.endsWith("--")) return true;
1024
+ String after = source.substring(end).replaceAll("^\\s+", "");
1025
+ if (after.startsWith("++") || after.startsWith("--")) return true;
1026
+ if (after.startsWith("=") && !after.startsWith("==")) return true;
1027
+ if (after.length() >= 2 && "+-*/%&|^".indexOf(after.charAt(0)) >= 0 && after.charAt(1) == '=') return true;
1028
+ return false;
1029
+ }
1030
+
1031
+ private static boolean hasIndexSideEffect(String source) {
1032
+ if (source.contains("++") || source.contains("--")) return true;
1033
+ Matcher call = Pattern.compile("\\.([A-Za-z_][A-Za-z0-9_]*)\\s*\\(").matcher(source);
1034
+ while (call.find()) {
1035
+ if (isTrackedMutationMethod(call.group(1))) return true;
1036
+ }
1037
+ return false;
1038
+ }
1039
+
1040
+ private static char nextNonWhitespace(String source, int start) {
1041
+ int index = start;
1042
+ while (index < source.length() && Character.isWhitespace(source.charAt(index))) index++;
1043
+ return index < source.length() ? source.charAt(index) : '\0';
1044
+ }
1045
+
1046
+ private static String arrayReadHelper(String type) {
1047
+ if (type == null) return null;
1048
+ String normalized = normalizeJavaType(type);
1049
+ if (!normalized.endsWith("[]")) return null;
1050
+ String element = normalized.substring(0, normalized.length() - 2).trim();
1051
+ if (element.endsWith("[]")) return "readObjectArrayAtLine";
1052
+ if ("int".equals(element)) return "readIntArrayAtLine";
1053
+ if ("boolean".equals(element)) return "readBooleanArrayAtLine";
1054
+ if ("long".equals(element)) return "readLongArrayAtLine";
1055
+ if ("double".equals(element)) return "readDoubleArrayAtLine";
1056
+ if ("float".equals(element)) return "readFloatArrayAtLine";
1057
+ if ("char".equals(element)) return "readCharArrayAtLine";
1058
+ if ("byte".equals(element)) return "readByteArrayAtLine";
1059
+ if ("short".equals(element)) return "readShortArrayAtLine";
1060
+ return "readObjectArrayAtLine";
1061
+ }
1062
+
1063
+ private static String matrixReadHelper(String type) {
1064
+ if (type == null) return null;
1065
+ String normalized = normalizeJavaType(type);
1066
+ if (!normalized.endsWith("[][]")) return null;
1067
+ String element = normalized.substring(0, normalized.length() - 4).trim();
1068
+ if ("int".equals(element)) return "readIntMatrixAtLine";
1069
+ if ("boolean".equals(element)) return "readBooleanMatrixAtLine";
1070
+ if ("long".equals(element)) return "readLongMatrixAtLine";
1071
+ if ("double".equals(element)) return "readDoubleMatrixAtLine";
1072
+ if ("float".equals(element)) return "readFloatMatrixAtLine";
1073
+ if ("char".equals(element)) return "readCharMatrixAtLine";
1074
+ if ("byte".equals(element)) return "readByteMatrixAtLine";
1075
+ if ("short".equals(element)) return "readShortMatrixAtLine";
1076
+ return "readObjectMatrixAtLine";
1077
+ }
1078
+
1079
+ private static String listArrayReadHelper(String type) {
1080
+ if (type == null) return null;
1081
+ String normalized = normalizeJavaType(type);
1082
+ if (!normalized.contains("List<") || !normalized.contains("[]")) return null;
1083
+ if (normalized.contains("int[]")) return "readIntArrayListAtLine";
1084
+ if (normalized.contains("long[]")) return "readLongArrayListAtLine";
1085
+ if (normalized.contains("char[]")) return "readCharArrayListAtLine";
1086
+ if (normalized.contains("boolean[]")) return "readBooleanArrayListAtLine";
1087
+ if (normalized.contains("double[]")) return "readDoubleArrayListAtLine";
1088
+ if (normalized.contains("float[]")) return "readFloatArrayListAtLine";
1089
+ if (normalized.contains("byte[]")) return "readByteArrayListAtLine";
1090
+ if (normalized.contains("short[]")) return "readShortArrayListAtLine";
1091
+ return "readObjectArrayListAtLine";
1092
+ }
1093
+
1094
+ private static boolean isStringArrayType(String type) {
1095
+ return "String[]".equals(type == null ? null : normalizeJavaType(type));
1096
+ }
1097
+
1098
+ private static boolean isArrayOfMapType(String type) {
1099
+ if (type == null) return false;
1100
+ String normalized = normalizeJavaType(type);
1101
+ return normalized.endsWith("[]") && normalized.contains("Map");
1102
+ }
1103
+
1104
+ private static boolean isMapType(String type) {
1105
+ if (type == null) return false;
1106
+ return normalizeJavaType(type).contains("Map");
1107
+ }
1108
+
1109
+ private static boolean isSetType(String type) {
1110
+ if (type == null) return false;
1111
+ return normalizeJavaType(type).contains("Set<");
1112
+ }
1113
+
1114
+ private static boolean isListType(String type) {
1115
+ if (type == null) return false;
1116
+ String normalized = normalizeJavaType(type);
1117
+ return normalized.contains("List<") && !normalized.contains("Map");
1118
+ }
1119
+
1120
+ private static boolean isQueueLikeType(String type) {
1121
+ if (type == null) return false;
1122
+ String normalized = normalizeJavaType(type);
1123
+ return normalized.contains("Queue<") || normalized.contains("Deque<") || normalized.contains("PriorityQueue<");
1124
+ }
1125
+
1126
+ private static String indexedAccessExpression(String name, String type, String index) {
1127
+ String normalized = type == null ? "" : normalizeJavaType(type);
1128
+ if (normalized.contains("Map")) {
1129
+ return "((" + indexedValueCastType(normalized, "java.util.Map") + ")((java.util.Map)" + name + ").get(" + index + "))";
1130
+ }
1131
+ return "((" + indexedValueCastType(normalized, "java.util.List") + ")((java.util.List)" + name + ").get(" + index + "))";
1132
+ }
1133
+
1134
+ private static String indexedValueCastType(String normalizedType, String fallback) {
1135
+ if (normalizedType.contains("Deque<")) return "java.util.Deque";
1136
+ if (normalizedType.contains("Queue<")) return "java.util.Queue";
1137
+ if (normalizedType.contains("Set<")) return "java.util.Set";
1138
+ if (normalizedType.contains("Collection<")) return "java.util.Collection";
1139
+ if (normalizedType.contains("List<")) return "java.util.List";
1140
+ return fallback;
1141
+ }
1142
+
1143
+ private static String normalizeJavaType(String type) {
1144
+ return type.trim().replaceAll("\\s+", " ").replaceAll("\\s*\\[\\s*\\]", "[]");
1145
+ }
1146
+
1147
+ private static java.util.List<String> registerLocalDeclarators(
1148
+ MethodFrame frame,
1149
+ String type,
1150
+ String declaratorsSource
1151
+ ) {
1152
+ java.util.List<String> names = new java.util.ArrayList<>();
1153
+ String normalizedType = normalizeJavaType(type);
1154
+ for (String declarator : splitTopLevel(declaratorsSource)) {
1155
+ String name = declaratorName(declarator);
1156
+ if (name == null) continue;
1157
+ frame.variables.put(name, normalizedType);
1158
+ names.add(name);
1159
+ }
1160
+ return names;
1161
+ }
1162
+
1163
+ private static String declaratorName(String declarator) {
1164
+ int assignment = declarator.indexOf('=');
1165
+ String left = assignment >= 0 ? declarator.substring(0, assignment).trim() : declarator.trim();
1166
+ Matcher name = Pattern.compile("([A-Za-z_][A-Za-z0-9_]*)\\s*(?:\\[\\s*\\])*\\s*$").matcher(left);
1167
+ return name.find() ? name.group(1) : null;
1168
+ }
1169
+
1170
+ private static void registerParameters(Map<String, String> variables, String parametersSource) {
1171
+ if (parametersSource == null || parametersSource.trim().isEmpty()) return;
1172
+ for (String parameter : splitTopLevel(parametersSource)) {
1173
+ String cleaned = parameter.replaceAll("@\\w+(?:\\([^)]*\\))?", "").replaceAll("\\bfinal\\b", "").trim();
1174
+ Matcher name = Pattern.compile("([A-Za-z_][A-Za-z0-9_]*)\\s*(?:\\.\\.\\.)?$").matcher(cleaned);
1175
+ if (!name.find()) continue;
1176
+ String paramName = name.group(1);
1177
+ String type = cleaned.substring(0, name.start()).trim();
1178
+ if (cleaned.endsWith("...")) type += "[]";
1179
+ if (!type.isEmpty()) variables.put(paramName, normalizeJavaType(type));
1180
+ }
1181
+ }
1182
+
1183
+ private static java.util.List<String> splitTopLevel(String source) {
1184
+ java.util.List<String> parts = new java.util.ArrayList<>();
1185
+ int start = 0;
1186
+ int angleDepth = 0;
1187
+ int parenDepth = 0;
1188
+ int bracketDepth = 0;
1189
+ int braceDepth = 0;
1190
+ boolean inString = false;
1191
+ boolean inChar = false;
1192
+ boolean escaped = false;
1193
+ for (int index = 0; index < source.length(); index++) {
1194
+ char ch = source.charAt(index);
1195
+ if (escaped) {
1196
+ escaped = false;
1197
+ continue;
1198
+ }
1199
+ if (ch == '\\') {
1200
+ escaped = inString || inChar;
1201
+ continue;
1202
+ }
1203
+ if (inString) {
1204
+ if (ch == '"') inString = false;
1205
+ continue;
1206
+ }
1207
+ if (inChar) {
1208
+ if (ch == '\'') inChar = false;
1209
+ continue;
1210
+ }
1211
+ if (ch == '"') {
1212
+ inString = true;
1213
+ continue;
1214
+ }
1215
+ if (ch == '\'') {
1216
+ inChar = true;
1217
+ continue;
1218
+ }
1219
+ if (ch == '<') angleDepth++;
1220
+ if (ch == '>') angleDepth = Math.max(0, angleDepth - 1);
1221
+ if (ch == '(') parenDepth++;
1222
+ if (ch == ')') parenDepth = Math.max(0, parenDepth - 1);
1223
+ if (ch == '[') bracketDepth++;
1224
+ if (ch == ']') bracketDepth = Math.max(0, bracketDepth - 1);
1225
+ if (ch == '{') braceDepth++;
1226
+ if (ch == '}') braceDepth = Math.max(0, braceDepth - 1);
1227
+ if (ch == ',' && angleDepth == 0 && parenDepth == 0 && bracketDepth == 0 && braceDepth == 0) {
1228
+ parts.add(source.substring(start, index).trim());
1229
+ start = index + 1;
1230
+ }
1231
+ }
1232
+ String tail = source.substring(start).trim();
1233
+ if (!tail.isEmpty()) parts.add(tail);
1234
+ return parts;
1235
+ }
1236
+
1237
+ private static String replaceAll(Pattern pattern, String source, Replacer replacer) {
1238
+ Matcher matcher = pattern.matcher(source);
1239
+ StringBuffer out = new StringBuffer();
1240
+ while (matcher.find()) {
1241
+ if (isInsideJavaLiteral(source, matcher.start())) {
1242
+ matcher.appendReplacement(out, Matcher.quoteReplacement(matcher.group(0)));
1243
+ continue;
1244
+ }
1245
+ matcher.appendReplacement(out, Matcher.quoteReplacement(replacer.replace(matcher)));
1246
+ }
1247
+ matcher.appendTail(out);
1248
+ return out.toString();
1249
+ }
1250
+
1251
+ private static boolean isInsideJavaLiteral(String source, int offset) {
1252
+ boolean inString = false;
1253
+ boolean inChar = false;
1254
+ boolean escaped = false;
1255
+ for (int index = 0; index < offset; index++) {
1256
+ char ch = source.charAt(index);
1257
+ if (escaped) {
1258
+ escaped = false;
1259
+ continue;
1260
+ }
1261
+ if (ch == '\\') {
1262
+ escaped = inString || inChar;
1263
+ continue;
1264
+ }
1265
+ if (inString) {
1266
+ if (ch == '"') inString = false;
1267
+ continue;
1268
+ }
1269
+ if (inChar) {
1270
+ if (ch == '\'') inChar = false;
1271
+ continue;
1272
+ }
1273
+ if (ch == '"') {
1274
+ inString = true;
1275
+ continue;
1276
+ }
1277
+ if (ch == '\'') {
1278
+ inChar = true;
1279
+ }
1280
+ }
1281
+ return inString || inChar;
1282
+ }
1283
+
1284
+ private static boolean isInsideTraceHooksCall(String source, int offset) {
1285
+ int marker = source.lastIndexOf("TraceHooks.", offset);
1286
+ if (marker < 0) return false;
1287
+ int delimiter = Math.max(source.lastIndexOf(';', offset), source.lastIndexOf('\n', offset));
1288
+ return marker > delimiter;
1289
+ }
1290
+
1291
+ private static boolean shouldEmitLine(String trimmed) {
1292
+ if (trimmed.isEmpty()) return false;
1293
+ if (trimmed.startsWith("//") || trimmed.startsWith("/*") || trimmed.startsWith("*")) return false;
1294
+ if (trimmed.startsWith("{") || trimmed.equals("}")) return false;
1295
+ if (trimmed.startsWith("}")) return false;
1296
+ if (trimmed.startsWith(".")) return false;
1297
+ if (trimmed.startsWith("case ") || trimmed.startsWith("default:")) return false;
1298
+ if (trimmed.startsWith("?") || trimmed.startsWith(":")) return false;
1299
+ if (trimmed.startsWith("&&") || trimmed.startsWith("||")) return false;
1300
+ if (trimmed.startsWith("else")) return false;
1301
+ if (trimmed.startsWith("catch") || trimmed.startsWith("finally")) return false;
1302
+ return true;
1303
+ }
1304
+
1305
+ private static boolean isScalarSnapshotType(String type) {
1306
+ return "boolean".equals(type) || "byte".equals(type) || "char".equals(type) || "short".equals(type) ||
1307
+ "int".equals(type) || "long".equals(type) || "float".equals(type) || "double".equals(type) || "String".equals(type);
1308
+ }
1309
+
1310
+ private static boolean isTrackedMutationMethod(String method) {
1311
+ return "add".equals(method) || "push".equals(method) || "offer".equals(method) ||
1312
+ "addAll".equals(method) ||
1313
+ "addLast".equals(method) || "offerLast".equals(method) || "put".equals(method) || "putIfAbsent".equals(method) ||
1314
+ "addFirst".equals(method) || "offerFirst".equals(method) ||
1315
+ "remove".equals(method) || "clear".equals(method) || "poll".equals(method) ||
1316
+ "pollFirst".equals(method) || "removeFirst".equals(method) || "set".equals(method) ||
1317
+ "pollLast".equals(method) || "removeLast".equals(method) || "pop".equals(method);
1318
+ }
1319
+ private static int braceDelta(String line) {
1320
+ int delta = 0;
1321
+ boolean inString = false;
1322
+ boolean escaped = false;
1323
+ for (int i = 0; i < line.length(); i++) {
1324
+ char ch = line.charAt(i);
1325
+ if (inString) {
1326
+ if (escaped) {
1327
+ escaped = false;
1328
+ } else if (ch == '\\') {
1329
+ escaped = true;
1330
+ } else if (ch == '"') {
1331
+ inString = false;
1332
+ }
1333
+ continue;
1334
+ }
1335
+ if (ch == '"') inString = true;
1336
+ if (ch == '{') delta++;
1337
+ if (ch == '}') delta--;
1338
+ }
1339
+ return delta;
1340
+ }
1341
+
1342
+ private static int parenDelta(String line) {
1343
+ int delta = 0;
1344
+ boolean inString = false;
1345
+ boolean inChar = false;
1346
+ boolean escaped = false;
1347
+ for (int i = 0; i < line.length(); i++) {
1348
+ char ch = line.charAt(i);
1349
+ if (escaped) {
1350
+ escaped = false;
1351
+ continue;
1352
+ }
1353
+ if (ch == '\\') {
1354
+ escaped = true;
1355
+ continue;
1356
+ }
1357
+ if (inString) {
1358
+ if (ch == '"') inString = false;
1359
+ continue;
1360
+ }
1361
+ if (inChar) {
1362
+ if (ch == '\'') inChar = false;
1363
+ continue;
1364
+ }
1365
+ if (ch == '"') {
1366
+ inString = true;
1367
+ continue;
1368
+ }
1369
+ if (ch == '\'') {
1370
+ inChar = true;
1371
+ continue;
1372
+ }
1373
+ if (ch == '(') delta++;
1374
+ if (ch == ')') delta--;
1375
+ }
1376
+ return delta;
1377
+ }
1378
+
1379
+ private static String indentOf(String line) {
1380
+ int index = 0;
1381
+ while (index < line.length() && Character.isWhitespace(line.charAt(index))) index++;
1382
+ return line.substring(0, index);
1383
+ }
1384
+
1385
+ private static int firstNonWhitespace(String line) {
1386
+ int index = 0;
1387
+ while (index < line.length() && Character.isWhitespace(line.charAt(index))) index++;
1388
+ return index;
1389
+ }
1390
+
1391
+ private static int findMatchingParen(String source, int openParen) {
1392
+ int depth = 0;
1393
+ boolean inString = false;
1394
+ boolean inChar = false;
1395
+ boolean escaped = false;
1396
+ for (int index = openParen; index < source.length(); index++) {
1397
+ char ch = source.charAt(index);
1398
+ if (escaped) {
1399
+ escaped = false;
1400
+ continue;
1401
+ }
1402
+ if (ch == '\\') {
1403
+ escaped = inString || inChar;
1404
+ continue;
1405
+ }
1406
+ if (inString) {
1407
+ if (ch == '"') inString = false;
1408
+ continue;
1409
+ }
1410
+ if (inChar) {
1411
+ if (ch == '\'') inChar = false;
1412
+ continue;
1413
+ }
1414
+ if (ch == '"') {
1415
+ inString = true;
1416
+ continue;
1417
+ }
1418
+ if (ch == '\'') {
1419
+ inChar = true;
1420
+ continue;
1421
+ }
1422
+ if (ch == '(') depth++;
1423
+ if (ch == ')') {
1424
+ depth--;
1425
+ if (depth == 0) return index;
1426
+ }
1427
+ }
1428
+ return -1;
1429
+ }
1430
+
1431
+ private static int findTopLevelElse(String source) {
1432
+ int parenDepth = 0;
1433
+ int bracketDepth = 0;
1434
+ int braceDepth = 0;
1435
+ boolean inString = false;
1436
+ boolean inChar = false;
1437
+ boolean escaped = false;
1438
+ for (int index = 0; index < source.length(); index++) {
1439
+ char ch = source.charAt(index);
1440
+ if (escaped) {
1441
+ escaped = false;
1442
+ continue;
1443
+ }
1444
+ if (ch == '\\') {
1445
+ escaped = inString || inChar;
1446
+ continue;
1447
+ }
1448
+ if (inString) {
1449
+ if (ch == '"') inString = false;
1450
+ continue;
1451
+ }
1452
+ if (inChar) {
1453
+ if (ch == '\'') inChar = false;
1454
+ continue;
1455
+ }
1456
+ if (ch == '"') {
1457
+ inString = true;
1458
+ continue;
1459
+ }
1460
+ if (ch == '\'') {
1461
+ inChar = true;
1462
+ continue;
1463
+ }
1464
+ if (ch == '(') parenDepth++;
1465
+ if (ch == ')') parenDepth = Math.max(0, parenDepth - 1);
1466
+ if (ch == '[') bracketDepth++;
1467
+ if (ch == ']') bracketDepth = Math.max(0, bracketDepth - 1);
1468
+ if (ch == '{') braceDepth++;
1469
+ if (ch == '}') braceDepth = Math.max(0, braceDepth - 1);
1470
+ if (parenDepth == 0 && bracketDepth == 0 && braceDepth == 0 && source.startsWith("else", index)) {
1471
+ boolean beforeBoundary = index == 0 || !Character.isJavaIdentifierPart(source.charAt(index - 1));
1472
+ boolean afterBoundary = index + 4 >= source.length() || !Character.isJavaIdentifierPart(source.charAt(index + 4));
1473
+ if (beforeBoundary && afterBoundary) return index;
1474
+ }
1475
+ }
1476
+ return -1;
1477
+ }
1478
+
1479
+ private static boolean isControlKeyword(String value) {
1480
+ return "else".equals(value) || "if".equals(value) || "for".equals(value) ||
1481
+ "while".equals(value) || "switch".equals(value) || "catch".equals(value) ||
1482
+ "finally".equals(value) || "do".equals(value) || "try".equals(value);
1483
+ }
1484
+
1485
+ private static String quote(String value) {
1486
+ return "\"" + value.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
1487
+ }
1488
+
1489
+ private static boolean isSimpleIdentifierExpression(String value) {
1490
+ return value != null && value.matches("[A-Za-z_][A-Za-z0-9_]*");
1491
+ }
1492
+
1493
+ private static String singleIdentifierIndexSource(String value) {
1494
+ if (value == null) return null;
1495
+ java.util.regex.Matcher identifiers = java.util.regex.Pattern
1496
+ .compile("[A-Za-z_][A-Za-z0-9_]*")
1497
+ .matcher(value);
1498
+ java.util.LinkedHashSet<String> unique = new java.util.LinkedHashSet<>();
1499
+ while (identifiers.find()) {
1500
+ String name = identifiers.group();
1501
+ if (!"TraceHooks".equals(name)) unique.add(name);
1502
+ }
1503
+ if (unique.size() != 1) return null;
1504
+ String stripped = value
1505
+ .replaceAll("[A-Za-z_][A-Za-z0-9_]*", "")
1506
+ .replaceAll("[0-9]+", "")
1507
+ .replaceAll("[+\\-*/%() \\t]", "");
1508
+ return stripped.isEmpty() ? unique.iterator().next() : null;
1509
+ }
1510
+
1511
+ private static String safeIndexSourceExpression(String value) {
1512
+ if (value == null) return null;
1513
+ String normalized = value.trim().replaceAll("\\s+", " ");
1514
+ if (normalized.isEmpty()) return null;
1515
+ if (!java.util.regex.Pattern.compile("[A-Za-z_][A-Za-z0-9_]*").matcher(normalized).find()) return null;
1516
+ if (isSimpleIdentifierExpression(normalized)) return normalized;
1517
+ if (normalized.matches("^[A-Za-z_][A-Za-z0-9_]*\\s*\\[[^\\]]+\\]\\s*$")) {
1518
+ return normalized.replaceAll("\\s+", "");
1519
+ }
1520
+ if (normalized.matches("^[A-Za-z_][A-Za-z0-9_]*(?:\\.[A-Za-z_][A-Za-z0-9_]*\\(\\))+(?:\\s*[+\\-*/%]\\s*[0-9]+)?$")) {
1521
+ return normalized;
1522
+ }
1523
+ String stripped = normalized
1524
+ .replaceAll("[A-Za-z_][A-Za-z0-9_]*", "")
1525
+ .replaceAll("[0-9]+", "")
1526
+ .replaceAll("[+\\-*/%.() \\t]", "");
1527
+ return stripped.isEmpty() ? normalized : null;
1528
+ }
1529
+
1530
+ private static String indexSourceArgument(String value) {
1531
+ if (value != null) {
1532
+ java.util.regex.Matcher charAtIndex = java.util.regex.Pattern
1533
+ .compile("^[A-Za-z_][A-Za-z0-9_]*\\.charAt\\(\\s*([\\s\\S]+)\\s*\\)$")
1534
+ .matcher(value.trim());
1535
+ if (charAtIndex.matches()) {
1536
+ String charAtSource = safeIndexSourceExpression(charAtIndex.group(1));
1537
+ if (charAtSource == null) charAtSource = singleIdentifierIndexSource(charAtIndex.group(1));
1538
+ if (charAtSource != null) return quote(charAtSource);
1539
+ }
1540
+ java.util.regex.Matcher tracedReadSource = java.util.regex.Pattern
1541
+ .compile("^TraceHooks\\.read[A-Za-z0-9_]*AtLine\\([\\s\\S]*,\\s*\"([A-Za-z_][A-Za-z0-9_]*)\"\\s*\\)$")
1542
+ .matcher(value.trim());
1543
+ if (tracedReadSource.matches()) return quote(tracedReadSource.group(1));
1544
+ String expressionSource = safeIndexSourceExpression(value.trim());
1545
+ if (expressionSource == null) expressionSource = singleIdentifierIndexSource(value.trim());
1546
+ if (expressionSource != null) return quote(expressionSource);
1547
+ }
1548
+ return isSimpleIdentifierExpression(value) ? quote(value) : "null";
1549
+ }
1550
+
1551
+ private static String escapedIndexSourcesTargetSegment(String... values) {
1552
+ StringBuilder out = new StringBuilder(",\\\"indexSources\\\":[");
1553
+ for (int index = 0; index < values.length; index++) {
1554
+ if (index > 0) out.append(",");
1555
+ String value = values[index];
1556
+ String expressionSource = safeIndexSourceExpression(value);
1557
+ if (expressionSource == null) expressionSource = singleIdentifierIndexSource(value);
1558
+ if (expressionSource != null) {
1559
+ out.append("\\\"").append(expressionSource).append("\\\"");
1560
+ } else {
1561
+ out.append("null");
1562
+ }
1563
+ }
1564
+ out.append("]");
1565
+ return out.toString();
1566
+ }
1567
+
1568
+ private static String mutationArgsEventSegment(String rawArgs, int sourceLine, MethodFrame frame) {
1569
+ java.util.List<String> args = splitTopLevel(rawArgs == null ? "" : rawArgs.trim());
1570
+ if (args.isEmpty()) return ",\\\"args\\\":[]";
1571
+ StringBuilder out = new StringBuilder(",\\\"args\\\":[");
1572
+ for (int index = 0; index < args.size(); index++) {
1573
+ if (index > 0) out.append(",\" + \",\" + \"");
1574
+ out.append("\" + TraceHooks.serializeResult(")
1575
+ .append(rewriteReads(args.get(index), sourceLine, frame))
1576
+ .append(") + \"");
1577
+ }
1578
+ out.append("]");
1579
+ return out.toString();
1580
+ }
1581
+
1582
+ private static MutatingArgs mutatingArgs(String rawArgs, int sourceLine, MethodFrame frame) {
1583
+ java.util.List<String> args = splitTopLevel(rawArgs == null ? "" : rawArgs.trim());
1584
+ if (args.isEmpty()) {
1585
+ return new MutatingArgs("", "", ",\\\"args\\\":[]");
1586
+ }
1587
+ java.util.List<String> callArgs = new java.util.ArrayList<>();
1588
+ java.util.List<String> eventArgs = new java.util.ArrayList<>();
1589
+ StringBuilder prefix = new StringBuilder();
1590
+ for (int index = 0; index < args.size(); index++) {
1591
+ String rewritten = rewriteReads(args.get(index), sourceLine, frame);
1592
+ if (rewritten.contains("TraceHooks.")) {
1593
+ String temp = "__tracecodeArg" + sourceLine + "_" + index;
1594
+ prefix.append("var ").append(temp).append(" = ").append(rewritten).append("; ");
1595
+ callArgs.add(temp);
1596
+ eventArgs.add(temp);
1597
+ } else {
1598
+ callArgs.add(rewritten);
1599
+ eventArgs.add(rewritten);
1600
+ }
1601
+ }
1602
+ StringBuilder event = new StringBuilder(",\\\"args\\\":[");
1603
+ for (int index = 0; index < eventArgs.size(); index++) {
1604
+ if (index > 0) event.append(",\" + \",\" + \"");
1605
+ event.append("\" + TraceHooks.serializeResult(").append(eventArgs.get(index)).append(") + \"");
1606
+ }
1607
+ event.append("]");
1608
+ return new MutatingArgs(prefix.toString(), String.join(", ", callArgs), event.toString());
1609
+ }
1610
+
1611
+ private static final class MutatingArgs {
1612
+ final String prefix;
1613
+ final String callArgs;
1614
+ final String eventSegment;
1615
+
1616
+ MutatingArgs(String prefix, String callArgs, String eventSegment) {
1617
+ this.prefix = prefix;
1618
+ this.callArgs = callArgs;
1619
+ this.eventSegment = eventSegment;
1620
+ }
1621
+ }
1622
+
1623
+ private static final class MethodFrame {
1624
+ final String name;
1625
+ final String returnType;
1626
+ int depth;
1627
+ int initializerDepth;
1628
+ int headerParenDepth;
1629
+ int expressionParenDepth;
1630
+ boolean pendingAnnotation;
1631
+ boolean suppressNextLineHook;
1632
+ boolean statementContinuation;
1633
+ final java.util.Set<String> fields;
1634
+ final Map<String, String> variables;
1635
+
1636
+ MethodFrame(String name, String returnType, int depth, Map<String, String> fields, String parametersSource) {
1637
+ this.name = name;
1638
+ this.returnType = returnType == null || returnType.isBlank() ? "var" : returnType;
1639
+ this.depth = depth;
1640
+ this.initializerDepth = 0;
1641
+ this.headerParenDepth = 0;
1642
+ this.expressionParenDepth = 0;
1643
+ this.pendingAnnotation = false;
1644
+ this.suppressNextLineHook = false;
1645
+ this.statementContinuation = false;
1646
+ this.fields = new java.util.HashSet<>(fields.keySet());
1647
+ this.variables = new HashMap<>(fields);
1648
+ registerParameters(this.variables, parametersSource);
1649
+ }
1650
+
1651
+ String typeOf(String variable) {
1652
+ return variables.get(variable);
1653
+ }
1654
+
1655
+ boolean isField(String variable) {
1656
+ return fields.contains(variable);
1657
+ }
1658
+
1659
+ String returnTypeOrVar() {
1660
+ return "void".equals(returnType) ? "var" : returnType;
1661
+ }
1662
+ }
1663
+
1664
+ private interface Replacer {
1665
+ String replace(Matcher matcher);
53
1666
  }
54
1667
  }