From 4d8dff725e7c693ac4de21d744b85e3609956338 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Mon, 27 Jun 2016 14:15:53 +0300 Subject: [PATCH] [formatter-core] implemented AdjustFormattingRangesState which extracts extra ranges to reformat, based on current formatting ranges and block structure --- .../formatting/AdjustFormatRangesState.kt | 117 ++++++++++++++++++ .../intellij/formatting/FormatProcessor.java | 10 +- .../com/intellij/formatting/engine/State.java | 2 +- .../psi/formatter/common/AbstractBlock.java | 9 ++ 4 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/formatting/AdjustFormatRangesState.kt diff --git a/platform/lang-impl/src/com/intellij/formatting/AdjustFormatRangesState.kt b/platform/lang-impl/src/com/intellij/formatting/AdjustFormatRangesState.kt new file mode 100644 index 000000000000..4a9585626d78 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/formatting/AdjustFormatRangesState.kt @@ -0,0 +1,117 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.formatting + +import com.intellij.formatting.engine.State +import com.intellij.openapi.util.TextRange +import com.intellij.psi.formatter.common.AbstractBlock +import com.intellij.util.containers.Stack + +interface BlockProcessor { + fun processLeafBlock(block: Block) + fun processCompositeBlock(block: Block) +} + +class AdditionalRangesExtractor : BlockProcessor { + + val additionalRanges = mutableListOf() + + override fun processLeafBlock(block: Block) { + extractAdditionalRange(block) + } + + override fun processCompositeBlock(block: Block) { + extractAdditionalRange(block) + } + + private fun extractAdditionalRange(block: Block) { + if (block is AbstractBlock) { + block.extraRangeToReformat?.let { additionalRanges.add(it) } + } + } + +} + + +class AdjustFormatRangesState(var currentRoot: Block, + val formatRanges: FormatTextRanges) : State() { + + private val extractor = AdditionalRangesExtractor() + private val state = Stack(currentRoot) + + init { + setOnDone({ + extractor.additionalRanges.forEach { formatRanges.add(it, true) } + }) + } + + override fun doIteration() { + val currentBlock = state.pop() + processBlock(currentBlock) + isDone = state.isEmpty() + } + + private fun processBlock(currentBlock: Block) { + if (formatRanges.isReadOnly(currentBlock.textRange, false)) { + extractor.processLeafBlock(currentBlock) + } + else { + val children = currentBlock.subBlocks + if (children.isEmpty()) { + extractor.processLeafBlock(currentBlock) + return + } + + extractor.processCompositeBlock(currentBlock) + + children + .filterNot { formatRanges.isReadOnly(it.textRange, false) } + .reversed() + .forEach { state.push(it) } + } + } + +} \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index caf00cbf450e..c4501427ac56 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -68,7 +68,15 @@ public class FormatProcessor { final InitialInfoBuilder builder = prepareToBuildBlocksSequentially(block, model, options, settings, defaultIndentOption, myProgressCallback); myWrapState = new WrapBlocksState(builder, blockIndentOptions); - myStateProcessor = new StateProcessor(myWrapState); + FormatTextRanges ranges = options.myAffectedRanges; + if (ranges != null) { + AdjustFormatRangesState adjustRangesState = new AdjustFormatRangesState(block, ranges); + myStateProcessor = new StateProcessor(adjustRangesState); + myStateProcessor.setNextState(myWrapState); + } + else { + myStateProcessor = new StateProcessor(myWrapState); + } } public BlockRangesMap getBlockRangesMap() { diff --git a/platform/lang-impl/src/com/intellij/formatting/engine/State.java b/platform/lang-impl/src/com/intellij/formatting/engine/State.java index 77f1760ae594..92c66d6b2eeb 100644 --- a/platform/lang-impl/src/com/intellij/formatting/engine/State.java +++ b/platform/lang-impl/src/com/intellij/formatting/engine/State.java @@ -26,7 +26,7 @@ public abstract class State { } } - public boolean isDone() { + public final boolean isDone() { return myDone; } diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java b/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java index 6310f66298d2..9277d6d8fcf4 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java @@ -178,4 +178,13 @@ public abstract class AbstractBlock implements ASTBlock { public String toString() { return myNode.getText() + " " + getTextRange(); } + + /** + * @return additional range to reformat, when this block if formatted + */ + @Nullable + public TextRange getExtraRangeToReformat() { + return null; + } + }