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.types;
018    
019    import jet.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
022    import org.jetbrains.jet.lang.resolve.BindingTrace;
023    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
024    import org.jetbrains.jet.storage.LockBasedStorageManager;
025    import org.jetbrains.jet.storage.NotNullLazyValue;
026    import org.jetbrains.jet.util.ReenteringLazyValueComputationException;
027    import org.jetbrains.jet.util.Box;
028    
029    import java.util.List;
030    
031    import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
032    
033    public class DeferredType implements JetType {
034        
035        public static DeferredType create(BindingTrace trace, NotNullLazyValue<JetType> lazyValue) {
036            DeferredType deferredType = new DeferredType(lazyValue);
037            trace.record(DEFERRED_TYPE, new Box<DeferredType>(deferredType));
038            return deferredType;
039        }
040        
041        public static DeferredType create(BindingTrace trace, Function0<JetType> compute) {
042            return create(trace, LockBasedStorageManager.NO_LOCKS.createLazyValue(compute));
043        }
044    
045        private final NotNullLazyValue<JetType> lazyValue;
046    
047        private DeferredType(NotNullLazyValue<JetType> lazyValue) {
048            this.lazyValue = lazyValue;
049        }
050    
051        public boolean isComputed() {
052            return lazyValue.isComputed();
053        }
054    
055        @NotNull
056        public JetType getActualType() {
057            return lazyValue.invoke();
058        }
059    
060        @Override
061        @NotNull
062        public JetScope getMemberScope() {
063            return getActualType().getMemberScope();
064        }
065    
066        @Override
067        public boolean isError() {
068            return getActualType().isError();
069        }
070    
071        @Override
072        @NotNull
073        public TypeConstructor getConstructor() {
074            return getActualType().getConstructor();
075        }
076    
077        @Override
078        @NotNull
079        public List<TypeProjection> getArguments() {
080            return getActualType().getArguments();
081        }
082    
083        @Override
084        public boolean isNullable() {
085            return getActualType().isNullable();
086        }
087    
088        @NotNull
089        @Override
090        public List<AnnotationDescriptor> getAnnotations() {
091            return getActualType().getAnnotations();
092        }
093    
094        @Override
095        public String toString() {
096            try {
097                if (lazyValue.isComputed()) {
098                    return getActualType().toString();
099                }
100                else {
101                    return "<Not computed yet>";
102                }
103            }
104            catch (ReenteringLazyValueComputationException e) {
105                return "<Failed to compute this type>";
106            }
107        }
108    
109        @Override
110        public boolean equals(Object obj) {
111            return getActualType().equals(obj);
112        }
113    
114        @Override
115        public int hashCode() {
116            return getActualType().hashCode();
117        }
118    }