/* * Copyright 2000-2012 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.psi.impl.source.tree.java; import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.scope.ElementClassHint; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; public class PsiDeclarationStatementImpl extends CompositePsiElement implements PsiDeclarationStatement { public PsiDeclarationStatementImpl() { super(JavaElementType.DECLARATION_STATEMENT); } @Override @NotNull public PsiElement[] getDeclaredElements() { return getChildrenAsPsiElements(DECLARED_ELEMENT_BIT_SET, PsiElement.ARRAY_FACTORY); } private static final TokenSet DECLARED_ELEMENT_BIT_SET = TokenSet.create(JavaElementType.LOCAL_VARIABLE, JavaElementType.CLASS); @Override public int getChildRole(ASTNode child) { if (child.getElementType() == JavaTokenType.COMMA) return ChildRole.COMMA; return super.getChildRole(child); } @Override public void deleteChildInternal(@NotNull ASTNode child) { if (DECLARED_ELEMENT_BIT_SET.contains(child.getElementType())) { PsiElement[] declaredElements = getDeclaredElements(); int length = declaredElements.length; if (length > 0) { if (length == 1) { getTreeParent().deleteChildInternal(this); return; } else { if (SourceTreeToPsiMap.psiElementToTree(declaredElements[length - 1]) == child) { removeCommaBefore(child); final LeafElement semicolon = Factory.createSingleLeafElement(JavaTokenType.SEMICOLON, ";", 0, 1, SharedImplUtil.findCharTableByTree(this), getManager()); SourceTreeToPsiMap.psiElementToTree(declaredElements[length - 2]).addChild(semicolon, null); } else if (SourceTreeToPsiMap.psiElementToTree(declaredElements[0]) == child) { CompositeElement next = (CompositeElement)SourceTreeToPsiMap.psiElementToTree(declaredElements[1]); ASTNode copyChild = child.copyElement(); ASTNode nameChild = ((CompositeElement)copyChild).findChildByRole(ChildRole.NAME); removeCommaBefore(next); next.addInternal((TreeElement)copyChild.getFirstChildNode(), nameChild.getTreePrev(), null, Boolean.FALSE); } else { removeCommaBefore (child); } } } } super.deleteChildInternal(child); } private void removeCommaBefore(ASTNode child) { ASTNode prev = child; do { prev = prev.getTreePrev(); } while (prev != null && ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains(prev.getElementType())); if (prev != null && prev.getElementType() == JavaTokenType.COMMA) deleteChildInternal(prev); } @Override public void accept(@NotNull PsiElementVisitor visitor) { if (visitor instanceof JavaElementVisitor) { ((JavaElementVisitor)visitor).visitDeclarationStatement(this); } else { visitor.visitElement(this); } } public String toString() { return "PsiDeclarationStatement"; } @Override public boolean processDeclarations(@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) { processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, this); PsiElement[] decls = getDeclaredElements(); for (PsiElement decl : decls) { if (decl != lastParent) { if (!processor.execute(decl, state)) return false; } else { final ElementClassHint hint = processor.getHint(ElementClassHint.KEY); if (lastParent instanceof PsiClass) { if (hint == null || hint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) { if (!processor.execute(lastParent, state)) return false; } } } } return true; } }