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.scopes;
018
019 import com.google.common.base.Function;
020 import com.google.common.collect.Collections2;
021 import com.google.common.collect.Lists;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.psi.util.PsiTreeUtil;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.annotations.TestOnly;
027 import org.jetbrains.kotlin.descriptors.*;
028 import org.jetbrains.kotlin.psi.*;
029 import org.jetbrains.kotlin.resolve.BindingContext;
030 import org.jetbrains.kotlin.resolve.BindingTrace;
031 import org.jetbrains.kotlin.resolve.TraceBasedRedeclarationHandler;
032 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
033 import org.jetbrains.kotlin.utils.Printer;
034
035 import java.util.Collection;
036 import java.util.List;
037
038 public final class JetScopeUtils {
039 private JetScopeUtils() {}
040
041 @NotNull
042 public static List<ReceiverValue> getImplicitReceiversHierarchyValues(@NotNull JetScope scope) {
043 Collection<ReceiverParameterDescriptor> hierarchy = scope.getImplicitReceiversHierarchy();
044
045 return Lists.newArrayList(
046 Collections2.transform(hierarchy,
047 new Function<ReceiverParameterDescriptor, ReceiverValue>() {
048 @Override
049 public ReceiverValue apply(ReceiverParameterDescriptor receiverParameterDescriptor) {
050 return receiverParameterDescriptor.getValue();
051 }
052 })
053 );
054 }
055
056 public static JetScope makeScopeForPropertyAccessor(
057 @NotNull PropertyDescriptor propertyDescriptor,
058 @NotNull JetScope parentScope,
059 @NotNull BindingTrace trace
060 ) {
061 JetScope propertyDeclarationInnerScope =
062 getPropertyDeclarationInnerScope(propertyDescriptor, parentScope,
063 propertyDescriptor.getTypeParameters(),
064 propertyDescriptor.getExtensionReceiverParameter(), trace);
065 WritableScope accessorScope = new WritableScopeImpl(propertyDeclarationInnerScope, parentScope.getContainingDeclaration(),
066 new TraceBasedRedeclarationHandler(trace), "Accessor Scope");
067 accessorScope.changeLockLevel(WritableScope.LockLevel.READING);
068
069 return accessorScope;
070 }
071
072 public static JetScope getPropertyDeclarationInnerScope(
073 @NotNull PropertyDescriptor propertyDescriptor,
074 @NotNull JetScope outerScope,
075 @NotNull RedeclarationHandler redeclarationHandler
076 ) {
077 return getPropertyDeclarationInnerScope(propertyDescriptor,
078 outerScope,
079 propertyDescriptor.getTypeParameters(),
080 propertyDescriptor.getExtensionReceiverParameter(),
081 redeclarationHandler,
082 true);
083 }
084
085 public static JetScope getPropertyDeclarationInnerScope(
086 @NotNull PropertyDescriptor propertyDescriptor,
087 @NotNull JetScope outerScope,
088 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
089 @Nullable ReceiverParameterDescriptor receiver,
090 BindingTrace trace
091 ) {
092 return getPropertyDeclarationInnerScope(propertyDescriptor, outerScope, typeParameters, receiver, trace, true);
093 }
094
095 public static JetScope getPropertyDeclarationInnerScopeForInitializer(
096 @NotNull PropertyDescriptor propertyDescriptor,
097 @NotNull JetScope outerScope,
098 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
099 @Nullable ReceiverParameterDescriptor receiver,
100 BindingTrace trace
101 ) {
102 return getPropertyDeclarationInnerScope(propertyDescriptor, outerScope, typeParameters, receiver, trace, false);
103 }
104
105 private static JetScope getPropertyDeclarationInnerScope(
106 @NotNull PropertyDescriptor propertyDescriptor,
107 @NotNull JetScope outerScope,
108 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
109 @Nullable ReceiverParameterDescriptor receiver,
110 BindingTrace trace,
111 boolean addLabelForProperty
112 ) {
113 TraceBasedRedeclarationHandler redeclarationHandler = new TraceBasedRedeclarationHandler(trace);
114 return getPropertyDeclarationInnerScope(propertyDescriptor, outerScope, typeParameters, receiver, redeclarationHandler,
115 addLabelForProperty);
116 }
117
118 @NotNull
119 private static JetScope getPropertyDeclarationInnerScope(
120 @NotNull PropertyDescriptor propertyDescriptor,
121 @NotNull JetScope outerScope,
122 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
123 @Nullable ReceiverParameterDescriptor receiver,
124 @NotNull RedeclarationHandler redeclarationHandler,
125 boolean addLabelForProperty
126 ) {
127 WritableScopeImpl result = new WritableScopeImpl(
128 outerScope, propertyDescriptor, redeclarationHandler,
129 "Property declaration inner scope");
130 if (addLabelForProperty) {
131 result.addLabeledDeclaration(propertyDescriptor);
132 }
133 for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
134 result.addClassifierDescriptor(typeParameterDescriptor);
135 }
136 if (receiver != null) {
137 result.setImplicitReceiver(receiver);
138 }
139 result.changeLockLevel(WritableScope.LockLevel.READING);
140 return result;
141 }
142
143 @TestOnly
144 @NotNull
145 public static String printStructure(@Nullable JetScope scope) {
146 StringBuilder out = new StringBuilder();
147 Printer p = new Printer(out);
148 if (scope == null) {
149 p.println("null");
150 }
151 else {
152 scope.printScopeStructure(p);
153 }
154 return out.toString();
155 }
156
157 @Nullable
158 public static JetScope getResolutionScope(@NotNull PsiElement element, @NotNull BindingContext context) {
159 PsiElement parent = element.getParent();
160
161 if (parent instanceof JetClassBody) {
162 JetClassOrObject classOrObject = (JetClassOrObject) parent.getParent();
163 ClassDescriptor classDescriptor = context.get(BindingContext.CLASS, classOrObject);
164 if (classDescriptor instanceof ClassDescriptorWithResolutionScopes) {
165 return ((ClassDescriptorWithResolutionScopes) classDescriptor).getScopeForMemberDeclarationResolution();
166 }
167 return null;
168 }
169
170 if (parent instanceof JetFile) {
171 PackageFragmentDescriptor packageFragment = context.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, (JetFile) parent);
172 if (packageFragment == null) return null;
173
174 PackageViewDescriptor packageView = packageFragment.getContainingDeclaration().getPackage(((JetFile) parent).getPackageFqName());
175 return packageView != null ? packageView.getMemberScope() : null;
176 }
177
178 JetExpression expression = PsiTreeUtil.getParentOfType(element, JetExpression.class, false);
179 return expression != null ? context.get(BindingContext.RESOLUTION_SCOPE, expression) : null;
180 }
181 }