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