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