001 /*
002 * Copyright 2010-2013 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.jet.lang.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.jet.lang.diagnostics.Diagnostic;
026 import org.jetbrains.jet.util.slicedmap.*;
027
028 import java.util.Collection;
029 import java.util.List;
030 import java.util.Map;
031
032 public class DelegatingBindingTrace implements BindingTrace {
033 @SuppressWarnings("ConstantConditions")
034 private final MutableSlicedMap map = BindingTraceContext.TRACK_REWRITES ? new TrackingSlicedMap(BindingTraceContext.TRACK_WITH_STACK_TRACES) : SlicedMapImpl.create();
035
036 private final BindingContext parentContext;
037 private final String name;
038 private final MutableDiagnosticsWithSuppression mutableDiagnostics;
039
040 private final BindingContext bindingContext = new BindingContext() {
041 @NotNull
042 @Override
043 public Diagnostics getDiagnostics() {
044 return mutableDiagnostics;
045 }
046
047 @Override
048 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
049 return DelegatingBindingTrace.this.get(slice, key);
050 }
051
052 @NotNull
053 @Override
054 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
055 return DelegatingBindingTrace.this.getKeys(slice);
056
057 }
058
059 @NotNull
060 @TestOnly
061 @Override
062 public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
063 Map<K, V> result = Maps.newHashMap();
064 result.putAll(parentContext.getSliceContents(slice));
065 result.putAll(map.getSliceContents(slice));
066 return ImmutableMap.copyOf(result);
067 }
068 };
069
070 public DelegatingBindingTrace(BindingContext parentContext, String debugName) {
071 this.parentContext = parentContext;
072 this.name = debugName;
073 this.mutableDiagnostics = new MutableDiagnosticsWithSuppression(bindingContext, parentContext.getDiagnostics());
074 }
075
076 public DelegatingBindingTrace(BindingContext parentContext, String debugName, @Nullable Object resolutionSubjectForMessage) {
077 this(parentContext, AnalyzingUtils.formDebugNameForBindingTrace(debugName, resolutionSubjectForMessage));
078 }
079
080 @Override
081 @NotNull
082 public BindingContext getBindingContext() {
083 return bindingContext;
084 }
085
086 @Override
087 public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
088 map.put(slice, key, value);
089 }
090
091 @Override
092 public <K> void record(WritableSlice<K, Boolean> slice, K key) {
093 record(slice, key, true);
094 }
095
096 @Override
097 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
098 V value = map.get(slice, key);
099 if (slice instanceof Slices.SetSlice) {
100 assert value != null;
101 if (value.equals(true)) return value;
102 }
103 else if (value != null) {
104 return value;
105 }
106
107 return parentContext.get(slice, key);
108 }
109
110 @NotNull
111 @Override
112 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
113 Collection<K> keys = map.getKeys(slice);
114 Collection<K> fromParent = parentContext.getKeys(slice);
115 if (keys.isEmpty()) return fromParent;
116 if (fromParent.isEmpty()) return keys;
117
118 List<K> result = Lists.newArrayList(keys);
119 result.addAll(fromParent);
120 return result;
121 }
122
123 public void addAllMyDataTo(@NotNull BindingTrace trace) {
124 addAllMyDataTo(trace, null, true);
125 }
126
127 public void moveAllMyDataTo(@NotNull BindingTrace trace) {
128 addAllMyDataTo(trace, null, true);
129 clear();
130 }
131
132 public void addAllMyDataTo(@NotNull BindingTrace trace, @Nullable TraceEntryFilter filter, boolean commitDiagnostics) {
133 for (Map.Entry<SlicedMapKey<?, ?>, ?> entry : map) {
134 SlicedMapKey slicedMapKey = entry.getKey();
135
136 WritableSlice slice = slicedMapKey.getSlice();
137 Object key = slicedMapKey.getKey();
138 Object value = entry.getValue();
139
140 if (filter == null || filter.accept(slice, key)) {
141 //noinspection unchecked
142 trace.record(slice, key, value);
143 }
144 }
145
146 if (!commitDiagnostics) return;
147
148 for (Diagnostic diagnostic : mutableDiagnostics.getOwnDiagnostics()) {
149 if (filter == null || filter.accept(null, diagnostic.getPsiElement())) {
150 trace.report(diagnostic);
151 }
152 }
153 }
154
155 public void clear() {
156 map.clear();
157 mutableDiagnostics.clear();
158 }
159
160 @Override
161 public void report(@NotNull Diagnostic diagnostic) {
162 mutableDiagnostics.report(diagnostic);
163 }
164
165 @Override
166 public String toString() {
167 return name;
168 }
169 }