From 1e30e6a2289e5b9231619ad31c3a4b5e6e777d3a Mon Sep 17 00:00:00 2001 From: Peter Vanusanik Date: Sat, 28 Jan 2023 04:26:48 -0800 Subject: [PATCH] indentation rewrite --- .../components/SltIndentationContainer.java | 76 ++++++------------- .../resources/templates/en_US/indentation.cl | 2 +- 2 files changed, 23 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltIndentationContainer.java b/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltIndentationContainer.java index 8e612ba..dbe6de5 100644 --- a/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltIndentationContainer.java +++ b/src/main/java/com/en_circle/slt/plugin/services/lisp/components/SltIndentationContainer.java @@ -102,55 +102,47 @@ private void loadBaseIndentation(List definitions) { indentation.ref = ((LispSymbol) definitionArg.getItems().get(1)).getValue().toUpperCase(); } else { indentation.indentationSetup = new ArrayList<>(); - Stack whole = new Stack<>(); - parseIndentation(indentation.indentationSetup, definitionArg, whole, x -> indentation.whole = x); + parseIndentation(indentation.indentationSetup, definitionArg, x -> indentation.whole = x); } } } } - private void parseIndentation(List indentationSetup, LispContainer definitionArg, Stack whole, + private void parseIndentation(List indentationSetup, LispContainer definitionArg, Consumer applyParentWhole) { int ix = 0; - whole.push(0); while (ix < definitionArg.getItems().size()) { LispElement e = definitionArg.getItems().get(ix++); - ix = parseSingleElement(e, definitionArg, indentationSetup, ix, whole, applyParentWhole); + ix = parseSingleElement(e, definitionArg, indentationSetup, ix, applyParentWhole); } - whole.pop(); } private int parseSingleElement(LispElement e, LispContainer definitionArg, List indentationSetup, int ix, - Stack whole, Consumer applyParentWhole) { + Consumer applyParentWhole) { if (e instanceof LispSymbol symbol) { if (symbol.getValue().equalsIgnoreCase("NIL")) { indentationSetup.add(new IndentationSetting()); } else if (symbol.getValue().equals("&lambda")) { IndentationSetting setting = new IndentationSetting(); - setting.whole = whole.peek(); setting.type = IndentationType.LAMBDA; indentationSetup.add(setting); } else if (symbol.getValue().equals("&rest")) { LispElement e2 = definitionArg.getItems().get(ix++); List innerSetting = new ArrayList<>(); - ix = parseSingleElement(e2, definitionArg, innerSetting, ix, whole, applyParentWhole); + ix = parseSingleElement(e2, definitionArg, innerSetting, ix, applyParentWhole); IndentationSetting setting = new IndentationSetting(); - setting.whole = whole.peek(); indentationSetup.add(setting); setting.type = IndentationType.REST; setting.inner = innerSetting.get(0); } else if (symbol.getValue().equals("&body")) { IndentationSetting setting = new IndentationSetting(); - setting.whole = whole.peek(); indentationSetup.add(setting); setting.type = IndentationType.BODY; } else if (symbol.getValue().equals("&whole")) { LispElement e2 = definitionArg.getItems().get(ix++); int wholeAdd = ((LispInteger) e2).getValue().intValue(); - int currentWhole = whole.pop() + (Integer) whole.stream().mapToInt(Integer::intValue).sum(); - whole.push(currentWhole + wholeAdd); if (ix == 2) { - applyParentWhole.accept(currentWhole + wholeAdd); + applyParentWhole.accept(wholeAdd); } } else { String refMethod = symbol.getValue(); @@ -162,15 +154,13 @@ private int parseSingleElement(LispElement e, LispContainer definitionArg, List< } } else if (e instanceof LispInteger integer) { IndentationSetting setting = new IndentationSetting(); - setting.whole = whole.peek(); setting.value = integer.getValue().intValue(); indentationSetup.add(setting); } else if (e instanceof LispContainer container) { IndentationSetting setting = new IndentationSetting(); - setting.whole = whole.peek(); setting.listSetting = new ArrayList<>(); indentationSetup.add(setting); - parseIndentation(setting.listSetting, container, whole, w -> setting.listAdd = w); + parseIndentation(setting.listSetting, container, w -> setting.listAdd = w); } return ix; } @@ -224,7 +214,7 @@ public Integer calculateIndent(PsiElement element, PsiFile file, boolean wasAfte } } else { int numLeftBraces = element.getNode().getElementType() == LispTypes.LPAREN ? 1 : 0; - int numRightBraces = element.getNode().getElementType() == LispTypes.RPAREN ? 1 : 0; + int numRightBraces = 0; PsiElement previousToplevel = element.getPrevSibling(); while (!(previousToplevel instanceof LispToplevel)) { if (previousToplevel == null) @@ -318,8 +308,6 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top hasHead = false; } - // all other offsets, such as whole are added here - int additionalOffset = 0; // applied inner setting, if matched IndentationSetting appliedSetting = null; // root indentation setting, if we matched head @@ -350,7 +338,6 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top // so we skip all rules and just use that base element's indent + new base indent as rule appliedSetting = backtrackIndentation.setting; listOfSettings = backtrackIndentation.listOfSettings; - additionalOffset = backtrackIndentation.parentWhole; toplevelOffset = backtrackIndentation.rulematchedForm; } else { toplevelOffset = backtrackRuleOnlyAppliedTo; @@ -387,7 +374,6 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top // so we skip all rules and just use that base element's indent + new base indent as rule appliedSetting = backtrackIndentation.setting; listOfSettings = backtrackIndentation.listOfSettings; - additionalOffset = backtrackIndentation.parentWhole; toplevelOffset = backtrackIndentation.rulematchedForm; } else { toplevelOffset = backtrackRuleOnlyAppliedTo; @@ -401,7 +387,7 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top if (indentationImplementation != null) { Integer offset = indentationImplementation.calculateOffsetForForm(state, topLevel, container, backTrackStack); if (offset != null) { - return offset + state.formIndentation.getOrDefault(toplevelOffset, OffsetInfo.DEFAULT).parentForm; + return offset; } } @@ -434,9 +420,9 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top // function arguments, and any further arguments like a body. // This is equivalent to (4 4 ... &body). if (argPosWithoutHead < indentation.normalArgumentCount) { - appliedOffset = additionalOffset + state.settings.parameterIndentation; + appliedOffset = state.settings.parameterIndentation; } else { - appliedOffset = additionalOffset + state.settings.bodyIndentation; + appliedOffset = state.settings.bodyIndentation; } } else if (indentation.indentationSetup != null) { // rule has multiple subrules, this handle it same as with backtrack, ie find correct subrule @@ -467,9 +453,6 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top if (appliedSetting != null) { // we actually have a matching rule - // original rule is preserved, so it can be later accessed because - // rest rule overwrites itself with child rule, as seen below - IndentationSetting originalSetting = appliedSetting; if (appliedSetting.type == IndentationType.REST) { // * &rest. When used, this must be the penultimate element. The // element after this one applies to all remaining arguments. @@ -486,32 +469,28 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top } else if (appliedSetting.type == IndentationType.BODY) { // * &body. This is equivalent to &rest lisp-body-indent, i.e., indent // all remaining elements by `lisp-body-indent'. - additionalOffset += findAdditionalOffset(originalSetting); - appliedOffset = additionalOffset + state.settings.bodyIndentation; + appliedOffset = state.settings.bodyIndentation; } else if (appliedSetting.type == IndentationType.LAMBDA) { // * &lambda. Indent the argument (which may be a list) by 4. - additionalOffset += findAdditionalOffset(originalSetting); - appliedOffset = additionalOffset + state.settings.lambdaIndentation; + appliedOffset = state.settings.lambdaIndentation; } } else { // type is null so this rule either has value or is callback or is "list add" if (appliedSetting.value != null) { // just add value - additionalOffset += findAdditionalOffset(originalSetting); - appliedOffset = additionalOffset + appliedSetting.value; + appliedOffset = appliedSetting.value; } else if (appliedSetting.listSetting != null) { // this is "list add" rule, ie rule with listSetting not null but applied directly. // list add rules are list rules that usually start with &whole. // &whole argument is then applied both as list add for main list and as additional add // for all inner rules (this is already calculated and baked into subrules with preserving hierarchy) - appliedOffset = additionalOffset + appliedSetting.listAdd; + appliedOffset = appliedSetting.listAdd; } } } if (appliedSetting != null && appliedSetting.indentationImplementation != null) { // we have callback so honor it - additionalOffset += findAdditionalOffset(originalSetting); indentationImplementation = appliedSetting.indentationImplementation; } } else { @@ -525,19 +504,13 @@ protected Integer calculateIndentForForm(IndentationState state, LispElement top // call callback and let it deal with this shit Integer offset = indentationImplementation.calculateOffsetForForm(state, topLevel, container, backTrackStack); if (offset != null) { - return additionalOffset + offset + state.formIndentation.getOrDefault(toplevelOffset, OffsetInfo.DEFAULT).parentForm; + return offset; } } // general return of indent offset // can be just generic value or calculated value - return appliedOffset + state.formIndentation.getOrDefault(toplevelOffset, OffsetInfo.DEFAULT).parentForm; - } - - private int findAdditionalOffset(IndentationSetting appliedSetting) { - if (appliedSetting != null) - return appliedSetting.whole; - return 0; + return appliedOffset + state.formIndentation.getOrDefault(container, OffsetInfo.DEFAULT).parentForm; } private ManualIndentation getMacroIndentation(String value, String packageName) { @@ -608,7 +581,6 @@ private BacktrackInformation doGetBacktrackIndentation(IndentationState state, // specifies how to indent the associated argument. if (indentation.indentationSetup != null) { int clevel = i; - int parentWhole = 0; boolean first = true; List settings = indentation.indentationSetup; @@ -636,7 +608,6 @@ private BacktrackInformation doGetBacktrackIndentation(IndentationState state, if (clevel == backTrackStack.size() - 1) { information.setting = setting; information.listOfSettings = settings; - information.parentWhole = parentWhole; information.exactHit = true; information.appliesRuleToOnly = null; break; @@ -650,7 +621,6 @@ private BacktrackInformation doGetBacktrackIndentation(IndentationState state, settings = setting.listSetting; } } - parentWhole = setting.whole; ++clevel; first = false; } @@ -700,7 +670,6 @@ private static class IndentationSetting { public List listSetting; public int listAdd; // listSetting != null -> apply this public IndentationImplementation indentationImplementation; - public int whole = 0; @Override public String toString() { @@ -743,7 +712,6 @@ protected static class BacktrackInformation { boolean exactHit = false; IndentationSetting setting; List listOfSettings; - int parentWhole; LispElement appliesRuleToOnly; LispElement rulematchedForm; IndentationImplementation manualCallback; @@ -780,11 +748,11 @@ private Integer lispIndentLoop(IndentationState state, LispElement topLevel, Lis int offsetDedent = state.hasRealElement ? 0 : 1; if (state.hasRealElement) { if (container.getItems().size() == 0) { - return state.settings.defaultIndentation; + return state.settings.defaultIndentation + state.formIndentation.getOrDefault(container, OffsetInfo.DEFAULT).parentForm; } } else { if (container.getItems().size() < 2) { - return state.settings.defaultIndentation; + return state.settings.defaultIndentation + state.formIndentation.getOrDefault(container, OffsetInfo.DEFAULT).parentForm; } } @@ -792,17 +760,17 @@ private Integer lispIndentLoop(IndentationState state, LispElement topLevel, Lis LispElement checkedElement = container.getItems().get(ix - offsetDedent - 1); while (checkedElement instanceof LispSymbol symbol) { if (loopBodyForms.contains(symbol.getValue().toUpperCase())) { - return state.settings.bodyIndentation; + return state.settings.bodyIndentation + state.formIndentation.getOrDefault(container, OffsetInfo.DEFAULT).parentForm; } ix--; int pos = ix - offsetDedent - 1; if (pos < 0) { - return state.settings.defaultIndentation + state.formIndentation.getOrDefault(checkedElement, OffsetInfo.DEFAULT).elementOffset; + return 6 + state.formIndentation.getOrDefault(container, OffsetInfo.DEFAULT).parentForm; } checkedElement = container.getItems().get(pos); } - return state.settings.defaultIndentation + state.formIndentation.getOrDefault(checkedElement, OffsetInfo.DEFAULT).elementOffset; + return 6 + state.formIndentation.getOrDefault(container, OffsetInfo.DEFAULT).parentForm; } private Integer lispIndentDefsetf(IndentationState state, LispElement topLevel, LispContainer container, diff --git a/src/main/resources/templates/en_US/indentation.cl b/src/main/resources/templates/en_US/indentation.cl index 2558d03..48ded77 100644 --- a/src/main/resources/templates/en_US/indentation.cl +++ b/src/main/resources/templates/en_US/indentation.cl @@ -82,7 +82,7 @@ Original license: (restart-case (as handler-case)) (if (&rest nil)) (lambda (&lambda &body)) -(let ((&whole 4 &rest (&whole 2 1 2)) &body)) +(let ((&whole 4 &rest (&whole 1 1 2)) &body)) (let* (as let)) (compiler-let (as let)) (handler-bind (as let))