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.codegen;
018    
019    import com.intellij.openapi.util.Pair;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.asm4.Type;
023    import org.jetbrains.asm4.commons.Method;
024    import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
025    import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
026    import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
027    
028    import java.util.*;
029    
030    public final class MemberMap {
031        private final Map<FunctionDescriptor, Method> methodForFunction = new HashMap<FunctionDescriptor, Method>();
032        private final Map<PropertyDescriptor, Pair<Type, String>> fieldForProperty = new HashMap<PropertyDescriptor, Pair<Type, String>>();
033        private final Map<PropertyDescriptor, String> syntheticMethodNameForProperty = new HashMap<PropertyDescriptor, String>();
034        private final Map<CallableMemberDescriptor, String> srcClassNameForCallable = new HashMap<CallableMemberDescriptor, String>();
035        private final Set<PropertyDescriptor> staticFieldInOuterClass = new HashSet<PropertyDescriptor>();
036    
037        @NotNull
038        public static MemberMap union(@NotNull Collection<MemberMap> maps) {
039            MemberMap result = new MemberMap();
040            for (MemberMap map : maps) {
041                for (Map.Entry<FunctionDescriptor, Method> entry : map.methodForFunction.entrySet()) {
042                    result.recordMethodOfDescriptor(entry.getKey(), entry.getValue());
043                }
044    
045                for (Map.Entry<PropertyDescriptor, Pair<Type, String>> entry : map.fieldForProperty.entrySet()) {
046                    result.recordFieldOfProperty(entry.getKey(), entry.getValue().first, entry.getValue().second);
047                }
048    
049                for (Map.Entry<PropertyDescriptor, String> entry : map.syntheticMethodNameForProperty.entrySet()) {
050                    result.recordSyntheticMethodNameOfProperty(entry.getKey(), entry.getValue());
051                }
052    
053                for (Map.Entry<CallableMemberDescriptor, String> entry : map.srcClassNameForCallable.entrySet()) {
054                    result.recordSrcClassNameForCallable(entry.getKey(), entry.getValue());
055                }
056    
057                for (PropertyDescriptor property : map.staticFieldInOuterClass) {
058                    result.recordStaticFieldInOuterClass(property);
059                }
060            }
061    
062            return result;
063        }
064    
065        public void recordMethodOfDescriptor(@NotNull FunctionDescriptor descriptor, @NotNull Method method) {
066            Method old = methodForFunction.put(descriptor, method);
067            assert old == null : "Duplicate method for callable member: " + descriptor + "; " + old;
068        }
069    
070        public void recordFieldOfProperty(@NotNull PropertyDescriptor descriptor, @NotNull Type type, @NotNull String fieldName) {
071            Pair<Type, String> old = fieldForProperty.put(descriptor, Pair.create(type, fieldName));
072            assert old == null : "Duplicate field for property: " + descriptor + "; " + old;
073        }
074    
075        public void recordSyntheticMethodNameOfProperty(@NotNull PropertyDescriptor descriptor, @NotNull String name) {
076            String old = syntheticMethodNameForProperty.put(descriptor, name);
077            assert old == null : "Duplicate synthetic method for property: " + descriptor + "; " + old;
078        }
079    
080        public void recordSrcClassNameForCallable(@NotNull CallableMemberDescriptor descriptor, @NotNull String name) {
081            String old = srcClassNameForCallable.put(descriptor, name);
082            assert old == null : "Duplicate src class name for callable: " + descriptor + "; " + old;
083        }
084    
085        public void recordStaticFieldInOuterClass(@NotNull PropertyDescriptor property) {
086            boolean added = staticFieldInOuterClass.add(property);
087            assert added : "Duplicate static field in outer class: " + property;
088        }
089    
090        @Nullable
091        public Method getMethodOfDescriptor(@NotNull FunctionDescriptor descriptor) {
092            return methodForFunction.get(descriptor);
093        }
094    
095        @Nullable
096        public Pair<Type, String> getFieldOfProperty(@NotNull PropertyDescriptor descriptor) {
097            return fieldForProperty.get(descriptor);
098        }
099    
100        @Nullable
101        public String getSyntheticMethodNameOfProperty(@NotNull PropertyDescriptor descriptor) {
102            return syntheticMethodNameForProperty.get(descriptor);
103        }
104    
105        @Nullable
106        public String getSrcClassNameOfCallable(@NotNull CallableMemberDescriptor descriptor) {
107            return srcClassNameForCallable.get(descriptor);
108        }
109    
110        public boolean isStaticFieldInOuterClass(@NotNull PropertyDescriptor property) {
111            return staticFieldInOuterClass.contains(property);
112        }
113    
114        @Override
115        public String toString() {
116            return "Functions: " + methodForFunction.size() +
117                   ", fields: " + fieldForProperty.size() +
118                   ", synthetic methods: " + syntheticMethodNameForProperty.size() +
119                   ", src class names: " + srcClassNameForCallable.size();
120        }
121    }