blob: 853483dd178337d7ff190a573594631235a537d1 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2018 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Red Hat Inc. - moved to jdt.core.manipulation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.dom;
import java.util.List;
import org.eclipse.text.edits.TextEditGroup;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
import org.eclipse.jdt.internal.core.manipulation.JavaManipulationPlugin;
import org.eclipse.jdt.internal.core.manipulation.MembersOrderPreferenceCacheCommon;
/**
* Rewrite helper for body declarations.
*
* @see ASTNodes#getBodyDeclarationsProperty(ASTNode)
*
* @since 1.10
*/
public class BodyDeclarationRewrite {
private ASTNode fTypeNode;
private ListRewrite fListRewrite;
public static BodyDeclarationRewrite create(ASTRewrite rewrite, ASTNode typeNode) {
return new BodyDeclarationRewrite(rewrite, typeNode);
}
private BodyDeclarationRewrite(ASTRewrite rewrite, ASTNode typeNode) {
ChildListPropertyDescriptor property= ASTNodes.getBodyDeclarationsProperty(typeNode);
fTypeNode= typeNode;
fListRewrite= rewrite.getListRewrite(typeNode, property);
}
public void insert(BodyDeclaration decl, TextEditGroup description) {
List<BodyDeclaration> container= ASTNodes.getBodyDeclarations(fTypeNode);
int index= getInsertionIndex(decl, container);
fListRewrite.insertAt(decl, index, description);
}
/**
* Computes the insertion index to be used to add the given member to the
* the list <code>container</code>.
* @param member the member to add
* @param container a list containing objects of type <code>BodyDeclaration</code>
* @return the insertion index to be used
*/
public static int getInsertionIndex(BodyDeclaration member, List<? extends BodyDeclaration> container) {
int containerSize= container.size();
// use MembersOrderPreferenceCacheCommon which has no UI dependencies and
// will get Preferences from the node specified by JavaManipulation.getPreferenceNodeId
MembersOrderPreferenceCacheCommon orderStore= JavaManipulationPlugin.getDefault().getMembersOrderPreferenceCacheCommon();
int orderIndex= getOrderPreference(member, orderStore);
int insertPos= containerSize;
int insertPosOrderIndex= -1;
for (int i= containerSize - 1; i >= 0; i--) {
int currOrderIndex= getOrderPreference(container.get(i), orderStore);
if (orderIndex == currOrderIndex) {
if (insertPosOrderIndex != orderIndex) { // no perfect match yet
insertPos= i + 1; // after a same kind
insertPosOrderIndex= orderIndex; // perfect match
}
} else if (insertPosOrderIndex != orderIndex) { // not yet a perfect match
if (currOrderIndex < orderIndex) { // we are bigger
if (insertPosOrderIndex == -1) {
insertPos= i + 1; // after
insertPosOrderIndex= currOrderIndex;
}
} else {
insertPos= i; // before
insertPosOrderIndex= currOrderIndex;
}
}
}
return insertPos;
}
private static int getOrderPreference(BodyDeclaration member, MembersOrderPreferenceCacheCommon store) {
int memberType= member.getNodeType();
int modifiers= member.getModifiers();
switch (memberType) {
case ASTNode.TYPE_DECLARATION:
case ASTNode.ENUM_DECLARATION :
case ASTNode.ANNOTATION_TYPE_DECLARATION :
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.TYPE_INDEX) * 2;
case ASTNode.FIELD_DECLARATION:
if (Modifier.isStatic(modifiers)) {
int index= store.getCategoryIndex(MembersOrderPreferenceCacheCommon.STATIC_FIELDS_INDEX) * 2;
if (Modifier.isFinal(modifiers)) {
return index; // first final static, then static
}
return index + 1;
}
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.FIELDS_INDEX) * 2;
case ASTNode.INITIALIZER:
if (Modifier.isStatic(modifiers)) {
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.STATIC_INIT_INDEX) * 2;
}
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.INIT_INDEX) * 2;
case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.METHOD_INDEX) * 2;
case ASTNode.METHOD_DECLARATION:
if (Modifier.isStatic(modifiers)) {
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.STATIC_METHODS_INDEX) * 2;
}
if (((MethodDeclaration) member).isConstructor()) {
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.CONSTRUCTORS_INDEX) * 2;
}
return store.getCategoryIndex(MembersOrderPreferenceCacheCommon.METHOD_INDEX) * 2;
default:
return 100;
}
}
}