Added API in PSI to add/remove modifiers and refactored quickfixes to use it
This commit is contained in:
@@ -27,9 +27,11 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.psi.addRemoveModifier.AddRemoveModifierPackage;
|
||||
import org.jetbrains.jet.lang.psi.stubs.PsiJetClassStub;
|
||||
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -90,6 +92,31 @@ public class JetClass extends JetTypeParameterListOwnerStub<PsiJetClassStub> imp
|
||||
return getStubOrPsiChild(JetStubElementTypes.PRIMARY_CONSTRUCTOR_MODIFIER_LIST);
|
||||
}
|
||||
|
||||
public void addPrimaryConstructorModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
JetModifierList modifierList = getPrimaryConstructorModifierList();
|
||||
if (modifierList != null) {
|
||||
AddRemoveModifierPackage.addModifier(modifierList, modifier, JetTokens.PUBLIC_KEYWORD);
|
||||
}
|
||||
else {
|
||||
if (modifier == JetTokens.PUBLIC_KEYWORD) return;
|
||||
|
||||
JetParameterList parameterList = getPrimaryConstructorParameterList();
|
||||
assert parameterList != null;
|
||||
JetModifierList newModifierList = new JetPsiFactory(getProject()).createModifierList(modifier);
|
||||
addBefore(newModifierList, parameterList);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePrimaryConstructorModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
JetModifierList list = getPrimaryConstructorModifierList();
|
||||
if (list != null) {
|
||||
PsiElement token = list.getModifier(modifier);
|
||||
if (token != null) {
|
||||
token.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetClassInitializer> getAnonymousInitializers() {
|
||||
|
||||
@@ -20,7 +20,9 @@ import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
import org.jetbrains.jet.lang.psi.addRemoveModifier.AddRemoveModifierPackage;
|
||||
import org.jetbrains.jet.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -37,11 +39,21 @@ abstract class JetDeclarationImpl extends JetExpressionImpl implements JetDeclar
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifier(JetModifierKeywordToken modifier) {
|
||||
public boolean hasModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
return modifierList != null && modifierList.hasModifier(modifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
AddRemoveModifierPackage.addModifier(this, modifier, JetTokens.INTERNAL_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
AddRemoveModifierPackage.removeModifier(this, modifier);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<JetAnnotationEntry> getAnnotationEntries() {
|
||||
|
||||
@@ -62,21 +62,7 @@ public abstract class JetModifierList extends JetElementImplStub<PsiJetModifierL
|
||||
return answer != null ? answer : Collections.<JetAnnotationEntry>emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<ASTNode> getModifierNodes() {
|
||||
List<ASTNode> modifierNodes = new ArrayList<ASTNode>();
|
||||
|
||||
ASTNode node = getNode().getFirstChildNode();
|
||||
while (node != null) {
|
||||
if (node.getElementType() instanceof JetModifierKeywordToken) {
|
||||
modifierNodes.add(node);
|
||||
}
|
||||
node = node.getTreeNext();
|
||||
}
|
||||
return modifierNodes;
|
||||
}
|
||||
|
||||
public boolean hasModifier(JetModifierKeywordToken token) {
|
||||
public boolean hasModifier(@NotNull JetModifierKeywordToken token) {
|
||||
PsiJetModifierListStub stub = getStub();
|
||||
if (stub != null) {
|
||||
return stub.hasModifier(token);
|
||||
@@ -85,12 +71,12 @@ public abstract class JetModifierList extends JetElementImplStub<PsiJetModifierL
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiElement getModifier(JetModifierKeywordToken token) {
|
||||
public PsiElement getModifier(@NotNull JetModifierKeywordToken token) {
|
||||
return findChildByType(token);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ASTNode getModifierNode(JetToken token) {
|
||||
public ASTNode getModifierNode(@NotNull JetToken token) {
|
||||
ASTNode node = getNode().getFirstChildNode();
|
||||
while (node != null) {
|
||||
if (node.getElementType() == token) return node;
|
||||
@@ -98,6 +84,4 @@ public abstract class JetModifierList extends JetElementImplStub<PsiJetModifierL
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lexer.JetModifierKeywordToken;
|
||||
|
||||
@@ -24,5 +25,8 @@ public interface JetModifierListOwner extends PsiElement, JetAnnotated {
|
||||
@Nullable
|
||||
JetModifierList getModifierList();
|
||||
|
||||
boolean hasModifier(JetModifierKeywordToken modifier);
|
||||
boolean hasModifier(@NotNull JetModifierKeywordToken modifier);
|
||||
|
||||
void addModifier(@NotNull JetModifierKeywordToken modifier);
|
||||
void removeModifier(@NotNull JetModifierKeywordToken modifier);
|
||||
}
|
||||
|
||||
@@ -21,8 +21,10 @@ import com.intellij.psi.stubs.IStubElementType;
|
||||
import com.intellij.psi.stubs.StubElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.psi.addRemoveModifier.AddRemoveModifierPackage;
|
||||
import org.jetbrains.jet.lang.psi.stubs.elements.JetStubElementTypes;
|
||||
import org.jetbrains.jet.lexer.JetModifierKeywordToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -43,11 +45,21 @@ public class JetModifierListOwnerStub<T extends StubElement> extends JetElementI
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifier(JetModifierKeywordToken modifier) {
|
||||
public boolean hasModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
return modifierList != null && modifierList.hasModifier(modifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
AddRemoveModifierPackage.addModifier(this, modifier, JetTokens.INTERNAL_KEYWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
AddRemoveModifierPackage.removeModifier(this, modifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public List<JetAnnotationEntry> getAnnotationEntries() {
|
||||
|
||||
@@ -110,7 +110,7 @@ public class JetObjectDeclaration extends JetNamedDeclarationStub<PsiJetObjectSt
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifier(JetModifierKeywordToken modifier) {
|
||||
public boolean hasModifier(@NotNull JetModifierKeywordToken modifier) {
|
||||
JetModifierList modifierList = getModifierList();
|
||||
return modifierList != null && modifierList.hasModifier(modifier);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 org.jetbrains.jet.lang.psi.addRemoveModifier
|
||||
|
||||
import org.jetbrains.jet.lexer.JetModifierKeywordToken
|
||||
import org.jetbrains.jet.lexer.JetTokens.*
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import org.jetbrains.jet.lang.psi.JetModifierListOwner
|
||||
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.jet.lang.psi.JetAnnotation
|
||||
import org.jetbrains.jet.lang.psi.JetModifierList
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.siblings
|
||||
|
||||
internal fun addModifier(owner: JetModifierListOwner, modifier: JetModifierKeywordToken, defaultVisibilityModifier: JetModifierKeywordToken) {
|
||||
val modifierList = owner.getModifierList()
|
||||
if (modifierList == null) {
|
||||
if (modifier == defaultVisibilityModifier) return
|
||||
|
||||
val newModifierList = JetPsiFactory(owner).createModifierList(modifier)
|
||||
val anchor = owner.getFirstChild()!!.siblings(forward = true)
|
||||
.dropWhile { it is PsiComment || it is PsiWhiteSpace }
|
||||
.first()
|
||||
owner.addBefore(newModifierList, anchor)
|
||||
}
|
||||
else {
|
||||
addModifier(modifierList, modifier, defaultVisibilityModifier)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun addModifier(modifierList: JetModifierList, modifier: JetModifierKeywordToken, defaultVisibilityModifier: JetModifierKeywordToken) {
|
||||
val newModifier = JetPsiFactory(modifierList).createModifierList(modifier).getModifier(modifier)!!
|
||||
val modifierToReplace = MODIFIERS_TO_REPLACE[modifier]
|
||||
?.map { modifierList.getModifier(it) }
|
||||
?.filterNotNull()
|
||||
?.firstOrNull()
|
||||
|
||||
if (modifier == defaultVisibilityModifier) { // do not insert explicit 'internal' keyword (or 'public' for primary constructor)
|
||||
//TODO: code style option
|
||||
if (modifierToReplace != null) {
|
||||
modifierToReplace.delete()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (modifierToReplace != null) {
|
||||
modifierToReplace.replace(newModifier)
|
||||
}
|
||||
else {
|
||||
val newModifierOrder = MODIFIERS_ORDER.indexOf(modifier)
|
||||
|
||||
fun placeAfter(child: PsiElement): Boolean {
|
||||
if (child is PsiWhiteSpace) return false
|
||||
if (child is JetAnnotation) return true // place modifiers after annotations
|
||||
val elementType = child.getNode()!!.getElementType()
|
||||
val order = MODIFIERS_ORDER.indexOf(elementType)
|
||||
return newModifierOrder > order
|
||||
}
|
||||
|
||||
val anchor = modifierList.getLastChild()?.siblings(forward = false)?.firstOrNull(::placeAfter)
|
||||
modifierList.addAfter(newModifier, anchor)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun removeModifier(owner: JetModifierListOwner, modifier: JetModifierKeywordToken) {
|
||||
owner.getModifierList()?.getModifier(modifier)?.delete()
|
||||
}
|
||||
|
||||
private val MODIFIERS_TO_REPLACE = mapOf(
|
||||
ABSTRACT_KEYWORD to listOf(OPEN_KEYWORD, FINAL_KEYWORD),
|
||||
OVERRIDE_KEYWORD to listOf(OPEN_KEYWORD),
|
||||
OPEN_KEYWORD to listOf(FINAL_KEYWORD),
|
||||
PUBLIC_KEYWORD to listOf(PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD),
|
||||
PROTECTED_KEYWORD to listOf(PUBLIC_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD),
|
||||
PRIVATE_KEYWORD to listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, INTERNAL_KEYWORD),
|
||||
INTERNAL_KEYWORD to listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD)
|
||||
)
|
||||
|
||||
private val MODIFIERS_ORDER = listOf(PUBLIC_KEYWORD, PROTECTED_KEYWORD, PRIVATE_KEYWORD, INTERNAL_KEYWORD,
|
||||
FINAL_KEYWORD, OPEN_KEYWORD, ABSTRACT_KEYWORD,
|
||||
OVERRIDE_KEYWORD,
|
||||
INNER_KEYWORD,
|
||||
ANNOTATION_KEYWORD, ENUM_KEYWORD)
|
||||
Reference in New Issue
Block a user