Home | History | Annotate | Download | only in impl
      1 /*
      2  * Copyright 2014, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 package org.jf.smalidea.psi.impl;
     33 
     34 import com.google.common.collect.ImmutableList;
     35 import com.intellij.lang.ASTNode;
     36 import com.intellij.psi.PsiElement;
     37 import com.intellij.psi.impl.source.tree.CompositePsiElement;
     38 import com.intellij.psi.tree.IElementType;
     39 import org.jetbrains.annotations.NotNull;
     40 import org.jetbrains.annotations.Nullable;
     41 
     42 import java.lang.reflect.Array;
     43 import java.util.ArrayList;
     44 import java.util.List;
     45 
     46 public abstract class SmaliCompositeElement extends CompositePsiElement {
     47     public SmaliCompositeElement(IElementType type) {
     48         super(type);
     49     }
     50 
     51     @NotNull
     52     @SuppressWarnings("unchecked")
     53     protected List<ASTNode> findChildrenByType(IElementType elementType) {
     54         List<ASTNode> result = ImmutableList.of();
     55         ASTNode child = getNode().getFirstChildNode();
     56         while (child != null) {
     57             if (elementType == child.getElementType()) {
     58                 if (result.size() == 0) {
     59                     result = new ArrayList<ASTNode>();
     60                 }
     61                 result.add((ASTNode)child.getPsi());
     62             }
     63             child = child.getTreeNext();
     64         }
     65         return result;
     66     }
     67 
     68     @NotNull
     69     @SuppressWarnings("unchecked")
     70     protected <T> T[] findChildrenByClass(Class<T> aClass) {
     71         List<T> result = new ArrayList<T>();
     72         for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
     73             if (aClass.isInstance(cur)) result.add((T)cur);
     74         }
     75         return result.toArray((T[]) Array.newInstance(aClass, result.size()));
     76     }
     77 
     78     @Nullable
     79     @SuppressWarnings("unchecked")
     80     protected <T> T findChildByClass(Class<T> aClass) {
     81         for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
     82             if (aClass.isInstance(cur)) return (T)cur;
     83         }
     84         return null;
     85     }
     86 
     87     @Nullable
     88     @SuppressWarnings("unchecked")
     89     protected <T> T findAncestorByClass(Class<T> aClass) {
     90         PsiElement parent = getParent();
     91         while (parent != null) {
     92             if (aClass.isInstance(parent)) {
     93                 return (T)parent;
     94             }
     95             parent = parent.getParent();
     96         }
     97         return null;
     98     }
     99 
    100     @Nullable
    101     @SuppressWarnings("unchecked")
    102     public <T> T findNextSiblingByClass(@NotNull Class<T> cls) {
    103         PsiElement prev = getNextSibling();
    104         while (true) {
    105             if (prev == null) {
    106                 return null;
    107             } else if (cls.isInstance(prev)) {
    108                 return (T)prev;
    109             }
    110             prev = prev.getNextSibling();
    111         }
    112     }
    113 
    114     @Nullable
    115     @SuppressWarnings("unchecked")
    116     public <T> T findPrevSiblingByClass(@NotNull Class<T> cls) {
    117         PsiElement prev = getPrevSibling();
    118         while (true) {
    119             if (prev == null) {
    120                 return null;
    121             } else if (cls.isInstance(prev)) {
    122                 return (T)prev;
    123             }
    124             prev = prev.getPrevSibling();
    125         }
    126     }
    127 }
    128