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