Merges adjacent steps. @param cc compilation context @return original or new expression @throws QueryException query exception
(final CompileContext cc)
| 948 | * @throws QueryException query exception |
| 949 | */ |
| 950 | private Expr mergeSteps(final CompileContext cc) throws QueryException { |
| 951 | final int sl = steps.length; |
| 952 | final ExprList stps = new ExprList(sl); |
| 953 | return cc.ok(root, true, () -> { |
| 954 | boolean chngd = false; |
| 955 | for(int s = 0; s < sl; s++) { |
| 956 | Expr curr = steps[s]; |
| 957 | if(curr instanceof final Step crr) { |
| 958 | Expr next = s < sl - 1 ? steps[s + 1] : null; |
| 959 | if(crr.test == NodeTest.NODE && next instanceof final Step stp && stp.axis == ATTRIBUTE) { |
| 960 | // rewrite node test before attribute step: node()/@* → */@* |
| 961 | next = Step.get(cc, null, crr.info(), crr.axis, NodeTest.ELEMENT, crr.exprs); |
| 962 | curr = cc.replaceWith(curr, next); |
| 963 | chngd = true; |
| 964 | } else if(next != null) { |
| 965 | // merge steps: //* → /descendant::* |
| 966 | next = mergeStep(crr, next, s > 0 ? steps[s - 1] : root, cc); |
| 967 | if(next != null) { |
| 968 | cc.info(QueryText.OPTMERGE_X, next); |
| 969 | curr = next; |
| 970 | chngd = true; |
| 971 | s++; |
| 972 | } |
| 973 | } |
| 974 | } |
| 975 | stps.add(curr); |
| 976 | cc.updateFocus(curr, true); |
| 977 | } |
| 978 | return chngd; |
| 979 | }) ? get(info, root, stps.finish()) : this; |
| 980 | } |
| 981 | |
| 982 | /** |
| 983 | * Moves predicates downward. |
no test coverage detected