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 org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.annotations.TestOnly;
023 import org.jetbrains.kotlin.diagnostics.Diagnostic;
024 import org.jetbrains.kotlin.psi.KtExpression;
025 import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
026 import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression;
027 import org.jetbrains.kotlin.types.KotlinType;
028 import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo;
029 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
030 import org.jetbrains.kotlin.util.slicedMap.*;
031
032 import java.util.Collection;
033
034 public class BindingTraceContext implements BindingTrace {
035 // These flags are used for debugging of "Rewrite at slice..." exceptions
036 /* package */ final static boolean TRACK_REWRITES = false;
037 /* package */ final static boolean TRACK_WITH_STACK_TRACES = true;
038
039 private final MutableSlicedMap map;
040 @Nullable private final MutableDiagnosticsWithSuppression mutableDiagnostics;
041 @NotNull private final BindingTraceFilter filter;
042
043 private final BindingContext bindingContext = new BindingContext() {
044
045 @NotNull
046 @Override
047 public Diagnostics getDiagnostics() {
048 return mutableDiagnostics != null ? mutableDiagnostics : Diagnostics.Companion.getEMPTY();
049 }
050
051 @Override
052 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
053 return BindingTraceContext.this.get(slice, key);
054 }
055
056 @NotNull
057 @Override
058 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
059 return BindingTraceContext.this.getKeys(slice);
060 }
061
062 @NotNull
063 @TestOnly
064 @Override
065 public <K, V> ImmutableMap<K, V> getSliceContents(@NotNull ReadOnlySlice<K, V> slice) {
066 return map.getSliceContents(slice);
067 }
068
069 @Nullable
070 @Override
071 public KotlinType getType(@NotNull KtExpression expression) {
072 return BindingTraceContext.this.getType(expression);
073 }
074
075 @Override
076 public void addOwnDataTo(@NotNull BindingTrace trace, boolean commitDiagnostics) {
077 BindingContextUtils.addOwnDataTo(trace, null, commitDiagnostics, map, mutableDiagnostics);
078 }
079 };
080
081 public BindingTraceContext() {
082 this(BindingTraceFilter.Companion.getACCEPT_ALL());
083 }
084
085 public BindingTraceContext(BindingTraceFilter filter) {
086 //noinspection ConstantConditions
087 this(TRACK_REWRITES ? new TrackingSlicedMap(TRACK_WITH_STACK_TRACES) : SlicedMapImpl.create(), filter);
088 }
089
090
091 private BindingTraceContext(@NotNull MutableSlicedMap map, BindingTraceFilter filter) {
092 this.map = map;
093 this.mutableDiagnostics = !filter.getIgnoreDiagnostics()
094 ? new MutableDiagnosticsWithSuppression(bindingContext, Diagnostics.Companion.getEMPTY())
095 : null;
096 this.filter = filter;
097 }
098
099 @TestOnly
100 public static BindingTraceContext createTraceableBindingTrace() {
101 return new BindingTraceContext(new TrackingSlicedMap(TRACK_WITH_STACK_TRACES), BindingTraceFilter.Companion.getACCEPT_ALL());
102 }
103
104 @Override
105 public void report(@NotNull Diagnostic diagnostic) {
106 if (mutableDiagnostics == null) {
107 return;
108 }
109 mutableDiagnostics.report(diagnostic);
110 }
111
112 public void clearDiagnostics() {
113 if (mutableDiagnostics != null) {
114 mutableDiagnostics.clear();
115 }
116 }
117
118 @Override
119 public boolean wantsDiagnostics() {
120 return mutableDiagnostics != null;
121 }
122
123 @NotNull
124 @Override
125 public BindingContext getBindingContext() {
126 return bindingContext;
127 }
128
129 @Override
130 public <K, V> void record(WritableSlice<K, V> slice, K key, V value) {
131 map.put(slice, key, value);
132 }
133
134 @Override
135 public <K> void record(WritableSlice<K, Boolean> slice, K key) {
136 record(slice, key, true);
137 }
138
139 @Override
140 public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
141 return map.get(slice, key);
142 }
143
144 @NotNull
145 @Override
146 public <K, V> Collection<K> getKeys(WritableSlice<K, V> slice) {
147 return map.getKeys(slice);
148 }
149
150 @Nullable
151 @Override
152 public KotlinType getType(@NotNull KtExpression expression) {
153 KotlinTypeInfo typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression);
154 return typeInfo != null ? typeInfo.getType() : null;
155 }
156
157 @Override
158 public void recordType(@NotNull KtExpression expression, @Nullable KotlinType type) {
159 KotlinTypeInfo typeInfo = get(BindingContext.EXPRESSION_TYPE_INFO, expression);
160 typeInfo = typeInfo != null ? typeInfo.replaceType(type) : TypeInfoFactoryKt.createTypeInfo(type);
161 record(BindingContext.EXPRESSION_TYPE_INFO, expression, typeInfo);
162 }
163 }