1111
1212public class LKQLToLkt implements Refactoring {
1313
14+ /** Pointer to last-entered selector during rewriting. */
15+ private Liblkqllang .SelectorDecl currentSelector = Liblkqllang .SelectorDecl .NONE ;
16+
1417 @ Override
1518 public void applyRefactor (Refactoring .State state ) {
1619 final var root = state .unit .getRoot ();
@@ -30,11 +33,15 @@ private String refactorNode(Liblkqllang.LkqlNode node) {
3033 case Liblkqllang .ParameterDecl paramDecl -> refactorParamDecl (paramDecl );
3134 case Liblkqllang .Match match -> refactorMatch (match );
3235 case Liblkqllang .MatchArm arm -> refactorArm (arm , arm .fPattern (), arm .fExpr ());
36+ case Liblkqllang .SelectorArm arm -> refactorArm (arm , arm .fPattern (), arm .fExpr ());
3337 case Liblkqllang .SelectorDecl selectorDecl -> refactorSelectorDecl (selectorDecl );
38+ case Liblkqllang .RecExpr recExpr -> refactorRecExpr (recExpr );
3439 case Liblkqllang .BlockBodyExpr bbe -> "var _ = " + refactorGeneric (bbe );
40+ case Liblkqllang .UnitLiteral _ -> "Unit()" ;
3541 case Liblkqllang .Expr expr when (
3642 expr .parent () instanceof Liblkqllang .TopLevelList
3743 ) -> "val _ = " + refactorGeneric (expr );
44+ case Liblkqllang .UniversalPattern _ -> "_" ;
3845 default -> refactorGeneric (node );
3946 };
4047 }
@@ -185,4 +192,86 @@ private String refactorArm(
185192 textRange (expr .tokenEnd ().next (), arm .tokenEnd ())
186193 );
187194 }
195+
196+ /*
197+ *
198+ * <annotations> selector <name> <docstring> <arms>
199+ *
200+ * <docstring>\n
201+ * <annotations> fun <name> (this : Any) : Any = match this { <arms> }
202+ *
203+ */
204+ private String refactorSelectorDecl (Liblkqllang .SelectorDecl selectorDecl ) {
205+ // save selector state on entering this function
206+ var previousSelector = currentSelector ;
207+ // set new state for nested refactors
208+ currentSelector = selectorDecl ;
209+ var s = "" ;
210+
211+ // pull docstring before declaration
212+ if (!selectorDecl .fDocNode ().isNone ()) s = refactorNode (selectorDecl .fDocNode ()) + "\n " ;
213+
214+ if (!selectorDecl .fAnnotation ().isNone ()) s +=
215+ refactorNode (selectorDecl .fAnnotation ()) +
216+ selectorDecl .fAnnotation ().tokenEnd ().next ().getText ();
217+
218+ final var whitespace = textRange (
219+ (selectorDecl .fDocNode ().isNone ()
220+ ? selectorDecl .fName ().tokenEnd ().next ()
221+ : selectorDecl .fDocNode ().tokenEnd ().next ()),
222+ selectorDecl .fArms ().tokenStart ().previous ()
223+ );
224+
225+ s +=
226+ "fun " +
227+ refactorNode (selectorDecl .fName ()) +
228+ "(this : Any) : Any = match this {" +
229+ whitespace +
230+ refactorNode (selectorDecl .fArms ()) +
231+ "\n }\n " ;
232+
233+ // restore previous state on exiting this function
234+ currentSelector = previousSelector ;
235+ return s ;
236+ }
237+
238+ /*
239+ *
240+ * 1) Expansion of implicit argument
241+ *
242+ * rec(<expr>) --> rec(<expr>, <expr>)
243+ *
244+ * 2) Case disjonction
245+ *
246+ * rec( <left>, <right>) --> <right> :: <selector>(<left>)
247+ * rec(*<left>, <right>) --> <right> :: <left>.iterator.flatMap(<selector>)
248+ * rec( <left>, *<right>) --> <right>.iterator ::: <selector>(<left>)
249+ * rec(*<left>, *<right>) --> <right>.iterator ::: <left>.iterator.flatMap(<selector>)
250+ *
251+ */
252+ private String refactorRecExpr (Liblkqllang .RecExpr recExpr ) {
253+ final var hasRight = !recExpr .fResultExpr ().isNone ();
254+
255+ final var unpackLeft = recExpr .fRecurseUnpack ().pAsBool ();
256+ final var unpackRight = hasRight ? recExpr .fResultUnpack ().pAsBool () : unpackLeft ;
257+
258+ final var left = recExpr .fRecurseExpr ();
259+ final var right = hasRight ? recExpr .fResultExpr () : left ;
260+
261+ var s = unpackRight ? refactorNode (right ) + ".iterator :::" : refactorNode (right ) + " ::" ;
262+
263+ // try to preserve spacing after "," (any newline for example)
264+ if (hasRight && left .tokenEnd ().next ().getText ().equals ("," )) {
265+ for (var tok = left .tokenEnd ().next ().next (); tok .isTrivia (); tok = tok .next ()) s +=
266+ tok .getText ();
267+ } else {
268+ s += " " ;
269+ }
270+
271+ s += unpackLeft
272+ ? refactorNode (left ) + ".iterator.flatMap(" + currentSelector .fName ().getText () + ")"
273+ : currentSelector .fName ().getText () + "(" + refactorNode (left ) + ")" ;
274+
275+ return s ;
276+ }
188277}
0 commit comments