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