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.calls.results;
018    
019    import com.intellij.openapi.application.Application;
020    import com.intellij.openapi.application.ApplicationManager;
021    import com.intellij.psi.PsiElement;
022    import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
023    import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
024    import org.jetbrains.jet.lang.resolve.calls.inference.BoundsOwner;
025    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
026    import org.jetbrains.jet.lang.resolve.calls.tasks.ResolutionTask;
027    import org.jetbrains.jet.lang.types.JetType;
028    import org.jetbrains.jet.util.slicedmap.*;
029    
030    import java.util.Collection;
031    import java.util.List;
032    import java.util.Map;
033    
034    public class ResolutionDebugInfo {
035        public static final WritableSlice<One, List<? extends ResolutionTask<? extends CallableDescriptor, ?>>> TASKS = Slices.createSimpleSlice();
036        public static final WritableSlice<One, ResolvedCall<? extends CallableDescriptor>> RESULT = Slices.createSimpleSlice();
037    
038        public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, StringBuilder> ERRORS = Slices.createSimpleSlice();
039        public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, StringBuilder> LOG = Slices.createSimpleSlice();
040        public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, Map<TypeParameterDescriptor, BoundsOwner>> BOUNDS_FOR_UNKNOWNS = Slices.createSimpleSlice();
041        public static final WritableSlice<ResolvedCall<? extends CallableDescriptor>, Map<JetType, BoundsOwner>> BOUNDS_FOR_KNOWNS = Slices.createSimpleSlice();
042    
043        public static boolean RESOLUTION_DEBUG_INFO_ENABLED = false;
044    
045        public static boolean isResolutionDebugEnabled() {
046            Application application = ApplicationManager.getApplication();
047            return (RESOLUTION_DEBUG_INFO_ENABLED || application.isInternal()) && !application.isUnitTestMode();
048        }
049    
050        public static final Data NO_DEBUG_INFO = new AbstractData() {
051    
052            @Override
053            public String toString() {
054                return "NO_DEBUG_INFO";
055            }
056    
057            @Override
058            public <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key) {
059                return SlicedMap.DO_NOTHING.get(slice, key);
060            }
061    
062            @Override
063            public <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value) {
064            }
065        };
066        public static final WritableSlice<PsiElement, Data> RESOLUTION_DEBUG_INFO = new BasicWritableSlice<PsiElement, Data>(Slices.ONLY_REWRITE_TO_EQUAL) {
067            @Override
068            public boolean check(PsiElement key, Data value) {
069                return isResolutionDebugEnabled();
070            }
071    
072            @Override
073            public Data computeValue(SlicedMap map, PsiElement key, Data value, boolean valueNotFound) {
074                if (valueNotFound) return NO_DEBUG_INFO;
075                return super.computeValue(map, key, value, valueNotFound);
076            }
077        };
078    
079        public static Data create() {
080            return isResolutionDebugEnabled() ? new DataImpl() : NO_DEBUG_INFO;
081        }
082    
083        public enum One { KEY }
084    
085        public interface Data {
086            <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key);
087            <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value);
088    
089            <V> void set(WritableSlice<One, ? super V> slice, V value);
090            <V> V get(ReadOnlySlice<One, V> slice);
091        }
092        
093        private static abstract class AbstractData implements Data {
094            @Override
095            public <V> void set(WritableSlice<One, ? super V> slice, V value) {
096                putByKey(slice, One.KEY, value);
097            }
098    
099            @Override
100            public <V> V get(ReadOnlySlice<One, V> slice) {
101                return getByKey(slice, One.KEY);
102            }
103        }
104    
105        private static class DataImpl extends AbstractData {
106            private final MutableSlicedMap map = SlicedMapImpl.create();
107    
108            @Override
109            public <K, V> V getByKey(ReadOnlySlice<K, V> slice, K key) {
110                return map.get(slice, key);
111            }
112    
113            @Override
114            public <K, V> void putByKey(WritableSlice<K, V> slice, K key, V value) {
115                map.put(slice, key, value);
116            }
117        }
118        
119        public static void println(Object message) {
120            if (isResolutionDebugEnabled()) {
121                System.out.println(message);
122            }
123        }
124    
125        static {
126            BasicWritableSlice.initSliceDebugNames(ResolutionDebugInfo.class);
127        }
128    }