@gitwand/core 2.5.0 → 2.6.0

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 (51) hide show
  1. package/dist/__tests__/refactoring/refactoring-pipeline.test.d.ts +14 -0
  2. package/dist/__tests__/refactoring/refactoring-pipeline.test.d.ts.map +1 -0
  3. package/dist/__tests__/refactoring/refactoring-pipeline.test.js +359 -0
  4. package/dist/__tests__/refactoring/refactoring-pipeline.test.js.map +1 -0
  5. package/dist/classifier.d.ts.map +1 -1
  6. package/dist/classifier.js +2 -0
  7. package/dist/classifier.js.map +1 -1
  8. package/dist/config.d.ts +20 -0
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/config.js +13 -0
  11. package/dist/config.js.map +1 -1
  12. package/dist/index.d.ts +3 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +2 -0
  15. package/dist/index.js.map +1 -1
  16. package/dist/patterns/refactoring-aware-merge.d.ts +52 -0
  17. package/dist/patterns/refactoring-aware-merge.d.ts.map +1 -0
  18. package/dist/patterns/refactoring-aware-merge.js +131 -0
  19. package/dist/patterns/refactoring-aware-merge.js.map +1 -0
  20. package/dist/refactoring/detect.d.ts +54 -0
  21. package/dist/refactoring/detect.d.ts.map +1 -0
  22. package/dist/refactoring/detect.js +389 -0
  23. package/dist/refactoring/detect.js.map +1 -0
  24. package/dist/refactoring/index.d.ts +13 -0
  25. package/dist/refactoring/index.d.ts.map +1 -0
  26. package/dist/refactoring/index.js +12 -0
  27. package/dist/refactoring/index.js.map +1 -0
  28. package/dist/refactoring/invert.d.ts +53 -0
  29. package/dist/refactoring/invert.d.ts.map +1 -0
  30. package/dist/refactoring/invert.js +180 -0
  31. package/dist/refactoring/invert.js.map +1 -0
  32. package/dist/refactoring/orchestration.d.ts +65 -0
  33. package/dist/refactoring/orchestration.d.ts.map +1 -0
  34. package/dist/refactoring/orchestration.js +174 -0
  35. package/dist/refactoring/orchestration.js.map +1 -0
  36. package/dist/refactoring/replay.d.ts +74 -0
  37. package/dist/refactoring/replay.d.ts.map +1 -0
  38. package/dist/refactoring/replay.js +200 -0
  39. package/dist/refactoring/replay.js.map +1 -0
  40. package/dist/resolver/assemble.d.ts.map +1 -1
  41. package/dist/resolver/assemble.js +21 -0
  42. package/dist/resolver/assemble.js.map +1 -1
  43. package/dist/resolver/index.d.ts.map +1 -1
  44. package/dist/resolver/index.js +9 -0
  45. package/dist/resolver/index.js.map +1 -1
  46. package/dist/resolver/policy.d.ts.map +1 -1
  47. package/dist/resolver/policy.js +2 -0
  48. package/dist/resolver/policy.js.map +1 -1
  49. package/dist/types.d.ts +59 -1
  50. package/dist/types.d.ts.map +1 -1
  51. package/package.json +1 -1
@@ -0,0 +1,52 @@
1
+ /**
2
+ * v2.6 — Pattern refactoring-aware-merge (priority 25, expérimental, opt-in).
3
+ *
4
+ * Détecte les conflits causés par des refactorings concurrents (renommages,
5
+ * déplacements de méthode) et délègue la résolution au pipeline RefMerge.
6
+ *
7
+ * ## Position dans la hiérarchie
8
+ *
9
+ * Priority 25 — après les patterns trivials (1–10) mais avant les patterns
10
+ * heuristiques (whitespace: 5, value_only: 8, non_overlapping: 4). En pratique,
11
+ * ce pattern n'est évalué que sur les hunks qui ont déjà résisté aux patterns
12
+ * plus simples, car ceux-ci ont une priorité inférieure (numéro plus petit).
13
+ *
14
+ * Attendez — la convention est : **plus petit = évalué en premier**. Donc 25
15
+ * signifie évalué AVANT whitespace_only (5) ? Non — whitespace (5) est évalué
16
+ * avant RefMerge (25). Les patterns à faible numéro sont prioritaires.
17
+ *
18
+ * RefMerge à priority 25 est évalué :
19
+ * - APRÈS non_overlapping (4), whitespace_only (5), reorder_only (6),
20
+ * insertion_at_boundary (7), value_only_change (8)
21
+ * - AVANT complex (999) et llm_proposed (998)
22
+ *
23
+ * C'est intentionnel : on ne tente RefMerge que si les patterns textuels simples
24
+ * n'ont pas suffi, car RefMerge est plus coûteux (tokenisation + détection).
25
+ *
26
+ * ## Activation
27
+ *
28
+ * Ce pattern est désactivé par défaut. Il s'active via `setRefMergeEnabled(true)`
29
+ * appelé par `resolve()` quand `options.refactoringAware.enabled === true`.
30
+ * Le flag est réinitialisé après chaque appel à `resolve()`.
31
+ *
32
+ * ## Résolution
33
+ *
34
+ * `detect()` exécute le pipeline RefMerge complet et cache le résultat dans
35
+ * `_lastResult`. Si le pipeline réussit (`lines !== null`), detect retourne `true`
36
+ * et `assembleResolution()` peut récupérer les lignes via `getLastRefMergeResult()`.
37
+ */
38
+ import type { PatternPlugin } from "../types.js";
39
+ import type { RefMergeResult } from "../refactoring/orchestration.js";
40
+ /** Active ou désactive le pattern RefMerge pour la prochaine résolution. */
41
+ export declare function setRefMergeEnabled(enabled: boolean, max?: number): void;
42
+ /** Retourne l'état d'activation courant (utile pour les tests). */
43
+ export declare function isRefMergeEnabled(): boolean;
44
+ /**
45
+ * Retourne le dernier résultat RefMerge mis en cache par `detect()`.
46
+ * Appelé par `assembleResolution()` pour récupérer les lignes sans recalcul.
47
+ * Retourne `null` si `detect()` n'a pas encore été appelé ou si le résultat a été reset.
48
+ */
49
+ export declare function getLastRefMergeResult(): RefMergeResult | null;
50
+ declare const refactoringAwareMerge: PatternPlugin;
51
+ export default refactoringAwareMerge;
52
+ //# sourceMappingURL=refactoring-aware-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactoring-aware-merge.d.ts","sourceRoot":"","sources":["../../src/patterns/refactoring-aware-merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,KAAK,EAAkC,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAatE,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,SAAK,GAAG,IAAI,CAInE;AAED,mEAAmE;AACnE,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,cAAc,GAAG,IAAI,CAE7D;AAID,QAAA,MAAM,qBAAqB,EAAE,aAyE5B,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * v2.6 — Pattern refactoring-aware-merge (priority 25, expérimental, opt-in).
3
+ *
4
+ * Détecte les conflits causés par des refactorings concurrents (renommages,
5
+ * déplacements de méthode) et délègue la résolution au pipeline RefMerge.
6
+ *
7
+ * ## Position dans la hiérarchie
8
+ *
9
+ * Priority 25 — après les patterns trivials (1–10) mais avant les patterns
10
+ * heuristiques (whitespace: 5, value_only: 8, non_overlapping: 4). En pratique,
11
+ * ce pattern n'est évalué que sur les hunks qui ont déjà résisté aux patterns
12
+ * plus simples, car ceux-ci ont une priorité inférieure (numéro plus petit).
13
+ *
14
+ * Attendez — la convention est : **plus petit = évalué en premier**. Donc 25
15
+ * signifie évalué AVANT whitespace_only (5) ? Non — whitespace (5) est évalué
16
+ * avant RefMerge (25). Les patterns à faible numéro sont prioritaires.
17
+ *
18
+ * RefMerge à priority 25 est évalué :
19
+ * - APRÈS non_overlapping (4), whitespace_only (5), reorder_only (6),
20
+ * insertion_at_boundary (7), value_only_change (8)
21
+ * - AVANT complex (999) et llm_proposed (998)
22
+ *
23
+ * C'est intentionnel : on ne tente RefMerge que si les patterns textuels simples
24
+ * n'ont pas suffi, car RefMerge est plus coûteux (tokenisation + détection).
25
+ *
26
+ * ## Activation
27
+ *
28
+ * Ce pattern est désactivé par défaut. Il s'active via `setRefMergeEnabled(true)`
29
+ * appelé par `resolve()` quand `options.refactoringAware.enabled === true`.
30
+ * Le flag est réinitialisé après chaque appel à `resolve()`.
31
+ *
32
+ * ## Résolution
33
+ *
34
+ * `detect()` exécute le pipeline RefMerge complet et cache le résultat dans
35
+ * `_lastResult`. Si le pipeline réussit (`lines !== null`), detect retourne `true`
36
+ * et `assembleResolution()` peut récupérer les lignes via `getLastRefMergeResult()`.
37
+ */
38
+ import { makeScore, scopeImpact } from "./utils.js";
39
+ import { tryRefMerge } from "../refactoring/orchestration.js";
40
+ // ─── État module ──────────────────────────────────────────────────────────────
41
+ /** Flag d'activation — positionné par `resolve()` */
42
+ let _refMergeEnabled = false;
43
+ /** Quota maximum de refactorings par branche */
44
+ let _maxRefactoringsPerSide = 10;
45
+ /** Dernier résultat RefMerge (cache pour éviter un double calcul detect+assemble) */
46
+ let _lastResult = null;
47
+ // ─── API d'activation (consommée par resolver/index.ts) ──────────────────────
48
+ /** Active ou désactive le pattern RefMerge pour la prochaine résolution. */
49
+ export function setRefMergeEnabled(enabled, max = 10) {
50
+ _refMergeEnabled = enabled;
51
+ _maxRefactoringsPerSide = max;
52
+ _lastResult = null; // reset cache
53
+ }
54
+ /** Retourne l'état d'activation courant (utile pour les tests). */
55
+ export function isRefMergeEnabled() {
56
+ return _refMergeEnabled;
57
+ }
58
+ /**
59
+ * Retourne le dernier résultat RefMerge mis en cache par `detect()`.
60
+ * Appelé par `assembleResolution()` pour récupérer les lignes sans recalcul.
61
+ * Retourne `null` si `detect()` n'a pas encore été appelé ou si le résultat a été reset.
62
+ */
63
+ export function getLastRefMergeResult() {
64
+ return _lastResult;
65
+ }
66
+ // ─── Plugin ───────────────────────────────────────────────────────────────────
67
+ const refactoringAwareMerge = {
68
+ type: "refactoring_aware_merge",
69
+ /**
70
+ * Priority 970 — évalué après tous les patterns textuels (10–60) mais avant
71
+ * llm_proposed (998) et complex (999). RefMerge est un recours pour les hunks
72
+ * que tous les patterns simples ont échoué à résoudre.
73
+ */
74
+ priority: 970,
75
+ /**
76
+ * Nécessite la base (diff3) pour détecter correctement les refactorings.
77
+ * Sans base, impossible de calculer ce qui a changé de chaque côté.
78
+ */
79
+ requires: "diff3",
80
+ detect(h) {
81
+ if (!_refMergeEnabled)
82
+ return false;
83
+ if (h.baseLines.length === 0)
84
+ return false;
85
+ // Exécuter le pipeline RefMerge complet et cacher le résultat
86
+ const result = tryRefMerge(h, _maxRefactoringsPerSide);
87
+ _lastResult = result;
88
+ return result.lines !== null;
89
+ },
90
+ confidence(h) {
91
+ return makeScore(82, // typeClassification : refactoring bijectivement vérifié + merge réussi
92
+ 12, // dataRisk : faible — merge déterministe, pas génératif
93
+ scopeImpact(h.oursLines.length + h.theirsLines.length), [
94
+ "Refactoring bijectivement vérifié (substitution simulée)",
95
+ "Merge textuel réussi sur les versions inversées",
96
+ ], []);
97
+ },
98
+ explanation(_h) {
99
+ if (_lastResult) {
100
+ const refs = [..._lastResult.oursRefs, ..._lastResult.theirsRefs];
101
+ const renames = refs.filter((r) => r.kind !== "move-method");
102
+ const moves = refs.filter((r) => r.kind === "move-method");
103
+ const parts = [];
104
+ if (renames.length > 0) {
105
+ parts.push(`${renames.length} renommage(s) détecté(s) et inversé(s)`);
106
+ }
107
+ if (moves.length > 0) {
108
+ parts.push(`${moves.length} déplacement(s) de méthode`);
109
+ }
110
+ return `Conflit de refactoring — ${parts.join(", ") || "refactoring détecté"}. Résolu via le pipeline RefMerge (inversion + merge + rejeu).`;
111
+ }
112
+ return "Conflit causé par un refactoring concurrent — résolu via le pipeline RefMerge.";
113
+ },
114
+ passReason(_h) {
115
+ if (_lastResult?.oursRefs.length || _lastResult?.theirsRefs.length) {
116
+ return `Refactoring(s) détecté(s) : ours=${_lastResult.oursRefs.length}, theirs=${_lastResult.theirsRefs.length}. Merge textuel réussi après inversion.`;
117
+ }
118
+ return "Refactoring bijectivement détecté — merge réussi après inversion.";
119
+ },
120
+ failReason(_h) {
121
+ if (!_refMergeEnabled) {
122
+ return "RefMerge désactivé (options.refactoringAware.enabled !== true).";
123
+ }
124
+ if (_lastResult && _lastResult.lines === null) {
125
+ return `RefMerge échoué : ${_lastResult.reason}`;
126
+ }
127
+ return "Aucun refactoring bijectivement détectable dans ce hunk.";
128
+ },
129
+ };
130
+ export default refactoringAwareMerge;
131
+ //# sourceMappingURL=refactoring-aware-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refactoring-aware-merge.js","sourceRoot":"","sources":["../../src/patterns/refactoring-aware-merge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * GitWand v2.6 — Détection de refactorings (expérimental)
3
+ *
4
+ * Détecte les refactorings entre la version de base d'un fichier et une branche
5
+ * (ours ou theirs). Utilisé par le pipeline RefMerge avant la résolution textuelle.
6
+ *
7
+ * ## Algorithme
8
+ *
9
+ * La détection est **purement textuelle** (zero dépendance, compatible browser) :
10
+ *
11
+ * ### rename-local / rename-top-level
12
+ * 1. Tokeniser base et branch en listes d'identifiants (sans mots-clés).
13
+ * 2. Identifier les tokens présents uniquement dans base (`removed`) et
14
+ * uniquement dans branch (`added`).
15
+ * 3. Pour chaque paire (oldName, newName) dont le compte d'occurrences est
16
+ * identique ET unique dans le groupe, construire une substitution candidate.
17
+ * 4. Appliquer toutes les substitutions simultanément sur la séquence base.
18
+ * 5. Si la séquence obtenue == séquence branch : les renames sont confirmés.
19
+ * 6. Classifier rename-local vs rename-top-level selon le contexte syntaxique.
20
+ *
21
+ * ### move-method
22
+ * Parser léger ligne par ligne pour extraire `Map<className → Set<methodName>>`.
23
+ * Détecter les méthodes ayant changé de classe entre base et branch.
24
+ *
25
+ * ## Garanties
26
+ * - Retourne `[]` en cas d'erreur ou d'absence de tree-sitter (safe by default).
27
+ * - Zéro import Node.js — compatible browser, Node.js, Tauri WebView.
28
+ * - Complexité O(n) sur la longueur du code (n = nombre de tokens).
29
+ */
30
+ import type { Refactoring } from "../types.js";
31
+ /**
32
+ * Détecte les refactorings entre la version de base d'un fichier et une branche.
33
+ *
34
+ * Point d'entrée principal du module. Appelé deux fois par l'orchestrateur
35
+ * RefMerge — une fois pour `(base, ours)`, une fois pour `(base, theirs)`.
36
+ *
37
+ * @param baseLines Lignes du fichier dans la version de base (ancêtre commun)
38
+ * @param branchLines Lignes du fichier dans la branche (ours ou theirs)
39
+ * @param maxRefactorings Quota maximum de refactorings retournés (défaut: 10)
40
+ * @returns Liste des refactorings détectés, triée par type de confiance
41
+ * (rename-top-level > rename-local > move-method).
42
+ * Retourne `[]` en cas d'erreur ou si aucun refactoring détecté.
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * const refs = detectRefactorings(
47
+ * ["function foo(x) { return x + 1; }"],
48
+ * ["function foo(value) { return value + 1; }"],
49
+ * );
50
+ * // refs = [{ kind: "rename-local", oldName: "x", newName: "value", scope: "foo" }]
51
+ * ```
52
+ */
53
+ export declare function detectRefactorings(baseLines: string[], branchLines: string[], maxRefactorings?: number): Refactoring[];
54
+ //# sourceMappingURL=detect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/refactoring/detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAoX/C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,EAAE,EACrB,eAAe,SAAK,GACnB,WAAW,EAAE,CA2Bf"}
@@ -0,0 +1,389 @@
1
+ /**
2
+ * GitWand v2.6 — Détection de refactorings (expérimental)
3
+ *
4
+ * Détecte les refactorings entre la version de base d'un fichier et une branche
5
+ * (ours ou theirs). Utilisé par le pipeline RefMerge avant la résolution textuelle.
6
+ *
7
+ * ## Algorithme
8
+ *
9
+ * La détection est **purement textuelle** (zero dépendance, compatible browser) :
10
+ *
11
+ * ### rename-local / rename-top-level
12
+ * 1. Tokeniser base et branch en listes d'identifiants (sans mots-clés).
13
+ * 2. Identifier les tokens présents uniquement dans base (`removed`) et
14
+ * uniquement dans branch (`added`).
15
+ * 3. Pour chaque paire (oldName, newName) dont le compte d'occurrences est
16
+ * identique ET unique dans le groupe, construire une substitution candidate.
17
+ * 4. Appliquer toutes les substitutions simultanément sur la séquence base.
18
+ * 5. Si la séquence obtenue == séquence branch : les renames sont confirmés.
19
+ * 6. Classifier rename-local vs rename-top-level selon le contexte syntaxique.
20
+ *
21
+ * ### move-method
22
+ * Parser léger ligne par ligne pour extraire `Map<className → Set<methodName>>`.
23
+ * Détecter les méthodes ayant changé de classe entre base et branch.
24
+ *
25
+ * ## Garanties
26
+ * - Retourne `[]` en cas d'erreur ou d'absence de tree-sitter (safe by default).
27
+ * - Zéro import Node.js — compatible browser, Node.js, Tauri WebView.
28
+ * - Complexité O(n) sur la longueur du code (n = nombre de tokens).
29
+ */
30
+ // ─── Constantes ───────────────────────────────────────────────────────────────
31
+ /**
32
+ * Regex des identifiants JavaScript/TypeScript valides.
33
+ * Capture les noms de variables, fonctions, classes, paramètres.
34
+ * Reset de lastIndex requis avant chaque utilisation (flag `g`).
35
+ */
36
+ const IDENT_RE = /[A-Za-z_$][A-Za-z0-9_$]*/g;
37
+ /**
38
+ * Mots-clés JS/TS exclus de la détection de renommage.
39
+ * Un mot-clé ne peut pas être "renommé" — ce serait un faux positif.
40
+ */
41
+ const KEYWORDS = new Set([
42
+ "abstract", "any", "as", "async", "await", "bigint", "boolean", "break",
43
+ "case", "catch", "class", "const", "constructor", "continue", "debugger",
44
+ "declare", "default", "delete", "do", "else", "enum", "export", "extends",
45
+ "false", "finally", "for", "from", "function", "get", "if", "implements",
46
+ "import", "in", "infer", "instanceof", "interface", "intrinsic", "is",
47
+ "keyof", "let", "module", "namespace", "never", "new", "null", "number",
48
+ "object", "of", "out", "override", "package", "private", "protected",
49
+ "public", "readonly", "require", "return", "satisfies", "set", "static",
50
+ "string", "super", "switch", "symbol", "this", "throw", "true", "try",
51
+ "type", "typeof", "undefined", "unique", "unknown", "using", "var", "void",
52
+ "while", "with", "yield",
53
+ ]);
54
+ // ─── Utilitaires de tokenisation ─────────────────────────────────────────────
55
+ /**
56
+ * Extrait la liste ordonnée des identifiants non-mot-clé d'un bloc de code.
57
+ * L'ordre est préservé — c'est la "séquence de tokens" utilisée pour la
58
+ * vérification de substitution bijective.
59
+ */
60
+ function tokenize(lines) {
61
+ const text = lines.join("\n");
62
+ const tokens = [];
63
+ IDENT_RE.lastIndex = 0;
64
+ let m;
65
+ while ((m = IDENT_RE.exec(text)) !== null) {
66
+ const tok = m[0];
67
+ if (!KEYWORDS.has(tok))
68
+ tokens.push(tok);
69
+ }
70
+ return tokens;
71
+ }
72
+ /** Compte les occurrences de chaque token. */
73
+ function freqMap(tokens) {
74
+ const map = new Map();
75
+ for (const tok of tokens)
76
+ map.set(tok, (map.get(tok) ?? 0) + 1);
77
+ return map;
78
+ }
79
+ /** Vérifie l'égalité élément par élément de deux tableaux de strings. */
80
+ function arraysEqual(a, b) {
81
+ if (a.length !== b.length)
82
+ return false;
83
+ for (let i = 0; i < a.length; i++) {
84
+ if (a[i] !== b[i])
85
+ return false;
86
+ }
87
+ return true;
88
+ }
89
+ /** Échappe les caractères spéciaux pour une utilisation dans un RegExp. */
90
+ function escapeRegex(s) {
91
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
92
+ }
93
+ /**
94
+ * Génère toutes les permutations d'un tableau de strings.
95
+ * Utilisé pour résoudre les groupes de renommages ambigus (même count d'occurrences).
96
+ * Limité à des tableaux de taille ≤ 4 (max 24 permutations) pour éviter l'explosion combinatoire.
97
+ */
98
+ function permutations(arr) {
99
+ if (arr.length <= 1)
100
+ return [[...arr]];
101
+ const result = [];
102
+ for (let i = 0; i < arr.length; i++) {
103
+ const first = arr[i];
104
+ const rest = [...arr.slice(0, i), ...arr.slice(i + 1)];
105
+ for (const perm of permutations(rest)) {
106
+ result.push([first, ...perm]);
107
+ }
108
+ }
109
+ return result;
110
+ }
111
+ /**
112
+ * Cherche récursivement une assignation valide (substMap) pour les groupes ambigus.
113
+ * Pour chaque groupe ambigu restant, essaie toutes les permutations de `news`
114
+ * et valide via la vérification bijective complète.
115
+ *
116
+ * @returns La substMap complète si une assignation valide est trouvée, sinon null.
117
+ */
118
+ function resolveAmbiguous(baseToks, branchToks, current, remaining) {
119
+ if (remaining.length === 0) {
120
+ // Vérification bijective finale : toutes les substitutions appliquées simultanément
121
+ const substituted = baseToks.map((t) => current.get(t) ?? t);
122
+ return arraysEqual(substituted, branchToks) ? current : null;
123
+ }
124
+ const [group, ...rest] = remaining;
125
+ for (const perm of permutations(group.news)) {
126
+ const candidate = new Map(current);
127
+ for (let i = 0; i < group.olds.length; i++) {
128
+ candidate.set(group.olds[i], perm[i]);
129
+ }
130
+ const result = resolveAmbiguous(baseToks, branchToks, candidate, rest);
131
+ if (result !== null)
132
+ return result;
133
+ }
134
+ return null;
135
+ }
136
+ // ─── Détection de renommages ──────────────────────────────────────────────────
137
+ /**
138
+ * Détecte les renommages uniformes entre base et branch.
139
+ *
140
+ * Algorithme de substitution bijective simultanée :
141
+ * 1. Tokens présents uniquement dans base → candidats `oldName`.
142
+ * 2. Tokens présents uniquement dans branch → candidats `newName`.
143
+ * 3. Grouper par nombre d'occurrences. Un groupe est "non ambigu" ssi
144
+ * exactement un oldName et un newName ont ce compte (signal fort).
145
+ * 4. Appliquer toutes les substitutions simultanément sur baseToks.
146
+ * 5. Si la séquence résultante == branchToks : tous les renames sont confirmés.
147
+ *
148
+ * Cette vérification simultanée gère correctement le cas multi-rename
149
+ * (ex: deux variables renommées en même temps dans le même hunk).
150
+ */
151
+ function detectRenames(baseLines, branchLines, max) {
152
+ const baseToks = tokenize(baseLines);
153
+ const branchToks = tokenize(branchLines);
154
+ if (baseToks.length === 0 || branchToks.length === 0)
155
+ return [];
156
+ const baseFreq = freqMap(baseToks);
157
+ const branchFreq = freqMap(branchToks);
158
+ // Tokens uniquement dans base (disparus → anciens noms candidats)
159
+ const onlyInBase = [...baseFreq.entries()].filter(([tok]) => !branchFreq.has(tok));
160
+ // Tokens uniquement dans branch (apparus → nouveaux noms candidats)
161
+ const onlyInBranch = new Map([...branchFreq.entries()].filter(([tok]) => !baseFreq.has(tok)));
162
+ if (onlyInBase.length === 0 || onlyInBranch.size === 0)
163
+ return [];
164
+ // Grouper par compte d'occurrences pour la correspondance non-ambiguë
165
+ const byCount = new Map();
166
+ for (const [tok, cnt] of onlyInBase) {
167
+ const g = byCount.get(cnt) ?? { old: [], next: [] };
168
+ g.old.push(tok);
169
+ byCount.set(cnt, g);
170
+ }
171
+ for (const [tok, cnt] of onlyInBranch) {
172
+ const g = byCount.get(cnt) ?? { old: [], next: [] };
173
+ g.next.push(tok);
174
+ byCount.set(cnt, g);
175
+ }
176
+ // Construire la map de substitution.
177
+ // Groupes non-ambigus (1 old → 1 new) : assignation directe.
178
+ // Groupes ambigus (plusieurs olds/news avec le même count) : on tente toutes
179
+ // les permutations via resolveAmbiguous() et la vérification bijective finale.
180
+ const unambiguousMap = new Map();
181
+ const ambiguousGroups = [];
182
+ for (const { old, next } of byCount.values()) {
183
+ if (old.length === 1 && next.length === 1) {
184
+ unambiguousMap.set(old[0], next[0]);
185
+ }
186
+ else if (old.length === next.length && old.length >= 2 && old.length <= 4) {
187
+ // Même cardinalité — potentiellement bijectif, à résoudre par permutation
188
+ ambiguousGroups.push({ olds: old, news: next });
189
+ }
190
+ // Cardinalités différentes → pas bijectif, ignoré
191
+ }
192
+ if (unambiguousMap.size === 0 && ambiguousGroups.length === 0)
193
+ return [];
194
+ // Trouver une assignation valide (vérification bijective sur la séquence complète)
195
+ const substMap = resolveAmbiguous(baseToks, branchToks, unambiguousMap, ambiguousGroups);
196
+ if (!substMap)
197
+ return [];
198
+ // Tous les renames sont confirmés — construire les objets Refactoring
199
+ const results = [];
200
+ for (const [oldName, newName] of substMap) {
201
+ if (results.length >= max)
202
+ break;
203
+ const kind = classifyRenameKind(baseLines, oldName);
204
+ results.push({
205
+ kind,
206
+ oldName,
207
+ newName,
208
+ scope: kind === "rename-local" ? extractScope(baseLines, oldName) : undefined,
209
+ });
210
+ }
211
+ return results;
212
+ }
213
+ /**
214
+ * Classifie un renommage en "rename-local" ou "rename-top-level".
215
+ *
216
+ * Heuristique : si le symbole apparaît comme nom dans une déclaration
217
+ * `function X`, `class X`, `async function X`, ou `export function X`
218
+ * au niveau top-level (début de ligne, indentation minimale), c'est top-level.
219
+ *
220
+ * Sinon : on suppose que c'est un renommage local (variable, paramètre).
221
+ */
222
+ function classifyRenameKind(baseLines, name) {
223
+ const escapedName = escapeRegex(name);
224
+ const topLevel = new RegExp(`^[ \\t]{0,2}(?:export\\s+)?(?:default\\s+)?(?:async\\s+)?(?:function|class)\\s+${escapedName}\\b`, "m");
225
+ const text = baseLines.join("\n");
226
+ return topLevel.test(text) ? "rename-top-level" : "rename-local";
227
+ }
228
+ /**
229
+ * Extrait le nom de la fonction englobante (portée) d'un renommage local.
230
+ *
231
+ * Utilisé pour remplir `Refactoring.scope` → permet à `invert.ts` de
232
+ * limiter la substitution inverse à la bonne portée lors du rejeu.
233
+ *
234
+ * Stratégie : cherche la dernière déclaration de fonction `function X(`
235
+ * ou `const X = (` qui précède la première occurrence du symbole renommé.
236
+ */
237
+ function extractScope(baseLines, name) {
238
+ const text = baseLines.join("\n");
239
+ const nameIdx = text.indexOf(name);
240
+ if (nameIdx === -1)
241
+ return undefined;
242
+ const before = text.slice(0, nameIdx);
243
+ // Pattern 1 : `function X(` ou `async function X(`
244
+ const funcMatches = [...before.matchAll(/(?:async\s+)?function\s+(\w+)\s*\(/g)];
245
+ if (funcMatches.length > 0) {
246
+ return funcMatches[funcMatches.length - 1][1];
247
+ }
248
+ // Pattern 2 : `const/let X = (` → arrow function
249
+ const arrowMatches = [...before.matchAll(/(?:const|let|var)\s+(\w+)\s*=/g)];
250
+ if (arrowMatches.length > 0) {
251
+ return arrowMatches[arrowMatches.length - 1][1];
252
+ }
253
+ return undefined;
254
+ }
255
+ /**
256
+ * Parse ligne par ligne pour extraire la carte des méthodes par classe.
257
+ *
258
+ * Suit la profondeur des accolades pour déterminer quand on sort d'une classe.
259
+ * Ne gère pas les classes imbriquées (cas rare, accepté comme limitation).
260
+ */
261
+ function extractClassMethods(lines) {
262
+ const result = new Map();
263
+ let currentClass = null;
264
+ let braceDepth = 0;
265
+ let classEntryDepth = -1;
266
+ for (const line of lines) {
267
+ // Détecter une déclaration de classe
268
+ const classMatch = line.match(/^\s{0,4}(?:export\s+)?(?:default\s+)?(?:abstract\s+)?class\s+(\w+)/);
269
+ if (classMatch && classMatch[1]) {
270
+ currentClass = classMatch[1];
271
+ classEntryDepth = braceDepth;
272
+ if (!result.has(currentClass))
273
+ result.set(currentClass, new Set());
274
+ }
275
+ // Compter les accolades pour suivre la portée
276
+ for (const ch of line) {
277
+ if (ch === "{") {
278
+ braceDepth++;
279
+ }
280
+ else if (ch === "}") {
281
+ braceDepth--;
282
+ // Si on sort de la profondeur d'entrée de la classe → fin de classe
283
+ if (currentClass !== null && braceDepth <= classEntryDepth) {
284
+ currentClass = null;
285
+ classEntryDepth = -1;
286
+ }
287
+ }
288
+ }
289
+ // Détecter les méthodes dans la classe courante
290
+ // (indentation > 0, suivi de `name(` avec modificateurs optionnels)
291
+ if (currentClass !== null) {
292
+ const methodMatch = line.match(/^\s{2,}(?:(?:public|private|protected|static|async|abstract|override|readonly)\s+)*([A-Za-z_$][A-Za-z0-9_$]*)\s*(?:<[^>]*>)?\s*\(/);
293
+ if (methodMatch && methodMatch[1]) {
294
+ const methodName = methodMatch[1];
295
+ if (!KEYWORDS.has(methodName) && methodName !== "constructor") {
296
+ result.get(currentClass).add(methodName);
297
+ }
298
+ }
299
+ }
300
+ }
301
+ return result;
302
+ }
303
+ /**
304
+ * Détecte les déplacements de méthode entre classes.
305
+ *
306
+ * Pour chaque méthode présente dans une classe `C` de base :
307
+ * - Si la méthode a disparu de `C` dans branch ET est apparue dans `D` (D ≠ C) :
308
+ * → move-method(method, C → D).
309
+ */
310
+ function detectMoveMethod(baseLines, branchLines, max) {
311
+ const baseClasses = extractClassMethods(baseLines);
312
+ const branchClasses = extractClassMethods(branchLines);
313
+ // Au moins deux classes dans base pour qu'un move soit possible
314
+ if (baseClasses.size === 0 || branchClasses.size === 0)
315
+ return [];
316
+ const results = [];
317
+ for (const [sourceClass, baseMethods] of baseClasses) {
318
+ for (const method of baseMethods) {
319
+ if (results.length >= max)
320
+ break;
321
+ // La méthode doit avoir disparu de sa classe d'origine dans branch
322
+ const stillHere = branchClasses.get(sourceClass)?.has(method) ?? false;
323
+ if (stillHere)
324
+ continue;
325
+ // Chercher dans quelle autre classe elle est apparue
326
+ for (const [targetClass, targetMethods] of branchClasses) {
327
+ if (targetClass === sourceClass)
328
+ continue;
329
+ if (targetMethods.has(method)) {
330
+ results.push({
331
+ kind: "move-method",
332
+ oldName: method,
333
+ sourceClass,
334
+ targetClass,
335
+ });
336
+ break;
337
+ }
338
+ }
339
+ }
340
+ }
341
+ return results;
342
+ }
343
+ // ─── API publique ─────────────────────────────────────────────────────────────
344
+ /**
345
+ * Détecte les refactorings entre la version de base d'un fichier et une branche.
346
+ *
347
+ * Point d'entrée principal du module. Appelé deux fois par l'orchestrateur
348
+ * RefMerge — une fois pour `(base, ours)`, une fois pour `(base, theirs)`.
349
+ *
350
+ * @param baseLines Lignes du fichier dans la version de base (ancêtre commun)
351
+ * @param branchLines Lignes du fichier dans la branche (ours ou theirs)
352
+ * @param maxRefactorings Quota maximum de refactorings retournés (défaut: 10)
353
+ * @returns Liste des refactorings détectés, triée par type de confiance
354
+ * (rename-top-level > rename-local > move-method).
355
+ * Retourne `[]` en cas d'erreur ou si aucun refactoring détecté.
356
+ *
357
+ * @example
358
+ * ```ts
359
+ * const refs = detectRefactorings(
360
+ * ["function foo(x) { return x + 1; }"],
361
+ * ["function foo(value) { return value + 1; }"],
362
+ * );
363
+ * // refs = [{ kind: "rename-local", oldName: "x", newName: "value", scope: "foo" }]
364
+ * ```
365
+ */
366
+ export function detectRefactorings(baseLines, branchLines, maxRefactorings = 10) {
367
+ try {
368
+ if (baseLines.length === 0 || branchLines.length === 0)
369
+ return [];
370
+ // Cas trivial : contenus identiques — aucun refactoring
371
+ if (arraysEqual(baseLines, branchLines))
372
+ return [];
373
+ const results = [];
374
+ // 1. Renames (rename-local + rename-top-level) — priorité haute
375
+ const renames = detectRenames(baseLines, branchLines, maxRefactorings);
376
+ results.push(...renames);
377
+ // 2. Move-method — uniquement si quota non épuisé
378
+ if (results.length < maxRefactorings) {
379
+ const moves = detectMoveMethod(baseLines, branchLines, maxRefactorings - results.length);
380
+ results.push(...moves);
381
+ }
382
+ return results;
383
+ }
384
+ catch {
385
+ // Dégradation silencieuse — jamais crasher l'orchestrateur
386
+ return [];
387
+ }
388
+ }
389
+ //# sourceMappingURL=detect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/refactoring/detect.ts"],"names":[],"mappings":"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"}