001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.psi;
018    
019    import com.intellij.psi.PsiElement;
020    import com.intellij.psi.stubs.StubElement;
021    import com.intellij.psi.tree.TokenSet;
022    import com.intellij.psi.util.PsiTreeUtil;
023    import com.intellij.util.ArrayFactory;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    
027    public final class KtStubbedPsiUtil {
028        @Nullable
029        public static KtDeclaration getContainingDeclaration(@NotNull PsiElement element) {
030            return getPsiOrStubParent(element, KtDeclaration.class, true);
031        }
032    
033        @Nullable
034        public static <T extends KtDeclaration> T getContainingDeclaration(@NotNull PsiElement element, @NotNull Class<T> declarationClass) {
035            return getPsiOrStubParent(element, declarationClass, true);
036        }
037    
038        //TODO: contribute to idea PsiTreeUtil#getPsiOrStubParent
039        @Nullable
040        public static <T extends KtElement> T getPsiOrStubParent(
041                @NotNull PsiElement element,
042                @NotNull Class<T> declarationClass,
043                boolean strict
044        ) {
045            if (!strict && declarationClass.isInstance(element)) {
046                //noinspection unchecked
047                return (T) element;
048            }
049            if (element instanceof KtElementImplStub) {
050                StubElement<?> stub = ((KtElementImplStub) element).getStub();
051                if (stub != null) {
052                    return stub.getParentStubOfType(declarationClass);
053                }
054            }
055            return PsiTreeUtil.getParentOfType(element, declarationClass, strict);
056        }
057    
058        @Nullable
059        public static <T extends KtElement> T getStubOrPsiChild(
060                @NotNull KtElementImplStub<?> element,
061                @NotNull TokenSet types,
062                @NotNull ArrayFactory<T> factory
063        ) {
064            T[] typeElements = element.getStubOrPsiChildren(types, factory);
065            if (typeElements.length == 0) {
066                return null;
067            }
068            return typeElements[0];
069        }
070    
071        private KtStubbedPsiUtil() {
072        }
073    }