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.resolve.lazy;
018    
019    import com.intellij.psi.PsiElement;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
022    import org.jetbrains.kotlin.psi.*;
023    import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
024    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
025    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor;
026    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
027    
028    public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
029    
030        private final LazyDeclarationResolver lazyDeclarationResolver;
031    
032        private final FileScopeProvider fileScopeProvider;
033    
034        public DeclarationScopeProviderImpl(
035                @NotNull LazyDeclarationResolver lazyDeclarationResolver,
036                @NotNull FileScopeProvider fileScopeProvider
037        ) {
038            this.lazyDeclarationResolver = lazyDeclarationResolver;
039            this.fileScopeProvider = fileScopeProvider;
040        }
041    
042        @Override
043        @NotNull
044        public LexicalScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) {
045            JetDeclaration jetDeclaration = JetStubbedPsiUtil.getPsiOrStubParent(elementOfDeclaration, JetDeclaration.class, false);
046    
047            assert !(elementOfDeclaration instanceof JetDeclaration) || jetDeclaration == elementOfDeclaration :
048                    "For JetDeclaration element getParentOfType() should return itself.";
049            assert jetDeclaration != null : "Should be contained inside declaration.";
050    
051            JetDeclaration parentDeclaration = JetStubbedPsiUtil.getContainingDeclaration(jetDeclaration);
052    
053            if (jetDeclaration instanceof JetPropertyAccessor) {
054                parentDeclaration = JetStubbedPsiUtil.getContainingDeclaration(parentDeclaration, JetDeclaration.class);
055            }
056    
057            if (parentDeclaration == null) {
058                return fileScopeProvider.getFileScope((JetFile) elementOfDeclaration.getContainingFile());
059            }
060    
061            if (parentDeclaration instanceof JetClassOrObject) {
062                JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration;
063                LazyClassDescriptor classDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(classOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE);
064                if (jetDeclaration instanceof JetClassInitializer || jetDeclaration instanceof JetProperty) {
065                    return classDescriptor.getScopeForInitializerResolution();
066                }
067                if (jetDeclaration instanceof JetObjectDeclaration
068                    || (jetDeclaration instanceof JetClass && !((JetClass) jetDeclaration).isInner())) {
069                    return classDescriptor.getScopeForStaticMemberDeclarationResolution();
070                }
071    
072                return classDescriptor.getScopeForMemberDeclarationResolution();
073            }
074    
075            throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + "\n" +
076                                            PsiUtilPackage.getElementTextWithContext(jetDeclaration));
077        }
078    
079        @NotNull
080        @Override
081        public DataFlowInfo getOuterDataFlowInfoForDeclaration(@NotNull PsiElement elementOfDeclaration) {
082            return DataFlowInfo.EMPTY;
083        }
084    }