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 }