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.PsiUtilsKt; 024 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; 025 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory; 026 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor; 027 import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor; 028 import org.jetbrains.kotlin.resolve.scopes.LexicalScope; 029 030 public class DeclarationScopeProviderImpl implements DeclarationScopeProvider { 031 032 private final LazyDeclarationResolver lazyDeclarationResolver; 033 034 private final FileScopeProvider fileScopeProvider; 035 036 public DeclarationScopeProviderImpl( 037 @NotNull LazyDeclarationResolver lazyDeclarationResolver, 038 @NotNull FileScopeProvider fileScopeProvider 039 ) { 040 this.lazyDeclarationResolver = lazyDeclarationResolver; 041 this.fileScopeProvider = fileScopeProvider; 042 } 043 044 @Override 045 @NotNull 046 public LexicalScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) { 047 KtDeclaration ktDeclaration = KtStubbedPsiUtil.getPsiOrStubParent(elementOfDeclaration, KtDeclaration.class, false); 048 049 assert !(elementOfDeclaration instanceof KtDeclaration) || ktDeclaration == elementOfDeclaration : 050 "For JetDeclaration element getParentOfType() should return itself."; 051 assert ktDeclaration != null : "Should be contained inside declaration."; 052 053 KtDeclaration parentDeclaration = KtStubbedPsiUtil.getContainingDeclaration(ktDeclaration); 054 055 if (ktDeclaration instanceof KtPropertyAccessor) { 056 parentDeclaration = KtStubbedPsiUtil.getContainingDeclaration(parentDeclaration, KtDeclaration.class); 057 } 058 059 if (parentDeclaration == null) { 060 return fileScopeProvider.getFileResolutionScope((KtFile) elementOfDeclaration.getContainingFile()); 061 } 062 063 if (parentDeclaration instanceof KtClassOrObject) { 064 KtClassOrObject parentClassOrObject = (KtClassOrObject) parentDeclaration; 065 LazyClassDescriptor parentClassDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(parentClassOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE); 066 067 if (ktDeclaration instanceof KtAnonymousInitializer || ktDeclaration instanceof KtProperty) { 068 return parentClassDescriptor.getScopeForInitializerResolution(); 069 } 070 071 if (ktDeclaration instanceof KtObjectDeclaration && ((KtObjectDeclaration) ktDeclaration).isCompanion()) { 072 return parentClassDescriptor.getScopeForCompanionObjectHeaderResolution(); 073 } 074 075 if (ktDeclaration instanceof KtObjectDeclaration || 076 ktDeclaration instanceof KtClass && !((KtClass) ktDeclaration).isInner()) { 077 return parentClassDescriptor.getScopeForStaticMemberDeclarationResolution(); 078 } 079 080 return parentClassDescriptor.getScopeForMemberDeclarationResolution(); 081 } 082 //TODO: this is not how it works for classes and for exact parity we can try to use the code above 083 if (parentDeclaration instanceof KtScript) { 084 LazyScriptDescriptor scriptDescriptor = (LazyScriptDescriptor) lazyDeclarationResolver.resolveToDescriptor(parentDeclaration); 085 return scriptDescriptor.getScopeForInitializerResolution(); 086 } 087 088 throw new IllegalStateException("Don't call this method for local declarations: " + ktDeclaration + "\n" + 089 PsiUtilsKt.getElementTextWithContext(ktDeclaration)); 090 } 091 092 @NotNull 093 @Override 094 public DataFlowInfo getOuterDataFlowInfoForDeclaration(@NotNull PsiElement elementOfDeclaration) { 095 return DataFlowInfoFactory.EMPTY; 096 } 097 }