Class SwitchRetrofittingTaskListener
- All Implemented Interfaces:
TaskListener
This listener will rewrite entirely the switch for a better one.
Instead of placing the guard in the case body, it will be evaluated in the switch condition.
Avoiding restarting the switch everytimes a guard fail,
and storing an index to not reevaluate previous cases.
So this method will convert cases labels into a ternary-chain that will placed in the switch condition.
And case labels will be changed to match their position in the switch.
Also, to avoid double method calls, if the switch condition was a method call,
an uninitialized variable is inserted in the previous line, and then initialized in the ternary-chain.
Same way goes for cases using a record-pattern with a guard using a component from that record.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionclassstatic classTreeCopierthat preserves types and symbols. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidaddBindings(com.sun.tools.javac.tree.JCTree.JCCase caseTree, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCStatement> out) Emits binding variable declarations at the top of a case body.com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCStatement> buildCaseBody(com.sun.tools.javac.tree.JCTree cSwitch, com.sun.tools.javac.tree.JCTree.JCCase c, com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean expression) com.sun.tools.javac.tree.JCTree.JCExpressionbuildEnumSwitchCondition(com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean hasNull, com.sun.tools.javac.tree.JCTree.JCExpression rawSel) Builds a simplesel == null ? -1 : sel.ordinal()condition.com.sun.tools.javac.tree.JCTree.JCExpressionbuildGuard(com.sun.tools.javac.tree.JCTree label, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.tree.JCTree.JCCase src) Returns the guard expression for a pattern slot (with binding substitution), or null if none.voidbuildGuardPreDecls(com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCStatement> out) Pre-declares variables for record components referenced in a guard.com.sun.tools.javac.tree.JCTree.JCExpressionbuildLabelCondition(com.sun.tools.javac.tree.JCTree label, com.sun.tools.javac.tree.JCTree.JCExpression sel) com.sun.tools.javac.tree.JCTree.JCExpressionbuildTypeSwitchCondition(com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean hasNull, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> labels, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> slotCases, com.sun.tools.javac.tree.JCTree.JCExpression rawSel) Builds a ternary chain and groups the same type-pattern.com.sun.tools.javac.tree.JCTree.JCExpressioncaptureSelector(com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCStatement> prefix, boolean init) Map<com.sun.tools.javac.util.Name, com.sun.tools.javac.tree.JCTree.JCExpression> collectBindings(com.sun.tools.javac.tree.JCTree label, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.tree.JCTree.JCCase caseTree) voidextractRecordBindings(com.sun.tools.javac.util.List<? extends com.sun.tools.javac.tree.JCTree> nested, com.sun.tools.javac.tree.JCTree.JCExpression baseAccessor, com.sun.tools.javac.util.List<com.sun.tools.javac.util.Name> componentNames, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCVariableDecl> out) Recursively extract bindings from nested record pattern components.com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> findPatternSwitches(com.sun.tools.javac.tree.JCTree node) voidintgetEnumOrdinal(com.sun.tools.javac.tree.JCTree.JCExpression expr) com.sun.tools.javac.util.List<com.sun.tools.javac.util.Name> getRecordComponentNames(com.sun.tools.javac.tree.JCTree pattern) com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> injectDefault(com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases) Injectsdefault: throw new IncompatibleClassChangeError(...)if no default exists.com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> prepareSwichCases(com.sun.tools.javac.tree.JCTree currentSwitch, com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean isExpression, boolean isEnum, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> labels) voidcom.sun.tools.javac.tree.JCTree.JCSwitchtransformSwitch(com.sun.tools.javac.tree.JCTree currentSwitch, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases, boolean expression, com.sun.tools.javac.tree.JCTree.JCExpression rawSel) Builds the standard switch from a pattern/null switch.
-
Constructor Details
-
SwitchRetrofittingTaskListener
public SwitchRetrofittingTaskListener(com.sun.tools.javac.util.Context context)
-
-
Method Details
-
started
- Specified by:
startedin interfaceTaskListener
-
finished
- Specified by:
finishedin interfaceTaskListener
-
findPatternSwitches
public com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> findPatternSwitches(com.sun.tools.javac.tree.JCTree node) -
transformSwitch
public com.sun.tools.javac.tree.JCTree.JCSwitch transformSwitch(com.sun.tools.javac.tree.JCTree currentSwitch, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases, boolean expression, com.sun.tools.javac.tree.JCTree.JCExpression rawSel) Builds the standard switch from a pattern/null switch. -
prepareSwichCases
public com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> prepareSwichCases(com.sun.tools.javac.tree.JCTree currentSwitch, com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean isExpression, boolean isEnum, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> labels) -
buildEnumSwitchCondition
public com.sun.tools.javac.tree.JCTree.JCExpression buildEnumSwitchCondition(com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean hasNull, com.sun.tools.javac.tree.JCTree.JCExpression rawSel) Builds a simplesel == null ? -1 : sel.ordinal()condition. -
buildTypeSwitchCondition
public com.sun.tools.javac.tree.JCTree.JCExpression buildTypeSwitchCondition(com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean hasNull, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree> labels, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> slotCases, com.sun.tools.javac.tree.JCTree.JCExpression rawSel) Builds a ternary chain and groups the same type-pattern. -
getEnumOrdinal
public int getEnumOrdinal(com.sun.tools.javac.tree.JCTree.JCExpression expr) -
captureSelector
public com.sun.tools.javac.tree.JCTree.JCExpression captureSelector(com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCStatement> prefix, boolean init) -
buildCaseBody
public com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCStatement> buildCaseBody(com.sun.tools.javac.tree.JCTree cSwitch, com.sun.tools.javac.tree.JCTree.JCCase c, com.sun.tools.javac.tree.JCTree.JCExpression sel, boolean expression) -
buildGuard
public com.sun.tools.javac.tree.JCTree.JCExpression buildGuard(com.sun.tools.javac.tree.JCTree label, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.tree.JCTree.JCCase src) Returns the guard expression for a pattern slot (with binding substitution), or null if none. -
buildLabelCondition
public com.sun.tools.javac.tree.JCTree.JCExpression buildLabelCondition(com.sun.tools.javac.tree.JCTree label, com.sun.tools.javac.tree.JCTree.JCExpression sel) -
injectDefault
public com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> injectDefault(com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases) Injectsdefault: throw new IncompatibleClassChangeError(...)if no default exists. -
getRecordComponentNames
public com.sun.tools.javac.util.List<com.sun.tools.javac.util.Name> getRecordComponentNames(com.sun.tools.javac.tree.JCTree pattern) -
collectBindings
public Map<com.sun.tools.javac.util.Name, com.sun.tools.javac.tree.JCTree.JCExpression> collectBindings(com.sun.tools.javac.tree.JCTree label, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.tree.JCTree.JCCase caseTree) -
addBindings
public void addBindings(com.sun.tools.javac.tree.JCTree.JCCase caseTree, com.sun.tools.javac.tree.JCTree.JCExpression sel, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCStatement> out) Emits binding variable declarations at the top of a case body. -
extractRecordBindings
public void extractRecordBindings(com.sun.tools.javac.util.List<? extends com.sun.tools.javac.tree.JCTree> nested, com.sun.tools.javac.tree.JCTree.JCExpression baseAccessor, com.sun.tools.javac.util.List<com.sun.tools.javac.util.Name> componentNames, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCVariableDecl> out) Recursively extract bindings from nested record pattern components.Generates variable declarations like:
final Point $tmp = parent.b(); final int bx = $tmp.x(); final int by = $tmp.y(); -
buildGuardPreDecls
public void buildGuardPreDecls(com.sun.tools.javac.util.List<com.sun.tools.javac.tree.JCTree.JCCase> cases, com.sun.tools.javac.util.ListBuffer<com.sun.tools.javac.tree.JCTree.JCStatement> out) Pre-declares variables for record components referenced in a guard.
These are assigned inline in the ternary-chain viacollectBindings(JCTree, JCTree.JCExpression, JCTree.JCCase), and aliased in the case body viaaddBindings(JCTree.JCCase, JCTree.JCExpression, ListBuffer).
-