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 org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.annotations.TestOnly;
024 import org.jetbrains.jet.lang.diagnostics.Diagnostic;
025 import org.jetbrains.jet.util.slicedmap.*;
026
027 import java.util.ArrayList;
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 List<Diagnostic> diagnostics = Lists.newArrayList();
038 private final String name;
039
040 private final BindingContext bindingContext = new BindingContext() {
041 @NotNull
042 @Override
043 public Collection<Diagnostic> getDiagnostics() {
044 ArrayList<Diagnostic> mergedDiagnostics = new ArrayList<Diagnostic>(diagnostics);
045 mergedDiagnostics.addAll(parentContext.getDiagnostics());
046 return mergedDiagnostics;
047 }
048
049 @Override
050 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
051 return DelegatingBindingTrace.this.get(slice, key);
052 }
053
054 @NotNull
055 @Override
056 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
057 return DelegatingBindingTrace.this.getKeys(slice);
058
059 }
060
061 @NotNull
062 @TestOnly
063 @Override
064 public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
065 ImmutableMap<K, V> parentContents = parentContext.getSliceContents(slice);
066 ImmutableMap<K, V> currentContents = map.getSliceContents(slice);
067 return ImmutableMap.<K, V>builder().putAll(parentContents).putAll(currentContents).build();
068 }
069 };
070
071 public DelegatingBindingTrace(BindingContext parentContext, String debugName) {
072 this.parentContext = parentContext;
073 this.name = debugName;
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 : diagnostics) {
149 trace.report(diagnostic);
150 }
151 }
152
153 public void clear() {
154 map.clear();
155 diagnostics.clear();
156 }
157
158 @Override
159 public void report(@NotNull Diagnostic diagnostic) {
160 diagnostics.add(diagnostic);
161 }
162
163 @Override
164 public String toString() {
165 return name;
166 }
167 }