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;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
022    import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
023    
024    import java.lang.ref.WeakReference;
025    import java.util.*;
026    
027    public class CallResolverExtensionProvider {
028    
029        private final static CompositeExtension DEFAULT =
030                new CompositeExtension(Arrays.asList(new NeedSyntheticCallResolverExtension(), new TypeParameterAsReifiedCheck()));
031    
032        private WeakReference<Map<DeclarationDescriptor, List<CallResolverExtension>>> extensionsCache;
033    
034        @NotNull
035        public CallResolverExtension createExtension(@Nullable DeclarationDescriptor descriptor, boolean isAnnotationContext) {
036            if (descriptor == null || isAnnotationContext) {
037                return DEFAULT;
038            }
039            return new CompositeExtension(createExtensions(descriptor));
040        }
041    
042        // create extension list with default one at the end
043        @NotNull
044        private List<CallResolverExtension> createExtensions(@NotNull DeclarationDescriptor declaration) {
045            Map<DeclarationDescriptor, List<CallResolverExtension>> map;
046            if (extensionsCache == null || (map = extensionsCache.get()) == null) {
047                map = new HashMap<DeclarationDescriptor, List<CallResolverExtension>>();
048                extensionsCache = new WeakReference<Map<DeclarationDescriptor, List<CallResolverExtension>>>(map);
049            }
050    
051            List<CallResolverExtension> extensions = map.get(declaration);
052            if (extensions != null) {
053                return extensions;
054            }
055    
056            extensions = new ArrayList<CallResolverExtension>();
057    
058            DeclarationDescriptor parent = declaration.getContainingDeclaration();
059            if (parent != null) {
060                extensions.addAll(createExtensions(parent));
061                extensions.remove(extensions.size() - 1);//remove default from parent list
062            }
063    
064            appendExtensionsFor(declaration, extensions);
065    
066            List<CallResolverExtension> immutableResult = Collections.unmodifiableList(extensions);
067            map.put(declaration, immutableResult);
068    
069            return immutableResult;
070        }
071    
072        // with default one at the end
073        private static void appendExtensionsFor(DeclarationDescriptor declarationDescriptor, List<CallResolverExtension> extensions) {
074            if (declarationDescriptor instanceof SimpleFunctionDescriptor) {
075                SimpleFunctionDescriptor descriptor = (SimpleFunctionDescriptor) declarationDescriptor;
076                if (descriptor.getInlineStrategy().isInline()) {
077                    extensions.add(new InlineCallResolverExtension(descriptor));
078                }
079            }
080            // add your extensions here
081            extensions.add(DEFAULT);
082        }
083    }