mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
properties: fix update of structure view & resource bundle editor (IDEA-170695)
This commit is contained in:
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.lang.properties.psi.impl;
|
||||
|
||||
import com.intellij.lang.properties.parsing.PropertiesTokenTypes;
|
||||
import com.intellij.lang.properties.psi.PropertiesFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
|
||||
import com.intellij.psi.impl.PsiTreeChangePreprocessorBase;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PropertiesPsiTreeChangePreprocessor extends PsiTreeChangePreprocessorBase {
|
||||
private static final TokenSet CODE_BLOCK_ELEMENTS = TokenSet.create(PropertiesTokenTypes.VALUE_CHARACTERS,
|
||||
PropertiesTokenTypes.END_OF_LINE_COMMENT,
|
||||
PropertiesTokenTypes.WHITE_SPACE,
|
||||
PropertiesTokenTypes.KEY_VALUE_SEPARATOR);
|
||||
|
||||
public PropertiesPsiTreeChangePreprocessor(@NotNull PsiManager psiManager) {
|
||||
super(psiManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onTreeChanged(@NotNull PsiTreeChangeEventImpl event) {
|
||||
if (event.isGenericChange()) return;
|
||||
switch (event.getCode()) {
|
||||
case BEFORE_PROPERTY_CHANGE:
|
||||
case BEFORE_CHILD_REMOVAL:
|
||||
case BEFORE_CHILD_ADDITION:
|
||||
case BEFORE_CHILD_MOVEMENT:
|
||||
case BEFORE_CHILDREN_CHANGE:
|
||||
case BEFORE_CHILD_REPLACEMENT:
|
||||
return;
|
||||
case CHILD_ADDED:
|
||||
if (isCodeBlock(event.getChild())) return;
|
||||
break;
|
||||
case CHILD_REMOVED:
|
||||
if (isCodeBlock(event.getChild())) return;
|
||||
break;
|
||||
case CHILD_REPLACED:
|
||||
if (isCodeBlock(event.getOldChild()) || isCodeBlock(event.getNewChild())) return;
|
||||
break;
|
||||
case CHILD_MOVED:
|
||||
if (isCodeBlock(event.getChild())) return;
|
||||
break;
|
||||
case CHILDREN_CHANGED:
|
||||
if (isCodeBlock(event.getChild())) return;
|
||||
case PROPERTY_CHANGED:
|
||||
break;
|
||||
}
|
||||
doIncOutOfCodeBlockCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptsEvent(@NotNull PsiTreeChangeEventImpl event) {
|
||||
return event.getFile() instanceof PropertiesFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isOutOfCodeBlock(@NotNull PsiElement element) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
private static boolean isCodeBlock(@NotNull PsiElement element) {
|
||||
return CODE_BLOCK_ELEMENTS.contains(PsiUtilCore.getElementType(element));
|
||||
}
|
||||
}
|
||||
@@ -123,6 +123,8 @@
|
||||
|
||||
<lang.inspectionSuppressor language="Properties" implementationClass="com.intellij.codeInspection.PropertiesInspectionSuppressor"/>
|
||||
<qualifiedNameProvider implementation="com.intellij.ide.actions.PropertiesQualifiedNameProvider"/>
|
||||
|
||||
<psi.treeChangePreprocessor implementation="com.intellij.lang.properties.psi.impl.PropertiesPsiTreeChangePreprocessor"/>
|
||||
</extensions>
|
||||
|
||||
<project-components>
|
||||
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.lang.properties;
|
||||
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PropertiesModificationTest extends LightCodeInsightFixtureTestCase {
|
||||
|
||||
public void testValueEditing() {
|
||||
doTestEditing(" # comment<caret>", false);
|
||||
}
|
||||
|
||||
public void testKeyEditing() {
|
||||
doTestEditing("key<caret> = value", true);
|
||||
}
|
||||
|
||||
public void testCommentEditing() {
|
||||
doTestEditing("key = value<caret>", false);
|
||||
}
|
||||
|
||||
public void testKeyReplacement() {
|
||||
doTestReplacement("<selection>key</selection> = value", true);
|
||||
}
|
||||
|
||||
public void testValueReplacement() {
|
||||
doTestReplacement("key = <selection>value</selection>", false);
|
||||
}
|
||||
|
||||
public void testCommentReplacement() {
|
||||
doTestReplacement("key = value \n# <selection>comment</selection> \n key2 = value2", false);
|
||||
}
|
||||
|
||||
public void testKeyDeletion() {
|
||||
doTestDeletion("<selection>key</selection> = value", true);
|
||||
}
|
||||
|
||||
public void testPropertiesDeletion() {
|
||||
doTestDeletion("ke<selection>y1 = value1 \n" +
|
||||
"key2 = value2 \n" +
|
||||
"key3 = value3 \n" +
|
||||
"key4 = value4 \n" +
|
||||
"key5 = val</selection>ue5 \n", true);
|
||||
}
|
||||
|
||||
private void doTestEditing(@NotNull String text, boolean isOutOfBlockModificationExpected) {
|
||||
doTest(text, () -> myFixture.type("xxx"), isOutOfBlockModificationExpected);
|
||||
}
|
||||
|
||||
private void doTestReplacement(@NotNull String text, boolean isOutOfBlockModificationExpected) {
|
||||
doTest(text, () -> WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
SelectionModel sel = getEditor().getSelectionModel();
|
||||
getEditor().getDocument().replaceString(sel.getSelectionStart(), sel.getSelectionEnd(), "xxx");
|
||||
}), isOutOfBlockModificationExpected);
|
||||
}
|
||||
|
||||
private void doTestDeletion(@NotNull String text, boolean isOutOfBlockModificationExpected) {
|
||||
doTest(text, () -> WriteCommandAction.runWriteCommandAction(getProject(), () -> {
|
||||
SelectionModel sel = getEditor().getSelectionModel();
|
||||
getEditor().getDocument().deleteString(sel.getSelectionStart(), sel.getSelectionEnd());
|
||||
}), isOutOfBlockModificationExpected);
|
||||
}
|
||||
|
||||
private void doTest(@NotNull String text, Runnable modificationAction, boolean isOutOfBlockModificationExpected) {
|
||||
myFixture.configureByText("test.properties", text);
|
||||
PsiModificationTracker tracker = myFixture.getPsiManager().getModificationTracker();
|
||||
long oldMod = tracker.getOutOfCodeBlockModificationCount();
|
||||
modificationAction.run();
|
||||
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
|
||||
long newMod = tracker.getOutOfCodeBlockModificationCount();
|
||||
assertTrue(isOutOfBlockModificationExpected ^ oldMod == newMod);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user