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 org.jetbrains.annotations.NotNull;
023    import org.jetbrains.annotations.Nullable;
024    import org.jetbrains.annotations.TestOnly;
025    import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
026    import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
027    import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
028    import org.jetbrains.kotlin.resolve.BindingTrace;
029    import org.jetbrains.kotlin.resolve.TraceBasedRedeclarationHandler;
030    import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
031    import org.jetbrains.kotlin.utils.Printer;
032    
033    import java.util.Collection;
034    import java.util.List;
035    
036    public final class JetScopeUtils {
037        private JetScopeUtils() {}
038    
039        @NotNull
040        public static List<ReceiverValue> getImplicitReceiversHierarchyValues(@NotNull JetScope scope) {
041            Collection<ReceiverParameterDescriptor> hierarchy = scope.getImplicitReceiversHierarchy();
042    
043            return Lists.newArrayList(
044                    Collections2.transform(hierarchy,
045                           new Function<ReceiverParameterDescriptor, ReceiverValue>() {
046                               @Override
047                               public ReceiverValue apply(ReceiverParameterDescriptor receiverParameterDescriptor) {
048                                   return receiverParameterDescriptor.getValue();
049                               }
050                           })
051            );
052        }
053    
054        public static JetScope makeScopeForPropertyAccessor(
055                @NotNull PropertyDescriptor propertyDescriptor,
056                @NotNull JetScope parentScope,
057                @NotNull BindingTrace trace
058        ) {
059            JetScope propertyDeclarationInnerScope =
060                    getPropertyDeclarationInnerScope(propertyDescriptor, parentScope,
061                                                     propertyDescriptor.getTypeParameters(),
062                                                     propertyDescriptor.getExtensionReceiverParameter(), trace);
063            WritableScope accessorScope = new WritableScopeImpl(propertyDeclarationInnerScope, parentScope.getContainingDeclaration(),
064                                                                new TraceBasedRedeclarationHandler(trace), "Accessor Scope");
065            accessorScope.changeLockLevel(WritableScope.LockLevel.READING);
066    
067            return accessorScope;
068        }
069    
070        public static JetScope getPropertyDeclarationInnerScope(
071                @NotNull PropertyDescriptor propertyDescriptor,
072                @NotNull JetScope outerScope,
073                @NotNull RedeclarationHandler redeclarationHandler
074        ) {
075            return getPropertyDeclarationInnerScope(propertyDescriptor,
076                                                    outerScope,
077                                                    propertyDescriptor.getTypeParameters(),
078                                                    propertyDescriptor.getExtensionReceiverParameter(),
079                                                    redeclarationHandler,
080                                                    true);
081        }
082    
083        public static JetScope getPropertyDeclarationInnerScope(
084                @NotNull PropertyDescriptor propertyDescriptor,
085                @NotNull JetScope outerScope,
086                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
087                @Nullable ReceiverParameterDescriptor receiver,
088                BindingTrace trace
089        ) {
090            return getPropertyDeclarationInnerScope(propertyDescriptor, outerScope, typeParameters, receiver, trace, true);
091        }
092    
093        public static JetScope getPropertyDeclarationInnerScopeForInitializer(
094                @NotNull JetScope outerScope,
095                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
096                @Nullable ReceiverParameterDescriptor receiver,
097                BindingTrace trace
098        ) {
099            return getPropertyDeclarationInnerScope(null, outerScope, typeParameters, receiver, trace, false);
100        }
101    
102        private static JetScope getPropertyDeclarationInnerScope(
103                @Nullable PropertyDescriptor propertyDescriptor,
104                // PropertyDescriptor can be null for property scope which hasn't label to property (in this case addLabelForProperty parameter must be false
105                @NotNull JetScope outerScope,
106                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
107                @Nullable ReceiverParameterDescriptor receiver,
108                BindingTrace trace,
109                boolean addLabelForProperty
110        ) {
111            TraceBasedRedeclarationHandler redeclarationHandler = new TraceBasedRedeclarationHandler(trace);
112            return getPropertyDeclarationInnerScope(propertyDescriptor, outerScope, typeParameters, receiver, redeclarationHandler,
113                                                    addLabelForProperty);
114        }
115    
116        @NotNull
117        private static JetScope getPropertyDeclarationInnerScope(
118                @Nullable PropertyDescriptor propertyDescriptor,
119                @NotNull JetScope outerScope,
120                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
121                @Nullable ReceiverParameterDescriptor receiver,
122                @NotNull RedeclarationHandler redeclarationHandler,
123                boolean addLabelForProperty
124        ) {
125            WritableScopeImpl result = new WritableScopeImpl(
126                    outerScope, outerScope.getContainingDeclaration(), redeclarationHandler,
127                    "Property declaration inner scope");
128            if (addLabelForProperty) {
129                assert propertyDescriptor != null : "PropertyDescriptor can be null for property scope which hasn't label to property";
130                result.addLabeledDeclaration(propertyDescriptor);
131            }
132            for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
133                result.addTypeParameterDescriptor(typeParameterDescriptor);
134            }
135            if (receiver != null) {
136                result.setImplicitReceiver(receiver);
137            }
138            result.changeLockLevel(WritableScope.LockLevel.READING);
139            return result;
140        }
141    
142        @TestOnly
143        @NotNull
144        public static String printStructure(@Nullable JetScope scope) {
145            StringBuilder out = new StringBuilder();
146            Printer p = new Printer(out);
147            if (scope == null) {
148                p.println("null");
149            }
150            else {
151                scope.printScopeStructure(p);
152            }
153            return out.toString();
154        }
155    }