@openrewrite/rewrite 8.92.16 → 8.92.18

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 (254) hide show
  1. package/README.md +48 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +2 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/java/formatting-utils.d.ts +2 -1
  6. package/dist/java/formatting-utils.d.ts.map +1 -1
  7. package/dist/java/formatting-utils.js +4 -3
  8. package/dist/java/formatting-utils.js.map +1 -1
  9. package/dist/java/rpc.d.ts.map +1 -1
  10. package/dist/java/rpc.js +2 -0
  11. package/dist/java/rpc.js.map +1 -1
  12. package/dist/java/tree.d.ts +8 -0
  13. package/dist/java/tree.d.ts.map +1 -1
  14. package/dist/java/tree.js +11 -1
  15. package/dist/java/tree.js.map +1 -1
  16. package/dist/java/type.d.ts +7 -1
  17. package/dist/java/type.d.ts.map +1 -1
  18. package/dist/java/type.js +16 -1
  19. package/dist/java/type.js.map +1 -1
  20. package/dist/javascript/add-import.d.ts +27 -21
  21. package/dist/javascript/add-import.d.ts.map +1 -1
  22. package/dist/javascript/add-import.js +303 -143
  23. package/dist/javascript/add-import.js.map +1 -1
  24. package/dist/javascript/amd.d.ts.map +1 -1
  25. package/dist/javascript/amd.js +25 -10
  26. package/dist/javascript/amd.js.map +1 -1
  27. package/dist/javascript/autodetect.js +36 -45
  28. package/dist/javascript/autodetect.js.map +1 -1
  29. package/dist/javascript/binding.d.ts +6 -4
  30. package/dist/javascript/binding.d.ts.map +1 -1
  31. package/dist/javascript/binding.js +54 -18
  32. package/dist/javascript/binding.js.map +1 -1
  33. package/dist/javascript/comparator.d.ts +22 -5
  34. package/dist/javascript/comparator.d.ts.map +1 -1
  35. package/dist/javascript/comparator.js +120 -38
  36. package/dist/javascript/comparator.js.map +1 -1
  37. package/dist/javascript/format/format.d.ts +2 -0
  38. package/dist/javascript/format/format.d.ts.map +1 -1
  39. package/dist/javascript/format/format.js +11 -1
  40. package/dist/javascript/format/format.js.map +1 -1
  41. package/dist/javascript/format/tabs-and-indents-visitor.d.ts.map +1 -1
  42. package/dist/javascript/format/tabs-and-indents-visitor.js +31 -4
  43. package/dist/javascript/format/tabs-and-indents-visitor.js.map +1 -1
  44. package/dist/javascript/index.d.ts +4 -2
  45. package/dist/javascript/index.d.ts.map +1 -1
  46. package/dist/javascript/index.js +10 -1
  47. package/dist/javascript/index.js.map +1 -1
  48. package/dist/javascript/markers.d.ts +12 -0
  49. package/dist/javascript/markers.d.ts.map +1 -1
  50. package/dist/javascript/markers.js +81 -2
  51. package/dist/javascript/markers.js.map +1 -1
  52. package/dist/javascript/method-matcher.d.ts +13 -2
  53. package/dist/javascript/method-matcher.d.ts.map +1 -1
  54. package/dist/javascript/method-matcher.js +32 -19
  55. package/dist/javascript/method-matcher.js.map +1 -1
  56. package/dist/javascript/node-resolution-result.js +3 -2
  57. package/dist/javascript/node-resolution-result.js.map +1 -1
  58. package/dist/javascript/package-name.d.ts +6 -0
  59. package/dist/javascript/package-name.d.ts.map +1 -0
  60. package/dist/javascript/package-name.js +47 -0
  61. package/dist/javascript/package-name.js.map +1 -0
  62. package/dist/javascript/parser.d.ts +9 -0
  63. package/dist/javascript/parser.d.ts.map +1 -1
  64. package/dist/javascript/parser.js +185 -88
  65. package/dist/javascript/parser.js.map +1 -1
  66. package/dist/javascript/preconditions.d.ts +4 -1
  67. package/dist/javascript/preconditions.d.ts.map +1 -1
  68. package/dist/javascript/preconditions.js +7 -4
  69. package/dist/javascript/preconditions.js.map +1 -1
  70. package/dist/javascript/print.d.ts +10 -1
  71. package/dist/javascript/print.d.ts.map +1 -1
  72. package/dist/javascript/print.js +120 -77
  73. package/dist/javascript/print.js.map +1 -1
  74. package/dist/javascript/recipes/change-method-target-to-import.d.ts +29 -0
  75. package/dist/javascript/recipes/change-method-target-to-import.d.ts.map +1 -0
  76. package/dist/javascript/recipes/change-method-target-to-import.js +164 -0
  77. package/dist/javascript/recipes/change-method-target-to-import.js.map +1 -0
  78. package/dist/javascript/recipes/index.d.ts +1 -0
  79. package/dist/javascript/recipes/index.d.ts.map +1 -1
  80. package/dist/javascript/recipes/index.js +1 -0
  81. package/dist/javascript/recipes/index.js.map +1 -1
  82. package/dist/javascript/scope.d.ts +60 -16
  83. package/dist/javascript/scope.d.ts.map +1 -1
  84. package/dist/javascript/scope.js +596 -131
  85. package/dist/javascript/scope.js.map +1 -1
  86. package/dist/javascript/search/uses-method.d.ts +1 -1
  87. package/dist/javascript/search/uses-method.d.ts.map +1 -1
  88. package/dist/javascript/search/uses-method.js +2 -2
  89. package/dist/javascript/search/uses-method.js.map +1 -1
  90. package/dist/javascript/search/uses-type.d.ts +14 -1
  91. package/dist/javascript/search/uses-type.d.ts.map +1 -1
  92. package/dist/javascript/search/uses-type.js +24 -9
  93. package/dist/javascript/search/uses-type.js.map +1 -1
  94. package/dist/javascript/templating/bindings.d.ts +1 -1
  95. package/dist/javascript/templating/bindings.d.ts.map +1 -1
  96. package/dist/javascript/templating/bindings.js +10 -50
  97. package/dist/javascript/templating/bindings.js.map +1 -1
  98. package/dist/javascript/templating/comparator.d.ts +8 -11
  99. package/dist/javascript/templating/comparator.d.ts.map +1 -1
  100. package/dist/javascript/templating/comparator.js +12 -110
  101. package/dist/javascript/templating/comparator.js.map +1 -1
  102. package/dist/javascript/templating/engine.d.ts +34 -24
  103. package/dist/javascript/templating/engine.d.ts.map +1 -1
  104. package/dist/javascript/templating/engine.js +208 -115
  105. package/dist/javascript/templating/engine.js.map +1 -1
  106. package/dist/javascript/templating/pattern.d.ts +11 -5
  107. package/dist/javascript/templating/pattern.d.ts.map +1 -1
  108. package/dist/javascript/templating/pattern.js +86 -20
  109. package/dist/javascript/templating/pattern.js.map +1 -1
  110. package/dist/javascript/templating/placeholder-replacement.d.ts +34 -3
  111. package/dist/javascript/templating/placeholder-replacement.d.ts.map +1 -1
  112. package/dist/javascript/templating/placeholder-replacement.js +126 -60
  113. package/dist/javascript/templating/placeholder-replacement.js.map +1 -1
  114. package/dist/javascript/templating/precedence.d.ts +3 -1
  115. package/dist/javascript/templating/precedence.d.ts.map +1 -1
  116. package/dist/javascript/templating/precedence.js +28 -8
  117. package/dist/javascript/templating/precedence.js.map +1 -1
  118. package/dist/javascript/templating/template.d.ts +7 -6
  119. package/dist/javascript/templating/template.d.ts.map +1 -1
  120. package/dist/javascript/templating/template.js +31 -28
  121. package/dist/javascript/templating/template.js.map +1 -1
  122. package/dist/javascript/templating/types.d.ts +6 -3
  123. package/dist/javascript/templating/types.d.ts.map +1 -1
  124. package/dist/javascript/templating/utils.d.ts +10 -1
  125. package/dist/javascript/templating/utils.d.ts.map +1 -1
  126. package/dist/javascript/templating/utils.js +22 -3
  127. package/dist/javascript/templating/utils.js.map +1 -1
  128. package/dist/javascript/tree-debug.d.ts +2 -0
  129. package/dist/javascript/tree-debug.d.ts.map +1 -1
  130. package/dist/javascript/tree-debug.js +6 -0
  131. package/dist/javascript/tree-debug.js.map +1 -1
  132. package/dist/javascript/tsconfig.d.ts.map +1 -1
  133. package/dist/javascript/tsconfig.js +7 -17
  134. package/dist/javascript/tsconfig.js.map +1 -1
  135. package/dist/javascript/type-mapping.d.ts +35 -16
  136. package/dist/javascript/type-mapping.d.ts.map +1 -1
  137. package/dist/javascript/type-mapping.js +271 -252
  138. package/dist/javascript/type-mapping.js.map +1 -1
  139. package/dist/javascript/type-report-cli.d.ts +7 -0
  140. package/dist/javascript/type-report-cli.d.ts.map +1 -0
  141. package/dist/javascript/type-report-cli.js +129 -0
  142. package/dist/javascript/type-report-cli.js.map +1 -0
  143. package/dist/javascript/type-report.d.ts +61 -0
  144. package/dist/javascript/type-report.d.ts.map +1 -0
  145. package/dist/javascript/type-report.js +488 -0
  146. package/dist/javascript/type-report.js.map +1 -0
  147. package/dist/markers.d.ts +4 -0
  148. package/dist/markers.d.ts.map +1 -1
  149. package/dist/markers.js +8 -0
  150. package/dist/markers.js.map +1 -1
  151. package/dist/print.d.ts +6 -1
  152. package/dist/print.d.ts.map +1 -1
  153. package/dist/print.js +21 -7
  154. package/dist/print.js.map +1 -1
  155. package/dist/recipe.d.ts +5 -0
  156. package/dist/recipe.d.ts.map +1 -1
  157. package/dist/recipe.js +5 -0
  158. package/dist/recipe.js.map +1 -1
  159. package/dist/rewrite-javascript-version.txt +1 -1
  160. package/dist/rpc/java-rpc-client.d.ts +2 -0
  161. package/dist/rpc/java-rpc-client.d.ts.map +1 -1
  162. package/dist/rpc/java-rpc-client.js +1 -0
  163. package/dist/rpc/java-rpc-client.js.map +1 -1
  164. package/dist/rpc/queue.d.ts +24 -0
  165. package/dist/rpc/queue.d.ts.map +1 -1
  166. package/dist/rpc/queue.js +71 -11
  167. package/dist/rpc/queue.js.map +1 -1
  168. package/dist/rpc/request/get-object.d.ts +4 -0
  169. package/dist/rpc/request/get-object.d.ts.map +1 -1
  170. package/dist/rpc/request/get-object.js +23 -1
  171. package/dist/rpc/request/get-object.js.map +1 -1
  172. package/dist/rpc/request/parse.d.ts.map +1 -1
  173. package/dist/rpc/request/parse.js +3 -1
  174. package/dist/rpc/request/parse.js.map +1 -1
  175. package/dist/rpc/request/prepare-recipe.d.ts +3 -1
  176. package/dist/rpc/request/prepare-recipe.d.ts.map +1 -1
  177. package/dist/rpc/request/prepare-recipe.js +13 -6
  178. package/dist/rpc/request/prepare-recipe.js.map +1 -1
  179. package/dist/rpc/request/print.d.ts +8 -2
  180. package/dist/rpc/request/print.d.ts.map +1 -1
  181. package/dist/rpc/request/print.js +12 -9
  182. package/dist/rpc/request/print.js.map +1 -1
  183. package/dist/rpc/rewrite-rpc.d.ts +3 -2
  184. package/dist/rpc/rewrite-rpc.d.ts.map +1 -1
  185. package/dist/rpc/rewrite-rpc.js +9 -3
  186. package/dist/rpc/rewrite-rpc.js.map +1 -1
  187. package/dist/rpc/server.d.ts.map +1 -1
  188. package/dist/rpc/server.js +19 -5
  189. package/dist/rpc/server.js.map +1 -1
  190. package/dist/search/is-source-file.d.ts +1 -0
  191. package/dist/search/is-source-file.d.ts.map +1 -1
  192. package/dist/search/is-source-file.js +7 -2
  193. package/dist/search/is-source-file.js.map +1 -1
  194. package/dist/test/java-rpc.d.ts.map +1 -1
  195. package/dist/test/java-rpc.js +3 -0
  196. package/dist/test/java-rpc.js.map +1 -1
  197. package/dist/test/rewrite-test.d.ts +5 -0
  198. package/dist/test/rewrite-test.d.ts.map +1 -1
  199. package/dist/test/rewrite-test.js +14 -3
  200. package/dist/test/rewrite-test.js.map +1 -1
  201. package/package.json +4 -3
  202. package/src/index.ts +3 -1
  203. package/src/java/formatting-utils.ts +5 -4
  204. package/src/java/rpc.ts +2 -0
  205. package/src/java/tree.ts +15 -0
  206. package/src/java/type.ts +19 -2
  207. package/src/javascript/add-import.ts +338 -152
  208. package/src/javascript/amd.ts +28 -12
  209. package/src/javascript/autodetect.ts +32 -41
  210. package/src/javascript/binding.ts +64 -22
  211. package/src/javascript/comparator.ts +129 -43
  212. package/src/javascript/format/format.ts +9 -0
  213. package/src/javascript/format/tabs-and-indents-visitor.ts +30 -3
  214. package/src/javascript/index.ts +6 -3
  215. package/src/javascript/markers.ts +77 -5
  216. package/src/javascript/method-matcher.ts +34 -22
  217. package/src/javascript/node-resolution-result.ts +3 -2
  218. package/src/javascript/package-name.ts +45 -0
  219. package/src/javascript/parser.ts +200 -91
  220. package/src/javascript/preconditions.ts +7 -4
  221. package/src/javascript/print.ts +123 -76
  222. package/src/javascript/recipes/change-method-target-to-import.ts +178 -0
  223. package/src/javascript/recipes/index.ts +1 -0
  224. package/src/javascript/scope.ts +705 -169
  225. package/src/javascript/search/uses-method.ts +2 -2
  226. package/src/javascript/search/uses-type.ts +30 -9
  227. package/src/javascript/templating/bindings.ts +13 -38
  228. package/src/javascript/templating/comparator.ts +16 -127
  229. package/src/javascript/templating/engine.ts +236 -129
  230. package/src/javascript/templating/pattern.ts +107 -28
  231. package/src/javascript/templating/placeholder-replacement.ts +154 -62
  232. package/src/javascript/templating/precedence.ts +33 -11
  233. package/src/javascript/templating/template.ts +35 -30
  234. package/src/javascript/templating/types.ts +6 -3
  235. package/src/javascript/templating/utils.ts +24 -2
  236. package/src/javascript/tree-debug.ts +9 -0
  237. package/src/javascript/tsconfig.ts +7 -17
  238. package/src/javascript/type-mapping.ts +277 -255
  239. package/src/javascript/type-report-cli.ts +96 -0
  240. package/src/javascript/type-report.ts +575 -0
  241. package/src/markers.ts +8 -0
  242. package/src/print.ts +23 -8
  243. package/src/recipe.ts +6 -0
  244. package/src/rpc/java-rpc-client.ts +3 -0
  245. package/src/rpc/queue.ts +80 -7
  246. package/src/rpc/request/get-object.ts +24 -0
  247. package/src/rpc/request/parse.ts +4 -1
  248. package/src/rpc/request/prepare-recipe.ts +16 -6
  249. package/src/rpc/request/print.ts +12 -8
  250. package/src/rpc/rewrite-rpc.ts +16 -5
  251. package/src/rpc/server.ts +18 -6
  252. package/src/search/is-source-file.ts +8 -3
  253. package/src/test/java-rpc.ts +3 -0
  254. package/src/test/rewrite-test.ts +14 -3
@@ -7,9 +7,9 @@ import {foundSearchResult} from "../../markers";
7
7
  export class UsesMethod extends JavaVisitor<ExecutionContext> {
8
8
  private readonly matcher;
9
9
 
10
- constructor(pattern: string) {
10
+ constructor(pattern: string, matchOverrides: boolean = false) {
11
11
  super();
12
- this.matcher = new MethodMatcher(pattern);
12
+ this.matcher = new MethodMatcher(pattern, matchOverrides);
13
13
  }
14
14
 
15
15
  protected async visitExpression(expression: Expression, p: ExecutionContext): Promise<J | undefined> {
@@ -1,27 +1,48 @@
1
1
  import {J, JavaVisitor, Type} from "../../java";
2
+ import {JS} from "../tree";
2
3
  import {ExecutionContext} from "../../execution";
3
4
  import * as picomatch from "picomatch";
4
5
  import {foundSearchResult} from "../../markers";
5
6
 
7
+ /**
8
+ * Marks each tree whose type matches a glob pattern.
9
+ *
10
+ * With `assignable`, a type also matches through a class or interface it extends. A primitive then
11
+ * matches by its keyword. With `includeImplicit`, a call also matches through its method's declaring,
12
+ * return and parameter types.
13
+ */
6
14
  export class UsesType extends JavaVisitor<ExecutionContext> {
7
15
  private readonly matcher: picomatch.Matcher;
16
+ private readonly assignable: boolean;
17
+ private readonly includeImplicit: boolean;
8
18
 
9
- constructor(typePattern: string) {
19
+ constructor(typePattern: string, {assignable = false, includeImplicit = false}: {
20
+ assignable?: boolean,
21
+ includeImplicit?: boolean
22
+ } = {}) {
10
23
  super();
11
- // Create a picomatch matcher for the pattern
12
24
  this.matcher = picomatch.default ? picomatch.default(typePattern) : (picomatch as any)(typePattern);
25
+ this.assignable = assignable;
26
+ this.includeImplicit = includeImplicit;
13
27
  }
14
28
 
15
29
  protected async preVisit(tree: J, _: ExecutionContext): Promise<J | undefined> {
16
- if (J.hasType(tree)) {
17
- const type = tree.type;
18
- if (Type.isFullyQualified(type)) {
19
- const fullyQualifiedName = Type.FullyQualified.getFullyQualifiedName(type);
20
- if (this.matcher(fullyQualifiedName)) {
21
- return foundSearchResult(tree);
22
- }
30
+ if (J.hasType(tree) && this.matches(tree.type)) {
31
+ return foundSearchResult(tree);
32
+ }
33
+ if (this.includeImplicit && JS.isMethodCall(tree) && tree.methodType) {
34
+ const method = tree.methodType;
35
+ if ([method.declaringType, method.returnType, ...method.parameterTypes].some(t => this.matches(t))) {
36
+ return foundSearchResult(tree);
23
37
  }
24
38
  }
25
39
  return tree;
26
40
  }
41
+
42
+ private matches(type: Type | undefined): boolean {
43
+ if (Type.isPrimitive(type)) {
44
+ return this.assignable && type.keyword !== '' && this.matcher(type.keyword);
45
+ }
46
+ return Type.isOfTypeWithName(type, this.assignable, this.matcher);
47
+ }
27
48
  }
@@ -13,64 +13,39 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import {J, Type} from '../../java';
16
+ import {J, NameTree} from '../../java';
17
17
  import {JavaScriptVisitor} from '../visitor';
18
- import {isValueReference} from '../scope';
18
+ import {isReference, scopeOf} from '../scope';
19
19
 
20
20
  /**
21
21
  * Renames the identifiers a template uses for its declared bindings to the names the file
22
22
  * actually binds. Runs before parameter substitution, so only the template's own code is in
23
23
  * scope and a caller's captured code is never rewritten.
24
24
  */
25
- export async function renameBindings<T extends J>(tree: T, renames: Record<string, string>, modules: Record<string, string>): Promise<T> {
26
- return new RenameBindingsVisitor(renames, modules).visit(tree, undefined) as Promise<T>;
25
+ export async function renameBindings<T extends J>(tree: T, renames: Record<string, string>): Promise<T> {
26
+ return new RenameBindingsVisitor(renames).visit(tree, undefined) as Promise<T>;
27
27
  }
28
28
 
29
29
  class RenameBindingsVisitor extends JavaScriptVisitor<undefined> {
30
- constructor(private readonly renames: Record<string, string>,
31
- private readonly modules: Record<string, string>) {
30
+ constructor(private readonly renames: Record<string, string>) {
32
31
  super();
33
32
  }
34
33
 
34
+ // The class of `Mocked<T>` and a decorator's name sit behind this hook, which the base visitor holds closed
35
+ protected override async visitTypeName<N extends NameTree>(nameTree: N, p: undefined): Promise<N> {
36
+ return await this.visit(nameTree, p) as N;
37
+ }
38
+
35
39
  override async visitIdentifier(identifier: J.Identifier, p: undefined): Promise<J | undefined> {
36
40
  const renamed = this.renames[identifier.simpleName];
37
41
  if (renamed === undefined || renamed === identifier.simpleName) {
38
42
  return identifier;
39
43
  }
40
44
 
41
- // Attribution settles it where the context import resolved. It is absent for a module the
42
- // parse could not reach, and the identifier's position decides instead.
43
- const resolved = resolvedModule(identifier);
44
- const refersToBinding = resolved !== undefined
45
- ? resolved === this.modules[identifier.simpleName]
46
- : isValueReference(this.cursor, identifier);
45
+ // Only the context binds at module scope, so a reference nothing in the template rebinds reads it
46
+ const refersToBinding = isReference(this.cursor, identifier) &&
47
+ !scopeOf(this.cursor).declares(identifier.simpleName);
47
48
 
48
49
  return refersToBinding ? {...identifier, simpleName: renamed} as J.Identifier : identifier;
49
50
  }
50
51
  }
51
-
52
- /** The module an identifier's attribution traces back to, following the owning-class chain to its root. */
53
- function resolvedModule(identifier: J.Identifier): string | undefined {
54
- const fieldType = identifier.fieldType;
55
- if (fieldType?.kind === Type.Kind.Variable) {
56
- const owner = (fieldType as Type.Variable).owner;
57
- return owner && Type.isClass(owner) ? rootName(owner as Type.Class) : undefined;
58
- }
59
- const type = identifier.type;
60
- if (type && Type.isMethod(type)) {
61
- const declaring = (type as Type.Method).declaringType;
62
- return declaring ? rootName(declaring as Type.Class) : undefined;
63
- }
64
- if (type && Type.isClass(type)) {
65
- return rootName(type as Type.Class);
66
- }
67
- return undefined;
68
- }
69
-
70
- function rootName(classType: Type.Class): string {
71
- let current: Type.Class = classType;
72
- while (current.owningClass && Type.isClass(current.owningClass)) {
73
- current = current.owningClass as Type.Class;
74
- }
75
- return Type.FullyQualified.getFullyQualifiedName(current);
76
- }
@@ -13,11 +13,11 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import {Cursor, Markers, Tree} from '../..';
16
+ import {Cursor, Tree} from '../..';
17
17
  import {J, Type} from '../../java';
18
18
  import {JS} from '../index';
19
19
  import {JavaScriptSemanticComparatorVisitor} from '../comparator';
20
- import {CaptureMarker, CaptureStorageValue, PlaceholderUtils} from './utils';
20
+ import {CaptureMarker, CaptureStorageValue, PlaceholderUtils, TEMPLATE_MODULE} from './utils';
21
21
  import {Capture, CaptureConstraintContext, CaptureMap, DebugLogEntry, MatchExplanation} from './types';
22
22
  import {CAPTURE_NAME_SYMBOL} from './capture';
23
23
 
@@ -54,8 +54,8 @@ export interface MatcherState {
54
54
  * Part of Layer 1 (Core Instrumentation).
55
55
  */
56
56
  export interface MatcherCallbacks {
57
- handleCapture: (capture: CaptureMarker, target: J, wrapper?: J.RightPadded<J>) => boolean;
58
- handleVariadicCapture: (capture: CaptureMarker, targets: J[], wrappers?: J.RightPadded<J>[]) => boolean;
57
+ handleCapture: (capture: CaptureMarker, target: J, wrapper?: J.RightPadded<J>) => Promise<boolean>;
58
+ handleVariadicCapture: (capture: CaptureMarker, targets: J[], wrappers?: J.RightPadded<J>[]) => Promise<boolean>;
59
59
  saveState: () => MatcherState;
60
60
  restoreState: (state: MatcherState) => void;
61
61
 
@@ -175,7 +175,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
175
175
  }
176
176
  }
177
177
 
178
- const success = this.matcher.handleCapture(captureMarker, target, undefined);
178
+ const success = await this.matcher.handleCapture(captureMarker, target, undefined);
179
179
  if (!success) {
180
180
  const captureName = captureMarker.captureName || 'unnamed';
181
181
  return this.captureConflict(captureName) as R;
@@ -194,9 +194,12 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
194
194
  return await super.visit(j, p, parent);
195
195
  }
196
196
 
197
- /** A capture in the receiver has to bind, so a matching `methodType` cannot stand in for it. */
198
- protected override selectMustBeVisited(method: J.MethodInvocation): boolean {
199
- return method.select !== undefined && containsCapture(method.select);
197
+ /**
198
+ * A function the pattern's `context` declares lives in no module of the source,
199
+ * so it stands in for any function of its name.
200
+ */
201
+ protected override declaresAnyCallee(declaringType: Type.FullyQualified): boolean {
202
+ return Type.FullyQualified.getFullyQualifiedName(declaringType) === TEMPLATE_MODULE;
200
203
  }
201
204
 
202
205
  protected hasSameKind(j: J, other: J): boolean {
@@ -252,7 +255,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
252
255
  }
253
256
 
254
257
  // Handle the capture with the wrapper - use the element for pattern matching
255
- const success = this.matcher.handleCapture(captureMarker, targetElement as J, targetWrapper as J.RightPadded<J> | undefined);
258
+ const success = await this.matcher.handleCapture(captureMarker, targetElement as J, targetWrapper as J.RightPadded<J> | undefined);
256
259
  if (!success) {
257
260
  const captureName = captureMarker.captureName || 'unnamed';
258
261
  return this.captureConflict(captureName);
@@ -337,90 +340,6 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
337
340
  return this.match;
338
341
  }
339
342
 
340
- override async visitMethodInvocation(methodInvocation: J.MethodInvocation, other: J): Promise<J | undefined> {
341
- // Check if any arguments are variadic captures
342
- const hasVariadicCapture = methodInvocation.arguments.elements.some(arg =>
343
- PlaceholderUtils.isVariadicCapture(arg)
344
- );
345
-
346
- // If no variadic captures, use parent implementation (which includes semantic/type-aware matching)
347
- if (!hasVariadicCapture) {
348
- return super.visitMethodInvocation(methodInvocation, other);
349
- }
350
-
351
- // Otherwise, handle variadic captures ourselves
352
- if (!this.match) {
353
- return this.abort(methodInvocation);
354
- }
355
-
356
- if (other.kind !== J.Kind.MethodInvocation) {
357
- // Set up cursors for kindMismatch
358
- const savedCursor = this.cursor;
359
- const savedTargetCursor = this.targetCursor;
360
- this.cursor = new Cursor(methodInvocation, this.cursor);
361
- this.targetCursor = new Cursor(other, this.targetCursor);
362
- try {
363
- return this.kindMismatch();
364
- } finally {
365
- this.cursor = savedCursor;
366
- this.targetCursor = savedTargetCursor;
367
- }
368
- }
369
-
370
- const otherMethodInvocation = other as J.MethodInvocation;
371
-
372
- // Set up cursors for the entire method
373
- const savedCursor = this.cursor;
374
- const savedTargetCursor = this.targetCursor;
375
- this.cursor = new Cursor(methodInvocation, this.cursor);
376
- this.targetCursor = new Cursor(otherMethodInvocation, this.targetCursor);
377
- try {
378
- // Compare select
379
- if ((methodInvocation.select === undefined) !== (otherMethodInvocation.select === undefined)) {
380
- return this.structuralMismatch('select');
381
- }
382
-
383
- // Visit select if present
384
- if (methodInvocation.select && otherMethodInvocation.select) {
385
- await this.visit(methodInvocation.select.element, otherMethodInvocation.select.element);
386
- if (!this.match) return methodInvocation;
387
- }
388
-
389
- // A pattern that spells out no type arguments says nothing about them, as with parentheses
390
- if (methodInvocation.typeParameters) {
391
- if (!otherMethodInvocation.typeParameters) {
392
- return this.structuralMismatch('typeParameters');
393
- }
394
-
395
- if (methodInvocation.typeParameters.elements.length !== otherMethodInvocation.typeParameters.elements.length) {
396
- return this.arrayLengthMismatch('typeParameters.elements');
397
- }
398
-
399
- // Visit each type parameter in lock step (visit RightPadded to check for markers)
400
- for (let i = 0; i < methodInvocation.typeParameters.elements.length; i++) {
401
- await this.visitRightPadded(methodInvocation.typeParameters.elements[i], otherMethodInvocation.typeParameters.elements[i] as any);
402
- if (!this.match) return methodInvocation;
403
- }
404
- }
405
-
406
- // Visit name
407
- await this.visit(methodInvocation.name, otherMethodInvocation.name);
408
- if (!this.match) {
409
- return methodInvocation;
410
- }
411
-
412
- // Special handling for variadic captures in arguments
413
- if (!await this.matchArguments(methodInvocation.arguments.elements, otherMethodInvocation.arguments.elements)) {
414
- return this.structuralMismatch('arguments');
415
- }
416
-
417
- return methodInvocation;
418
- } finally {
419
- this.cursor = savedCursor;
420
- this.targetCursor = savedTargetCursor;
421
- }
422
- }
423
-
424
343
  override async visitBlock(block: J.Block, other: J): Promise<J | undefined> {
425
344
  // Check if any statements have CaptureMarker indicating they're variadic
426
345
  const hasVariadicCapture = block.statements.some(stmt => {
@@ -522,14 +441,6 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
522
441
  }
523
442
  }
524
443
 
525
- /**
526
- * Matches argument lists, with special handling for variadic captures.
527
- * A variadic capture can match zero or more consecutive arguments.
528
- */
529
- private async matchArguments(patternArgs: J.RightPadded<J>[], targetArgs: J.RightPadded<J>[]): Promise<boolean> {
530
- return await this.matchSequence(patternArgs, targetArgs, true);
531
- }
532
-
533
444
  /**
534
445
  * Generic sequence matching with variadic capture support.
535
446
  * Works for any sequence of JRightPadded elements (arguments, statements, etc.).
@@ -693,7 +604,7 @@ export class PatternMatchingComparator extends JavaScriptSemanticComparatorVisit
693
604
  const savedState = this.matcher.saveState();
694
605
 
695
606
  // Handle the variadic capture
696
- const success = this.matcher.handleVariadicCapture(captureMarker, capturedElements, capturedWrappers);
607
+ const success = await this.matcher.handleVariadicCapture(captureMarker, capturedElements, capturedWrappers);
697
608
  if (!success) {
698
609
  // Restore state and try next amount
699
610
  this.matcher.restoreState(savedState);
@@ -958,7 +869,7 @@ export class DebugPatternMatchingComparator extends PatternMatchingComparator {
958
869
  this.debug.log('debug', 'constraint', `Constraint passed for capture: ${captureMarker.captureName}`);
959
870
  }
960
871
 
961
- const success = this.matcher.handleCapture(captureMarker, target, undefined);
872
+ const success = await this.matcher.handleCapture(captureMarker, target, undefined);
962
873
  if (!success) {
963
874
  return this.abort(j) as R;
964
875
  }
@@ -1055,7 +966,7 @@ export class DebugPatternMatchingComparator extends PatternMatchingComparator {
1055
966
  this.debug.log('debug', 'constraint', `Constraint passed for wrapped capture: ${captureMarker.captureName}`);
1056
967
  }
1057
968
 
1058
- const success = this.matcher.handleCapture(captureMarker, targetElement as J, targetWrapper as J.RightPadded<J> | undefined);
969
+ const success = await this.matcher.handleCapture(captureMarker, targetElement as J, targetWrapper as J.RightPadded<J> | undefined);
1059
970
  if (!success) {
1060
971
  return this.abort(right);
1061
972
  }
@@ -1407,7 +1318,7 @@ export class DebugPatternMatchingComparator extends PatternMatchingComparator {
1407
1318
 
1408
1319
  const savedState = this.matcher.saveState();
1409
1320
 
1410
- const success = this.matcher.handleVariadicCapture(captureMarker, capturedElements, capturedWrappers);
1321
+ const success = await this.matcher.handleVariadicCapture(captureMarker, capturedElements, capturedWrappers);
1411
1322
  if (!success) {
1412
1323
  this.matcher.restoreState(savedState);
1413
1324
  continue;
@@ -1462,25 +1373,3 @@ export class DebugPatternMatchingComparator extends PatternMatchingComparator {
1462
1373
  }
1463
1374
  }
1464
1375
  }
1465
-
1466
- /** Whether anything under `node`, the padding wrappers a marker moves onto included, is a capture. */
1467
- function containsCapture(node: unknown): boolean {
1468
- if (node === null || typeof node !== 'object') {
1469
- return false;
1470
- }
1471
- if (Array.isArray(node)) {
1472
- return node.some(containsCapture);
1473
- }
1474
- const record = node as Record<string, unknown>;
1475
- if (typeof record.kind !== 'string') {
1476
- return false;
1477
- }
1478
- // Attribution is a cyclic graph, and a capture is never reachable through one
1479
- if (Type.isType(node)) {
1480
- return false;
1481
- }
1482
- if (record.markers && PlaceholderUtils.getCaptureMarker(node as { markers: Markers })) {
1483
- return true;
1484
- }
1485
- return Object.entries(record).some(([key, value]) => key !== 'markers' && containsCapture(value));
1486
- }