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 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.collect.ImmutableMap; 020import com.google.common.collect.Lists; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.annotations.Nullable; 023import org.jetbrains.annotations.TestOnly; 024import org.jetbrains.jet.lang.diagnostics.Diagnostic; 025import org.jetbrains.jet.util.slicedmap.*; 026 027import java.util.ArrayList; 028import java.util.Collection; 029import java.util.List; 030import java.util.Map; 031 032public 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}