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;
018
019 import com.google.common.collect.ImmutableMap;
020 import com.google.common.collect.Lists;
021 import com.google.common.collect.Maps;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.annotations.TestOnly;
025 import org.jetbrains.kotlin.diagnostics.Diagnostic;
026 import org.jetbrains.kotlin.psi.KtExpression;
027 import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
028 import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression;
029 import org.jetbrains.kotlin.types.KotlinType;
030 import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
031 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
032 import org.jetbrains.kotlin.util.slicedMap.*;
033
034 import java.util.Collection;
035 import java.util.List;
036 import java.util.Map;
037
038 public class DelegatingBindingTrace implements BindingTrace {
039 @SuppressWarnings("ConstantConditions")
040 private final MutableSlicedMap map = BindingTraceContext.TRACK_REWRITES ? new TrackingSlicedMap(BindingTraceContext.TRACK_WITH_STACK_TRACES) : SlicedMapImpl.create();
041
042 private final BindingContext parentContext;
043 private final String name;
044 private final MutableDiagnosticsWithSuppression mutableDiagnostics;
045
046 private final BindingContext bindingContext = new BindingContext() {
047 @NotNull
048 @Override
049 public Diagnostics getDiagnostics() {
050 return mutableDiagnostics;
051 }
052
053 @Override
054 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
055 return DelegatingBindingTrace.this.get(slice, key);
056 }
057
058
059 @Nullable
060 @Override
061 public KotlinType getType(@NotNull KtExpression expression) {
062 return DelegatingBindingTrace.this.getType(expression);
063 }
064
065 @NotNull
066 @Override
067 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
068 return DelegatingBindingTrace.this.getKeys(slice);
069 }
070
071 @Override
072 public void addOwnDataTo(@NotNull BindingTrace trace, boolean commitDiagnostics) {
073 BindingContextUtils.addOwnDataTo(trace, null, commitDiagnostics, map, mutableDiagnostics);
074 }
075
076 @NotNull
077 @TestOnly
078 @Override
079 public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
080 Map<K, V> result = Maps.newHashMap();
081 result.putAll(parentContext.getSliceContents(slice));
082 result.putAll(map.getSliceContents(slice));
083 return ImmutableMap.copyOf(result);
084 }
085 };
086
087 public DelegatingBindingTrace(BindingContext parentContext, String debugName) {
088 this(parentContext, true, debugName);
089 }
090
091 public DelegatingBindingTrace(BindingContext parentContext, boolean withParentDiagnostics, String debugName) {
092 this.parentContext = parentContext;
093 this.name = debugName;
094 this.mutableDiagnostics = withParentDiagnostics ?
095 new MutableDiagnosticsWithSuppression(bindingContext, parentContext.getDiagnostics()) :
096 new MutableDiagnosticsWithSuppression(bindingContext);
097 }
098
099 public DelegatingBindingTrace(BindingContext parentContext, String debugName, @Nullable Object resolutionSubjectForMessage) {
100 this(parentContext, AnalyzingUtils.formDebugNameForBindingTrace(debugName, resolutionSubjectForMessage));
101 }
102
103 @Override
104 @NotNull
105 public BindingContext getBindingContext() {
106 return bindingContext;
107 }
108
109 @Override
110 public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
111 map.put(slice, key, value);
112 }
113
114 @Override
115 public <K> void record(WritableSlice<K, Boolean> slice, K key) {
116 record(slice, key, true);
117 }
118
119 @Override
120 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
121 V value = map.get(slice, key);
122 if (slice instanceof Slices.SetSlice) {
123 assert value != null;
124 if (value.equals(true)) return value;
125 }
126 else if (value != null) {
127 return value;
128 }
129
130 return parentContext.get(slice, key);
131 }
132
133 @NotNull
134 @Override
135 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
136 Collection<K> keys = map.getKeys(slice);
137 Collection<K> fromParent = parentContext.getKeys(slice);
138 if (keys.isEmpty()) return fromParent;
139 if (fromParent.isEmpty()) return keys;
140
141 List<K> result = Lists.newArrayList(keys);
142 result.addAll(fromParent);
143 return result;
144 }
145
146 @Nullable
147 @Override
148 public KotlinType getType(@NotNull KtExpression expression) {
149 KotlinTypeInfo typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression);
150 return typeInfo != null ? typeInfo.getType() : null;
151 }
152
153 @Override
154 public void recordType(@NotNull KtExpression expression, @Nullable KotlinType type) {
155 KotlinTypeInfo typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression);
156 if (typeInfo == null) {
157 typeInfo = TypeInfoFactoryKt.createTypeInfo(type);
158 }
159 else {
160 typeInfo = typeInfo.replaceType(type);
161 }
162 record(BindingContext.EXPRESSION_TYPE_INFO, expression, typeInfo);
163 }
164
165 public void addOwnDataTo(@NotNull BindingTrace trace) {
166 addOwnDataTo(trace, null, true);
167 }
168
169 public void moveAllMyDataTo(@NotNull BindingTrace trace) {
170 addOwnDataTo(trace, null, true);
171 clear();
172 }
173
174 public void addOwnDataTo(@NotNull BindingTrace trace, @Nullable TraceEntryFilter filter, boolean commitDiagnostics) {
175 BindingContextUtils.addOwnDataTo(trace, filter, commitDiagnostics, map, mutableDiagnostics);
176 }
177
178 public void clear() {
179 map.clear();
180 mutableDiagnostics.clear();
181 }
182
183 @Override
184 public void report(@NotNull Diagnostic diagnostic) {
185 mutableDiagnostics.report(diagnostic);
186 }
187
188 @Override
189 public String toString() {
190 return name;
191 }
192 }